Skip to content

storeaccess: clear the legacy owner bit when revoking in bulk - #98

Open
r4nc0r wants to merge 1 commit into
grommunio:masterfrom
r4nc0r:fix/storeowner-legacy-bulk-revoke
Open

storeaccess: clear the legacy owner bit when revoking in bulk#98
r4nc0r wants to merge 1 commit into
grommunio:masterfrom
r4nc0r:fix/storeowner-legacy-bulk-revoke

Conversation

@r4nc0r

@r4nc0r r4nc0r commented Sep 10, 2026

Copy link
Copy Markdown

What happens

Revoking an additional store owner in bulk returns success and changes nothing when the grant was written by admin-api 1.20 or earlier. The grantee keeps store ownership, GET storeAccess keeps listing them, and the admin-web entry is back on the next reload. Both bulk paths are affected: PUT /domains/{d}/users/{u}/storeAccess with the user left out of the list, and grommunio-admin user <mailbox> storeowner remove.

This is the part of #93 point 2 that 7deb809 did not reach. DELETE storeAccess/{username} is already correct there. Follow-up to #95, which I closed in favour of 7deb809.

Why

setFolderMembers adds the mask for the users in the list and removes it from every other member, so bulk revocation happens by omission with STOREACCESS_SET (0x700). A grant written up to 1.20 carries GROMOXSTOREOWNER (0x2000) instead, and 0x2000 & ~0x700 is 0x2000, so nothing is written. gromox grants store ownership from that bit on its own — get_mbox_perm in exch/exmdb/store.cpp ORs the stored rights in verbatim — and STOREACCESS_GET matches it, so the user stays both an owner and listed.

7deb809 does clear the legacy bit in setUserStoreAccessMulti, but only for the users named in the request, which are exactly the ones keeping their access. cli/user.py does not clear it at all.

The change

One setFolderMembers(eid, [], Permissions.GROMOXSTOREOWNER) call per bulk path. An empty list clears the mask from every member, so grantees and revokees are both covered in a single round trip, which is what deleteUserStoreAccess already does for a single user. A row left with no rights is removed by setFolderMembers itself.

Verified

revoke path row before master with this patch
bulk, user omitted 0x2000 0x2000, listed, still owner row removed
bulk, user omitted 0x3800 0x3800, listed, still owner 0x1800, not listed
bulk, user omitted 0x700 row removed row removed
bulk, user omitted 0x7fb 0x4fb, not listed 0x4fb, not listed
DELETE storeAccess 0x2000 / 0x3800 row removed / 0x1800 unchanged by this patch

Modern and client-granted rows are unaffected: the delta only ever clears 0x2000. The two rows that disagree on master are the legacy ones.

grommunio/gromox@8e0dd961 replaces 0x2000 with 0x100 on folder 9 in a one-time private-store schema upgrade (schema 29), after which these rows no longer exist. This patch is what makes the bulk paths correct on an installation whose gromox has not reached that schema yet, and a no-op afterwards.

Both bulk paths write STOREACCESS_SET for the requested users, which
setFolderMembers removes from everyone else. A grant written up to 1.20
carries GROMOXSTOREOWNER instead, so the removal is a no-op for it: the
grantee stays a store owner and stays listed, and the admin-web entry
comes back on the next reload.

The API path cleared the bit only from the users it was granting to, and
the CLI path did not clear it at all. Clearing it from every member with
an empty setFolderMembers call covers grantees and revokees alike, which
is what deleteUserStoreAccess already does for a single user.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant