Skip to content

fix: a restore cannot hand an account to somebody else - #886

Merged
blaipr merged 1 commit into
mainfrom
fix/a-restore-cannot-hand-an-account-to-someone-else
Aug 26, 2026
Merged

fix: a restore cannot hand an account to somebody else#886
blaipr merged 1 commit into
mainfrom
fix/a-restore-cannot-hand-an-account-to-someone-else

Conversation

@blaipr

@blaipr blaipr commented Aug 26, 2026

Copy link
Copy Markdown
Member

update() excludes userId and userGroupId from the columns it writes and puts them
back only when userCanChangeOwner() and userCanChangeGroup() say the caller may change
them — an application admin, an accounts admin, or the owner holding accPermission.
restoreModified() excluded neither, so it wrote every column of the historical snapshot
back, those two among them.

Restoring an old version therefore reverted who owns the account and which group it
belongs to. Those are exactly the columns AccountAcl compares the signed-in user
against, so it changes who can see the account — and the door needs only
ACCOUNT_EDIT_RESTORE, which AccountPermission buckets with plain ACCOUNT_EDIT. So
anybody the account was merely shared with for editing could hand it back to a previous
owner and group, which is the thing userCanChangeOwner() exists to refuse them two
screens away.

The restore asks the same two questions the edit asks, and writes those columns only if
the answer is yes. Everything else in the snapshot is restored exactly as before.

Checked by putting the two columns back in the exclusion list: the new test fails,
asserting on the bound values of the emitted statement rather than on a row, because
what matters is that the UPDATE does not carry them at all.

`update()` excludes `userId` and `userGroupId` from the columns it writes and puts them
back only when `userCanChangeOwner()` and `userCanChangeGroup()` say the caller may change
them — an application admin, an accounts admin, or the owner holding `accPermission`.
`restoreModified()` excluded neither, so it wrote every column of the historical snapshot
back, those two among them.

Restoring an old version therefore reverted who owns the account and which group it
belongs to. Those are exactly the columns `AccountAcl` compares the signed-in user
against, so it changes who can see the account — and the door needs only
`ACCOUNT_EDIT_RESTORE`, which `AccountPermission` buckets with plain `ACCOUNT_EDIT`. So
anybody the account was merely shared with for editing could hand it back to a previous
owner and group, which is the thing `userCanChangeOwner()` exists to refuse them two
screens away.

The restore asks the same two questions the edit asks, and writes those columns only if
the answer is yes. Everything else in the snapshot is restored exactly as before.

Checked by putting the two columns back in the exclusion list: the new test fails,
asserting on the bound values of the emitted statement rather than on a row, because
what matters is that the UPDATE does not carry them at all.
@blaipr
blaipr merged commit 15ed440 into main Aug 26, 2026
8 checks passed
@blaipr
blaipr deleted the fix/a-restore-cannot-hand-an-account-to-someone-else branch August 26, 2026 20:45
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