From 9ccc2e3149939c11ce47dcc04586c7e15556edfa Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Thu, 1 Nov 2018 22:06:00 +0100 Subject: [PATCH] Fix warnings --- package.yaml | 39 ++++-- routes | 6 +- src/Cron.hs | 111 +++++++++--------- src/Foundation.hs | 76 ++++++------ src/Handler/Corrections.hs | 70 +++++------ src/Handler/Course.hs | 56 +++++---- src/Handler/Home.hs | 1 - src/Handler/School.hs | 32 +---- src/Handler/Sheet.hs | 56 ++++----- src/Handler/Submission.hs | 17 ++- src/Handler/SystemMessage.hs | 39 +++--- src/Handler/Term.hs | 6 +- src/Handler/Utils/DateTime.hs | 2 - src/Handler/Utils/Form.hs | 12 +- src/Handler/Utils/Mail.hs | 2 +- src/Handler/Utils/Rating.hs | 8 +- src/Handler/Utils/Submission.hs | 45 +++---- src/Handler/Utils/Table/Pagination.hs | 44 +++---- src/Handler/Utils/Templates.hs | 4 +- src/Jobs.hs | 11 +- src/Jobs/Handler/HelpRequest.hs | 2 +- .../SendNotification/CorrectionsAssigned.hs | 7 +- .../Handler/SendNotification/SheetActive.hs | 3 +- .../Handler/SendNotification/SheetInactive.hs | 3 +- .../SendNotification/SubmissionRated.hs | 2 + src/Jobs/Queue.hs | 1 - src/Mail.hs | 26 ++-- src/Model.hs | 2 +- src/Model/Migration/Types.hs | 8 +- src/Model/Types/JSON.hs | 10 +- src/Utils/Lens.hs | 2 +- templates/correction-user.hamlet | 2 +- templates/default-layout.hamlet | 2 +- templates/login.hamlet | 2 +- templates/mail/submissionRated.hamlet | 2 +- templates/mail/support.hamlet | 2 +- .../messages/submissionFilesIgnored.hamlet | 2 +- templates/widgets/asidenav.hamlet | 14 +-- templates/widgets/rating.hamlet | 2 +- 39 files changed, 331 insertions(+), 400 deletions(-) diff --git a/package.yaml b/package.yaml index 820a16e46..0820ca9d3 100644 --- a/package.yaml +++ b/package.yaml @@ -156,24 +156,35 @@ default-extensions: - BinaryLiterals - PolyKinds -ghc-options: - - -Wall - - -fwarn-tabs +when: + - condition: flag(pedantic) + then: + ghc-options: + - -Wall + - -Werror + - -fwarn-tabs + - -fno-warn-type-defaults + - -fno-warn-partial-type-signatures + else: + ghc-options: + - -Wall + - -fno-warn-type-defaults + - -fno-warn-partial-type-signatures # The library contains all of our application code. The executable # defined below is just a thin wrapper. library: source-dirs: src when: - - condition: (flag(dev)) || (flag(library-only)) - then: - ghc-options: - - -O0 - - -ddump-splices - cpp-options: -DDEVELOPMENT - else: - ghc-options: - - -O2 + - condition: (flag(dev)) || (flag(library-only)) + then: + ghc-options: + - -O0 + - -ddump-splices + cpp-options: -DDEVELOPMENT + else: + ghc-options: + - -O2 # Runnable executable for our application executables: @@ -219,3 +230,7 @@ flags: description: Turn on development settings, like auto-reload templates. manual: false default: false + pedantic: + description: Be very pedantic about warnings and errors + manual: true + default: true diff --git a/routes b/routes index 17a653125..f953da2e5 100644 --- a/routes +++ b/routes @@ -50,8 +50,8 @@ !/term/#TermId TermCourseListR GET !free !/term/#TermId/#SchoolId TermSchoolCourseListR GET !free -/school SchoolListR GET -/school/#SchoolId SchoolShowR GET +/school SchoolListR GET !development +/school/#SchoolId SchoolShowR GET !development -- For Pattern Synonyms see Foundation @@ -64,7 +64,7 @@ /edit CEditR GET POST /delete CDeleteR GET POST !lecturerANDempty /users CUsersR GET - /user/#CryptoUUIDUser CUserR GET + /user/#CryptoUUIDUser CUserR GET !development /correctors CHiWisR GET /subs CCorrectionsR GET POST /ex SheetListR GET !registered !materials diff --git a/src/Cron.hs b/src/Cron.hs index cb2d9a338..600eb873c 100644 --- a/src/Cron.hs +++ b/src/Cron.hs @@ -1,5 +1,6 @@ module Cron - ( CronNextMatch(..) + ( evalCronMatch + , CronNextMatch(..) , nextCronMatch , module Cron.Types ) where @@ -18,11 +19,7 @@ import Data.Ratio ((%)) import qualified Data.Set as Set -import Data.List.NonEmpty (NonEmpty(..)) -import qualified Data.List.NonEmpty as NonEmpty - -import Utils.Lens.TH -import Control.Lens +import Utils.Lens hiding (from, to) data CronDate = CronDate @@ -38,7 +35,7 @@ makeLenses_ ''CronDate evalCronMatch :: CronMatch -> Natural -> Bool evalCronMatch CronMatchAny _ = True evalCronMatch CronMatchNone _ = False -evalCronMatch (CronMatchSome set) x = Set.member x $ toNullable set +evalCronMatch (CronMatchSome xs) x = Set.member x $ toNullable xs evalCronMatch (CronMatchStep step) x = (x `mod` step) == 0 evalCronMatch (CronMatchContiguous from to) x = from <= x && x <= to evalCronMatch (CronMatchIntersect a b) x = evalCronMatch a x && evalCronMatch b x @@ -115,7 +112,7 @@ genMatch :: Int -- ^ Period -> [Natural] genMatch p m st CronMatchAny = take p $ map (bool id (succ . (`mod` fromIntegral p)) m) [st..] genMatch _ _ _ CronMatchNone = [] -genMatch p m _ (CronMatchSome set) = take p . map (bool id (succ . (`mod` fromIntegral p)) m) . Set.toAscList $ toNullable set +genMatch p m _ (CronMatchSome xs) = take p . map (bool id (succ . (`mod` fromIntegral p)) m) . Set.toAscList $ toNullable xs genMatch p m st (CronMatchStep step) = do start <- [st..st + step] guard $ (start `mod` step) == 0 @@ -135,9 +132,9 @@ genMatch p m st (CronMatchIntersect aGen bGen) mergeAnd [] _ = [] mergeAnd _ [] = [] mergeAnd (a:as) (b:bs) - | a < b = mergeAnd as (b:bs) - | a == b = a : mergeAnd as bs - | a > b = mergeAnd (a:as) bs + | a < b = mergeAnd as (b:bs) + | a == b = a : mergeAnd as bs + | otherwise = mergeAnd (a:as) bs genMatch p m st (CronMatchUnion CronMatchNone other) = genMatch p m st other genMatch p m st (CronMatchUnion other CronMatchNone) = genMatch p m st other genMatch p m st (CronMatchUnion CronMatchAny _) = genMatch p m st CronMatchAny @@ -147,9 +144,9 @@ genMatch p m st (CronMatchUnion aGen bGen) = merge (genMatch p m st aGen) (genMa merge [] bs = bs merge as [] = as merge (a:as) (b:bs) - | a < b = a : merge as (b:bs) - | a == b = a : merge as bs - | a > b = b : merge (a:as) bs + | a < b = a : merge as (b:bs) + | a == b = a : merge as bs + | otherwise = b : merge (a:as) bs nextCronMatch :: TZ -- ^ Timezone of the `Cron`-Entry -> Maybe UTCTime -- ^ Time of last execution of the job @@ -166,7 +163,6 @@ nextCronMatch tz mPrev now c@Cron{..} = case notAfter of | otherwise -> MatchNone MatchNone -> nextMatch where - nextMatch = nextCronMatch' tz mPrev now c notAfter | Right c' <- cronNotAfter , Just ref <- notAfterRef @@ -178,34 +174,34 @@ nextCronMatch tz mPrev now c@Cron{..} = case notAfter of notAfterRef | Just prevT <- mPrev = Just prevT | otherwise = case execRef' now False cronInitial of + MatchAsap -> error "execRef' should not return MatchAsap" MatchAt t -> Just t MatchNone -> Nothing - - nextCronMatch' tz mPrev now c@Cron{..} - | isNothing mPrev - = execRef now False cronInitial - | Just prevT <- mPrev - = case cronRepeat of - CronRepeatOnChange - | not $ matchesCron tz Nothing prevT c - -> let - cutoffTime = addUTCTime cronRateLimit prevT - in case execRef now False cronInitial of - MatchAsap - | now < cutoffTime -> MatchAt cutoffTime - MatchAt ts - | ts < cutoffTime -> MatchAt cutoffTime - other -> other - CronRepeatScheduled cronNext - -> case cronNext of - CronAsap - | addUTCTime cronRateLimit prevT <= now - -> MatchAsap - | otherwise - -> MatchAt $ addUTCTime cronRateLimit prevT - cronNext - -> execRef (addUTCTime cronRateLimit prevT) True cronNext - _other -> MatchNone + nextMatch = case mPrev of + Nothing + -> execRef now False cronInitial + Just prevT + -> case cronRepeat of + CronRepeatOnChange + | not $ matchesCron tz Nothing prevT c + -> let + cutoffTime = addUTCTime cronRateLimit prevT + in case execRef now False cronInitial of + MatchAsap + | now < cutoffTime -> MatchAt cutoffTime + MatchAt ts + | ts < cutoffTime -> MatchAt cutoffTime + other -> other + CronRepeatScheduled cronNext + -> case cronNext of + CronAsap + | addUTCTime cronRateLimit prevT <= now + -> MatchAsap + | otherwise + -> MatchAt $ addUTCTime cronRateLimit prevT + _other + -> execRef (addUTCTime cronRateLimit prevT) True cronNext + _other -> MatchNone execRef ref wasExecd cronAbsolute = case execRef' ref wasExecd cronAbsolute of MatchAt t @@ -219,19 +215,26 @@ nextCronMatch tz mPrev now c@Cron{..} = case notAfter of | otherwise -> MatchNone CronCalendar{..} -> listToMatch $ do let CronDate{..} = toCronDate $ utcToLocalTimeTZ tz ref - cronYear <- genMatch 400 False cdYear cronYear - cronWeekOfYear <- genMatch 53 True cdWeekOfYear cronWeekOfYear - cronDayOfYear <- genMatch 366 True cdDayOfYear cronDayOfYear - cronMonth <- genMatch 12 True cdMonth cronMonth - cronWeekOfMonth <- genMatch 5 True cdWeekOfMonth cronWeekOfMonth - cronDayOfMonth <- genMatch 31 True cdDayOfMonth cronDayOfMonth - cronDayOfWeek <- genMatch 7 True cdDayOfWeek cronDayOfWeek - cronHour <- genMatch 24 True cdHour cronHour - cronMinute <- genMatch 60 True cdMinute cronMinute - cronSecond <- genMatch 60 True cdSecond cronSecond - guard $ consistentCronDate CronDate{..} - localDay <- maybeToList $ fromGregorianValid (fromIntegral cronYear) (fromIntegral cronMonth) (fromIntegral cronDayOfMonth) - let localTimeOfDay = TimeOfDay (fromIntegral cronHour) (fromIntegral cronMinute) (fromIntegral cronSecond) + + mCronYear <- genMatch 400 False cdYear cronYear + mCronWeekOfYear <- genMatch 53 True cdWeekOfYear cronWeekOfYear + mCronDayOfYear <- genMatch 366 True cdDayOfYear cronDayOfYear + mCronMonth <- genMatch 12 True cdMonth cronMonth + mCronWeekOfMonth <- genMatch 5 True cdWeekOfMonth cronWeekOfMonth + mCronDayOfMonth <- genMatch 31 True cdDayOfMonth cronDayOfMonth + mCronDayOfWeek <- genMatch 7 True cdDayOfWeek cronDayOfWeek + mCronHour <- genMatch 24 True cdHour cronHour + mCronMinute <- genMatch 60 True cdMinute cronMinute + mCronSecond <- genMatch 60 True cdSecond cronSecond + guard $ consistentCronDate CronDate + { cdYear = mCronYear, cdMonth = mCronMonth, cdDayOfMonth = mCronDayOfMonth + , cdHour = mCronHour, cdMinute = mCronMinute, cdSecond = mCronSecond + , cdWeekOfYear = mCronWeekOfYear, cdWeekOfMonth = mCronWeekOfMonth + , cdDayOfYear = mCronDayOfYear, cdDayOfWeek = mCronDayOfWeek + } + + localDay <- maybeToList $ fromGregorianValid (fromIntegral mCronYear) (fromIntegral mCronMonth) (fromIntegral mCronDayOfMonth) + let localTimeOfDay = TimeOfDay (fromIntegral mCronHour) (fromIntegral mCronMinute) (fromIntegral mCronSecond) return $ localTimeToUTCTZ tz LocalTime{..} CronNotScheduled -> MatchNone diff --git a/src/Foundation.hs b/src/Foundation.hs index 4cb048b8d..ca40aa24a 100644 --- a/src/Foundation.hs +++ b/src/Foundation.hs @@ -1,4 +1,5 @@ {-# LANGUAGE UndecidableInstances #-} +{-# OPTIONS_GHC -fno-warn-orphans #-} -- MonadCrypto module Foundation where @@ -10,20 +11,18 @@ import Text.Jasmine (minifym) import qualified Web.ClientSession as ClientSession import Yesod.Auth.Message -import Yesod.Auth.Dummy import Auth.LDAP import Auth.PWHash import Auth.Dummy import Jobs.Types -import qualified Network.Wai as W (requestMethod, pathInfo) +import qualified Network.Wai as W (pathInfo) import Yesod.Default.Util (addStaticContentExternal) import Yesod.Core.Types (Logger) import qualified Yesod.Core.Unsafe as Unsafe import Data.CaseInsensitive (CI) import qualified Data.CaseInsensitive as CI -import qualified Data.Text.Encoding as TE import qualified Data.CryptoID as E @@ -40,12 +39,10 @@ import qualified Data.Text as Text import qualified Data.Text.Encoding as Text import Data.List (foldr1) -import qualified Data.List as List import Data.Set (Set) import qualified Data.Set as Set import Data.Map (Map, (!?)) import qualified Data.Map as Map -import Data.List (findIndex) import Data.Monoid (Any(..)) @@ -61,22 +58,14 @@ import Control.Monad.Trans.Maybe (MaybeT(..)) import Control.Monad.Trans.Reader (runReader, mapReaderT) import Control.Monad.Trans.Writer (WriterT(..)) import Control.Monad.Writer.Class (MonadWriter(..)) -import Control.Monad.Catch (handleAll) import qualified Control.Monad.Catch as C -import System.FilePath - -import Handler.Utils.Templates import Handler.Utils.StudyFeatures import Control.Lens -import Utils import Utils.Form -import Utils.Lens import Utils.SystemMessage import Data.Aeson hiding (Error, Success) -import Data.Aeson.TH -import qualified Data.Yaml as Yaml import Text.Shakespeare.Text (st) @@ -147,9 +136,11 @@ type MsgRenderer = MsgRendererS UniWorX -- see Utils type MailM a = MailT (HandlerT UniWorX IO) a -- Pattern Synonyms for convenience +pattern CSheetR :: TermId -> SchoolId -> CourseShorthand -> SheetName -> SheetR -> Route UniWorX pattern CSheetR tid ssh csh shn ptn = CourseR tid ssh csh (SheetR shn ptn) +pattern CSubmissionR :: TermId -> SchoolId -> CourseShorthand -> SheetName -> CryptoFileNameSubmission -> SubmissionR -> Route UniWorX pattern CSubmissionR tid ssh csh shn cid ptn = CSheetR tid ssh csh shn (SubmissionR cid ptn) @@ -212,9 +203,10 @@ instance RenderMessage UniWorX Load where newtype MsgLanguage = MsgLanguage Lang deriving (Eq, Ord, Show, Read) instance RenderMessage UniWorX MsgLanguage where - renderMessage foundation ls (MsgLanguage lang) - | lang == "de-DE" = mr MsgGermanGermany - | "de" `isPrefixOf` lang = mr MsgGerman + renderMessage foundation ls (MsgLanguage lang@(Text.splitOn "-" -> lang')) + | ["de", "DE"] <- lang' = mr MsgGermanGermany + | ("de" : _) <- lang' = mr MsgGerman + | otherwise = lang where mr = renderMessage foundation ls @@ -280,8 +272,8 @@ orAR _ _ AuthenticationRequired = AuthenticationRequired orAR mr (Unauthorized x) (Unauthorized y) = Unauthorized . render mr $ MsgUnauthorizedOr x y -- and andAR mr (Unauthorized x) (Unauthorized y) = Unauthorized . render mr $ MsgUnauthorizedAnd x y -andAR _ reason@(Unauthorized x) _ = reason -andAR _ _ reason@(Unauthorized x) = reason +andAR _ reason@(Unauthorized _) _ = reason +andAR _ _ reason@(Unauthorized _) = reason andAR _ Authorized other = other andAR _ AuthenticationRequired _ = AuthenticationRequired @@ -338,6 +330,14 @@ knownTags = Map.fromList -- should not throw exceptions, i.e. no getBy404 or req allow <- appAllowDeprecated . appSettings <$> getYesod return $ bool (Unauthorized "Deprecated Route") Authorized allow ) + ,("development", APHandler $ \r _ -> do + $logWarnS "AccessControl" ("route in development: " <> tshow r) +#ifdef DEVELOPMENT + return Authorized +#else + return $ Unauthorized "Route under development" +#endif + ) ,("lecturer", APDB $ \route _ -> case route of CourseR tid ssh csh _ -> exceptT return return $ do authId <- maybeExceptT AuthenticationRequired $ lift maybeAuthId @@ -406,7 +406,7 @@ knownTags = Map.fromList -- should not throw exceptions, i.e. no getBy404 or req return Authorized CourseR tid ssh csh CRegisterR -> maybeT (unauthorizedI MsgUnauthorizedCourseTime) $ do - Entity cid Course{..} <- MaybeT . getBy $ TermSchoolCourseShort tid ssh csh + Entity _ Course{courseRegisterFrom, courseRegisterTo} <- MaybeT . getBy $ TermSchoolCourseShort tid ssh csh cTime <- (NTop . Just) <$> liftIO getCurrentTime guard $ NTop courseRegisterFrom <= cTime && NTop courseRegisterTo >= cTime @@ -414,7 +414,7 @@ knownTags = Map.fromList -- should not throw exceptions, i.e. no getBy404 or req MessageR cID -> maybeT (unauthorizedI MsgUnauthorizedSystemMessageTime) $ do smId <- decrypt cID - SystemMessage{..} <- MaybeT $ get smId + SystemMessage{systemMessageFrom, systemMessageTo} <- MaybeT $ get smId cTime <- (NTop . Just) <$> liftIO getCurrentTime guard $ NTop systemMessageFrom <= cTime && NTop systemMessageTo >= cTime @@ -617,14 +617,14 @@ instance Yesod UniWorX where errPage = case err of NotFound -> [whamlet|

_{MsgErrorResponseNotFound}|] - InternalError err -> encrypted err [whamlet|

#{err}|] + InternalError err' -> encrypted err' [whamlet|

#{err'}|] InvalidArgs errs -> [whamlet|