@@ -1,10 +1,15 @@
1module Random.Token
2module Random.Token
3 , tokenToAscii
4 , tokenToAscii
4 , tokenToText
5 , tokenToText
5 , asciiToToken
6 , asciiToToken
6 , textToToken
7 , textToToken
7 , generateToken
11 , generateToken
10import Control.DeepSeq
15import Control.DeepSeq
@@ -19,16 +24,17 @@ import Data.Typeable
19import Test.QuickCheck.Arbitrary
24import Test.QuickCheck.Arbitrary
20import Web.HttpApiData
25import Web.HttpApiData
22import Crypto.Random as R
29import Crypto.Random as R
23import Database.PostgreSQL.Simple.FromField
30import Database.PostgreSQL.Simple.FromField
24import Database.PostgreSQL.Simple.ToField
31import Database.PostgreSQL.Simple.ToField
26-- | 16 bytes lenght random value parametrized by label.
34-- | 16 bytes lenght random value parametrized by label.
27newtype Token (a :: k) = Token ByteString
35newtype Token (a :: k) = Token ByteString
28 deriving (Ord, Eq, Show, NFData)
36 deriving (Ord, Eq, Show, NFData)
30−type role Token nominal
32instance Arbitrary (Token a) where
38instance Arbitrary (Token a) where
33 arbitrary = fmap (Token . BS.pack) $ sequence $ L.replicate 16 arbitrary
39 arbitrary = fmap (Token . BS.pack) $ sequence $ L.replicate 16 arbitrary
@@ -40,6 +46,7 @@ instance FromJSON (Token a) where
40instance ToJSON (Token a) where
46instance ToJSON (Token a) where
41 toJSON = toJSON . tokenToText
47 toJSON = toJSON . tokenToText
43instance forall a. (Typeable (Token a), Typeable a) => FromField (Token a) where
50instance forall a. (Typeable (Token a), Typeable a) => FromField (Token a) where
44 fromField fld bs = do
51 fromField fld bs = do
45 t <- fromField fld bs
52 t <- fromField fld bs
@@ -53,6 +60,8 @@ instance ToField (Token a) where
53generateToken :: (MonadRandom m) => m (Token a)
60generateToken :: (MonadRandom m) => m (Token a)
54generateToken = Token <$> R.getRandomBytes 16
61generateToken = Token <$> R.getRandomBytes 16
56instance FromHttpApiData (Token a) where
65instance FromHttpApiData (Token a) where
57 parseQueryParam = first T.pack . textToToken
66 parseQueryParam = first T.pack . textToToken
@@ -70,3 +79,9 @@ asciiToToken bs = Token <$> B64.decode bs
71textToToken :: Text -> Either String (Token a)
80textToToken :: Text -> Either String (Token a)
72textToToken = asciiToToken . T.encodeUtf8
81textToToken = asciiToToken . T.encodeUtf8
83+tokenWithContents :: Text -> Token a
84+tokenWithContents = Token . T.encodeUtf8
86+unsafeCoerceToken :: Token a -> Token b
87+unsafeCoerceToken (Token a) = Token a