-
Notifications
You must be signed in to change notification settings - Fork 84
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: user management api * refactor: user managment end points * refactor: user api query the whole row
- Loading branch information
1 parent
834c48c
commit ddda356
Showing
2 changed files
with
198 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
import { and, eq } from "drizzle-orm"; | ||
import { NextResponse } from "next/server"; | ||
import withDatabaseOperation from "@/lib/with-database-ops"; | ||
import { database_user_role, database_role } from "@/db/schema"; | ||
import { db } from "@/db"; | ||
import zod from "zod"; | ||
|
||
export const runtime = "edge"; | ||
|
||
const assignUserSchema = zod.object({ | ||
user: zod.string(), | ||
role: zod.string(), | ||
}); | ||
|
||
const deleteUserSchema = zod.object({ | ||
user: zod.string(), | ||
}); | ||
|
||
async function getUserRoleInfo(userId: string, databaseId: string) { | ||
return db.query.database_user_role.findFirst({ | ||
where: and( | ||
eq(database_user_role.databaseId, databaseId), | ||
eq(database_user_role.userId, userId) | ||
), | ||
}); | ||
} | ||
|
||
async function checkUserHasOwnerRole(roleId: string) { | ||
const roleInfo = await db.query.database_role.findFirst({ | ||
where: eq(database_role.id, roleId), | ||
}); | ||
return roleInfo?.isOwner; | ||
} | ||
|
||
export const POST = withDatabaseOperation( | ||
async ({ user, body, database, permission }) => { | ||
const parsed = assignUserSchema.safeParse(body); | ||
|
||
if (!parsed.success) { | ||
return NextResponse.json( | ||
{ | ||
success: false, | ||
error: "Invalid request body", | ||
}, | ||
{ status: 400 } | ||
); | ||
} | ||
|
||
if (!permission.isOwner) { | ||
return NextResponse.json( | ||
{ | ||
success: false, | ||
error: "You do not have permission", | ||
}, | ||
{ status: 403 } | ||
); | ||
} | ||
|
||
const { user: userId, role: roleId } = parsed.data; | ||
|
||
const userExists = await db.query.user.findFirst({ | ||
where: (fields, op) => op.eq(fields.id, userId), | ||
}); | ||
|
||
if (!userExists) { | ||
return NextResponse.json( | ||
{ success: false, error: "User does not exist" }, | ||
{ status: 404 } | ||
); | ||
} | ||
|
||
const roleInfo = await db.query.database_role.findFirst({ | ||
where: (fields) => eq(fields.id, roleId), | ||
}); | ||
|
||
if (roleInfo?.isOwner && database.userId !== user.id) { | ||
return NextResponse.json( | ||
{ success: false, error: "Owner cannot reassign other owner" }, | ||
{ status: 403 } | ||
); | ||
} | ||
|
||
const userRole = await getUserRoleInfo(userId, database.id); | ||
|
||
if (userRole) { | ||
// Update the role if it exists | ||
await db | ||
.update(database_user_role) | ||
.set({ roleId }) | ||
.where( | ||
and( | ||
eq(database_user_role.databaseId, database.id), | ||
eq(database_user_role.userId, userId) | ||
) | ||
); | ||
} else { | ||
await db.insert(database_user_role).values({ | ||
userId, | ||
databaseId: database.id, | ||
roleId, | ||
createdBy: user.id, | ||
createdAt: Date.now(), | ||
}); | ||
} | ||
|
||
return NextResponse.json({ success: true }); | ||
} | ||
); | ||
|
||
export const DELETE = withDatabaseOperation( | ||
async ({ body, database, permission, user }) => { | ||
const parsed = deleteUserSchema.safeParse(body); | ||
|
||
if (!parsed.success) { | ||
return NextResponse.json( | ||
{ | ||
success: false, | ||
error: "Invalid request body", | ||
}, | ||
{ status: 400 } | ||
); | ||
} | ||
|
||
if (!permission.isOwner) { | ||
return NextResponse.json( | ||
{ | ||
success: false, | ||
error: "You do not have permission", | ||
}, | ||
{ status: 403 } | ||
); | ||
} | ||
|
||
const { user: userId } = parsed.data; | ||
|
||
const userRole = await getUserRoleInfo(userId, database.id); | ||
|
||
if (!userRole || !userRole.roleId) { | ||
return NextResponse.json( | ||
{ success: false, error: "User is not assigned to this database" }, | ||
{ status: 404 } | ||
); | ||
} | ||
|
||
const userHasOwnerRole = await checkUserHasOwnerRole(userRole.roleId); | ||
|
||
if (userHasOwnerRole && database.userId !== user.id) { | ||
return NextResponse.json( | ||
{ | ||
success: false, | ||
error: "Only the database creator can remove an owner", | ||
}, | ||
{ status: 403 } | ||
); | ||
} | ||
|
||
await db | ||
.delete(database_user_role) | ||
.where( | ||
and( | ||
eq(database_user_role.databaseId, database.id), | ||
eq(database_user_role.userId, userId) | ||
) | ||
); | ||
|
||
return NextResponse.json({ success: true }); | ||
} | ||
); | ||
|
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { db } from "@/db"; | ||
import { database_role, database_user_role } from "@/db/schema-database"; | ||
import { user } from "@/db/schema-user"; | ||
import withDatabaseOperation from "@/lib/with-database-ops"; | ||
import { eq } from "drizzle-orm"; | ||
import { NextResponse } from "next/server"; | ||
|
||
export const GET = withDatabaseOperation(async ({ database: databaseInfo }) => { | ||
const users = await db | ||
.select({ | ||
id: user.id, | ||
name: user.name, | ||
role: { | ||
id: database_role.id, | ||
name: database_role.name, | ||
}, | ||
createdAt: database_user_role.createdAt, | ||
assignedBy: { | ||
id: user.id, | ||
name: user.name, | ||
}, | ||
}) | ||
.from(database_user_role) | ||
.innerJoin(user, eq(database_user_role.userId, user.id)) | ||
.innerJoin(database_role, eq(database_user_role.roleId, database_role.id)) | ||
.where(eq(database_user_role.databaseId, databaseInfo.id)); | ||
|
||
return NextResponse.json({ users }); | ||
}); |