feat(tutorials): delegate control to tutors

This commit is contained in:
Gregor Kleen 2019-10-14 11:50:06 +02:00
parent 31524132ca
commit 261f3ed92f
15 changed files with 53 additions and 11 deletions

View File

@ -412,6 +412,7 @@ UnknownAuthPredicate tag@String: Authorisierungsprädikat "#{tag}" ist dem Syste
UnauthorizedRedirect: Die angeforderte Seite existiert nicht oder Sie haben keine Berechtigung, die angeforderte Seite zu sehen.
UnauthorizedSelf: Aktueller Nutzer ist nicht angegebener Benutzer.
UnauthorizedTutorialTutor: Sie sind nicht Tutor für dieses Tutorium.
UnauthorizedTutorialTutorControl: Tutoren dürfen dieses Tutorium nicht editieren.
UnauthorizedCourseTutor: Sie sind nicht Tutor für diesen Kurs.
UnauthorizedTutor: Sie sind nicht Tutor.
UnauthorizedTutorialRegisterGroup: Sie sind bereits in einem Tutorium mit derselben Registrierungs-Gruppe.
@ -1126,6 +1127,7 @@ AuthTagDevelopment: Seite ist nicht in Entwicklung
AuthTagLecturer: Nutzer ist Dozent
AuthTagCorrector: Nutzer ist Korrektor
AuthTagTutor: Nutzer ist Tutor
AuthTagTutorControl: Tutoren haben Kontrolle über ihre Tutorium
AuthTagTime: Zeitliche Einschränkungen sind erfüllt
AuthTagStaffTime: Zeitliche Einschränkungen für Lehrbeteiligte sind erfüllt
AuthTagAllocationTime: Zeitliche Einschränkungen durch Zentralanmeldung sind erfüllt
@ -1276,6 +1278,8 @@ TutorialDeregisterUntil: Abmeldungen bis
TutorialsHeading: Tutorien
TutorialEdit: Bearbeiten
TutorialDelete: Löschen
TutorialTutorControlled: Tutoren dürfen Tutorium editieren
TutorialTutorControlledTip: Sollen Tutoren beliebige Aspekte dieses Tutoriums (Name, Registrierungs-Gruppe, Raum, Zeit, andere Tutoren, ...) beliebig editieren dürfen?
CourseExams: Prüfungen
CourseTutorials: Übungen

View File

@ -10,6 +10,7 @@ Tutorial json
registerTo UTCTime Maybe
deregisterUntil UTCTime Maybe
lastChanged UTCTime default=now()
tutorControlled Bool default=false
UniqueTutorial course name
deriving Generic
Tutor

4
routes
View File

@ -158,12 +158,12 @@
/tuts CTutorialListR GET !tutor -- THIS route is used to check for overall course tutor access!
/tuts/new CTutorialNewR GET POST
/tuts/#TutorialName TutorialR:
/edit TEditR GET POST
/edit TEditR GET POST !tutorANDtutor-control
/delete TDeleteR GET POST
/participants TUsersR GET POST !tutor
/register TRegisterR POST !timeANDcapacityANDcourse-registeredANDregister-group !timeANDtutorial-registered
/communication TCommR GET POST !tutor
/tutor-invite TInviteR GET POST
/tutor-invite TInviteR GET POST !tutorANDtutor-control
/exams CExamListR GET !free
/exams/new CExamNewR GET POST
/exams/#ExamName ExamR:

View File

@ -132,6 +132,12 @@ data Transaction
{ transactionOffice :: UserId
, transactionField :: StudyTermsId
}
| TransactionTutorialEdit
{ transactionTutorial :: TutorialId
}
| TransactionTutorialDelete
{ transactionTutorial :: TutorialId
}
deriving (Eq, Ord, Read, Show, Generic, Typeable)

View File

@ -799,6 +799,13 @@ tagAccessPredicate AuthTutor = APDB $ \mAuthId route _ -> exceptT return return
_ -> do
guardMExceptT (not $ Map.null resMap) (unauthorizedI MsgUnauthorizedTutor)
return Authorized
tagAccessPredicate AuthTutorControl = APDB $ \_ route _ -> case route of
CTutorialR tid ssh csh tutn _ -> maybeT (unauthorizedI MsgUnauthorizedTutorialTutorControl) $ do
Entity cid _ <- $cachedHereBinary (tid, ssh, csh) . MaybeT . getBy $ TermSchoolCourseShort tid ssh csh
Entity _ Tutorial{..} <- $cachedHereBinary (cid, tutn) . MaybeT . getBy $ UniqueTutorial cid tutn
guard tutorialTutorControlled
return Authorized
r -> $unsupportedAuthPredicate AuthTutorControl r
tagAccessPredicate AuthTime = APDB $ \mAuthId route _ -> case route of
CApplicationR tid ssh csh _ _ -> maybeT (unauthorizedI MsgUnauthorizedApplicationTime) $ do
course <- $cachedHereBinary (tid, ssh, csh) . MaybeT . getKeyBy $ TermSchoolCourseShort tid ssh csh

View File

@ -54,7 +54,7 @@ getInfoLecturerR =
tooltipPlanned = [whamlet| _{MsgLecturerInfoTooltipPlanned} |]
tooltipNewU2W = [whamlet| _{MsgLecturerInfoTooltipNewU2W} |]
newU2WFeat, probFeatInline, plannedFeat, plannedFeatInline :: WidgetFor UniWorX ()
newU2WFeat = [whamlet| ^{iconTooltip tooltipNew (Just IconAnnounce) True} |] -- to be used inside text blocks
newU2WFeat = [whamlet| ^{iconTooltip tooltipNewU2W (Just IconAnnounce) True} |] -- to be used inside text blocks
probFeatInline = [whamlet| ^{iconTooltip tooltipProblem (Just IconProblem) True} |] -- to be used inside text blocks
plannedFeat = [whamlet| ^{iconTooltip tooltipPlanned (Just IconPlanned) False} |]
plannedFeatInline = [whamlet| ^{iconTooltip tooltipPlanned (Just IconPlanned) True} |] -- to be used inside text blocks
@ -66,4 +66,4 @@ getInfoLecturerR =
let expiryTime = UTCTime (addGregorianMonthsRollOver 1 $ fromGregorian year month day) 0
if currentTime > expiryTime
then mempty
else toWidget [whamlet| ^{iconTooltip tooltipNewU2W (Just IconNew) False} |]
else toWidget [whamlet| ^{iconTooltip tooltipNew (Just IconNew) False} |]

View File

@ -35,5 +35,5 @@ postTDeleteR tid ssh csh tutn = do
, drSuccessMessage = SomeMessage MsgTutorialDeleted
, drAbort = SomeRoute $ CTutorialR tid ssh csh tutn TUsersR
, drSuccess = SomeRoute $ CourseR tid ssh csh CTutorialListR
, drDelete = const id -- TODO: audit
, drDelete = \tutid' act -> act <* audit (TransactionTutorialDelete tutid')
}

View File

@ -42,6 +42,7 @@ postTEditR tid ssh csh tutn = do
, tfDeregisterUntil = tutorialDeregisterUntil
, tfTutors = Set.fromList (map Right tutorIds)
<> Set.mapMonotonic Left (Map.keysSet tutorInvites)
, tfTutorControlled = tutorialTutorControlled
}
return (cid, tutid, template)
@ -63,8 +64,11 @@ postTEditR tid ssh csh tutn = do
, tutorialRegisterTo = tfRegisterTo
, tutorialDeregisterUntil = tfDeregisterUntil
, tutorialLastChanged = now
, tutorialTutorControlled = tfTutorControlled
}
when (is _Nothing insertRes) $ do
audit $ TransactionTutorialEdit tutid
let (invites, adds) = partitionEithers $ Set.toList tfTutors
deleteWhere [ TutorTutorial ==. tutid ]

View File

@ -18,10 +18,11 @@ import qualified Data.CaseInsensitive as CI
data TutorialForm = TutorialForm
{ tfName :: TutorialName
, tfType :: CI Text
, tfRegGroup :: Maybe (CI Text)
, tfTutorControlled :: Bool
, tfCapacity :: Maybe Int
, tfRoom :: Text
, tfTime :: Occurrences
, tfRegGroup :: Maybe (CI Text)
, tfRegisterFrom :: Maybe UTCTime
, tfRegisterTo :: Maybe UTCTime
, tfDeregisterUntil :: Maybe UTCTime
@ -66,10 +67,11 @@ tutorialForm cid template html = do
flip (renderAForm FormStandard) html $ TutorialForm
<$> areq (textField & cfStrip & cfCI) (fslpI MsgTutorialName (mr MsgTutorialName) & setTooltip MsgTutorialNameTip) (tfName <$> template)
<*> areq (textField & cfStrip & cfCI & addDatalist tutTypeDatalist) (fslpI MsgTutorialType $ mr MsgTutorialType) (tfType <$> template)
<*> aopt (textField & cfStrip & cfCI) (fslI MsgTutorialRegGroup & setTooltip MsgTutorialRegGroupTip) ((tfRegGroup <$> template) <|> Just (Just "tutorial"))
<*> apopt checkBoxField (fslI MsgTutorialTutorControlled & setTooltip MsgTutorialTutorControlledTip) (tfTutorControlled <$> template)
<*> aopt (natFieldI MsgTutorialCapacityNonPositive) (fslpI MsgTutorialCapacity (mr MsgTutorialCapacity) & setTooltip MsgTutorialCapacityTip) (tfCapacity <$> template)
<*> areq textField (fslpI MsgTutorialRoom $ mr MsgTutorialRoomPlaceholder) (tfRoom <$> template)
<*> occurrencesAForm ("occurrences" :: Text) (tfTime <$> template)
<*> aopt (textField & cfStrip & cfCI) (fslI MsgTutorialRegGroup & setTooltip MsgTutorialRegGroupTip) ((tfRegGroup <$> template) <|> Just (Just "tutorial"))
<*> aopt utcTimeField (fslpI MsgRegisterFrom (mr MsgDate)
& setTooltip MsgCourseRegisterFromTip
) (tfRegisterFrom <$> template)

View File

@ -35,8 +35,11 @@ postCTutorialNewR tid ssh csh = do
, tutorialRegisterTo = tfRegisterTo
, tutorialDeregisterUntil = tfDeregisterUntil
, tutorialLastChanged = now
, tutorialTutorControlled = tfTutorControlled
}
whenIsJust insertRes $ \tutid -> do
audit $ TransactionTutorialEdit tutid
let (invites, adds) = partitionEithers $ Set.toList tfTutors
insertMany_ $ map (Tutor tutid) adds
sinkInvitationsF tutorInvitationConfig $ map (, tutid, (InvDBDataTutor, InvTokenDataTutor)) invites

View File

@ -43,6 +43,7 @@ data AuthTag -- sortiert nach gewünschter Reihenfolge auf /authpreds, d.h. Prä
| AuthLecturer
| AuthCorrector
| AuthTutor
| AuthTutorControl
| AuthExamOffice
| AuthAllocationRegistered
| AuthCourseRegistered

View File

@ -1,5 +1,11 @@
$newline never
<dl .deflist>
<dt .deflist__dt>
^{formatGregorianW 2019 10 14}
<dd .deflist__dd>
<ul>
<li>Kontrolle über Einstellungen eines Tutoriums kann an Tutoren deligiert werden
<dt .deflist__dt>
^{formatGregorianW 2019 10 10}
<dd .deflist__dd>

View File

@ -254,7 +254,13 @@ $newline text
Eine Tutoriumsgruppe kann beliebig viele Tutoren haben und ein Tutor kann beliebig viele Tutoriengruppen betreuen.
<p>
Tutoren haben Zugriff auf die Namen und Studiendaten ihrer Tutoriums-Teilnehmer und können auch Mitteilungen an sie verschicken (analog zu Kursmitteilungen).
Tutoren haben Zugriff auf die Namen und Studiendaten ihrer Tutoriums-Teilnehmer, können Mitteilungen an sie verschicken (analog zu Kursmitteilungen) und Teilnehmer aus ihrem Tutorium entfernen.
<p>
^{newFeat 2019 10 14} Optional kann den Tutoren volle Kontrolle über
ihre Tutorien überlassen werden (bis auf Löschen des Tutoriums), Tutoren
können dann insbesondere eigenständig den regulären Raum und die Zeit
ihres Tutoriums anpassen.
<dt .deflist__dt> Anmeldung
<dd .deflist__dd>
@ -277,10 +283,9 @@ $newline text
<p>
Um die Anmeldung in beliebig viele Tutoriumsgruppen zuzulassen können alle Registrierungs-Gruppen leer gelassen werden.
<dt .deflist__dt> ^{plannedFeat} Nachmeldung
<dt .deflist__dt> ^{newFeat 2019 10 10} Nachmeldung
<dt .deflist__dd>
<p>
Es gibt zur Zeit keine Möglichkeit für die Kursverwalter oder Tutoren, Teilnehmer zu einem Tutorium hinzuzufügen.
Kursverwalter können über die Teilnehmerliste der Veranstaltung Kursteilnehmer in Tutorien einteilen.
<section id="exams">

View File

@ -716,6 +716,7 @@ fillDb = do
, tutorialRegisterTo = Nothing
, tutorialDeregisterUntil = Nothing
, tutorialLastChanged = now
, tutorialTutorControlled = True
}
void . insert $ Tutor tut1 gkleen
void . insert $ TutorialParticipant tut1 fhamann
@ -734,6 +735,7 @@ fillDb = do
, tutorialRegisterTo = Nothing
, tutorialDeregisterUntil = Nothing
, tutorialLastChanged = now
, tutorialTutorControlled = False
}
void . insert $ Tutor tut2 gkleen
-- datenbanksysteme

View File

@ -70,6 +70,7 @@ instance Arbitrary Tutorial where
<*> arbitrary
<*> arbitrary
<*> arbitrary
<*> arbitrary
shrink = genericShrink
instance Arbitrary User where