Include user information and token expiration in authentication responses

Updated the `Token` schema to include `user` data and `expires_in` field. Adjusted backend `auth_service.py` to populate these fields while generating tokens. Replaced `getCurrentUserInfo` with `getCurrentUserProfile` in the frontend and disabled ESLint for generated files to suppress warnings.
This commit is contained in:
2025-11-02 04:36:29 +01:00
parent 0b0d1d2b06
commit e25b010b57
15 changed files with 37 additions and 48 deletions

2
backend/app/schemas/users.py Normal file → Executable file
View File

@@ -86,6 +86,8 @@ class Token(BaseModel):
access_token: str
refresh_token: Optional[str] = None
token_type: str = "bearer"
user: "UserResponse" # Forward reference since UserResponse is defined above
expires_in: Optional[int] = None # Token expiration in seconds
class TokenPayload(BaseModel):

View File

@@ -15,7 +15,7 @@ from app.core.auth import (
TokenInvalidError
)
from app.models.user import User
from app.schemas.users import Token, UserCreate
from app.schemas.users import Token, UserCreate, UserResponse
logger = logging.getLogger(__name__)
@@ -118,7 +118,7 @@ class AuthService:
user: User to create tokens for
Returns:
Token object with access and refresh tokens
Token object with access and refresh tokens and user info
"""
# Generate claims
claims = {
@@ -137,9 +137,14 @@ class AuthService:
subject=str(user.id)
)
# Convert User model to UserResponse schema
user_response = UserResponse.model_validate(user)
return Token(
access_token=access_token,
refresh_token=refresh_token
refresh_token=refresh_token,
user=user_response,
expires_in=86400 # 24 hours in seconds (matching ACCESS_TOKEN_EXPIRE_MINUTES)
)
@staticmethod

View File

@@ -1,5 +0,0 @@
{
"root": true,
"ignorePatterns": ["*"],
"rules": {}
}

View File

@@ -1,4 +1,5 @@
// This file is auto-generated by @hey-api/openapi-ts
/* eslint-disable */
import { type ClientOptions, type Config, createClient, createConfig } from './client';
import type { ClientOptions as ClientOptions2 } from './types.gen';

View File

@@ -1,4 +1,5 @@
// This file is auto-generated by @hey-api/openapi-ts
/* eslint-disable */
export type { Auth } from '../core/auth.gen';
export type { QuerySerializerOptions } from '../core/bodySerializer.gen';

View File

@@ -1,4 +1,5 @@
// This file is auto-generated by @hey-api/openapi-ts
/* eslint-disable */
export type AuthToken = string | undefined;

View File

@@ -1,4 +1,5 @@
// This file is auto-generated by @hey-api/openapi-ts
/* eslint-disable */
type Slot = 'body' | 'headers' | 'path' | 'query';

View File

@@ -1,4 +1,5 @@
// This file is auto-generated by @hey-api/openapi-ts
/* eslint-disable */
interface SerializeOptions<T>
extends SerializePrimitiveOptions,

View File

@@ -1,4 +1,5 @@
// This file is auto-generated by @hey-api/openapi-ts
/* eslint-disable */
/**
* JSON-friendly union that mirrors what Pinia Colada can hash.

View File

@@ -1,4 +1,5 @@
// This file is auto-generated by @hey-api/openapi-ts
/* eslint-disable */
import type { Auth, AuthToken } from './auth.gen';
import type {

View File

@@ -1,4 +1,5 @@
// This file is auto-generated by @hey-api/openapi-ts
/* eslint-disable */
import type { BodySerializer, QuerySerializer } from './bodySerializer.gen';
import {

View File

@@ -1,4 +1,5 @@
// This file is auto-generated by @hey-api/openapi-ts
/* eslint-disable */
export type * from './types.gen';
export * from './sdk.gen';

View File

@@ -1,8 +1,9 @@
// This file is auto-generated by @hey-api/openapi-ts
/* eslint-disable */
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, GetCurrentUserInfoData, GetCurrentUserInfoResponses, 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, 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> & {
/**
@@ -129,27 +130,6 @@ export const refreshToken = <ThrowOnError extends boolean = false>(options: Opti
});
};
/**
* Get Current User Info
*
* Get current user information.
*
* Requires authentication.
*/
export const getCurrentUserInfo = <ThrowOnError extends boolean = false>(options?: Options<GetCurrentUserInfoData, ThrowOnError>) => {
return (options?.client ?? client).get<GetCurrentUserInfoResponses, unknown, ThrowOnError>({
responseType: 'json',
security: [
{
scheme: 'bearer',
type: 'http'
}
],
url: '/api/v1/auth/me',
...options
});
};
/**
* Request Password Reset
*

View File

@@ -1,4 +1,5 @@
// This file is auto-generated by @hey-api/openapi-ts
/* eslint-disable */
export type ClientOptions = {
baseURL: `${string}://${string}` | (string & {});
@@ -560,6 +561,11 @@ export type Token = {
* Token Type
*/
token_type?: string;
user: UserResponse;
/**
* Expires In
*/
expires_in?: number | null;
};
/**
@@ -650,6 +656,10 @@ export type UserUpdate = {
* Phone Number
*/
phone_number?: string | null;
/**
* Password
*/
password?: string | null;
/**
* Preferences
*/
@@ -660,6 +670,10 @@ export type UserUpdate = {
* Is Active
*/
is_active?: boolean | null;
/**
* Is Superuser
*/
is_superuser?: boolean | null;
};
/**
@@ -810,22 +824,6 @@ export type RefreshTokenResponses = {
export type RefreshTokenResponse = RefreshTokenResponses[keyof RefreshTokenResponses];
export type GetCurrentUserInfoData = {
body?: never;
path?: never;
query?: never;
url: '/api/v1/auth/me';
};
export type GetCurrentUserInfoResponses = {
/**
* Successful Response
*/
200: UserResponse;
};
export type GetCurrentUserInfoResponse = GetCurrentUserInfoResponses[keyof GetCurrentUserInfoResponses];
export type RequestPasswordResetData = {
body: PasswordResetRequest;
path?: never;

4
frontend/src/lib/api/hooks/useAuth.ts Normal file → Executable file
View File

@@ -15,7 +15,7 @@ import {
register,
logout,
logoutAll,
getCurrentUserInfo,
getCurrentUserProfile,
requestPasswordReset,
confirmPasswordReset,
changeCurrentUserPassword,
@@ -55,7 +55,7 @@ export function useMe() {
const query = useQuery({
queryKey: authKeys.me,
queryFn: async (): Promise<User> => {
const response = await getCurrentUserInfo({
const response = await getCurrentUserProfile({
throwOnError: true,
});
return response.data as User;