mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
(core) update read access for exceptional sessions
Summary: Exceptional sessions had lost full read access to documents; this restores it. Exceptional sessions are used for system actions or while creating documents. Test Plan: added test Reviewers: alexmojaki Reviewed By: alexmojaki Differential Revision: https://phab.getgrist.com/D2966
This commit is contained in:
parent
4ca47878ca
commit
4a23b964ed
@ -653,6 +653,13 @@ export class GranularAccess implements GranularAccessForBundle {
|
|||||||
* access level and any row-level access functions needed.
|
* access level and any row-level access functions needed.
|
||||||
*/
|
*/
|
||||||
public async getTableAccess(docSession: OptDocSession, tableId: string): Promise<TablePermissionSetWithContext> {
|
public async getTableAccess(docSession: OptDocSession, tableId: string): Promise<TablePermissionSetWithContext> {
|
||||||
|
if (this._hasExceptionalFullAccess(docSession)) {
|
||||||
|
return {
|
||||||
|
perms: {read: 'allow', create: 'allow', delete: 'allow', update: 'allow', schemaEdit: 'allow'},
|
||||||
|
ruleType: 'table',
|
||||||
|
getMemos() { throw new Error('never needed'); }
|
||||||
|
};
|
||||||
|
}
|
||||||
return (await this._getAccess(docSession)).getTableAccess(tableId);
|
return (await this._getAccess(docSession)).getTableAccess(tableId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -665,6 +672,7 @@ export class GranularAccess implements GranularAccessForBundle {
|
|||||||
const cursor: ActionCursor = {docSession, action: data, actionIdx: null};
|
const cursor: ActionCursor = {docSession, action: data, actionIdx: null};
|
||||||
const tableId = getTableId(data);
|
const tableId = getTableId(data);
|
||||||
if (this.getReadPermission(permInfo.getTableAccess(tableId)) === 'mixed') {
|
if (this.getReadPermission(permInfo.getTableAccess(tableId)) === 'mixed') {
|
||||||
|
const readAccessCheck = this._readAccessCheck(docSession);
|
||||||
await this._filterRowsAndCells(cursor, data, data, readAccessCheck, true);
|
await this._filterRowsAndCells(cursor, data, data, readAccessCheck, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -684,7 +692,7 @@ export class GranularAccess implements GranularAccessForBundle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public assertCanRead(ps: PermissionSetWithContext) {
|
public assertCanRead(ps: PermissionSetWithContext) {
|
||||||
readAccessCheck.throwIfDenied(ps);
|
accessChecks.fatal.read.get(ps);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -734,6 +742,18 @@ export class GranularAccess implements GranularAccessForBundle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The AccessCheck for the "read" permission is used enough to merit a shortcut.
|
||||||
|
// We just need to be careful to retain unfettered access for exceptional sessions.
|
||||||
|
private _readAccessCheck(docSession: OptDocSession): IAccessCheck {
|
||||||
|
return this._hasExceptionalFullAccess(docSession) ? dummyAccessCheck : accessChecks.check.read;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return true for special system sessions or document-creation sessions, where
|
||||||
|
// unfettered access is appropriate.
|
||||||
|
private _hasExceptionalFullAccess(docSession: OptDocSession): Boolean {
|
||||||
|
return docSession.mode === 'system' || docSession.mode === 'nascent';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This filters a message being broadcast to all clients to be appropriate for one
|
* This filters a message being broadcast to all clients to be appropriate for one
|
||||||
* particular client, if that client may need some material filtered out.
|
* particular client, if that client may need some material filtered out.
|
||||||
@ -909,6 +929,7 @@ export class GranularAccess implements GranularAccessForBundle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Return the results, also applying any cell-level access control.
|
// Return the results, also applying any cell-level access control.
|
||||||
|
const readAccessCheck = this._readAccessCheck(cursor.docSession);
|
||||||
for (const a of revisedDocActions) {
|
for (const a of revisedDocActions) {
|
||||||
await this._filterRowsAndCells({...cursor, action: a}, rowsAfter, rowsAfter, readAccessCheck, false);
|
await this._filterRowsAndCells({...cursor, action: a}, rowsAfter, rowsAfter, readAccessCheck, false);
|
||||||
}
|
}
|
||||||
@ -1518,6 +1539,7 @@ export class GranularAccess implements GranularAccessForBundle {
|
|||||||
const permInfo = await this._getStepAccess(cursor);
|
const permInfo = await this._getStepAccess(cursor);
|
||||||
const tableAccess = permInfo.getTableAccess(tableId);
|
const tableAccess = permInfo.getTableAccess(tableId);
|
||||||
const access = this.getReadPermission(tableAccess);
|
const access = this.getReadPermission(tableAccess);
|
||||||
|
const readAccessCheck = this._readAccessCheck(cursor.docSession);
|
||||||
const results: DocAction[] = [];
|
const results: DocAction[] = [];
|
||||||
if (access === 'deny') {
|
if (access === 'deny') {
|
||||||
// filter out this data.
|
// filter out this data.
|
||||||
@ -1636,7 +1658,7 @@ export class GranularAccess implements GranularAccessForBundle {
|
|||||||
// TODO: deal with ReplaceTableData, which both deletes and creates rows.
|
// TODO: deal with ReplaceTableData, which both deletes and creates rows.
|
||||||
private async _getAccessForActionType(docSession: OptDocSession, a: DocAction,
|
private async _getAccessForActionType(docSession: OptDocSession, a: DocAction,
|
||||||
severity: 'check'|'fatal'): Promise<IAccessCheck> {
|
severity: 'check'|'fatal'): Promise<IAccessCheck> {
|
||||||
if (docSession.mode === 'system' || docSession.mode === 'nascent') {
|
if (this._hasExceptionalFullAccess(docSession)) {
|
||||||
return dummyAccessCheck;
|
return dummyAccessCheck;
|
||||||
}
|
}
|
||||||
const tableId = getTableId(a);
|
const tableId = getTableId(a);
|
||||||
@ -1821,6 +1843,7 @@ class UserAttributes {
|
|||||||
|
|
||||||
interface IAccessCheck {
|
interface IAccessCheck {
|
||||||
get(ps: PermissionSetWithContext): string;
|
get(ps: PermissionSetWithContext): string;
|
||||||
|
throwIfDenied(ps: PermissionSetWithContext): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
class AccessCheck implements IAccessCheck {
|
class AccessCheck implements IAccessCheck {
|
||||||
@ -1852,11 +1875,11 @@ export const accessChecks = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// The AccessCheck for the "read" permission is used enough to merit a shortcut.
|
|
||||||
const readAccessCheck = accessChecks.check.read;
|
|
||||||
|
|
||||||
// This AccessCheck allows everything.
|
// This AccessCheck allows everything.
|
||||||
const dummyAccessCheck = { get() { return 'allow'; } };
|
const dummyAccessCheck: IAccessCheck = {
|
||||||
|
get() { return 'allow'; },
|
||||||
|
throwIfDenied() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user