module Session.KeySpec
( spec
) where
import Test.Prelude
import Data.Set qualified as Set
import Data.Text qualified as T
import Data.Text.Encoding (encodeUtf8)
import Session.Key
import Yesod.Session.Manager
spec :: Spec
spec = context "SessionKeyManager" $ do
specify "generates 24-character text"
$ forAll (genMockInit id)
$ \mockInit -> ioProperty $ do
Mock {sessionManager} <- newMock id mockInit
sessionKey <- newSessionKey sessionManager
pure $ T.length sessionKey.text == 24
specify "uses only letters, numbers, dash, underscore"
$ forAll (genMockInit id)
$ \mockInit -> ioProperty $ do
Mock {sessionManager} <- newMock id mockInit
sessionKey <- newSessionKey sessionManager
let charactersPresent = Set.fromList (T.unpack sessionKey.text)
pure $ charactersPresent `Set.isSubsetOf` charactersWanted
specify "never generates the same key twice"
$ forAll (genMockInit id)
$ \mockInit -> ioProperty $ do
Mock {sessionManager} <- newMock id mockInit
let n = 1000
sessionKeys <-
fmap Set.fromList
$ replicateM n
$ newSessionKey sessionManager
pure $ Set.size sessionKeys == n
specify "accepts its own keys"
$ forAll (genMockInit id)
$ \mockInit -> ioProperty $ do
Mock {sessionManager} <- newMock id mockInit
sessionKey <- newSessionKey sessionManager
pure $ sessionKeyAppearsReasonable sessionManager sessionKey
specify "does not accept invalid keys"
$ forAll (genMockInit id)
$ \mockInit -> ioProperty $ do
Mock {sessionManager} <- newMock id mockInit
pure
$ all
(isNothing . checkedSessionKeyFromCookieValue sessionManager)
someInvalidCookies
charactersWanted :: Set Char
charactersWanted =
foldMap Set.fromList [['a' .. 'z'], ['A' .. 'Z'], ['0' .. '9'], "-_"]
someInvalidSessionKeyTexts :: [Text]
someInvalidSessionKeyTexts =
[ ""
, "123456789-123456789-123"
, "123456789-123456789-12345"
, "aaaaaaaaaaaaaaaaaa*aaaaa"
]
someInvalidCookies :: [ByteString]
someInvalidCookies =
(encodeUtf8 <$> someInvalidSessionKeyTexts)
<> someInvalidUtf8ByteStrings
someInvalidUtf8ByteStrings :: [ByteString]
someInvalidUtf8ByteStrings =
[ "\xc3\x28"
, "\xa0\xa1"
, "\xe2\x28\xa1"
, "\xe2\x82\x28"
, "\xf0\x28\x8c\xbc"
, "\xf0\x90\x28\xbc"
, "\xf0\x28\x8c\x28"
]