content: {-# LANGUAGE AllowAmbiguousTypes #-}
  
  {-|
  Module: IHP.Job.Dashboard.Auth
  Description:  Authentication for Job dashboard
  -}
  module IHP.Job.Dashboard.Auth (
      AuthenticationMethod(..),
      NoAuth(..),
      BasicAuth(..),
      BasicAuthStatic(..),
  ) where
  
  import IHP.Prelude
  import IHP.ControllerPrelude
  import qualified IHP.EnvVar as EnvVar
  
  -- | Defines one method, 'authenticate', called before every action. Use to authenticate user.
  --
  -- Three implementations are provided:
  -- - 'NoAuth' : No authentication
  -- - 'BasicAuth' : HTTP Basic Auth using environment variables
  -- - 'BasicAuthStatic' : HTTP Basic Auth using static values
  --
  -- Define your own implementation to use custom authentication for production.
  class AuthenticationMethod a where
      authenticate :: (?context :: ControllerContext, ?modelContext :: ModelContext) => IO ()
  
  -- | Don't use any authentication for jobs.
  data NoAuth
  
  -- | Authenticate using HTTP Basic Authentication by looking up username/password values
  -- in environment variables given as type-level strings.
  data BasicAuth (userEnv :: Symbol) (passEnv :: Symbol)
  
  -- | Authenticate using HTTP Basic Authentication using username/password given as type level strings.
  -- Meant for development only!
  data BasicAuthStatic (user :: Symbol) (pass :: Symbol)
  
  instance AuthenticationMethod NoAuth where
      authenticate = pure ()
  
  instance (KnownSymbol userEnv, KnownSymbol passEnv) => AuthenticationMethod (BasicAuth userEnv passEnv) where
      authenticate = do
          creds <- (,) <$> EnvVar.envOrNothing (symbolToByteString @userEnv) <*> EnvVar.envOrNothing (symbolToByteString @passEnv)
          case creds of
              (Just user, Just pass) -> basicAuth user pass "jobs"
              _ -> error "Did not find HTTP Basic Auth credentials for Jobs Dashboard."
  
  instance (KnownSymbol user, KnownSymbol pass) => AuthenticationMethod (BasicAuthStatic user pass) where
      authenticate = basicAuth (cs $ symbolVal $ Proxy @user) (cs $ symbolVal $ Proxy @pass) "jobs"
  
  