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:
149
frontend/src/lib/api/dashboard/users.ts
Normal file
149
frontend/src/lib/api/dashboard/users.ts
Normal 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);
|
||||
}
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user