(core) granular access control in the presence of schema changes

Summary:
 - Support schema changes in the presence of non-trivial ACL rules.
 - Fix update of `aclFormulaParsed` when updating formulas automatically after schema change.
 - Filter private metadata in broadcasts, not just fetches.  Censorship method is unchanged, just refactored.
 - Allow only owners to change ACL rules.
 - Force reloads if rules are changed.
 - Track rule changes within bundle, for clarity during schema changes - tableId and colId changes create a muddle otherwise.
 - Show or forbid pages dynamically depending on user's access to its sections. Logic unchanged, just no longer requires reload.
 - Fix calculation of pre-existing rows touched by a bundle, in the presence of schema changes.
 - Gray out acl page for non-owners.

Test Plan: added tests

Reviewers: dsagal

Reviewed By: dsagal

Differential Revision: https://phab.getgrist.com/D2734
This commit is contained in:
Paul Fitzpatrick
2021-03-01 11:51:30 -05:00
parent aae4a58300
commit 4ab096d179
18 changed files with 930 additions and 454 deletions

View File

@@ -28,11 +28,6 @@ type NameType = Observable<string>|ko.Observable<string>;
// the item in the menu.
export function buildPageDom(name: NameType, actions: PageActions, ...args: DomElementArg[]) {
// If name is blank, this page is censored, so don't include any options for manipulation.
// We can get fancier about this later.
const initName = ('peek' in name) ? name.peek() : name.get();
if (initName === '') { return dom('div', '-'); }
const isRenaming = observable(false);
const pageMenu = () => [
menuItem(() => isRenaming.set(true), "Rename", testId('rename'),
@@ -57,43 +52,44 @@ export function buildPageDom(name: NameType, actions: PageActions, ...args: DomE
return pageElem = dom(
'div',
dom.autoDispose(lis),
domComputed(isRenaming, (isrenaming) => (
isrenaming ?
cssPageItem(
cssPageInitial(dom.text((use) => use(name)[0])),
cssEditorInput(
{
initialValue: typeof name === 'function' ? name() : name.get() || '',
save: (val) => actions.onRename(val),
close: () => isRenaming.set(false)
},
testId('editor'),
dom.on('mousedown', (ev) => ev.stopPropagation()),
dom.on('click', (ev) => { ev.stopPropagation(); ev.preventDefault(); })
),
// Note that we don't pass extra args when renaming is on, because they usually includes
// mouse event handlers interferring with input editor and yields wrong behavior on
// firefox.
) :
cssPageItem(
cssPageInitial(dom.text((use) => use(name)[0])),
cssPageName(dom.text(name), testId('label')),
cssPageMenuTrigger(
cssPageIcon('Dots'),
menu(pageMenu, {placement: 'bottom-start', parentSelectorToMark: '.' + itemHeader.className}),
dom.on('click', (ev) => { ev.stopPropagation(); ev.preventDefault(); }),
domComputed((use) => use(name) === '', blank => blank ? dom('div', '-') :
domComputed(isRenaming, (isrenaming) => (
isrenaming ?
cssPageItem(
cssPageInitial(dom.text((use) => use(name)[0])),
cssEditorInput(
{
initialValue: typeof name === 'function' ? name() : name.get() || '',
save: (val) => actions.onRename(val),
close: () => isRenaming.set(false)
},
testId('editor'),
dom.on('mousedown', (ev) => ev.stopPropagation()),
dom.on('click', (ev) => { ev.stopPropagation(); ev.preventDefault(); })
),
// Note that we don't pass extra args when renaming is on, because they usually includes
// mouse event handlers interferring with input editor and yields wrong behavior on
// firefox.
) :
cssPageItem(
cssPageInitial(dom.text((use) => use(name)[0])),
cssPageName(dom.text(name), testId('label')),
cssPageMenuTrigger(
cssPageIcon('Dots'),
menu(pageMenu, {placement: 'bottom-start', parentSelectorToMark: '.' + itemHeader.className}),
dom.on('click', (ev) => { ev.stopPropagation(); ev.preventDefault(); }),
// Let's prevent dragging to start when un-intentionally holding the mouse down on '...' menu.
dom.on('mousedown', (ev) => ev.stopPropagation()),
testId('dots'),
),
// Prevents the default dragging behaviour that Firefox support for links which conflicts
// with our own dragging pages.
dom.on('dragstart', (ev) => ev.preventDefault()),
args
)
)),
);
// Let's prevent dragging to start when un-intentionally holding the mouse down on '...' menu.
dom.on('mousedown', (ev) => ev.stopPropagation()),
testId('dots'),
),
// Prevents the default dragging behaviour that Firefox support for links which conflicts
// with our own dragging pages.
dom.on('dragstart', (ev) => ev.preventDefault()),
args
)
)),
));
}
const cssPageItem = styled('a', `