2018-06-27 16:11:32 +03:00
|
|
|
module Hasura.RQL.DDL.Permission
|
|
|
|
( CreatePerm
|
2018-12-13 10:26:15 +03:00
|
|
|
, runCreatePerm
|
2018-06-27 16:11:32 +03:00
|
|
|
, purgePerm
|
|
|
|
, PermDef(..)
|
|
|
|
|
|
|
|
, InsPerm(..)
|
|
|
|
, InsPermDef
|
|
|
|
, CreateInsPerm
|
|
|
|
, clearInsInfra
|
|
|
|
, buildInsInfra
|
|
|
|
, buildInsPermInfo
|
|
|
|
, DropInsPerm
|
|
|
|
, dropInsPermP2
|
|
|
|
|
|
|
|
, SelPerm(..)
|
|
|
|
, SelPermDef
|
|
|
|
, CreateSelPerm
|
|
|
|
, buildSelPermInfo
|
|
|
|
, DropSelPerm
|
|
|
|
, dropSelPermP2
|
|
|
|
|
|
|
|
, UpdPerm(..)
|
|
|
|
, UpdPermDef
|
|
|
|
, CreateUpdPerm
|
|
|
|
, buildUpdPermInfo
|
|
|
|
, DropUpdPerm
|
|
|
|
, dropUpdPermP2
|
|
|
|
|
|
|
|
, DelPerm(..)
|
|
|
|
, DelPermDef
|
|
|
|
, CreateDelPerm
|
|
|
|
, buildDelPermInfo
|
|
|
|
, DropDelPerm
|
|
|
|
, dropDelPermP2
|
|
|
|
|
|
|
|
, IsPerm(..)
|
|
|
|
, addPermP1
|
|
|
|
, addPermP2
|
2018-12-13 10:26:15 +03:00
|
|
|
|
2019-03-01 12:17:22 +03:00
|
|
|
, dropView
|
2018-12-13 10:26:15 +03:00
|
|
|
, DropPerm
|
|
|
|
, runDropPerm
|
|
|
|
|
|
|
|
, SetPermComment(..)
|
|
|
|
, runSetPermComment
|
2019-08-17 00:35:22 +03:00
|
|
|
|
|
|
|
, rebuildPermInfo
|
|
|
|
, fetchPermDef
|
2018-06-27 16:11:32 +03:00
|
|
|
) where
|
|
|
|
|
2019-03-18 19:22:21 +03:00
|
|
|
import Hasura.EncJSON
|
2018-08-06 15:15:08 +03:00
|
|
|
import Hasura.Prelude
|
2018-06-27 16:11:32 +03:00
|
|
|
import Hasura.RQL.DDL.Permission.Internal
|
2018-08-17 17:44:43 +03:00
|
|
|
import Hasura.RQL.DDL.Permission.Triggers
|
2019-10-18 11:29:47 +03:00
|
|
|
import Hasura.RQL.DML.Internal hiding (askPermInfo)
|
2018-11-16 15:40:23 +03:00
|
|
|
import Hasura.RQL.GBoolExp
|
2018-12-15 19:10:29 +03:00
|
|
|
import Hasura.RQL.Types
|
2018-06-27 16:11:32 +03:00
|
|
|
import Hasura.SQL.Types
|
|
|
|
|
2018-08-06 15:15:08 +03:00
|
|
|
import qualified Database.PG.Query as Q
|
2018-06-27 16:11:32 +03:00
|
|
|
import qualified Hasura.SQL.DML as S
|
|
|
|
|
2018-10-26 17:58:20 +03:00
|
|
|
import Data.Aeson
|
2018-06-27 16:11:32 +03:00
|
|
|
import Data.Aeson.Casing
|
|
|
|
import Data.Aeson.TH
|
2018-08-06 15:15:08 +03:00
|
|
|
import Language.Haskell.TH.Syntax (Lift)
|
2018-06-27 16:11:32 +03:00
|
|
|
|
2018-10-26 17:58:20 +03:00
|
|
|
import qualified Data.HashMap.Strict as HM
|
2018-08-06 15:15:08 +03:00
|
|
|
import qualified Data.HashSet as HS
|
|
|
|
import qualified Data.Text as T
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
|
|
-- Insert permission
|
|
|
|
data InsPerm
|
|
|
|
= InsPerm
|
2019-04-15 10:04:30 +03:00
|
|
|
{ ipCheck :: !BoolExp
|
|
|
|
, ipSet :: !(Maybe ColVals)
|
|
|
|
, ipColumns :: !(Maybe PermColSpec)
|
2018-06-27 16:11:32 +03:00
|
|
|
} deriving (Show, Eq, Lift)
|
|
|
|
|
|
|
|
$(deriveJSON (aesonDrop 2 snakeCase){omitNothingFields=True} ''InsPerm)
|
|
|
|
|
|
|
|
type InsPermDef = PermDef InsPerm
|
|
|
|
type CreateInsPerm = CreatePerm InsPerm
|
|
|
|
|
|
|
|
buildViewName :: QualifiedTable -> RoleName -> PermType -> QualifiedTable
|
2019-07-11 12:00:45 +03:00
|
|
|
buildViewName (QualifiedObject sn tn) rn pt =
|
2019-01-25 06:31:54 +03:00
|
|
|
QualifiedObject hdbViewsSchema $ TableName
|
2019-07-11 12:00:45 +03:00
|
|
|
(roleNameToTxt rn <> "__" <> T.pack (show pt) <> "__" <> snTxt <> "__" <> tnTxt)
|
2018-06-27 16:11:32 +03:00
|
|
|
where
|
|
|
|
snTxt = getSchemaTxt sn
|
|
|
|
tnTxt = getTableTxt tn
|
|
|
|
|
|
|
|
buildView :: QualifiedTable -> QualifiedTable -> Q.Query
|
|
|
|
buildView tn vn =
|
|
|
|
Q.fromBuilder $ mconcat
|
2018-10-19 05:15:28 +03:00
|
|
|
[ "CREATE VIEW " <> toSQL vn
|
|
|
|
, " AS SELECT * FROM " <> toSQL tn
|
2018-06-27 16:11:32 +03:00
|
|
|
]
|
|
|
|
|
|
|
|
dropView :: QualifiedTable -> Q.Tx ()
|
|
|
|
dropView vn =
|
|
|
|
Q.unitQ dropViewS () False
|
|
|
|
where
|
|
|
|
dropViewS = Q.fromBuilder $
|
2018-10-19 05:15:28 +03:00
|
|
|
"DROP VIEW " <> toSQL vn
|
2018-06-27 16:11:32 +03:00
|
|
|
|
2019-02-11 15:45:30 +03:00
|
|
|
procSetObj
|
|
|
|
:: (QErrM m)
|
2019-08-11 18:34:38 +03:00
|
|
|
=> TableInfo PGColumnInfo -> Maybe ColVals
|
2019-04-17 12:48:41 +03:00
|
|
|
-> m (PreSetColsPartial, [Text], [SchemaDependency])
|
2019-02-11 15:45:30 +03:00
|
|
|
procSetObj ti mObj = do
|
2019-08-17 00:35:22 +03:00
|
|
|
(setColTups, deps) <- withPathK "set" $
|
|
|
|
fmap unzip $ forM (HM.toList setObj) $ \(pgCol, val) -> do
|
2019-02-11 15:45:30 +03:00
|
|
|
ty <- askPGType fieldInfoMap pgCol $
|
|
|
|
"column " <> pgCol <<> " not found in table " <>> tn
|
2019-08-11 18:34:38 +03:00
|
|
|
sqlExp <- valueParser (PGTypeScalar ty) val
|
2019-08-17 00:35:22 +03:00
|
|
|
let dep = mkColDep (getDepReason sqlExp) tn pgCol
|
|
|
|
return ((pgCol, sqlExp), dep)
|
|
|
|
return (HM.fromList setColTups, depHeaders, deps)
|
2019-02-11 15:45:30 +03:00
|
|
|
where
|
2019-07-22 15:47:13 +03:00
|
|
|
fieldInfoMap = _tiFieldInfoMap ti
|
|
|
|
tn = _tiName ti
|
2019-02-11 15:45:30 +03:00
|
|
|
setObj = fromMaybe mempty mObj
|
|
|
|
depHeaders = getDepHeadersFromVal $ Object $
|
|
|
|
HM.fromList $ map (first getPGColTxt) $ HM.toList setObj
|
|
|
|
|
2019-08-17 00:35:22 +03:00
|
|
|
getDepReason = bool DRSessionVariable DROnType . isStaticValue
|
|
|
|
|
2018-06-27 16:11:32 +03:00
|
|
|
buildInsPermInfo
|
|
|
|
:: (QErrM m, CacheRM m)
|
2019-08-11 18:34:38 +03:00
|
|
|
=> TableInfo PGColumnInfo
|
2018-06-27 16:11:32 +03:00
|
|
|
-> PermDef InsPerm
|
2018-11-16 15:40:23 +03:00
|
|
|
-> m (WithDeps InsPermInfo)
|
2019-04-17 12:48:41 +03:00
|
|
|
buildInsPermInfo tabInfo (PermDef rn (InsPerm chk set mCols) _) =
|
|
|
|
withPathK "permission" $ do
|
2018-06-27 16:11:32 +03:00
|
|
|
(be, beDeps) <- withPathK "check" $
|
2018-11-16 15:40:23 +03:00
|
|
|
-- procBoolExp tn fieldInfoMap (S.QualVar "NEW") chk
|
|
|
|
procBoolExp tn fieldInfoMap chk
|
2019-02-11 15:45:30 +03:00
|
|
|
(setColsSQL, setHdrs, setColDeps) <- procSetObj tabInfo set
|
2019-06-21 14:04:21 +03:00
|
|
|
void $ withPathK "columns" $ indexedForM insCols $ \col ->
|
|
|
|
askPGType fieldInfoMap col ""
|
|
|
|
let fltrHeaders = getDependentHeaders chk
|
|
|
|
reqHdrs = fltrHeaders `union` setHdrs
|
2019-08-17 00:35:22 +03:00
|
|
|
insColDeps = map (mkColDep DRUntyped tn) insCols
|
2019-06-21 14:04:21 +03:00
|
|
|
deps = mkParentDep tn : beDeps ++ setColDeps ++ insColDeps
|
2019-04-15 10:04:30 +03:00
|
|
|
insColsWithoutPresets = insCols \\ HM.keys setColsSQL
|
|
|
|
return (InsPermInfo (HS.fromList insColsWithoutPresets) vn be setColsSQL reqHdrs, deps)
|
2018-06-27 16:11:32 +03:00
|
|
|
where
|
2019-07-22 15:47:13 +03:00
|
|
|
fieldInfoMap = _tiFieldInfoMap tabInfo
|
|
|
|
tn = _tiName tabInfo
|
2018-06-27 16:11:32 +03:00
|
|
|
vn = buildViewName tn rn PTInsert
|
2019-09-19 07:47:36 +03:00
|
|
|
allCols = map pgiColumn $ getCols fieldInfoMap
|
2019-04-15 10:04:30 +03:00
|
|
|
insCols = fromMaybe allCols $ convColSpec fieldInfoMap <$> mCols
|
2018-06-27 16:11:32 +03:00
|
|
|
|
2018-09-04 16:39:48 +03:00
|
|
|
buildInsInfra :: QualifiedTable -> InsPermInfo -> Q.TxE QErr ()
|
2019-04-15 10:04:30 +03:00
|
|
|
buildInsInfra tn (InsPermInfo _ vn be _ _) = do
|
2019-04-17 12:48:41 +03:00
|
|
|
resolvedBoolExp <- convAnnBoolExpPartialSQL sessVarFromCurrentSetting be
|
2019-10-11 08:13:57 +03:00
|
|
|
let trigFnQ = buildInsTrigFn vn tn $ toSQLBoolExp (S.QualVar "NEW") resolvedBoolExp
|
2018-06-27 16:11:32 +03:00
|
|
|
Q.catchE defaultTxErrorHandler $ do
|
|
|
|
-- Create the view
|
|
|
|
Q.unitQ (buildView tn vn) () False
|
|
|
|
-- Inject defaults on the view
|
|
|
|
Q.discardQ (injectDefaults vn tn) () False
|
|
|
|
-- Construct a trigger function
|
2018-09-29 08:42:47 +03:00
|
|
|
Q.unitQ trigFnQ () False
|
2018-06-27 16:11:32 +03:00
|
|
|
-- Add trigger for check expression
|
|
|
|
Q.unitQ (buildInsTrig vn) () False
|
|
|
|
|
|
|
|
clearInsInfra :: QualifiedTable -> Q.TxE QErr ()
|
|
|
|
clearInsInfra vn =
|
|
|
|
Q.catchE defaultTxErrorHandler $ do
|
|
|
|
dropView vn
|
|
|
|
Q.unitQ (dropInsTrigFn vn) () False
|
|
|
|
|
|
|
|
type DropInsPerm = DropPerm InsPerm
|
|
|
|
|
2018-12-13 10:26:15 +03:00
|
|
|
dropInsPermP2
|
|
|
|
:: (CacheRWM m, MonadTx m)
|
|
|
|
=> DropInsPerm -> QualifiedTable -> m ()
|
2018-06-27 16:11:32 +03:00
|
|
|
dropInsPermP2 = dropPermP2
|
|
|
|
|
|
|
|
type instance PermInfo InsPerm = InsPermInfo
|
|
|
|
|
|
|
|
instance IsPerm InsPerm where
|
|
|
|
|
|
|
|
type DropPermP1Res InsPerm = QualifiedTable
|
|
|
|
|
|
|
|
permAccessor = PAInsert
|
|
|
|
|
|
|
|
buildPermInfo = buildInsPermInfo
|
|
|
|
|
2018-09-04 16:39:48 +03:00
|
|
|
addPermP2Setup qt _ = liftTx . buildInsInfra qt
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
|
|
buildDropPermP1Res dp =
|
|
|
|
ipiView <$> dropPermP1 dp
|
|
|
|
|
|
|
|
dropPermP2Setup _ vn =
|
|
|
|
liftTx $ clearInsInfra vn
|
|
|
|
|
|
|
|
-- Select constraint
|
|
|
|
data SelPerm
|
|
|
|
= SelPerm
|
2019-10-18 11:29:47 +03:00
|
|
|
{ spColumns :: !PermColSpec -- ^ Allowed columns
|
|
|
|
, spFilter :: !BoolExp -- ^ Filter expression
|
|
|
|
, spLimit :: !(Maybe Int) -- ^ Limit value
|
|
|
|
, spAllowAggregations :: !Bool -- ^ Allow aggregation
|
|
|
|
, spComputedFields :: ![ComputedFieldName] -- ^ Allowed computed fields
|
2018-06-27 16:11:32 +03:00
|
|
|
} deriving (Show, Eq, Lift)
|
2019-10-18 11:29:47 +03:00
|
|
|
$(deriveToJSON (aesonDrop 2 snakeCase){omitNothingFields=True} ''SelPerm)
|
2018-06-27 16:11:32 +03:00
|
|
|
|
2019-10-18 11:29:47 +03:00
|
|
|
instance FromJSON SelPerm where
|
|
|
|
parseJSON = withObject "SelPerm" $ \o ->
|
|
|
|
SelPerm
|
|
|
|
<$> o .: "columns"
|
|
|
|
<*> o .: "filter"
|
|
|
|
<*> o .:? "limit"
|
|
|
|
<*> o .:? "allow_aggregations" .!= False
|
|
|
|
<*> o .:? "computed_fields" .!= []
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
|
|
buildSelPermInfo
|
|
|
|
:: (QErrM m, CacheRM m)
|
2019-10-18 11:29:47 +03:00
|
|
|
=> RoleName
|
|
|
|
-> TableInfo PGColumnInfo
|
2018-06-27 16:11:32 +03:00
|
|
|
-> SelPerm
|
2018-11-16 15:40:23 +03:00
|
|
|
-> m (WithDeps SelPermInfo)
|
2019-10-18 11:29:47 +03:00
|
|
|
buildSelPermInfo role tabInfo sp = do
|
2018-06-27 16:11:32 +03:00
|
|
|
let pgCols = convColSpec fieldInfoMap $ spColumns sp
|
|
|
|
|
|
|
|
(be, beDeps) <- withPathK "filter" $
|
2018-11-16 15:40:23 +03:00
|
|
|
procBoolExp tn fieldInfoMap $ spFilter sp
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
|
|
-- check if the columns exist
|
|
|
|
void $ withPathK "columns" $ indexedForM pgCols $ \pgCol ->
|
|
|
|
askPGType fieldInfoMap pgCol autoInferredErr
|
|
|
|
|
2019-10-18 11:29:47 +03:00
|
|
|
-- validate computed fields
|
|
|
|
withPathK "computed_fields" $ indexedForM_ computedFields $ \name -> do
|
|
|
|
computedFieldInfo <- askComputedFieldInfo fieldInfoMap name
|
|
|
|
case _cfiReturnType computedFieldInfo of
|
|
|
|
CFRScalar _ -> pure ()
|
|
|
|
CFRSetofTable returnTable -> do
|
|
|
|
returnTableInfo <- askTabInfo returnTable
|
|
|
|
let function = _cffName $ _cfiFunction $ computedFieldInfo
|
|
|
|
errModifier e = "computed field " <> name <<> " executes function "
|
|
|
|
<> function <<> " which returns set of table "
|
|
|
|
<> returnTable <<> "; " <> e
|
|
|
|
void $ modifyErr errModifier $ askPermInfo returnTableInfo role PASelect
|
|
|
|
|
2019-08-17 00:35:22 +03:00
|
|
|
let deps = mkParentDep tn : beDeps ++ map (mkColDep DRUntyped tn) pgCols
|
2019-10-18 11:29:47 +03:00
|
|
|
++ map (mkComputedFieldDep DRUntyped tn) computedFields
|
2018-06-27 16:11:32 +03:00
|
|
|
depHeaders = getDependentHeaders $ spFilter sp
|
2018-08-06 15:15:08 +03:00
|
|
|
mLimit = spLimit sp
|
|
|
|
|
|
|
|
withPathK "limit" $ mapM_ onlyPositiveInt mLimit
|
2018-06-27 16:11:32 +03:00
|
|
|
|
2019-10-18 11:29:47 +03:00
|
|
|
return ( SelPermInfo (HS.fromList pgCols) (HS.fromList computedFields)
|
|
|
|
tn be mLimit allowAgg depHeaders
|
|
|
|
, deps
|
|
|
|
)
|
2018-06-27 16:11:32 +03:00
|
|
|
where
|
2019-07-22 15:47:13 +03:00
|
|
|
tn = _tiName tabInfo
|
|
|
|
fieldInfoMap = _tiFieldInfoMap tabInfo
|
2019-10-18 11:29:47 +03:00
|
|
|
allowAgg = spAllowAggregations sp
|
|
|
|
computedFields = spComputedFields sp
|
2018-06-27 16:11:32 +03:00
|
|
|
autoInferredErr = "permissions for relationships are automatically inferred"
|
|
|
|
|
|
|
|
type SelPermDef = PermDef SelPerm
|
|
|
|
type CreateSelPerm = CreatePerm SelPerm
|
|
|
|
type DropSelPerm = DropPerm SelPerm
|
|
|
|
|
|
|
|
type instance PermInfo SelPerm = SelPermInfo
|
|
|
|
|
2018-12-13 10:26:15 +03:00
|
|
|
dropSelPermP2
|
|
|
|
:: (CacheRWM m, MonadTx m)
|
|
|
|
=> DropSelPerm -> m ()
|
|
|
|
dropSelPermP2 dp =
|
|
|
|
dropPermP2 dp ()
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
|
|
instance IsPerm SelPerm where
|
|
|
|
|
|
|
|
type DropPermP1Res SelPerm = ()
|
|
|
|
|
|
|
|
permAccessor = PASelect
|
|
|
|
|
2019-10-18 11:29:47 +03:00
|
|
|
buildPermInfo ti (PermDef rn a _) =
|
|
|
|
buildSelPermInfo rn ti a
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
|
|
buildDropPermP1Res =
|
|
|
|
void . dropPermP1
|
|
|
|
|
|
|
|
addPermP2Setup _ _ _ = return ()
|
|
|
|
|
|
|
|
dropPermP2Setup _ _ = return ()
|
|
|
|
|
|
|
|
-- Update constraint
|
|
|
|
data UpdPerm
|
|
|
|
= UpdPerm
|
|
|
|
{ ucColumns :: !PermColSpec -- Allowed columns
|
2019-02-11 15:45:30 +03:00
|
|
|
, ucSet :: !(Maybe ColVals) -- Preset columns
|
2018-06-27 16:11:32 +03:00
|
|
|
, ucFilter :: !BoolExp -- Filter expression
|
|
|
|
} deriving (Show, Eq, Lift)
|
|
|
|
|
|
|
|
$(deriveJSON (aesonDrop 2 snakeCase){omitNothingFields=True} ''UpdPerm)
|
|
|
|
|
|
|
|
type UpdPermDef = PermDef UpdPerm
|
|
|
|
type CreateUpdPerm = CreatePerm UpdPerm
|
|
|
|
|
|
|
|
buildUpdPermInfo
|
|
|
|
:: (QErrM m, CacheRM m)
|
2019-08-11 18:34:38 +03:00
|
|
|
=> TableInfo PGColumnInfo
|
2018-06-27 16:11:32 +03:00
|
|
|
-> UpdPerm
|
2018-11-16 15:40:23 +03:00
|
|
|
-> m (WithDeps UpdPermInfo)
|
2019-02-11 15:45:30 +03:00
|
|
|
buildUpdPermInfo tabInfo (UpdPerm colSpec set fltr) = do
|
2018-06-27 16:11:32 +03:00
|
|
|
(be, beDeps) <- withPathK "filter" $
|
2018-11-16 15:40:23 +03:00
|
|
|
procBoolExp tn fieldInfoMap fltr
|
2018-06-27 16:11:32 +03:00
|
|
|
|
2019-02-11 15:45:30 +03:00
|
|
|
(setColsSQL, setHeaders, setColDeps) <- procSetObj tabInfo set
|
|
|
|
|
2018-06-27 16:11:32 +03:00
|
|
|
-- check if the columns exist
|
2019-06-21 14:04:21 +03:00
|
|
|
void $ withPathK "columns" $ indexedForM updCols $ \updCol ->
|
2018-06-27 16:11:32 +03:00
|
|
|
askPGType fieldInfoMap updCol relInUpdErr
|
|
|
|
|
2019-08-17 00:35:22 +03:00
|
|
|
let updColDeps = map (mkColDep DRUntyped tn) updCols
|
2019-02-11 15:45:30 +03:00
|
|
|
deps = mkParentDep tn : beDeps ++ updColDeps ++ setColDeps
|
2018-06-27 16:11:32 +03:00
|
|
|
depHeaders = getDependentHeaders fltr
|
2019-02-11 15:45:30 +03:00
|
|
|
reqHeaders = depHeaders `union` setHeaders
|
|
|
|
updColsWithoutPreSets = updCols \\ HM.keys setColsSQL
|
2018-06-27 16:11:32 +03:00
|
|
|
|
2019-02-11 15:45:30 +03:00
|
|
|
return (UpdPermInfo (HS.fromList updColsWithoutPreSets) tn be setColsSQL reqHeaders, deps)
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
|
|
where
|
2019-07-22 15:47:13 +03:00
|
|
|
tn = _tiName tabInfo
|
|
|
|
fieldInfoMap = _tiFieldInfoMap tabInfo
|
2018-06-27 16:11:32 +03:00
|
|
|
updCols = convColSpec fieldInfoMap colSpec
|
|
|
|
relInUpdErr = "relationships can't be used in update"
|
|
|
|
|
|
|
|
type instance PermInfo UpdPerm = UpdPermInfo
|
|
|
|
|
|
|
|
type DropUpdPerm = DropPerm UpdPerm
|
|
|
|
|
2018-12-13 10:26:15 +03:00
|
|
|
dropUpdPermP2
|
|
|
|
:: (CacheRWM m, MonadTx m)
|
|
|
|
=> DropUpdPerm -> m ()
|
2018-06-27 16:11:32 +03:00
|
|
|
dropUpdPermP2 dp = dropPermP2 dp ()
|
|
|
|
|
|
|
|
instance IsPerm UpdPerm where
|
|
|
|
|
|
|
|
type DropPermP1Res UpdPerm = ()
|
|
|
|
|
|
|
|
permAccessor = PAUpdate
|
|
|
|
|
|
|
|
buildPermInfo ti (PermDef _ a _) =
|
|
|
|
buildUpdPermInfo ti a
|
|
|
|
|
|
|
|
addPermP2Setup _ _ _ = return ()
|
|
|
|
|
|
|
|
buildDropPermP1Res =
|
|
|
|
void . dropPermP1
|
|
|
|
|
|
|
|
dropPermP2Setup _ _ = return ()
|
|
|
|
|
|
|
|
-- Delete permission
|
|
|
|
data DelPerm
|
|
|
|
= DelPerm { dcFilter :: !BoolExp }
|
|
|
|
deriving (Show, Eq, Lift)
|
|
|
|
|
|
|
|
$(deriveJSON (aesonDrop 2 snakeCase){omitNothingFields=True} ''DelPerm)
|
|
|
|
|
|
|
|
type DelPermDef = PermDef DelPerm
|
|
|
|
type CreateDelPerm = CreatePerm DelPerm
|
|
|
|
|
|
|
|
buildDelPermInfo
|
|
|
|
:: (QErrM m, CacheRM m)
|
2019-08-11 18:34:38 +03:00
|
|
|
=> TableInfo PGColumnInfo
|
2018-06-27 16:11:32 +03:00
|
|
|
-> DelPerm
|
2018-11-16 15:40:23 +03:00
|
|
|
-> m (WithDeps DelPermInfo)
|
2018-06-27 16:11:32 +03:00
|
|
|
buildDelPermInfo tabInfo (DelPerm fltr) = do
|
|
|
|
(be, beDeps) <- withPathK "filter" $
|
2018-11-16 15:40:23 +03:00
|
|
|
procBoolExp tn fieldInfoMap fltr
|
2018-06-27 16:11:32 +03:00
|
|
|
let deps = mkParentDep tn : beDeps
|
|
|
|
depHeaders = getDependentHeaders fltr
|
2018-11-16 15:40:23 +03:00
|
|
|
return (DelPermInfo tn be depHeaders, deps)
|
2018-06-27 16:11:32 +03:00
|
|
|
where
|
2019-07-22 15:47:13 +03:00
|
|
|
tn = _tiName tabInfo
|
|
|
|
fieldInfoMap = _tiFieldInfoMap tabInfo
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
|
|
type DropDelPerm = DropPerm DelPerm
|
|
|
|
|
2018-12-13 10:26:15 +03:00
|
|
|
dropDelPermP2 :: (CacheRWM m, MonadTx m) => DropDelPerm -> m ()
|
2018-06-27 16:11:32 +03:00
|
|
|
dropDelPermP2 dp = dropPermP2 dp ()
|
|
|
|
|
|
|
|
type instance PermInfo DelPerm = DelPermInfo
|
|
|
|
|
|
|
|
instance IsPerm DelPerm where
|
|
|
|
|
|
|
|
type DropPermP1Res DelPerm = ()
|
|
|
|
|
|
|
|
permAccessor = PADelete
|
|
|
|
|
|
|
|
buildPermInfo ti (PermDef _ a _) =
|
|
|
|
buildDelPermInfo ti a
|
|
|
|
|
|
|
|
addPermP2Setup _ _ _ = return ()
|
|
|
|
|
|
|
|
buildDropPermP1Res =
|
|
|
|
void . dropPermP1
|
|
|
|
|
|
|
|
dropPermP2Setup _ _ = return ()
|
|
|
|
|
|
|
|
data SetPermComment
|
|
|
|
= SetPermComment
|
|
|
|
{ apTable :: !QualifiedTable
|
|
|
|
, apRole :: !RoleName
|
|
|
|
, apPermission :: !PermType
|
|
|
|
, apComment :: !(Maybe T.Text)
|
|
|
|
} deriving (Show, Eq, Lift)
|
|
|
|
|
|
|
|
$(deriveJSON (aesonDrop 2 snakeCase) ''SetPermComment)
|
|
|
|
|
2018-12-13 10:26:15 +03:00
|
|
|
setPermCommentP1 :: (UserInfoM m, QErrM m, CacheRM m) => SetPermComment -> m ()
|
2018-06-27 16:11:32 +03:00
|
|
|
setPermCommentP1 (SetPermComment qt rn pt _) = do
|
|
|
|
adminOnly
|
|
|
|
tabInfo <- askTabInfo qt
|
|
|
|
action tabInfo
|
|
|
|
where
|
|
|
|
action tabInfo = case pt of
|
|
|
|
PTInsert -> assertPermDefined rn PAInsert tabInfo
|
|
|
|
PTSelect -> assertPermDefined rn PASelect tabInfo
|
|
|
|
PTUpdate -> assertPermDefined rn PAUpdate tabInfo
|
|
|
|
PTDelete -> assertPermDefined rn PADelete tabInfo
|
|
|
|
|
2019-03-18 19:22:21 +03:00
|
|
|
setPermCommentP2 :: (QErrM m, MonadTx m) => SetPermComment -> m EncJSON
|
2018-06-27 16:11:32 +03:00
|
|
|
setPermCommentP2 apc = do
|
|
|
|
liftTx $ setPermCommentTx apc
|
|
|
|
return successMsg
|
|
|
|
|
2018-12-13 10:26:15 +03:00
|
|
|
runSetPermComment
|
|
|
|
:: (QErrM m, CacheRM m, MonadTx m, UserInfoM m)
|
2019-03-18 19:22:21 +03:00
|
|
|
=> SetPermComment -> m EncJSON
|
2018-12-13 10:26:15 +03:00
|
|
|
runSetPermComment defn = do
|
|
|
|
setPermCommentP1 defn
|
|
|
|
setPermCommentP2 defn
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
|
|
setPermCommentTx
|
|
|
|
:: SetPermComment
|
|
|
|
-> Q.TxE QErr ()
|
2019-01-25 06:31:54 +03:00
|
|
|
setPermCommentTx (SetPermComment (QualifiedObject sn tn) rn pt comment) =
|
2018-06-27 16:11:32 +03:00
|
|
|
Q.unitQE defaultTxErrorHandler [Q.sql|
|
|
|
|
UPDATE hdb_catalog.hdb_permission
|
|
|
|
SET comment = $1
|
|
|
|
WHERE table_schema = $2
|
|
|
|
AND table_name = $3
|
|
|
|
AND role_name = $4
|
|
|
|
AND perm_type = $5
|
|
|
|
|] (comment, sn, tn, rn, permTypeToCode pt) True
|
|
|
|
|
2018-12-13 10:26:15 +03:00
|
|
|
purgePerm
|
|
|
|
:: (CacheRWM m, MonadTx m)
|
|
|
|
=> QualifiedTable -> RoleName -> PermType -> m ()
|
2018-06-27 16:11:32 +03:00
|
|
|
purgePerm qt rn pt =
|
|
|
|
case pt of
|
|
|
|
PTInsert -> dropInsPermP2 dp $ buildViewName qt rn PTInsert
|
|
|
|
PTSelect -> dropSelPermP2 dp
|
|
|
|
PTUpdate -> dropUpdPermP2 dp
|
|
|
|
PTDelete -> dropDelPermP2 dp
|
|
|
|
where
|
|
|
|
dp :: DropPerm a
|
|
|
|
dp = DropPerm qt rn
|
2019-08-17 00:35:22 +03:00
|
|
|
|
|
|
|
rebuildPermInfo
|
|
|
|
:: (QErrM m, CacheRWM m, MonadTx m)
|
|
|
|
=> QualifiedTable -> RoleName -> PermType -> m ()
|
|
|
|
rebuildPermInfo qt rn pt = do
|
|
|
|
(pDef, comment) <- liftTx $ fetchPermDef qt rn pt
|
|
|
|
case pt of
|
|
|
|
PTInsert -> do
|
|
|
|
perm <- decodeValue pDef
|
|
|
|
updatePerm PAInsert $ PermDef rn perm comment
|
|
|
|
PTSelect -> do
|
|
|
|
perm <- decodeValue pDef
|
|
|
|
updatePerm PASelect $ PermDef rn perm comment
|
|
|
|
PTUpdate -> do
|
|
|
|
perm <- decodeValue pDef
|
|
|
|
updatePerm PAUpdate $ PermDef rn perm comment
|
|
|
|
PTDelete -> do
|
|
|
|
perm <- decodeValue pDef
|
|
|
|
updatePerm PADelete $ PermDef rn perm comment
|
|
|
|
|
|
|
|
where
|
|
|
|
updatePerm :: (QErrM m, CacheRWM m, IsPerm a)
|
|
|
|
=> PermAccessor (PermInfo a) -> PermDef a -> m ()
|
|
|
|
updatePerm pa perm = do
|
|
|
|
delPermFromCache pa rn qt
|
|
|
|
tabInfo <- askTabInfo qt
|
|
|
|
(permInfo, deps) <- addPermP1 tabInfo perm
|
|
|
|
addPermToCache qt rn pa permInfo deps
|
|
|
|
|
|
|
|
fetchPermDef
|
|
|
|
:: QualifiedTable
|
|
|
|
-> RoleName
|
|
|
|
-> PermType
|
|
|
|
-> Q.TxE QErr (Value, Maybe T.Text)
|
|
|
|
fetchPermDef (QualifiedObject sn tn) rn pt =
|
|
|
|
(first Q.getAltJ . Q.getRow) <$> Q.withQE defaultTxErrorHandler
|
|
|
|
[Q.sql|
|
|
|
|
SELECT perm_def::json, comment
|
|
|
|
FROM hdb_catalog.hdb_permission
|
|
|
|
WHERE table_schema = $1
|
|
|
|
AND table_name = $2
|
|
|
|
AND role_name = $3
|
|
|
|
AND perm_type = $4
|
|
|
|
|] (sn, tn, rn, permTypeToCode pt) True
|