(core) Update ACL resources/rules when tables/columns get renamed

Summary:
- Placed rule-updating functions in acl.py.
- Reset UI when rules update externally, or alert the user to reset if there
  are pending local changes.
- Removed some unused and distracting bits from client-side DocModel.

A few improvements related to poor error handling:
- In case of missing DocActions (tickled by broken ACL rule handling), don't
  add to confusion by attempting to process bad actions
- In case of missing attributes in ACL formulas, return undefined rather than
  fail; the latter creates more problems.
- In case in invalid rules, fail rather than skip; this feels more correct now
  that we have error checking and recovery option, and helps avoid invalid rules.
- Prevent saving invalid rules with an empty ACL formula.
- Fix bug with rule positions.

Test Plan: Added a python and browser test for table/column renames.

Reviewers: paulfitz

Reviewed By: paulfitz

Differential Revision: https://phab.getgrist.com/D2698
This commit is contained in:
Dmitry S
2020-12-28 00:40:10 -05:00
parent d6d1eb217f
commit 5deac68315
14 changed files with 338 additions and 79 deletions

View File

@@ -256,7 +256,7 @@ function readAclRules(docData: DocData, {log, compile}: ReadAclOptions): ReadAcl
for (const [resourceId, rules] of rulesByResource.entries()) {
const resourceRec = resourcesTable.getRecord(resourceId as number);
if (!resourceRec) {
log.error(`ACLRule ${rules[0].id} ignored; refers to an invalid ACLResource ${resourceId}`);
throw new Error(`ACLRule ${rules[0].id} refers to an invalid ACLResource ${resourceId}`);
continue;
}
if (!resourceRec.tableId || !resourceRec.colIds) {
@@ -271,7 +271,7 @@ function readAclRules(docData: DocData, {log, compile}: ReadAclOptions): ReadAcl
for (const rule of rules) {
if (rule.userAttributes) {
if (tableId !== '*' || colIds !== '*') {
log.warn(`ACLRule ${rule.id} ignored; user attributes must be on the default resource`);
throw new Error(`ACLRule ${rule.id} invalid; user attributes must be on the default resource`);
continue;
}
const parsed = JSON.parse(String(rule.userAttributes));
@@ -279,15 +279,15 @@ function readAclRules(docData: DocData, {log, compile}: ReadAclOptions): ReadAcl
if (!(parsed && typeof parsed === 'object' &&
[parsed.name, parsed.tableId, parsed.lookupColId, parsed.charId]
.every(p => p && typeof p === 'string'))) {
log.warn(`User attribute rule ${rule.id} is invalid`);
throw new Error(`User attribute rule ${rule.id} is invalid`);
continue;
}
parsed.origRecord = rule;
userAttributes.push(parsed as UserAttributeRule);
} else if (body.length > 0 && !body[body.length - 1].aclFormula) {
log.warn(`ACLRule ${rule.id} ignored because listed after default rule`);
throw new Error(`ACLRule ${rule.id} invalid because listed after default rule`);
} else if (rule.aclFormula && !rule.aclFormulaParsed) {
log.warn(`ACLRule ${rule.id} ignored because missing its parsed formula`);
throw new Error(`ACLRule ${rule.id} invalid because missing its parsed formula`);
} else {
body.push({
origRecord: rule,