Add admin session management functionality via new API integration

- Implemented `adminListSessions` function to fetch paginated session data for admin monitoring.
- Updated `useAdmin` hook to include session statistics and new API call.
- Enhanced `DashboardStats` to display total session count.
- Added types for `/api/v1/admin/sessions` endpoint responses, errors, and request parameters.
This commit is contained in:
Felipe Cardoso
2025-11-06 20:01:46 +01:00
parent 01e0b9ab21
commit da1f4e365a
3 changed files with 188 additions and 37 deletions

View File

@@ -3,7 +3,7 @@
import { type Client, type Options as Options2, type TDataShape, urlSearchParamsBodySerializer } from './client';
import { client } from './client.gen';
import type { AdminActivateUserData, AdminActivateUserErrors, AdminActivateUserResponses, AdminAddOrganizationMemberData, AdminAddOrganizationMemberErrors, AdminAddOrganizationMemberResponses, AdminBulkUserActionData, AdminBulkUserActionErrors, AdminBulkUserActionResponses, AdminCreateOrganizationData, AdminCreateOrganizationErrors, AdminCreateOrganizationResponses, AdminCreateUserData, AdminCreateUserErrors, AdminCreateUserResponses, AdminDeactivateUserData, AdminDeactivateUserErrors, AdminDeactivateUserResponses, AdminDeleteOrganizationData, AdminDeleteOrganizationErrors, AdminDeleteOrganizationResponses, AdminDeleteUserData, AdminDeleteUserErrors, AdminDeleteUserResponses, AdminGetOrganizationData, AdminGetOrganizationErrors, AdminGetOrganizationResponses, AdminGetUserData, AdminGetUserErrors, AdminGetUserResponses, AdminListOrganizationMembersData, AdminListOrganizationMembersErrors, AdminListOrganizationMembersResponses, AdminListOrganizationsData, AdminListOrganizationsErrors, AdminListOrganizationsResponses, AdminListUsersData, AdminListUsersErrors, AdminListUsersResponses, AdminRemoveOrganizationMemberData, AdminRemoveOrganizationMemberErrors, AdminRemoveOrganizationMemberResponses, AdminUpdateOrganizationData, AdminUpdateOrganizationErrors, AdminUpdateOrganizationResponses, AdminUpdateUserData, AdminUpdateUserErrors, AdminUpdateUserResponses, ChangeCurrentUserPasswordData, ChangeCurrentUserPasswordErrors, ChangeCurrentUserPasswordResponses, CleanupExpiredSessionsData, CleanupExpiredSessionsResponses, ConfirmPasswordResetData, ConfirmPasswordResetErrors, ConfirmPasswordResetResponses, DeleteUserData, DeleteUserErrors, DeleteUserResponses, GetCurrentUserProfileData, GetCurrentUserProfileResponses, GetMyOrganizationsData, GetMyOrganizationsErrors, GetMyOrganizationsResponses, GetOrganizationData, GetOrganizationErrors, GetOrganizationMembersData, GetOrganizationMembersErrors, GetOrganizationMembersResponses, GetOrganizationResponses, GetUserByIdData, GetUserByIdErrors, GetUserByIdResponses, HealthCheckData, HealthCheckResponses, ListMySessionsData, ListMySessionsResponses, ListUsersData, ListUsersErrors, ListUsersResponses, LoginData, LoginErrors, LoginOauthData, LoginOauthErrors, LoginOauthResponses, LoginResponses, LogoutAllData, LogoutAllResponses, LogoutData, LogoutErrors, LogoutResponses, RefreshTokenData, RefreshTokenErrors, RefreshTokenResponses, RegisterData, RegisterErrors, RegisterResponses, RequestPasswordResetData, RequestPasswordResetErrors, RequestPasswordResetResponses, RevokeSessionData, RevokeSessionErrors, RevokeSessionResponses, RootGetData, RootGetResponses, UpdateCurrentUserData, UpdateCurrentUserErrors, UpdateCurrentUserResponses, UpdateOrganizationData, UpdateOrganizationErrors, UpdateOrganizationResponses, UpdateUserData, UpdateUserErrors, UpdateUserResponses } from './types.gen';
import type { AdminActivateUserData, AdminActivateUserErrors, AdminActivateUserResponses, AdminAddOrganizationMemberData, AdminAddOrganizationMemberErrors, AdminAddOrganizationMemberResponses, AdminBulkUserActionData, AdminBulkUserActionErrors, AdminBulkUserActionResponses, AdminCreateOrganizationData, AdminCreateOrganizationErrors, AdminCreateOrganizationResponses, AdminCreateUserData, AdminCreateUserErrors, AdminCreateUserResponses, AdminDeactivateUserData, AdminDeactivateUserErrors, AdminDeactivateUserResponses, AdminDeleteOrganizationData, AdminDeleteOrganizationErrors, AdminDeleteOrganizationResponses, AdminDeleteUserData, AdminDeleteUserErrors, AdminDeleteUserResponses, AdminGetOrganizationData, AdminGetOrganizationErrors, AdminGetOrganizationResponses, AdminGetUserData, AdminGetUserErrors, AdminGetUserResponses, AdminListOrganizationMembersData, AdminListOrganizationMembersErrors, AdminListOrganizationMembersResponses, AdminListOrganizationsData, AdminListOrganizationsErrors, AdminListOrganizationsResponses, AdminListSessionsData, AdminListSessionsErrors, AdminListSessionsResponses, AdminListUsersData, AdminListUsersErrors, AdminListUsersResponses, AdminRemoveOrganizationMemberData, AdminRemoveOrganizationMemberErrors, AdminRemoveOrganizationMemberResponses, AdminUpdateOrganizationData, AdminUpdateOrganizationErrors, AdminUpdateOrganizationResponses, AdminUpdateUserData, AdminUpdateUserErrors, AdminUpdateUserResponses, ChangeCurrentUserPasswordData, ChangeCurrentUserPasswordErrors, ChangeCurrentUserPasswordResponses, CleanupExpiredSessionsData, CleanupExpiredSessionsResponses, ConfirmPasswordResetData, ConfirmPasswordResetErrors, ConfirmPasswordResetResponses, DeleteUserData, DeleteUserErrors, DeleteUserResponses, GetCurrentUserProfileData, GetCurrentUserProfileResponses, GetMyOrganizationsData, GetMyOrganizationsErrors, GetMyOrganizationsResponses, GetOrganizationData, GetOrganizationErrors, GetOrganizationMembersData, GetOrganizationMembersErrors, GetOrganizationMembersResponses, GetOrganizationResponses, GetUserByIdData, GetUserByIdErrors, GetUserByIdResponses, HealthCheckData, HealthCheckResponses, ListMySessionsData, ListMySessionsResponses, ListUsersData, ListUsersErrors, ListUsersResponses, LoginData, LoginErrors, LoginOauthData, LoginOauthErrors, LoginOauthResponses, LoginResponses, LogoutAllData, LogoutAllResponses, LogoutData, LogoutErrors, LogoutResponses, RefreshTokenData, RefreshTokenErrors, RefreshTokenResponses, RegisterData, RegisterErrors, RegisterResponses, RequestPasswordResetData, RequestPasswordResetErrors, RequestPasswordResetResponses, RevokeSessionData, RevokeSessionErrors, RevokeSessionResponses, RootGetData, RootGetResponses, UpdateCurrentUserData, UpdateCurrentUserErrors, UpdateCurrentUserResponses, UpdateOrganizationData, UpdateOrganizationErrors, UpdateOrganizationResponses, UpdateUserData, UpdateUserErrors, UpdateUserResponses } from './types.gen';
export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = Options2<TData, ThrowOnError> & {
/**
@@ -812,6 +812,28 @@ export const adminRemoveOrganizationMember = <ThrowOnError extends boolean = fal
});
};
/**
* Admin: List All Sessions
*
* List all sessions across all users (admin only).
*
* Returns paginated list of sessions with user information.
* Useful for admin dashboard statistics and session monitoring.
*/
export const adminListSessions = <ThrowOnError extends boolean = false>(options?: Options<AdminListSessionsData, ThrowOnError>) => {
return (options?.client ?? client).get<AdminListSessionsResponses, AdminListSessionsErrors, ThrowOnError>({
responseType: 'json',
security: [
{
scheme: 'bearer',
type: 'http'
}
],
url: '/api/v1/admin/sessions',
...options
});
};
/**
* Get My Organizations
*

View File

@@ -23,6 +23,76 @@ export type AddMemberRequest = {
role?: OrganizationRole;
};
/**
* AdminSessionResponse
*
* Schema for session responses in admin panel.
*
* Includes user information for admin to see who owns each session.
*/
export type AdminSessionResponse = {
/**
* Device Name
*
* Friendly device name
*/
device_name?: string | null;
/**
* Device Id
*
* Persistent device identifier
*/
device_id?: string | null;
/**
* Id
*/
id: string;
/**
* User Id
*/
user_id: string;
/**
* User Email
*
* Email of the user who owns this session
*/
user_email: string;
/**
* User Full Name
*
* Full name of the user
*/
user_full_name?: string | null;
/**
* Ip Address
*/
ip_address?: string | null;
/**
* Location City
*/
location_city?: string | null;
/**
* Location Country
*/
location_country?: string | null;
/**
* Last Used At
*/
last_used_at: string;
/**
* Created At
*/
created_at: string;
/**
* Expires At
*/
expires_at: string;
/**
* Is Active
*/
is_active: boolean;
};
/**
* Body_login_oauth
*/
@@ -312,6 +382,22 @@ export type OrganizationUpdate = {
} | null;
};
/**
* PaginatedResponse[AdminSessionResponse]
*/
export type PaginatedResponseAdminSessionResponse = {
/**
* Data
*
* List of items
*/
data: Array<AdminSessionResponse>;
/**
* Pagination metadata
*/
pagination: PaginationMeta;
};
/**
* PaginatedResponse[OrganizationMemberResponse]
*/
@@ -1711,6 +1797,46 @@ export type AdminRemoveOrganizationMemberResponses = {
export type AdminRemoveOrganizationMemberResponse = AdminRemoveOrganizationMemberResponses[keyof AdminRemoveOrganizationMemberResponses];
export type AdminListSessionsData = {
body?: never;
path?: never;
query?: {
/**
* Is Active
*
* Filter by active status
*/
is_active?: boolean | null;
/**
* Page
*/
page?: number;
/**
* Limit
*/
limit?: number;
};
url: '/api/v1/admin/sessions';
};
export type AdminListSessionsErrors = {
/**
* Validation Error
*/
422: HttpValidationError;
};
export type AdminListSessionsError = AdminListSessionsErrors[keyof AdminListSessionsErrors];
export type AdminListSessionsResponses = {
/**
* Successful Response
*/
200: PaginatedResponseAdminSessionResponse;
};
export type AdminListSessionsResponse = AdminListSessionsResponses[keyof AdminListSessionsResponses];
export type GetMyOrganizationsData = {
body?: never;
path?: never;

View File

@@ -11,31 +11,31 @@
'use client';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query';
import {
adminListUsers,
adminListOrganizations,
adminCreateUser,
adminGetUser,
adminUpdateUser,
adminDeleteUser,
type AddMemberRequest,
adminActivateUser,
adminDeactivateUser,
adminAddOrganizationMember,
adminBulkUserAction,
adminCreateOrganization,
adminUpdateOrganization,
adminCreateUser,
adminDeactivateUser,
adminDeleteOrganization,
adminDeleteUser,
adminGetOrganization,
adminListOrganizationMembers,
adminAddOrganizationMember,
adminListOrganizations,
adminListSessions,
adminListUsers,
adminRemoveOrganizationMember,
type UserCreate,
type UserUpdate,
adminUpdateOrganization,
adminUpdateUser,
type OrganizationCreate,
type OrganizationUpdate,
type AddMemberRequest,
type UserCreate,
type UserUpdate,
} from '@/lib/api/client';
import { useAuth } from '@/lib/auth/AuthContext';
import {useAuth} from '@/lib/auth/AuthContext';
/**
* Constants for admin hooks
@@ -51,7 +51,7 @@ export interface AdminStats {
totalUsers: number;
activeUsers: number;
totalOrganizations: number;
totalSessions: number; // TODO: Requires admin sessions endpoint
totalSessions: number;
}
/**
@@ -103,19 +103,22 @@ export function useAdminStats() {
const orgsData = (orgsResponse as { data: { pagination: { total: number } } }).data;
const totalOrganizations = orgsData?.pagination?.total || 0;
// TODO: Add admin sessions endpoint
// Currently no admin-level endpoint exists to fetch all sessions
// across all users. The /api/v1/sessions/me endpoint only returns
// sessions for the current user.
//
// Once backend implements /api/v1/admin/sessions, uncomment below:
// const sessionsResponse = await adminListSessions({
// query: { page: 1, limit: 10000 },
// throwOnError: false,
// });
// const totalSessions = sessionsResponse.data?.pagination?.total || 0;
// Fetch sessions list
const sessionsResponse = await adminListSessions({
query: {
page: 1,
limit: STATS_FETCH_LIMIT,
},
throwOnError: false,
});
const totalSessions = 0; // Placeholder until admin sessions endpoint exists
if ('error' in sessionsResponse) {
throw new Error('Failed to fetch sessions');
}
// Type assertion: if no error, response has data
const sessionsData = (sessionsResponse as { data: { pagination: { total: number } } }).data;
const totalSessions = sessionsData?.pagination?.total || 0;
return {
totalUsers,