ebook-manager/backend/src/API/Users.hs

70 lines
2.4 KiB
Haskell
Raw Normal View History

2019-01-21 21:47:58 +02:00
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
2018-08-04 22:05:41 +03:00
module API.Users where
2018-08-03 23:36:38 +03:00
2018-11-12 21:32:42 +02:00
import ClassyPrelude
2019-01-21 21:47:58 +02:00
import Control.Monad.Catch (throwM)
2018-11-12 21:32:42 +02:00
import Data.Aeson
2019-01-21 21:47:58 +02:00
import Database (runDB)
2018-11-12 21:32:42 +02:00
import Database.Schema
import Database.User
import Servant
2019-01-21 21:47:58 +02:00
import Servant.Auth as SA
2018-11-12 21:32:42 +02:00
import Servant.Auth.Server as SAS
2019-01-21 21:47:58 +02:00
import qualified Servant.Docs as Docs
2018-11-12 21:32:42 +02:00
import Server.Auth
import Types
import Web.FormUrlEncoded
2018-08-03 23:36:38 +03:00
2019-01-21 21:47:58 +02:00
data RegisterForm = RegisterForm { username :: Username
, email :: Email
, password :: PlainPassword
2018-08-04 22:05:41 +03:00
, passwordAgain :: PlainPassword }
2018-08-03 23:36:38 +03:00
deriving (Generic, Show)
2018-11-12 21:32:42 +02:00
instance Docs.ToSample RegisterForm
2018-08-04 22:05:41 +03:00
data LoginStatus = LoginStatus ( Maybe SafeUser ) deriving Generic
2018-08-03 23:36:38 +03:00
data RegisterStatus = RegisterStatus deriving Generic
2018-11-12 21:32:42 +02:00
instance Docs.ToSample RegisterStatus
2018-08-03 23:36:38 +03:00
instance ToJSON LoginStatus
instance FromJSON LoginStatus
2018-11-12 21:32:42 +02:00
instance Docs.ToSample LoginStatus
2018-08-03 23:36:38 +03:00
instance FromJSON RegisterForm
instance ToJSON RegisterForm
instance ToJSON RegisterStatus
instance FromJSON RegisterStatus
instance FromForm RegisterForm
instance ToForm RegisterForm
2018-08-04 23:43:26 +03:00
2018-08-05 23:13:49 +03:00
type API = Auth '[SA.BasicAuth, SA.JWT] SafeUser :> "login" :> Get '[JSON] LoginStatus
2018-08-03 23:36:38 +03:00
:<|> "register" :> ReqBody '[JSON, FormUrlEncoded] RegisterForm :> Post '[JSON] RegisterStatus
handler :: ServerT API AppM
handler = loginHandler :<|> registerHandler
2018-08-04 23:43:26 +03:00
loginHandler :: AuthResult SafeUser -> AppM LoginStatus
loginHandler (Authenticated u) = return (LoginStatus (Just u))
2019-01-21 21:47:58 +02:00
loginHandler _ = return (LoginStatus Nothing)
2018-08-03 23:36:38 +03:00
registerHandler :: RegisterForm -> AppM RegisterStatus
registerHandler RegisterForm{..} =
case () of
() | password /= passwordAgain -> noMatch
| otherwise ->
2018-08-04 22:05:41 +03:00
either (const alreadyExists) (const (pure RegisterStatus)) =<< runDB (insertUser username email password)
2018-08-03 23:36:38 +03:00
where
noMatch = throwM err403{errBody = "passwords don't match"}
alreadyExists = throwM err403{errBody = "User already exists"}