mirror of
https://github.com/bulwarkmail/native.git
synced 2026-10-31 16:06:32 +00:00
fix: let files in a shared folder be renamed and deleted on Stalwart 1.0, which sends rights for folders only
This commit is contained in:
@@ -32,6 +32,15 @@ describe('fileNodeAccess', () => {
|
|||||||
expect(fileNodeAccess(nodes.at(-1)!, nodes)).toEqual({ rename: true, delete: true, move: false, duplicate: true });
|
expect(fileNodeAccess(nodes.at(-1)!, nodes)).toEqual({ rename: true, delete: true, move: false, duplicate: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('takes the folder\'s rights for a file that names none (Stalwart 1.0)', () => {
|
||||||
|
const writable = shared(WRITE, WRITE);
|
||||||
|
const nodes = [...writable.slice(0, 2), { ...writable[2], myRights: undefined }];
|
||||||
|
expect(fileNodeAccess(nodes.at(-1)!, nodes)).toEqual({ rename: true, delete: true, move: false, duplicate: true });
|
||||||
|
const readOnly = shared(NONE, NONE);
|
||||||
|
const ro = [...readOnly.slice(0, 2), { ...readOnly[2], myRights: undefined }];
|
||||||
|
expect(fileNodeAccess(ro.at(-1)!, ro)).toEqual({ rename: false, delete: false, move: false, duplicate: false });
|
||||||
|
});
|
||||||
|
|
||||||
it('offers nothing inside a folder shared read-only', () => {
|
it('offers nothing inside a folder shared read-only', () => {
|
||||||
const nodes = shared(NONE, NONE);
|
const nodes = shared(NONE, NONE);
|
||||||
expect(fileNodeAccess(nodes.at(-1)!, nodes)).toEqual({ rename: false, delete: false, move: false, duplicate: false });
|
expect(fileNodeAccess(nodes.at(-1)!, nodes)).toEqual({ rename: false, delete: false, move: false, duplicate: false });
|
||||||
|
|||||||
+17
-4
@@ -27,24 +27,37 @@ function sharedParent(node: FileNode, nodes: FileNode[]): FileNode | undefined {
|
|||||||
return nodes.find((n) => n.id === node.parentId && !n.discoverableOnly);
|
return nodes.find((n) => n.id === node.parentId && !n.discoverableOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Stalwart 1.0 sends `myRights` on folders only; a file has the rights of
|
||||||
|
// the folder it is in. Walk up to the nearest node that names its rights.
|
||||||
|
function effectiveRights(node: FileNode, nodes: FileNode[]): FileNode['myRights'] {
|
||||||
|
const seen = new Set<string>();
|
||||||
|
let current: FileNode | undefined = node;
|
||||||
|
while (current && !seen.has(current.id)) {
|
||||||
|
if (current.myRights) return current.myRights;
|
||||||
|
seen.add(current.id);
|
||||||
|
const parentId: string | null | undefined = current.parentId;
|
||||||
|
current = parentId == null ? undefined : nodes.find((n) => n.id === parentId);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
export function fileNodeAccess(node: FileNode, nodes: FileNode[]): FileNodeAccess {
|
export function fileNodeAccess(node: FileNode, nodes: FileNode[]): FileNodeAccess {
|
||||||
if (!node.isShared) return ALL;
|
if (!node.isShared) return ALL;
|
||||||
const parent = sharedParent(node, nodes);
|
const parent = sharedParent(node, nodes);
|
||||||
if (!parent) return { rename: false, delete: false, move: false, duplicate: false };
|
if (!parent) return { rename: false, delete: false, move: false, duplicate: false };
|
||||||
const rights = node.myRights;
|
const rights = effectiveRights(node, nodes);
|
||||||
return {
|
return {
|
||||||
rename: !!rights?.mayRename,
|
rename: !!rights?.mayRename,
|
||||||
delete: !!rights?.mayDelete,
|
delete: !!rights?.mayDelete,
|
||||||
move: false,
|
move: false,
|
||||||
duplicate: !!parent.myRights?.mayAddChildren,
|
duplicate: !!effectiveRights(parent, nodes)?.mayAddChildren,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether new folders and uploads may go into the folder `folderId` (null:
|
* Whether new folders and uploads may go into the folder `folderId` (null:
|
||||||
* the user's own drive root). Inside a shared folder only with its
|
* the user's own drive root). Inside a shared folder only with its
|
||||||
* `mayAddChildren`; Stalwart 0.16 reports a child of a shared folder with
|
* `mayAddChildren`.
|
||||||
* every right false, so there it is offered in the shared folder itself.
|
|
||||||
*/
|
*/
|
||||||
export function mayCreateIn(folderId: string | null, nodes: FileNode[]): boolean {
|
export function mayCreateIn(folderId: string | null, nodes: FileNode[]): boolean {
|
||||||
if (folderId === null) return true;
|
if (folderId === null) return true;
|
||||||
|
|||||||
Reference in New Issue
Block a user