blob: 31cd5105a37407f20495a7a8f88401f57b19a0b6 (
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
{-# LANGUAGE OverloadedStrings #-}
module Controller.SignIn
( signIn
, validateSignIn
) where
import Web.Scotty
import Network.HTTP.Types.Status (ok200)
import Database.Persist
import Control.Monad.IO.Class (liftIO)
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Encoding as TE
import Data.Time.Clock (getCurrentTime, diffUTCTime)
import Data.Maybe (isJust)
import qualified LoginSession
import Config
import SendMail
import Text.Email.Validate as Email
import Model.Database
import Model.User
import Model.SignIn
import Model.Message.Key
import Model.Message (getMessage)
import Json (jsonError)
import Secure (getUserFromToken)
import qualified View.Mail.SignIn as SignIn
signIn :: Config -> Text -> ActionM ()
signIn config login =
if Email.isValid (TE.encodeUtf8 login)
then do
maybeUser <- liftIO . runDb $ getUser login
case maybeUser of
Just user -> do
token <- liftIO . runDb $ createSignInToken login
let url = T.concat ["http://", hostname config, "/validateSignIn?token=", token]
maybeSentMail <- liftIO . sendMail $ SignIn.getMail (entityVal user) url [login]
case maybeSentMail of
Right _ ->
status ok200
Left _ ->
jsonError (getMessage SendEmailFail)
Nothing ->
jsonError (getMessage Unauthorized)
else
jsonError (getMessage EnterValidEmail)
validateSignIn :: Config -> Text -> ActionM ()
validateSignIn config textToken = do
alreadySigned <- isAlreadySigned
if alreadySigned
then
redirect "/"
else do
mbSignIn <- liftIO . runDb $ getSignInToken textToken
now <- liftIO getCurrentTime
case mbSignIn of
Just signIn ->
if signInIsUsed . entityVal $ signIn
then
redirectError (getMessage SignInUsed)
else
let diffTime = now `diffUTCTime` (signInCreation . entityVal $ signIn)
in if diffTime > (fromIntegral $ (signInExpirationMn config) * 60)
then
redirectError (getMessage SignInExpired)
else do
LoginSession.put (signInToken . entityVal $ signIn)
liftIO . runDb . signInTokenToUsed . entityKey $ signIn
redirect "/"
Nothing ->
redirectError (getMessage SignInInvalid)
isAlreadySigned :: ActionM Bool
isAlreadySigned = do
mbToken <- LoginSession.get
case mbToken of
Nothing ->
return False
Just token -> do
liftIO . runDb . fmap isJust $ getUserFromToken token
redirectError :: Text -> ActionM ()
redirectError msg =
redirect . TL.fromStrict . T.concat $ ["/?signInError=", msg]
|