mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
(core) Hiding helper columns used for column transformation
Summary: When a column is transformed, it creates two helper columns whose values are always broadcasted to all clients. Now when there are some ACL rules, we are going to prune those columns from messages sent to other connected clients. Test Plan: Added new tests Reviewers: dsagal, paulfitz Reviewed By: dsagal, paulfitz Subscribers: dsagal Differential Revision: https://phab.getgrist.com/D3728
This commit is contained in:
parent
1a4561dbf2
commit
2a86cde474
@ -31,7 +31,7 @@ export type TableDataAction = ['TableData', string, number[], BulkColValues];
|
||||
export type AddColumn = ['AddColumn', string, string, ColInfo];
|
||||
export type RemoveColumn = ['RemoveColumn', string, string];
|
||||
export type RenameColumn = ['RenameColumn', string, string, string];
|
||||
export type ModifyColumn = ['ModifyColumn', string, string, ColInfo];
|
||||
export type ModifyColumn = ['ModifyColumn', string, string, Partial<ColInfo>];
|
||||
|
||||
export type AddTable = ['AddTable', string, ColInfoWithId[]];
|
||||
export type RemoveTable = ['RemoveTable', string];
|
||||
|
@ -40,7 +40,8 @@ import { getDocSessionAccess, getDocSessionAltSessionId, getDocSessionUser,
|
||||
OptDocSession } from 'app/server/lib/DocSession';
|
||||
import { DocStorage, REMOVE_UNUSED_ATTACHMENTS_DELAY } from 'app/server/lib/DocStorage';
|
||||
import log from 'app/server/lib/log';
|
||||
import { IPermissionInfo, PermissionInfo, PermissionSetWithContext } from 'app/server/lib/PermissionInfo';
|
||||
import { IPermissionInfo, MixedPermissionSetWithContext,
|
||||
PermissionInfo, PermissionSetWithContext } from 'app/server/lib/PermissionInfo';
|
||||
import { TablePermissionSetWithContext } from 'app/server/lib/PermissionInfo';
|
||||
import { integerParam } from 'app/server/lib/requestUtils';
|
||||
import { getColIdsFromDocAction, getColValuesFromDocAction, getRelatedRows,
|
||||
@ -191,6 +192,17 @@ const UPLOADED_ATTACHMENT_OWNERSHIP_PERIOD =
|
||||
// older than this limit.
|
||||
const HISTORICAL_ATTACHMENT_OWNERSHIP_PERIOD = 24 * 60 * 60 * 1000;
|
||||
|
||||
// Transform columns are special. In case we have some rules defined they are only visible
|
||||
// to those with SCHEMA_EDIT permission.
|
||||
const TRANSFORM_COLUMN_PREFIXES = ['gristHelper_Converted', 'gristHelper_Transform'];
|
||||
|
||||
/**
|
||||
* Checks if this is a special helper column used during type conversion.
|
||||
*/
|
||||
function isTransformColumn(colId: string): boolean {
|
||||
return TRANSFORM_COLUMN_PREFIXES.some(prefix => colId.startsWith(prefix));
|
||||
}
|
||||
|
||||
interface DocUpdateMessage {
|
||||
actionGroup: ActionGroup;
|
||||
docActions: DocAction[];
|
||||
@ -1324,6 +1336,7 @@ export class GranularAccess implements GranularAccessForBundle {
|
||||
*/
|
||||
private _pruneColumns(a: DocAction, permInfo: IPermissionInfo, tableId: string,
|
||||
accessCheck: IAccessCheck): DocAction|null {
|
||||
permInfo = new TransformColumnPermissionInfo(permInfo);
|
||||
if (a[0] === 'RemoveRecord' || a[0] === 'BulkRemoveRecord') {
|
||||
return a;
|
||||
} else if (a[0] === 'AddRecord' || a[0] === 'BulkAddRecord' || a[0] === 'UpdateRecord' ||
|
||||
@ -2856,6 +2869,9 @@ export class CensorshipInfo {
|
||||
(colId !== 'manualSort' && permInfo.getColumnAccess(tableId, colId).perms.read === 'deny')) {
|
||||
censoredColumnCodes.add(columnCode(tableRef, colId));
|
||||
}
|
||||
if (isTransformColumn(colId) && permInfo.getColumnAccess(tableId, colId).perms.schemaEdit === 'deny') {
|
||||
censoredColumnCodes.add(columnCode(tableRef, colId));
|
||||
}
|
||||
}
|
||||
// Collect a list of all sections and views containing a table to which the user has no access.
|
||||
rec = new RecordView(tables._grist_Views_section, undefined);
|
||||
@ -3158,6 +3174,42 @@ function actionHasRuleChange(a: DocAction): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper around a permission info object that overrides permissions for transform columns.
|
||||
*/
|
||||
class TransformColumnPermissionInfo implements IPermissionInfo {
|
||||
constructor(private _inner: IPermissionInfo) {
|
||||
|
||||
}
|
||||
public getColumnAccess(tableId: string, colId: string): MixedPermissionSetWithContext {
|
||||
const access = this._inner.getColumnAccess(tableId, colId);
|
||||
const isSchemaDenied = access.perms.schemaEdit === 'deny';
|
||||
// If this is a transform column, it's only accessible if the user has a schemaEdit access.
|
||||
if (isSchemaDenied && isTransformColumn(colId)) {
|
||||
return {
|
||||
...access,
|
||||
perms: {
|
||||
create: 'deny',
|
||||
read: 'deny',
|
||||
update: 'deny',
|
||||
delete: 'deny',
|
||||
schemaEdit: 'deny',
|
||||
}
|
||||
};
|
||||
}
|
||||
return access;
|
||||
}
|
||||
public getTableAccess(tableId: string): TablePermissionSetWithContext {
|
||||
return this._inner.getTableAccess(tableId);
|
||||
}
|
||||
public getFullAccess(): MixedPermissionSetWithContext {
|
||||
return this._inner.getFullAccess();
|
||||
}
|
||||
public getRuleCollection(): ACLRuleCollection {
|
||||
return this._inner.getRuleCollection();
|
||||
}
|
||||
}
|
||||
|
||||
interface SingleCellInfo extends SingleCell {
|
||||
userRef: string;
|
||||
id: number;
|
||||
|
Loading…
Reference in New Issue
Block a user