(core) updates from grist-core

This commit is contained in:
Paul Fitzpatrick
2024-01-08 09:19:50 -05:00
11 changed files with 155 additions and 44 deletions

View File

@@ -26,6 +26,9 @@
* If omitted, the name will either be the concatenation of "given_name" + "family_name" or the "name" attribute.
* env GRIST_OIDC_SP_PROFILE_EMAIL_ATTR
* The key of the attribute to use for the user's email. Defaults to "email".
* env GRIST_OIDC_IDP_END_SESSION_ENDPOINT
* If set, overrides the IdP's end_session_endpoint with an alternative URL to redirect user upon logout
* (for an IdP that has a logout endpoint but does not support the OIDC RP-Initiated Logout specification).
* env GRIST_OIDC_IDP_SKIP_END_SESSION_ENDPOINT
* If set to "true", on logout, there won't be any attempt to call the IdP's end_session_endpoint
* (the user will remain logged in in the IdP).
@@ -63,6 +66,7 @@ export class OIDCConfig {
private _redirectUrl: string;
private _namePropertyKey?: string;
private _emailPropertyKey: string;
private _endSessionEndpoint: string;
private _skipEndSessionEndpoint: boolean;
private _ignoreEmailVerified: boolean;
@@ -94,6 +98,11 @@ export class OIDCConfig {
defaultValue: 'email',
});
this._endSessionEndpoint = section.flag('endSessionEndpoint').readString({
envVar: 'GRIST_OIDC_IDP_END_SESSION_ENDPOINT',
defaultValue: '',
})!;
this._skipEndSessionEndpoint = section.flag('skipEndSessionEndpoint').readBool({
envVar: 'GRIST_OIDC_IDP_SKIP_END_SESSION_ENDPOINT',
defaultValue: false,
@@ -112,9 +121,11 @@ export class OIDCConfig {
redirect_uris: [ this._redirectUrl ],
response_types: [ 'code' ],
});
if (this._client.issuer.metadata.end_session_endpoint === undefined && !this._skipEndSessionEndpoint) {
if (this._client.issuer.metadata.end_session_endpoint === undefined &&
!this._endSessionEndpoint && !this._skipEndSessionEndpoint) {
throw new Error('The Identity provider does not propose end_session_endpoint. ' +
'If that is expected, please set GRIST_OIDC_IDP_SKIP_END_SESSION_ENDPOINT=true');
'If that is expected, please set GRIST_OIDC_IDP_SKIP_END_SESSION_ENDPOINT=true ' +
'or provide an alternative logout URL in GRIST_OIDC_IDP_END_SESSION_ENDPOINT');
}
log.info(`OIDCConfig: initialized with issuer ${issuerUrl}`);
}
@@ -187,6 +198,10 @@ export class OIDCConfig {
if (this._skipEndSessionEndpoint) {
return redirectUrl.href;
}
// Alternatively, we could use a logout URL specified by configuration.
if (this._endSessionEndpoint) {
return this._endSessionEndpoint;
}
return this._client.endSessionUrl({
post_logout_redirect_uri: redirectUrl.href
});

View File

@@ -22,6 +22,7 @@ import {ActionHistory, asActionGroup, getActionUndoInfo} from './ActionHistory';
import {ActiveDoc} from './ActiveDoc';
import {makeExceptionalDocSession, OptDocSession} from './DocSession';
import {WorkCoordinator} from './WorkCoordinator';
import {summarizeAction} from 'app/common/ActionSummarizer';
// Describes the request to apply a UserActionBundle. It includes a Client (so that broadcast
// message can set `.fromSelf` property), and methods to resolve or reject the promise for when
@@ -246,14 +247,14 @@ export class Sharing {
try {
const isCalculate = (userActions.length === 1 && SYSTEM_ACTIONS.has(userActions[0][0] as string));
const isSystemAction = (userActions.length === 1 && SYSTEM_ACTIONS.has(userActions[0][0] as string));
// `internal` is true if users shouldn't be able to undo the actions. Applies to:
// - Calculate/UpdateCurrentTime because it's not considered as performed by a particular client.
// - Adding attachment metadata when uploading attachments,
// because then the attachment file may get hard-deleted and redo won't work properly.
// - Action was rejected but it had some side effects (e.g. NOW() or UUID() formulas).
const internal =
isCalculate ||
isSystemAction ||
userActions.every(a => a[0] === "AddRecord" && a[1] === "_grist_Attachments") ||
!!failure;
@@ -305,7 +306,7 @@ export class Sharing {
// If the document has shut down in the meantime, and this was just a "Calculate" action,
// return a trivial result. This is just to reduce noisy warnings in migration tests.
if (this._activeDoc.isShuttingDown && isCalculate) {
if (this._activeDoc.isShuttingDown && isSystemAction) {
return {
actionNum: localActionBundle.actionNum,
retValues: [],
@@ -336,7 +337,12 @@ export class Sharing {
}
await this._activeDoc.processActionBundle(ownActionBundle);
const actionSummary = await this._activeDoc.handleTriggers(localActionBundle);
// Don't trigger webhooks for single Calculate actions, this causes a deadlock on document load.
// See gh issue #799
const isSingleCalculateAction = userActions.length === 1 && userActions[0][0] === 'Calculate';
const actionSummary = !isSingleCalculateAction ?
await this._activeDoc.handleTriggers(localActionBundle) :
summarizeAction(localActionBundle);
// Opportunistically use actionSummary to see if _grist_Shares was
// changed.

View File

@@ -174,7 +174,7 @@ export class DocTriggers {
const triggersTable = docData.getMetaTable("_grist_Triggers");
const getTableId = docData.getMetaTable("_grist_Tables").getRowPropFunc("tableId");
const triggersByTableRef = _.groupBy(triggersTable.getRecords(), "tableRef");
const triggersByTableRef = _.groupBy(triggersTable.getRecords().filter(t => t.enabled), "tableRef");
const triggersByTableId: Array<[string, Trigger[]]> = [];
// First we need a list of columns which must be included in full in the action summary
@@ -545,9 +545,7 @@ export class DocTriggers {
tableDelta: TableDelta,
): boolean {
let readyBefore: boolean;
if (!trigger.enabled) {
return false;
} else if (!trigger.isReadyColRef) {
if (!trigger.isReadyColRef) {
// User hasn't configured a column, so all records are considered ready immediately
readyBefore = recordDelta.existedBefore;
} else {