Skip to content

Commit bdfe7e9

Browse files
authored
fix(invitation): allow admins to remove members from workspace (#701)
* fix(invitation): added ability for admins to remove members of their workspace * lint * remove references to workspace_member db table * remove deprecated @next/font * only allow admin to rename workspace * bring workflow name change inline, remove dialog
1 parent 27c248a commit bdfe7e9

File tree

20 files changed

+1549
-881
lines changed

20 files changed

+1549
-881
lines changed

apps/sim/app/api/organizations/[id]/workspaces/route.ts

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { type NextRequest, NextResponse } from 'next/server'
33
import { getSession } from '@/lib/auth'
44
import { createLogger } from '@/lib/logs/console-logger'
55
import { db } from '@/db'
6-
import { member, permissions, user, workspace, workspaceMember } from '@/db/schema'
6+
import { member, permissions, user, workspace } from '@/db/schema'
77

88
const logger = createLogger('OrganizationWorkspacesAPI')
99

@@ -116,10 +116,9 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
116116
id: workspace.id,
117117
name: workspace.name,
118118
ownerId: workspace.ownerId,
119-
createdAt: workspace.createdAt,
120119
isOwner: eq(workspace.ownerId, memberId),
121120
permissionType: permissions.permissionType,
122-
joinedAt: workspaceMember.joinedAt,
121+
createdAt: permissions.createdAt,
123122
})
124123
.from(workspace)
125124
.leftJoin(
@@ -130,10 +129,6 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
130129
eq(permissions.userId, memberId)
131130
)
132131
)
133-
.leftJoin(
134-
workspaceMember,
135-
and(eq(workspaceMember.workspaceId, workspace.id), eq(workspaceMember.userId, memberId))
136-
)
137132
.where(
138133
or(
139134
// Member owns the workspace
@@ -148,7 +143,7 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
148143
name: workspace.name,
149144
isOwner: workspace.isOwner,
150145
permission: workspace.permissionType,
151-
joinedAt: workspace.joinedAt,
146+
joinedAt: workspace.createdAt,
152147
createdAt: workspace.createdAt,
153148
}))
154149

apps/sim/app/api/organizations/invitations/accept/route.ts

Lines changed: 3 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { getSession } from '@/lib/auth'
55
import { env } from '@/lib/env'
66
import { createLogger } from '@/lib/logs/console-logger'
77
import { db } from '@/db'
8-
import { invitation, member, permissions, workspaceInvitation, workspaceMember } from '@/db/schema'
8+
import { invitation, member, permissions, workspaceInvitation } from '@/db/schema'
99

1010
const logger = createLogger('OrganizationInvitationAcceptance')
1111

@@ -135,18 +135,6 @@ export async function GET(req: NextRequest) {
135135
wsInvitation.expiresAt &&
136136
new Date().toISOString() <= wsInvitation.expiresAt.toISOString()
137137
) {
138-
// Check if user isn't already a member of the workspace
139-
const existingWorkspaceMember = await tx
140-
.select()
141-
.from(workspaceMember)
142-
.where(
143-
and(
144-
eq(workspaceMember.workspaceId, wsInvitation.workspaceId),
145-
eq(workspaceMember.userId, session.user.id)
146-
)
147-
)
148-
.limit(1)
149-
150138
// Check if user doesn't already have permissions on the workspace
151139
const existingPermission = await tx
152140
.select()
@@ -160,17 +148,7 @@ export async function GET(req: NextRequest) {
160148
)
161149
.limit(1)
162150

163-
if (existingWorkspaceMember.length === 0 && existingPermission.length === 0) {
164-
// Add user as workspace member
165-
await tx.insert(workspaceMember).values({
166-
id: randomUUID(),
167-
workspaceId: wsInvitation.workspaceId,
168-
userId: session.user.id,
169-
role: wsInvitation.role,
170-
joinedAt: new Date(),
171-
updatedAt: new Date(),
172-
})
173-
151+
if (existingPermission.length === 0) {
174152
// Add workspace permissions
175153
await tx.insert(permissions).values({
176154
id: randomUUID(),
@@ -311,17 +289,6 @@ export async function POST(req: NextRequest) {
311289
wsInvitation.expiresAt &&
312290
new Date().toISOString() <= wsInvitation.expiresAt.toISOString()
313291
) {
314-
const existingWorkspaceMember = await tx
315-
.select()
316-
.from(workspaceMember)
317-
.where(
318-
and(
319-
eq(workspaceMember.workspaceId, wsInvitation.workspaceId),
320-
eq(workspaceMember.userId, session.user.id)
321-
)
322-
)
323-
.limit(1)
324-
325292
const existingPermission = await tx
326293
.select()
327294
.from(permissions)
@@ -334,16 +301,7 @@ export async function POST(req: NextRequest) {
334301
)
335302
.limit(1)
336303

337-
if (existingWorkspaceMember.length === 0 && existingPermission.length === 0) {
338-
await tx.insert(workspaceMember).values({
339-
id: randomUUID(),
340-
workspaceId: wsInvitation.workspaceId,
341-
userId: session.user.id,
342-
role: wsInvitation.role,
343-
joinedAt: new Date(),
344-
updatedAt: new Date(),
345-
})
346-
304+
if (existingPermission.length === 0) {
347305
await tx.insert(permissions).values({
348306
id: randomUUID(),
349307
userId: session.user.id,

apps/sim/app/api/workspaces/[id]/permissions/route.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1+
import crypto from 'crypto'
12
import { and, eq } from 'drizzle-orm'
23
import { type NextRequest, NextResponse } from 'next/server'
34
import { getSession } from '@/lib/auth'
45
import { getUsersWithPermissions, hasWorkspaceAdminAccess } from '@/lib/permissions/utils'
56
import { db } from '@/db'
6-
import { permissions, type permissionTypeEnum, workspaceMember } from '@/db/schema'
7+
import { permissions, type permissionTypeEnum } from '@/db/schema'
78

89
type PermissionType = (typeof permissionTypeEnum.enumValues)[number]
910

@@ -33,18 +34,19 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
3334
}
3435

3536
// Verify the current user has access to this workspace
36-
const userMembership = await db
37+
const userPermission = await db
3738
.select()
38-
.from(workspaceMember)
39+
.from(permissions)
3940
.where(
4041
and(
41-
eq(workspaceMember.workspaceId, workspaceId),
42-
eq(workspaceMember.userId, session.user.id)
42+
eq(permissions.entityId, workspaceId),
43+
eq(permissions.entityType, 'workspace'),
44+
eq(permissions.userId, session.user.id)
4345
)
4446
)
4547
.limit(1)
4648

47-
if (userMembership.length === 0) {
49+
if (userPermission.length === 0) {
4850
return NextResponse.json({ error: 'Workspace not found or access denied' }, { status: 404 })
4951
}
5052

apps/sim/app/api/workspaces/[id]/route.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { and, eq } from 'drizzle-orm'
22
import { type NextRequest, NextResponse } from 'next/server'
33
import { getSession } from '@/lib/auth'
44
import { createLogger } from '@/lib/logs/console-logger'
5-
import { workflow, workspaceMember } from '@/db/schema'
5+
import { workflow } from '@/db/schema'
66

77
const logger = createLogger('WorkspaceByIdAPI')
88

@@ -126,9 +126,6 @@ export async function DELETE(
126126
// workflow_schedule, webhook, marketplace, chat, and memory records
127127
await tx.delete(workflow).where(eq(workflow.workspaceId, workspaceId))
128128

129-
// Delete workspace members
130-
await tx.delete(workspaceMember).where(eq(workspaceMember.workspaceId, workspaceId))
131-
132129
// Delete all permissions associated with this workspace
133130
await tx
134131
.delete(permissions)

0 commit comments

Comments
 (0)