aboutsummaryrefslogtreecommitdiff
path: root/src/server/Controller/Index.hs
blob: 9fb2aa0823a628e0113693cb4f4f267ea5d3841c (plain)
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
module Controller.Index
  ( get
  , signOut
  ) where

import Control.Monad.IO.Class (liftIO)
import Data.Text (Text)
import Data.Time.Clock (getCurrentTime, diffUTCTime)
import Network.HTTP.Types.Status (ok200)
import Web.Scotty hiding (get)

import Conf (Conf(..))
import Model.Init (getInit)
import Model.Json.Init (InitResult(..))
import Model.Message.Key
import Model.User (User)
import qualified LoginSession
import qualified Model.Json.Conf as M
import qualified Model.Query as Query
import qualified Model.SignIn as SignIn
import qualified Model.User as User
import Secure (getUserFromToken)
import View.Page (page)

get :: Conf -> Maybe Text -> ActionM ()
get conf mbToken = do
  initResult <- case mbToken of
    Just token -> do
      userOrError <- validateSignIn conf token
      case userOrError of
        Left errorKey ->
          return . InitError $ errorKey
        Right user ->
          liftIO . Query.run . fmap InitSuccess . getInit $ user
    Nothing -> do
      mbLoggedUser <- getLoggedUser
      case mbLoggedUser of
        Nothing ->
          return InitEmpty
        Just user ->
          liftIO . Query.run . fmap InitSuccess . getInit $ user
  html $ page (M.Conf { M.currency = currency conf }) initResult

validateSignIn :: Conf -> Text -> ActionM (Either Key User)
validateSignIn conf textToken = do
  mbLoggedUser <- getLoggedUser
  case mbLoggedUser of
    Just loggedUser ->
      return . Right $ loggedUser
    Nothing -> do
      mbSignIn <- liftIO . Query.run $ SignIn.getSignIn textToken
      now <- liftIO getCurrentTime
      case mbSignIn of
        Nothing ->
          return . Left $ SignInInvalid
        Just signIn ->
          if SignIn.isUsed signIn
            then
              return . Left $ SignInUsed
            else
              let diffTime = now `diffUTCTime` (SignIn.creation signIn)
              in  if diffTime > signInExpiration conf
                    then
                      return . Left $ SignInExpired
                    else do
                      LoginSession.put conf (SignIn.token signIn)
                      mbUser <- liftIO . Query.run $ do
                        SignIn.signInTokenToUsed . SignIn.id $ signIn
                        User.getUser . SignIn.email $ signIn
                      return $ case mbUser of
                        Nothing -> Left UnauthorizedSignIn
                        Just user -> Right user

getLoggedUser :: ActionM (Maybe User)
getLoggedUser = do
  mbToken <- LoginSession.get
  case mbToken of
    Nothing ->
      return Nothing
    Just token -> do
      liftIO . Query.run . getUserFromToken $ token

signOut :: Conf -> ActionM ()
signOut conf = LoginSession.delete conf >> status ok200