chore(audit): audit submissionhelper

This commit is contained in:
Sarah Vaupel 2019-09-04 14:46:11 +02:00
parent 7a0efbb5ca
commit 99cd37c5e0
5 changed files with 49 additions and 7 deletions

View File

@ -53,7 +53,6 @@ data Transaction
, transactionCourseApplication :: CourseApplicationId , transactionCourseApplication :: CourseApplicationId
} }
-- TODO: audit work in progress
| TransactionSubmissionEdit | TransactionSubmissionEdit
{ transactionSubmission :: SubmissionId { transactionSubmission :: SubmissionId
, transactionSheet :: SheetId , transactionSheet :: SheetId

View File

@ -409,7 +409,8 @@ submissionHelper tid ssh csh shn mcid = do
(Just files, _) -> -- new files (Just files, _) -> -- new files
runConduit $ transPipe (lift . lift) files .| extractRatingsMsg .| sinkSubmission uid (maybe (Left shid) Right msmid) False runConduit $ transPipe (lift . lift) files .| extractRatingsMsg .| sinkSubmission uid (maybe (Left shid) Right msmid) False
(Nothing, Nothing) -- new submission, no file upload requested (Nothing, Nothing) -- new submission, no file upload requested
-> insert Submission -> do
sid <- insert Submission
{ submissionSheet = shid { submissionSheet = shid
, submissionRatingPoints = Nothing , submissionRatingPoints = Nothing
, submissionRatingComment = Nothing , submissionRatingComment = Nothing
@ -417,6 +418,10 @@ submissionHelper tid ssh csh shn mcid = do
, submissionRatingAssigned = Nothing , submissionRatingAssigned = Nothing
, submissionRatingTime = Nothing , submissionRatingTime = Nothing
} }
audit $ TransactionSubmissionEdit sid shid
return sid
-- Determine new submission users
subUsers <- if subUsers <- if
| isLecturer -> return adhocMembers | isLecturer -> return adhocMembers
| otherwise -> do | otherwise -> do
@ -429,12 +434,30 @@ submissionHelper tid ssh csh shn mcid = do
return $ submissionGroupUser' E.^. SubmissionGroupUserUser return $ submissionGroupUser' E.^. SubmissionGroupUserUser
-- SubmissionUser for all group members (pre-registered & ad-hoc) -- SubmissionUser for all group members (pre-registered & ad-hoc)
return $ groupUids `Set.union` adhocMembers return $ groupUids `Set.union` adhocMembers
let (subEmails, subUids) = partitionEithers $ Set.toList subUsers
deleteWhere [SubmissionUserSubmission ==. smid] -- Determine old submission users
deleteWhere [InvitationFor ==. invRef @SubmissionUser smid, InvitationEmail /<-. subEmails] subUsersOld <- if
insertMany_ $ map (flip SubmissionUser smid) subUids | isJust msmid -> setOf (folded . _entityVal . _submissionUserUser . to Right) <$> selectList [SubmissionUserSubmission ==. smid] []
sinkInvitationsF submissionUserInvitationConfig $ map (\lEmail -> (lEmail, smid, (InvDBDataSubmissionUser, InvTokenDataSubmissionUser))) subEmails | otherwise -> return Set.empty -- optimization (do not perform selection if submission was freshly created)
forM_ (subUsers `setSymmDiff` subUsersOld) $ \change -> if
-- change is a new user being added to the submission users => send invitation / insert
| change `Set.member` subUsers -> case change of
Left subEmail -> do
-- user does not exist yet => send invitation
sinkInvitationsF submissionUserInvitationConfig [(subEmail, smid, (InvDBDataSubmissionUser, InvTokenDataSubmissionUser))]
return ()
Right subUid -> do
-- user exists and has an id => insert as SubmissionUser and audit
_ <- insert $ SubmissionUser subUid smid
audit $ TransactionSubmissionUserEdit smid subUid
-- change is an old user that is not a submission user anymore => delete invitation / delete
| otherwise -> case change of
Left subEmail -> runConduit $ yield subEmail .| deleteInvitations @SubmissionUser smid
Right subUid -> do
deleteWhere [SubmissionUserUser ==. subUid]
audit $ TransactionSubmissionUserDelete smid subUid
addMessageI Success $ if | Nothing <- msmid -> MsgSubmissionCreated addMessageI Success $ if | Nothing <- msmid -> MsgSubmissionCreated
| otherwise -> MsgSubmissionUpdated | otherwise -> MsgSubmissionUpdated
return smid return smid

View File

@ -11,6 +11,7 @@ module Handler.Utils.Invitations
, InvitationReference(..), invRef , InvitationReference(..), invRef
, InvitationConfig(..), InvitationTokenConfig(..) , InvitationConfig(..), InvitationTokenConfig(..)
, sourceInvitations, sourceInvitationsList , sourceInvitations, sourceInvitationsList
, deleteInvitations
, sinkInvitations, sinkInvitationsF , sinkInvitations, sinkInvitationsF
, invitationR', InvitationR(..) , invitationR', InvitationR(..)
) where ) where
@ -28,6 +29,7 @@ import Control.Monad.Trans.Reader (mapReaderT)
import qualified Data.Conduit.List as C import qualified Data.Conduit.List as C
import qualified Data.List.NonEmpty as NonEmpty import qualified Data.List.NonEmpty as NonEmpty
import qualified Data.HashSet as HashSet import qualified Data.HashSet as HashSet
import qualified Data.Set as Set
import Data.Aeson (fromJSON) import Data.Aeson (fromJSON)
import qualified Data.Aeson as JSON import qualified Data.Aeson as JSON
@ -257,6 +259,18 @@ sourceInvitationsList :: forall junction.
sourceInvitationsList forKey = runConduit $ sourceInvitations forKey .| C.foldMap pure sourceInvitationsList forKey = runConduit $ sourceInvitations forKey .| C.foldMap pure
-- | Deletes all invitations for given emails and a given junction. (Type application required)
deleteInvitations :: forall junction m.
( IsInvitableJunction junction
, MonadIO m
)
=> Key (InvitationFor junction)
-> Sink UserEmail (ReaderT SqlBackend m) ()
deleteInvitations k = do
subEmails <- C.foldMap Set.singleton
lift $ deleteWhere [InvitationEmail <-. Set.toList subEmails, InvitationFor ==. invRef @junction k]
data ButtonInvite = BtnInviteAccept | BtnInviteDecline data ButtonInvite = BtnInviteAccept | BtnInviteDecline
deriving (Eq, Ord, Read, Show, Enum, Bounded, Generic, Typeable) deriving (Eq, Ord, Read, Show, Enum, Bounded, Generic, Typeable)
instance Universe ButtonInvite instance Universe ButtonInvite

View File

@ -395,6 +395,10 @@ setIntersections (h:t) = foldl' Set.intersection h t
setMapMaybe :: (Ord a, Ord b) => (a -> Maybe b) -> Set a -> Set b setMapMaybe :: (Ord a, Ord b) => (a -> Maybe b) -> Set a -> Set b
setMapMaybe f = Set.fromList . mapMaybe f . Set.toList setMapMaybe f = Set.fromList . mapMaybe f . Set.toList
-- | Symmetric difference of two sets.
setSymmDiff :: Ord a => Set a -> Set a -> Set a
setSymmDiff x y = (x `Set.difference` y) `Set.union` (y `Set.difference` x)
---------- ----------
-- Maps -- -- Maps --
---------- ----------

View File

@ -169,6 +169,8 @@ makeLenses_ ''File
makeLenses_ ''Submission makeLenses_ ''Submission
makeLenses_ ''SubmissionUser
-- makeClassy_ ''Load -- makeClassy_ ''Load