module Conduit.Features.Account.Errors where

import Conduit.DB.Core (DBError(..))
import Conduit.Errors (FeatureError(..))
import Conduit.Validation (ValErrs(..))
import Network.HTTP.Types (status403, status404, status422, status500)
import Web.Scotty.Trans (ActionT, json, status)

data AccountError
  = UserNotFoundEx
  | CredsTaken [Text]
  | BadLoginCredsEx
  | SomeDBEx DBError
  deriving (Int -> AccountError -> ShowS
[AccountError] -> ShowS
AccountError -> String
(Int -> AccountError -> ShowS)
-> (AccountError -> String)
-> ([AccountError] -> ShowS)
-> Show AccountError
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> AccountError -> ShowS
showsPrec :: Int -> AccountError -> ShowS
$cshow :: AccountError -> String
show :: AccountError -> String
$cshowList :: [AccountError] -> ShowS
showList :: [AccountError] -> ShowS
Show, AccountError -> AccountError -> Bool
(AccountError -> AccountError -> Bool)
-> (AccountError -> AccountError -> Bool) -> Eq AccountError
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: AccountError -> AccountError -> Bool
== :: AccountError -> AccountError -> Bool
$c/= :: AccountError -> AccountError -> Bool
/= :: AccountError -> AccountError -> Bool
Eq)

instance FeatureError AccountError where
  handleFeatureError :: forall (m :: * -> *). MonadIO m => AccountError -> ActionT m ()
handleFeatureError = AccountError -> ActionT m ()
forall (m :: * -> *). MonadIO m => AccountError -> ActionT m ()
handleFeatureError'
  handleDBError :: DBError -> AccountError
handleDBError = DBError -> AccountError
handleDBErr'

handleFeatureError' :: (MonadIO m) => AccountError -> ActionT m ()
handleFeatureError' :: forall (m :: * -> *). MonadIO m => AccountError -> ActionT m ()
handleFeatureError' AccountError
UserNotFoundEx  = Status -> ActionT m ()
forall (m :: * -> *). MonadIO m => Status -> ActionT m ()
status Status
status404
handleFeatureError' (CredsTaken [Text]
cs) = Status -> ActionT m ()
forall (m :: * -> *). MonadIO m => Status -> ActionT m ()
status Status
status422 ActionT m () -> ActionT m () -> ActionT m ()
forall a b. ActionT m a -> ActionT m b -> ActionT m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ValErrs -> ActionT m ()
forall a (m :: * -> *). (ToJSON a, MonadIO m) => a -> ActionT m ()
json ([(Text, Text)] -> ValErrs
ValErrs ([(Text, Text)] -> ValErrs) -> [(Text, Text)] -> ValErrs
forall a b. (a -> b) -> a -> b
$ [Text]
cs [Text] -> (Text -> (Text, Text)) -> [(Text, Text)]
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> (,Text
"has already been taken"))
handleFeatureError' AccountError
BadLoginCredsEx = Status -> ActionT m ()
forall (m :: * -> *). MonadIO m => Status -> ActionT m ()
status Status
status403 ActionT m () -> ActionT m () -> ActionT m ()
forall a b. ActionT m a -> ActionT m b -> ActionT m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ValErrs -> ActionT m ()
forall a (m :: * -> *). (ToJSON a, MonadIO m) => a -> ActionT m ()
json ([(Text, Text)] -> ValErrs
ValErrs [(Text
"email or password", Text
"is invalid")])
handleFeatureError' (SomeDBEx DBError
e)    = DBError -> ActionT m ()
forall a (m :: * -> *). (MonadIO m, Show a) => a -> m ()
print DBError
e ActionT m () -> ActionT m () -> ActionT m ()
forall a b. ActionT m a -> ActionT m b -> ActionT m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Status -> ActionT m ()
forall (m :: * -> *). MonadIO m => Status -> ActionT m ()
status Status
status500

handleDBErr' :: DBError -> AccountError
handleDBErr' :: DBError -> AccountError
handleDBErr' (UniquenessError Text
"username") = [Text] -> AccountError
CredsTaken [Text
"username"]
handleDBErr' (UniquenessError Text
"email") = [Text] -> AccountError
CredsTaken [Text
"email"]
handleDBErr' (UniquenessError Text
_) = Text -> AccountError
forall a t. (HasCallStack, IsText t) => t -> a
error Text
"should never happen; no other uniqueness constraints exist"
handleDBErr' DBError
err = DBError -> AccountError
SomeDBEx DBError
err