mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-17 12:31:52 +03:00
9ef603360c
Co-authored-by: Vamshi Surabhi <vamshi@hasura.io> Co-authored-by: Vladimir Ciobanu <admin@cvlad.info> Co-authored-by: Antoine Leblanc <antoine@hasura.io> Co-authored-by: Stylish Haskell Bot <stylish-haskell@users.noreply.github.com> GitOrigin-RevId: 9d631878037637f3ed2994b5d0525efd978f7b8f
118 lines
5.0 KiB
Haskell
118 lines
5.0 KiB
Haskell
{-# LANGUAGE Arrows #-}
|
|
|
|
module Hasura.RQL.DDL.Schema.Cache.Permission
|
|
( buildTablePermissions
|
|
, mkPermissionMetadataObject
|
|
, mkRemoteSchemaPermissionMetadataObject
|
|
) where
|
|
|
|
import Hasura.Prelude
|
|
|
|
import qualified Data.HashMap.Strict.Extended as M
|
|
import qualified Data.Sequence as Seq
|
|
|
|
import Control.Arrow.Extended
|
|
import Data.Aeson
|
|
import Data.Text.Extended
|
|
|
|
import qualified Hasura.Incremental as Inc
|
|
|
|
import Hasura.RQL.DDL.Permission
|
|
import Hasura.RQL.DDL.Permission.Internal
|
|
import Hasura.RQL.DDL.Schema.Cache.Common
|
|
import Hasura.RQL.Types
|
|
import Hasura.Session
|
|
|
|
buildTablePermissions
|
|
:: ( ArrowChoice arr, Inc.ArrowDistribute arr, Inc.ArrowCache m arr
|
|
, MonadError QErr m, ArrowWriter (Seq CollectedInfo) arr
|
|
, BackendMetadata b)
|
|
=> ( SourceName
|
|
, Inc.Dependency (TableCoreCache b)
|
|
, FieldInfoMap (FieldInfo b)
|
|
, TablePermissionInputs b
|
|
) `arr` (RolePermInfoMap b)
|
|
buildTablePermissions = Inc.cache proc (source, tableCache, tableFields, tablePermissions) -> do
|
|
let alignedPermissions = alignPermissions tablePermissions
|
|
table = _tpiTable tablePermissions
|
|
|
|
(| Inc.keyed (\_ (insertPermission, selectPermission, updatePermission, deletePermission) -> do
|
|
insert <- buildPermission -< (tableCache, source, table, tableFields, listToMaybe insertPermission)
|
|
select <- buildPermission -< (tableCache, source, table, tableFields, listToMaybe selectPermission)
|
|
update <- buildPermission -< (tableCache, source, table, tableFields, listToMaybe updatePermission)
|
|
delete <- buildPermission -< (tableCache, source, table, tableFields, listToMaybe deletePermission)
|
|
returnA -< RolePermInfo insert select update delete)
|
|
|) alignedPermissions
|
|
where
|
|
mkMap :: [PermDef a] -> HashMap RoleName (PermDef a)
|
|
mkMap = mapFromL _pdRole
|
|
|
|
alignPermissions TablePermissionInputs{..} =
|
|
let insertsMap = M.map (\a -> ([a], [], [], [])) (mkMap _tpiInsert)
|
|
selectsMap = M.map (\a -> ([], [a], [], [])) (mkMap _tpiSelect)
|
|
updatesMap = M.map (\a -> ([], [], [a], [])) (mkMap _tpiUpdate)
|
|
deletesMap = M.map (\a -> ([], [], [], [a])) (mkMap _tpiDelete)
|
|
unionMap = M.unionWith (<>)
|
|
in insertsMap `unionMap` selectsMap `unionMap` updatesMap `unionMap` deletesMap
|
|
|
|
mkPermissionMetadataObject
|
|
:: forall a b. (Backend b, IsPerm b a)
|
|
=> SourceName -> TableName b -> PermDef a -> MetadataObject
|
|
mkPermissionMetadataObject source table permDef =
|
|
let permType = permAccToType (permAccessor :: PermAccessor b (PermInfo b a))
|
|
objectId = MOSourceObjId source $
|
|
SMOTableObj table $ MTOPerm (_pdRole permDef) permType
|
|
definition = toJSON $ WithTable source table permDef
|
|
in MetadataObject objectId definition
|
|
|
|
mkRemoteSchemaPermissionMetadataObject
|
|
:: AddRemoteSchemaPermissions
|
|
-> MetadataObject
|
|
mkRemoteSchemaPermissionMetadataObject (AddRemoteSchemaPermissions rsName roleName defn _) =
|
|
let objectId = MORemoteSchemaPermissions rsName roleName
|
|
in MetadataObject objectId $ toJSON defn
|
|
|
|
withPermission
|
|
:: forall a b c s arr bknd. (ArrowChoice arr, ArrowWriter (Seq CollectedInfo) arr, IsPerm bknd c, Backend bknd)
|
|
=> WriterA (Seq SchemaDependency) (ErrorA QErr arr) (a, s) b
|
|
-> arr (a, ((SourceName, TableName bknd, PermDef c), s)) (Maybe b)
|
|
withPermission f = proc (e, ((source, table, permission), s)) -> do
|
|
let metadataObject = mkPermissionMetadataObject source table permission
|
|
permType = permAccToType (permAccessor :: PermAccessor bknd (PermInfo bknd c))
|
|
roleName = _pdRole permission
|
|
schemaObject = SOSourceObj source $
|
|
SOITableObj table $ TOPerm roleName permType
|
|
addPermContext err = "in permission for role " <> roleName <<> ": " <> err
|
|
(| withRecordInconsistency (
|
|
(| withRecordDependencies (
|
|
(| modifyErrA (f -< (e, s))
|
|
|) (addTableContext table . addPermContext))
|
|
|) metadataObject schemaObject)
|
|
|) metadataObject
|
|
|
|
buildPermission
|
|
:: ( ArrowChoice arr, Inc.ArrowCache m arr
|
|
, ArrowWriter (Seq CollectedInfo) arr
|
|
, MonadError QErr m, IsPerm b a
|
|
, Inc.Cacheable a
|
|
, BackendMetadata b
|
|
)
|
|
=> ( Inc.Dependency (TableCoreCache b)
|
|
, SourceName
|
|
, TableName b
|
|
, FieldInfoMap (FieldInfo b)
|
|
, Maybe (PermDef a)
|
|
) `arr` Maybe (PermInfo b a)
|
|
buildPermission = Inc.cache proc (tableCache, source, table, tableFields, maybePermission) -> do
|
|
(| traverseA ( \permission ->
|
|
(| withPermission (do
|
|
bindErrorA -< when (_pdRole permission == adminRoleName) $
|
|
throw400 ConstraintViolation "cannot define permission for admin role"
|
|
(info, dependencies) <- liftEitherA <<< Inc.bindDepend -< runExceptT $
|
|
runTableCoreCacheRT (buildPermInfo source table tableFields permission) (source, tableCache)
|
|
tellA -< Seq.fromList dependencies
|
|
returnA -< info)
|
|
|) (source, table, permission))
|
|
|) maybePermission
|
|
>-> (\info -> join info >- returnA)
|