fix(personalised-sheet-files): more thorough check wrt sub-warnings
This commit is contained in:
parent
c9b86d8770
commit
0b0eaff20d
@ -1572,13 +1572,23 @@ evalAccessFor mAuthId route isWrite = do
|
|||||||
evalAccessForDB :: (MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX, BackendCompatible SqlBackend backend) => Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> ReaderT backend m AuthResult
|
evalAccessForDB :: (MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX, BackendCompatible SqlBackend backend) => Maybe (AuthId UniWorX) -> Route UniWorX -> Bool -> ReaderT backend m AuthResult
|
||||||
evalAccessForDB = evalAccessFor
|
evalAccessForDB = evalAccessFor
|
||||||
|
|
||||||
evalAccess :: (MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX) => Route UniWorX -> Bool -> m AuthResult
|
evalAccessWith :: (MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX) => [(AuthTag, Bool)] -> Route UniWorX -> Bool -> m AuthResult
|
||||||
evalAccess route isWrite = do
|
evalAccessWith assumptions route isWrite = do
|
||||||
mAuthId <- liftHandler maybeAuthId
|
mAuthId <- liftHandler maybeAuthId
|
||||||
tagActive <- fromMaybe def <$> lookupSessionJson SessionActiveAuthTags
|
tagActive <- fromMaybe def <$> lookupSessionJson SessionActiveAuthTags
|
||||||
dnf <- either throwM return $ routeAuthTags route
|
dnf <- either throwM return $ routeAuthTags route
|
||||||
(result, deactivated) <- runWriterT $ evalAuthTags tagActive dnf mAuthId route isWrite
|
let dnf' = ala Endo foldMap (map ((=<<) . uncurry dnfAssumeValue) assumptions) $ Just dnf
|
||||||
result <$ tellSessionJson SessionInactiveAuthTags deactivated
|
case dnf' of
|
||||||
|
Nothing -> return Authorized
|
||||||
|
Just dnf'' -> do
|
||||||
|
(result, deactivated) <- runWriterT $ evalAuthTags tagActive dnf'' mAuthId route isWrite
|
||||||
|
result <$ tellSessionJson SessionInactiveAuthTags deactivated
|
||||||
|
|
||||||
|
evalAccessWithDB :: (MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX, BackendCompatible SqlBackend backend) => [(AuthTag, Bool)] -> Route UniWorX -> Bool -> ReaderT backend m AuthResult
|
||||||
|
evalAccessWithDB = evalAccessWith
|
||||||
|
|
||||||
|
evalAccess :: (MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX) => Route UniWorX -> Bool -> m AuthResult
|
||||||
|
evalAccess = evalAccessWith []
|
||||||
|
|
||||||
evalAccessDB :: (MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX, BackendCompatible SqlBackend backend) => Route UniWorX -> Bool -> ReaderT backend m AuthResult
|
evalAccessDB :: (MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX, BackendCompatible SqlBackend backend) => Route UniWorX -> Bool -> ReaderT backend m AuthResult
|
||||||
evalAccessDB = evalAccess
|
evalAccessDB = evalAccess
|
||||||
@ -1598,6 +1608,29 @@ hasReadAccessTo = flip hasAccessTo False
|
|||||||
hasWriteAccessTo :: (MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX) => Route UniWorX -> m Bool
|
hasWriteAccessTo :: (MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX) => Route UniWorX -> m Bool
|
||||||
hasWriteAccessTo = flip hasAccessTo True
|
hasWriteAccessTo = flip hasAccessTo True
|
||||||
|
|
||||||
|
wouldHaveAccessTo :: ( MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX )
|
||||||
|
=> [(AuthTag, Bool)] -- ^ Assumptions
|
||||||
|
-> Route UniWorX
|
||||||
|
-> Bool
|
||||||
|
-> m Bool
|
||||||
|
wouldHaveAccessTo assumptions route isWrite = (== Authorized) <$> evalAccessWith assumptions route isWrite
|
||||||
|
|
||||||
|
wouldHaveReadAccessTo, wouldHaveWriteAccessTo
|
||||||
|
:: ( MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX )
|
||||||
|
=> [(AuthTag, Bool)] -- ^ Assumptions
|
||||||
|
-> Route UniWorX
|
||||||
|
-> m Bool
|
||||||
|
wouldHaveReadAccessTo assumptions route = wouldHaveAccessTo assumptions route False
|
||||||
|
wouldHaveWriteAccessTo assumptions route = wouldHaveAccessTo assumptions route True
|
||||||
|
|
||||||
|
wouldHaveReadAccessToIff, wouldHaveWriteAccessToIff
|
||||||
|
:: ( MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX )
|
||||||
|
=> [(AuthTag, Bool)] -- ^ Assumptions
|
||||||
|
-> Route UniWorX
|
||||||
|
-> m Bool
|
||||||
|
wouldHaveReadAccessToIff assumptions route = and2M (fmap not $ hasReadAccessTo route) $ wouldHaveReadAccessTo assumptions route
|
||||||
|
wouldHaveWriteAccessToIff assumptions route = and2M (fmap not $ hasWriteAccessTo route) $ wouldHaveWriteAccessTo assumptions route
|
||||||
|
|
||||||
-- | Conditional redirect that hides the URL if the user is not authorized for the route
|
-- | Conditional redirect that hides the URL if the user is not authorized for the route
|
||||||
redirectAccess :: (MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX) => Route UniWorX -> m a
|
redirectAccess :: (MonadThrow m, MonadHandler m, HandlerSite m ~ UniWorX) => Route UniWorX -> m a
|
||||||
redirectAccess url = do
|
redirectAccess url = do
|
||||||
|
|||||||
@ -116,7 +116,11 @@ getSShowR tid ssh csh shn = do
|
|||||||
, formEncoding = generateEnctype
|
, formEncoding = generateEnctype
|
||||||
, formSubmit = FormNoSubmit
|
, formSubmit = FormNoSubmit
|
||||||
}
|
}
|
||||||
mRequiredExam <- fmap join . for (sheetRequireExamRegistration sheet) $ \eId -> fmap (fmap $(E.unValueN 4)) . runDB . E.selectMaybe . E.from $ \(exam `E.InnerJoin` course) -> do
|
checkExamRegistration <- orM
|
||||||
|
[ wouldHaveWriteAccessToIff [(AuthExamRegistered, True)] $ CSheetR tid ssh csh shn SubmissionNewR
|
||||||
|
, wouldHaveReadAccessToIff [(AuthExamRegistered, True)] $ CSheetR tid ssh csh shn SArchiveR
|
||||||
|
]
|
||||||
|
mRequiredExam <- fmap join . for (guardOnM checkExamRegistration $ sheetRequireExamRegistration sheet) $ \eId -> fmap (fmap $(E.unValueN 4)) . runDB . E.selectMaybe . E.from $ \(exam `E.InnerJoin` course) -> do
|
||||||
E.on $ exam E.^. ExamCourse E.==. course E.^. CourseId
|
E.on $ exam E.^. ExamCourse E.==. course E.^. CourseId
|
||||||
E.where_ $ exam E.^. ExamId E.==. E.val eId
|
E.where_ $ exam E.^. ExamId E.==. E.val eId
|
||||||
return (course E.^. CourseTerm, course E.^. CourseSchool, course E.^. CourseShorthand, exam E.^. ExamName)
|
return (course E.^. CourseTerm, course E.^. CourseSchool, course E.^. CourseShorthand, exam E.^. ExamName)
|
||||||
@ -125,14 +129,15 @@ getSShowR tid ssh csh shn = do
|
|||||||
let eUrl = CExamR etid essh ecsh examn EShowR
|
let eUrl = CExamR etid essh ecsh examn EShowR
|
||||||
guardM $ hasReadAccessTo eUrl
|
guardM $ hasReadAccessTo eUrl
|
||||||
return eUrl
|
return eUrl
|
||||||
mMissingExamRegistration <- for (sheetRequireExamRegistration sheet) $ \eId -> maybeT (return True) $ do
|
mMissingExamRegistration <- for (guardOnM checkExamRegistration $ sheetRequireExamRegistration sheet) $ \eId -> maybeT (return True) $ do
|
||||||
uid <- MaybeT maybeAuthId
|
uid <- MaybeT maybeAuthId
|
||||||
lift . fmap not . runDB $ exists [ ExamRegistrationExam ==. eId, ExamRegistrationUser ==. uid ]
|
lift . fmap not . runDB $ exists [ ExamRegistrationExam ==. eId, ExamRegistrationUser ==. uid ]
|
||||||
|
|
||||||
let checkPersonalisedFiles
|
checkPersonalisedFiles <- andM
|
||||||
= not (sheetAllowNonPersonalisedSubmission sheet)
|
[ return . not $ sheetAllowNonPersonalisedSubmission sheet
|
||||||
&& NTop (sheetActiveFrom sheet) <= NTop (Just now)
|
, return $ NTop (sheetActiveFrom sheet) <= NTop (Just now), return $ NTop (Just now) <= NTop (sheetActiveTo sheet)
|
||||||
&& NTop (sheetActiveTo sheet) >= NTop (Just now)
|
, wouldHaveWriteAccessToIff [(AuthPersonalisedSheetFiles, True)] $ CSheetR tid ssh csh shn SubmissionNewR
|
||||||
|
]
|
||||||
mMissingPersonalisedFiles <- for (guardOnM checkPersonalisedFiles muid) $ \uid -> runDB $
|
mMissingPersonalisedFiles <- for (guardOnM checkPersonalisedFiles muid) $ \uid -> runDB $
|
||||||
fmap not . E.selectExists . E.from $ \psFile ->
|
fmap not . E.selectExists . E.from $ \psFile ->
|
||||||
E.where_ $ psFile E.^. PersonalisedSheetFileUser E.==. E.val uid
|
E.where_ $ psFile E.^. PersonalisedSheetFileUser E.==. E.val uid
|
||||||
|
|||||||
@ -127,6 +127,8 @@ data PredLiteral a = PLVariable { plVar :: a } | PLNegated { plVar :: a }
|
|||||||
deriving (Eq, Ord, Read, Show, Generic, Typeable)
|
deriving (Eq, Ord, Read, Show, Generic, Typeable)
|
||||||
deriving anyclass (Hashable, Binary)
|
deriving anyclass (Hashable, Binary)
|
||||||
|
|
||||||
|
makeLenses_ ''PredLiteral
|
||||||
|
|
||||||
deriveJSON defaultOptions
|
deriveJSON defaultOptions
|
||||||
{ constructorTagModifier = camelToPathPiece' 1
|
{ constructorTagModifier = camelToPathPiece' 1
|
||||||
, sumEncoding = TaggedObject "val" "var"
|
, sumEncoding = TaggedObject "val" "var"
|
||||||
@ -145,6 +147,8 @@ newtype PredDNF a = PredDNF { dnfTerms :: Set (NonNull (Set (PredLiteral a))) }
|
|||||||
deriving newtype (Semigroup, Monoid)
|
deriving newtype (Semigroup, Monoid)
|
||||||
deriving anyclass (Binary, Hashable)
|
deriving anyclass (Binary, Hashable)
|
||||||
|
|
||||||
|
makeLenses_ ''PredDNF
|
||||||
|
|
||||||
$(return [])
|
$(return [])
|
||||||
|
|
||||||
instance ToJSON a => ToJSON (PredDNF a) where
|
instance ToJSON a => ToJSON (PredDNF a) where
|
||||||
@ -161,6 +165,20 @@ type AuthLiteral = PredLiteral AuthTag
|
|||||||
type AuthDNF = PredDNF AuthTag
|
type AuthDNF = PredDNF AuthTag
|
||||||
|
|
||||||
|
|
||||||
|
dnfAssumeValue :: forall a. Ord a => a -> Bool -> PredDNF a -> Maybe (PredDNF a)
|
||||||
|
-- ^ `Nothing` corresponds to @⊤@
|
||||||
|
dnfAssumeValue var val
|
||||||
|
= fmap (PredDNF . Set.fromList) . sequence
|
||||||
|
. foldMapOf (_dnfTerms . folded) (pure @[] . fromNullable . Set.filter (not . agrees) . toNullable)
|
||||||
|
. over _dnfTerms (Set.filter $ none disagrees . toNullable)
|
||||||
|
where
|
||||||
|
agrees, disagrees :: PredLiteral a -> Bool
|
||||||
|
agrees PLVariable{..} = plVar == var && val
|
||||||
|
agrees PLNegated{..} = plVar == var && not val
|
||||||
|
disagrees PLNegated{..} = plVar == var && val
|
||||||
|
disagrees PLVariable{..} = plVar == var && not val
|
||||||
|
|
||||||
|
|
||||||
data UserGroupName
|
data UserGroupName
|
||||||
= UserGroupMetrics
|
= UserGroupMetrics
|
||||||
| UserGroupCustom { userGroupCustomName :: CI Text }
|
| UserGroupCustom { userGroupCustomName :: CI Text }
|
||||||
|
|||||||
@ -180,8 +180,6 @@ makePrisms ''OccurrenceException
|
|||||||
|
|
||||||
makeLenses_ ''Occurrences
|
makeLenses_ ''Occurrences
|
||||||
|
|
||||||
makeLenses_ ''PredDNF
|
|
||||||
|
|
||||||
makeLenses_ ''Invitation
|
makeLenses_ ''Invitation
|
||||||
|
|
||||||
makeLenses_ ''ExamBonusRule
|
makeLenses_ ''ExamBonusRule
|
||||||
|
|||||||
Reference in New Issue
Block a user