feat(organization): add ownership transfer - #5236
Open
denis0wn wants to merge 1 commit into
Open
Conversation
Adds an owner-only organization.transferOwnership mutation and a "Transfer Ownership" action in the Users table, covering the "Add the ability to transfer ownership" item from Dokploy#1413. - Target must be an existing member of the active organization; self-transfer and already-owner targets are rejected. - Atomic swap in one transaction: target -> owner, previous owner -> admin, organization.ownerId updated; audit log entry included. - UI gated to the organization owner, with a confirmation dialog and session/list invalidation after success. - 10 focused vitest tests over the mocked-DB harness.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR: feat(organization): add ownership transfer
Related issue: #1413 (checklist item "Add the ability to transfer ownership").
Slice announced in: #1413 (comment)
Description
Adds the ability to transfer organization ownership to an existing member. The
ownerrole was previously nontransferable by design (updateMemberRolerejectsany change to/from
owner), so this introduces a dedicated, owner-only mutationinstead of relaxing that guard.
Changes
Backend —
apps/dokploy/server/api/routers/organization.tsorganization.transferOwnershipmutation (memberIdinput):organization.ownerIdor a memberrecord with
role === "owner"in the active organization); admins/membersget
FORBIDDEN.transferring to a member who is already the owner is rejected.
owner, previousowner member role →
admin,organization.ownerId→ target user. Thisguarantees exactly one owner before and after the transfer.
type: "transferOwnership",from/to/toEmailmetadata (same audit pattern as the other organization mutations).
Frontend —
apps/dokploy/components/dashboard/settings/users/show-users.tsxorganization owner, only for other members who are not owners.
DialogAction, destructive) explaining that the callerbecomes an admin; success/error toasts; refetches the member list and
invalidates the session query so role-gated UI updates immediately.
Tests —
apps/dokploy/__test__/api/organization-transfer-ownership.test.ts10 focused tests using the existing mocked-DB harness:
memberId);member (new owner), member (previous owner demoted), organization (ownerId).
Verification performed by the author
pnpm exec vitest run --config __test__/vitest.config.ts(new file): 10/10 pass.canarywithout this change (*.real.test.tsrequiring a Docker socket anda git clone over https) — verified by stashing this branch and re-running them.
pnpm --filter=dokploy run typecheck(tsc --noEmit): pass.pnpm exec biome checkon the changed files: clean.dokploy:setup) was not runbecause this environment has no Docker daemon; the mutation is covered by the
unit tests above and follows the exact patterns of the neighboring mutations.
AI assistance disclosure
This implementation was produced with an AI coding agent under the supervision
of the account owner, who reviewed the diff and the test results. All claims in
"Verification performed" are from actual runs.
Scope
Out of scope (separate slices of #1413): teams, view-only role, remote-server
assignment, team-based invitations.
Greptile Summary
Adds an owner-only organization ownership-transfer mutation, a dashboard confirmation action, and focused API tests.
Confidence Score: 3/5
This PR should not merge until ownership transfers are serialized so concurrent requests cannot leave multiple users with owner privileges.
The new mutation checks ownership outside the transaction and has no database constraint or lock enforcing a single owner-role member, allowing concurrent transfers to persist multiple privileged owners.
Files Needing Attention: apps/dokploy/server/api/routers/organization.ts
Security Review
Concurrent transfers are not serialized, so separate targets can retain owner-role authorization after
organization.ownerIdresolves to only one of them.Reviews (1): Last reviewed commit: "feat(organization): add ownership transf..." | Re-trigger Greptile
Context used: