users cannot delete themselves anymore
This commit is contained in:
parent
2ddb637b6e
commit
21ba1f2afa
@ -1,4 +1,5 @@
|
||||
Es s
|
||||
Übersicht über PageActions und Workflow im Vergleich zum alten UniWorX:
|
||||
-----
|
||||
|
||||
Course Actions im alten UniWorX:
|
||||
- Studenten
|
||||
@ -8,6 +9,8 @@ Course Actions im alten UniWorX:
|
||||
- E-Mails
|
||||
- Online-Evaluation
|
||||
|
||||
-----
|
||||
|
||||
CourseActions in Uni2Work:
|
||||
-1 Übungsblätter (öfter)
|
||||
[ Auch aus SheetList übernommen un hier ebenfalls angzeigt:
|
||||
|
||||
@ -6,6 +6,7 @@ BtnDeregister: Abmelden
|
||||
BtnHijack: Sitzung übernehmen
|
||||
|
||||
Aborted: Abgebrochen
|
||||
Remarks: Hinweise
|
||||
Registered: Angemeldet
|
||||
RegisteredHeader: Anmeldung
|
||||
RegisteredSince date@Text: Angemeldet seit #{date}
|
||||
|
||||
3
routes
3
routes
@ -37,6 +37,7 @@
|
||||
/ HomeR GET !free
|
||||
/users UsersR GET -- no tags, i.e. admins only
|
||||
/users/#CryptoUUIDUser AdminUserR GET POST !development
|
||||
/users/#CryptoUUIDUser/delete AdminUserDeleteR POST !development
|
||||
/users/#CryptoUUIDUser/hijack AdminHijackUserR POST !adminANDno-escalation
|
||||
/admin AdminR GET
|
||||
/admin/features AdminFeaturesR GET POST
|
||||
@ -52,7 +53,7 @@
|
||||
/help HelpR GET POST !free
|
||||
|
||||
/user ProfileR GET POST !free
|
||||
/user/profile ProfileDataR GET POST !free
|
||||
/user/profile ProfileDataR GET !free
|
||||
/user/authpreds AuthPredsR GET POST !free
|
||||
|
||||
/term TermShowR GET !free
|
||||
|
||||
@ -833,6 +833,7 @@ getCUserR _tid _ssh _csh uCId = do
|
||||
-- - User is a lecturer for course
|
||||
uid <- decrypt uCId
|
||||
User{..} <- runDB $ get404 uid
|
||||
|
||||
-- USE src/utils/Form.formResult
|
||||
defaultLayout -- TODO
|
||||
[whamlet|
|
||||
@ -844,5 +845,6 @@ getCHiWisR = error "CHiWisR: Not implemented"
|
||||
|
||||
getCNotesR, postCNotesR :: TermId -> SchoolId -> CourseShorthand -> Handler Html
|
||||
-- NOTE: The route getNotesR is abused for correctorORlecturer access rights!
|
||||
getCNotesR = error "CNotesR: Not implemented"
|
||||
-- PROBLEM: Correctors usually don't know Participants by name (anonymous), maybe notes are not shared?
|
||||
getCNotesR = error "CNotesR: Not implemented"
|
||||
postCNotesR = error "CNotesR: Not implemented"
|
||||
|
||||
@ -121,134 +121,47 @@ postProfileR = do
|
||||
setTitle . toHtml $ "Profil " <> userIdent
|
||||
$(widgetFile "formPageI18n")
|
||||
|
||||
postProfileDataR :: Handler Html
|
||||
postProfileDataR = do
|
||||
((btnResult,_), _) <- runFormPost buttonForm
|
||||
case btnResult of
|
||||
(FormSuccess BtnDelete) -> do
|
||||
(uid, User{..}) <- requireAuthPair
|
||||
clearCreds False -- Logout-User
|
||||
((deletedSubmissions,groupSubmissions),deletedSubmissionGroups) <- runDB $ deleteUser uid
|
||||
-- addMessageIHamlet
|
||||
$(addMessageFile Success "templates/deletedUser.hamlet") -- USE THIS ONE
|
||||
-- addMessageI Success $ MsgDeleteUser deletedSubmissions
|
||||
-- when (groupSubmissions > 0) $ addMessageI Info $ MsgDeleteUserGroupSubmissions groupSubmissions
|
||||
defaultLayout
|
||||
$(widgetFile "deletedUser")
|
||||
|
||||
-- (FormSuccess BtnAbort ) -> do
|
||||
-- addMessageI Info MsgAborted
|
||||
-- redirect ProfileDataR
|
||||
_other -> getProfileDataR
|
||||
|
||||
|
||||
|
||||
deleteUser :: UserId -> DB ((Int,Int),Int64) -- TODO: Restrict deletions for lecturers, tutors and students in course that won't allow deregistration
|
||||
deleteUser duid = do
|
||||
-- E.deleteCount for submissions is not cascading, hence we first select and then delete manually
|
||||
-- We delete all files tied to submissions where the user is the lone submissionUser
|
||||
|
||||
-- Do not deleteCascade submissions where duid is the corrector:
|
||||
updateWhere [SubmissionRatingBy ==. Just duid] [SubmissionRatingBy =. Nothing]
|
||||
|
||||
groupSubmissions <- selectSubmissionsWhere (\numBuddies -> numBuddies E.>. E.val (0::Int64))
|
||||
singleSubmissions <- selectSubmissionsWhere (\numBuddies -> numBuddies E.==. E.val (0::Int64))
|
||||
deleteCascade duid
|
||||
forM_ singleSubmissions $ \(E.Value submissionId) -> do
|
||||
deleteFileIds <- map E.unValue <$> getSubmissionFiles submissionId
|
||||
deleteCascade submissionId
|
||||
deleteCascadeWhere [FileId <-. deleteFileIds] -- TODO: throws exception for de-duplicated files
|
||||
|
||||
deletedSubmissionGroups <- deleteSingleSubmissionGroups
|
||||
return ((length singleSubmissions, length groupSubmissions),deletedSubmissionGroups)
|
||||
where
|
||||
selectSubmissionsWhere :: (E.SqlExpr (E.Value Int64) -> E.SqlExpr (E.Value Bool)) -> DB [E.Value (Key Submission)]
|
||||
selectSubmissionsWhere whereBuddies = E.select $ E.from $ \(submission `E.InnerJoin` suser) -> do
|
||||
E.on $ submission E.^. SubmissionId E.==. suser E.^. SubmissionUserSubmission
|
||||
let numBuddies = E.sub_select $ E.from $ \subUsers -> do
|
||||
E.where_ $ subUsers E.^. SubmissionUserSubmission E.==. submission E.^. SubmissionId
|
||||
E.&&. subUsers E.^. SubmissionUserUser E.!=. E.val duid
|
||||
return E.countRows
|
||||
E.where_ $ suser E.^. SubmissionUserUser E.==. E.val duid
|
||||
E.&&. whereBuddies numBuddies
|
||||
return $ submission E.^. SubmissionId
|
||||
|
||||
getSubmissionFiles :: SubmissionId -> DB [E.Value (Key File)]
|
||||
getSubmissionFiles subId = E.select $ E.from $ \file -> do
|
||||
E.where_ $ E.exists $ E.from $ \submissionFile ->
|
||||
E.where_ $ submissionFile E.^. SubmissionFileSubmission E.==. E.val subId
|
||||
E.&&. submissionFile E.^. SubmissionFileFile E.==. file E.^. FileId
|
||||
return $ file E.^. FileId
|
||||
|
||||
deleteSingleSubmissionGroups = E.deleteCount $ E.from $ \submissionGroup -> do
|
||||
E.where_ $ E.exists $ E.from $ \subGroupUser ->
|
||||
E.where_ $ subGroupUser E.^. SubmissionGroupUserSubmissionGroup E.==. submissionGroup E.^. SubmissionGroupId
|
||||
E.&&. subGroupUser E.^. SubmissionGroupUserUser E.==. E.val duid
|
||||
E.where_ $ E.notExists $ E.from $ \subGroupUser ->
|
||||
E.where_ $ subGroupUser E.^. SubmissionGroupUserSubmissionGroup E.==. submissionGroup E.^. SubmissionGroupId
|
||||
E.&&. subGroupUser E.^. SubmissionGroupUserUser E.!=. E.val duid
|
||||
|
||||
|
||||
|
||||
getProfileDataR :: Handler Html
|
||||
getProfileDataR = do
|
||||
(uid, User{..}) <- requireAuthPair
|
||||
userEnt <- requireAuth
|
||||
dataWidget <- runDB $ makeProfileData userEnt
|
||||
defaultLayout $ do
|
||||
dataWidget
|
||||
$(widgetFile "dsgvDisclaimer")
|
||||
|
||||
makeProfileData :: (Entity User) -> DB Widget
|
||||
makeProfileData (Entity uid User{..}) = do
|
||||
-- MsgRenderer mr <- getMsgRenderer
|
||||
(admin_rights,lecturer_rights,lecture_corrector,studies) <- runDB $ (,,,) <$>
|
||||
E.select
|
||||
( E.from $ \(adright `E.InnerJoin` school) -> do
|
||||
E.where_ $ adright E.^. UserAdminUser E.==. E.val uid
|
||||
E.on $ adright E.^. UserAdminSchool E.==. school E.^. SchoolId
|
||||
return (school E.^. SchoolShorthand)
|
||||
)
|
||||
<*>
|
||||
E.select
|
||||
( E.from $ \(lecright `E.InnerJoin` school) -> do
|
||||
E.where_ $ lecright E.^. UserLecturerUser E.==. E.val uid
|
||||
E.on $ lecright E.^. UserLecturerSchool E.==. school E.^. SchoolId
|
||||
return (school E.^. SchoolShorthand)
|
||||
)
|
||||
<*>
|
||||
E.select
|
||||
( E.distinct $ E.from $ \(sheet `E.InnerJoin` corrector `E.InnerJoin` course) -> do
|
||||
E.on $ sheet E.^. SheetCourse E.==. course E.^. CourseId
|
||||
E.on $ sheet E.^. SheetId E.==. corrector E.^. SheetCorrectorSheet
|
||||
E.where_ $ corrector E.^. SheetCorrectorUser E.==. E.val uid
|
||||
return (course E.^. CourseTerm, course E.^. CourseSchool, course E.^. CourseShorthand)
|
||||
)
|
||||
<*>
|
||||
E.select
|
||||
( E.from $ \(studydegree `E.InnerJoin` studyfeat `E.InnerJoin` studyterms) -> do
|
||||
E.where_ $ studyfeat E.^. StudyFeaturesUser E.==. E.val uid
|
||||
E.on $ studyfeat E.^. StudyFeaturesField E.==. studyterms E.^. StudyTermsId
|
||||
E.on $ studyfeat E.^. StudyFeaturesDegree E.==. studydegree E.^. StudyDegreeId
|
||||
return (studyfeat, studydegree, studyterms)
|
||||
)
|
||||
( (hasRows, ownedCoursesTable)
|
||||
, enrolledCoursesTable
|
||||
, submissionTable
|
||||
, submissionGroupTable
|
||||
, correctionsTable
|
||||
) <- runDB $ (,,,,)
|
||||
<$> mkOwnedCoursesTable uid -- Tabelle mit eigenen Kursen
|
||||
<*> mkEnrolledCoursesTable uid -- Tabelle mit allen Teilnehmer: Kurs (link), Datum
|
||||
<*> mkSubmissionTable uid -- Tabelle mit allen Abgaben und Abgabe-Gruppen
|
||||
<*> mkSubmissionGroupTable uid -- Tabelle mit allen Abgabegruppen
|
||||
<*> mkCorrectionsTable uid -- Tabelle mit allen Korrektor-Aufgaben
|
||||
|
||||
|
||||
admin_rights <- E.select $ E.from $ \(adright `E.InnerJoin` school) -> do
|
||||
E.where_ $ adright E.^. UserAdminUser E.==. E.val uid
|
||||
E.on $ adright E.^. UserAdminSchool E.==. school E.^. SchoolId
|
||||
return (school E.^. SchoolShorthand)
|
||||
lecturer_rights <- E.select $ E.from $ \(lecright `E.InnerJoin` school) -> do
|
||||
E.where_ $ lecright E.^. UserLecturerUser E.==. E.val uid
|
||||
E.on $ lecright E.^. UserLecturerSchool E.==. school E.^. SchoolId
|
||||
return (school E.^. SchoolShorthand)
|
||||
lecture_corrector <- E.select $ E.distinct $ E.from $ \(sheet `E.InnerJoin` corrector `E.InnerJoin` course) -> do
|
||||
E.on $ sheet E.^. SheetCourse E.==. course E.^. CourseId
|
||||
E.on $ sheet E.^. SheetId E.==. corrector E.^. SheetCorrectorSheet
|
||||
E.where_ $ corrector E.^. SheetCorrectorUser E.==. E.val uid
|
||||
return (course E.^. CourseTerm, course E.^. CourseSchool, course E.^. CourseShorthand)
|
||||
studies <- E.select $ E.from $ \(studydegree `E.InnerJoin` studyfeat `E.InnerJoin` studyterms) -> do
|
||||
E.where_ $ studyfeat E.^. StudyFeaturesUser E.==. E.val uid
|
||||
E.on $ studyfeat E.^. StudyFeaturesField E.==. studyterms E.^. StudyTermsId
|
||||
E.on $ studyfeat E.^. StudyFeaturesDegree E.==. studydegree E.^. StudyDegreeId
|
||||
return (studyfeat, studydegree, studyterms)
|
||||
--Tables
|
||||
(hasRows, ownedCoursesTable) <- mkOwnedCoursesTable uid -- Tabelle mit eigenen Kursen
|
||||
enrolledCoursesTable <- mkEnrolledCoursesTable uid -- Tabelle mit allen Teilnehmer: Kurs (link), Datum
|
||||
submissionTable <- mkSubmissionTable uid -- Tabelle mit allen Abgaben und Abgabe-Gruppen
|
||||
submissionGroupTable <- mkSubmissionGroupTable uid -- Tabelle mit allen Abgabegruppen
|
||||
correctionsTable <- mkCorrectionsTable uid -- Tabelle mit allen Korrektor-Aufgaben
|
||||
let examTable = [whamlet|Klausuren werden momentan leider noch nicht unterstützt.|]
|
||||
let ownTutorialTable = [whamlet|Übungsgruppen werden momentan leider noch nicht unterstützt.|]
|
||||
let tutorialTable = [whamlet|Übungsgruppen werden momentan leider noch nicht unterstützt.|]
|
||||
|
||||
lastLogin <- traverse (formatTime SelFormatDateTime) userLastAuthentication
|
||||
|
||||
-- Delete Button
|
||||
(btnWdgt, btnEnctype) <- generateFormPost (buttonForm :: Form ButtonDelete)
|
||||
defaultLayout $ do
|
||||
let delWdgt = $(widgetFile "widgets/data-delete/data-delete")
|
||||
$(widgetFile "profileData")
|
||||
$(widgetFile "dsgvDisclaimer")
|
||||
return $(widgetFile "profileData")
|
||||
|
||||
|
||||
|
||||
|
||||
@ -16,6 +16,8 @@ import qualified Data.Map as Map
|
||||
import qualified Database.Esqueleto as E
|
||||
import qualified Database.Esqueleto.Utils as E
|
||||
|
||||
import Handler.Profile (makeProfileData)
|
||||
|
||||
|
||||
hijackUserForm :: CryptoUUIDUser -> Form ()
|
||||
hijackUserForm cID csrf = do
|
||||
@ -157,7 +159,7 @@ postAdminUserR uuid = do
|
||||
uid <- decrypt uuid
|
||||
let fromSchoolList = Set.fromList . map (userAdminSchool . entityVal)
|
||||
let unValueRights (school, E.Value isAdmin, E.Value isLecturer) = (school,isAdmin,isLecturer)
|
||||
(User{..}, fromSchoolList -> adminSchools, fmap unValueRights -> userRights) <- runDB $ (,,)
|
||||
(user@User{..}, fromSchoolList -> adminSchools, fmap unValueRights -> userRights) <- runDB $ (,,)
|
||||
<$> get404 uid
|
||||
<*> selectList [UserAdminUser ==. adminId] []
|
||||
<*> E.select ( E.from $ \school -> do
|
||||
@ -172,7 +174,7 @@ postAdminUserR uuid = do
|
||||
)
|
||||
-- above data is needed for both form generation and result evaluation
|
||||
let userRightsForm :: Form [(SchoolId, Bool, Bool)]
|
||||
userRightsForm csrf = do
|
||||
userRightsForm = identifyForm FIDuserRights $ \csrf -> do
|
||||
boxRights <- forM userRights $ \(school@(Entity sid _), isAdmin, isLecturer) ->
|
||||
if Set.member sid adminSchools
|
||||
then do
|
||||
@ -205,5 +207,79 @@ postAdminUserR uuid = do
|
||||
formResult result userRightsAction
|
||||
let heading =
|
||||
[whamlet|_{MsgAccessRightsFor} ^{nameWidget userDisplayName userSurname}|]
|
||||
siteLayout heading
|
||||
-- Delete Button needed in data-delete
|
||||
(btnWdgt, btnEnctype) <- generateFormPost (buttonForm :: Form ButtonDelete)
|
||||
userDataWidget <- runDB $ makeProfileData $ Entity uid user
|
||||
siteLayout heading $ do
|
||||
let deleteWidget = $(widgetFile "widgets/data-delete/data-delete")
|
||||
$(widgetFile "adminUser")
|
||||
|
||||
|
||||
postAdminUserDeleteR :: CryptoUUIDUser -> Handler Html
|
||||
postAdminUserDeleteR uuid = do
|
||||
uid <- decrypt uuid
|
||||
((btnResult,_), _) <- runFormPost (buttonForm :: Form ButtonDelete)
|
||||
case btnResult of
|
||||
(FormSuccess BtnDelete) -> do
|
||||
User{..} <- runDB $ get404 uid
|
||||
-- clearCreds False -- Logout-User
|
||||
((deletedSubmissions,groupSubmissions),deletedSubmissionGroups) <- runDB $ deleteUser uid
|
||||
-- addMessageIHamlet
|
||||
$(addMessageFile Success "templates/deletedUser.hamlet") -- USE THIS ONE
|
||||
-- addMessageI Success $ MsgDeleteUser deletedSubmissions
|
||||
-- when (groupSubmissions > 0) $ addMessageI Info $ MsgDeleteUserGroupSubmissions groupSubmissions
|
||||
defaultLayout
|
||||
$(widgetFile "deletedUser")
|
||||
|
||||
-- (FormSuccess BtnAbort ) -> do
|
||||
-- addMessageI Info MsgAborted
|
||||
-- redirect ProfileDataR
|
||||
_other -> getAdminUserR uuid
|
||||
|
||||
|
||||
|
||||
deleteUser :: UserId -> DB ((Int,Int),Int64) -- TODO: Restrict deletions for lecturers, tutors and students in course that won't allow deregistration
|
||||
deleteUser duid = do
|
||||
-- E.deleteCount for submissions is not cascading, hence we first select and then delete manually
|
||||
-- We delete all files tied to submissions where the user is the lone submissionUser
|
||||
|
||||
-- Do not deleteCascade submissions where duid is the corrector:
|
||||
updateWhere [SubmissionRatingBy ==. Just duid] [SubmissionRatingBy =. Nothing]
|
||||
|
||||
groupSubmissions <- selectSubmissionsWhere (\numBuddies -> numBuddies E.>. E.val (0::Int64))
|
||||
singleSubmissions <- selectSubmissionsWhere (\numBuddies -> numBuddies E.==. E.val (0::Int64))
|
||||
deleteCascade duid
|
||||
forM_ singleSubmissions $ \(E.Value submissionId) -> do
|
||||
deleteFileIds <- map E.unValue <$> getSubmissionFiles submissionId
|
||||
deleteCascade submissionId
|
||||
deleteCascadeWhere [FileId <-. deleteFileIds] -- TODO: throws exception for de-duplicated files
|
||||
|
||||
deletedSubmissionGroups <- deleteSingleSubmissionGroups
|
||||
return ((length singleSubmissions, length groupSubmissions),deletedSubmissionGroups)
|
||||
where
|
||||
selectSubmissionsWhere :: (E.SqlExpr (E.Value Int64) -> E.SqlExpr (E.Value Bool)) -> DB [E.Value (Key Submission)]
|
||||
selectSubmissionsWhere whereBuddies = E.select $ E.from $ \(submission `E.InnerJoin` suser) -> do
|
||||
E.on $ submission E.^. SubmissionId E.==. suser E.^. SubmissionUserSubmission
|
||||
let numBuddies = E.sub_select $ E.from $ \subUsers -> do
|
||||
E.where_ $ subUsers E.^. SubmissionUserSubmission E.==. submission E.^. SubmissionId
|
||||
E.&&. subUsers E.^. SubmissionUserUser E.!=. E.val duid
|
||||
return E.countRows
|
||||
E.where_ $ suser E.^. SubmissionUserUser E.==. E.val duid
|
||||
E.&&. whereBuddies numBuddies
|
||||
return $ submission E.^. SubmissionId
|
||||
|
||||
getSubmissionFiles :: SubmissionId -> DB [E.Value (Key File)]
|
||||
getSubmissionFiles subId = E.select $ E.from $ \file -> do
|
||||
E.where_ $ E.exists $ E.from $ \submissionFile ->
|
||||
E.where_ $ submissionFile E.^. SubmissionFileSubmission E.==. E.val subId
|
||||
E.&&. submissionFile E.^. SubmissionFileFile E.==. file E.^. FileId
|
||||
return $ file E.^. FileId
|
||||
|
||||
deleteSingleSubmissionGroups = E.deleteCount $ E.from $ \submissionGroup -> do
|
||||
E.where_ $ E.exists $ E.from $ \subGroupUser ->
|
||||
E.where_ $ subGroupUser E.^. SubmissionGroupUserSubmissionGroup E.==. submissionGroup E.^. SubmissionGroupId
|
||||
E.&&. subGroupUser E.^. SubmissionGroupUserUser E.==. E.val duid
|
||||
E.where_ $ E.notExists $ E.from $ \subGroupUser ->
|
||||
E.where_ $ subGroupUser E.^. SubmissionGroupUserSubmissionGroup E.==. submissionGroup E.^. SubmissionGroupId
|
||||
E.&&. subGroupUser E.^. SubmissionGroupUserUser E.!=. E.val duid
|
||||
|
||||
|
||||
@ -44,11 +44,16 @@ simpleLink :: Widget -> Route UniWorX -> Widget
|
||||
simpleLink lbl url = [whamlet|<a href=@{url}>^{lbl}|]
|
||||
|
||||
-- | toWidget-Version of @nameHtml@, for convenience
|
||||
nameWidget :: Text -> Text -> Widget
|
||||
nameWidget :: Text -- ^ userDisplayName
|
||||
-> Text -- ^ userSurname
|
||||
-> Widget
|
||||
nameWidget displayName surname = toWidget $ nameHtml displayName surname
|
||||
|
||||
-- | toWidget-Version of @nameEmailHtml@, for convenience
|
||||
nameEmailWidget :: CI Text -> Text -> Text -> Widget
|
||||
nameEmailWidget :: CI Text -- ^ userEmail
|
||||
-> Text -- ^ userDisplayName
|
||||
-> Text -- ^ userSurname
|
||||
-> Widget
|
||||
nameEmailWidget email displayName surname = toWidget $ nameEmailHtml email displayName surname
|
||||
|
||||
-- | Show user's displayName, highlighting the surname if possible.
|
||||
|
||||
@ -125,14 +125,16 @@ linkButton lbl cls url = do
|
||||
|
||||
-- buttonForm :: (Button UniWorX a, Finite a) => Markup -> MForm (HandlerT UniWorX IO) (FormResult a, Widget)
|
||||
buttonForm :: (Button UniWorX a, Finite a) => Form a
|
||||
buttonForm csrf = do
|
||||
(res, ($ []) -> fViews) <- aFormToForm . disambiguateButtons $ combinedButtonFieldF ""
|
||||
return (res, [whamlet|
|
||||
$newline never
|
||||
#{csrf}
|
||||
$forall bView <- fViews
|
||||
^{fvInput bView}
|
||||
|])
|
||||
buttonForm = identifyForm FIDbuttonForm buttonFormAux -- TODO: distinguish diffent buttons despite @disambiguateButtons@
|
||||
where
|
||||
buttonFormAux csrf = do
|
||||
(res, ($ []) -> fViews) <- aFormToForm . disambiguateButtons $ combinedButtonFieldF ""
|
||||
return (res, [whamlet|
|
||||
$newline never
|
||||
#{csrf}
|
||||
$forall bView <- fViews
|
||||
^{fvInput bView}
|
||||
|])
|
||||
|
||||
|
||||
------------
|
||||
|
||||
@ -4,7 +4,11 @@ import Data.Either (isLeft)
|
||||
|
||||
import Import.NoFoundation
|
||||
|
||||
modal :: WidgetT site IO () -> Either (SomeRoute site) (WidgetT site IO ()) -> WidgetT site IO ()
|
||||
|
||||
-- | Create a link to a modal
|
||||
modal :: WidgetT site IO () -- ^ Widget that represents the link
|
||||
-> Either (SomeRoute site) (WidgetT site IO ()) -- ^ Modal contant: either dynamic link or static widget
|
||||
-> WidgetT site IO () -- ^ result widget
|
||||
modal modalTrigger modalContent = do
|
||||
let modalDynamic = isLeft modalContent
|
||||
modalId <- newIdent
|
||||
|
||||
@ -217,6 +217,8 @@ data FormIdentifier
|
||||
| FIDDBTable
|
||||
| FIDDelete
|
||||
| FIDCourseRegister
|
||||
| FIDuserRights
|
||||
| FIDbuttonForm
|
||||
deriving (Eq, Ord, Read, Show)
|
||||
|
||||
instance PathPiece FormIdentifier where
|
||||
@ -238,7 +240,7 @@ identifyForm' resLens identVal form fragment = do
|
||||
|]
|
||||
|
||||
-- Check if we got its value back.
|
||||
hasIdent <- (== Just identVal) <$> lookupGlobalPostParamForm PostFormIdentifier
|
||||
hasIdent <- (== Just identVal) <$> lookupGlobalPostParamForm PostFormIdentifier
|
||||
|
||||
-- Run the form proper (with our hidden <input>). If the
|
||||
-- data is missing, then do not provide any params to the
|
||||
@ -250,7 +252,7 @@ identifyForm' resLens identVal form fragment = do
|
||||
|
||||
identifyForm :: (Monad m, PathPiece ident, Eq ident) => ident -> (Html -> MForm m (FormResult a, widget)) -> (Html -> MForm m (FormResult a, widget))
|
||||
identifyForm = identifyForm' id
|
||||
|
||||
|
||||
|
||||
{- Hinweise zur Erinnerung:
|
||||
- identForm primär, wenn es mehr als ein Formular pro Handler gibt
|
||||
|
||||
@ -1,6 +1,14 @@
|
||||
<p>
|
||||
$# Does not use link-email.hamlet, but should
|
||||
^{mailtoHtml userEmail}
|
||||
<form method=post action=@{AdminUserR uuid} enctype=#{formEnctype}>
|
||||
^{formWidget}
|
||||
^{submitButtonView}
|
||||
<section>
|
||||
$# Does not use link-email.hamlet, but should
|
||||
^{mailtoHtml userEmail}
|
||||
<form method=post action=@{AdminUserR uuid} enctype=#{formEnctype}>
|
||||
^{formWidget}
|
||||
^{submitButtonView}
|
||||
<section>
|
||||
^{userDataWidget}
|
||||
<h3>
|
||||
^{modal "Benutzer löschen" (Right deleteWidget)}
|
||||
Achtung, dieser Link löscht momentan noch den kompletten Benutzer
|
||||
unwiderruflich aus der Live-Datenbank mit
|
||||
<code>DELETE CASCADE uid
|
||||
\ Klausurdaten müssen jedoch langfristig gespeichert werden!
|
||||
@ -1,6 +1,10 @@
|
||||
<div .container>
|
||||
<h1>
|
||||
_{MsgUserAccountDeleted userDisplayName}
|
||||
<div .container>
|
||||
#{nameEmailHtml userEmail userDisplayName userSurname}
|
||||
<div .container>
|
||||
#{mailtoHtml userEmail}
|
||||
<div .container>
|
||||
#{display deletedSubmissions} Abgaben wurden unwiederruflich gelöscht.
|
||||
$if groupSubmissions > 0
|
||||
@ -12,5 +16,3 @@
|
||||
$if deletedSubmissionGroups > 0
|
||||
<div .container>
|
||||
#{display deletedSubmissionGroups} benannte Abgabengruppen wurden gelöscht, da diese dadurch leer wurden.
|
||||
<div .container>
|
||||
Good Bye!
|
||||
|
||||
@ -115,20 +115,28 @@
|
||||
<a href=@{CorrectionsR}>Auflistung aller tatsächlich zugewiesenen Korrekturen
|
||||
.
|
||||
|
||||
<h2>
|
||||
^{modal "Alle Benutzerbezogenen Daten löschen" (Right delWdgt)}
|
||||
<p>
|
||||
<h4>Hinweise:
|
||||
|
||||
<section>
|
||||
<h2>_{MsgRemarks}
|
||||
<ul>
|
||||
<li>
|
||||
Sichern Sie Ihre Daten! Während des Testbetriebs von Uni2work
|
||||
könnten Daten unabsichtlich unwidderuflich gelöscht werden.
|
||||
Sichern Sie bitte Ihre Daten! Die Uni2work Datenbank wird täglich gesichert;
|
||||
dennoch können wir Probleme während des Testbetriebs noch nicht gänzlich ausschließen.
|
||||
<li>
|
||||
Nicht aufgeführt sind Zeitstempel mit Benutzerinformationen, z.B. bei der Editierung und Korrektur von Übungen, Übungsgruppenleiterschaft, Raumbuchungen, etc.
|
||||
<li>
|
||||
Benutzerdaten bleiben so lange gespeichert, bis ein Institutsadministrator über die Exmatrikulation informiert wurde. Dann wird der Account gelöscht.
|
||||
Abgaben/Bonuspunkte werden unwiderruflich gelöscht.
|
||||
Klausurnoten verbleiben aus statistischen Gründen anonymisiert im System.
|
||||
Sie können die
|
||||
<a href=@{HelpR}>
|
||||
Löschung Ihre Daten über eine Supportanfrage beantragen
|
||||
. Ihre Daten werden dann nach Ablauf einer Frist gelöscht.
|
||||
Daten, welche keiner gesetzlichen Aufbewahrungsfrist unterliegen
|
||||
(z.B. Klausurnoten) verbleiben im System bis zur Ablauf der Aufbewahrungsfrist.
|
||||
<p>
|
||||
Benutzerdaten bleiben prinzipiell so lange gespeichert,
|
||||
bis ein Institutsadministrator über die Exmatrikulation informiert wurde.
|
||||
Dann wird der Account mit einer angemessenen zeitverzögerung gelöscht.
|
||||
Anonymisierte Klausurnoten verbleiben aus statistischen Gründen dauerhaft im System.
|
||||
|
||||
<li>
|
||||
Bei gemeinsamen Gruppenabgaben wird nur die Zuordnung zu diesem Benutzer gelöscht.
|
||||
Die Abgabe selbst wird erst gelöscht, wenn alle Benutzer einer Abgabe deren Löschung veranlasst haben.
|
||||
|
||||
@ -1,16 +1,22 @@
|
||||
<form .form-inline method=post action=@{ProfileDataR} enctype=#{btnEnctype}>
|
||||
<form .form-inline method=post action=@{AdminUserDeleteR uuid} enctype=#{btnEnctype}>
|
||||
<h2>
|
||||
Sind Sie sich absolut sicher, alle Ihre in Uni2work gespeicherten Daten zu löschen?
|
||||
Sind Sie sich absolut sicher
|
||||
Benutzer ^{nameEmailWidget userEmail userDisplayName userSurname} zu löschen?
|
||||
<div .container>
|
||||
Während der Testphase von Uni2work können Sie hiermit
|
||||
Ihren Account bei Uni2work vollständig löschen.
|
||||
Mit Ihrem Campus-Account können Sie sich aber danach
|
||||
jederzeit erneut einloggen, wodurch wieder ein leerer Account erstellt wird.
|
||||
Während der Testphase von Uni2work
|
||||
werden Benutzer hiermit vollständig aus der Live-Datenbank mit
|
||||
<code>DELETE CASCADE uid
|
||||
gelöscht.
|
||||
Klausurdaten müssen jedoch unbedingt 5 Jahre bis nach Exmatrikulation
|
||||
aufbewahrt werden!
|
||||
<div .container>
|
||||
Benutzer können sich mit Ihrem Campus-Account
|
||||
natürlich jederzeit erneut einloggen, wodurch wieder ein leerer Account erstellt wird.
|
||||
<div .container>
|
||||
Hochgeladene Hausaufgaben-Dateien werden unabhhängig vom Urherber nur dann gelöscht,
|
||||
wenn die Dateien ausschließlich Ihnen zugeordnet sind.
|
||||
wenn die Dateien ausschließlich diesem Benutzer zugeordnet waren.
|
||||
Dateien aus Gruppenabgaben werden also erst dann gelöscht,
|
||||
wenn alle Gruppenmitglieder Ihren Account gelöscht haben.
|
||||
wenn die Accounts alle Gruppenmitglieder gelöscht wurden.
|
||||
<div .container>
|
||||
<em>Achtung:
|
||||
Auch abgegebene Hausübungen werden gelöscht!
|
||||
@ -19,9 +25,5 @@
|
||||
(Verbuchte Noten sollten dadurch nicht betroffen sein, aber in einem etwaigen
|
||||
Streitfall konnen die per Uni2work verwalteten Hausaufgaben dann
|
||||
auch nicht mehr rekonstruiert/berücksichtigt werden.)
|
||||
<div .container>
|
||||
<em>Nach der Testphase von Uni2work wird das Löschen eines Accounts etwas
|
||||
eingeschränkt werden, da z.B. Klausurnoten 5 Jahre bis nach Exmatrikulation
|
||||
aufbewahrt werden müssen.
|
||||
<div .container>
|
||||
^{btnWdgt}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user