-- | Description: Interpreter for 'Authorize'
module Polysemy.Account.Api.Interpreter.Authorize where

import Exon (exon)

import Polysemy.Account.Api.Effect.Authorize (Authorize (Authorize))
import qualified Polysemy.Account.Data.AuthedAccount as AuthedAccount
import Polysemy.Account.Data.AuthedAccount (AuthedAccount (AuthedAccount))
import Polysemy.Account.Data.Privilege (Privilege)

-- | Interpret 'Authorize' using a monadic predicate.
interpretAuthorizeWith ::
  (param -> AuthedAccount i priv -> Sem r (Maybe Text)) ->
  InterpreterFor (Authorize i param priv) r
interpretAuthorizeWith :: forall param i priv (r :: EffectRow).
(param -> AuthedAccount i priv -> Sem r (Maybe Text))
-> InterpreterFor (Authorize i param priv) r
interpretAuthorizeWith param -> AuthedAccount i priv -> Sem r (Maybe Text)
check =
  forall (e :: (* -> *) -> * -> *) (r :: EffectRow) a.
FirstOrder e "interpret" =>
(forall (rInitial :: EffectRow) x. e (Sem rInitial) x -> Sem r x)
-> Sem (e : r) a -> Sem r a
interpret \case
    Authorize param
required AuthedAccount i priv
account ->
      param -> AuthedAccount i priv -> Sem r (Maybe Text)
check param
required AuthedAccount i priv
account

-- | Interpret 'Authorize' using 'Privilege' for both parameter and privilege types.
--
-- Simply verify that all parameter privileges are present in the account.
interpretAuthorizeP ::
  InterpreterFor (Authorize i [Privilege] [Privilege]) r
interpretAuthorizeP :: forall i (r :: EffectRow).
InterpreterFor (Authorize i [Privilege] [Privilege]) r
interpretAuthorizeP =
  forall (e :: (* -> *) -> * -> *) (r :: EffectRow) a.
FirstOrder e "interpret" =>
(forall (rInitial :: EffectRow) x. e (Sem rInitial) x -> Sem r x)
-> Sem (e : r) a -> Sem r a
interpret \case
    Authorize [Privilege]
required AuthedAccount {[Privilege]
$sel:privileges:AuthedAccount :: forall i p. AuthedAccount i p -> p
privileges :: [Privilege]
privileges} ->
      forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ case forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b c. (a -> b -> c) -> b -> a -> c
flip forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
elem [Privilege]
privileges) [Privilege]
required of
        [] -> forall a. Maybe a
Nothing
        [Privilege]
missing -> forall a. a -> Maybe a
Just [exon|Missing privileges: #{show missing}|]