mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 01:12:56 +03:00
console: Separate update into pre_update and post_update
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/8918 GitOrigin-RevId: b7e066e951158f5ce1dafb062aef5cc1332d617f
This commit is contained in:
parent
f4f1c9f0df
commit
48341c1ff9
@ -140,7 +140,7 @@ const Component = (props: ComponentProps) => {
|
||||
table={table}
|
||||
roleName={roleName}
|
||||
queryType={queryType}
|
||||
subQueryType={queryType === 'update' ? 'pre' : undefined}
|
||||
subQueryType={queryType === 'update' ? 'pre_update' : undefined}
|
||||
permissionsKey={filterKeys[0]}
|
||||
dataSourceName={dataSourceName}
|
||||
supportedOperators={data?.defaultValues?.supportedOperators ?? []}
|
||||
@ -157,7 +157,9 @@ const Component = (props: ComponentProps) => {
|
||||
table={table}
|
||||
roleName={roleName}
|
||||
queryType={queryType}
|
||||
subQueryType={queryType === 'update' ? 'post' : undefined}
|
||||
subQueryType={
|
||||
queryType === 'update' ? 'post_update' : undefined
|
||||
}
|
||||
permissionsKey={filterKeys[1]}
|
||||
dataSourceName={dataSourceName}
|
||||
supportedOperators={
|
||||
|
@ -20,7 +20,7 @@ test('create select args object from form data', () => {
|
||||
permission: {
|
||||
columns: ['AlbumId', 'Title', 'ArtistId'],
|
||||
filter: { _not: { AlbumId: { _eq: 'X-Hasura-User-Id' } } },
|
||||
set: [],
|
||||
set: {},
|
||||
allow_aggregations: false,
|
||||
},
|
||||
source: 'Chinook',
|
||||
|
@ -48,7 +48,7 @@ const createSelectObject = (input: PermissionsSchema) => {
|
||||
const permissionObject: SelectPermissionMetadata = {
|
||||
columns,
|
||||
filter,
|
||||
set: [],
|
||||
set: {},
|
||||
allow_aggregations: input.aggregationEnabled,
|
||||
};
|
||||
|
||||
|
@ -16,6 +16,7 @@ import { QueryType } from '../../types';
|
||||
import { ReturnValue } from '../hooks';
|
||||
import { useMetadataTable } from '../../../hasura-metadata-api/metadataHooks';
|
||||
import { getNonSelectedQueryTypePermissions } from '../utils/getMapQueryTypePermissions';
|
||||
import { copyQueryTypePermissions } from '../utils/copyQueryTypePermissions';
|
||||
|
||||
const NoChecksLabel = () => (
|
||||
<span data-test="without-checks">Without any checks </span>
|
||||
@ -31,7 +32,7 @@ const CustomLabel = () => (
|
||||
export interface RowPermissionsProps {
|
||||
table: unknown;
|
||||
queryType: QueryType;
|
||||
subQueryType?: string;
|
||||
subQueryType?: 'pre_update' | 'post_update';
|
||||
dataSourceName: string;
|
||||
supportedOperators: Operator[];
|
||||
defaultValues: ReturnValue['defaultValues'];
|
||||
@ -49,39 +50,32 @@ enum SelectedSection {
|
||||
delete = 'delete',
|
||||
}
|
||||
|
||||
const getRowPermission = (queryType: QueryType, subQueryType?: string) => {
|
||||
if (queryType === 'insert') {
|
||||
export type RowPermissionsSectionType =
|
||||
| QueryType
|
||||
| 'pre_update'
|
||||
| 'post_update';
|
||||
|
||||
export const getRowPermission = (
|
||||
queryType: RowPermissionsSectionType
|
||||
): 'filter' | 'check' => {
|
||||
if (queryType === 'pre_update') {
|
||||
return 'filter';
|
||||
}
|
||||
if (queryType === 'post_update') {
|
||||
return 'check';
|
||||
}
|
||||
|
||||
if (queryType === 'update') {
|
||||
if (subQueryType === 'post') {
|
||||
return 'check';
|
||||
}
|
||||
|
||||
return 'filter';
|
||||
if (queryType === 'insert') {
|
||||
return 'check';
|
||||
}
|
||||
|
||||
return 'filter';
|
||||
};
|
||||
|
||||
const getRowPermissionCheckType = (
|
||||
queryType: QueryType,
|
||||
subQueryType?: string
|
||||
) => {
|
||||
if (queryType === 'insert') {
|
||||
return 'checkType';
|
||||
}
|
||||
|
||||
if (queryType === 'update') {
|
||||
if (subQueryType === 'post') {
|
||||
return 'checkType';
|
||||
}
|
||||
|
||||
return 'filterType';
|
||||
}
|
||||
|
||||
return 'filterType';
|
||||
queryType: RowPermissionsSectionType
|
||||
): 'filterType' | 'checkType' => {
|
||||
const permissionType = getRowPermission(queryType);
|
||||
return permissionType === 'filter' ? 'filterType' : 'checkType';
|
||||
};
|
||||
|
||||
const useTypeName = ({
|
||||
@ -153,16 +147,17 @@ export const RowPermissionsSection: React.FC<RowPermissionsProps> = ({
|
||||
roleName
|
||||
);
|
||||
|
||||
const { watch, setValue, reset, getValues } = useFormContext();
|
||||
const { watch, setValue } = useFormContext();
|
||||
// determines whether the inputs should be pointed at `check` or `filter`
|
||||
const rowPermissions = getRowPermission(queryType, subQueryType);
|
||||
const rowPermissions = getRowPermission(subQueryType ?? queryType);
|
||||
|
||||
// determines whether the check type should be pointer at `checkType` or `filterType`
|
||||
const rowPermissionsCheckType = getRowPermissionCheckType(
|
||||
queryType,
|
||||
subQueryType
|
||||
subQueryType ?? queryType
|
||||
);
|
||||
|
||||
const selectedSection = watch(rowPermissionsCheckType);
|
||||
|
||||
return (
|
||||
<fieldset key={queryType} className="grid gap-2">
|
||||
<div>
|
||||
@ -216,13 +211,14 @@ export const RowPermissionsSection: React.FC<RowPermissionsProps> = ({
|
||||
value={type}
|
||||
checked={selectedSection === type}
|
||||
onClick={() => {
|
||||
reset({
|
||||
...getValues(),
|
||||
...data,
|
||||
queryType,
|
||||
});
|
||||
|
||||
setValue(rowPermissionsCheckType, type);
|
||||
const newValues = copyQueryTypePermissions(
|
||||
type,
|
||||
queryType,
|
||||
subQueryType,
|
||||
data
|
||||
);
|
||||
setValue(...newValues);
|
||||
}}
|
||||
/>
|
||||
<span data-test="mutual-check">
|
||||
@ -234,7 +230,9 @@ export const RowPermissionsSection: React.FC<RowPermissionsProps> = ({
|
||||
<div
|
||||
// Permissions are not otherwise stored in plan JSON format in the dom.
|
||||
// This is a hack to get the JSON into the dom for testing.
|
||||
data-state={JSON.stringify(data[getRowPermission(type)])}
|
||||
data-state={JSON.stringify(
|
||||
getRowPermission(type) ? data?.[getRowPermission(type)] : {}
|
||||
)}
|
||||
data-testid="external-check-json-editor"
|
||||
className="mt-4 p-6 rounded-lg bg-white border border-gray-200 min-h-32 w-full"
|
||||
>
|
||||
|
@ -0,0 +1,19 @@
|
||||
import { copyQueryTypePermissions } from './copyQueryTypePermissions';
|
||||
|
||||
describe('copyQueryTypePermissions should', () => {
|
||||
test('handle pre_update mapping', () => {
|
||||
const result = copyQueryTypePermissions('insert', 'update', 'pre_update', {
|
||||
check: { Name: { _eq: 'select' } },
|
||||
columns: {},
|
||||
});
|
||||
expect(result).toEqual(['filter', { Name: { _eq: 'select' } }]);
|
||||
});
|
||||
|
||||
test('handle pre_update mapping', () => {
|
||||
const result = copyQueryTypePermissions('insert', 'update', 'post_update', {
|
||||
check: { Name: { _eq: 'insert' } },
|
||||
columns: {},
|
||||
});
|
||||
expect(result).toEqual(['check', { Name: { _eq: 'insert' } }]);
|
||||
});
|
||||
});
|
@ -0,0 +1,22 @@
|
||||
import {
|
||||
RowPermissionsSectionType,
|
||||
getRowPermission,
|
||||
} from '../components/RowPermissions';
|
||||
|
||||
export const copyQueryTypePermissions = (
|
||||
permissoinType: RowPermissionsSectionType,
|
||||
queryType: RowPermissionsSectionType,
|
||||
subQueryType: 'pre_update' | 'post_update' | undefined,
|
||||
data: Record<string, any>
|
||||
): [string, Record<string, string>] => {
|
||||
const mappedType = getRowPermission(permissoinType);
|
||||
if (subQueryType) {
|
||||
// This only applies to the visual section of 'pre_update' and 'post_update'
|
||||
const mappedsubQueryType = getRowPermission(subQueryType);
|
||||
return [mappedsubQueryType, data[mappedType]];
|
||||
}
|
||||
// This only applies to the real query types 'select', 'insert', 'update', 'delete'
|
||||
// It has to take the special cases of 'pre_update' and 'post_update' into account when mapping values from the update permissions
|
||||
const mappedQueryType = getRowPermission(queryType);
|
||||
return [mappedQueryType, data[mappedType]];
|
||||
};
|
@ -49,7 +49,15 @@ describe('getMapQueryTypePermissions should', () => {
|
||||
},
|
||||
},
|
||||
{
|
||||
queryType: 'update',
|
||||
queryType: 'pre_update',
|
||||
data: {
|
||||
columns: { Title: true },
|
||||
filter: { Title: { _eq: 'X-Hasura-User-Id' } },
|
||||
check: { Title: { _eq: 'X-Hasura-User-Id' } },
|
||||
},
|
||||
},
|
||||
{
|
||||
queryType: 'post_update',
|
||||
data: {
|
||||
columns: { Title: true },
|
||||
filter: { Title: { _eq: 'X-Hasura-User-Id' } },
|
||||
|
@ -14,7 +14,6 @@ const getPermissionsMappedByRole = ({
|
||||
key,
|
||||
currentRole,
|
||||
currentQueryType,
|
||||
tally,
|
||||
queryType,
|
||||
}: {
|
||||
tableData: MetadataTable;
|
||||
@ -25,7 +24,6 @@ const getPermissionsMappedByRole = ({
|
||||
| 'update_permissions';
|
||||
currentRole: string;
|
||||
currentQueryType: string;
|
||||
tally: Record<string, any>[];
|
||||
queryType: string;
|
||||
}) => {
|
||||
const permissions =
|
||||
@ -34,21 +32,24 @@ const getPermissionsMappedByRole = ({
|
||||
tableData?.[key]?.find(
|
||||
(data: { role: string }) => data.role === currentRole
|
||||
)?.permission;
|
||||
if (!permissions) return tally;
|
||||
if (currentQueryType === 'update' || currentQueryType === 'insert') {
|
||||
if (!permissions) return null;
|
||||
if (currentQueryType === 'pre_update') {
|
||||
if (!permissions.check) permissions.check = permissions?.filter;
|
||||
}
|
||||
if (currentQueryType === 'post_update') {
|
||||
if (!permissions.filter) permissions.filter = permissions?.check;
|
||||
}
|
||||
if (currentQueryType === 'insert') {
|
||||
if (!permissions.check) permissions.check = permissions?.filter;
|
||||
} else if (currentQueryType === 'select' || currentQueryType === 'delete') {
|
||||
if (!permissions.filter) permissions.filter = permissions?.check;
|
||||
}
|
||||
permissions.columns = formatColumns(permissions.columns);
|
||||
|
||||
return [
|
||||
...tally,
|
||||
{
|
||||
queryType,
|
||||
data: permissions,
|
||||
},
|
||||
];
|
||||
return {
|
||||
queryType,
|
||||
data: permissions,
|
||||
};
|
||||
};
|
||||
|
||||
export const getNonSelectedQueryTypePermissions = (
|
||||
@ -67,49 +68,64 @@ export const getNonSelectedQueryTypePermissions = (
|
||||
key === 'delete_permissions' ||
|
||||
key === 'insert_permissions'
|
||||
)
|
||||
?.reduce((tally: Record<string, any>[], key: string) => {
|
||||
?.reduce((tally: any[], key: string) => {
|
||||
if (key === 'select_permissions' && currentQueryType !== 'select') {
|
||||
return getPermissionsMappedByRole({
|
||||
tableData,
|
||||
key,
|
||||
currentRole,
|
||||
currentQueryType,
|
||||
tally,
|
||||
queryType: 'select',
|
||||
});
|
||||
return [
|
||||
...tally,
|
||||
getPermissionsMappedByRole({
|
||||
tableData,
|
||||
key,
|
||||
currentRole,
|
||||
currentQueryType,
|
||||
queryType: 'select',
|
||||
}),
|
||||
].filter(Boolean);
|
||||
}
|
||||
if (key === 'update_permissions' && currentQueryType !== 'update') {
|
||||
return getPermissionsMappedByRole({
|
||||
const pre = getPermissionsMappedByRole({
|
||||
tableData,
|
||||
key,
|
||||
currentRole,
|
||||
currentQueryType,
|
||||
tally,
|
||||
queryType: 'update',
|
||||
currentQueryType: 'pre_update',
|
||||
queryType: 'pre_update',
|
||||
});
|
||||
const post = getPermissionsMappedByRole({
|
||||
tableData,
|
||||
key,
|
||||
currentRole,
|
||||
currentQueryType: 'post_update',
|
||||
queryType: 'post_update',
|
||||
});
|
||||
|
||||
return [...tally, pre, post].filter(Boolean);
|
||||
}
|
||||
|
||||
if (key === 'delete_permissions' && currentQueryType !== 'delete') {
|
||||
return getPermissionsMappedByRole({
|
||||
tableData,
|
||||
key,
|
||||
currentRole,
|
||||
currentQueryType,
|
||||
tally,
|
||||
queryType: 'delete',
|
||||
});
|
||||
return [
|
||||
...tally,
|
||||
getPermissionsMappedByRole({
|
||||
tableData,
|
||||
key,
|
||||
currentRole,
|
||||
currentQueryType,
|
||||
queryType: 'delete',
|
||||
}),
|
||||
].filter(Boolean);
|
||||
}
|
||||
|
||||
if (key === 'insert_permissions' && currentQueryType !== 'insert') {
|
||||
return getPermissionsMappedByRole({
|
||||
tableData,
|
||||
key,
|
||||
currentRole,
|
||||
currentQueryType,
|
||||
tally,
|
||||
queryType: 'insert',
|
||||
});
|
||||
return [
|
||||
...tally,
|
||||
getPermissionsMappedByRole({
|
||||
tableData,
|
||||
key,
|
||||
currentRole,
|
||||
currentQueryType,
|
||||
queryType: 'insert',
|
||||
}),
|
||||
].filter(Boolean);
|
||||
}
|
||||
|
||||
return tally;
|
||||
}, []);
|
||||
|
||||
|
@ -57,7 +57,7 @@ GDCUpdateTableCloneSelectPermission.play = async ({ canvasElement }) => {
|
||||
|
||||
await userEvent.click(tableUserUpdateButton);
|
||||
const selectCheckbox = await canvas.findByTestId(
|
||||
'external-user-select-input-pre'
|
||||
'external-user-select-input-pre_update'
|
||||
);
|
||||
await userEvent.click(selectCheckbox);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user