Merge branch 'fradrive/cr3'
This commit is contained in:
commit
ad8e67dab1
@ -83,6 +83,7 @@ health-check-matching-cluster-config-timeout: "_env:HEALTHCHECK_MATCHING_CLUSTER
|
|||||||
|
|
||||||
synchronise-ldap-users-within: "_env:SYNCHRONISE_LDAP_WITHIN:1209600" # 14 Tage in Sekunden
|
synchronise-ldap-users-within: "_env:SYNCHRONISE_LDAP_WITHIN:1209600" # 14 Tage in Sekunden
|
||||||
synchronise-ldap-users-interval: "_env:SYNCHRONISE_LDAP_INTERVAL:3600" # jede Stunde
|
synchronise-ldap-users-interval: "_env:SYNCHRONISE_LDAP_INTERVAL:3600" # jede Stunde
|
||||||
|
synchronise-ldap-users-expire: "_env:SYNCHRONISE_LDAP_EXPIRE:15897600" # halbes Jahr in Sekunden
|
||||||
|
|
||||||
synchronise-avs-users-within: "_env:SYNCHRONISE_AVS_WITHIN:5702400" # alle 66 Tage
|
synchronise-avs-users-within: "_env:SYNCHRONISE_AVS_WITHIN:5702400" # alle 66 Tage
|
||||||
synchronise-avs-users-interval: "_env:SYNCHRONISE_AVS_INTERVAL:21600" # alle 6 Stunden
|
synchronise-avs-users-interval: "_env:SYNCHRONISE_AVS_INTERVAL:21600" # alle 6 Stunden
|
||||||
|
|||||||
@ -48,6 +48,8 @@ FilterSupervisorCompany fsh@CompanyShorthand: Hat aktiven Ansprechpartner, #{fsh
|
|||||||
FilterSupervisorForeign fsh@CompanyShorthand: Hat aktiven Ansprechpartner, der selbst nicht #{fsh} angehört
|
FilterSupervisorForeign fsh@CompanyShorthand: Hat aktiven Ansprechpartner, der selbst nicht #{fsh} angehört
|
||||||
FilterForeignSupervisor: Hat firmenfremde Ansprechpartner
|
FilterForeignSupervisor: Hat firmenfremde Ansprechpartner
|
||||||
FilterFirmExtern: Externe Firma
|
FilterFirmExtern: Externe Firma
|
||||||
|
FilterFirmPrimary: Ist primäre Firma in FRADrive
|
||||||
|
FilterHasQualification: Hat Firmenangehörige mit aktuell gültiger Qualifikation
|
||||||
FirmSupervisorOf fsh@CompanyShorthand: Ansprechpartner #{fsh} angehörig
|
FirmSupervisorOf fsh@CompanyShorthand: Ansprechpartner #{fsh} angehörig
|
||||||
FirmSupervisorIndependent: Ansprechpartner ohne jegliche Firmenzugehörigkeit
|
FirmSupervisorIndependent: Ansprechpartner ohne jegliche Firmenzugehörigkeit
|
||||||
FirmEmployeeOf fsh@CompanyShorthand: Firmenangehörige #{fsh}
|
FirmEmployeeOf fsh@CompanyShorthand: Firmenangehörige #{fsh}
|
||||||
|
|||||||
@ -48,6 +48,8 @@ FilterSupervisorCompany fsh: Has active company supervisor belonging to #{fsh}
|
|||||||
FilterSupervisorForeign fsh: Has active supervisor not belonging to #{fsh}
|
FilterSupervisorForeign fsh: Has active supervisor not belonging to #{fsh}
|
||||||
FilterForeignSupervisor: Has company-external supervisors
|
FilterForeignSupervisor: Has company-external supervisors
|
||||||
FilterFirmExtern: External company
|
FilterFirmExtern: External company
|
||||||
|
FilterFirmPrimary: Is primary company in FRADrive
|
||||||
|
FilterHasQualification: Has company associates with currently valid qualification
|
||||||
FirmSupervisorOf fsh@CompanyShorthand: Supervisors belonging to #{fsh}
|
FirmSupervisorOf fsh@CompanyShorthand: Supervisors belonging to #{fsh}
|
||||||
FirmSupervisorIndependent: Independent supervisors
|
FirmSupervisorIndependent: Independent supervisors
|
||||||
FirmEmployeeOf fsh@CompanyShorthand: #{fsh} associated users
|
FirmEmployeeOf fsh@CompanyShorthand: #{fsh} associated users
|
||||||
|
|||||||
@ -151,3 +151,5 @@ BreadcrumbSubmissionAuthorshipStatements: Eigenständigkeitserklärungen
|
|||||||
BreadcrumbExternalApis: Externe APIs
|
BreadcrumbExternalApis: Externe APIs
|
||||||
BreadcrumbApiDocs: API Dokumentation
|
BreadcrumbApiDocs: API Dokumentation
|
||||||
BreadcrumbSwagger !ident-ok: OpenAPI 2.0 (Swagger)
|
BreadcrumbSwagger !ident-ok: OpenAPI 2.0 (Swagger)
|
||||||
|
BreadcrumbSynchLdap !ident-ok: LDAP Synch
|
||||||
|
BreadcrumbSynchAvs !ident-ok: AVS Synch
|
||||||
@ -151,3 +151,5 @@ BreadcrumbSubmissionAuthorshipStatements: Statements of Authorship
|
|||||||
BreadcrumbExternalApis: External APIs
|
BreadcrumbExternalApis: External APIs
|
||||||
BreadcrumbApiDocs: API documentation
|
BreadcrumbApiDocs: API documentation
|
||||||
BreadcrumbSwagger: OpenAPI 2.0 (Swagger)
|
BreadcrumbSwagger: OpenAPI 2.0 (Swagger)
|
||||||
|
BreadcrumbSynchLdap: Synch LDAP
|
||||||
|
BreadcrumbSynchAvs: Synch AVS
|
||||||
|
|||||||
@ -73,6 +73,7 @@ TableDiffDaysTooltip: Zeitspanne nach ISO 8601. Beispiel: "P2Y3M4D" ist eine Zei
|
|||||||
TableExamOfficeLabel: Label-Name
|
TableExamOfficeLabel: Label-Name
|
||||||
TableExamOfficeLabelStatus: Label-Farbe
|
TableExamOfficeLabelStatus: Label-Farbe
|
||||||
TableExamOfficeLabelPriority: Label-Priorität
|
TableExamOfficeLabelPriority: Label-Priorität
|
||||||
|
TableQualification: Qualifikation
|
||||||
TableQualifications: Qualifikationen
|
TableQualifications: Qualifikationen
|
||||||
TableCompany: Firma
|
TableCompany: Firma
|
||||||
TableCompanyFilter: Firma oder Nummer
|
TableCompanyFilter: Firma oder Nummer
|
||||||
|
|||||||
@ -73,6 +73,7 @@ TableDiffDaysTooltip: Duration given according to ISO 8601. Example: "P2Y3M4D" i
|
|||||||
TableExamOfficeLabel: Label name
|
TableExamOfficeLabel: Label name
|
||||||
TableExamOfficeLabelStatus: Label colour
|
TableExamOfficeLabelStatus: Label colour
|
||||||
TableExamOfficeLabelPriority: Label priority
|
TableExamOfficeLabelPriority: Label priority
|
||||||
|
TableQualification: Qualification
|
||||||
TableQualifications: Qualifications
|
TableQualifications: Qualifications
|
||||||
TableCompany: Company
|
TableCompany: Company
|
||||||
TableCompanyFilter: Company/Nr
|
TableCompanyFilter: Company/Nr
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
-- Description of companies associated with users
|
-- Description of companies associated with users
|
||||||
|
|
||||||
Company
|
Company
|
||||||
name CompanyName -- == (CI Text)
|
name CompanyName -- == (CI Text) -- NOTE: Fraport department name may carry additional information; use the Shorthand with respect to UserCompanyDepartment
|
||||||
shorthand CompanyShorthand -- == (CI Text) and CompanyKey :: CompanyShorthand -> CompanyId A change to AvsId as primary key is too much work and not strictly necessary due to Uniqueness
|
shorthand CompanyShorthand -- == (CI Text) and CompanyKey :: CompanyShorthand -> CompanyId A change to AvsId as primary key is too much work and not strictly necessary due to Uniqueness
|
||||||
avsId Int default=0 -- primary key from avs, use negative numbers for non-AVS companies
|
avsId Int default=0 -- primary key from avs, use negative numbers for non-AVS companies
|
||||||
prefersPostal Bool default=false -- new company users prefers letters by post instead of email
|
prefersPostal Bool default=false -- new company users prefers letters by post instead of email
|
||||||
|
|||||||
8
routes
8
routes
@ -52,9 +52,11 @@
|
|||||||
|
|
||||||
/ NewsR GET !free
|
/ NewsR GET !free
|
||||||
/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 GET POST !adminANDno-escalation
|
/users/#CryptoUUIDUser/hijack AdminHijackUserR GET POST !adminANDno-escalation
|
||||||
|
/users/#CryptoUUIDUser/sync/ldap AdminUserSyncLdapR GET
|
||||||
|
/users/#CryptoUUIDUser/sync/avs AdminUserSyncAvsR GET
|
||||||
/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
|
||||||
|
|||||||
@ -87,9 +87,11 @@ breadcrumb (AdminUserR cID) = useRunDB . maybeT (i18nCrumb MsgBreadcrumbUser $ J
|
|||||||
uid <- decrypt cID
|
uid <- decrypt cID
|
||||||
User{..} <- MaybeT $ get uid
|
User{..} <- MaybeT $ get uid
|
||||||
return (userDisplayName, Just UsersR)
|
return (userDisplayName, Just UsersR)
|
||||||
breadcrumb (AdminUserDeleteR cID) = i18nCrumb MsgBreadcrumbUserDelete . Just $ AdminUserR cID
|
breadcrumb (AdminUserDeleteR cID) = i18nCrumb MsgBreadcrumbUserDelete . Just $ AdminUserR cID
|
||||||
breadcrumb (AdminHijackUserR cID) = i18nCrumb MsgBreadcrumbUserHijack . Just $ AdminUserR cID
|
breadcrumb (AdminUserSyncLdapR cID) = i18nCrumb MsgBreadcrumbSynchLdap . Just $ AdminUserR cID
|
||||||
breadcrumb (UserNotificationR cID) = useRunDB $ do
|
breadcrumb (AdminUserSyncAvsR cID) = i18nCrumb MsgBreadcrumbSynchAvs . Just $ AdminUserR cID
|
||||||
|
breadcrumb (AdminHijackUserR cID) = i18nCrumb MsgBreadcrumbUserHijack . Just $ AdminUserR cID
|
||||||
|
breadcrumb (UserNotificationR cID) = useRunDB $ do
|
||||||
mayList <- hasReadAccessTo UsersR
|
mayList <- hasReadAccessTo UsersR
|
||||||
if
|
if
|
||||||
| mayList
|
| mayList
|
||||||
@ -1225,6 +1227,14 @@ pageActions (AdminUserR cID) = return
|
|||||||
, NavPageActionPrimary
|
, NavPageActionPrimary
|
||||||
{ navLink = defNavLink MsgMenuUserEdit $ ForProfileR cID
|
{ navLink = defNavLink MsgMenuUserEdit $ ForProfileR cID
|
||||||
, navChildren = []
|
, navChildren = []
|
||||||
|
}
|
||||||
|
, NavPageActionPrimary
|
||||||
|
{ navLink = defNavLink MsgUserLdapSync $ AdminUserSyncLdapR cID
|
||||||
|
, navChildren = []
|
||||||
|
}
|
||||||
|
, NavPageActionPrimary
|
||||||
|
{ navLink = defNavLink MsgUserAvsSync $ AdminUserSyncAvsR cID
|
||||||
|
, navChildren = []
|
||||||
}
|
}
|
||||||
, NavPageActionPrimary
|
, NavPageActionPrimary
|
||||||
{ navLink = defNavLinkModal MsgUserHijack $ AdminHijackUserR cID
|
{ navLink = defNavLinkModal MsgUserHijack $ AdminHijackUserR cID
|
||||||
|
|||||||
@ -95,7 +95,7 @@ handleAdminProblems mbProblemTable = do
|
|||||||
(Left e) -> return $ Left $ text2widget $ tshow (e :: SomeException)
|
(Left e) -> return $ Left $ text2widget $ tshow (e :: SomeException)
|
||||||
(Right AvsLicenceDifferences{..}) -> do
|
(Right AvsLicenceDifferences{..}) -> do
|
||||||
let problemIds = avsLicenceDiffRevokeAll <> avsLicenceDiffGrantVorfeld <> avsLicenceDiffRevokeRollfeld <> avsLicenceDiffGrantRollfeld
|
let problemIds = avsLicenceDiffRevokeAll <> avsLicenceDiffGrantVorfeld <> avsLicenceDiffRevokeRollfeld <> avsLicenceDiffGrantRollfeld
|
||||||
queueAvsUpdateByAID problemIds $ Just nowaday
|
void $ runDB $ queueAvsUpdateByAID problemIds $ Just nowaday
|
||||||
return $ Right
|
return $ Right
|
||||||
( Set.size avsLicenceDiffRevokeAll
|
( Set.size avsLicenceDiffRevokeAll
|
||||||
, Set.size avsLicenceDiffGrantVorfeld
|
, Set.size avsLicenceDiffGrantVorfeld
|
||||||
|
|||||||
@ -464,7 +464,7 @@ resultAllCompanyDefaultReroutes = _dbrOutput . _4 . _unValue
|
|||||||
|
|
||||||
mkFirmAllTable :: Bool -> UserId -> DB (FormResult (FirmActionData, Set CompanyId), Widget)
|
mkFirmAllTable :: Bool -> UserId -> DB (FormResult (FirmActionData, Set CompanyId), Widget)
|
||||||
mkFirmAllTable isAdmin uid = do
|
mkFirmAllTable isAdmin uid = do
|
||||||
-- now <- liftIO getCurrentTime
|
now <- liftIO getCurrentTime
|
||||||
mr <- getMessageRender
|
mr <- getMessageRender
|
||||||
let
|
let
|
||||||
resultDBTable = DBTable{..}
|
resultDBTable = DBTable{..}
|
||||||
@ -701,6 +701,16 @@ mkFirmAllTable isAdmin uid = do
|
|||||||
Just False -> E.notExists checkSuper
|
Just False -> E.notExists checkSuper
|
||||||
)
|
)
|
||||||
, single ("company-postal", FilterColumn $ E.mkExactFilterLast $ views (to queryAllCompany) (E.isJust . (E.^. CompanyPostAddress)))
|
, single ("company-postal", FilterColumn $ E.mkExactFilterLast $ views (to queryAllCompany) (E.isJust . (E.^. CompanyPostAddress)))
|
||||||
|
, single ("qualification" , FilterColumn . E.mkExistsFilter $ \row (CI.mk -> criterion :: CI Text) -> do
|
||||||
|
(usrCmp :& usrQual :& qual) <- E.from $ E.table @UserCompany
|
||||||
|
`E.innerJoin` E.table @QualificationUser
|
||||||
|
`E.on` (\(usrCmp :& usrQual) -> usrCmp E.^. UserCompanyUser E.==. usrQual E.^. QualificationUserUser)
|
||||||
|
`E.innerJoin` E.table @Qualification
|
||||||
|
`E.on` (\(_ :& usrQual :& qual) -> qual E.^. QualificationId E.==. usrQual E.^. QualificationUserQualification)
|
||||||
|
E.where_ $ usrCmp E.^. UserCompanyCompany E.==. queryAllCompany row E.^. CompanyId
|
||||||
|
E.&&. qual E.^. QualificationShorthand E.==. E.val criterion
|
||||||
|
E.&&. validQualification now usrQual
|
||||||
|
)
|
||||||
]
|
]
|
||||||
dbtFilterUI mPrev = mconcat
|
dbtFilterUI mPrev = mconcat
|
||||||
[ fltrCompanyNameUI mPrev
|
[ fltrCompanyNameUI mPrev
|
||||||
@ -711,6 +721,7 @@ mkFirmAllTable isAdmin uid = do
|
|||||||
, prismAForm (singletonFilter "is-default-supervisor") mPrev $ aopt textField (fslI MsgFirmSuperDefault)
|
, prismAForm (singletonFilter "is-default-supervisor") mPrev $ aopt textField (fslI MsgFirmSuperDefault)
|
||||||
, prismAForm (singletonFilter "foreign-supervisor" . maybePrism _PathPiece) mPrev $ aopt (boolField . Just $ SomeMessage MsgBoolIrrelevant) (fslI MsgFilterForeignSupervisor)
|
, prismAForm (singletonFilter "foreign-supervisor" . maybePrism _PathPiece) mPrev $ aopt (boolField . Just $ SomeMessage MsgBoolIrrelevant) (fslI MsgFilterForeignSupervisor)
|
||||||
, prismAForm (singletonFilter "company-postal" . maybePrism _PathPiece) mPrev $ aopt (boolField . Just $ SomeMessage MsgBoolIrrelevant) (fslI MsgFilterFirmExtern)
|
, prismAForm (singletonFilter "company-postal" . maybePrism _PathPiece) mPrev $ aopt (boolField . Just $ SomeMessage MsgBoolIrrelevant) (fslI MsgFilterFirmExtern)
|
||||||
|
, fltrQualificationHdrUI MsgFilterHasQualification mPrev
|
||||||
]
|
]
|
||||||
dbtStyle = def { dbsFilterLayout = defaultDBSFilterLayout }
|
dbtStyle = def { dbsFilterLayout = defaultDBSFilterLayout }
|
||||||
dbtParams = DBParamsForm
|
dbtParams = DBParamsForm
|
||||||
@ -796,7 +807,7 @@ queryUserUser = $(sqlIJproj 2 1)
|
|||||||
queryUserUserCompany :: UserCompanyTableExpr -> E.SqlExpr (Entity UserCompany)
|
queryUserUserCompany :: UserCompanyTableExpr -> E.SqlExpr (Entity UserCompany)
|
||||||
queryUserUserCompany = $(sqlIJproj 2 2)
|
queryUserUserCompany = $(sqlIJproj 2 2)
|
||||||
|
|
||||||
type UserCompanyTableData = DBRow (Entity User, Entity UserCompany, E.Value Word64, E.Value Word64)
|
type UserCompanyTableData = DBRow (Entity User, Entity UserCompany, E.Value Word64, E.Value Word64) -- , E.Value Bool)
|
||||||
|
|
||||||
resultUserUser :: Lens' UserCompanyTableData (Entity User)
|
resultUserUser :: Lens' UserCompanyTableData (Entity User)
|
||||||
resultUserUser = _dbrOutput . _1
|
resultUserUser = _dbrOutput . _1
|
||||||
@ -810,6 +821,9 @@ resultUserCompanySupervisors = _dbrOutput . _3 . _unValue
|
|||||||
resultUserCompanyReroutes :: Lens' UserCompanyTableData Word64
|
resultUserCompanyReroutes :: Lens' UserCompanyTableData Word64
|
||||||
resultUserCompanyReroutes = _dbrOutput . _4 . _unValue
|
resultUserCompanyReroutes = _dbrOutput . _4 . _unValue
|
||||||
|
|
||||||
|
-- resultUserCompanyPrimary :: Lens' UserCompanyTableData Bool
|
||||||
|
-- resultUserCompanyPrimary = _dbrOutput . _5 . _unValue
|
||||||
|
|
||||||
instance HasEntity UserCompanyTableData User where
|
instance HasEntity UserCompanyTableData User where
|
||||||
hasEntity = resultUserUser
|
hasEntity = resultUserUser
|
||||||
|
|
||||||
@ -837,20 +851,24 @@ mkFirmUserTable isAdmin cid = do
|
|||||||
(usr :& usrCmp) <- E.from $ E.table @User `E.leftJoin` E.table @UserCompany
|
(usr :& usrCmp) <- E.from $ E.table @User `E.leftJoin` E.table @UserCompany
|
||||||
`E.on` (\(usr :& usrCmp) -> usr E.^. UserId E.=?. usrCmp E.?. UserCompanyUser E.&&. usrCmp E.?. UserCompanyCompany E.==. E.justVal cid)
|
`E.on` (\(usr :& usrCmp) -> usr E.^. UserId E.=?. usrCmp E.?. UserCompanyUser E.&&. usrCmp E.?. UserCompanyCompany E.==. E.justVal cid)
|
||||||
E.where_ $ E.isTrue (usrCmp E.?. UserCompanySupervisor)
|
E.where_ $ E.isTrue (usrCmp E.?. UserCompanySupervisor)
|
||||||
E.||. E.exists (firmQuerySupervisedBy cid Nothing usr)
|
E.||. E.exists (firmQuerySupervisedBy cid Nothing usr)
|
||||||
return (usr E.^. UserId, usr E.^. UserDisplayName, usrCmp E.?. UserCompanySupervisor)
|
return (usr E.^. UserId, usr E.^. UserDisplayName, usrCmp E.?. UserCompanySupervisor)
|
||||||
let
|
let
|
||||||
-- supervisorField :: Field Handler UserId
|
-- supervisorField :: Field Handler UserId
|
||||||
-- supervisorField = selectField' (Just $ SomeMessage MsgMultiNoSelection) $ procOptions rawSupers
|
-- supervisorField = selectField' (Just $ SomeMessage MsgMultiNoSelection) $ procOptions rawSupers
|
||||||
supervisorsField = multiSelectField' (Just $ SomeMessage MsgMultiNoSelection) $ procOptions rawSupers
|
supervisorsField = multiSelectField' (Just $ SomeMessage MsgMultiNoSelection) $ procOptions rawSupers
|
||||||
|
|
||||||
|
|
||||||
fsh = unCompanyKey cid
|
fsh = unCompanyKey cid
|
||||||
resultDBTable = DBTable{..}
|
resultDBTable = DBTable{..}
|
||||||
where
|
where
|
||||||
dbtSQLQuery = \(usr `E.InnerJoin` usrCmp) -> do
|
dbtSQLQuery = \(usr `E.InnerJoin` usrCmp) -> do
|
||||||
EL.on $ usr E.^. UserId E.==. usrCmp E.^. UserCompanyUser
|
EL.on $ usr E.^. UserId E.==. usrCmp E.^. UserCompanyUser
|
||||||
E.where_ $ usrCmp E.^. UserCompanyCompany E.==. E.val cid
|
E.where_ $ usrCmp E.^. UserCompanyCompany E.==. E.val cid
|
||||||
|
-- let isPrimary = E.notExists (do
|
||||||
|
-- other <- E.from $ E.table @UserCompany
|
||||||
|
-- E.where_ $ other E.^. UserCompanyUser E.==. usrCmp E.^. UserCompanyUser
|
||||||
|
-- E.&&. other E.^. UserCompanyPriority E.>. usrCmp E.^. UserCompanyPriority
|
||||||
|
-- )
|
||||||
return (usr, usrCmp, firmCountUserSupervisors usrCmp, firmCountUserSupervisorsReroute usrCmp)
|
return (usr, usrCmp, firmCountUserSupervisors usrCmp, firmCountUserSupervisorsReroute usrCmp)
|
||||||
dbtRowKey = queryUserUser >>> (E.^. UserId)
|
dbtRowKey = queryUserUser >>> (E.^. UserId)
|
||||||
dbtProj = dbtProjId
|
dbtProj = dbtProjId
|
||||||
@ -928,15 +946,25 @@ mkFirmUserTable isAdmin cid = do
|
|||||||
usrSpr <- E.from $ E.table @UserSupervisor
|
usrSpr <- E.from $ E.table @UserSupervisor
|
||||||
E.where_ $ usrSpr E.^. UserSupervisorUser E.==. queryUserUser row E.^. UserId
|
E.where_ $ usrSpr E.^. UserSupervisorUser E.==. queryUserUser row E.^. UserId
|
||||||
E.&&. usrSpr E.^. UserSupervisorSupervisor `E.in_` E.vals criteria
|
E.&&. usrSpr E.^. UserSupervisorSupervisor `E.in_` E.vals criteria
|
||||||
|
, singletonMap "is-primary-company" $ FilterColumn $ \row (getLast -> criterion) ->
|
||||||
|
let checkPrimary = do
|
||||||
|
other <- E.from $ E.table @UserCompany
|
||||||
|
E.where_ $ other E.^. UserCompanyUser E.==. queryUserUserCompany row E.^. UserCompanyUser
|
||||||
|
E.&&. other E.^. UserCompanyPriority E.>. queryUserUserCompany row E.^. UserCompanyPriority
|
||||||
|
in case criterion of
|
||||||
|
Nothing -> E.true
|
||||||
|
Just False -> E.exists checkPrimary
|
||||||
|
Just True -> E.notExists checkPrimary
|
||||||
]
|
]
|
||||||
-- superField = selectField $ ????
|
-- superField = selectField $ ????
|
||||||
dbtFilterUI mPrev = mconcat
|
dbtFilterUI mPrev = mconcat
|
||||||
[ fltrUserNameEmailHdrUI MsgTableCompanyUser mPrev
|
[ fltrUserNameEmailHdrUI MsgTableCompanyUser mPrev
|
||||||
-- , prismAForm (singletonFilter "supervisor-is" . maybePrism _PathPiece) mPrev $ aopt (hoistField lift supervisorField) (fslI MsgFilterSupervisor)
|
-- , prismAForm (singletonFilter "supervisor-is" . maybePrism _PathPiece) mPrev $ aopt (hoistField lift supervisorField) (fslI MsgFilterSupervisor)
|
||||||
, prismAForm (multiFilter "supervisors-are" . maybePrism monoPathPieces) mPrev $ aopt (hoistField lift supervisorsField) (fslI MsgFilterSupervisor & setTooltip MsgMultiSelectTip)
|
, prismAForm (multiFilter "supervisors-are" . maybePrism monoPathPieces) mPrev $ aopt (hoistField lift supervisorsField) (fslI MsgFilterSupervisor & setTooltip MsgMultiSelectTip)
|
||||||
, prismAForm (singletonFilter "has-supervisor" . maybePrism _PathPiece) mPrev $ aopt (boolField . Just $ SomeMessage MsgBoolIrrelevant) (fslI MsgFilterSupervisor)
|
, prismAForm (singletonFilter "has-supervisor" . maybePrism _PathPiece) mPrev $ aopt (boolField . Just $ SomeMessage MsgBoolIrrelevant) (fslI MsgFilterSupervisor)
|
||||||
, prismAForm (singletonFilter "has-company-supervisor" . maybePrism _PathPiece) mPrev $ aopt (boolField . Just $ SomeMessage MsgBoolIrrelevant) (fslI $ MsgFilterSupervisorCompany fsh)
|
, prismAForm (singletonFilter "has-company-supervisor" . maybePrism _PathPiece) mPrev $ aopt (boolField . Just $ SomeMessage MsgBoolIrrelevant) (fslI $ MsgFilterSupervisorCompany fsh)
|
||||||
, prismAForm (singletonFilter "has-foreign-supervisor" . maybePrism _PathPiece) mPrev $ aopt (boolField . Just $ SomeMessage MsgBoolIrrelevant) (fslI $ MsgFilterSupervisorForeign fsh)
|
, prismAForm (singletonFilter "has-foreign-supervisor" . maybePrism _PathPiece) mPrev $ aopt (boolField . Just $ SomeMessage MsgBoolIrrelevant) (fslI $ MsgFilterSupervisorForeign fsh)
|
||||||
|
, prismAForm (singletonFilter "is-primary-company" . maybePrism _PathPiece) mPrev $ aopt (boolField . Just $ SomeMessage MsgBoolIrrelevant) (fslI MsgFilterFirmPrimary)
|
||||||
]
|
]
|
||||||
dbtStyle = def { dbsFilterLayout = defaultDBSFilterLayout }
|
dbtStyle = def { dbsFilterLayout = defaultDBSFilterLayout }
|
||||||
acts :: Map FirmUserAction (AForm Handler FirmUserActionData)
|
acts :: Map FirmUserAction (AForm Handler FirmUserActionData)
|
||||||
|
|||||||
@ -14,11 +14,14 @@ module Handler.Profile
|
|||||||
, getSetDisplayEmailR, postSetDisplayEmailR
|
, getSetDisplayEmailR, postSetDisplayEmailR
|
||||||
, getCsvOptionsR, postCsvOptionsR
|
, getCsvOptionsR, postCsvOptionsR
|
||||||
, postLangR
|
, postLangR
|
||||||
|
, getAdminUserSyncAvsR
|
||||||
|
, getAdminUserSyncLdapR
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Import
|
import Import
|
||||||
|
|
||||||
import Handler.Utils
|
import Handler.Utils
|
||||||
|
import Handler.Utils.Avs
|
||||||
import Handler.Utils.Profile
|
import Handler.Utils.Profile
|
||||||
import Handler.Utils.Users
|
import Handler.Utils.Users
|
||||||
import Handler.Utils.Company
|
import Handler.Utils.Company
|
||||||
@ -1255,3 +1258,18 @@ postLangR = do
|
|||||||
addMessage Success . toHtml $ mr MsgLanguageChanged
|
addMessage Success . toHtml $ mr MsgLanguageChanged
|
||||||
|
|
||||||
redirect . fromMaybe NewsR =<< lookupGlobalGetParam GetReferer
|
redirect . fromMaybe NewsR =<< lookupGlobalGetParam GetReferer
|
||||||
|
|
||||||
|
|
||||||
|
getAdminUserSyncLdapR :: CryptoUUIDUser -> Handler Html
|
||||||
|
getAdminUserSyncLdapR uuid = do
|
||||||
|
uid <- decrypt uuid
|
||||||
|
queueJob' $ JobSynchroniseLdapUser uid
|
||||||
|
addMessageI Success $ MsgSynchroniseLdapUserQueued 1
|
||||||
|
redirectUltDest $ AdminUserR uuid
|
||||||
|
|
||||||
|
getAdminUserSyncAvsR :: CryptoUUIDUser -> Handler Html
|
||||||
|
getAdminUserSyncAvsR uuid = do
|
||||||
|
uid <- decrypt uuid
|
||||||
|
n <- runDB $ queueAvsUpdateByUID (Set.singleton uid) Nothing
|
||||||
|
addMessageI Success $ MsgSynchroniseAvsUserQueued $ fromIntegral n
|
||||||
|
redirectUltDest $ AdminUserR uuid
|
||||||
|
|||||||
@ -62,19 +62,20 @@ hijackUserForm = \csrf -> do
|
|||||||
-- instance HasUser (DBRow (Entity USer)) where
|
-- instance HasUser (DBRow (Entity USer)) where
|
||||||
-- hasUser = _entityVal
|
-- hasUser = _entityVal
|
||||||
|
|
||||||
data UserAction = UserLdapSync | UserAddSupervisor | UserSetSupervisor | UserRemoveSupervisor | UserAvsSync
|
data UserAction = UserAvsSync | UserLdapSync | UserAddSupervisor | UserSetSupervisor | UserRemoveSupervisor
|
||||||
deriving (Eq, Ord, Enum, Bounded, Read, Show, Generic)
|
deriving (Eq, Ord, Enum, Bounded, Read, Show, Generic)
|
||||||
deriving anyclass (Universe, Finite)
|
deriving anyclass (Universe, Finite)
|
||||||
|
|
||||||
nullaryPathPiece ''UserAction $ camelToPathPiece' 1
|
nullaryPathPiece ''UserAction $ camelToPathPiece' 1
|
||||||
embedRenderMessage ''UniWorX ''UserAction id
|
embedRenderMessage ''UniWorX ''UserAction id
|
||||||
|
|
||||||
data UserActionData = UserLdapSyncData
|
data UserActionData = UserAvsSyncData
|
||||||
|
| UserLdapSyncData
|
||||||
| UserHijack
|
| UserHijack
|
||||||
| UserAddSupervisorData { getActionSupervisors :: Set Text, getActionRerouteNotifications :: Bool, getActionSupervisorReason :: Maybe Text }
|
| UserAddSupervisorData { getActionSupervisors :: Set Text, getActionRerouteNotifications :: Bool, getActionSupervisorReason :: Maybe Text }
|
||||||
| UserSetSupervisorData { getActionSupervisors :: Set Text, getActionRerouteNotifications :: Bool, getActionSupervisorReason :: Maybe Text }
|
| UserSetSupervisorData { getActionSupervisors :: Set Text, getActionRerouteNotifications :: Bool, getActionSupervisorReason :: Maybe Text }
|
||||||
| UserRemoveSupervisorData
|
| UserRemoveSupervisorData
|
||||||
| UserAvsSyncData
|
|
||||||
deriving (Eq, Ord, Read, Show, Generic)
|
deriving (Eq, Ord, Read, Show, Generic)
|
||||||
|
|
||||||
isNotSetSupervisor :: UserActionData -> Bool
|
isNotSetSupervisor :: UserActionData -> Bool
|
||||||
@ -369,8 +370,8 @@ postUsersR = do
|
|||||||
addMessageI Success . MsgSynchroniseLdapUserQueued $ Set.size userSet
|
addMessageI Success . MsgSynchroniseLdapUserQueued $ Set.size userSet
|
||||||
redirectKeepGetParams UsersR
|
redirectKeepGetParams UsersR
|
||||||
(UserAvsSyncData, userSet) -> do
|
(UserAvsSyncData, userSet) -> do
|
||||||
queueAvsUpdateByUID userSet Nothing
|
n <- runDB $ queueAvsUpdateByUID userSet Nothing
|
||||||
addMessageI Success . MsgSynchroniseAvsUserQueued $ Set.size userSet
|
addMessageI Success . MsgSynchroniseAvsUserQueued $ fromIntegral n
|
||||||
redirectKeepGetParams UsersR
|
redirectKeepGetParams UsersR
|
||||||
(UserHijack, Set.lookupMin -> Just uid) ->
|
(UserHijack, Set.lookupMin -> Just uid) ->
|
||||||
hijackUser uid >>= sendResponse
|
hijackUser uid >>= sendResponse
|
||||||
@ -404,16 +405,23 @@ postUsersR = do
|
|||||||
runDBJobs . runConduit $ selectSource [] [] .| C.mapM_ (queueDBJob . JobSynchroniseLdapUser . entityKey)
|
runDBJobs . runConduit $ selectSource [] [] .| C.mapM_ (queueDBJob . JobSynchroniseLdapUser . entityKey)
|
||||||
addMessageI Success MsgSynchroniseLdapAllUsersQueued
|
addMessageI Success MsgSynchroniseLdapAllUsersQueued
|
||||||
redirect UsersR
|
redirect UsersR
|
||||||
AllUsersAvsSync -> do
|
AllUsersAvsSync -> do
|
||||||
nowaday <- liftIO getCurrentTime <&> utctDay
|
now <- liftIO getCurrentTime
|
||||||
n <- runDB $ Ex.insertSelectCount $ do
|
let nowaday = utctDay now
|
||||||
usr <- Ex.from $ Ex.table @User
|
n <- runDB $ E.insertSelectWithConflictCount UniqueAvsSyncUser
|
||||||
return (AvsSync
|
( do
|
||||||
Ex.<# (usr Ex.^. UserId)
|
usr <- Ex.from $ Ex.table @User
|
||||||
Ex.<&> E.now_
|
return (AvsSync
|
||||||
-- Ex.<&> Ex.just (E.day E.now_) -- don't use DB time here, since job handler compares with FRADrive clock
|
Ex.<# (usr Ex.^. UserId)
|
||||||
Ex.<&> E.justVal nowaday
|
Ex.<&> E.val now
|
||||||
)
|
-- Ex.<&> Ex.just (E.day E.now_) -- don't use DB time here, since job handler compares with FRADrive clock
|
||||||
|
Ex.<&> E.justVal nowaday
|
||||||
|
)
|
||||||
|
) (\current excluded ->
|
||||||
|
[ AvsSyncCreationTime E.=. E.least (current E.^. AvsSyncCreationTime) (excluded E.^. AvsSyncCreationTime)
|
||||||
|
, AvsSyncPause E.=. E.greatest (current E.^. AvsSyncPause) (excluded E.^. AvsSyncPause)
|
||||||
|
]
|
||||||
|
)
|
||||||
queueJob' JobSynchroniseAvsQueue
|
queueJob' JobSynchroniseAvsQueue
|
||||||
addMessageI Success $ MsgSynchroniseAvsAllUsersQueued n
|
addMessageI Success $ MsgSynchroniseAvsAllUsersQueued n
|
||||||
redirect UsersR
|
redirect UsersR
|
||||||
@ -659,7 +667,7 @@ postAdminUserR uuid = do
|
|||||||
}
|
}
|
||||||
userDataWidget <- runDB $ makeProfileData $ Entity uid user
|
userDataWidget <- runDB $ makeProfileData $ Entity uid user
|
||||||
siteLayout heading $ do
|
siteLayout heading $ do
|
||||||
let _deleteWidget = $(i18nWidgetFile "data-delete")
|
let _deleteWidget = $(i18nWidgetFile "data-delete") -- TODO: update deletion text for FRADrive
|
||||||
$(widgetFile "adminUser")
|
$(widgetFile "adminUser")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -61,7 +61,7 @@ import Handler.Utils.Memcached
|
|||||||
import Database.Esqueleto.Experimental ((:&)(..))
|
import Database.Esqueleto.Experimental ((:&)(..))
|
||||||
import qualified Database.Esqueleto.Experimental as E -- needs TypeApplications Lang-Pragma
|
import qualified Database.Esqueleto.Experimental as E -- needs TypeApplications Lang-Pragma
|
||||||
import qualified Database.Esqueleto.Utils as E
|
import qualified Database.Esqueleto.Utils as E
|
||||||
-- import qualified Database.Esqueleto.PostgreSQL as E
|
import qualified Database.Esqueleto.PostgreSQL as E
|
||||||
|
|
||||||
import Servant.Client.Core.ClientError (ClientError)
|
import Servant.Client.Core.ClientError (ClientError)
|
||||||
|
|
||||||
@ -329,19 +329,40 @@ updateAvsUserByADC (AvsDataContact apid newAvsPersonInfo newAvsFirmInfo) = runMa
|
|||||||
let usrId = userAvsUser usravs
|
let usrId = userAvsUser usravs
|
||||||
usr <- MaybeT $ get usrId
|
usr <- MaybeT $ get usrId
|
||||||
lift $ do -- maybeT no longer needed from here onwards
|
lift $ do -- maybeT no longer needed from here onwards
|
||||||
newAvsCardNo <- queryAvsFullCardNo apid -- Nothing os ok here, does not throw
|
|
||||||
now <- liftIO getCurrentTime
|
|
||||||
let oldAvsPersonInfo = userAvsLastPersonInfo usravs -- Nothing is ok here
|
let oldAvsPersonInfo = userAvsLastPersonInfo usravs -- Nothing is ok here
|
||||||
oldAvsFirmInfo = userAvsLastFirmInfo usravs -- Nothing is ok here
|
oldAvsFirmInfo = userAvsLastFirmInfo usravs -- Nothing is ok here
|
||||||
oldAvsCardNo = userAvsLastCardNo usravs & fmap Just
|
oldAvsCardNo = userAvsLastCardNo usravs & fmap Just
|
||||||
per_ups = mapMaybe (mkUpdate' usr newAvsPersonInfo oldAvsPersonInfo)
|
newAvsCardNo <- queryAvsFullCardNo apid -- Nothing os ok here, does not throw
|
||||||
|
now <- liftIO getCurrentTime
|
||||||
|
mbLdapExpire <- getsYesod $ views appSettings appSynchroniseLdapUsersExpire
|
||||||
|
ldap_ups <- if | Just ldapExpire <- mbLdapExpire
|
||||||
|
, maybe True (\lastLdapSync -> now > addUTCTime ldapExpire lastLdapSync) (userLastLdapSynchronisation usr)
|
||||||
|
, Just udep <- userCompanyDepartment usr
|
||||||
|
, let aipn = newAvsPersonInfo ^? _avsInfoInternalPersonalNo . _Just . _avsInternalPersonalNo
|
||||||
|
depKey = CompanyKey $ stripCI udep -- Shorthand is returned by LDAP
|
||||||
|
-> do -- LDAP sync invalid/expired
|
||||||
|
usrComp <- getBy $ UniqueUserCompany usrId depKey
|
||||||
|
whenIsJust usrComp $ \Entity{entityKey=ucKey, entityVal=UserCompany{userCompanySupervisor=isSuper, userCompanySupervisorReroute=rroute}} -> do
|
||||||
|
delete ucKey
|
||||||
|
when isSuper $ reportAdminProblem $ AdminProblemSupervisorLeftCompany usrId depKey rroute
|
||||||
|
return [ UserCompanyDepartment =. Nothing
|
||||||
|
, UserCompanyPersonalNumber =. aipn
|
||||||
|
, UserLdapPrimaryKey =. aipn
|
||||||
|
]
|
||||||
|
| otherwise
|
||||||
|
-> return $ mapMaybe (mkUpdate' usr newAvsPersonInfo oldAvsPersonInfo) $
|
||||||
|
bcons (isJust $ newAvsPersonInfo ^? _avsInfoInternalPersonalNo . _Just . _avsInternalPersonalNo)
|
||||||
|
( CheckUpdate UserLdapPrimaryKey $ _avsInfoInternalPersonalNo . _Just . _avsInternalPersonalNo . re _Just)
|
||||||
|
[ CheckUpdate UserCompanyPersonalNumber $ _avsInfoInternalPersonalNo . _Just . _avsInternalPersonalNo . re _Just
|
||||||
|
]
|
||||||
|
let per_ups = mapMaybe (mkUpdate' usr newAvsPersonInfo oldAvsPersonInfo)
|
||||||
[ CheckUpdate UserFirstName _avsInfoFirstName
|
[ CheckUpdate UserFirstName _avsInfoFirstName
|
||||||
, CheckUpdate UserSurname _avsInfoLastName
|
, CheckUpdate UserSurname _avsInfoLastName
|
||||||
, CheckUpdate UserDisplayName _avsInfoDisplayName
|
, CheckUpdate UserDisplayName _avsInfoDisplayName
|
||||||
, CheckUpdate UserBirthday _avsInfoDateOfBirth
|
, CheckUpdate UserBirthday _avsInfoDateOfBirth
|
||||||
, CheckUpdate UserMobile _avsInfoPersonMobilePhoneNo
|
, CheckUpdate UserMobile _avsInfoPersonMobilePhoneNo
|
||||||
, CheckUpdate UserMatrikelnummer $ _avsInfoPersonNo . re _Just -- Maybe im User, aber nicht im AvsInfo; also: `re _Just` work like `to Just`
|
, CheckUpdate UserMatrikelnummer $ _avsInfoPersonNo . re _Just -- Maybe im User, aber nicht im AvsInfo; also: `re _Just` work like `to Just`
|
||||||
, CheckUpdate UserCompanyPersonalNumber $ _avsInfoInternalPersonalNo . _Just . _avsInternalPersonalNo . re _Just -- Maybe im User und im AvsInfo
|
-- , CheckUpdate UserCompanyPersonalNumber $ _avsInfoInternalPersonalNo . _Just . _avsInternalPersonalNo . re _Just -- Maybe im User und im AvsInfo; needs special treatment, see ldap_ups above
|
||||||
]
|
]
|
||||||
apiEmail = _avsInfoPersonEMail . to (fromMaybe mempty) . from _CI
|
apiEmail = _avsInfoPersonEMail . to (fromMaybe mempty) . from _CI
|
||||||
afiEmail = _avsFirmPrimaryEmail . to (fromMaybe mempty) . from _CI
|
afiEmail = _avsFirmPrimaryEmail . to (fromMaybe mempty) . from _CI
|
||||||
@ -360,14 +381,15 @@ updateAvsUserByADC (AvsDataContact apid newAvsPersonInfo newAvsFirmInfo) = runMa
|
|||||||
CheckUpdate UserPostAddress _avsFirmPostAddress -- since company address should now be referenced with UserCompany instead
|
CheckUpdate UserPostAddress _avsFirmPostAddress -- since company address should now be referenced with UserCompany instead
|
||||||
pin_up = mkUpdate' usr newAvsCardNo oldAvsCardNo $ -- Maybe update PDF pin to latest card
|
pin_up = mkUpdate' usr newAvsCardNo oldAvsCardNo $ -- Maybe update PDF pin to latest card
|
||||||
CheckUpdate UserPinPassword $ to $ fmap avsFullCardNo2pin -- _Just . to avsFullCardNo2pin . re _Just
|
CheckUpdate UserPinPassword $ to $ fmap avsFullCardNo2pin -- _Just . to avsFullCardNo2pin . re _Just
|
||||||
usr_up1 = eml_up `mcons` (frm_up `mcons` (pin_up `mcons` per_ups))
|
usr_up1 = eml_up `mcons` (frm_up `mcons` (pin_up `mcons` (ldap_ups <> per_ups)))
|
||||||
avs_ups = ((UserAvsNoPerson =.) <$> readMay (avsInfoPersonNo newAvsPersonInfo)) `mcons`
|
avs_ups = ((UserAvsNoPerson =.) <$> readMay (avsInfoPersonNo newAvsPersonInfo)) `mcons`
|
||||||
[ UserAvsLastSynch =. now
|
[ UserAvsLastSynch =. now
|
||||||
, UserAvsLastSynchError =. Nothing
|
, UserAvsLastSynchError =. Nothing
|
||||||
, UserAvsLastPersonInfo =. Just newAvsPersonInfo
|
, UserAvsLastPersonInfo =. Just newAvsPersonInfo
|
||||||
, UserAvsLastFirmInfo =. Just newAvsFirmInfo
|
, UserAvsLastFirmInfo =. Just newAvsFirmInfo
|
||||||
, UserAvsLastCardNo =. newAvsCardNo
|
, UserAvsLastCardNo =. newAvsCardNo
|
||||||
]
|
]
|
||||||
|
|
||||||
-- update company association & supervision
|
-- update company association & supervision
|
||||||
Entity{entityKey=newCompanyId} <- upsertAvsCompany newAvsFirmInfo oldAvsFirmInfo
|
Entity{entityKey=newCompanyId} <- upsertAvsCompany newAvsFirmInfo oldAvsFirmInfo
|
||||||
oldCompanyEnt <- getAvsCompany `traverseJoin` oldAvsFirmInfo
|
oldCompanyEnt <- getAvsCompany `traverseJoin` oldAvsFirmInfo
|
||||||
@ -640,24 +662,28 @@ upsertAvsCompany newAvsFirmInfo mbOldAvsFirmInfo = do
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
queueAvsUpdateByUID :: (MonoFoldable mono, UserId ~ Element mono) => mono -> Maybe Day -> DB Int64
|
||||||
|
queueAvsUpdateByUID uids = queueAvsUpdateAux (E.table @User) (E.^. UserId) (\usr -> usr E.^. UserId `E.in_` E.vals uids)
|
||||||
|
|
||||||
queueAvsUpdateByUID :: (MonoFoldable mono, UserId ~ Element mono) => mono -> Maybe Day -> Handler ()
|
queueAvsUpdateByAID :: (MonoFoldable mono, AvsPersonId ~ Element mono) => mono -> Maybe Day -> DB Int64
|
||||||
queueAvsUpdateByUID uids pause = do
|
queueAvsUpdateByAID aids = queueAvsUpdateAux (E.table @UserAvs) (E.^. UserAvsUser) (\usrAvs -> usrAvs E.^. UserAvsPersonId `E.in_` E.vals aids)
|
||||||
now <- liftIO getCurrentTime
|
|
||||||
runDB $ putMany [AvsSync uid now pause | uid <- toList uids]
|
|
||||||
queueJob' JobSynchroniseAvsQueue
|
|
||||||
|
|
||||||
queueAvsUpdateByAID :: (MonoFoldable mono, AvsPersonId ~ Element mono) => mono -> Maybe Day -> Handler ()
|
-- queueAvsUpdateAux :: E.From (E.SqlExpr (Entity ent)) -> (E.SqlExpr (Entity ent) -> E.SqlExpr (E.Value UserId)) -> (E.SqlExpr (Entity ent) -> E.SqlExpr (E.Value Bool)) -> Maybe Day -> DB Int64
|
||||||
queueAvsUpdateByAID aids pause = do
|
queueAvsUpdateAux :: E.From t -> (t -> E.SqlExpr (E.Value UserId)) -> (t -> E.SqlExpr (E.Value Bool)) -> Maybe Day -> DB Int64
|
||||||
now <- liftIO getCurrentTime
|
queueAvsUpdateAux tbl prj fltr pause = do
|
||||||
runDB $ do
|
now <- liftIO getCurrentTime
|
||||||
uids <- E.select $ do
|
n <- E.insertSelectWithConflictCount UniqueAvsSyncUser
|
||||||
usrAvs <- E.from $ E.table @UserAvs
|
( do
|
||||||
E.where_ $ usrAvs E.^. UserAvsPersonId `E.in_` E.vals aids
|
usr <- E.from tbl
|
||||||
-- E.&&. (E.isNothing pause E.||. pause E.>. E.dayMaybe (usrAvs E.?. UserAvsLastSynch)) -- pause is checked later on in JobSynchroniseAvsQueue
|
E.where_ $ fltr usr
|
||||||
return $ usrAvs E.^. UserAvsUser
|
return (AvsSync E.<# prj usr E.<&> E.val now E.<&> E.val pause)
|
||||||
putMany [AvsSync uid now pause | E.Value uid <- uids]
|
) (\current excluded ->
|
||||||
queueJob' JobSynchroniseAvsQueue
|
[ AvsSyncCreationTime E.=. E.least (current E.^. AvsSyncCreationTime) (excluded E.^. AvsSyncCreationTime)
|
||||||
|
, AvsSyncPause E.=. E.greatest (current E.^. AvsSyncPause) (excluded E.^. AvsSyncPause)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
runDBJobs' $ queueDBJob JobSynchroniseAvsQueue
|
||||||
|
return n
|
||||||
|
|
||||||
|
|
||||||
-- | Find or upsert User by AvsCardId (with dot), Fraport PersonalNumber, Fraport Email-Address or by prefixed AvsId or prefixed AvsNo;
|
-- | Find or upsert User by AvsCardId (with dot), Fraport PersonalNumber, Fraport Email-Address or by prefixed AvsId or prefixed AvsNo;
|
||||||
|
|||||||
@ -78,20 +78,23 @@ addCompanySupervisors cid uid =
|
|||||||
|
|
||||||
-- | removes user supervisorship on switch. WARNING: problems are not yet written to DB via reportProblem yet
|
-- | removes user supervisorship on switch. WARNING: problems are not yet written to DB via reportProblem yet
|
||||||
switchAvsUserCompany :: Bool -> Bool -> UserId -> CompanyId -> DB ([Update User], [AdminProblem])
|
switchAvsUserCompany :: Bool -> Bool -> UserId -> CompanyId -> DB ([Update User], [AdminProblem])
|
||||||
switchAvsUserCompany usrPostAddrUpd keepOldCompanySupervs uid newCompanyId = do
|
switchAvsUserCompany usrPostEmailUpds keepOldCompanySupervs uid newCompanyId = do
|
||||||
usrRec <- get404 uid
|
usrRec <- get404 uid
|
||||||
newCompany <- get404 newCompanyId
|
newCompany <- get404 newCompanyId
|
||||||
mbUsrComp <- getUserPrimaryCompany uid
|
mbUsrComp <- getUserPrimaryCompany uid
|
||||||
mbOldComp <- (get . userCompanyCompany) `traverseJoin` mbUsrComp
|
mbOldComp <- (get . userCompanyCompany) `traverseJoin` mbUsrComp
|
||||||
mbUsrAvs <- if usrPostAddrUpd then getBy (UniqueUserAvsUser uid) else return Nothing
|
mbUsrAvs <- if usrPostEmailUpds then getBy (UniqueUserAvsUser uid) else return Nothing
|
||||||
let usrPostAddr :: Maybe StoredMarkup = userPostAddress usrRec
|
let usrPostAddr :: Maybe StoredMarkup = userPostAddress usrRec
|
||||||
avsPostAddr :: Maybe StoredMarkup = mbUsrAvs ^? _Just . _entityVal . _userAvsLastFirmInfo . _Just . _avsFirmPostAddress . _Just
|
avsPostAddr :: Maybe StoredMarkup = mbUsrAvs ^? _Just . _entityVal . _userAvsLastFirmInfo . _Just . _avsFirmPostAddress . _Just
|
||||||
usrPostUp = toMaybe (usrPostAddrUpd && fromMaybe False (liftA2 isSimilarMarkup usrPostAddr avsPostAddr))
|
usrPostUp = toMaybe (usrPostEmailUpds && fromMaybe False (liftA2 isSimilarMarkup usrPostAddr avsPostAddr))
|
||||||
(UserPostAddress =. Nothing) -- use company address indirectyl instead
|
(UserPostAddress =. Nothing) -- use company address indirectly instead
|
||||||
usrPrefPost = userPrefersPostal usrRec
|
usrPrefPost = userPrefersPostal usrRec
|
||||||
usrPrefPostUp = toMaybe (Just usrPrefPost == (mbOldComp ^? _Just . _companyPrefersPostal))
|
usrPrefPostUp = toMaybe (Just usrPrefPost == (mbOldComp ^? _Just . _companyPrefersPostal))
|
||||||
(UserPrefersPostal =. companyPrefersPostal newCompany)
|
(UserPrefersPostal =. companyPrefersPostal newCompany)
|
||||||
usrUpdate = catMaybes [usrPostUp, usrPrefPostUp]
|
usrEmail :: UserEmail = userDisplayEmail usrRec
|
||||||
|
avsEmail :: Maybe UserEmail = mbUsrAvs ^? _Just . _entityVal . _userAvsLastFirmInfo . _Just . _avsFirmPrimaryEmail . _Just . from _CI
|
||||||
|
usrEmailUp = toMaybe (usrPostEmailUpds && avsEmail == Just usrEmail) (UserDisplayEmail =. "")
|
||||||
|
usrUpdate = catMaybes [usrPostUp, usrPrefPostUp, usrEmailUp]
|
||||||
-- [UserPostAddress =. Nothing, UserPrefersPostal =. companyPrefersPostal newCompany] -- unconditional
|
-- [UserPostAddress =. Nothing, UserPrefersPostal =. companyPrefersPostal newCompany] -- unconditional
|
||||||
-- update uid usrUpdate
|
-- update uid usrUpdate
|
||||||
-- repsertSuperiorSupervisor is not called here, since the Superior is indepentent of the actual company association
|
-- repsertSuperiorSupervisor is not called here, since the Superior is indepentent of the actual company association
|
||||||
|
|||||||
@ -594,6 +594,12 @@ degreeField = selectField $ optionsPersistKey [] [Asc StudyDegreeName, Asc Study
|
|||||||
degreeFieldEnt :: Field Handler (Entity StudyDegree)
|
degreeFieldEnt :: Field Handler (Entity StudyDegree)
|
||||||
degreeFieldEnt = selectField $ optionsPersist [] [Asc StudyDegreeName, Asc StudyDegreeShorthand, Asc StudyDegreeKey] id
|
degreeFieldEnt = selectField $ optionsPersist [] [Asc StudyDegreeName, Asc StudyDegreeShorthand, Asc StudyDegreeKey] id
|
||||||
|
|
||||||
|
qualificationField :: Field Handler QualificationId
|
||||||
|
qualificationField = selectField $ optionsPersistKey [] [Asc QualificationName] qualificationName
|
||||||
|
|
||||||
|
qualificationFieldShort :: Field Handler QualificationShorthand
|
||||||
|
qualificationFieldShort = selectField $ (qualificationShorthand . entityVal) <<$>> optionsPersist [] [Asc QualificationName] qualificationName
|
||||||
|
|
||||||
qualificationFieldEnt :: Field Handler (Entity Qualification)
|
qualificationFieldEnt :: Field Handler (Entity Qualification)
|
||||||
qualificationFieldEnt = selectField $ optionsPersist [] [Asc QualificationName] qualificationName
|
qualificationFieldEnt = selectField $ optionsPersist [] [Asc QualificationName] qualificationName
|
||||||
|
|
||||||
|
|||||||
@ -470,6 +470,8 @@ fltrUserMatriclenrUI mPrev =
|
|||||||
|
|
||||||
----------------
|
----------------
|
||||||
-- User E-Mail
|
-- User E-Mail
|
||||||
|
----------------
|
||||||
|
|
||||||
colUserEmail :: (IsDBTable m c, HasUser a) => Colonnade Sortable a (DBCell m c)
|
colUserEmail :: (IsDBTable m c, HasUser a) => Colonnade Sortable a (DBCell m c)
|
||||||
colUserEmail = sortable (Just "user-email") (i18nCell MsgTableEmail) cellHasEMail
|
colUserEmail = sortable (Just "user-email") (i18nCell MsgTableEmail) cellHasEMail
|
||||||
|
|
||||||
@ -719,6 +721,19 @@ fltrRelevantStudyFeaturesSemesterUI :: DBFilterUI
|
|||||||
fltrRelevantStudyFeaturesSemesterUI = fltrFeaturesSemesterUI
|
fltrRelevantStudyFeaturesSemesterUI = fltrFeaturesSemesterUI
|
||||||
|
|
||||||
|
|
||||||
|
--------------------
|
||||||
|
-- Qualifications
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
fltrQualification :: OpticFilterColumn t QualificationShorthand
|
||||||
|
fltrQualification queryQual = singletonMap "qualification" . FilterColumn $ mkExactFilter (view queryQual)
|
||||||
|
|
||||||
|
fltrQualificationUI :: DBFilterUI
|
||||||
|
fltrQualificationUI = fltrQualificationHdrUI MsgTableQualification
|
||||||
|
|
||||||
|
fltrQualificationHdrUI :: (RenderMessage UniWorX msg) => msg -> DBFilterUI
|
||||||
|
fltrQualificationHdrUI msg mPrev = prismAForm (singletonFilter "qualification" . maybePrism _PathPiece) mPrev $ aopt (hoistField lift qualificationFieldShort) (fslI msg)
|
||||||
|
|
||||||
|
|
||||||
---------------
|
---------------
|
||||||
-- Companies --
|
-- Companies --
|
||||||
|
|||||||
@ -152,8 +152,8 @@ getUserEmailAutomatic Entity{entityKey=uid, entityVal=User{userDisplayEmail, use
|
|||||||
-- address is prefixed with userDisplayName
|
-- address is prefixed with userDisplayName
|
||||||
getPostalAddress :: Entity User -> DB (Maybe [Text])
|
getPostalAddress :: Entity User -> DB (Maybe [Text])
|
||||||
getPostalAddress Entity{entityKey=uid, entityVal=User{..}}
|
getPostalAddress Entity{entityKey=uid, entityVal=User{..}}
|
||||||
| Just pa <- userPostAddress
|
| (Just upo) <- userPostAddress, validPostAddress userPostAddress
|
||||||
= prefixMarkupName pa
|
= prefixMarkupName upo
|
||||||
| otherwise
|
| otherwise
|
||||||
= do
|
= do
|
||||||
getUserPrimaryCompanyAddress uid companyPostAddress >>= \case
|
getUserPrimaryCompanyAddress uid companyPostAddress >>= \case
|
||||||
@ -170,11 +170,11 @@ getPostalAddress Entity{entityKey=uid, entityVal=User{..}}
|
|||||||
-- primed variant returns storedMarkup without prefixed userDisplayName and whether updates are automatic
|
-- primed variant returns storedMarkup without prefixed userDisplayName and whether updates are automatic
|
||||||
getPostalAddress' :: Entity User -> DB (Maybe StoredMarkup, Bool)
|
getPostalAddress' :: Entity User -> DB (Maybe StoredMarkup, Bool)
|
||||||
getPostalAddress' Entity{entityKey=uid, entityVal=User{..}}
|
getPostalAddress' Entity{entityKey=uid, entityVal=User{..}}
|
||||||
| res@(Just upo) <- userPostAddress
|
| validPostAddress userPostAddress
|
||||||
= do
|
= do
|
||||||
muavs <- getBy $ UniqueUserAvsUser uid
|
muavs <- getBy $ UniqueUserAvsUser uid
|
||||||
let auto = upo == muavs ^. _Just . _userAvsLastFirmInfo . _Just . _avsFirmPostAddress . _Just -- Recall: _Just on Nothing yields mempty here
|
let auto = userPostAddress == muavs ^? _Just . _userAvsLastFirmInfo . _Just . _avsFirmPostAddress . _Just -- Recall: using _Just with ^. on Nothing yields mempty
|
||||||
return (res, auto)
|
return (userPostAddress, auto)
|
||||||
| otherwise
|
| otherwise
|
||||||
= do
|
= do
|
||||||
getUserPrimaryCompanyAddress uid companyPostAddress >>= \case
|
getUserPrimaryCompanyAddress uid companyPostAddress >>= \case
|
||||||
|
|||||||
@ -38,7 +38,8 @@ visibleUTCTime dtf t = do
|
|||||||
-- | Simple link to a known route
|
-- | Simple link to a known route
|
||||||
simpleLink :: HasRoute UniWorX url => Widget -> url -> Widget
|
simpleLink :: HasRoute UniWorX url => Widget -> url -> Widget
|
||||||
simpleLink lbl url = do
|
simpleLink lbl url = do
|
||||||
isAuth <- hasReadAccessTo $ urlRoute url
|
let route = urlRoute url
|
||||||
|
isAuth <- liftHandler . $cachedHereBinary route $ hasReadAccessTo route
|
||||||
if | isAuth -> do
|
if | isAuth -> do
|
||||||
tUrl <- toTextUrl url
|
tUrl <- toTextUrl url
|
||||||
[whamlet|
|
[whamlet|
|
||||||
@ -127,7 +128,7 @@ editedByW fmt tm usr = do
|
|||||||
-- | like `modal`, but only conditionally displays the modal link only after checking access rights. WARNING: this might be too slow for large dbTable. Use `modalAccessCheckOnClick` instead
|
-- | like `modal`, but only conditionally displays the modal link only after checking access rights. WARNING: this might be too slow for large dbTable. Use `modalAccessCheckOnClick` instead
|
||||||
modalAccess :: Widget -> Widget -> Bool -> Route UniWorX -> Widget
|
modalAccess :: Widget -> Widget -> Bool -> Route UniWorX -> Widget
|
||||||
modalAccess wdgtNo wdgtYes writeAccess route = do
|
modalAccess wdgtNo wdgtYes writeAccess route = do
|
||||||
authOk <- liftHandler $ bool hasReadAccessTo hasWriteAccessTo writeAccess route
|
authOk <- liftHandler . $cachedHereBinary (route, writeAccess) $ bool hasReadAccessTo hasWriteAccessTo writeAccess route
|
||||||
if authOk
|
if authOk
|
||||||
then modal wdgtYes (Left $ SomeRoute route)
|
then modal wdgtYes (Left $ SomeRoute route)
|
||||||
else wdgtNo
|
else wdgtNo
|
||||||
|
|||||||
@ -658,7 +658,7 @@ _avsFirmPrimaryEmail = to mkEmail
|
|||||||
mkEmail afi =
|
mkEmail afi =
|
||||||
let candidates = catMaybes
|
let candidates = catMaybes
|
||||||
[ afi ^. _avsFirmCommunication . _Just . _avsCommunicationEMail
|
[ afi ^. _avsFirmCommunication . _Just . _avsCommunicationEMail
|
||||||
, afi ^. _avsFirmEMailSuperior
|
, afi ^. _avsFirmEMailSuperior -- only set for Fraport departments, hence this is a non-personal department wide email suitable as company email
|
||||||
, afi ^. _avsFirmEMail
|
, afi ^. _avsFirmEMail
|
||||||
]
|
]
|
||||||
in pickValidEmail candidates -- should we return an invalid email rather than none?
|
in pickValidEmail candidates -- should we return an invalid email rather than none?
|
||||||
|
|||||||
@ -164,6 +164,7 @@ data AppSettings = AppSettings
|
|||||||
|
|
||||||
, appSynchroniseLdapUsersWithin :: Maybe NominalDiffTime
|
, appSynchroniseLdapUsersWithin :: Maybe NominalDiffTime
|
||||||
, appSynchroniseLdapUsersInterval :: NominalDiffTime
|
, appSynchroniseLdapUsersInterval :: NominalDiffTime
|
||||||
|
, appSynchroniseLdapUsersExpire :: Maybe NominalDiffTime
|
||||||
|
|
||||||
, appSynchroniseAvsUsersWithin :: Maybe NominalDiffTime
|
, appSynchroniseAvsUsersWithin :: Maybe NominalDiffTime
|
||||||
, appSynchroniseAvsUsersInterval :: NominalDiffTime
|
, appSynchroniseAvsUsersInterval :: NominalDiffTime
|
||||||
@ -703,6 +704,7 @@ instance FromJSON AppSettings where
|
|||||||
|
|
||||||
appSynchroniseLdapUsersWithin <- o .:? "synchronise-ldap-users-within"
|
appSynchroniseLdapUsersWithin <- o .:? "synchronise-ldap-users-within"
|
||||||
appSynchroniseLdapUsersInterval <- o .: "synchronise-ldap-users-interval"
|
appSynchroniseLdapUsersInterval <- o .: "synchronise-ldap-users-interval"
|
||||||
|
appSynchroniseLdapUsersExpire <- o .:? "synrchonise-ldap-users-expire" -- time after last synch to delete LDAP sepcific data
|
||||||
|
|
||||||
appSynchroniseAvsUsersWithin <- o .:? "synchronise-avs-users-within"
|
appSynchroniseAvsUsersWithin <- o .:? "synchronise-avs-users-within"
|
||||||
appSynchroniseAvsUsersInterval <- o .: "synchronise-avs-users-interval"
|
appSynchroniseAvsUsersInterval <- o .: "synchronise-avs-users-interval"
|
||||||
|
|||||||
@ -20,7 +20,8 @@ $# SPDX-License-Identifier: AGPL-3.0-or-later
|
|||||||
_{MsgAdminUserAssimilate}
|
_{MsgAdminUserAssimilate}
|
||||||
^{assimilateForm}
|
^{assimilateForm}
|
||||||
$# <section>
|
$# <section>
|
||||||
$# <p>
|
$# <h3 .show-hide__toggle uw-show-hide data-show-hide-collapsed>
|
||||||
$# _{MsgUserAccountDeleteWarning}
|
$# _{MsgUserAccountDeleteWarning}
|
||||||
$# <p>
|
$# <div>
|
||||||
$# ^{modal "Benutzer löschen" (Right deleteWidget)}
|
$# <p>
|
||||||
|
$# ^{modal _{MsgBreadcrumbUserDelete} (Right deleteWidget)}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user