fix(add-users): fix and refactor confirm post param handling

This commit is contained in:
Sarah Vaupel 2022-12-12 12:28:05 +01:00
parent 56a23b7abf
commit 727d78cabc
3 changed files with 31 additions and 30 deletions

View File

@ -125,6 +125,7 @@ CourseParticipantsRegistered n@Int: #{n} #{pluralDE n "Teinehmer:in" "Teilnehmer
CourseParticipantsRegisteredTutorial n@Int: #{n} #{pluralDE n "Teinehmer:in" "Teilnehmer:innen"} erfolgreich zur Übungsgruppe angemeldet CourseParticipantsRegisteredTutorial n@Int: #{n} #{pluralDE n "Teinehmer:in" "Teilnehmer:innen"} erfolgreich zur Übungsgruppe angemeldet
CourseParticipantsRegisterConfirmationHeading: Teilnehmer:innen hinzufügen CourseParticipantsRegisterConfirmationHeading: Teilnehmer:innen hinzufügen
CourseParticipantsRegisterUnnecessary: Alle angeforderten Anmeldungen sind bereits vorhanden. Es wurden keine Änderungen vorgenommen. CourseParticipantsRegisterUnnecessary: Alle angeforderten Anmeldungen sind bereits vorhanden. Es wurden keine Änderungen vorgenommen.
CourseParticipantsRegisterConfirmInvalid: Ungültiges Bestätigungsformular!
CourseApplicationText: Text-Bewerbung CourseApplicationText: Text-Bewerbung
CourseApplicationFollowInstructions: Beachten Sie die Anweisungen zur Bewerbung! CourseApplicationFollowInstructions: Beachten Sie die Anweisungen zur Bewerbung!

View File

@ -125,6 +125,7 @@ CourseParticipantsAlreadyTutorialMember n: #{n} #{pluralEN n "participant is" "p
CourseParticipantsRegistered n: Successfully registered #{n} #{pluralEN n "participant" "participants"} for course CourseParticipantsRegistered n: Successfully registered #{n} #{pluralEN n "participant" "participants"} for course
CourseParticipantsRegisteredTutorial n: Successfully registered #{n} #{pluralEN n "participant" "participants"} for tutorial CourseParticipantsRegisteredTutorial n: Successfully registered #{n} #{pluralEN n "participant" "participants"} for tutorial
CourseParticipantsRegisterConfirmationHeading: Register participants CourseParticipantsRegisterConfirmationHeading: Register participants
CourseParticipantsRegisterConfirmInvalid: Invalid confirmation form!
CourseApplicationText: Application text CourseApplicationText: Application text
CourseApplicationFollowInstructions: Please follow the instructions for applications! CourseApplicationFollowInstructions: Please follow the instructions for applications!

View File

@ -1,4 +1,4 @@
-- SPDX-FileCopyrightText: 2022 Gregor Kleen <gregor.kleen@ifi.lmu.de>,Sarah Vaupel <sarah.vaupel@ifi.lmu.de> -- SPDX-FileCopyrightText: 2022 Sarah Vaupel <sarah.vaupel@ifi.lmu.de>
-- --
-- SPDX-License-Identifier: AGPL-3.0-or-later -- SPDX-License-Identifier: AGPL-3.0-or-later
@ -30,7 +30,7 @@ type UserSearchKey = Text
type TutorialIdent = CI Text type TutorialIdent = CI Text
data ButtonCourseRegisterMode = BtnCourseRegisterAdd | BtnCourseRegisterConfirm | BtnCourseRegisterAbort data ButtonCourseRegisterMode = BtnCourseRegisterConfirm | BtnCourseRegisterAbort
deriving (Eq, Ord, Enum, Bounded, Read, Show, Generic, Typeable) deriving (Eq, Ord, Enum, Bounded, Read, Show, Generic, Typeable)
instance Universe ButtonCourseRegisterMode instance Universe ButtonCourseRegisterMode
instance Finite ButtonCourseRegisterMode instance Finite ButtonCourseRegisterMode
@ -41,11 +41,8 @@ nullaryPathPiece ''ButtonCourseRegisterMode $ camelToPathPiece' 1
instance Button UniWorX ButtonCourseRegisterMode where instance Button UniWorX ButtonCourseRegisterMode where
btnLabel x = [whamlet|_{x}|] btnLabel x = [whamlet|_{x}|]
btnClasses BtnCourseRegisterAdd = [BCIsButton, BCPrimary]
btnClasses BtnCourseRegisterConfirm = [BCIsButton, BCPrimary] btnClasses BtnCourseRegisterConfirm = [BCIsButton, BCPrimary]
btnClasses BtnCourseRegisterAbort = [BCIsButton, BCDanger] btnClasses BtnCourseRegisterAbort = [BCIsButton, BCDanger]
btnValidate _ BtnCourseRegisterAbort = False btnValidate _ BtnCourseRegisterAbort = False
btnValidate _ _ = True btnValidate _ _ = True
@ -125,30 +122,35 @@ getCAddUserR, postCAddUserR :: TermId -> SchoolId -> CourseShorthand -> Handler
getCAddUserR = postCAddUserR getCAddUserR = postCAddUserR
postCAddUserR tid ssh csh = do postCAddUserR tid ssh csh = do
cid <- runDB . getKeyBy404 $ TermSchoolCourseShort tid ssh csh cid <- runDB . getKeyBy404 $ TermSchoolCourseShort tid ssh csh
today <- localDay . TZ.utcToLocalTimeTZ appTZ <$> liftIO getCurrentTime
currentRoute <- fromMaybe (error "postCAddUserR called from 404-handler") <$> getCurrentRoute currentRoute <- fromMaybe (error "postCAddUserR called from 404-handler") <$> getCurrentRoute
piConfirmPost <- throwExceptT . runMaybeT $ encodedSecretBoxOpen =<< MaybeT (lift . lookupPostParam $ toPathPiece PostCourseUserAddConfirmAction) confirmAvailableActs <- fmap (maybe FormMissing FormSuccess) . throwExceptT . runMaybeT $ encodedSecretBoxOpen =<< MaybeT (lift . lookupPostParam $ toPathPiece PostCourseUserAddConfirmAvailableActions)
$logErrorS "CAddUserR" . tshow $ Aeson.encode piConfirmPost confirmActs <- fmap (maybe FormMissing FormSuccess) . throwExceptT . runMaybeT $ encodedSecretBoxOpen =<< MaybeT (lift . lookupPostParam $ toPathPiece PostCourseUserAddConfirmAction)
let $logErrorS "CAddUserR available" . tshow $ Aeson.encode (confirmAvailableActs :: Maybe (Set CourseRegisterActionData))
piConfirmRes :: FormResult CourseRegisterActionData $logErrorS "CAddUserR acts" . tshow $ Aeson.encode (confirmActs :: Maybe (Set CourseRegisterActionData))
piConfirmRes = maybe FormMissing FormSuccess piConfirmPost if
case piConfirmRes of | FormSuccess acts <- confirmActs
FormSuccess res'' -> do , FormSuccess _availableActs <- confirmAvailableActs
let res' = [res''] -> do
forM_ res' $ \case -- TODO: check that all acts are member of availableActs!
CourseRegisterActionAddTutorialMemberData{..} -> do forM_ (Set.toList acts) $ \case
registeredUsers <- registerUsers cid $ Map.singleton crActAddTutorialMemberIdent (Just $ view _1 crActAddTutorialMemberUser) CourseRegisterActionAddTutorialMemberData{..} -> do
tutId <- upsertNewTutorial cid crActAddTutorialMemberTutorial registeredUsers <- registerUsers cid $ Map.singleton crActAddTutorialMemberIdent (Just $ view _1 crActAddTutorialMemberUser)
registerTutorialMembers tutId registeredUsers tutId <- upsertNewTutorial cid crActAddTutorialMemberTutorial
redirect $ CTutorialR tid ssh csh crActAddTutorialMemberTutorial TUsersR registerTutorialMembers tutId registeredUsers
CourseRegisterActionAddParticipantData{..} -> do redirect $ CTutorialR tid ssh csh crActAddTutorialMemberTutorial TUsersR
void . registerUsers cid $ Map.singleton crActAddParticipantIdent (Just $ view _1 crActAddParticipantUser) CourseRegisterActionAddParticipantData{..} -> do
redirect $ CourseR tid ssh csh CUsersR void . registerUsers cid $ Map.singleton crActAddParticipantIdent (Just $ view _1 crActAddParticipantUser)
FormMissing -> return () redirect $ CourseR tid ssh csh CUsersR
FormFailure errs -> forM_ errs $ addMessage Error . toHtml | FormSuccess _ <- confirmActsRes
-> addMessageI Error MsgCourseParticipantsRegisterConfirmInvalid
| FormMissing <- confirmActsRes
-> return ()
| FormFailure errs <- confirmActsRes
-> forM_ errs $ addMessage Error . toHtml
((usersToAdd :: FormResult AddUserRequest, formWgt), formEncoding) <- runFormPost . renderWForm FormStandard $ do ((usersToAdd :: FormResult AddUserRequest, formWgt), formEncoding) <- runFormPost . renderWForm FormStandard $ do
today <- localDay . TZ.utcToLocalTimeTZ appTZ <$> liftIO getCurrentTime
let let
cfCommaSeparatedSet :: forall m. Functor m => Field m Text -> Field m (Set Text) cfCommaSeparatedSet :: forall m. Functor m => Field m Text -> Field m (Set Text)
cfCommaSeparatedSet = guardField (not . Set.null) . convertField (Set.fromList . mapMaybe (assertM' (not . Text.null) . Text.strip) . Text.splitOn ",") (Text.intercalate ", " . Set.toList) cfCommaSeparatedSet = guardField (not . Set.null) . convertField (Set.fromList . mapMaybe (assertM' (not . Text.null) . Text.strip) . Text.splitOn ",") (Text.intercalate ", " . Set.toList)
@ -177,7 +179,7 @@ postCAddUserR tid ssh csh = do
siteLayoutMsg MsgCourseParticipantsRegisterHeading $ do siteLayoutMsg MsgCourseParticipantsRegisterHeading $ do
setTitleI MsgCourseParticipantsRegisterHeading setTitleI MsgCourseParticipantsRegisterHeading
actionMap :: Map CourseRegisterAction (Set CourseRegisterActionData) <- fmap Map.unions . forM usersFound $ \case actionMap :: Map CourseRegisterAction (Set CourseRegisterActionData) <- fmap (Map.unionsWith Set.union) . forM usersFound $ \case
(_, Nothing) -> error "Found user in AVS, but response is Nothing!" -- this should not be possible (_, Nothing) -> error "Found user in AVS, but response is Nothing!" -- this should not be possible
(ukey, Just uid) -> do (ukey, Just uid) -> do
-- isParticipant <- exists [CourseParticipantCourse ==. cid, CourseParticipantUser ==. uid, CourseParticipantState ==. CourseParticipantActive] -- isParticipant <- exists [CourseParticipantCourse ==. cid, CourseParticipantUser ==. uid, CourseParticipantState ==. CourseParticipantActive]
@ -293,10 +295,7 @@ registerTutorialMembers :: TutorialId -> Set UserId -> Handler ()
registerTutorialMembers tutId (Set.toList -> users) = runDB $ do registerTutorialMembers tutId (Set.toList -> users) = runDB $ do
prevParticipants <- fmap Set.fromList $ selectList [TutorialParticipantUser <-. users, TutorialParticipantTutorial ==. tutId] [] prevParticipants <- fmap Set.fromList $ selectList [TutorialParticipantUser <-. users, TutorialParticipantTutorial ==. tutId] []
participants <- fmap Set.fromList . for users $ \tutorialParticipantUser -> upsert participants <- fmap Set.fromList . for users $ \tutorialParticipantUser -> upsert
TutorialParticipant TutorialParticipant { tutorialParticipantTutorial = tutId, .. }
{ tutorialParticipantTutorial = tutId
, ..
}
[] []
let newParticipants = participants Set.\\ prevParticipants let newParticipants = participants Set.\\ prevParticipants
unless (Set.null newParticipants) $ unless (Set.null newParticipants) $