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:
2
backend/app/schemas/users.py
Normal file → Executable file
2
backend/app/schemas/users.py
Normal file → Executable file
@@ -86,6 +86,8 @@ class Token(BaseModel):
|
|||||||
access_token: str
|
access_token: str
|
||||||
refresh_token: Optional[str] = None
|
refresh_token: Optional[str] = None
|
||||||
token_type: str = "bearer"
|
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):
|
class TokenPayload(BaseModel):
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ from app.core.auth import (
|
|||||||
TokenInvalidError
|
TokenInvalidError
|
||||||
)
|
)
|
||||||
from app.models.user import User
|
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__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -118,7 +118,7 @@ class AuthService:
|
|||||||
user: User to create tokens for
|
user: User to create tokens for
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Token object with access and refresh tokens
|
Token object with access and refresh tokens and user info
|
||||||
"""
|
"""
|
||||||
# Generate claims
|
# Generate claims
|
||||||
claims = {
|
claims = {
|
||||||
@@ -137,9 +137,14 @@ class AuthService:
|
|||||||
subject=str(user.id)
|
subject=str(user.id)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Convert User model to UserResponse schema
|
||||||
|
user_response = UserResponse.model_validate(user)
|
||||||
|
|
||||||
return Token(
|
return Token(
|
||||||
access_token=access_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
|
@staticmethod
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"root": true,
|
|
||||||
"ignorePatterns": ["*"],
|
|
||||||
"rules": {}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
// This file is auto-generated by @hey-api/openapi-ts
|
// This file is auto-generated by @hey-api/openapi-ts
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
import { type ClientOptions, type Config, createClient, createConfig } from './client';
|
import { type ClientOptions, type Config, createClient, createConfig } from './client';
|
||||||
import type { ClientOptions as ClientOptions2 } from './types.gen';
|
import type { ClientOptions as ClientOptions2 } from './types.gen';
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// This file is auto-generated by @hey-api/openapi-ts
|
// This file is auto-generated by @hey-api/openapi-ts
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
export type { Auth } from '../core/auth.gen';
|
export type { Auth } from '../core/auth.gen';
|
||||||
export type { QuerySerializerOptions } from '../core/bodySerializer.gen';
|
export type { QuerySerializerOptions } from '../core/bodySerializer.gen';
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// This file is auto-generated by @hey-api/openapi-ts
|
// This file is auto-generated by @hey-api/openapi-ts
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
export type AuthToken = string | undefined;
|
export type AuthToken = string | undefined;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// This file is auto-generated by @hey-api/openapi-ts
|
// This file is auto-generated by @hey-api/openapi-ts
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
type Slot = 'body' | 'headers' | 'path' | 'query';
|
type Slot = 'body' | 'headers' | 'path' | 'query';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// This file is auto-generated by @hey-api/openapi-ts
|
// This file is auto-generated by @hey-api/openapi-ts
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
interface SerializeOptions<T>
|
interface SerializeOptions<T>
|
||||||
extends SerializePrimitiveOptions,
|
extends SerializePrimitiveOptions,
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// This file is auto-generated by @hey-api/openapi-ts
|
// This file is auto-generated by @hey-api/openapi-ts
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JSON-friendly union that mirrors what Pinia Colada can hash.
|
* JSON-friendly union that mirrors what Pinia Colada can hash.
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// This file is auto-generated by @hey-api/openapi-ts
|
// This file is auto-generated by @hey-api/openapi-ts
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
import type { Auth, AuthToken } from './auth.gen';
|
import type { Auth, AuthToken } from './auth.gen';
|
||||||
import type {
|
import type {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// This file is auto-generated by @hey-api/openapi-ts
|
// This file is auto-generated by @hey-api/openapi-ts
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
import type { BodySerializer, QuerySerializer } from './bodySerializer.gen';
|
import type { BodySerializer, QuerySerializer } from './bodySerializer.gen';
|
||||||
import {
|
import {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// This file is auto-generated by @hey-api/openapi-ts
|
// This file is auto-generated by @hey-api/openapi-ts
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
export type * from './types.gen';
|
export type * from './types.gen';
|
||||||
export * from './sdk.gen';
|
export * from './sdk.gen';
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
// This file is auto-generated by @hey-api/openapi-ts
|
// 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 { type Client, type Options as Options2, type TDataShape, urlSearchParamsBodySerializer } from './client';
|
||||||
import { client } from './client.gen';
|
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> & {
|
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
|
* Request Password Reset
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// This file is auto-generated by @hey-api/openapi-ts
|
// This file is auto-generated by @hey-api/openapi-ts
|
||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
export type ClientOptions = {
|
export type ClientOptions = {
|
||||||
baseURL: `${string}://${string}` | (string & {});
|
baseURL: `${string}://${string}` | (string & {});
|
||||||
@@ -560,6 +561,11 @@ export type Token = {
|
|||||||
* Token Type
|
* Token Type
|
||||||
*/
|
*/
|
||||||
token_type?: string;
|
token_type?: string;
|
||||||
|
user: UserResponse;
|
||||||
|
/**
|
||||||
|
* Expires In
|
||||||
|
*/
|
||||||
|
expires_in?: number | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -650,6 +656,10 @@ export type UserUpdate = {
|
|||||||
* Phone Number
|
* Phone Number
|
||||||
*/
|
*/
|
||||||
phone_number?: string | null;
|
phone_number?: string | null;
|
||||||
|
/**
|
||||||
|
* Password
|
||||||
|
*/
|
||||||
|
password?: string | null;
|
||||||
/**
|
/**
|
||||||
* Preferences
|
* Preferences
|
||||||
*/
|
*/
|
||||||
@@ -660,6 +670,10 @@ export type UserUpdate = {
|
|||||||
* Is Active
|
* Is Active
|
||||||
*/
|
*/
|
||||||
is_active?: boolean | null;
|
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 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 = {
|
export type RequestPasswordResetData = {
|
||||||
body: PasswordResetRequest;
|
body: PasswordResetRequest;
|
||||||
path?: never;
|
path?: never;
|
||||||
|
|||||||
4
frontend/src/lib/api/hooks/useAuth.ts
Normal file → Executable file
4
frontend/src/lib/api/hooks/useAuth.ts
Normal file → Executable file
@@ -15,7 +15,7 @@ import {
|
|||||||
register,
|
register,
|
||||||
logout,
|
logout,
|
||||||
logoutAll,
|
logoutAll,
|
||||||
getCurrentUserInfo,
|
getCurrentUserProfile,
|
||||||
requestPasswordReset,
|
requestPasswordReset,
|
||||||
confirmPasswordReset,
|
confirmPasswordReset,
|
||||||
changeCurrentUserPassword,
|
changeCurrentUserPassword,
|
||||||
@@ -55,7 +55,7 @@ export function useMe() {
|
|||||||
const query = useQuery({
|
const query = useQuery({
|
||||||
queryKey: authKeys.me,
|
queryKey: authKeys.me,
|
||||||
queryFn: async (): Promise<User> => {
|
queryFn: async (): Promise<User> => {
|
||||||
const response = await getCurrentUserInfo({
|
const response = await getCurrentUserProfile({
|
||||||
throwOnError: true,
|
throwOnError: true,
|
||||||
});
|
});
|
||||||
return response.data as User;
|
return response.data as User;
|
||||||
|
|||||||
Reference in New Issue
Block a user