mirror of
https://github.com/zhigang1992/graphql-engine.git
synced 2026-05-25 18:32:23 +08:00
This commit is contained in:
committed by
Vamshi Surabhi
parent
fbcae53efa
commit
999580481c
@@ -41,6 +41,7 @@ const defaultQueryPermissions = {
|
||||
check: {},
|
||||
allow_upsert: true,
|
||||
set: {},
|
||||
columns: [],
|
||||
localSet: [
|
||||
{
|
||||
...defaultInsertSetState,
|
||||
|
||||
@@ -279,7 +279,8 @@ const modifyReducer = (tableName, schemas, modifyStateOrig, action) => {
|
||||
...getBasePermissionsState(
|
||||
action.tableSchema,
|
||||
action.role,
|
||||
action.query
|
||||
action.query,
|
||||
action.insertPermColumnRestriction
|
||||
),
|
||||
},
|
||||
};
|
||||
|
||||
@@ -49,17 +49,29 @@ export const SET_TYPE_CONFIG = 'ModifyTable/SET_TYPE_CONFIG';
|
||||
|
||||
/* */
|
||||
|
||||
const queriesWithPermColumns = ['select', 'update'];
|
||||
const getQueriesWithPermColumns = insert => {
|
||||
const queries = ['select', 'update'];
|
||||
if (insert) {
|
||||
queries.push('insert');
|
||||
}
|
||||
return queries;
|
||||
};
|
||||
const permChangeTypes = {
|
||||
save: 'update',
|
||||
delete: 'delete',
|
||||
};
|
||||
|
||||
const permOpenEdit = (tableSchema, role, query) => ({
|
||||
const permOpenEdit = (
|
||||
tableSchema,
|
||||
role,
|
||||
query,
|
||||
insertPermColumnRestriction
|
||||
) => ({
|
||||
type: PERM_OPEN_EDIT,
|
||||
tableSchema,
|
||||
role,
|
||||
query,
|
||||
insertPermColumnRestriction,
|
||||
});
|
||||
const permSetFilter = filter => ({ type: PERM_SET_FILTER, filter });
|
||||
const permSetFilterSameAs = filter => ({
|
||||
@@ -122,7 +134,12 @@ const setConfigValueType = value => {
|
||||
: 'static';
|
||||
};
|
||||
|
||||
const getBasePermissionsState = (tableSchema, role, query) => {
|
||||
const getBasePermissionsState = (
|
||||
tableSchema,
|
||||
role,
|
||||
query,
|
||||
insertPermColumnRestriction
|
||||
) => {
|
||||
const _permissions = JSON.parse(JSON.stringify(defaultPermissionsState));
|
||||
|
||||
_permissions.table = tableSchema.table_name;
|
||||
@@ -139,6 +156,13 @@ const getBasePermissionsState = (tableSchema, role, query) => {
|
||||
// If the query is insert, transform set object if exists to an array
|
||||
if (q === 'insert') {
|
||||
// If set is an object
|
||||
if (insertPermColumnRestriction) {
|
||||
if (!_permissions[q].columns) {
|
||||
_permissions[q].columns = tableSchema.columns.map(
|
||||
c => c.column_name
|
||||
);
|
||||
}
|
||||
}
|
||||
if ('set' in _permissions[q]) {
|
||||
if (
|
||||
Object.keys(_permissions[q].set).length > 0 &&
|
||||
@@ -619,7 +643,7 @@ export {
|
||||
permSetBulkSelect,
|
||||
toggleColumn,
|
||||
toggleAllColumns,
|
||||
queriesWithPermColumns,
|
||||
getQueriesWithPermColumns,
|
||||
getFilterKey,
|
||||
getBasePermissionsState,
|
||||
updatePermissionsState,
|
||||
|
||||
@@ -9,7 +9,7 @@ import 'brace/theme/github';
|
||||
|
||||
import { RESET } from '../TableModify/ModifyActions';
|
||||
import {
|
||||
queriesWithPermColumns,
|
||||
getQueriesWithPermColumns,
|
||||
permChangeTypes,
|
||||
permOpenEdit,
|
||||
permSetFilter,
|
||||
@@ -417,7 +417,14 @@ class Permissions extends Component {
|
||||
if (isNewPerm && permsState.newRole !== '') {
|
||||
dispatch(permOpenEdit(tableSchema, permsState.newRole, queryType));
|
||||
} else if (role !== '') {
|
||||
dispatch(permOpenEdit(tableSchema, role, queryType));
|
||||
dispatch(
|
||||
permOpenEdit(
|
||||
tableSchema,
|
||||
role,
|
||||
queryType,
|
||||
semverCheck('insertPermRestrictColumns', this.props.serverVersion)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
window.alert('Please enter a role name');
|
||||
}
|
||||
@@ -452,21 +459,21 @@ class Permissions extends Component {
|
||||
const bulkSelect = permsState.bulkSelect;
|
||||
const currentInputSelection = bulkSelect.filter(e => e === role)
|
||||
.length ? (
|
||||
<input
|
||||
onChange={dispatchBulkSelect}
|
||||
checked="checked"
|
||||
data-role={role}
|
||||
className={styles.bulkSelect}
|
||||
type="checkbox"
|
||||
/>
|
||||
) : (
|
||||
<input
|
||||
onChange={dispatchBulkSelect}
|
||||
data-role={role}
|
||||
className={styles.bulkSelect}
|
||||
type="checkbox"
|
||||
/>
|
||||
);
|
||||
<input
|
||||
onChange={dispatchBulkSelect}
|
||||
checked="checked"
|
||||
data-role={role}
|
||||
className={styles.bulkSelect}
|
||||
type="checkbox"
|
||||
/>
|
||||
) : (
|
||||
<input
|
||||
onChange={dispatchBulkSelect}
|
||||
data-role={role}
|
||||
className={styles.bulkSelect}
|
||||
type="checkbox"
|
||||
/>
|
||||
);
|
||||
_permissionsRowHtml.push(
|
||||
<td key={-1}>
|
||||
<div>
|
||||
@@ -765,164 +772,164 @@ class Permissions extends Component {
|
||||
const setOptions =
|
||||
insertState && insertState.localSet && insertState.localSet.length > 0
|
||||
? insertState.localSet.map((s, i) => {
|
||||
return (
|
||||
<div className={styles.insertSetConfigRow} key={i}>
|
||||
<div
|
||||
className={
|
||||
styles.display_inline +
|
||||
return (
|
||||
<div className={styles.insertSetConfigRow} key={i}>
|
||||
<div
|
||||
className={
|
||||
styles.display_inline +
|
||||
' ' +
|
||||
styles.add_mar_right +
|
||||
' ' +
|
||||
styles.input_element_wrapper
|
||||
}
|
||||
>
|
||||
<select
|
||||
className="input-sm form-control"
|
||||
value={s.key}
|
||||
onChange={this.onSetKeyChange.bind(this)}
|
||||
data-index-id={i}
|
||||
disabled={disableInput}
|
||||
}
|
||||
>
|
||||
<option value="" disabled>
|
||||
<select
|
||||
className="input-sm form-control"
|
||||
value={s.key}
|
||||
onChange={this.onSetKeyChange.bind(this)}
|
||||
data-index-id={i}
|
||||
disabled={disableInput}
|
||||
>
|
||||
<option value="" disabled>
|
||||
Column Name
|
||||
</option>
|
||||
{columns && columns.length > 0
|
||||
? columns.map((c, key) => (
|
||||
<option
|
||||
value={c.column_name}
|
||||
data-column-type={c.data_type}
|
||||
key={key}
|
||||
>
|
||||
{c.column_name}
|
||||
</option>
|
||||
))
|
||||
: null}
|
||||
</select>
|
||||
</div>
|
||||
<div
|
||||
className={
|
||||
styles.display_inline +
|
||||
</option>
|
||||
{columns && columns.length > 0
|
||||
? columns.map((c, key) => (
|
||||
<option
|
||||
value={c.column_name}
|
||||
data-column-type={c.data_type}
|
||||
key={key}
|
||||
>
|
||||
{c.column_name}
|
||||
</option>
|
||||
))
|
||||
: null}
|
||||
</select>
|
||||
</div>
|
||||
<div
|
||||
className={
|
||||
styles.display_inline +
|
||||
' ' +
|
||||
styles.add_mar_right +
|
||||
' ' +
|
||||
styles.input_element_wrapper
|
||||
}
|
||||
>
|
||||
<select
|
||||
className="input-sm form-control"
|
||||
onChange={this.onSetTypeChange.bind(this)}
|
||||
data-index-id={i}
|
||||
value={setConfigValueType(s.value) || ''}
|
||||
disabled={disableInput}
|
||||
}
|
||||
>
|
||||
<option value="" disabled>
|
||||
<select
|
||||
className="input-sm form-control"
|
||||
onChange={this.onSetTypeChange.bind(this)}
|
||||
data-index-id={i}
|
||||
value={setConfigValueType(s.value) || ''}
|
||||
disabled={disableInput}
|
||||
>
|
||||
<option value="" disabled>
|
||||
Select Preset Type
|
||||
</option>
|
||||
<option value="static">static</option>
|
||||
<option value="session">from session variable</option>
|
||||
</select>
|
||||
</div>
|
||||
<div
|
||||
className={
|
||||
styles.display_inline +
|
||||
</option>
|
||||
<option value="static">static</option>
|
||||
<option value="session">from session variable</option>
|
||||
</select>
|
||||
</div>
|
||||
<div
|
||||
className={
|
||||
styles.display_inline +
|
||||
' ' +
|
||||
styles.add_mar_right +
|
||||
' ' +
|
||||
styles.input_element_wrapper
|
||||
}
|
||||
>
|
||||
{setConfigValueType(s.value) === 'session' ? (
|
||||
<InputGroup>
|
||||
<InputGroup.Addon>X-Hasura-</InputGroup.Addon>
|
||||
<input
|
||||
className={'input-sm form-control '}
|
||||
}
|
||||
>
|
||||
{setConfigValueType(s.value) === 'session' ? (
|
||||
<InputGroup>
|
||||
<InputGroup.Addon>X-Hasura-</InputGroup.Addon>
|
||||
<input
|
||||
className={'input-sm form-control '}
|
||||
placeholder="column_value"
|
||||
value={s.value.slice(X_HASURA_CONST.length)}
|
||||
onChange={this.onSetValueChange.bind(this)}
|
||||
onBlur={e => this.onSetValueBlur(e, i, null)}
|
||||
data-index-id={i}
|
||||
data-prefix-val={X_HASURA_CONST}
|
||||
disabled={disableInput}
|
||||
/>
|
||||
</InputGroup>
|
||||
) : (
|
||||
<EnhancedInput
|
||||
placeholder="column_value"
|
||||
value={s.value.slice(X_HASURA_CONST.length)}
|
||||
type={
|
||||
i in this.state.insertSetOperations.columnTypeMap
|
||||
? this.state.insertSetOperations.columnTypeMap[i]
|
||||
: ''
|
||||
}
|
||||
value={s.value}
|
||||
onChange={this.onSetValueChange.bind(this)}
|
||||
onBlur={e => this.onSetValueBlur(e, i, null)}
|
||||
data-index-id={i}
|
||||
onBlur={this.onSetValueBlur}
|
||||
indexId={i}
|
||||
data-prefix-val={X_HASURA_CONST}
|
||||
disabled={disableInput}
|
||||
/>
|
||||
</InputGroup>
|
||||
) : (
|
||||
<EnhancedInput
|
||||
placeholder="column_value"
|
||||
type={
|
||||
i in this.state.insertSetOperations.columnTypeMap
|
||||
? this.state.insertSetOperations.columnTypeMap[i]
|
||||
: ''
|
||||
)}
|
||||
</div>
|
||||
{setConfigValueType(s.value) === 'session' ? (
|
||||
<div
|
||||
className={
|
||||
styles.display_inline +
|
||||
' ' +
|
||||
styles.add_mar_right +
|
||||
' ' +
|
||||
styles.input_element_wrapper +
|
||||
' ' +
|
||||
styles.e_g_text
|
||||
}
|
||||
>
|
||||
e.g. X-Hasura-User-Id
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
className={
|
||||
styles.display_inline +
|
||||
' ' +
|
||||
styles.add_mar_right +
|
||||
' ' +
|
||||
styles.input_element_wrapper +
|
||||
' ' +
|
||||
styles.e_g_text
|
||||
}
|
||||
>
|
||||
e.g. false, 1, some-text
|
||||
</div>
|
||||
)}
|
||||
{i !== insertState.localSet.length - 1 ? (
|
||||
<div
|
||||
className={
|
||||
styles.display_inline +
|
||||
' ' +
|
||||
styles.add_mar_right +
|
||||
' ' +
|
||||
styles.input_element_wrapper
|
||||
}
|
||||
>
|
||||
<i
|
||||
className="fa-lg fa fa-times"
|
||||
onClick={
|
||||
!disableInput ? this.deleteSetKeyVal.bind(this) : ''
|
||||
}
|
||||
data-index-id={i}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
className={
|
||||
styles.display_inline +
|
||||
' ' +
|
||||
styles.add_mar_right +
|
||||
' ' +
|
||||
styles.input_element_wrapper
|
||||
}
|
||||
value={s.value}
|
||||
onChange={this.onSetValueChange.bind(this)}
|
||||
onBlur={this.onSetValueBlur}
|
||||
indexId={i}
|
||||
data-prefix-val={X_HASURA_CONST}
|
||||
disabled={disableInput}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{setConfigValueType(s.value) === 'session' ? (
|
||||
<div
|
||||
className={
|
||||
styles.display_inline +
|
||||
' ' +
|
||||
styles.add_mar_right +
|
||||
' ' +
|
||||
styles.input_element_wrapper +
|
||||
' ' +
|
||||
styles.e_g_text
|
||||
}
|
||||
>
|
||||
e.g. X-Hasura-User-Id
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
className={
|
||||
styles.display_inline +
|
||||
' ' +
|
||||
styles.add_mar_right +
|
||||
' ' +
|
||||
styles.input_element_wrapper +
|
||||
' ' +
|
||||
styles.e_g_text
|
||||
}
|
||||
>
|
||||
e.g. false, 1, some-text
|
||||
</div>
|
||||
)}
|
||||
{i !== insertState.localSet.length - 1 ? (
|
||||
<div
|
||||
className={
|
||||
styles.display_inline +
|
||||
' ' +
|
||||
styles.add_mar_right +
|
||||
' ' +
|
||||
styles.input_element_wrapper
|
||||
}
|
||||
>
|
||||
<i
|
||||
className="fa-lg fa fa-times"
|
||||
onClick={
|
||||
!disableInput ? this.deleteSetKeyVal.bind(this) : ''
|
||||
}
|
||||
data-index-id={i}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div
|
||||
className={
|
||||
styles.display_inline +
|
||||
' ' +
|
||||
styles.add_mar_right +
|
||||
' ' +
|
||||
styles.input_element_wrapper
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})
|
||||
);
|
||||
})
|
||||
: null;
|
||||
|
||||
return (
|
||||
@@ -1056,13 +1063,15 @@ class Permissions extends Component {
|
||||
const getColumnSection = (tableSchema, permsState) => {
|
||||
let _columnSection = '';
|
||||
const query = permsState.query;
|
||||
|
||||
if (queriesWithPermColumns.indexOf(query) !== -1) {
|
||||
if (
|
||||
getQueriesWithPermColumns(
|
||||
semverCheck('insertPermRestrictColumns', this.props.serverVersion)
|
||||
).indexOf(query) !== -1
|
||||
) {
|
||||
const dispatchToggleAllColumns = () => {
|
||||
const allColumns = tableSchema.columns.map(c => c.column_name);
|
||||
dispatch(permToggleAllColumns(allColumns));
|
||||
};
|
||||
|
||||
_columnSection = (
|
||||
<div className={styles.editPermissionsSection}>
|
||||
<div>
|
||||
|
||||
@@ -9,6 +9,7 @@ const componentsSemver = {
|
||||
supportColumnChangeTrigger: '1.0.0-alpha26',
|
||||
analyzeApiChange: '1.0.0-alpha26',
|
||||
insertPrefix: '1.0.0-alpha26',
|
||||
insertPermRestrictColumns: '1.0.0-alpha28',
|
||||
};
|
||||
|
||||
const getPreRelease = version => {
|
||||
|
||||
@@ -504,8 +504,7 @@ resolveInsCtx tn = do
|
||||
InsCtx view colInfos setVals relInfoMap <-
|
||||
onNothing (Map.lookup tn ctxMap) $
|
||||
throw500 $ "table " <> tn <<> " not found"
|
||||
let defValMap = Map.fromList $ flip zip (repeat $ S.SEUnsafe "DEFAULT") $
|
||||
map pgiName colInfos
|
||||
let defValMap = S.mkColDefValMap $ map pgiName colInfos
|
||||
defValWithSet = Map.union setVals defValMap
|
||||
return (view, colInfos, defValWithSet, relInfoMap)
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ module Hasura.GraphQL.Resolve.Mutation
|
||||
|
||||
import Hasura.Prelude
|
||||
|
||||
import qualified Data.HashMap.Strict as Map
|
||||
import qualified Data.HashMap.Strict.InsOrd as OMap
|
||||
import qualified Language.GraphQL.Draft.Syntax as G
|
||||
|
||||
@@ -43,15 +42,14 @@ convertMutResp ty selSet =
|
||||
|
||||
convertRowObj
|
||||
:: (MonadError QErr m, MonadState PrepArgs m)
|
||||
=> InsSetCols -> AnnGValue
|
||||
=> AnnGValue
|
||||
-> m [(PGCol, S.SQLExp)]
|
||||
convertRowObj setVals val =
|
||||
flip withObject val $ \_ obj -> do
|
||||
inpVals <- forM (OMap.toList obj) $ \(k, v) -> do
|
||||
convertRowObj val =
|
||||
flip withObject val $ \_ obj ->
|
||||
forM (OMap.toList obj) $ \(k, v) -> do
|
||||
prepExpM <- asPGColValM v >>= mapM prepare
|
||||
let prepExp = fromMaybe (S.SEUnsafe "NULL") prepExpM
|
||||
return (PGCol $ G.unName k, prepExp)
|
||||
return $ Map.toList setVals <> inpVals
|
||||
|
||||
type ApplySQLOp = (PGCol, S.SQLExp) -> S.SQLExp
|
||||
|
||||
@@ -98,7 +96,7 @@ convertUpdate
|
||||
-> Convert RespTx
|
||||
convertUpdate tn filterExp fld = do
|
||||
-- a set expression is same as a row object
|
||||
setExpM <- withArgM args "_set" $ convertRowObj Map.empty
|
||||
setExpM <- withArgM args "_set" convertRowObj
|
||||
-- where bool expression to filter column
|
||||
whereExp <- withArg args "where" $ convertBoolExp tn
|
||||
-- increment operator on integer columns
|
||||
|
||||
@@ -74,6 +74,7 @@ data InsPerm
|
||||
{ icCheck :: !BoolExp
|
||||
, icAllowUpsert :: !(Maybe Bool)
|
||||
, icSet :: !(Maybe Object)
|
||||
, icColumns :: !(Maybe PermColSpec)
|
||||
} deriving (Show, Eq, Lift)
|
||||
|
||||
$(deriveJSON (aesonDrop 2 snakeCase){omitNothingFields=True} ''InsPerm)
|
||||
@@ -109,7 +110,7 @@ buildInsPermInfo
|
||||
=> TableInfo
|
||||
-> PermDef InsPerm
|
||||
-> m InsPermInfo
|
||||
buildInsPermInfo tabInfo (PermDef rn (InsPerm chk upsrt set) _) = withPathK "permission" $ do
|
||||
buildInsPermInfo tabInfo (PermDef rn (InsPerm chk upsrt set mCols) _) = withPathK "permission" $ do
|
||||
(be, beDeps) <- withPathK "check" $
|
||||
procBoolExp tn fieldInfoMap (S.QualVar "NEW") chk
|
||||
let deps = mkParentDep tn : beDeps
|
||||
@@ -125,11 +126,17 @@ buildInsPermInfo tabInfo (PermDef rn (InsPerm chk upsrt set) _) = withPathK "per
|
||||
return (pgCol, sqlExp)
|
||||
let setHdrs = mapMaybe (fetchHdr . snd) (HM.toList setObj)
|
||||
reqHdrs = fltrHeaders `union` setHdrs
|
||||
return $ InsPermInfo vn be allowUpsrt setColsSQL deps reqHdrs
|
||||
preSetCols = HM.union setColsSQL nonInsColVals
|
||||
return $ InsPermInfo vn be allowUpsrt preSetCols deps reqHdrs
|
||||
where
|
||||
fieldInfoMap = tiFieldInfoMap tabInfo
|
||||
tn = tiName tabInfo
|
||||
vn = buildViewName tn rn PTInsert
|
||||
allCols = map pgiName $ getCols fieldInfoMap
|
||||
nonInsCols = case mCols of
|
||||
Nothing -> []
|
||||
Just cols -> (\\) allCols $ convColSpec fieldInfoMap cols
|
||||
nonInsColVals = S.mkColDefValMap nonInsCols
|
||||
|
||||
fetchHdr (String t) = bool Nothing (Just $ T.toLower t)
|
||||
$ isUserVar t
|
||||
|
||||
@@ -47,9 +47,7 @@ instance ToJSON PermColSpec where
|
||||
|
||||
convColSpec :: FieldInfoMap -> PermColSpec -> [PGCol]
|
||||
convColSpec _ (PCCols cols) = cols
|
||||
convColSpec cim PCStar =
|
||||
map pgiName $ fst $ partitionEithers $
|
||||
map fieldInfoToEither $ M.elems cim
|
||||
convColSpec cim PCStar = map pgiName $ getCols cim
|
||||
|
||||
assertPermNotDefined
|
||||
:: (MonadError QErr m)
|
||||
|
||||
@@ -86,9 +86,11 @@ convObj
|
||||
-> InsObj
|
||||
-> m ([PGCol], [S.SQLExp])
|
||||
convObj prepFn defInsVals setInsVals fieldInfoMap insObj = do
|
||||
inpInsVals <- flip HM.traverseWithKey reqInsObj $ \c val -> do
|
||||
inpInsVals <- flip HM.traverseWithKey insObj $ \c val -> do
|
||||
let relWhenPGErr = "relationships can't be inserted"
|
||||
colType <- askPGType fieldInfoMap c relWhenPGErr
|
||||
-- if column has predefined value then throw error
|
||||
when (c `elem` preSetCols) $ throwNotInsErr c
|
||||
-- Encode aeson's value into prepared value
|
||||
withPathK (getPGColTxt c) $ prepFn colType val
|
||||
let insVals = HM.union setInsVals inpInsVals
|
||||
@@ -97,7 +99,12 @@ convObj prepFn defInsVals setInsVals fieldInfoMap insObj = do
|
||||
|
||||
return (inpCols, sqlExps)
|
||||
where
|
||||
reqInsObj = HM.difference insObj setInsVals
|
||||
preSetCols = HM.keys setInsVals
|
||||
|
||||
throwNotInsErr c = do
|
||||
role <- userRole <$> askUserInfo
|
||||
throw400 NotSupported $ "column " <> c <<> " is not insertable"
|
||||
<> " for role " <>> role
|
||||
|
||||
buildConflictClause
|
||||
:: (P1C m)
|
||||
|
||||
@@ -12,6 +12,7 @@ import Hasura.SQL.Types
|
||||
import Data.String (fromString)
|
||||
import Language.Haskell.TH.Syntax (Lift)
|
||||
|
||||
import qualified Data.HashMap.Strict as HM
|
||||
import qualified Data.Text.Extended as T
|
||||
import qualified Text.Builder as TB
|
||||
|
||||
@@ -318,6 +319,10 @@ mkSQLOpExp
|
||||
-> SQLExp -- result
|
||||
mkSQLOpExp op lhs rhs = SEOpApp op [lhs, rhs]
|
||||
|
||||
mkColDefValMap :: [PGCol] -> HM.HashMap PGCol SQLExp
|
||||
mkColDefValMap cols =
|
||||
HM.fromList $ zip cols (repeat $ SEUnsafe "DEFAULT")
|
||||
|
||||
handleIfNull :: SQLExp -> SQLExp -> SQLExp
|
||||
handleIfNull l e = SEFnApp "coalesce" [e, l] Nothing
|
||||
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
description: Insert into resident table only with insertable columns
|
||||
url: /v1alpha1/graphql
|
||||
status: 200
|
||||
headers:
|
||||
X-Hasura-Role: infant
|
||||
X-Hasura-Infant-Id: '1'
|
||||
X-Hasura-Infant-Name: 'Bittu'
|
||||
response:
|
||||
data:
|
||||
insert_resident:
|
||||
affected_rows: 1
|
||||
returning:
|
||||
- id: 1
|
||||
name: Bittu
|
||||
age: 3
|
||||
is_user: false
|
||||
query:
|
||||
query: |
|
||||
mutation {
|
||||
insert_resident(
|
||||
objects: [
|
||||
{
|
||||
age: 3
|
||||
}
|
||||
]
|
||||
){
|
||||
affected_rows
|
||||
returning{
|
||||
id
|
||||
name
|
||||
age
|
||||
is_user
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
description: Insert into resident table with non insertable columns (Error)
|
||||
url: /v1alpha1/graphql
|
||||
status: 400
|
||||
headers:
|
||||
X-Hasura-Role: infant
|
||||
X-Hasura-Infant-Id: '1'
|
||||
X-Hasura-Infant-Name: 'Bittu'
|
||||
query:
|
||||
query: |
|
||||
mutation {
|
||||
insert_resident(
|
||||
objects: [
|
||||
{
|
||||
age: 3
|
||||
is_user: true
|
||||
}
|
||||
]
|
||||
){
|
||||
affected_rows
|
||||
returning{
|
||||
id
|
||||
name
|
||||
age
|
||||
is_user
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -222,3 +222,33 @@ args:
|
||||
- is_user
|
||||
filter:
|
||||
id: X-Hasura-Resident-Id
|
||||
|
||||
#Create insert permission for infant on resident
|
||||
- type: create_insert_permission
|
||||
args:
|
||||
table: resident
|
||||
role: infant
|
||||
permission:
|
||||
check:
|
||||
id: X-Hasura-Infant-Id
|
||||
allow_upsert: false
|
||||
set:
|
||||
name: X-Hasura-Infant-Name
|
||||
id: X-Hasura-Infant-Id
|
||||
columns:
|
||||
- age
|
||||
|
||||
#Create select permission for infant on resident
|
||||
- type: create_select_permission
|
||||
args:
|
||||
table: resident
|
||||
role: infant
|
||||
permission:
|
||||
columns:
|
||||
- id
|
||||
- name
|
||||
- age
|
||||
- is_user
|
||||
filter:
|
||||
id: X-Hasura-Infant-Id
|
||||
|
||||
|
||||
@@ -117,6 +117,12 @@ class TestGraphqlInsertPermission(DefaultTestQueries):
|
||||
def test_resident_user_role_insert(self, hge_ctx):
|
||||
check_query_f(hge_ctx, self.dir() + "/resident_user.yaml")
|
||||
|
||||
def test_resident_infant_role_insert(self, hge_ctx):
|
||||
check_query_f(hge_ctx, self.dir() + "/resident_infant.yaml")
|
||||
|
||||
def test_resident_infant_role_insert_fail(self, hge_ctx):
|
||||
check_query_f(hge_ctx, self.dir() + "/resident_infant_fail.yaml")
|
||||
|
||||
@classmethod
|
||||
def dir(cls):
|
||||
return "queries/graphql_mutation/insert/permissions"
|
||||
|
||||
Reference in New Issue
Block a user