mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) implement authorization via query parameter
Summary: This adds any parameters in a document url whose key ends in '_' into a `user.Link` object available in access control formulas and in setting up characteristic tables. This allows, for example, sending links to a document that contain a hard-to-guess token, and having that link grant access to a controlled part of the document (invoices for a specific customer for example). A `user.Origin` field is also added, set during rest api calls, but is only tested manually at this point. It could be elaborated for embedding use-cases. Test Plan: added test Reviewers: dsagal Reviewed By: dsagal Differential Revision: https://phab.getgrist.com/D2680
This commit is contained in:
@@ -80,5 +80,6 @@ export interface DocListAPI {
|
||||
/**
|
||||
* Opens a document, loads it, subscribes to its userAction events, and returns its metadata.
|
||||
*/
|
||||
openDoc(userDocName: string, openMode?: OpenDocMode): Promise<OpenLocalDocResult>;
|
||||
openDoc(userDocName: string, openMode?: OpenDocMode,
|
||||
linkParameters?: Record<string, string>): Promise<OpenLocalDocResult>;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ export interface InfoView {
|
||||
}
|
||||
|
||||
// Represents user info, which may include properties which are themselves RowRecords.
|
||||
export type UserInfo = Record<string, CellValue|InfoView>;
|
||||
export type UserInfo = Record<string, CellValue|InfoView|Record<string, string>>;
|
||||
|
||||
/**
|
||||
* Input into the AclMatchFunc. Compiled formulas evaluate AclMatchInput to produce a boolean.
|
||||
|
||||
@@ -3,7 +3,6 @@ import {OpenDocMode} from 'app/common/DocListAPI';
|
||||
import {encodeQueryParams, isAffirmative} from 'app/common/gutil';
|
||||
import {localhostRegex} from 'app/common/LoginState';
|
||||
import {Document} from 'app/common/UserAPI';
|
||||
import identity = require('lodash/identity');
|
||||
import pickBy = require('lodash/pickBy');
|
||||
import {StringUnion} from './StringUnion';
|
||||
|
||||
@@ -67,6 +66,8 @@ export interface IGristUrlState {
|
||||
style?: InterfaceStyle;
|
||||
compare?: string;
|
||||
aclUI?: boolean;
|
||||
linkParameters?: Record<string, string>; // Parameters to pass as 'user.Link' in granular ACLs.
|
||||
// Encoded in URL as query params with extra '_' suffix.
|
||||
};
|
||||
hash?: HashLink; // if present, this specifies an individual row within a section of a page.
|
||||
}
|
||||
@@ -173,10 +174,13 @@ export function encodeUrl(gristConfig: Partial<GristLoadConfig>,
|
||||
parts.push(`welcome/${state.welcome}`);
|
||||
}
|
||||
|
||||
const queryParams = pickBy(state.params, identity) as {[key: string]: string};
|
||||
const queryParams = pickBy(state.params, (v, k) => k !== 'linkParameters') as {[key: string]: string};
|
||||
if (state.newui !== undefined) {
|
||||
queryParams.newui = state.newui ? '1' : '0';
|
||||
}
|
||||
for (const [k, v] of Object.entries(state.params?.linkParameters || {})) {
|
||||
queryParams[`${k}_`] = v;
|
||||
}
|
||||
const hashParts: string[] = [];
|
||||
if (state.hash && state.hash.rowId) {
|
||||
const hash = state.hash;
|
||||
@@ -264,6 +268,12 @@ export function decodeUrl(gristConfig: Partial<GristLoadConfig>, location: Locat
|
||||
if (sp.has('aclUI')) {
|
||||
state.params!.aclUI = isAffirmative(sp.get('aclUI'));
|
||||
}
|
||||
for (const [k, v] of sp.entries()) {
|
||||
if (k.endsWith('_')) {
|
||||
if (!state.params!.linkParameters) { state.params!.linkParameters = {}; }
|
||||
state.params!.linkParameters[k.slice(0, k.length - 1)] = v;
|
||||
}
|
||||
}
|
||||
if (location.hash) {
|
||||
const hash = location.hash;
|
||||
const hashParts = hash.split('.');
|
||||
|
||||
Reference in New Issue
Block a user