feat: Implement user management service and frontend integration

- Added UserService to manage Keycloak users with license validation in the backend.
- Created API client for user management in the frontend.
- Developed user management page with functionalities to create, update, delete, and list users.
- Implemented user statistics retrieval and display.
- Added dialogs for user creation, editing, password change, and deletion confirmation.
This commit is contained in:
2026-01-13 09:56:53 -06:00
parent 34e71b3114
commit f812d71508
10 changed files with 1759 additions and 108 deletions

View File

@@ -0,0 +1,149 @@
/**
* Cliente API para gestión de usuarios
*/
import { api } from '$lib/api';
export interface User {
id: string;
username: string;
email: string;
first_name: string;
last_name: string;
enabled: boolean;
email_verified: boolean;
created_timestamp?: number;
role?: string;
}
export interface UserStats {
total_users: number;
active_users: number;
inactive_users: number;
max_users_allowed: number;
users_available: number;
usage_percentage: number;
}
export interface UserListResponse {
users: User[];
total: number;
page: number;
page_size: number;
total_pages: number;
}
export interface CreateUserRequest {
email: string;
username: string;
first_name: string;
last_name: string;
password: string;
role?: string;
enabled?: boolean;
email_verified?: boolean;
}
export interface UpdateUserRequest {
first_name?: string;
last_name?: string;
email?: string;
enabled?: boolean;
email_verified?: boolean;
role?: string;
}
export interface ChangePasswordRequest {
password: string;
temporary?: boolean;
}
export const usersAPI = {
/**
* Obtiene estadísticas de usuarios del tenant
*/
async getStats(): Promise<UserStats> {
const response = await api.get<UserStats>('/v1/core/users/stats');
if (response.error) {
throw new Error(response.error);
}
return response.data!;
},
/**
* Lista usuarios del tenant con paginación
*/
async list(params?: {
page?: number;
page_size?: number;
search?: string;
}): Promise<UserListResponse> {
const queryParams = new URLSearchParams();
if (params?.page) queryParams.set('page', params.page.toString());
if (params?.page_size) queryParams.set('page_size', params.page_size.toString());
if (params?.search) queryParams.set('search', params.search);
const endpoint = `/v1/core/users/${queryParams.toString() ? `?${queryParams}` : ''}`;
const response = await api.get<UserListResponse>(endpoint);
if (response.error) {
throw new Error(response.error);
}
return response.data!;
},
/**
* Obtiene un usuario específico
*/
async get(userId: string): Promise<User> {
const response = await api.get<User>(`/v1/core/users/${userId}`);
if (response.error) {
throw new Error(response.error);
}
return response.data!;
},
/**
* Crea un nuevo usuario
*/
async create(data: CreateUserRequest): Promise<User> {
const response = await api.post<User>('/v1/core/users/', data);
if (response.error) {
throw new Error(response.error);
}
return response.data!;
},
/**
* Actualiza un usuario existente
*/
async update(userId: string, data: UpdateUserRequest): Promise<User> {
const response = await api.put<User>(`/v1/core/users/${userId}`, data);
if (response.error) {
throw new Error(response.error);
}
return response.data!;
},
/**
* Elimina un usuario
*/
async delete(userId: string, softDelete: boolean = true): Promise<void> {
const queryParams = new URLSearchParams();
queryParams.set('soft_delete', softDelete.toString());
const response = await api.delete(`/v1/core/users/${userId}?${queryParams}`);
if (response.error) {
throw new Error(response.error);
}
},
/**
* Cambia la contraseña de un usuario
*/
async changePassword(userId: string, data: ChangePasswordRequest): Promise<void> {
const response = await api.post(`/v1/core/users/${userId}/change-password`, data);
if (response.error) {
throw new Error(response.error);
}
}
};