diff --git a/core/datarekisteri-core.cabal b/core/datarekisteri-core.cabal index 601b097..9b007de 100644 --- a/core/datarekisteri-core.cabal +++ b/core/datarekisteri-core.cabal @@ -20,6 +20,7 @@ library morpheus-graphql-core, morpheus-graphql-server, persistent, + persistent-postgresql, relude, text, time, diff --git a/core/src/Datarekisteri/Core/Types.hs b/core/src/Datarekisteri/Core/Types.hs index 685cedd..39de52e 100644 --- a/core/src/Datarekisteri/Core/Types.hs +++ b/core/src/Datarekisteri/Core/Types.hs @@ -12,6 +12,7 @@ module Datarekisteri.Core.Types , Email , KeyID(..) , Permission(..) + , Permissions(..) , PhoneNumber , Scope(..) , Time(..) @@ -36,18 +37,21 @@ import Relude import qualified "base64" Data.ByteString.Base64 as B64 -import Data.Aeson (ToJSON(..), FromJSON(..)) +import Data.Aeson (Value, ToJSON(..), FromJSON(..), Result(..), ToJSONKey(..), FromJSONKey(..), FromJSONKeyFunction(..), ToJSONKeyFunction(..), fromJSON, eitherDecodeStrict) +import Data.Aeson.Encoding (string) import Data.Char (isSpace) -import Data.Morpheus.Server.Types (SCALAR) +import Data.Morpheus.Server.Types (SCALAR, TYPE) import Data.Morpheus.Types (GQLType, DecodeScalar(..), KIND, EncodeScalar(..), ScalarValue(..)) import Data.Morpheus.Types.GQLScalar (scalarToJSON, scalarFromJSON) import Data.Time (UTCTime, NominalDiffTime, addUTCTime, Day) import Data.Time.Format.ISO8601 (iso8601Show, iso8601ParseM) import Database.Persist.Class (PersistField(..)) import Database.Persist.PersistValue (PersistValue(..)) +import Database.Persist.Postgresql.JSON () -- persistent instances for Aeson's Value import Database.Persist.Sql (PersistFieldSql(..)) import Text.Email.Validate (EmailAddress, toByteString, validate, emailAddress) +import qualified Data.Map as Map import qualified Data.Text as T base64Encode :: ByteString -> Base64 @@ -95,6 +99,10 @@ instance EncodeScalar Scope where instance GQLType Scope where type KIND Scope = SCALAR instance ToJSON Scope where toJSON = scalarToJSON instance FromJSON Scope where parseJSON = scalarFromJSON <=< parseJSON +instance ToJSONKey Scope where toJSONKey = ToJSONKeyText (fromString . show) (string . show) +instance FromJSONKey Scope + where fromJSONKey = FromJSONKeyTextParser $ + either fail pure . (eitherDecodeStrict . encodeUtf8) data Permission = None | ReadOnly @@ -112,7 +120,24 @@ instance GQLType Permission where type KIND Permission = SCALAR instance ToJSON Permission where toJSON = scalarToJSON instance FromJSON Permission where parseJSON = scalarFromJSON <=< parseJSON -readPermission :: Text -> Maybe (Map Scope Permission) +newtype Permissions = Permissions (Map Scope Permission) + deriving (Show, Eq, Read, Generic, ToJSON, FromJSON, Semigroup, Monoid) + +instance GQLType Permissions where type KIND Permissions = TYPE + +instance PersistField Permissions where + toPersistValue = toPersistValue . toJSON + fromPersistValue = resultToEither . fromJSON <=< fromPersistValue + where resultToEither (Success x) = Right x + resultToEither (Error err) = Left $ T.pack err + +instance PersistFieldSql Permissions where sqlType _ = sqlType (Proxy :: Proxy Value) + +instance Ord Permissions where + (Permissions a) <= (Permissions b) = + and $ Map.intersectionWith (<=) a $ b <> (const None <$> Map.difference a b) + +readPermission :: Text -> Maybe Permissions readPermission = rightToMaybe . readEither . toString newtype PhoneNumber = PhoneNumber Text deriving (Show, Generic)