Bind to cryptoids

This commit is contained in:
Gregor Kleen 2017-10-10 14:30:48 +02:00
parent 62c2320aef
commit 9de9032916
13 changed files with 119 additions and 8 deletions

1
.gitignore vendored
View File

@ -2,6 +2,7 @@ dist*
static/tmp/ static/tmp/
static/combined/ static/combined/
client_session_key.aes client_session_key.aes
cryptoid_key.bf
*.hi *.hi
*.o *.o
*.sqlite3 *.sqlite3

View File

@ -32,5 +32,7 @@ database:
database: "_env:PGDATABASE:uniworx" database: "_env:PGDATABASE:uniworx"
poolsize: "_env:PGPOOLSIZE:10" poolsize: "_env:PGPOOLSIZE:10"
cryptoid-keyfile: "_env:CRYPTOID_KEYFILE:cryptoid_key.bf"
copyright: Insert copyright statement here copyright: Insert copyright statement here
#analytics: UA-YOURCODE #analytics: UA-YOURCODE

View File

@ -58,6 +58,13 @@ dependencies:
- filepath - filepath
- transformers - transformers
- wl-pprint-text - wl-pprint-text
- uuid-types
- path-pieces
- uuid-crypto
- cryptoids-types
- cryptoids
- binary
- mtl
# The library contains all of our application code. The executable # The library contains all of our application code. The executable
# defined below is just a thin wrapper. # defined below is just a thin wrapper.

2
routes
View File

@ -18,3 +18,5 @@
/course/#TermIdentifier/#Text/edit CourseEditExistR GET /course/#TermIdentifier/#Text/edit CourseEditExistR GET
/course/#TermIdentifier/#Text/show CourseShowR GET /course/#TermIdentifier/#Text/show CourseShowR GET
-- For demonstration
/course/#CryptoUUIDCourse/edit CourseEditExistIDR GET

View File

@ -55,14 +55,16 @@ mkYesodDispatch "UniWorX" resourcesUniWorX
-- the place to put your migrate statements to have automatic database -- the place to put your migrate statements to have automatic database
-- migrations handled by Yesod. -- migrations handled by Yesod.
makeFoundation :: AppSettings -> IO UniWorX makeFoundation :: AppSettings -> IO UniWorX
makeFoundation appSettings = do makeFoundation appSettings@(AppSettings{..}) = do
-- Some basic initializations: HTTP connection manager, logger, and static -- Some basic initializations: HTTP connection manager, logger, and static
-- subsite. -- subsite.
appHttpManager <- newManager appHttpManager <- newManager
appLogger <- newStdoutLoggerSet defaultBufSize >>= makeYesodLogger appLogger <- newStdoutLoggerSet defaultBufSize >>= makeYesodLogger
appStatic <- appStatic <-
(if appMutableStatic appSettings then staticDevel else static) (if appMutableStatic then staticDevel else static)
(appStaticDir appSettings) appStaticDir
appCryptoIDKey <- readKeyFile appCryptoIDKeyFile
-- We need a log function to create a connection pool. We need a connection -- We need a log function to create a connection pool. We need a connection
-- pool to create our foundation. And we need our foundation to get a -- pool to create our foundation. And we need our foundation to get a
@ -78,8 +80,8 @@ makeFoundation appSettings = do
-- Create the database connection pool -- Create the database connection pool
pool <- flip runLoggingT logFunc $ createPostgresqlPool pool <- flip runLoggingT logFunc $ createPostgresqlPool
(pgConnStr $ appDatabaseConf appSettings) (pgConnStr appDatabaseConf)
(pgPoolSize $ appDatabaseConf appSettings) (pgPoolSize appDatabaseConf)
-- Perform database migration using our application's logging settings. -- Perform database migration using our application's logging settings.
runLoggingT (runSqlPool (runMigration migrateAll) pool) logFunc runLoggingT (runSqlPool (runMigration migrateAll) pool) logFunc

36
src/CryptoID.hs Normal file
View File

@ -0,0 +1,36 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE FlexibleInstances, TypeSynonymInstances #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module CryptoID
( module CryptoID
, module Data.UUID.Cryptographic
, module Data.CryptoID.Poly
) where
import CryptoID.TH
import ClassyPrelude hiding (fromString)
import Model
import Data.CryptoID
import Data.CryptoID.Poly hiding (decrypt, encrypt)
import Data.UUID.Cryptographic
import Data.UUID.Types
import Web.PathPieces
instance PathPiece UUID where
fromPathPiece = fromString . unpack
toPathPiece = pack . toString
decKeysBinary [ ''SubmissionId
, ''CourseId
]
decTypeAliases [ "Submission"
, "Course"
]

38
src/CryptoID/TH.hs Normal file
View File

@ -0,0 +1,38 @@
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE ViewPatterns #-}
module CryptoID.TH where
import ClassyPrelude
import Language.Haskell.TH
import Data.CryptoID (CryptoID)
import Data.UUID.Types (UUID)
import Data.Binary (Binary(..))
import Database.Persist.Sql (toSqlKey, fromSqlKey)
decTypeAliases :: [String] -> Q [Dec]
decTypeAliases = return . concatMap decTypeAliases'
where
decTypeAliases' :: String -> [Dec]
decTypeAliases' n
= [ TySynD cryptoIDn [] $ ConT ''CryptoID `AppT` LitT (StrTyLit n)
, TySynD cryptoUUIDn [] $ ConT cryptoIDn `AppT` ConT ''UUID
]
where
cryptoIDn = mkName $ "CryptoID" ++ n
cryptoUUIDn = mkName $ "CryptoUUID" ++ n
decKeysBinary :: [Name] -> DecsQ
decKeysBinary = fmap concat . mapM decKeyBinary
where
decKeyBinary :: Name -> DecsQ
decKeyBinary (conT -> t)
= [d| instance Binary $(t) where
get = $(varE 'toSqlKey) <$> get
put = put . $(varE 'fromSqlKey)
|]

View File

@ -50,6 +50,7 @@ data UniWorX = UniWorX
, appConnPool :: ConnectionPool -- ^ Database connection pool. , appConnPool :: ConnectionPool -- ^ Database connection pool.
, appHttpManager :: Manager , appHttpManager :: Manager
, appLogger :: Logger , appLogger :: Logger
, appCryptoIDKey :: CryptoIDKey
} }
data MenuItem = MenuItem data MenuItem = MenuItem
@ -177,6 +178,7 @@ instance Yesod UniWorX where
isAuthorized (TermEditExistR _) _ = return Authorized isAuthorized (TermEditExistR _) _ = return Authorized
isAuthorized CourseEditR _ = return Authorized isAuthorized CourseEditR _ = return Authorized
isAuthorized (CourseEditExistR _ _) _ = return Authorized isAuthorized (CourseEditExistR _ _) _ = return Authorized
isAuthorized (CourseEditExistIDR _) _ = return Authorized

View File

@ -19,6 +19,8 @@ import Yesod.Form.Bootstrap3
import Colonnade import Colonnade
import Yesod.Colonnade import Yesod.Colonnade
import qualified Data.UUID.Cryptographic as UUID
getCourseListR :: Handler TypedContent getCourseListR :: Handler TypedContent
getCourseListR = redirect TermShowR getCourseListR = redirect TermShowR
@ -77,6 +79,12 @@ getCourseEditExistR tid csh = do
course <- runDB $ getBy $ CourseTermShort (TermKey tid) csh course <- runDB $ getBy $ CourseTermShort (TermKey tid) csh
courseEditHandler course courseEditHandler course
getCourseEditExistIDR :: CryptoUUIDCourse -> Handler Html
getCourseEditExistIDR cID = do
cIDKey <- getsYesod appCryptoIDKey
courseID <- UUID.decrypt cIDKey cID
courseEditHandler =<< runDB (getEntity courseID)
courseEditHandler :: Maybe (Entity Course) -> Handler Html courseEditHandler :: Maybe (Entity Course) -> Handler Html
courseEditHandler course = do courseEditHandler course = do

View File

@ -34,12 +34,16 @@ import Data.Text.Encoding.Error (UnicodeException(..))
import qualified Data.Text.Lazy.Encoding as Lazy.Text import qualified Data.Text.Lazy.Encoding as Lazy.Text
import qualified Data.ByteString.Lazy as Lazy (ByteString) import qualified Data.ByteString.Lazy as Lazy (ByteString)
import qualified Data.ByteString.Lazy as Lazy.ByteString
import Text.Read (readEither) import Text.Read (readEither)
import GHC.Generics (Generic) import GHC.Generics (Generic)
import Data.Typeable (Typeable) import Data.Typeable (Typeable)
import Data.Binary (encode, decode)
import qualified Data.CryptoID.Poly as Poly
instance HasResolution prec => Pretty (Fixed prec) where instance HasResolution prec => Pretty (Fixed prec) where
pretty = pretty . show pretty = pretty . show
@ -48,7 +52,7 @@ instance HasResolution prec => Pretty (Fixed prec) where
data Rating = Rating data Rating = Rating
{ ratingCourseName :: Text { ratingCourseName :: Text
, ratingSheetName :: Text , ratingSheetName :: Text
, ratingSubmissionId :: SubmissionId , ratingSubmissionId :: CryptoIDSubmission ByteString -- ^ 'SubmissionId'
, ratingComment :: Maybe Text , ratingComment :: Maybe Text
, ratingPoints :: Maybe Points , ratingPoints :: Maybe Points
} deriving (Read, Show, Eq, Generic, Typeable) } deriving (Read, Show, Eq, Generic, Typeable)
@ -67,10 +71,12 @@ instance Exception RatingException
getRating :: SubmissionId -> YesodDB UniWorX (Maybe Rating) getRating :: SubmissionId -> YesodDB UniWorX (Maybe Rating)
getRating ratingSubmissionId = runMaybeT $ do getRating submissionId = runMaybeT $ do
Submission{ submissionSheetId, submissionRatingComment = ratingComment, submissionRatingPoints = ratingPoints } <- MaybeT $ get ratingSubmissionId Submission{ submissionSheetId, submissionRatingComment = ratingComment, submissionRatingPoints = ratingPoints } <- MaybeT $ get submissionId
Sheet{ sheetCourseId, sheetName = ratingSheetName } <- MaybeT $ get submissionSheetId Sheet{ sheetCourseId, sheetName = ratingSheetName } <- MaybeT $ get submissionSheetId
Course{ courseName = ratingCourseName } <- MaybeT $ get sheetCourseId Course{ courseName = ratingCourseName } <- MaybeT $ get sheetCourseId
cIDKey <- getsYesod appCryptoIDKey
ratingSubmissionId <- Poly.encrypt cIDKey . Lazy.ByteString.toStrict $ encode submissionId
return Rating{..} return Rating{..}
formatRating :: Rating -> Lazy.ByteString formatRating :: Rating -> Lazy.ByteString

View File

@ -12,3 +12,5 @@ import Yesod.Core.Types as Import (loggerSet)
import Yesod.Default.Config2 as Import import Yesod.Default.Config2 as Import
import Data.Fixed as Import import Data.Fixed as Import
import CryptoID as Import

View File

@ -59,6 +59,7 @@ data AppSettings = AppSettings
-- ^ Copyright text to appear in the footer of the page -- ^ Copyright text to appear in the footer of the page
, appAnalytics :: Maybe Text , appAnalytics :: Maybe Text
-- ^ Google Analytics code -- ^ Google Analytics code
, appCryptoIDKeyFile :: FilePath
, appAuthDummyLogin :: Bool , appAuthDummyLogin :: Bool
-- ^ Indicate if auth dummy login should be enabled. -- ^ Indicate if auth dummy login should be enabled.
@ -87,6 +88,7 @@ instance FromJSON AppSettings where
appCopyright <- o .: "copyright" appCopyright <- o .: "copyright"
appAnalytics <- o .:? "analytics" appAnalytics <- o .:? "analytics"
appCryptoIDKeyFile <- o .: "cryptoid-keyfile"
appAuthDummyLogin <- o .:? "auth-dummy-login" .!= defaultDev appAuthDummyLogin <- o .:? "auth-dummy-login" .!= defaultDev

View File

@ -10,4 +10,7 @@ extra-deps:
- colonnade-1.1.1 - colonnade-1.1.1
- yesod-colonnade-1.1.0 - yesod-colonnade-1.1.0
- zip-stream-0.1.0.1 - zip-stream-0.1.0.1
- uuid-crypto-1.1.0
- cryptoids-0.1.0
- cryptoids-types-0.0.0
resolver: lts-9.3 resolver: lts-9.3