first commit

This commit is contained in:
2025-11-24 16:30:37 +00:00
commit 843e93a274
114 changed files with 25585 additions and 0 deletions

209
app/api/users/[id]/route.ts Normal file
View File

@@ -0,0 +1,209 @@
import { NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { userDb } from "@/lib/db";
import bcrypt from "bcryptjs";
// GET /api/users/[id] - Get single user (admin only)
export async function GET(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth();
if (!session?.user) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
// Only admins can view users
if ((session.user as any).role !== 'ADMIN') {
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
}
const { id } = await params;
const user = userDb.findById(id);
if (!user) {
return NextResponse.json({ error: "User not found" }, { status: 404 });
}
const currentUsername = session.user.name || '';
const currentUserId = (session.user as any).id || '';
// Only the "admin" user can view any user details
// ADMIN users can only view their own created viewers
if (currentUsername !== 'admin') {
// Check if this user is a child of the current user
if (user.parent_user_id !== currentUserId) {
return NextResponse.json({ error: "User not found" }, { status: 404 });
}
}
// Remove password hash from response
const { passwordHash, ...safeUser } = user;
return NextResponse.json({ user: safeUser });
} catch (error) {
console.error("Error fetching user:", error);
return NextResponse.json(
{ error: "Failed to fetch user" },
{ status: 500 }
);
}
}
// PATCH /api/users/[id] - Update user (admin only)
export async function PATCH(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth();
if (!session?.user) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
// Only admins can update users
if ((session.user as any).role !== 'ADMIN') {
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
}
const { id } = await params;
const user = userDb.findById(id);
if (!user) {
return NextResponse.json({ error: "User not found" }, { status: 404 });
}
const currentUsername = session.user.name || '';
const currentUserId = (session.user as any).id || '';
// Only the "admin" user can modify any user
// ADMIN users can only modify their own created viewers
if (currentUsername !== 'admin') {
// Check if this user is a child of the current user
if (user.parent_user_id !== currentUserId) {
return NextResponse.json(
{ error: "Forbidden: Cannot modify this user" },
{ status: 403 }
);
}
}
const body = await request.json();
const { username, email, password, role } = body;
// Validation
if (role && !['ADMIN', 'VIEWER'].includes(role)) {
return NextResponse.json(
{ error: "Invalid role. Must be ADMIN or VIEWER" },
{ status: 400 }
);
}
// Check if username is taken by another user
if (username && username !== user.username) {
const existing = userDb.findByUsername(username);
if (existing && existing.id !== id) {
return NextResponse.json(
{ error: "Username already exists" },
{ status: 409 }
);
}
}
// Prepare update data
const updateData: {
username?: string;
email?: string | null;
passwordHash?: string;
role?: string;
} = {};
if (username !== undefined) updateData.username = username;
if (email !== undefined) updateData.email = email;
if (role !== undefined) updateData.role = role;
if (password) {
updateData.passwordHash = await bcrypt.hash(password, 10);
}
const updated = userDb.update(id, updateData);
if (!updated) {
return NextResponse.json({ error: "Failed to update user" }, { status: 500 });
}
// Remove password hash from response
const { passwordHash, ...safeUser } = updated;
return NextResponse.json({ user: safeUser });
} catch (error) {
console.error("Error updating user:", error);
return NextResponse.json(
{ error: "Failed to update user" },
{ status: 500 }
);
}
}
// DELETE /api/users/[id] - Delete user (admin only)
export async function DELETE(
request: Request,
{ params }: { params: Promise<{ id: string }> }
) {
try {
const session = await auth();
if (!session?.user) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
// Only admins can delete users
if ((session.user as any).role !== 'ADMIN') {
return NextResponse.json({ error: "Forbidden" }, { status: 403 });
}
const { id } = await params;
const user = userDb.findById(id);
if (!user) {
return NextResponse.json({ error: "User not found" }, { status: 404 });
}
const currentUsername = session.user.name || '';
const currentUserId = (session.user as any).id || '';
// Only the "admin" user can delete any user
// ADMIN users can only delete their own created viewers
if (currentUsername !== 'admin') {
// Check if this user is a child of the current user
if (user.parent_user_id !== currentUserId) {
return NextResponse.json(
{ error: "Forbidden: Cannot delete this user" },
{ status: 403 }
);
}
}
// Prevent deleting yourself
if ((session.user as any).id === id) {
return NextResponse.json(
{ error: "Cannot delete your own account" },
{ status: 400 }
);
}
const success = userDb.delete(id);
if (!success) {
return NextResponse.json({ error: "Failed to delete user" }, { status: 500 });
}
return NextResponse.json({ message: "User deleted successfully" });
} catch (error) {
console.error("Error deleting user:", error);
return NextResponse.json(
{ error: "Failed to delete user" },
{ status: 500 }
);
}
}