fix(users): fix #112 and also add some convenience

This commit is contained in:
Steffen Jost 2023-07-25 15:21:28 +00:00
parent b4ba0a30dc
commit 35096ace01
6 changed files with 30 additions and 12 deletions

View File

@ -38,6 +38,7 @@ MenuTermShow: Jahr
MenuSubmissionDelete: Abgabe löschen MenuSubmissionDelete: Abgabe löschen
MenuUsers: Benutzer:in MenuUsers: Benutzer:in
MenuUserAdd: Benutzer:in anlegen MenuUserAdd: Benutzer:in anlegen
MenuUserEdit: Benutzer:in editieren
MenuUserNotifications: Benachrichtigungs-Einstellungen MenuUserNotifications: Benachrichtigungs-Einstellungen
MenuUserPassword: Passwort MenuUserPassword: Passwort
MenuAdminTest: Admin-Demo MenuAdminTest: Admin-Demo

View File

@ -38,6 +38,7 @@ MenuTermShow: Semesters
MenuSubmissionDelete: Delete submission MenuSubmissionDelete: Delete submission
MenuUsers: User MenuUsers: User
MenuUserAdd: Add user MenuUserAdd: Add user
MenuUserEdit: Edit user
MenuUserNotifications: Notification settings MenuUserNotifications: Notification settings
MenuUserPassword: Password MenuUserPassword: Password
MenuAdminTest: Admin-demo MenuAdminTest: Admin-demo

2
routes
View File

@ -54,7 +54,7 @@
/users UsersR GET POST -- no tags, i.e. admins only /users UsersR GET POST -- no tags, i.e. admins only
/users/#CryptoUUIDUser AdminUserR GET POST /users/#CryptoUUIDUser AdminUserR GET POST
/users/#CryptoUUIDUser/delete AdminUserDeleteR POST /users/#CryptoUUIDUser/delete AdminUserDeleteR POST
/users/#CryptoUUIDUser/hijack AdminHijackUserR POST !adminANDno-escalation /users/#CryptoUUIDUser/hijack AdminHijackUserR GET POST !adminANDno-escalation
/users/#CryptoUUIDUser/notifications UserNotificationR GET POST !self /users/#CryptoUUIDUser/notifications UserNotificationR GET POST !self
/users/#CryptoUUIDUser/password UserPasswordR GET POST !selfANDis-pw-hash /users/#CryptoUUIDUser/password UserPasswordR GET POST !selfANDis-pw-hash
!/users/functionary-invite/new AdminNewFunctionaryInviteR GET POST !/users/functionary-invite/new AdminNewFunctionaryInviteR GET POST

View File

@ -1192,6 +1192,13 @@ pageActions (AdminUserR cID) = return
} }
, navChildren = [] , navChildren = []
} }
, NavPageActionPrimary
{ navLink = defNavLink MsgMenuUserEdit $ ForProfileR cID
, navChildren = []
}
, NavPageActionSecondary
{ navLink = (defNavLink MsgUserHijack $ AdminHijackUserR cID){ navType = NavTypeLink { navModal = True }}
}
] ]
pageActions InfoR = return pageActions InfoR = return
[ NavPageActionPrimary [ NavPageActionPrimary

View File

@ -376,8 +376,9 @@ validateSettings User{..} = do
let pinBad = validCmdArgument =<< userPinPassword' let pinBad = validCmdArgument =<< userPinPassword'
pinMinChar = 5 pinMinChar = 5
pinLength = maybe 0 length userPinPassword' pinLength = maybe 0 length userPinPassword'
pinOk <- if userPrefersPostal' || pinMinChar <= pinLength then pure True else liftHandler $ hasReadAccessTo AdminR -- admins are allowed to ignore pin requirements
whenIsJust pinBad (tellValidationError . MsgPDFPasswordInvalid) -- used as CMD argument for pdftk whenIsJust pinBad (tellValidationError . MsgPDFPasswordInvalid) -- used as CMD argument for pdftk
guardValidation (MsgPDFPasswordTooShort pinMinChar) $ userPrefersPostal' || pinMinChar <= pinLength guardValidation (MsgPDFPasswordTooShort pinMinChar) pinOk
data ButtonResetTokens = BtnResetTokens data ButtonResetTokens = BtnResetTokens
@ -412,6 +413,7 @@ postProfileR = requireAuthPair >>= serveProfileR
serveProfileR :: (UserId, User) -> Handler Html serveProfileR :: (UserId, User) -> Handler Html
serveProfileR (uid, user@User{..}) = do serveProfileR (uid, user@User{..}) = do
currentRoute <- fromMaybe ProfileR <$> getCurrentRoute
(userSchools, userExamOfficeLabels) <- runDB $ do (userSchools, userExamOfficeLabels) <- runDB $ do
userSchools <- fmap (setOf $ folded . _Value) . E.select . E.from $ \school -> do userSchools <- fmap (setOf $ folded . _Value) . E.select . E.from $ \school -> do
E.where_ . E.exists . E.from $ \userSchool -> E.where_ . E.exists . E.from $ \userSchool ->
@ -513,7 +515,7 @@ serveProfileR (uid, user@User{..}) = do
, ExamOfficeLabelPriority =. examOfficeLabelPriority , ExamOfficeLabelPriority =. examOfficeLabelPriority
] ]
addMessageI Success MsgSettingsUpdate addMessageI Success MsgSettingsUpdate
redirect $ ProfileR :#: ProfileSettings redirect $ currentRoute :#: ProfileSettings
((tokenRes, tokenFormWidget), tokenEnctype) <- runFormPost . identifyForm ProfileResetTokens $ buttonForm ((tokenRes, tokenFormWidget), tokenEnctype) <- runFormPost . identifyForm ProfileResetTokens $ buttonForm
@ -521,7 +523,7 @@ serveProfileR (uid, user@User{..}) = do
now <- liftIO getCurrentTime now <- liftIO getCurrentTime
runDB $ update uid [ UserTokensIssuedAfter =. Just now ] runDB $ update uid [ UserTokensIssuedAfter =. Just now ]
addMessageI Info MsgTokensResetSuccess addMessageI Info MsgTokensResetSuccess
redirect $ ProfileR :#: ProfileResetTokens redirect $ currentRoute :#: ProfileResetTokens
tResetTime <- traverse (formatTime SelFormatDateTime) userTokensIssuedAfter tResetTime <- traverse (formatTime SelFormatDateTime) userTokensIssuedAfter
@ -530,7 +532,7 @@ serveProfileR (uid, user@User{..}) = do
let settingsForm = let settingsForm =
wrapForm formWidget FormSettings wrapForm formWidget FormSettings
{ formMethod = POST { formMethod = POST
, formAction = Just . SomeRoute $ ProfileR :#: ProfileSettings , formAction = Just . SomeRoute $ currentRoute :#: ProfileSettings
, formEncoding = formEnctype , formEncoding = formEnctype
, formAttrs = [] , formAttrs = []
, formSubmit = FormSubmit , formSubmit = FormSubmit
@ -539,7 +541,7 @@ serveProfileR (uid, user@User{..}) = do
tokenForm = tokenForm =
wrapForm tokenFormWidget FormSettings wrapForm tokenFormWidget FormSettings
{ formMethod = POST { formMethod = POST
, formAction = Just . SomeRoute $ ProfileR :#: ProfileResetTokens , formAction = Just . SomeRoute $ currentRoute :#: ProfileResetTokens
, formEncoding = tokenEnctype , formEncoding = tokenEnctype
, formAttrs = [] , formAttrs = []
, formSubmit = FormNoSubmit , formSubmit = FormNoSubmit

View File

@ -413,15 +413,22 @@ hijackUser uid = do
User{userIdent} <- runDB $ get404 uid User{userIdent} <- runDB $ get404 uid
setCredsRedirect $ Creds apDummy (CI.original userIdent) [] setCredsRedirect $ Creds apDummy (CI.original userIdent) []
getAdminHijackUserR :: CryptoUUIDUser -> Handler TypedContent
getAdminHijackUserR = postAdminHijackUserR
postAdminHijackUserR :: CryptoUUIDUser -> Handler TypedContent postAdminHijackUserR :: CryptoUUIDUser -> Handler TypedContent
postAdminHijackUserR cID = do postAdminHijackUserR cID = do
uid <- decrypt cID uid <- decrypt cID
((hijackRes, _), _) <- runFormPost hijackUserForm ((hijackRes, hijackWgt), hijackEnctype) <- runFormPost hijackUserForm
case hijackRes of
ret <- formResultMaybe hijackRes $ \() -> Just <$> hijackUser uid (FormSuccess ()) -> hijackUser uid
_ -> selectRep $ do
maybe (redirect UsersR) return ret provideRep . siteLayoutMsg MsgUserHijack $ do
setTitleI MsgUserHijack
let hjForm = wrapForm hijackWgt def{ formEncoding = hijackEnctype }
[whamlet|
^{hjForm}
|]
data ButtonAuthMode = BtnAuthLDAP | BtnAuthPWHash | BtnPasswordReset data ButtonAuthMode = BtnAuthLDAP | BtnAuthPWHash | BtnPasswordReset
deriving (Eq, Ord, Read, Show, Enum, Bounded, Generic) deriving (Eq, Ord, Read, Show, Enum, Bounded, Generic)