fix(#1413): Organisation and Teams Management - #5467
J2c-ashwani wants to merge 2 commits into
Conversation
| .set({ | ||
| name: input.name, | ||
| logo: input.logo, | ||
| metadata: updatedMetadata, |
There was a problem hiding this comment.
Every organization update writes the metadata value read near the start of the mutation, even when description is omitted. If saveCustomAiProviders writes new provider settings after that read but before this update completes, this stale write restores the old metadata and silently discards the saved aiProviders. Only write metadata when the description changes, or update the JSON field atomically.
| project: [], service: ["read"], environment: ["read"], docker: [], | ||
| sshKeys: [], gitProviders: [], traefikFiles: [], api: [], | ||
| volume: ["read"], deployment: ["read"], envVars: ["read"], | ||
| projectEnvVars: ["read"], environmentEnvVars: ["read"], |
There was a problem hiding this comment.
Granting environmentEnvVars: ["read"] lets a scoped user open the environment-variable editor, which renders the raw env value returned by environment.one in a read-only code editor. A view-only user can therefore retrieve credentials and tokens stored in environment variables. Use a secret-safe permission or return redacted values for this role.
How this was verified: A scoped user-role member is authorized to view the environment-variable editor, which renders the unredacted env field returned by the environment query.
| transferOwnership: protectedProcedure | ||
| .input(z.object({ newOwnerMemberId: z.string() })) | ||
| .mutation(async ({ ctx, input }) => { | ||
| const orgId = ctx.session.activeOrganizationId; | ||
| const org = await db.query.organization.findFirst({ where: eq(organization.id, orgId) }); | ||
| if (!org) throw new TRPCError({ code: "NOT_FOUND", message: "Organization not found" }); | ||
| if (org.ownerId !== ctx.user.id) throw new TRPCError({ code: "FORBIDDEN", message: "Only owner can transfer ownership" }); | ||
|
|
||
| const targetMember = await db.query.member.findFirst({ | ||
| where: and(eq(member.id, input.newOwnerMemberId), eq(member.organizationId, orgId)), | ||
| }); | ||
| if (!targetMember) throw new TRPCError({ code: "NOT_FOUND", message: "Target member not found in organization" }); | ||
| if (targetMember.userId === ctx.user.id) throw new TRPCError({ code: "BAD_REQUEST", message: "Already the owner" }); | ||
|
|
||
| await db.transaction(async (tx) => { | ||
| await tx.update(organization).set({ ownerId: targetMember.userId }).where(eq(organization.id, orgId)); | ||
| await tx.update(member).set({ role: "owner" }).where(eq(member.id, targetMember.id)); | ||
| await tx.update(member).set({ role: "admin" }).where(and(eq(member.organizationId, orgId), eq(member.userId, ctx.user.id))); | ||
| }); |
There was a problem hiding this comment.
Ownership transfer lacks tests
The regression test covers only the static userRole permission map, leaving this ownership-transfer transaction and its authorization and state transitions untested. Regressions in the owner-only guard, organization-scoped target lookup, or coordinated owner/admin updates could compromise organization control without failing the suite. Add route-level tests for successful transfer and the forbidden, cross-organization, and self-transfer paths.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
…viewer secret protection, and permission tests
|
Updated in commit
|
Description
Fixes #1413: Organisation and Teams Management
Automated targeted fix resolving root cause with zero new regressions.
Changes Made
Verification & Testing
Reproduction & Test Output:
Regression Test:
Added regression test covering the specific bug boundary.
Bounty Claim
/claim #1413
Payout Destination:
ashwani@fsidigital.caThe PR is not safe to merge until it prevents stale organization updates from erasing AI-provider metadata and removes plaintext secret access from the view-only role.
Summary
This PR introduces a view-only organization role, organization descriptions, invitation cleanup, ownership transfer, broader server-package export mappings, and regression tests for the role permission map.
userrole with selected read permissions.useras a default role.@dokploy/serverpackage entry points to generated distribution files.Reviews (1) · Last reviewed commit: "fix(#1413): Organisation and Teams Manag..."