graphql-engine/server/src-lib/Hasura/RQL/DDL/Permission/Internal.hs

125 lines
3.6 KiB
Haskell
Raw Normal View History

2018-06-27 16:11:32 +03:00
{-# LANGUAGE TypeFamilyDependencies #-}
module Hasura.RQL.DDL.Permission.Internal where
2020-08-27 19:36:39 +03:00
import Hasura.Prelude
import qualified Data.HashMap.Strict as M
import qualified Data.Text as T
2020-08-27 19:36:39 +03:00
import Control.Lens hiding ((.=))
2018-06-27 16:11:32 +03:00
import Data.Aeson.TH
import Data.Aeson.Types
import Data.Text.Extended
import Hasura.Backends.Postgres.Translate.BoolExp
2018-06-27 16:11:32 +03:00
import Hasura.RQL.Types
import Hasura.Server.Utils
import Hasura.Session
2018-06-27 16:11:32 +03:00
convColSpec :: FieldInfoMap (FieldInfo b) -> PermColSpec b -> [Column b]
2018-06-27 16:11:32 +03:00
convColSpec _ (PCCols cols) = cols
convColSpec cim PCStar = map pgiColumn $ getCols cim
2018-06-27 16:11:32 +03:00
permissionIsDefined
:: Maybe (RolePermInfo backend) -> PermAccessor backend a -> Bool
2018-06-27 16:11:32 +03:00
permissionIsDefined rpi pa =
isJust $ join $ rpi ^? _Just.permAccToLens pa
2018-06-27 16:11:32 +03:00
assertPermDefined
:: (Backend backend, MonadError QErr m)
2018-06-27 16:11:32 +03:00
=> RoleName
-> PermAccessor backend a
-> TableInfo backend
2018-06-27 16:11:32 +03:00
-> m ()
assertPermDefined roleName pa tableInfo =
unless (permissionIsDefined rpi pa) $ throw400 PermissionDenied $ mconcat
[ "'" <> tshow (permAccToType pa) <> "'"
, " permission on " <>> _tciName (_tiCoreInfo tableInfo)
2018-06-27 16:11:32 +03:00
, " for role " <>> roleName
, " does not exist"
]
where
rpi = M.lookup roleName $ _tiRolePermInfoMap tableInfo
2018-06-27 16:11:32 +03:00
askPermInfo
:: (Backend backend, MonadError QErr m)
=> TableInfo backend
2018-06-27 16:11:32 +03:00
-> RoleName
-> PermAccessor backend c
2018-06-27 16:11:32 +03:00
-> m c
askPermInfo tabInfo roleName pa =
(M.lookup roleName rpim >>= (^. permAccToLens pa))
`onNothing`
throw400 PermissionDenied
(mconcat
[ pt <> " permission on " <>> _tciName (_tiCoreInfo tabInfo)
, " for role " <>> roleName
, " does not exist"
])
2018-06-27 16:11:32 +03:00
where
pt = permTypeToCode $ permAccToType pa
rpim = _tiRolePermInfoMap tabInfo
2018-06-27 16:11:32 +03:00
type CreatePerm b a = WithTable b (PermDef a)
2018-06-27 16:11:32 +03:00
data CreatePermP1Res a
= CreatePermP1Res
{ cprInfo :: !a
, cprDeps :: ![SchemaDependency]
} deriving (Show, Eq)
procBoolExp
:: (QErrM m, TableCoreInfoRM b m, BackendMetadata b)
=> SourceName
-> TableName b
-> FieldInfoMap (FieldInfo b)
-> BoolExp b
-> m (AnnBoolExpPartialSQL b, [SchemaDependency])
procBoolExp source tn fieldInfoMap be = do
abe <- annBoolExp parseCollectableType fieldInfoMap $ unBoolExp be
let deps = getBoolExpDeps source tn abe
return (abe, deps)
2018-06-27 16:11:32 +03:00
isReqUserId :: Text -> Bool
isReqUserId = (== "req_user_id") . T.toLower
getDepHeadersFromVal :: Value -> [Text]
getDepHeadersFromVal val = case val of
Object o -> parseObject o
_ -> parseOnlyString val
2018-06-27 16:11:32 +03:00
where
parseOnlyString v = case v of
(String t)
backend only insert permissions (rfc #4120) (#4224) * move user info related code to Hasura.User module * the RFC #4120 implementation; insert permissions with admin secret * revert back to old RoleName based schema maps An attempt made to avoid duplication of schema contexts in types if any role doesn't possess any admin secret specific schema * fix compile errors in haskell test * keep 'user_vars' for session variables in http-logs * no-op refacto * tests for admin only inserts * update docs for admin only inserts * updated CHANGELOG.md * default behaviour when admin secret is not set * fix x-hasura-role to X-Hasura-Role in pytests * introduce effective timeout in actions async tests * update docs for admin-secret not configured case * Update docs/graphql/manual/api-reference/schema-metadata-api/permission.rst Co-Authored-By: Marion Schleifer <marion@hasura.io> * Apply suggestions from code review Co-Authored-By: Marion Schleifer <marion@hasura.io> * a complete iteration backend insert permissions accessable via 'x-hasura-backend-privilege' session variable * console changes for backend-only permissions * provide tooltip id; update labels and tooltips; * requested changes * requested changes - remove className from Toggle component - use appropriate function name (capitalizeFirstChar -> capitalize) * use toggle props from definitelyTyped * fix accidental commit * Revert "introduce effective timeout in actions async tests" This reverts commit b7a59c19d643520cfde6af579889e1038038438a. * generate complete schema for both 'default' and 'backend' sessions * Apply suggestions from code review Co-Authored-By: Marion Schleifer <marion@hasura.io> * remove unnecessary import, export Toggle as is * update session variable in tooltip * 'x-hasura-use-backend-only-permissions' variable to switch * update help texts * update docs * update docs * update console help text * regenerate package-lock * serve no backend schema when backend_only: false and header set to true - Few type name refactor as suggested by @0x777 * update CHANGELOG.md * Update CHANGELOG.md * Update CHANGELOG.md * fix a merge bug where a certain entity didn't get removed Co-authored-by: Marion Schleifer <marion@hasura.io> Co-authored-by: Rishichandra Wawhal <rishi@hasura.io> Co-authored-by: rikinsk <rikin.kachhia@gmail.com> Co-authored-by: Tirumarai Selvan <tiru@hasura.io>
2020-04-24 12:10:53 +03:00
| isSessionVariable t -> [T.toLower t]
| isReqUserId t -> [userIdHeader]
| otherwise -> []
_ -> []
parseObject o =
concatMap getDepHeadersFromVal (M.elems o)
getDependentHeaders :: BoolExp b -> [Text]
getDependentHeaders (BoolExp boolExp) =
flip foldMap boolExp $ \(ColExp _ v) -> getDepHeadersFromVal v
2018-06-27 16:11:32 +03:00
data DropPerm b a
2018-06-27 16:11:32 +03:00
= DropPerm
{ dipSource :: !SourceName
, dipTable :: !(TableName b)
, dipRole :: !RoleName
} deriving (Generic)
deriving instance (Backend b) => Show (DropPerm b a)
deriving instance (Backend b) => Eq (DropPerm b a)
instance (Backend b) => ToJSON (DropPerm b a) where
toJSON = genericToJSON hasuraJSON{omitNothingFields=True}
instance (Backend b) => FromJSON (DropPerm b a) where
parseJSON = withObject "DropPerm" $ \o ->
DropPerm
<$> o .:? "source" .!= defaultSource
<*> o .: "table"
<*> o .: "role"
2018-06-27 16:11:32 +03:00
type family PermInfo (b :: BackendType) a = r | r -> a