{-# OPTIONS_GHC -Wno-orphans #-}

-- | Functions and instances for authentication
module WebGear.OpenApi.Trait.Auth (addSecurityScheme) where

import Control.Lens ((&), (.~), (<>~))
import Control.Monad.State.Strict (MonadState)
import Data.OpenApi (
  Definitions,
  NamedSchema,
  OpenApi,
  Schema,
  SecurityDefinitions (..),
  SecurityRequirement (..),
  SecurityScheme,
  ToSchema (..),
  allOperations,
  components,
  description,
  security,
  securitySchemes,
 )
import Data.OpenApi.Declare (Declare)
import Data.Proxy (Proxy (..))
import Data.Text (Text)
import GHC.TypeLits (KnownSymbol)
import WebGear.Core.Handler (Description (..))
import WebGear.Core.Trait.Auth.Common (AuthToken)
import WebGear.OpenApi.Handler (Documentation (..), consumeDescription)

instance (KnownSymbol scheme) => ToSchema (AuthToken scheme) where
  declareNamedSchema :: Proxy (AuthToken scheme) -> Declare (Definitions Schema) NamedSchema
  declareNamedSchema :: Proxy (AuthToken scheme)
-> Declare (Definitions Schema) NamedSchema
declareNamedSchema Proxy (AuthToken scheme)
_ = Proxy String -> Declare (Definitions Schema) NamedSchema
forall a.
ToSchema a =>
Proxy a -> Declare (Definitions Schema) NamedSchema
declareNamedSchema (Proxy String -> Declare (Definitions Schema) NamedSchema)
-> Proxy String -> Declare (Definitions Schema) NamedSchema
forall a b. (a -> b) -> a -> b
$ forall t. Proxy t
forall {k} (t :: k). Proxy t
Proxy @String

addSecurityScheme :: (MonadState Documentation m) => Text -> SecurityScheme -> OpenApi -> m OpenApi
addSecurityScheme :: forall (m :: * -> *).
MonadState Documentation m =>
Text -> SecurityScheme -> OpenApi -> m OpenApi
addSecurityScheme Text
schemeName SecurityScheme
scheme OpenApi
doc = do
  Maybe Description
desc <- m (Maybe Description)
forall (m :: * -> *).
MonadState Documentation m =>
m (Maybe Description)
consumeDescription
  let scheme' :: SecurityScheme
scheme' = SecurityScheme
scheme SecurityScheme
-> (SecurityScheme -> SecurityScheme) -> SecurityScheme
forall a b. a -> (a -> b) -> b
& (Maybe Text -> Identity (Maybe Text))
-> SecurityScheme -> Identity SecurityScheme
forall s a. HasDescription s a => Lens' s a
Lens' SecurityScheme (Maybe Text)
description ((Maybe Text -> Identity (Maybe Text))
 -> SecurityScheme -> Identity SecurityScheme)
-> Maybe Text -> SecurityScheme -> SecurityScheme
forall s t a b. ASetter s t a b -> b -> s -> t
.~ (Description -> Text) -> Maybe Description -> Maybe Text
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Description -> Text
getDescription Maybe Description
desc
      secSchemes :: SecurityDefinitions
secSchemes = Definitions SecurityScheme -> SecurityDefinitions
SecurityDefinitions [(Text
schemeName, SecurityScheme
scheme')]
      secReqs :: [SecurityRequirement]
secReqs = [InsOrdHashMap Text [Text] -> SecurityRequirement
SecurityRequirement [(Text
schemeName, [])]] :: [SecurityRequirement]
  OpenApi -> m OpenApi
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (OpenApi -> m OpenApi) -> OpenApi -> m OpenApi
forall a b. (a -> b) -> a -> b
$
    OpenApi
doc
      OpenApi -> (OpenApi -> OpenApi) -> OpenApi
forall a b. a -> (a -> b) -> b
& (Components -> Identity Components) -> OpenApi -> Identity OpenApi
forall s a. HasComponents s a => Lens' s a
Lens' OpenApi Components
components ((Components -> Identity Components)
 -> OpenApi -> Identity OpenApi)
-> ((SecurityDefinitions -> Identity SecurityDefinitions)
    -> Components -> Identity Components)
-> (SecurityDefinitions -> Identity SecurityDefinitions)
-> OpenApi
-> Identity OpenApi
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SecurityDefinitions -> Identity SecurityDefinitions)
-> Components -> Identity Components
forall s a. HasSecuritySchemes s a => Lens' s a
Lens' Components SecurityDefinitions
securitySchemes ((SecurityDefinitions -> Identity SecurityDefinitions)
 -> OpenApi -> Identity OpenApi)
-> SecurityDefinitions -> OpenApi -> OpenApi
forall a s t. Semigroup a => ASetter s t a a -> a -> s -> t
<>~ SecurityDefinitions
secSchemes
      OpenApi -> (OpenApi -> OpenApi) -> OpenApi
forall a b. a -> (a -> b) -> b
& (Operation -> Identity Operation) -> OpenApi -> Identity OpenApi
Traversal' OpenApi Operation
allOperations ((Operation -> Identity Operation) -> OpenApi -> Identity OpenApi)
-> (([SecurityRequirement] -> Identity [SecurityRequirement])
    -> Operation -> Identity Operation)
-> ([SecurityRequirement] -> Identity [SecurityRequirement])
-> OpenApi
-> Identity OpenApi
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([SecurityRequirement] -> Identity [SecurityRequirement])
-> Operation -> Identity Operation
forall s a. HasSecurity s a => Lens' s a
Lens' Operation [SecurityRequirement]
security (([SecurityRequirement] -> Identity [SecurityRequirement])
 -> OpenApi -> Identity OpenApi)
-> [SecurityRequirement] -> OpenApi -> OpenApi
forall a s t. Semigroup a => ASetter s t a a -> a -> s -> t
<>~ [SecurityRequirement]
secReqs