{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}

-- |
-- Module      : Language.Github.Actions.Permissions
-- Description : GitHub Actions permissions and access control
-- Copyright   : (c) 2025 Bellroy Pty Ltd
-- License     : BSD-3-Clause
-- Maintainer  : Bellroy Tech Team <haskell@bellroy.com>
--
-- This module provides types for managing GitHub Actions permissions and access control.
-- Permissions control what GitHub APIs and resources workflows and jobs can access.
--
-- You can set permissions at the workflow level (affecting all jobs) or at individual
-- job levels. This follows the principle of least privilege by allowing you to grant
-- only the specific permissions needed.
--
-- For more information about GitHub Actions permissions, see:
-- <https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#permissions>
module Language.Github.Actions.Permissions
  ( Permissions (..),
    PermissionType (..),
    Permission (..),
    gen,
  )
where

import Control.Monad.Fail.Hoist (hoistFail')
import Data.Aeson (FromJSON, FromJSONKey, ToJSON, ToJSONKey)
import qualified Data.Aeson as Aeson
import qualified Data.Aeson.Types as Aeson
import Data.Map (Map)
import Data.String.Interpolate (i)
import Data.Text (Text)
import GHC.Generics (Generic)
import Hedgehog (MonadGen)
import qualified Hedgehog.Gen as Gen
import qualified Hedgehog.Range as Range
import Language.Github.Actions.Internal (inverseMap)

-- | Types of permissions that can be granted to GitHub Actions workflows.
--
-- Each permission type corresponds to a specific area of GitHub functionality
-- that workflows might need to access.
--
-- For more details about each permission type, see: <https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token>
data PermissionType
  = -- | Manage GitHub Actions (e.g., cancel workflow runs)
    Actions
  | -- | Create and verify attestations
    Attestations
  | -- | Create and update check runs and suites
    Checks
  | -- | Read and write repository contents
    Contents
  | -- | Create and manage deployments
    Deployments
  | -- | Request OIDC JWT ID tokens
    IdToken
  | -- | Create and manage issues
    Issues
  | -- | Create and manage discussions
    Discussions
  | -- | Publish and manage packages
    Packages
  | -- | Deploy to GitHub Pages
    Pages
  | -- | Create and manage pull requests
    PullRequests
  | -- | Manage repository projects
    RepositoryProjects
  | -- | Read and write security events
    SecurityEvents
  | -- | Create commit status checks
    Statuses
  deriving stock (PermissionType
PermissionType -> PermissionType -> Bounded PermissionType
forall a. a -> a -> Bounded a
$cminBound :: PermissionType
minBound :: PermissionType
$cmaxBound :: PermissionType
maxBound :: PermissionType
Bounded, Int -> PermissionType
PermissionType -> Int
PermissionType -> [PermissionType]
PermissionType -> PermissionType
PermissionType -> PermissionType -> [PermissionType]
PermissionType
-> PermissionType -> PermissionType -> [PermissionType]
(PermissionType -> PermissionType)
-> (PermissionType -> PermissionType)
-> (Int -> PermissionType)
-> (PermissionType -> Int)
-> (PermissionType -> [PermissionType])
-> (PermissionType -> PermissionType -> [PermissionType])
-> (PermissionType -> PermissionType -> [PermissionType])
-> (PermissionType
    -> PermissionType -> PermissionType -> [PermissionType])
-> Enum PermissionType
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: PermissionType -> PermissionType
succ :: PermissionType -> PermissionType
$cpred :: PermissionType -> PermissionType
pred :: PermissionType -> PermissionType
$ctoEnum :: Int -> PermissionType
toEnum :: Int -> PermissionType
$cfromEnum :: PermissionType -> Int
fromEnum :: PermissionType -> Int
$cenumFrom :: PermissionType -> [PermissionType]
enumFrom :: PermissionType -> [PermissionType]
$cenumFromThen :: PermissionType -> PermissionType -> [PermissionType]
enumFromThen :: PermissionType -> PermissionType -> [PermissionType]
$cenumFromTo :: PermissionType -> PermissionType -> [PermissionType]
enumFromTo :: PermissionType -> PermissionType -> [PermissionType]
$cenumFromThenTo :: PermissionType
-> PermissionType -> PermissionType -> [PermissionType]
enumFromThenTo :: PermissionType
-> PermissionType -> PermissionType -> [PermissionType]
Enum, PermissionType -> PermissionType -> Bool
(PermissionType -> PermissionType -> Bool)
-> (PermissionType -> PermissionType -> Bool) -> Eq PermissionType
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PermissionType -> PermissionType -> Bool
== :: PermissionType -> PermissionType -> Bool
$c/= :: PermissionType -> PermissionType -> Bool
/= :: PermissionType -> PermissionType -> Bool
Eq, (forall x. PermissionType -> Rep PermissionType x)
-> (forall x. Rep PermissionType x -> PermissionType)
-> Generic PermissionType
forall x. Rep PermissionType x -> PermissionType
forall x. PermissionType -> Rep PermissionType x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. PermissionType -> Rep PermissionType x
from :: forall x. PermissionType -> Rep PermissionType x
$cto :: forall x. Rep PermissionType x -> PermissionType
to :: forall x. Rep PermissionType x -> PermissionType
Generic, Eq PermissionType
Eq PermissionType =>
(PermissionType -> PermissionType -> Ordering)
-> (PermissionType -> PermissionType -> Bool)
-> (PermissionType -> PermissionType -> Bool)
-> (PermissionType -> PermissionType -> Bool)
-> (PermissionType -> PermissionType -> Bool)
-> (PermissionType -> PermissionType -> PermissionType)
-> (PermissionType -> PermissionType -> PermissionType)
-> Ord PermissionType
PermissionType -> PermissionType -> Bool
PermissionType -> PermissionType -> Ordering
PermissionType -> PermissionType -> PermissionType
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: PermissionType -> PermissionType -> Ordering
compare :: PermissionType -> PermissionType -> Ordering
$c< :: PermissionType -> PermissionType -> Bool
< :: PermissionType -> PermissionType -> Bool
$c<= :: PermissionType -> PermissionType -> Bool
<= :: PermissionType -> PermissionType -> Bool
$c> :: PermissionType -> PermissionType -> Bool
> :: PermissionType -> PermissionType -> Bool
$c>= :: PermissionType -> PermissionType -> Bool
>= :: PermissionType -> PermissionType -> Bool
$cmax :: PermissionType -> PermissionType -> PermissionType
max :: PermissionType -> PermissionType -> PermissionType
$cmin :: PermissionType -> PermissionType -> PermissionType
min :: PermissionType -> PermissionType -> PermissionType
Ord, Int -> PermissionType -> ShowS
[PermissionType] -> ShowS
PermissionType -> String
(Int -> PermissionType -> ShowS)
-> (PermissionType -> String)
-> ([PermissionType] -> ShowS)
-> Show PermissionType
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PermissionType -> ShowS
showsPrec :: Int -> PermissionType -> ShowS
$cshow :: PermissionType -> String
show :: PermissionType -> String
$cshowList :: [PermissionType] -> ShowS
showList :: [PermissionType] -> ShowS
Show)

instance FromJSON PermissionType where
  parseJSON :: Value -> Parser PermissionType
parseJSON =
    String
-> (Text -> Parser PermissionType)
-> Value
-> Parser PermissionType
forall a. String -> (Text -> Parser a) -> Value -> Parser a
Aeson.withText String
"PermissionType" ((Text -> Parser PermissionType) -> Value -> Parser PermissionType)
-> (Text -> Parser PermissionType)
-> Value
-> Parser PermissionType
forall a b. (a -> b) -> a -> b
$
      Either String PermissionType -> Parser PermissionType
forall (t :: * -> *) (m :: * -> *) a.
(PluckError String t m, MonadFail m) =>
t a -> m a
hoistFail' (Either String PermissionType -> Parser PermissionType)
-> (Text -> Either String PermissionType)
-> Text
-> Parser PermissionType
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Either String PermissionType
parsePermissionType

instance FromJSONKey PermissionType where
  fromJSONKey :: FromJSONKeyFunction PermissionType
fromJSONKey = (Text -> Parser PermissionType)
-> FromJSONKeyFunction PermissionType
forall a. (Text -> Parser a) -> FromJSONKeyFunction a
Aeson.FromJSONKeyTextParser (Value -> Parser PermissionType
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON (Value -> Parser PermissionType)
-> (Text -> Value) -> Text -> Parser PermissionType
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Value
Aeson.String)

instance ToJSON PermissionType where
  toJSON :: PermissionType -> Value
toJSON = Text -> Value
Aeson.String (Text -> Value)
-> (PermissionType -> Text) -> PermissionType -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. PermissionType -> Text
renderPermissionType

instance ToJSONKey PermissionType where
  toJSONKey :: ToJSONKeyFunction PermissionType
toJSONKey = (PermissionType -> Text) -> ToJSONKeyFunction PermissionType
forall a. (a -> Text) -> ToJSONKeyFunction a
Aeson.toJSONKeyText PermissionType -> Text
renderPermissionType

renderPermissionType :: PermissionType -> Text
renderPermissionType :: PermissionType -> Text
renderPermissionType = \case
  PermissionType
Actions -> Text
"actions"
  PermissionType
Attestations -> Text
"attestations"
  PermissionType
Checks -> Text
"checks"
  PermissionType
Contents -> Text
"contents"
  PermissionType
Deployments -> Text
"deployments"
  PermissionType
IdToken -> Text
"id-token"
  PermissionType
Issues -> Text
"issues"
  PermissionType
Discussions -> Text
"discussions"
  PermissionType
Packages -> Text
"packages"
  PermissionType
Pages -> Text
"pages"
  PermissionType
PullRequests -> Text
"pull-requests"
  PermissionType
RepositoryProjects -> Text
"repository-projects"
  PermissionType
SecurityEvents -> Text
"security-events"
  PermissionType
Statuses -> Text
"statuses"

parsePermissionType :: Text -> Either String PermissionType
parsePermissionType :: Text -> Either String PermissionType
parsePermissionType Text
t =
  Either String PermissionType
-> (PermissionType -> Either String PermissionType)
-> Maybe PermissionType
-> Either String PermissionType
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (String -> Either String PermissionType
forall a b. a -> Either a b
Left [i|Unknown PermissionType: #{t}|]) PermissionType -> Either String PermissionType
forall a b. b -> Either a b
Right (Maybe PermissionType -> Either String PermissionType)
-> Maybe PermissionType -> Either String PermissionType
forall a b. (a -> b) -> a -> b
$
    (PermissionType -> Text) -> Text -> Maybe PermissionType
forall a k. (Bounded a, Enum a, Ord k) => (a -> k) -> k -> Maybe a
inverseMap PermissionType -> Text
renderPermissionType Text
t

-- | Permission levels that can be granted for each permission type.
data Permission
  = -- | No access granted
    None
  | -- | Read-only access
    Read
  | -- | Read and write access
    Write
  deriving stock (Permission
Permission -> Permission -> Bounded Permission
forall a. a -> a -> Bounded a
$cminBound :: Permission
minBound :: Permission
$cmaxBound :: Permission
maxBound :: Permission
Bounded, Int -> Permission
Permission -> Int
Permission -> [Permission]
Permission -> Permission
Permission -> Permission -> [Permission]
Permission -> Permission -> Permission -> [Permission]
(Permission -> Permission)
-> (Permission -> Permission)
-> (Int -> Permission)
-> (Permission -> Int)
-> (Permission -> [Permission])
-> (Permission -> Permission -> [Permission])
-> (Permission -> Permission -> [Permission])
-> (Permission -> Permission -> Permission -> [Permission])
-> Enum Permission
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
$csucc :: Permission -> Permission
succ :: Permission -> Permission
$cpred :: Permission -> Permission
pred :: Permission -> Permission
$ctoEnum :: Int -> Permission
toEnum :: Int -> Permission
$cfromEnum :: Permission -> Int
fromEnum :: Permission -> Int
$cenumFrom :: Permission -> [Permission]
enumFrom :: Permission -> [Permission]
$cenumFromThen :: Permission -> Permission -> [Permission]
enumFromThen :: Permission -> Permission -> [Permission]
$cenumFromTo :: Permission -> Permission -> [Permission]
enumFromTo :: Permission -> Permission -> [Permission]
$cenumFromThenTo :: Permission -> Permission -> Permission -> [Permission]
enumFromThenTo :: Permission -> Permission -> Permission -> [Permission]
Enum, Permission -> Permission -> Bool
(Permission -> Permission -> Bool)
-> (Permission -> Permission -> Bool) -> Eq Permission
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Permission -> Permission -> Bool
== :: Permission -> Permission -> Bool
$c/= :: Permission -> Permission -> Bool
/= :: Permission -> Permission -> Bool
Eq, (forall x. Permission -> Rep Permission x)
-> (forall x. Rep Permission x -> Permission) -> Generic Permission
forall x. Rep Permission x -> Permission
forall x. Permission -> Rep Permission x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Permission -> Rep Permission x
from :: forall x. Permission -> Rep Permission x
$cto :: forall x. Rep Permission x -> Permission
to :: forall x. Rep Permission x -> Permission
Generic, Eq Permission
Eq Permission =>
(Permission -> Permission -> Ordering)
-> (Permission -> Permission -> Bool)
-> (Permission -> Permission -> Bool)
-> (Permission -> Permission -> Bool)
-> (Permission -> Permission -> Bool)
-> (Permission -> Permission -> Permission)
-> (Permission -> Permission -> Permission)
-> Ord Permission
Permission -> Permission -> Bool
Permission -> Permission -> Ordering
Permission -> Permission -> Permission
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Permission -> Permission -> Ordering
compare :: Permission -> Permission -> Ordering
$c< :: Permission -> Permission -> Bool
< :: Permission -> Permission -> Bool
$c<= :: Permission -> Permission -> Bool
<= :: Permission -> Permission -> Bool
$c> :: Permission -> Permission -> Bool
> :: Permission -> Permission -> Bool
$c>= :: Permission -> Permission -> Bool
>= :: Permission -> Permission -> Bool
$cmax :: Permission -> Permission -> Permission
max :: Permission -> Permission -> Permission
$cmin :: Permission -> Permission -> Permission
min :: Permission -> Permission -> Permission
Ord, Int -> Permission -> ShowS
[Permission] -> ShowS
Permission -> String
(Int -> Permission -> ShowS)
-> (Permission -> String)
-> ([Permission] -> ShowS)
-> Show Permission
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Permission -> ShowS
showsPrec :: Int -> Permission -> ShowS
$cshow :: Permission -> String
show :: Permission -> String
$cshowList :: [Permission] -> ShowS
showList :: [Permission] -> ShowS
Show)

instance FromJSON Permission where
  parseJSON :: Value -> Parser Permission
parseJSON =
    String -> (Text -> Parser Permission) -> Value -> Parser Permission
forall a. String -> (Text -> Parser a) -> Value -> Parser a
Aeson.withText String
"Permission" ((Text -> Parser Permission) -> Value -> Parser Permission)
-> (Text -> Parser Permission) -> Value -> Parser Permission
forall a b. (a -> b) -> a -> b
$
      Either String Permission -> Parser Permission
forall (t :: * -> *) (m :: * -> *) a.
(PluckError String t m, MonadFail m) =>
t a -> m a
hoistFail' (Either String Permission -> Parser Permission)
-> (Text -> Either String Permission) -> Text -> Parser Permission
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Either String Permission
parsePermission

instance ToJSON Permission where
  toJSON :: Permission -> Value
toJSON = Text -> Value
Aeson.String (Text -> Value) -> (Permission -> Text) -> Permission -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Permission -> Text
renderPermission

renderPermission :: Permission -> Text
renderPermission :: Permission -> Text
renderPermission = \case
  Permission
None -> Text
"none"
  Permission
Read -> Text
"read"
  Permission
Write -> Text
"write"

parsePermission :: Text -> Either String Permission
parsePermission :: Text -> Either String Permission
parsePermission Text
t =
  Either String Permission
-> (Permission -> Either String Permission)
-> Maybe Permission
-> Either String Permission
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (String -> Either String Permission
forall a b. a -> Either a b
Left [i|Unknown Permission: #{t}|]) Permission -> Either String Permission
forall a b. b -> Either a b
Right (Maybe Permission -> Either String Permission)
-> Maybe Permission -> Either String Permission
forall a b. (a -> b) -> a -> b
$
    (Permission -> Text) -> Text -> Maybe Permission
forall a k. (Bounded a, Enum a, Ord k) => (a -> k) -> k -> Maybe a
inverseMap Permission -> Text
renderPermission Text
t

-- | Overall permissions configuration for a workflow or job.
--
-- Permissions can be set globally (affecting all permission types) or
-- individually for specific permission types.
--
-- Example usage:
--
-- @
-- import Language.Github.Actions.Permissions
--
-- -- Grant read access to everything
-- readOnlyPerms :: Permissions
-- readOnlyPerms = ReadAll
--
-- -- Grant specific permissions only
-- customPerms :: Permissions
-- customPerms = Custom $ Map.fromList
--  [ (Contents, Read)
--  , (PullRequests, Write)
--  ]
-- @
data Permissions
  = -- | No permissions granted (empty object)
    NoPermissions
  | -- | Read access to all permission types
    ReadAll
  | -- | Write access to all permission types
    WriteAll
  | -- | Custom permission mapping
    Custom (Map PermissionType Permission)
  deriving stock (Permissions -> Permissions -> Bool
(Permissions -> Permissions -> Bool)
-> (Permissions -> Permissions -> Bool) -> Eq Permissions
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Permissions -> Permissions -> Bool
== :: Permissions -> Permissions -> Bool
$c/= :: Permissions -> Permissions -> Bool
/= :: Permissions -> Permissions -> Bool
Eq, (forall x. Permissions -> Rep Permissions x)
-> (forall x. Rep Permissions x -> Permissions)
-> Generic Permissions
forall x. Rep Permissions x -> Permissions
forall x. Permissions -> Rep Permissions x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. Permissions -> Rep Permissions x
from :: forall x. Permissions -> Rep Permissions x
$cto :: forall x. Rep Permissions x -> Permissions
to :: forall x. Rep Permissions x -> Permissions
Generic, Eq Permissions
Eq Permissions =>
(Permissions -> Permissions -> Ordering)
-> (Permissions -> Permissions -> Bool)
-> (Permissions -> Permissions -> Bool)
-> (Permissions -> Permissions -> Bool)
-> (Permissions -> Permissions -> Bool)
-> (Permissions -> Permissions -> Permissions)
-> (Permissions -> Permissions -> Permissions)
-> Ord Permissions
Permissions -> Permissions -> Bool
Permissions -> Permissions -> Ordering
Permissions -> Permissions -> Permissions
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Permissions -> Permissions -> Ordering
compare :: Permissions -> Permissions -> Ordering
$c< :: Permissions -> Permissions -> Bool
< :: Permissions -> Permissions -> Bool
$c<= :: Permissions -> Permissions -> Bool
<= :: Permissions -> Permissions -> Bool
$c> :: Permissions -> Permissions -> Bool
> :: Permissions -> Permissions -> Bool
$c>= :: Permissions -> Permissions -> Bool
>= :: Permissions -> Permissions -> Bool
$cmax :: Permissions -> Permissions -> Permissions
max :: Permissions -> Permissions -> Permissions
$cmin :: Permissions -> Permissions -> Permissions
min :: Permissions -> Permissions -> Permissions
Ord, Int -> Permissions -> ShowS
[Permissions] -> ShowS
Permissions -> String
(Int -> Permissions -> ShowS)
-> (Permissions -> String)
-> ([Permissions] -> ShowS)
-> Show Permissions
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Permissions -> ShowS
showsPrec :: Int -> Permissions -> ShowS
$cshow :: Permissions -> String
show :: Permissions -> String
$cshowList :: [Permissions] -> ShowS
showList :: [Permissions] -> ShowS
Show)

instance FromJSON Permissions where
  parseJSON :: Value -> Parser Permissions
parseJSON Value
v = case Value
v of
    Aeson.String Text
"{}" -> Permissions -> Parser Permissions
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Permissions
NoPermissions
    Aeson.String Text
"read-all" -> Permissions -> Parser Permissions
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Permissions
ReadAll
    Aeson.String Text
"write-all" -> Permissions -> Parser Permissions
forall a. a -> Parser a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Permissions
WriteAll
    Aeson.String Text
s -> String -> Parser Permissions
forall a. String -> Parser a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail [i|Invalid Permissions: #{s}|]
    Aeson.Object Object
o -> Map PermissionType Permission -> Permissions
Custom (Map PermissionType Permission -> Permissions)
-> Parser (Map PermissionType Permission) -> Parser Permissions
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Value -> Parser (Map PermissionType Permission)
forall a. FromJSON a => Value -> Parser a
Aeson.parseJSON (Object -> Value
Aeson.Object Object
o)
    Value
_ -> String -> Parser Permissions
forall a. String -> Parser a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Permissions must be a string or an object"

instance ToJSON Permissions where
  toJSON :: Permissions -> Value
toJSON = \case
    Permissions
NoPermissions -> Text -> Value
Aeson.String Text
"{}"
    Permissions
ReadAll -> Text -> Value
Aeson.String Text
"read-all"
    Permissions
WriteAll -> Text -> Value
Aeson.String Text
"write-all"
    Custom Map PermissionType Permission
m -> Map PermissionType Permission -> Value
forall a. ToJSON a => a -> Value
Aeson.toJSON Map PermissionType Permission
m

gen :: (MonadGen m) => m Permissions
gen :: forall (m :: * -> *). MonadGen m => m Permissions
gen =
  [m Permissions] -> m Permissions
forall (m :: * -> *) a. MonadGen m => [m a] -> m a
Gen.choice
    [ Permissions -> m Permissions
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Permissions
NoPermissions,
      Permissions -> m Permissions
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Permissions
ReadAll,
      Permissions -> m Permissions
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Permissions
WriteAll,
      (Map PermissionType Permission -> Permissions)
-> m (Map PermissionType Permission) -> m Permissions
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Map PermissionType Permission -> Permissions
Custom (m (Map PermissionType Permission) -> m Permissions)
-> (m (PermissionType, Permission)
    -> m (Map PermissionType Permission))
-> m (PermissionType, Permission)
-> m Permissions
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Range Int
-> m (PermissionType, Permission)
-> m (Map PermissionType Permission)
forall (m :: * -> *) k v.
(MonadGen m, Ord k) =>
Range Int -> m (k, v) -> m (Map k v)
Gen.map (Int -> Int -> Range Int
forall a. Integral a => a -> a -> Range a
Range.linear Int
1 Int
5) (m (PermissionType, Permission) -> m Permissions)
-> m (PermissionType, Permission) -> m Permissions
forall a b. (a -> b) -> a -> b
$
        (PermissionType -> Permission -> (PermissionType, Permission))
-> m PermissionType
-> m Permission
-> m (PermissionType, Permission)
forall a b c. (a -> b -> c) -> m a -> m b -> m c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 (,) m PermissionType
forall (m :: * -> *) a. (MonadGen m, Enum a, Bounded a) => m a
Gen.enumBounded m Permission
forall (m :: * -> *) a. (MonadGen m, Enum a, Bounded a) => m a
Gen.enumBounded
    ]