better-chatbot / src /lib /user /server.ts
Bot
Initial commit for HF Spaces
05c5ed5
Raw
History Blame Contribute Delete
4.58 kB
"use server";
import { BasicUserWithLastLogin, UserPreferences } from "app-types/user";
import { auth, getSession } from "auth/server";
import { Session } from "better-auth";
import { userRepository } from "lib/db/repository";
import { headers } from "next/headers";
import { notFound } from "next/navigation";
import { customModelProvider } from "@/lib/ai/models";
// Helper function to get model provider from model name
const getModelProvider = (modelName: string): string => {
for (const { provider, models } of customModelProvider.modelsInfo) {
for (const model of models) {
if (model.name === modelName) {
return provider;
}
}
}
return "unknown";
};
/**
* Get the user by id
* We can only get the user by id for the current user as a non-admin user
* We can get the user by id for any user as an admin user
*/
export async function getUser(
userId?: string,
): Promise<BasicUserWithLastLogin | null> {
const resolvedUserId = await getUserIdAndCheckAccess(userId);
return await userRepository.getUserById(resolvedUserId);
}
/**
* Get user accounts
* We can only list accounts for the current user as a non-admin user
* We can list accounts for any user as an admin user
*/
export async function getUserAccounts(userId?: string) {
const resolvedUserId = await getUserIdAndCheckAccess(userId);
const accounts = await auth.api.listUserAccounts({
params: { userId: resolvedUserId },
headers: await headers(),
});
const hasPassword = accounts.some(
(account) => account.providerId === "credential",
);
const oauthProviders = accounts
.filter((account) => account.providerId !== "credential")
.map((account) => account.providerId);
return { accounts, hasPassword, oauthProviders };
}
/**
* List user sessions
* We use the better-auth API to list the sessions
* We can only list sessions for the current user as a non-admin user
* We can list sessions for any user as an admin user
*/
export async function getUserSessions(userId?: string): Promise<Session[]> {
const resolvedUserId = await getUserIdAndCheckAccess(userId);
return await auth.api.listSessions({
params: { userId: resolvedUserId },
headers: await headers(),
});
}
/**
* Get the user ID and check access
* if the requested user id is not provided, we use the current user id
* if the requested user id is provided, we check if the current user has access to the requested user
* if the current user has access to the requested user, we return the requested user id
* if the current user does not have access to the requested user, we throw a 404 error
* if the requested user id is not found, we throw a 404 error
*/
export async function getUserIdAndCheckAccess(
requestedUserId?: string,
): Promise<string> {
const session = await getSession();
if (!session) {
notFound();
}
const currentUserId = session.user.id;
const userId = requestedUserId ? requestedUserId : currentUserId;
if (!userId) {
notFound();
}
return userId;
}
/**
* Get the user stats
* We can only get stats for the current user as a non-admin user
* We can get stats for any user as an admin user
*/
export async function getUserStats(userId?: string): Promise<{
threadCount: number;
messageCount: number;
modelStats: Array<{
model: string;
messageCount: number;
totalTokens: number;
provider: string;
}>;
totalTokens: number;
period: string;
}> {
const resolvedUserId = await getUserIdAndCheckAccess(userId);
const stats = await userRepository.getUserStats(resolvedUserId);
// Add provider information to each model stat
return {
...stats,
modelStats: stats.modelStats.map((stat) => ({
...stat,
provider: getModelProvider(stat.model),
})),
};
}
/**
* Get the user preferences
* We can only get preferences for the current user as a non-admin user
* We can get preferences for any user as an admin user
*/
export async function getUserPreferences(
userId?: string,
): Promise<UserPreferences | null> {
const resolvedUserId = await getUserIdAndCheckAccess(userId);
return await userRepository.getPreferences(resolvedUserId);
}
export async function updateUserDetails(
userId: string,
name?: string,
email?: string,
image?: string,
) {
const resolvedUserId = await getUserIdAndCheckAccess(userId);
if (!name && !email && !image) {
return;
}
return await userRepository.updateUserDetails({
userId: resolvedUserId,
...(name && { name }),
...(email && { email }),
...(image && { image }),
});
}