module Hasura.RQL.DDL.InheritedRoles ( runAddInheritedRole, runDropInheritedRole, dropInheritedRoleInMetadata, resolveInheritedRole, ) where import Data.HashMap.Strict.InsOrd qualified as OMap import Data.HashSet qualified as Set import Data.Text.Extended import Hasura.Base.Error import Hasura.EncJSON import Hasura.Prelude import Hasura.RQL.Types import Hasura.Session runAddInheritedRole :: ( MonadError QErr m, CacheRWM m, MetadataM m ) => InheritedRole -> m EncJSON runAddInheritedRole addInheritedRoleQ@(Role inheritedRoleName (ParentRoles parentRoles)) = do when (inheritedRoleName `elem` parentRoles) $ throw400 InvalidParams "an inherited role name cannot be in the role combination" buildSchemaCacheFor (MOInheritedRole inheritedRoleName) $ MetadataModifier $ metaInheritedRoles %~ OMap.insert inheritedRoleName addInheritedRoleQ pure successMsg dropInheritedRoleInMetadata :: RoleName -> MetadataModifier dropInheritedRoleInMetadata roleName = MetadataModifier $ metaInheritedRoles %~ OMap.delete roleName runDropInheritedRole :: (MonadError QErr m, CacheRWM m, MetadataM m) => DropInheritedRole -> m EncJSON runDropInheritedRole (DropInheritedRole roleName) = do inheritedRolesMetadata <- _metaInheritedRoles <$> getMetadata unless (roleName `OMap.member` inheritedRolesMetadata) $ throw400 NotExists $ roleName <<> " inherited role doesn't exist" buildSchemaCacheFor (MOInheritedRole roleName) (dropInheritedRoleInMetadata roleName) pure successMsg -- | `resolveInheritedRole` resolves an inherited role by checking if -- all the parent roles of an inherited role exists and report -- the dependencies of the inherited role which will be the list -- of the parent roles resolveInheritedRole :: MonadError QErr m => HashSet RoleName -> InheritedRole -> m (Role, [SchemaDependency]) resolveInheritedRole allRoles (Role roleName (ParentRoles parentRoles)) = do let missingParentRoles = Set.filter (`notElem` allRoles) parentRoles unless (Set.null missingParentRoles) $ let errMessage roles = "the following parent role(s) are not found: " <> roles <> " which are required to construct the inherited role: " <>> roleName in throw400 NotExists $ errMessage $ commaSeparated $ Set.map roleNameToTxt missingParentRoles let schemaDependencies = map (\parentRole -> SchemaDependency (SORole parentRole) DRParentRole) $ toList parentRoles pure $ (Role roleName $ ParentRoles parentRoles, schemaDependencies)