mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) implement cleaner row-level access control for outgoing messages
Summary: This implements row-level access control for outgoing messages, replacing the document reloading placeholder that was there before. * Prior to broadcasting messages, GranularAccess is notified of actions+undo. * While broadcasting messages to different sessions, if we find we need row level access control information, rows before and after the change are reconstructed. * Messages are rewritten if rows that were previously forbidden are now allowed, and vice versa. The diff is somewhat under-tested and under-optimized. Next step would be to implement row-level access control for incoming actions, which may result in some rejiggering of the code from this diff to avoid duplication of effort under some conditions. Test Plan: added test Reviewers: dsagal Reviewed By: dsagal Differential Revision: https://phab.getgrist.com/D2670
This commit is contained in:
@@ -16,8 +16,14 @@ type FetchTableFunc = (tableId: string) => Promise<TableDataAction>;
|
||||
export class DocData extends ActionDispatcher {
|
||||
private _tables: Map<string, TableData> = new Map();
|
||||
|
||||
constructor(private _fetchTableFunc: FetchTableFunc, metaTableData: {[tableId: string]: TableDataAction}) {
|
||||
/**
|
||||
* If metaTableData is not supplied, then any tables needed should be loaded manually,
|
||||
* using syncTable(). All column types will be set to Any, which will affect default
|
||||
* values.
|
||||
*/
|
||||
constructor(private _fetchTableFunc: FetchTableFunc, metaTableData: {[tableId: string]: TableDataAction} | null) {
|
||||
super();
|
||||
if (metaTableData === null) { return; }
|
||||
// Create all meta tables, and populate data we already have.
|
||||
for (const tableId in schema) {
|
||||
if (schema.hasOwnProperty(tableId)) {
|
||||
@@ -67,6 +73,17 @@ export class DocData extends ActionDispatcher {
|
||||
return (!table.isLoaded || force) ? table.fetchData(this._fetchTableFunc) : Promise.resolve();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the data for tableId unconditionally, and without knowledge of its metadata.
|
||||
* Columns will be assumed to have type 'Any'.
|
||||
*/
|
||||
public async syncTable(tableId: string): Promise<void> {
|
||||
const tableData = await this._fetchTableFunc(tableId);
|
||||
const colTypes = fromPairs(Object.keys(tableData[3]).map(c => [c, 'Any']));
|
||||
colTypes.id = 'Any';
|
||||
this._tables.set(tableId, this.createTableData(tableId, tableData, colTypes));
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles an action received from the server, by forwarding it to the appropriate TableData
|
||||
* object.
|
||||
|
||||
Reference in New Issue
Block a user