git.mcksp
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
module Cookies
    ( setCookie
    , getCookie
    , getCookieFromHeader
    , setSession
    , deleteSession
    ) where

import Web.Cookie
import Web.Scotty.Trans
import Data.Text
import Utils
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Encoding as T
import Control.Monad.IO.Class (liftIO, MonadIO)
import Models
import Control.Monad.Reader (lift)
import Repos.Utils
import qualified Repos.Sessions as Sessions

setCookie :: MonadIO m => Text -> Text -> ActionT m ()
setCookie key value = addHeader "Set-Cookie" $
    TL.fromStrict . T.decodeUtf8 . renderSetCookieBS $ simpleCookie key value

simpleCookie :: Text -> Text -> SetCookie
simpleCookie key value =
    defaultSetCookie {
        setCookieName = T.encodeUtf8 key,
        setCookieValue = T.encodeUtf8 value,
        setCookieHttpOnly = True,
        setCookieSecure = True,
        setCookieSameSite = Just sameSiteLax
    }

getCookie :: Monad m => Text -> ActionT m (Maybe Text)
getCookie key = do
    rawCookie <- header "Cookie"
    return $ getCookieFromHeader (TL.toStrict <$> rawCookie) key

getCookieFromHeader :: Maybe Text -> Text -> Maybe Text
getCookieFromHeader rawCookie key = do
    let cookie = parseCookiesText . T.encodeUtf8 <$> rawCookie
    -- tutorial monad >>= TODO
    cookie >>= lookup key

setSession :: CanDB m => Text -> ActionT m ()
setSession userId = do
    -- tutorial functor
    session <- liftIO $ Session <$> uuid <*> pure userId <*> now
    -- TODO what when couldn't create session
    _ <- lift $ Sessions.create session
    setCookie "session" session.token

deleteSession :: CanDB m => ActionT m ()
deleteSession = do
    sessionId <- getCookie "session"
    -- tutorial mapM_ / maybe function
    lift $ mapM_ Sessions.delete sessionId
    -- TODO set expire at
    setCookie "session" ""