- Admin users can choose to install skills to public (built-in) or custom category via UI radio selector in InstallSkillDialog - Backend: SkillStorage.ainstall_skill_from_archive accepts target_category param; non-admin 403 on public install - Backend: AgentStore/SkillStore add count_owned(user_id); UserRepository/LocalAuthProvider add list_users() - Backend: GET /api/v1/auth/users endpoint (admin-only) returns all users with skill_count and agent_count - Frontend: admin-only "用户管理" nav item in sidebar; /page/workspace/admin/users route with user table - i18n: added sidebar.users and adminUsers section in zh-CN/en-US Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
42 lines
1.1 KiB
TypeScript
42 lines
1.1 KiB
TypeScript
import { apiFetch } from "@/core/api/fetch-client";
|
|
import { getBackendBaseURL } from "@/core/config";
|
|
|
|
import type { LoginByUsernameResponse } from "./index";
|
|
|
|
export interface UserListItem {
|
|
id: string;
|
|
email: string;
|
|
system_role: "admin" | "user";
|
|
skill_count: number;
|
|
agent_count: number;
|
|
}
|
|
|
|
export async function listAllUsers(): Promise<UserListItem[]> {
|
|
const res = await apiFetch(`${getBackendBaseURL()}/api/v1/auth/users`);
|
|
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
return res.json() as Promise<UserListItem[]>;
|
|
}
|
|
|
|
export async function loginByUsername(
|
|
username: string,
|
|
): Promise<LoginByUsernameResponse> {
|
|
const response = await apiFetch(
|
|
`${getBackendBaseURL()}/api/v1/auth/login/username`,
|
|
{
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify({ username }),
|
|
},
|
|
);
|
|
if (!response.ok) {
|
|
const error = await response
|
|
.json()
|
|
.catch(() => ({ detail: "Login failed." }));
|
|
throw new Error(error.detail ?? "Login failed.");
|
|
}
|
|
return response.json() as Promise<LoginByUsernameResponse>;
|
|
}
|
|
|