Return existing in SPseudonymR

This commit is contained in:
Gregor Kleen 2018-10-15 08:44:12 +02:00
parent 4266683b15
commit 8e28c397fd
4 changed files with 46 additions and 7 deletions

2
routes
View File

@ -80,7 +80,7 @@
/correction CorrectionR GET POST !corrector !ownerANDisReadANDrated /correction CorrectionR GET POST !corrector !ownerANDisReadANDrated
!/#SubmissionFileType/*FilePath SubDownloadR GET !owner !/#SubmissionFileType/*FilePath SubDownloadR GET !owner
/correctors SCorrR GET POST /correctors SCorrR GET POST
/pseudonym SPseudonymR POST !registeredANDcorrector-submissions /pseudonym SPseudonymR GET POST !registeredANDcorrector-submissions
!/#SheetFileType/*FilePath SFileR GET !timeANDregistered !timeANDmaterials !corrector !/#SheetFileType/*FilePath SFileR GET !timeANDregistered !timeANDmaterials !corrector

View File

@ -49,6 +49,8 @@ import Control.Monad.Writer (MonadWriter(..), execWriterT)
-- import qualified Data.List as List -- import qualified Data.List as List
import Control.Monad.Trans.Except (ExceptT(..), runExceptT, mapExceptT, throwE)
import Network.Mime import Network.Mime
import Data.Set (Set) import Data.Set (Set)
@ -346,22 +348,28 @@ getSShowR tid ssh csh shn = do
$(widgetFile "sheetShow") $(widgetFile "sheetShow")
postSPseudonymR :: TermId -> SchoolId -> CourseShorthand -> SheetName -> Handler TypedContent postSPseudonymR :: TermId -> SchoolId -> CourseShorthand -> SheetName -> Handler TypedContent
getSPseudonymR = postSPseudonymR
postSPseudonymR tid ssh csh shn = do postSPseudonymR tid ssh csh shn = do
uid <- requireAuthId uid <- requireAuthId
shId <- runDB $ fetchSheetId tid ssh csh shn shId <- runDB $ fetchSheetId tid ssh csh shn
let let
genPseudonym = do genPseudonym = do
inserted <- runDB . setSerializable $ do inserted <- runExceptT . mapExceptT (runDB . setSerializable) $ do
candidate <- liftIO getRandom candidate <- liftIO getRandom
fmap (const candidate) <$> insertUnique (SheetPseudonym shId candidate uid) existing <- lift . getBy $ UniqueSheetPseudonymUser shId uid
case existing of
Just (Entity _ SheetPseudonym{sheetPseudonymPseudonym}) -> throwE sheetPseudonymPseudonym
Nothing
-> lift $ fmap (const candidate) <$> insertUnique (SheetPseudonym shId candidate uid)
case inserted of case inserted of
Nothing -> genPseudonym Right Nothing -> genPseudonym
Just ps -> return ps Right (Just ps) -> return ps
Left ps -> return ps
ps <- genPseudonym ps <- genPseudonym
let ps' = Text.unwords . map CI.original $ review pseudonymWords ps let ps' = Text.unwords . map CI.original $ review pseudonymWords ps
selectRep $ do selectRep $ do
provideRep $ return ps' provideRep $ return ps'
provideRep . return $ Aeson.String ps' provideJson ps
provideRep (redirect $ CSheetR tid ssh csh shn SShowR :: Handler Html) provideRep (redirect $ CSheetR tid ssh csh shn SShowR :: Handler Html)

View File

@ -13,6 +13,7 @@ import Yesod.Auth as Import
import Yesod.Core.Types as Import (loggerSet) import Yesod.Core.Types as Import (loggerSet)
import Yesod.Default.Config2 as Import import Yesod.Default.Config2 as Import
import Utils as Import import Utils as Import
import Yesod.Core.Json as Import (provideJson)
import Data.Fixed as Import import Data.Fixed as Import

View File

@ -9,6 +9,7 @@
{-# LANGUAGE ViewPatterns #-} {-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE DerivingStrategies #-} {-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE BinaryLiterals #-} {-# LANGUAGE BinaryLiterals #-}
{-# LANGUAGE MultiWayIf #-}
{-- # LANGUAGE ExistentialQuantification #-} -- for DA type {-- # LANGUAGE ExistentialQuantification #-} -- for DA type
{-# OPTIONS_GHC -fno-warn-orphans #-} -- for instance PathPiece (CI Text) {-# OPTIONS_GHC -fno-warn-orphans #-} -- for instance PathPiece (CI Text)
@ -541,7 +542,14 @@ newtype Pseudonym = Pseudonym Word24
instance PersistField Pseudonym where instance PersistField Pseudonym where
toPersistValue p = toPersistValue (fromIntegral p :: Word32) toPersistValue p = toPersistValue (fromIntegral p :: Word32)
fromPersistValue = fmap (fromIntegral :: Word32 -> Pseudonym) . fromPersistValue fromPersistValue v = do
w <- fromPersistValue v :: Either Text Word32
if
| 0 <= w
, w <= fromIntegral (maxBound :: Pseudonym)
-> return $ fromIntegral w
| otherwise
-> Left "Pseudonym out of range"
instance PersistFieldSql Pseudonym where instance PersistFieldSql Pseudonym where
sqlType _ = SqlInt32 sqlType _ = SqlInt32
@ -550,6 +558,28 @@ instance Random Pseudonym where
randomR (max minBound -> lo, min maxBound -> hi) gen = over _1 (fromIntegral :: Word32 -> Pseudonym) $ randomR (fromIntegral lo, fromIntegral hi) gen randomR (max minBound -> lo, min maxBound -> hi) gen = over _1 (fromIntegral :: Word32 -> Pseudonym) $ randomR (fromIntegral lo, fromIntegral hi) gen
random = randomR (minBound, maxBound) random = randomR (minBound, maxBound)
instance FromJSON Pseudonym where
parseJSON v@(Aeson.Number _) = do
w <- parseJSON v :: Aeson.Parser Word32
if
| 0 <= w
, w <= fromIntegral (maxBound :: Pseudonym)
-> return $ fromIntegral w
| otherwise
-> fail "Pseudonym out auf range"
parseJSON (Aeson.String (map CI.mk . Text.words -> ws))
= case preview pseudonymWords ws of
Just p -> return p
Nothing -> fail "Could not parse pseudonym"
parseJSON v = flip (Aeson.withArray "Pseudonym") v $ \ws -> do
ws' <- toList . map CI.mk <$> mapM parseJSON ws
case preview pseudonymWords ws' of
Just p -> return p
Nothing -> fail "Could not parse pseudonym words"
instance ToJSON Pseudonym where
toJSON = toJSON . (review pseudonymWords :: Pseudonym -> [CI Text])
pseudonymWordlist :: [CI Text] pseudonymWordlist :: [CI Text]
pseudonymWordlist = $(wordlist "config/wordlist.txt") pseudonymWordlist = $(wordlist "config/wordlist.txt")