Docker images / prepare-release (push) Successful in 10s
Docker images / backend-image (push) Successful in 1m57s
Docker images / frontend-image (push) Successful in 4m8s
Docker images / notify-webhook (push) Skipped
Docker images / updater-image (push) Successful in 44s
Docker images / publish-release (push) Successful in 11s
Added user management functionality, including the creation of app_users and user_interface_bindings tables in the database. Implemented API routes for user data retrieval and permissions handling. Enhanced the traffic monitoring system to include user traffic statistics and interface bindings. Updated relevant components and services to support the new user features, improving overall application functionality and user experience.
106 lines
3.1 KiB
TypeScript
106 lines
3.1 KiB
TypeScript
import {
|
|
appUserReadSchema,
|
|
catalogInterfaceSchema,
|
|
userBindingSchema,
|
|
type AppUserCreate,
|
|
type AppUserRead,
|
|
type AppUserUpdate,
|
|
type CatalogInterface,
|
|
type UserBinding,
|
|
type UserBindingCreate,
|
|
} from "@mmapp/contracts/users"
|
|
import { z } from "zod"
|
|
import { requestJson } from "@/shared/api/http-client"
|
|
import type { AppUser, CatalogIface, InterfaceBinding } from "@/lib/users"
|
|
|
|
const usersListPayload = z.object({ users: z.array(appUserReadSchema) })
|
|
const userPayload = z.object({ user: appUserReadSchema })
|
|
const bindingPayload = z.object({ binding: userBindingSchema })
|
|
const catalogPayload = z.object({ interfaces: z.array(catalogInterfaceSchema) })
|
|
|
|
export function toFrontendBinding(b: UserBinding): InterfaceBinding {
|
|
return {
|
|
id: b.id,
|
|
userId: b.userId,
|
|
serverId: String(b.serverId),
|
|
serverName: b.serverName,
|
|
serverSite: b.serverSite,
|
|
serverCountry: b.serverCountry,
|
|
interfaceName: b.interfaceName,
|
|
interfaceType: b.interfaceType,
|
|
comment: b.comment,
|
|
}
|
|
}
|
|
|
|
export function toFrontendUser(u: AppUserRead): AppUser {
|
|
return {
|
|
id: u.id,
|
|
name: u.name,
|
|
login: u.login,
|
|
email: u.email,
|
|
role: u.role,
|
|
last: u.lastSeen ?? "—",
|
|
avatar: u.avatar,
|
|
active: u.active,
|
|
sections: u.sections,
|
|
servers: u.servers,
|
|
bindings: u.bindings.map(toFrontendBinding),
|
|
}
|
|
}
|
|
|
|
export async function listAppUsers(baseUrl: string): Promise<AppUser[]> {
|
|
const payload = await requestJson<unknown>(baseUrl, "/api/users")
|
|
return usersListPayload.parse(payload).users.map(toFrontendUser)
|
|
}
|
|
|
|
export async function createAppUser(baseUrl: string, data: AppUserCreate): Promise<AppUser> {
|
|
const payload = await requestJson<unknown>(baseUrl, "/api/users", {
|
|
method: "POST",
|
|
body: JSON.stringify(data),
|
|
})
|
|
return toFrontendUser(userPayload.parse(payload).user)
|
|
}
|
|
|
|
export async function updateAppUser(baseUrl: string, id: string, data: AppUserUpdate): Promise<AppUser> {
|
|
const payload = await requestJson<unknown>(baseUrl, `/api/users/${id}`, {
|
|
method: "PATCH",
|
|
body: JSON.stringify(data),
|
|
})
|
|
return toFrontendUser(userPayload.parse(payload).user)
|
|
}
|
|
|
|
export async function deleteAppUser(baseUrl: string, id: string): Promise<void> {
|
|
await requestJson<void>(baseUrl, `/api/users/${id}`, { method: "DELETE" })
|
|
}
|
|
|
|
export async function createUserBinding(
|
|
baseUrl: string,
|
|
userId: string,
|
|
data: UserBindingCreate,
|
|
): Promise<InterfaceBinding> {
|
|
const payload = await requestJson<unknown>(baseUrl, `/api/users/${userId}/bindings`, {
|
|
method: "POST",
|
|
body: JSON.stringify(data),
|
|
})
|
|
return toFrontendBinding(bindingPayload.parse(payload).binding)
|
|
}
|
|
|
|
export async function deleteUserBinding(
|
|
baseUrl: string,
|
|
userId: string,
|
|
bindingId: string,
|
|
): Promise<void> {
|
|
await requestJson<void>(baseUrl, `/api/users/${userId}/bindings/${bindingId}`, { method: "DELETE" })
|
|
}
|
|
|
|
export async function listInterfaceCatalog(
|
|
baseUrl: string,
|
|
serverId: string,
|
|
): Promise<CatalogIface[]> {
|
|
const payload = await requestJson<unknown>(
|
|
baseUrl,
|
|
`/api/users/interface-catalog?serverId=${encodeURIComponent(serverId)}`,
|
|
)
|
|
return catalogPayload.parse(payload).interfaces as CatalogInterface[]
|
|
}
|