Skip to content

Commit 8d78ecb

Browse files
committed
fix(credentials): reflect workspace permission in credential member role
Workspace admin users were incorrectly assigned 'member' role on credential_member when workspace-scoped secrets were created or synced. Only the workspace owner got 'admin'. Now workspace permissions table is consulted: owner/admin → credential admin, write/read → member. - environment.ts: query workspace permissions in ensureWorkspaceCredentialMemberships - route.ts POST: apply same mapping during credential creation
1 parent 11ad891 commit 8d78ecb

2 files changed

Lines changed: 38 additions & 9 deletions

File tree

apps/sim/app/api/credentials/route.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { AuditAction, AuditResourceType, recordAudit } from '@sim/audit'
22
import { db } from '@sim/db'
3-
import { account, credential, credentialMember, workspace } from '@sim/db/schema'
3+
import { account, credential, credentialMember, permissions, workspace } from '@sim/db/schema'
44
import { createLogger } from '@sim/logger'
55
import { getPostgresErrorCode } from '@sim/utils/errors'
66
import { generateId } from '@sim/utils/id'
@@ -535,17 +535,30 @@ export const POST = withRouteHandler(async (request: NextRequest) => {
535535
})
536536

537537
if ((type === 'env_workspace' || type === 'service_account') && workspaceRow?.ownerId) {
538-
const workspaceUserIds = await getWorkspaceMemberUserIds(workspaceId)
538+
const [workspaceUserIds, wsPermissionRows] = await Promise.all([
539+
getWorkspaceMemberUserIds(workspaceId),
540+
db
541+
.select({ userId: permissions.userId, permissionType: permissions.permissionType })
542+
.from(permissions)
543+
.where(
544+
and(eq(permissions.entityType, 'workspace'), eq(permissions.entityId, workspaceId))
545+
),
546+
])
547+
const wsPermissionByUser = new Map(
548+
wsPermissionRows.map((row) => [row.userId, row.permissionType])
549+
)
539550
if (workspaceUserIds.length > 0) {
540551
for (const memberUserId of workspaceUserIds) {
552+
const wsPermission = wsPermissionByUser.get(memberUserId)
553+
const isAdmin =
554+
memberUserId === workspaceRow.ownerId ||
555+
memberUserId === session.user.id ||
556+
wsPermission === 'admin'
541557
await tx.insert(credentialMember).values({
542558
id: generateId(),
543559
credentialId,
544560
userId: memberUserId,
545-
role:
546-
memberUserId === workspaceRow.ownerId || memberUserId === session.user.id
547-
? 'admin'
548-
: 'member',
561+
role: isAdmin ? 'admin' : 'member',
549562
status: 'active',
550563
joinedAt: now,
551564
invitedBy: session.user.id,

apps/sim/lib/credentials/environment.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,20 @@ export async function getUserWorkspaceIds(userId: string): Promise<string[]> {
6464
async function ensureWorkspaceCredentialMemberships(
6565
credentialId: string,
6666
memberUserIds: string[],
67-
ownerUserId: string
67+
ownerUserId: string,
68+
workspaceId: string
6869
) {
6970
if (!memberUserIds.length) return
7071

72+
const workspacePermissionRows = await db
73+
.select({ userId: permissions.userId, permissionType: permissions.permissionType })
74+
.from(permissions)
75+
.where(and(eq(permissions.entityType, 'workspace'), eq(permissions.entityId, workspaceId)))
76+
77+
const wsPermissionByUser = new Map(
78+
workspacePermissionRows.map((row) => [row.userId, row.permissionType])
79+
)
80+
7181
const existingMemberships = await db
7282
.select({
7383
id: credentialMember.id,
@@ -87,7 +97,8 @@ async function ensureWorkspaceCredentialMemberships(
8797
const now = new Date()
8898

8999
for (const memberUserId of memberUserIds) {
90-
const targetRole = memberUserId === ownerUserId ? 'admin' : 'member'
100+
const wsPermission = wsPermissionByUser.get(memberUserId)
101+
const targetRole = memberUserId === ownerUserId || wsPermission === 'admin' ? 'admin' : 'member'
91102
const existing = byUserId.get(memberUserId)
92103
if (existing) {
93104
if (existing.status === 'revoked') {
@@ -182,7 +193,12 @@ export async function syncWorkspaceEnvCredentials(params: {
182193
}
183194

184195
for (const credentialId of credentialIdsToEnsureMembership) {
185-
await ensureWorkspaceCredentialMemberships(credentialId, memberUserIds, workspaceRow.ownerId)
196+
await ensureWorkspaceCredentialMemberships(
197+
credentialId,
198+
memberUserIds,
199+
workspaceRow.ownerId,
200+
workspaceId
201+
)
186202
}
187203

188204
if (normalizedKeys.length > 0) {

0 commit comments

Comments
 (0)