From 593a6a72d2750135dbe6348b53f48b18db6032b5 Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Wed, 11 Sep 2019 17:02:22 +0200 Subject: [PATCH 1/5] fix(datepicker): increase datepicker z-index in modals --- frontend/src/utils/form/datepicker.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frontend/src/utils/form/datepicker.js b/frontend/src/utils/form/datepicker.js index 11d7394bc..acc057502 100644 --- a/frontend/src/utils/form/datepicker.js +++ b/frontend/src/utils/form/datepicker.js @@ -139,6 +139,11 @@ export class Datepicker { // initialize tail.datetime (datepicker) instance this.datepickerInstance = datetime(this._element, { ...datepickerGlobalConfig, ...datepickerConfig }); + // if the input element is in any open modal, increase the z-index of the datepicker + if (this._element.closest('.modal--open')) { + this.datepickerInstance.dt.style.zIndex = 9999; + } + // register this datepicker instance with the formID of the given element in the datepicker collection const formID = this._element.form.id; const elemID = this._element.id; From 3f9454a7ef4ff2303827b692c52151d07a96c67d Mon Sep 17 00:00:00 2001 From: Sarah Vaupel Date: Wed, 11 Sep 2019 17:56:10 +0200 Subject: [PATCH 2/5] fix(datepicker): quickfix to fix datepicker position in modals --- frontend/src/utils/form/datepicker.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/frontend/src/utils/form/datepicker.js b/frontend/src/utils/form/datepicker.js index acc057502..932d3b515 100644 --- a/frontend/src/utils/form/datepicker.js +++ b/frontend/src/utils/form/datepicker.js @@ -3,6 +3,7 @@ import { Utility } from '../../core/utility'; import moment from 'moment'; const KEYCODE_ESCAPE = 27; +const Z_INDEX_MODAL = 9999; // INTERNAL (Uni2work specific) formats for formatting dates and/or times const FORM_DATE_FORMAT = { @@ -139,9 +140,14 @@ export class Datepicker { // initialize tail.datetime (datepicker) instance this.datepickerInstance = datetime(this._element, { ...datepickerGlobalConfig, ...datepickerConfig }); - // if the input element is in any open modal, increase the z-index of the datepicker + // append the datepicker element (dt) to the form + this._element.form.appendChild(this.datepickerInstance.dt); + + // if the input element is in any open modal, increase the z-index of the datepicker and set its position to fixed to avoid repositioning on page scroll + // FIXME: instead of setting the position to fixed, use absolute and reposition (decrease left) if (this._element.closest('.modal--open')) { - this.datepickerInstance.dt.style.zIndex = 9999; + this.datepickerInstance.dt.style.zIndex = Z_INDEX_MODAL; + this.datepickerInstance.dt.style.position = 'fixed'; } // register this datepicker instance with the formID of the given element in the datepicker collection From bb9c34fa4de6efc811e6a336a8e68f924ff37b56 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Thu, 12 Sep 2019 09:32:21 +0200 Subject: [PATCH 3/5] feat(invitations): additional explanation for new users --- messages/uniworx/de.msg | 2 ++ templates/mail/invitation.hamlet | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/messages/uniworx/de.msg b/messages/uniworx/de.msg index cae00655d..350bc2047 100644 --- a/messages/uniworx/de.msg +++ b/messages/uniworx/de.msg @@ -796,6 +796,8 @@ MailSubjectSupportCustom customSubject@Text: [Support] #{customSubject} CommCourseSubject: Kursmitteilung MailSubjectLecturerInvitation tid@TermId ssh@SchoolId csh@CourseShorthand: [#{tid}-#{ssh}-#{csh}] Einladung zum Kursverwalter InvitationAcceptDecline: Einladung annehmen/ablehnen +InvitationFromTip displayName@Text: Sie erhalten diese Einladung, weil #{displayName} ihren Versand in Uni2work ausgelöst hat. +InvitationUniWorXTip: Uni2work ist ein webbasiertes Lehrverwaltungssystem der LMU München. MailSubjectParticipantInvitation tid@TermId ssh@SchoolId csh@CourseShorthand: [#{tid}-#{ssh}-#{csh}] Einladung zum Kursteilname diff --git a/templates/mail/invitation.hamlet b/templates/mail/invitation.hamlet index ef3b004e5..ffa11b5cf 100644 --- a/templates/mail/invitation.hamlet +++ b/templates/mail/invitation.hamlet @@ -9,3 +9,7 @@ $newline never

_{MsgInvitationAcceptDecline} +

+ _{MsgInvitationFromTip (userDisplayName jInviter')} +

+ _{MsgInvitationUniWorXTip} From 67f120120f616377c8b5ab34b63941475195fcac Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Thu, 12 Sep 2019 10:36:39 +0200 Subject: [PATCH 4/5] feat(admin-users): allow adding users --- messages/uniworx/de.msg | 22 +++- routes | 1 + src/Foundation.hs | 9 ++ src/Handler/Users.hs | 6 +- src/Handler/Users/Add.hs | 108 ++++++++++++++++++ .../SendNotification/UserAuthModeUpdate.hs | 6 +- templates/mail/userAuthModeUpdate.hamlet | 17 ++- 7 files changed, 156 insertions(+), 13 deletions(-) create mode 100644 src/Handler/Users/Add.hs diff --git a/messages/uniworx/de.msg b/messages/uniworx/de.msg index 350bc2047..add0b278e 100644 --- a/messages/uniworx/de.msg +++ b/messages/uniworx/de.msg @@ -781,9 +781,9 @@ MailUserRightsIntro name@Text email@UserEmail: #{name} <#{email}> hat folgende U MailNoLecturerRights: Sie haben derzeit keine Dozenten-Rechte. MailLecturerRights n@Int: Als Dozent dürfen Sie Veranstaltungen innerhalb #{pluralDE n "Ihres Instituts" "Ihrer Institute"} anlegen. -MailSubjectUserAuthModeUpdate: Änderung Ihres Uni2work-Anmeldemodus -UserAuthModePWHashChangedToLDAP: Sie melden sich nun mit Ihrer Campus-Kennung an -UserAuthModeLDAPChangedToPWHash: Sie melden sich nun mit einer Uni2work-internen Kennung an +MailSubjectUserAuthModeUpdate: Ihr Uni2work-Login +UserAuthModePWHashChangedToLDAP: Sie können sich nun mit Ihrer Campus-Kennung in Uni2work einloggen +UserAuthModeLDAPChangedToPWHash: Sie können sich nun mit einer Uni2work-internen Kennung in Uni2work einloggen NewPasswordLinkTip: Das Passwort Ihrer Uni2work-internen Kennung können Sie auf der folgenden Seite setzen: NewPasswordLink: Neues Passwort setzen AuthPWHashTip: Sie müssen nun das mit "Uni2work-Login" beschriftete Login-Formular verwenden. Stellen Sie bitte sicher, dass Sie ein Passwort gesetzt haben, bevor Sie versuchen sich anzumelden. @@ -1000,6 +1000,7 @@ MenuCourseApplications: Bewerbungen MenuTermShow: Semester MenuSubmissionDelete: Abgabe löschen MenuUsers: Benutzer +MenuUserAdd: Benutzer anlegen MenuUserNotifications: Benachrichtigungs-Einstellungen MenuUserPassword: Passwort MenuAdminTest: Admin-Demo @@ -1631,4 +1632,17 @@ MailAllocationUnratedApplications: Für die unten aufgeführten Kurse liegen Bew MailSubjectAllocationOutdatedRatings allocation@AllocationName: Bereits bewertete Bewerbungen für ihre Kurse in der Zentralanmeldung „#{allocation}“ haben sich geändert MailAllocationOutdatedRatings: Für die unten aufgeführten Kurse liegen Bewerbungen vor, die im Rahmen der Zentralanmeldung an den jeweiligen Kurs gestellt wurden, die sich verändert haben, seit sie zuletzt bewertet wurden. -MailAllocationOutdatedRatingsWarning: Bewerbungen deren Bewertung veraltet ist (d.h. die Bewerbung wurde nach der Bewertung verändert) zählen als nicht bewertet. \ No newline at end of file +MailAllocationOutdatedRatingsWarning: Bewerbungen deren Bewertung veraltet ist (d.h. die Bewerbung wurde nach der Bewertung verändert) zählen als nicht bewertet. + +AdminUserTitle: Titel +AdminUserFirstName: Vorname +AdminUserSurname: Nachname +AdminUserDisplayName: Anzeige-Name +AdminUserEmail: E-Mail Addresse +AdminUserIdent: Identifikation +AdminUserAuth: Authentifizierung +AdminUserMatriculation: Matrikelnummer +AuthKindLDAP: Campus-Kennung +AuthKindPWHash: Uni2work-Kennung +UserAdded: Benutzer erfolgreich angelegt +UserCollision: Benutzer konnte wegen Eindeutigkeit nicht angelegt werden \ No newline at end of file diff --git a/routes b/routes index 293577bf9..9ff5066c9 100644 --- a/routes +++ b/routes @@ -51,6 +51,7 @@ /users/#CryptoUUIDUser/password UserPasswordR GET POST !selfANDis-pw-hash !/users/functionary-invite/new AdminNewFunctionaryInviteR GET POST !/users/functionary-invite AdminFunctionaryInviteR GET POST +!/users/add AdminUserAddR GET POST /admin AdminR GET /admin/features AdminFeaturesR GET POST /admin/test AdminTestR GET POST diff --git a/src/Foundation.hs b/src/Foundation.hs index 740fc2f45..72eb97237 100644 --- a/src/Foundation.hs +++ b/src/Foundation.hs @@ -1752,6 +1752,7 @@ instance YesodBreadcrumbs UniWorX where breadcrumb (AuthR _) = return ("Login" , Just HomeR) breadcrumb HomeR = return ("Uni2work" , Nothing) breadcrumb UsersR = return ("Benutzer" , Just AdminR) + breadcrumb AdminUserAddR = return ("Benutzer anlegen", Just UsersR) breadcrumb (AdminUserR _) = return ("Users" , Just UsersR) breadcrumb AdminR = return ("Administration", Nothing) breadcrumb AdminFeaturesR = return ("Test" , Just AdminR) @@ -2096,6 +2097,14 @@ pageActions (UsersR) = , menuItemModal = True , menuItemAccessCallback' = return True } + , MenuItem + { menuItemType = PageActionPrime + , menuItemLabel = MsgMenuUserAdd + , menuItemIcon = Nothing + , menuItemRoute = SomeRoute AdminUserAddR + , menuItemModal = True + , menuItemAccessCallback' = return True + } ] pageActions (AdminUserR cID) = [ MenuItem diff --git a/src/Handler/Users.hs b/src/Handler/Users.hs index a9d46dfae..be223fa7c 100644 --- a/src/Handler/Users.hs +++ b/src/Handler/Users.hs @@ -1,6 +1,8 @@ {-# OPTIONS_GHC -fno-warn-orphans #-} -module Handler.Users where +module Handler.Users + ( module Handler.Users + ) where import Import @@ -31,6 +33,8 @@ import qualified Data.ByteString.Base64 as Base64 import Text.Hamlet (ihamlet) import Data.Aeson hiding (Result(..)) +import Handler.Users.Add as Handler.Users + hijackUserForm :: Form () hijackUserForm csrf = do diff --git a/src/Handler/Users/Add.hs b/src/Handler/Users/Add.hs new file mode 100644 index 000000000..42834eb2e --- /dev/null +++ b/src/Handler/Users/Add.hs @@ -0,0 +1,108 @@ +module Handler.Users.Add + ( AuthenticationKind(..) + , classifyAuth, mkAuthMode + , AdminUserForm(..), adminUserForm + , getAdminUserAddR, postAdminUserAddR + ) where + + +import Import +import Handler.Utils +import Jobs + + +data AdminUserForm = AdminUserForm + { aufTitle :: Maybe Text + , aufFirstName :: Text + , aufSurname :: UserSurname + , aufDisplayName :: UserDisplayName + , aufMatriculation :: Maybe UserMatriculation + , aufEmail :: UserEmail + , aufIdent :: UserIdent + , aufAuth :: AuthenticationKind + } + +data AuthenticationKind = AuthKindLDAP | AuthKindPWHash + deriving (Eq, Ord, Read, Show, Enum, Bounded, Generic, Typeable) +instance Universe AuthenticationKind +instance Finite AuthenticationKind +embedRenderMessage ''UniWorX ''AuthenticationKind id +nullaryPathPiece ''AuthenticationKind $ camelToPathPiece' 2 + +classifyAuth :: AuthenticationMode -> AuthenticationKind +classifyAuth AuthLDAP = AuthKindLDAP +classifyAuth AuthPWHash{} = AuthKindPWHash + +mkAuthMode :: AuthenticationKind -> AuthenticationMode +mkAuthMode AuthKindLDAP = AuthLDAP +mkAuthMode AuthKindPWHash = AuthPWHash "" + +adminUserForm :: Maybe AdminUserForm -> Form AdminUserForm +adminUserForm template = renderAForm FormStandard + $ AdminUserForm + <$> aopt (textField & cfStrip) (fslI MsgAdminUserTitle) (aufTitle <$> template) + <*> areq (textField & cfStrip) (fslI MsgAdminUserFirstName) (aufFirstName <$> template) + <*> areq (textField & cfStrip) (fslI MsgAdminUserSurname) (aufSurname <$> template) + <*> areq (textField & cfStrip) (fslI MsgAdminUserDisplayName) (aufDisplayName <$> template) + <*> aopt (textField & cfStrip) (fslI MsgAdminUserMatriculation) (aufMatriculation <$> template) + <*> areq (emailField & cfCI) (fslI MsgAdminUserEmail) (aufEmail <$> template) + <*> areq (textField & cfStrip & cfCI) (fslI MsgAdminUserIdent) (aufIdent <$> template) + <*> areq (selectField optionsFinite) (fslI MsgAdminUserAuth) (aufAuth <$> template <|> Just AuthKindLDAP) + + +getAdminUserAddR, postAdminUserAddR :: Handler Html +getAdminUserAddR = postAdminUserAddR +postAdminUserAddR = do + ((userRes, userView), userEnctype) <- runFormPost $ adminUserForm Nothing + + formResult userRes $ \AdminUserForm{..} -> do + now <- liftIO getCurrentTime + UserDefaultConf{..} <- getsYesod $ view _appUserDefaults + + let + newUser@User{..} = User + { userIdent = aufIdent + , userMaxFavourites = userDefaultMaxFavourites + , userTheme = userDefaultTheme + , userDateTimeFormat = userDefaultDateTimeFormat + , userDateFormat = userDefaultDateFormat + , userTimeFormat = userDefaultTimeFormat + , userDownloadFiles = userDefaultDownloadFiles + , userWarningDays = userDefaultWarningDays + , userNotificationSettings = def + , userMailLanguages = def + , userTokensIssuedAfter = Nothing + , userCreated = now + , userLastLdapSynchronisation = Nothing + , userLastAuthentication = Nothing + , userEmail = aufEmail + , userDisplayName = aufDisplayName + , userFirstName = aufFirstName + , userSurname = aufSurname + , userTitle = aufTitle + , userMatrikelnummer = aufMatriculation + , userAuthentication = mkAuthMode aufAuth + } + + didInsert <- runDBJobs . runMaybeT $ do + uid <- MaybeT $ insertUnique newUser + lift . queueDBJob $ JobSynchroniseLdapUser uid + lift . queueDBJob . JobQueueNotification $ NotificationUserAuthModeUpdate uid userAuthentication + when (aufAuth == AuthKindPWHash) $ + lift . queueDBJob $ JobSendPasswordReset uid + return uid + + case didInsert of + Just uid -> do + addMessageI Success MsgUserAdded + cID <- encrypt uid + redirect $ AdminUserR cID + Nothing -> + addMessageI Error MsgUserCollision + + siteLayoutMsg MsgMenuUserAdd $ do + setTitleI MsgMenuUserAdd + wrapForm userView def + { formAction = Just $ SomeRoute AdminUserAddR + , formEncoding = userEnctype + } diff --git a/src/Jobs/Handler/SendNotification/UserAuthModeUpdate.hs b/src/Jobs/Handler/SendNotification/UserAuthModeUpdate.hs index a2f7cb5b5..73629874d 100644 --- a/src/Jobs/Handler/SendNotification/UserAuthModeUpdate.hs +++ b/src/Jobs/Handler/SendNotification/UserAuthModeUpdate.hs @@ -6,6 +6,8 @@ module Jobs.Handler.SendNotification.UserAuthModeUpdate import Import +import Auth.PWHash (PWHashMessage(..)) + import Handler.Utils.Mail import Jobs.Handler.SendNotification.Utils @@ -18,8 +20,8 @@ dispatchNotificationUserAuthModeUpdate nUser _nOriginalAuthMode jRecipient = us replaceMailHeader "Auto-Submitted" $ Just "auto-generated" setSubjectI MsgMailSubjectUserAuthModeUpdate - editNotifications <- mkEditNotifications jRecipient + editNotifications <- ihamletSomeMessage <$> mkEditNotifications jRecipient addAlternatives $ - providePreferredAlternative ($(ihamletFile "templates/mail/userAuthModeUpdate.hamlet") :: HtmlUrlI18n UniWorXMessage (Route UniWorX)) + providePreferredAlternative ($(ihamletFile "templates/mail/userAuthModeUpdate.hamlet") :: HtmlUrlI18n (SomeMessage UniWorX) (Route UniWorX)) diff --git a/templates/mail/userAuthModeUpdate.hamlet b/templates/mail/userAuthModeUpdate.hamlet index 79ba9c8ef..d128ab4db 100644 --- a/templates/mail/userAuthModeUpdate.hamlet +++ b/templates/mail/userAuthModeUpdate.hamlet @@ -13,13 +13,18 @@ $newline never

$case userAuthentication $of AuthLDAP - _{MsgUserAuthModePWHashChangedToLDAP} + _{SomeMessage MsgUserAuthModePWHashChangedToLDAP} $of AuthPWHash _ - _{MsgUserAuthModeLDAPChangedToPWHash} + _{SomeMessage MsgUserAuthModeLDAPChangedToPWHash} $if is _AuthPWHash userAuthentication

- _{MsgAuthPWHashTip} -

- _{MsgPasswordResetEmailIncoming} + _{SomeMessage MsgAuthPWHashTip} +

+
_{SomeMessage MsgPWHashIdent} +
#{userIdent} +
_{SomeMessage MsgPWHashPassword} +
+ _{SomeMessage MsgPasswordResetEmailIncoming} - ^{editNotifications} + $if is _Just userLastAuthentication + ^{editNotifications} From 9248b72b6f5e1f4d516dcf3f1329fe4a419f597c Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Thu, 12 Sep 2019 10:48:58 +0200 Subject: [PATCH 5/5] chore(release): 6.7.0 --- CHANGELOG.md | 18 ++++++++++++++++++ package-lock.json | 2 +- package.json | 2 +- package.yaml | 2 +- 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b28f4605..0df264d6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,24 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [6.7.0](https://gitlab.cip.ifi.lmu.de/jost/UniWorX/compare/v6.6.0...v6.7.0) (2019-09-12) + + +### Bug Fixes + +* **datepicker:** increase datepicker z-index in modals ([593a6a7](https://gitlab.cip.ifi.lmu.de/jost/UniWorX/commit/593a6a7)) +* **datepicker:** quickfix to fix datepicker position in modals ([3f9454a](https://gitlab.cip.ifi.lmu.de/jost/UniWorX/commit/3f9454a)) +* **submission-users:** properly delete old invitations ([91c926b](https://gitlab.cip.ifi.lmu.de/jost/UniWorX/commit/91c926b)) + + +### Features + +* **admin-users:** allow adding users ([67f1201](https://gitlab.cip.ifi.lmu.de/jost/UniWorX/commit/67f1201)) +* **health:** timeout all health checks ([33338cd](https://gitlab.cip.ifi.lmu.de/jost/UniWorX/commit/33338cd)) +* **invitations:** additional explanation for new users ([bb9c34f](https://gitlab.cip.ifi.lmu.de/jost/UniWorX/commit/bb9c34f)) + + + ## [6.6.0](https://gitlab.cip.ifi.lmu.de/jost/UniWorX/compare/v6.5.0...v6.6.0) (2019-09-09) diff --git a/package-lock.json b/package-lock.json index daac92fa4..fcb1215fb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "uni2work", - "version": "6.6.0", + "version": "6.7.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 42d9345cf..fc9399b98 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "uni2work", - "version": "6.6.0", + "version": "6.7.0", "description": "", "keywords": [], "author": "", diff --git a/package.yaml b/package.yaml index e8685cb40..937849fb1 100644 --- a/package.yaml +++ b/package.yaml @@ -1,5 +1,5 @@ name: uniworx -version: 6.6.0 +version: 6.7.0 dependencies: # Due to a bug in GHC 8.0.1, we block its usage