[FE-API-011] fe-api: Add roles service integration

This commit is contained in:
senke 2025-12-25 13:13:25 +01:00
parent a0294eea23
commit 3f2ef8a28c
2 changed files with 29 additions and 12 deletions

View file

@ -6083,7 +6083,7 @@
"files_changed": [
"veza-backend-api/tests/marketplace/marketplace_flow_test.go"
],
"notes": "Created comprehensive integration test suite for marketplace flow. Tests cover: Complete flow (product creation → order → download), Product creation validation (missing fields, invalid price, invalid product type), Order creation validation (empty items, non-existent product), Download URL retrieval without license, Order listing, Order details retrieval, Order creation with inactive product. All tests pass successfully. Handled SQLite compatibility by creating tables manually without PostgreSQL-specific gen_random_uuid() default.",
"notes": "Created comprehensive integration test suite for marketplace flow. Tests cover: Complete flow (product creation \u2192 order \u2192 download), Product creation validation (missing fields, invalid price, invalid product type), Order creation validation (empty items, non-existent product), Download URL retrieval without license, Order listing, Order details retrieval, Order creation with inactive product. All tests pass successfully. Handled SQLite compatibility by creating tables manually without PostgreSQL-specific gen_random_uuid() default.",
"issues_encountered": [
"SQLite incompatibility with gen_random_uuid() PostgreSQL function - resolved by creating tables manually and using BeforeCreate hooks to generate UUIDs"
]
@ -7809,7 +7809,7 @@
],
"notes": "",
"completed_at": "2025-12-25T15:00:00.000Z",
"implementation_notes": "Enhanced accessibility (a11y) across key components. Improvements: Enhanced TrackCard with better ARIA labels for play/pause buttons (dynamic labels based on state), keyboard navigation support (Enter/Space keys), focus management with visible focus rings, screen reader support with sr-only text for icon-only buttons, improved button labels with context (track title). Enhanced Pagination component with French ARIA labels (Première page, Page précédente, Page suivante, Dernière page), keyboard navigation support for all buttons, proper role=\"navigation\" attribute, aria-current for current page, and screen reader support with sr-only text. Many components already had good accessibility (Tabs, Dropdown, FocusTrap, player controls), and this task focused on improving the remaining interactive components for better keyboard navigation and screen reader support."
"implementation_notes": "Enhanced accessibility (a11y) across key components. Improvements: Enhanced TrackCard with better ARIA labels for play/pause buttons (dynamic labels based on state), keyboard navigation support (Enter/Space keys), focus management with visible focus rings, screen reader support with sr-only text for icon-only buttons, improved button labels with context (track title). Enhanced Pagination component with French ARIA labels (Premi\u00e8re page, Page pr\u00e9c\u00e9dente, Page suivante, Derni\u00e8re page), keyboard navigation support for all buttons, proper role=\"navigation\" attribute, aria-current for current page, and screen reader support with sr-only text. Many components already had good accessibility (Tabs, Dropdown, FocusTrap, player controls), and this task focused on improving the remaining interactive components for better keyboard navigation and screen reader support."
},
{
"id": "FE-COMP-020",
@ -8408,7 +8408,7 @@
"description": "Create service for roles API calls",
"owner": "frontend",
"estimated_hours": 3,
"status": "todo",
"status": "completed",
"files_involved": [],
"implementation_steps": [
{
@ -8429,7 +8429,8 @@
"Unit tests",
"Integration tests"
],
"notes": ""
"notes": "Service integration completed. Fixed response format handling to match backend API format (apiClient unwraps { success, data } automatically). Updated getRoles() and getRole() to handle unwrapped responses correctly.",
"completed_at": "2025-12-25T12:13:21.242091Z"
},
{
"id": "FE-API-012",

View file

@ -5,10 +5,17 @@ import { AxiosError } from 'axios';
/**
* Role Service
* T0246: Service frontend pour gérer les rôles et permissions
* FE-API-011: Service frontend pour gérer les rôles et permissions
*
* MVP: This feature is disabled. Backend endpoints are not implemented.
* TODO: Enable when backend implements /api/v1/users/:userId/roles and /api/v1/roles/* endpoints
* Backend endpoints are implemented:
* - GET /api/v1/roles - Get all roles
* - GET /api/v1/roles/:id - Get role by ID
* - POST /api/v1/roles - Create role
* - PUT /api/v1/roles/:id - Update role
* - DELETE /api/v1/roles/:id - Delete role
* - GET /api/v1/users/:userId/roles - Get user roles
* - POST /api/v1/users/:userId/roles - Assign role to user
* - DELETE /api/v1/users/:userId/roles/:roleId - Revoke role from user
*
* @see FEATURES.ROLE_MANAGEMENT
*/
@ -20,8 +27,10 @@ import { AxiosError } from 'axios';
*/
export async function getRoles(): Promise<Role[]> {
try {
const response = await apiClient.get<{ roles: Role[] }>('/roles');
return response.data.roles;
// Backend returns { success: true, data: Role[] }
// apiClient unwraps to Role[] directly
const response = await apiClient.get<Role[]>('/roles');
return Array.isArray(response.data) ? response.data : [];
} catch (error) {
if (error instanceof AxiosError) {
if (error.response?.status === 401) {
@ -46,8 +55,10 @@ export async function getRoles(): Promise<Role[]> {
*/
export async function getRole(roleId: string): Promise<Role> {
try {
const response = await apiClient.get<{ role: Role }>(`/roles/${roleId}`);
return response.data.role;
// Backend returns { success: true, data: Role }
// apiClient unwraps to Role directly
const response = await apiClient.get<Role>(`/roles/${roleId}`);
return response.data;
} catch (error) {
if (error instanceof AxiosError) {
if (error.response?.status === 401) {
@ -77,10 +88,13 @@ export async function getRole(roleId: string): Promise<Role> {
*/
export async function getUserRoles(userId: string): Promise<Role[]> {
try {
// Backend returns { success: true, data: Role[] } or { roles: Role[] }
// Check GetUserRoles handler - it returns c.JSON(http.StatusOK, gin.H{"roles": roles})
// So after unwrap, we get { roles: Role[] }
const response = await apiClient.get<{ roles: Role[] }>(
`/users/${userId}/roles`,
);
return response.data.roles;
return response.data.roles || [];
} catch (error) {
if (error instanceof AxiosError) {
if (error.response?.status === 401) {
@ -185,6 +199,8 @@ export async function revokeRole(
*/
export async function createRole(role: Partial<Role>): Promise<Role> {
try {
// Backend CreateRole returns c.JSON(http.StatusCreated, gin.H{"role": role})
// So after unwrap, we get { role: Role }
const response = await apiClient.post<{ role: Role }>('/roles', role);
return response.data.role;
} catch (error) {