mirror of
https://github.com/simstudioai/sim.git
synced 2026-02-15 00:44:56 -05:00
more permissions stuff
This commit is contained in:
@@ -13,7 +13,18 @@ interface RouteContext {
|
||||
params: Promise<{ id: string }>
|
||||
}
|
||||
|
||||
async function requireAdminMembership(credentialId: string, userId: string) {
|
||||
async function requireWorkspaceAdminMembership(credentialId: string, userId: string) {
|
||||
const [cred] = await db
|
||||
.select({ id: credential.id, workspaceId: credential.workspaceId })
|
||||
.from(credential)
|
||||
.where(eq(credential.id, credentialId))
|
||||
.limit(1)
|
||||
|
||||
if (!cred) return null
|
||||
|
||||
const perm = await getUserEntityPermissions(userId, 'workspace', cred.workspaceId)
|
||||
if (perm === null) return null
|
||||
|
||||
const [membership] = await db
|
||||
.select({ role: credentialMember.role, status: credentialMember.status })
|
||||
.from(credentialMember)
|
||||
@@ -91,7 +102,7 @@ export async function POST(request: NextRequest, context: RouteContext) {
|
||||
|
||||
const { id: credentialId } = await context.params
|
||||
|
||||
const admin = await requireAdminMembership(credentialId, session.user.id)
|
||||
const admin = await requireWorkspaceAdminMembership(credentialId, session.user.id)
|
||||
if (!admin) {
|
||||
return NextResponse.json({ error: 'Admin access required' }, { status: 403 })
|
||||
}
|
||||
@@ -153,7 +164,7 @@ export async function DELETE(request: NextRequest, context: RouteContext) {
|
||||
return NextResponse.json({ error: 'userId query parameter required' }, { status: 400 })
|
||||
}
|
||||
|
||||
const admin = await requireAdminMembership(credentialId, session.user.id)
|
||||
const admin = await requireWorkspaceAdminMembership(credentialId, session.user.id)
|
||||
if (!admin) {
|
||||
return NextResponse.json({ error: 'Admin access required' }, { status: 403 })
|
||||
}
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { db } from '@sim/db'
|
||||
import { pendingCredentialDraft } from '@sim/db/schema'
|
||||
import { credential, credentialMember, pendingCredentialDraft } from '@sim/db/schema'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { and, eq, lt } from 'drizzle-orm'
|
||||
import { NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { getSession } from '@/lib/auth'
|
||||
import { checkWorkspaceAccess } from '@/lib/workspaces/permissions/utils'
|
||||
|
||||
const logger = createLogger('CredentialDraftAPI')
|
||||
|
||||
@@ -33,6 +34,36 @@ export async function POST(request: Request) {
|
||||
|
||||
const { workspaceId, providerId, displayName, description, credentialId } = parsed.data
|
||||
const userId = session.user.id
|
||||
|
||||
const workspaceAccess = await checkWorkspaceAccess(workspaceId, userId)
|
||||
if (!workspaceAccess.canWrite) {
|
||||
return NextResponse.json({ error: 'Write permission required' }, { status: 403 })
|
||||
}
|
||||
|
||||
if (credentialId) {
|
||||
const [membership] = await db
|
||||
.select({ role: credentialMember.role, status: credentialMember.status })
|
||||
.from(credentialMember)
|
||||
.innerJoin(credential, eq(credential.id, credentialMember.credentialId))
|
||||
.where(
|
||||
and(
|
||||
eq(credentialMember.credentialId, credentialId),
|
||||
eq(credentialMember.userId, userId),
|
||||
eq(credentialMember.status, 'active'),
|
||||
eq(credentialMember.role, 'admin'),
|
||||
eq(credential.workspaceId, workspaceId)
|
||||
)
|
||||
)
|
||||
.limit(1)
|
||||
|
||||
if (!membership) {
|
||||
return NextResponse.json(
|
||||
{ error: 'Admin access required on the target credential' },
|
||||
{ status: 403 }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const now = new Date()
|
||||
|
||||
await db
|
||||
|
||||
@@ -22,9 +22,9 @@
|
||||
*/
|
||||
|
||||
import { db } from '@sim/db'
|
||||
import { permissions, user, workspace } from '@sim/db/schema'
|
||||
import { credential, credentialMember, permissions, user, workspace } from '@sim/db/schema'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { and, eq, inArray } from 'drizzle-orm'
|
||||
import { withAdminAuthParams } from '@/app/api/v1/admin/middleware'
|
||||
import {
|
||||
badRequestResponse,
|
||||
@@ -215,6 +215,28 @@ export const DELETE = withAdminAuthParams<RouteParams>(async (_, context) => {
|
||||
|
||||
await db.delete(permissions).where(eq(permissions.id, memberId))
|
||||
|
||||
// Revoke credential memberships for all credentials in this workspace
|
||||
const workspaceCredentialIds = await db
|
||||
.select({ id: credential.id })
|
||||
.from(credential)
|
||||
.where(eq(credential.workspaceId, workspaceId))
|
||||
|
||||
if (workspaceCredentialIds.length > 0) {
|
||||
await db
|
||||
.update(credentialMember)
|
||||
.set({ status: 'revoked', updatedAt: new Date() })
|
||||
.where(
|
||||
and(
|
||||
eq(credentialMember.userId, existingMember.userId),
|
||||
eq(credentialMember.status, 'active'),
|
||||
inArray(
|
||||
credentialMember.credentialId,
|
||||
workspaceCredentialIds.map((c) => c.id)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
logger.info(`Admin API: Removed member ${memberId} from workspace ${workspaceId}`, {
|
||||
userId: existingMember.userId,
|
||||
})
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { db } from '@sim/db'
|
||||
import { permissions, workspace } from '@sim/db/schema'
|
||||
import { credential, credentialMember, permissions, workspace } from '@sim/db/schema'
|
||||
import { createLogger } from '@sim/logger'
|
||||
import { and, eq } from 'drizzle-orm'
|
||||
import { and, eq, inArray } from 'drizzle-orm'
|
||||
import { type NextRequest, NextResponse } from 'next/server'
|
||||
import { z } from 'zod'
|
||||
import { getSession } from '@/lib/auth'
|
||||
@@ -101,6 +101,28 @@ export async function DELETE(req: NextRequest, { params }: { params: Promise<{ i
|
||||
)
|
||||
)
|
||||
|
||||
// Revoke credential memberships for all credentials in this workspace
|
||||
const workspaceCredentialIds = await db
|
||||
.select({ id: credential.id })
|
||||
.from(credential)
|
||||
.where(eq(credential.workspaceId, workspaceId))
|
||||
|
||||
if (workspaceCredentialIds.length > 0) {
|
||||
await db
|
||||
.update(credentialMember)
|
||||
.set({ status: 'revoked', updatedAt: new Date() })
|
||||
.where(
|
||||
and(
|
||||
eq(credentialMember.userId, userId),
|
||||
eq(credentialMember.status, 'active'),
|
||||
inArray(
|
||||
credentialMember.credentialId,
|
||||
workspaceCredentialIds.map((c) => c.id)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
return NextResponse.json({ success: true })
|
||||
} catch (error) {
|
||||
logger.error('Error removing workspace member:', error)
|
||||
|
||||
Reference in New Issue
Block a user