Update package dependencies, enhance README for clarity, and implement new features in the admin panel and script detail pages. Added support for collections, improved script submission previews, and refactored comment handling in the script detail view.

This commit is contained in:
2025-08-15 20:29:02 +01:00
parent 5fdfe3e790
commit ef211ebe0a
27 changed files with 3457 additions and 353 deletions

168
src/lib/api/users.ts Normal file
View File

@ -0,0 +1,168 @@
import { db } from '@/lib/db';
import { users } from '@/lib/db/schema';
import { eq, like } from 'drizzle-orm';
import { generateId, ApiError } from './index';
export interface CreateUserData {
email: string;
username: string;
displayName: string;
avatarUrl?: string;
bio?: string;
}
export interface UpdateUserData {
username?: string;
displayName?: string;
avatarUrl?: string;
bio?: string;
}
// Create a new user
export async function createUser(data: CreateUserData) {
try {
const userId = generateId();
const now = new Date();
const [user] = await db.insert(users).values({
id: userId,
email: data.email,
username: data.username,
displayName: data.displayName,
avatarUrl: data.avatarUrl,
bio: data.bio,
isAdmin: false,
isModerator: false,
createdAt: now,
updatedAt: now,
}).returning();
return user;
} catch (error) {
throw new ApiError(`Failed to create user: ${error}`, 500);
}
}
// Get user by ID
export async function getUserById(id: string) {
try {
const user = await db.query.users.findFirst({
where: eq(users.id, id),
with: {
scripts: {
where: eq(users.isAdmin, true) ? undefined : eq(users.id, id), // Only show own scripts unless admin
},
},
});
if (!user) {
throw new ApiError('User not found', 404);
}
return user;
} catch (error) {
if (error instanceof ApiError) throw error;
throw new ApiError(`Failed to get user: ${error}`, 500);
}
}
// Get user by email
export async function getUserByEmail(email: string) {
try {
const user = await db.query.users.findFirst({
where: eq(users.email, email),
});
return user;
} catch (error) {
throw new ApiError(`Failed to get user by email: ${error}`, 500);
}
}
// Get user by username
export async function getUserByUsername(username: string) {
try {
const user = await db.query.users.findFirst({
where: eq(users.username, username),
});
return user;
} catch (error) {
throw new ApiError(`Failed to get user by username: ${error}`, 500);
}
}
// Update user
export async function updateUser(id: string, data: UpdateUserData) {
try {
const updateData = {
...data,
updatedAt: new Date(),
};
const [updatedUser] = await db
.update(users)
.set(updateData)
.where(eq(users.id, id))
.returning();
return updatedUser;
} catch (error) {
throw new ApiError(`Failed to update user: ${error}`, 500);
}
}
// Update user permissions (admin only)
export async function updateUserPermissions(
id: string,
permissions: { isAdmin?: boolean; isModerator?: boolean }
) {
try {
const updateData = {
...permissions,
updatedAt: new Date(),
};
const [updatedUser] = await db
.update(users)
.set(updateData)
.where(eq(users.id, id))
.returning();
return updatedUser;
} catch (error) {
throw new ApiError(`Failed to update user permissions: ${error}`, 500);
}
}
// Search users
export async function searchUsers(query: string, limit: number = 20) {
try {
const searchResults = await db
.select()
.from(users)
.where(
like(users.username, `%${query}%`)
)
.limit(limit);
return searchResults;
} catch (error) {
throw new ApiError(`Failed to search users: ${error}`, 500);
}
}
// Get all users (admin only)
export async function getAllUsers(limit: number = 50, offset: number = 0) {
try {
const allUsers = await db
.select()
.from(users)
.limit(limit)
.offset(offset);
return allUsers;
} catch (error) {
throw new ApiError(`Failed to get all users: ${error}`, 500);
}
}