-- SPDX-FileCopyrightText: 2024 Sarah Vaupel <sarah.vaupel@uniworx.de>
--
-- SPDX-License-Identifier: AGPL-3.0-or-later

{-# OPTIONS_GHC -fno-warn-orphans #-}

module Settings.Ldap
  ( LdapConf(..)
  , _ldapHost, _ldapDn, _ldapBase, _ldapScope, _ldapTimeout, _ldapSearchTimeout
  ) where

import ClassyPrelude

import Utils.Lens.TH

import Control.Monad.Fail (fail)

import Data.Aeson
import Data.Aeson.TH
import qualified Data.Text.Encoding as Text
import Data.Time.Clock

import qualified Ldap.Client as Ldap


data LdapConf = LdapConf
  { ldapHost     :: Ldap.Host
  , ldapPort     :: Ldap.PortNumber
  , ldapDn       :: Ldap.Dn
  , ldapPassword :: Ldap.Password
  , ldapBase     :: Ldap.Dn
  , ldapScope    :: Ldap.Scope
  , ldapTimeout  :: NominalDiffTime
  , ldapSearchTimeout :: Int32
  } deriving (Show)

makeLenses_ ''LdapConf

deriveFromJSON defaultOptions ''Ldap.Scope

instance FromJSON LdapConf where
  parseJSON = withObject "LdapConf" $ \o -> do
    ldapTls <- o .:? "tls"
    tlsSettings <- case ldapTls :: Maybe String of
      Just spec
        | spec == "insecure" -> return $ Just Ldap.insecureTlsSettings
        | spec == "default"  -> return $ Just Ldap.defaultTlsSettings
        | spec == "none"     -> return Nothing
        | spec == "notls"    -> return Nothing
        | null spec          -> return Nothing
      Nothing                -> return Nothing
      _otherwise             -> fail "Could not parse LDAP TLSSettings"
    ldapHost <- maybe Ldap.Plain (flip Ldap.Tls) tlsSettings <$> o .:? "host" .!= ""
    ldapPort <- (fromIntegral :: Int -> Ldap.PortNumber) <$> o .: "port"
    ldapDn <- Ldap.Dn <$> o .:? "user" .!= ""
    ldapPassword <- Ldap.Password . Text.encodeUtf8 <$> o .:? "pass" .!= ""
    ldapBase <- Ldap.Dn <$> o .:? "baseDN" .!= ""
    ldapScope <- o .: "scope"
    ldapTimeout <- o .: "timeout"
    ldapSearchTimeout <- o .: "search-timeout"
    return LdapConf{..}
