diff options
Diffstat (limited to 'overlays/spm/lib')
-rw-r--r-- | overlays/spm/lib/Crypto/JWT/Instances.hs | 22 | ||||
-rw-r--r-- | overlays/spm/lib/Data/CaseInsensitive/Instances.hs | 22 | ||||
-rw-r--r-- | overlays/spm/lib/Data/UUID/Instances.hs | 18 | ||||
-rw-r--r-- | overlays/spm/lib/Spm.hs | 5 | ||||
-rw-r--r-- | overlays/spm/lib/Spm/Api.hs | 91 |
5 files changed, 158 insertions, 0 deletions
diff --git a/overlays/spm/lib/Crypto/JWT/Instances.hs b/overlays/spm/lib/Crypto/JWT/Instances.hs new file mode 100644 index 00000000..fa3c83b0 --- /dev/null +++ b/overlays/spm/lib/Crypto/JWT/Instances.hs | |||
@@ -0,0 +1,22 @@ | |||
1 | {-# OPTIONS_GHC -fno-warn-orphans #-} | ||
2 | |||
3 | module Crypto.JWT.Instances () where | ||
4 | |||
5 | import Prelude | ||
6 | import Control.Arrow | ||
7 | |||
8 | import Crypto.JWT | ||
9 | import Servant.API.ContentTypes | ||
10 | |||
11 | |||
12 | instance MimeRender PlainText SignedJWT where | ||
13 | mimeRender _ = encodeCompact | ||
14 | |||
15 | instance MimeRender OctetStream SignedJWT where | ||
16 | mimeRender _ = encodeCompact | ||
17 | |||
18 | instance MimeUnrender PlainText SignedJWT where | ||
19 | mimeUnrender _ = left (show @Error) . decodeCompact | ||
20 | |||
21 | instance MimeUnrender OctetStream SignedJWT where | ||
22 | mimeUnrender _ = left (show @Error) . decodeCompact | ||
diff --git a/overlays/spm/lib/Data/CaseInsensitive/Instances.hs b/overlays/spm/lib/Data/CaseInsensitive/Instances.hs new file mode 100644 index 00000000..1476b9d9 --- /dev/null +++ b/overlays/spm/lib/Data/CaseInsensitive/Instances.hs | |||
@@ -0,0 +1,22 @@ | |||
1 | {-# OPTIONS_GHC -fno-warn-orphans #-} | ||
2 | |||
3 | module Data.CaseInsensitive.Instances () where | ||
4 | |||
5 | import Prelude | ||
6 | |||
7 | import Data.CaseInsensitive (CI) | ||
8 | import qualified Data.CaseInsensitive as CI | ||
9 | |||
10 | import Servant.API.ContentTypes | ||
11 | |||
12 | import Data.Aeson | ||
13 | |||
14 | |||
15 | instance MimeRender PlainText a => MimeRender PlainText (CI a) where | ||
16 | mimeRender p = mimeRender p . CI.original | ||
17 | |||
18 | instance ToJSON a => ToJSON (CI a) where | ||
19 | toJSON = toJSON . CI.original | ||
20 | |||
21 | instance (FromJSON a, CI.FoldCase a) => FromJSON (CI a) where | ||
22 | parseJSON = fmap CI.mk . parseJSON | ||
diff --git a/overlays/spm/lib/Data/UUID/Instances.hs b/overlays/spm/lib/Data/UUID/Instances.hs new file mode 100644 index 00000000..335937d8 --- /dev/null +++ b/overlays/spm/lib/Data/UUID/Instances.hs | |||
@@ -0,0 +1,18 @@ | |||
1 | {-# OPTIONS_GHC -fno-warn-orphans #-} | ||
2 | |||
3 | module Data.UUID.Instances () where | ||
4 | |||
5 | import Prelude | ||
6 | import Data.UUID (UUID) | ||
7 | import qualified Data.UUID as UUID | ||
8 | import Servant.API.ContentTypes | ||
9 | |||
10 | |||
11 | instance MimeRender PlainText UUID where | ||
12 | mimeRender p = mimeRender p . UUID.toText | ||
13 | |||
14 | instance MimeRender JSON UUID where | ||
15 | mimeRender p = mimeRender p . UUID.toText | ||
16 | |||
17 | instance MimeRender OctetStream UUID where | ||
18 | mimeRender p = mimeRender p . UUID.toByteString | ||
diff --git a/overlays/spm/lib/Spm.hs b/overlays/spm/lib/Spm.hs new file mode 100644 index 00000000..c7f7dfe5 --- /dev/null +++ b/overlays/spm/lib/Spm.hs | |||
@@ -0,0 +1,5 @@ | |||
1 | module Spm | ||
2 | ( module Spm.Api | ||
3 | ) where | ||
4 | |||
5 | import Spm.Api | ||
diff --git a/overlays/spm/lib/Spm/Api.hs b/overlays/spm/lib/Spm/Api.hs new file mode 100644 index 00000000..14acfac4 --- /dev/null +++ b/overlays/spm/lib/Spm/Api.hs | |||
@@ -0,0 +1,91 @@ | |||
1 | {-# LANGUAGE TemplateHaskell, OverloadedStrings #-} | ||
2 | |||
3 | module Spm.Api | ||
4 | ( SpmStyle(..), _SpmWords, _SpmConsonants | ||
5 | , SpmMailbox | ||
6 | , SpmApi, spmApi | ||
7 | ) where | ||
8 | |||
9 | import Prelude | ||
10 | |||
11 | import Servant.API | ||
12 | |||
13 | import Data.Proxy (Proxy(..)) | ||
14 | |||
15 | import Data.Text (Text) | ||
16 | |||
17 | import GHC.Generics (Generic) | ||
18 | import Type.Reflection (Typeable) | ||
19 | |||
20 | import Control.Lens.TH | ||
21 | |||
22 | import Data.CaseInsensitive (CI) | ||
23 | import qualified Data.CaseInsensitive as CI | ||
24 | import Data.CaseInsensitive.Instances () | ||
25 | |||
26 | import Crypto.JOSE.JWK (JWKSet) | ||
27 | import Crypto.JWT (SignedJWT) | ||
28 | import Crypto.JWT.Instances () | ||
29 | |||
30 | import Data.UUID (UUID) | ||
31 | import Data.UUID.Instances () | ||
32 | |||
33 | -- import Data.Aeson (ToJSON, FromJSON) | ||
34 | |||
35 | |||
36 | data SpmStyle = SpmWords | SpmConsonants | ||
37 | deriving (Eq, Ord, Read, Show, Bounded, Enum) | ||
38 | makePrisms ''SpmStyle | ||
39 | |||
40 | instance ToHttpApiData SpmStyle where | ||
41 | toUrlPiece = \case | ||
42 | SpmWords -> "words" | ||
43 | SpmConsonants -> "consonants" | ||
44 | instance FromHttpApiData SpmStyle where | ||
45 | parseUrlPiece t@(CI.mk -> t') | ||
46 | | t' == "words" = Right SpmWords | ||
47 | | t' == "consonants" = Right SpmConsonants | ||
48 | | otherwise = Left $ "Expected one of ‘words’ or ‘consonants’ but got ‘" <> t <> "’" | ||
49 | |||
50 | |||
51 | newtype SpmMailbox = SpmMailbox { unSpmMailbox :: CI Text } | ||
52 | deriving stock (Eq, Ord, Read, Show, Generic, Typeable) | ||
53 | deriving newtype (MimeRender JSON, MimeRender PlainText) | ||
54 | makeWrapped ''SpmMailbox | ||
55 | -- newtype SpmLocal = SpmLocal | ||
56 | -- { unSpmLocal :: CI Text | ||
57 | -- } deriving stock (Eq, Ord, Read, Show, Generic, Typeable) | ||
58 | -- deriving newtype (ToJSON, FromJSON) | ||
59 | -- makeWrapped ''SpmLocal | ||
60 | -- newtype SpmExtension = SpmExtension | ||
61 | -- { unSpmExtension :: CI Text | ||
62 | -- } deriving stock (Eq, Ord, Read, Show, Generic, Typeable) | ||
63 | -- deriving newtype (ToJSON, FromJSON) | ||
64 | -- makeWrapped ''SpmExtension | ||
65 | |||
66 | -- newtype SpmMappingListing = SpmMappingListing { unSpmMappingListing :: Set SpmMapping } | ||
67 | -- deriving stock (Eq, Ord, Read, Show, Generic, Typeable) | ||
68 | -- instance ToJSON SpmMappingList where | ||
69 | -- toJSON SpmMappingListing{..} = object [ "mappings" .= unSpmMappingListing ] | ||
70 | |||
71 | -- data SpmMapping = SpmMapping | ||
72 | -- { spmMappingLocal :: Maybe SpmLocal | ||
73 | -- , spmMappingExtension :: Maybe SpmExtension | ||
74 | -- } deriving stock (Eq, Ord, Read, Show, Generic, Typeable) | ||
75 | -- instance ToJSON SpmMapping where | ||
76 | -- toJSON SpmMapping{..} = object | ||
77 | -- [ "local" .= spmMappingLocal | ||
78 | -- , "extension" .= spmMappingExtension | ||
79 | -- ] | ||
80 | |||
81 | type SpmApi = "whoami" :> Get '[PlainText, JSON] SpmMailbox | ||
82 | :<|> "jwks.json" :> Get '[JSON] JWKSet | ||
83 | :<|> "instance-id" :> Get '[PlainText, JSON, OctetStream] UUID | ||
84 | :<|> "spm" :> "generate" :> QueryParam "style" SpmStyle :> Get '[PlainText, JSON, OctetStream] SignedJWT | ||
85 | :<|> "spm" :> "claim" :> ReqBody '[PlainText, JSON, OctetStream] SignedJWT :> PostNoContent | ||
86 | -- :<|> "mappings" :> Get '[PlainText, JSON] SpmMappingListing | ||
87 | -- :<|> "mappings" :> Capture SpmMapping :> GetNoContent | ||
88 | -- :<|> "mappings" :> Capture SpmMapping :> DeleteNoContent | ||
89 | |||
90 | spmApi :: Proxy SpmApi | ||
91 | spmApi = Proxy | ||