{-# LANGUAGE QuasiQuotes #-}

-- This file is part of the Wire Server implementation.
--
-- Copyright (C) 2020 Wire Swiss GmbH <opensource@wire.com>
--
-- This program is free software: you can redistribute it and/or modify it under
-- the terms of the GNU Affero General Public License as published by the Free
-- Software Foundation, either version 3 of the License, or (at your option) any
-- later version.
--
-- This program is distributed in the hope that it will be useful, but WITHOUT
-- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-- FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
-- details.
--
-- You should have received a copy of the GNU Affero General Public License along
-- with this program. If not, see <https://www.gnu.org/licenses/>.

module Web.Scim.Schema.ResourceType where

import Data.Aeson
import Data.Text (Text)
import GHC.Generics (Generic)
import Network.URI.Static
import Web.Scim.Schema.Common
import Web.Scim.Schema.Schema (Schema (..))
import Prelude hiding (map)

-- | Supported resource types. Each resource type also corresponds to an
-- endpoint, described by 'ResourceTypeEndpoint'.
data ResourceType
  = UserResource
  | GroupResource
  deriving (Int -> ResourceType -> ShowS
[ResourceType] -> ShowS
ResourceType -> String
(Int -> ResourceType -> ShowS)
-> (ResourceType -> String)
-> ([ResourceType] -> ShowS)
-> Show ResourceType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ResourceType] -> ShowS
$cshowList :: [ResourceType] -> ShowS
show :: ResourceType -> String
$cshow :: ResourceType -> String
showsPrec :: Int -> ResourceType -> ShowS
$cshowsPrec :: Int -> ResourceType -> ShowS
Show, ResourceType -> ResourceType -> Bool
(ResourceType -> ResourceType -> Bool)
-> (ResourceType -> ResourceType -> Bool) -> Eq ResourceType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: ResourceType -> ResourceType -> Bool
$c/= :: ResourceType -> ResourceType -> Bool
== :: ResourceType -> ResourceType -> Bool
$c== :: ResourceType -> ResourceType -> Bool
Eq, Int -> ResourceType
ResourceType -> Int
ResourceType -> [ResourceType]
ResourceType -> ResourceType
ResourceType -> ResourceType -> [ResourceType]
ResourceType -> ResourceType -> ResourceType -> [ResourceType]
(ResourceType -> ResourceType)
-> (ResourceType -> ResourceType)
-> (Int -> ResourceType)
-> (ResourceType -> Int)
-> (ResourceType -> [ResourceType])
-> (ResourceType -> ResourceType -> [ResourceType])
-> (ResourceType -> ResourceType -> [ResourceType])
-> (ResourceType -> ResourceType -> ResourceType -> [ResourceType])
-> Enum ResourceType
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: ResourceType -> ResourceType -> ResourceType -> [ResourceType]
$cenumFromThenTo :: ResourceType -> ResourceType -> ResourceType -> [ResourceType]
enumFromTo :: ResourceType -> ResourceType -> [ResourceType]
$cenumFromTo :: ResourceType -> ResourceType -> [ResourceType]
enumFromThen :: ResourceType -> ResourceType -> [ResourceType]
$cenumFromThen :: ResourceType -> ResourceType -> [ResourceType]
enumFrom :: ResourceType -> [ResourceType]
$cenumFrom :: ResourceType -> [ResourceType]
fromEnum :: ResourceType -> Int
$cfromEnum :: ResourceType -> Int
toEnum :: Int -> ResourceType
$ctoEnum :: Int -> ResourceType
pred :: ResourceType -> ResourceType
$cpred :: ResourceType -> ResourceType
succ :: ResourceType -> ResourceType
$csucc :: ResourceType -> ResourceType
Enum, ResourceType
ResourceType -> ResourceType -> Bounded ResourceType
forall a. a -> a -> Bounded a
maxBound :: ResourceType
$cmaxBound :: ResourceType
minBound :: ResourceType
$cminBound :: ResourceType
Bounded)

instance ToJSON ResourceType where
  toJSON :: ResourceType -> Value
toJSON ResourceType
UserResource = Value
"User"
  toJSON ResourceType
GroupResource = Value
"Group"

instance FromJSON ResourceType where
  parseJSON :: Value -> Parser ResourceType
parseJSON = String
-> (Text -> Parser ResourceType) -> Value -> Parser ResourceType
forall a. String -> (Text -> Parser a) -> Value -> Parser a
withText String
"ResourceType" ((Text -> Parser ResourceType) -> Value -> Parser ResourceType)
-> (Text -> Parser ResourceType) -> Value -> Parser ResourceType
forall a b. (a -> b) -> a -> b
$ \case
    Text
"User" -> ResourceType -> Parser ResourceType
forall (f :: * -> *) a. Applicative f => a -> f a
pure ResourceType
UserResource
    Text
"Group" -> ResourceType -> Parser ResourceType
forall (f :: * -> *) a. Applicative f => a -> f a
pure ResourceType
GroupResource
    Text
other -> String -> Parser ResourceType
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String
"unknown ResourceType: " String -> ShowS
forall a. [a] -> [a] -> [a]
++ Text -> String
forall a. Show a => a -> String
show Text
other)

-- | Definitions of endpoints, returned by @/ResourceTypes@.
data Resource = Resource
  { Resource -> Text
name :: Text,
    Resource -> URI
endpoint :: URI,
    Resource -> Schema
schema :: Schema
  }
  deriving (Int -> Resource -> ShowS
[Resource] -> ShowS
Resource -> String
(Int -> Resource -> ShowS)
-> (Resource -> String) -> ([Resource] -> ShowS) -> Show Resource
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Resource] -> ShowS
$cshowList :: [Resource] -> ShowS
show :: Resource -> String
$cshow :: Resource -> String
showsPrec :: Int -> Resource -> ShowS
$cshowsPrec :: Int -> Resource -> ShowS
Show, Resource -> Resource -> Bool
(Resource -> Resource -> Bool)
-> (Resource -> Resource -> Bool) -> Eq Resource
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Resource -> Resource -> Bool
$c/= :: Resource -> Resource -> Bool
== :: Resource -> Resource -> Bool
$c== :: Resource -> Resource -> Bool
Eq, (forall x. Resource -> Rep Resource x)
-> (forall x. Rep Resource x -> Resource) -> Generic Resource
forall x. Rep Resource x -> Resource
forall x. Resource -> Rep Resource x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Resource x -> Resource
$cfrom :: forall x. Resource -> Rep Resource x
Generic)

instance ToJSON Resource where
  toJSON :: Resource -> Value
toJSON = Options -> Resource -> Value
forall a.
(Generic a, GToJSON Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON Options
serializeOptions

instance FromJSON Resource where
  parseJSON :: Value -> Parser Resource
parseJSON = Options -> Value -> Parser Resource
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON Options
parseOptions (Value -> Parser Resource)
-> (Value -> Value) -> Value -> Parser Resource
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Value -> Value
jsonLower

----------------------------------------------------------------------------
-- Available resource endpoints

usersResource :: Resource
usersResource :: Resource
usersResource =
  Resource :: Text -> URI -> Schema -> Resource
Resource
    { name :: Text
name = Text
"User",
      endpoint :: URI
endpoint = URI -> URI
URI [relativeReference|/Users|],
      schema :: Schema
schema = Schema
User20
    }

groupsResource :: Resource
groupsResource :: Resource
groupsResource =
  Resource :: Text -> URI -> Schema -> Resource
Resource
    { name :: Text
name = Text
"Group",
      endpoint :: URI
endpoint = URI -> URI
URI [relativeReference|/Groups|],
      schema :: Schema
schema = Schema
Group20
    }