diff --git a/app/client/models/errors.ts b/app/client/models/errors.ts index 847dee7d..a7c6ba99 100644 --- a/app/client/models/errors.ts +++ b/app/client/models/errors.ts @@ -83,7 +83,7 @@ export function reportError(err: Error|string): void { _notifier.createUserError(message, options); } else if (err.name === 'NeedUpgradeError') { _notifier.createUserError(err.message, {actions: ['upgrade'], key: 'NEED_UPGRADE'}); - } else if (code === 'AUTH_NO_EDIT') { + } else if (code === 'AUTH_NO_EDIT' || code === 'ACL_DENY') { _notifier.createUserError(message, {key: code}); } else { // If we don't recognize it, consider it an application error (bug) that the user should be diff --git a/app/server/lib/ActiveDoc.ts b/app/server/lib/ActiveDoc.ts index 1b97aa00..09cfea51 100644 --- a/app/server/lib/ActiveDoc.ts +++ b/app/server/lib/ActiveDoc.ts @@ -28,6 +28,7 @@ import {toTableDataAction} from 'app/common/DocActions'; import {DocData} from 'app/common/DocData'; import {DocSnapshots} from 'app/common/DocSnapshot'; import {EncActionBundleFromHub} from 'app/common/EncActionBundle'; +import {ErrorWithCode} from 'app/common/ErrorWithCode'; import {byteString, countIf} from 'app/common/gutil'; import {InactivityTimer} from 'app/common/InactivityTimer'; import * as marshal from 'app/common/marshal'; @@ -1183,7 +1184,7 @@ export class ActiveDoc extends EventEmitter { options: ApplyUAOptions = {}): Promise { if (!await this._granularAccess.canMaybeApplyUserActions(docSession, actions)) { - throw new Error('cannot perform a requested action'); + throw new ErrorWithCode('ACL_DENY', 'Action blocked by access rules'); } const client = docSession.client; diff --git a/app/server/lib/GranularAccess.ts b/app/server/lib/GranularAccess.ts index 2cb35648..237c2df4 100644 --- a/app/server/lib/GranularAccess.ts +++ b/app/server/lib/GranularAccess.ts @@ -844,15 +844,15 @@ export class GranularAccess { } else { // Look up user information in database. if (!this._homeDbManager) { throw new Error('database required'); } - const user = linkParameters.aclAsUserId ? + const dbUser = linkParameters.aclAsUserId ? (await this._homeDbManager.getUser(integerParam(linkParameters.aclAsUserId))) : (await this._homeDbManager.getUserByLogin(linkParameters.aclAsUser)); - const docAuth = user && await this._homeDbManager.getDocAuthCached({ + const docAuth = dbUser && await this._homeDbManager.getDocAuthCached({ urlId: this._docId, - userId: user.id + userId: dbUser.id }); access = docAuth?.access || null; - fullUser = user && this._homeDbManager.makeFullUser(user) || null; + fullUser = dbUser && this._homeDbManager.makeFullUser(dbUser) || null; attrs.override = { access, user: fullUser }; } } else { @@ -1195,7 +1195,7 @@ function getAccessForActionType(a: DocAction): AccessFn { function denyIsFatal(fn: AccessFn): AccessFn { return (ps) => { const result = fn(ps); - if (result === 'deny') { throw new Error('access denied'); } + if (result === 'deny') { throw new ErrorWithCode('ACL_DENY', 'Blocked by access rules'); } return result; }; }