refactor: improve code formatting and consistency across multiple files
- Standardized import statements and removed unnecessary line breaks for better readability in various components. - Enhanced error handling and logging in the useElectronPrinter hook. - Updated sample data formatting in AgGridShowcase for improved clarity. - Refactored JSX elements for consistent indentation and structure in LandingSample, AuthPage, and EventsPage components. - Consolidated and simplified conditional rendering logic in several components. These changes aim to enhance code maintainability and readability throughout the project.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { lodash } from '@repo/utils';
|
||||
import { appDatabase, AppDatabaseKey, appStorage, AppStorageKey } from '../storage/local';
|
||||
import { PrivilegeEntity } from '@repo/ui/foundations';
|
||||
import { API_URL } from '../constants/api-url';
|
||||
import { mapUserPrivileges } from './map-user-privileges';
|
||||
import type { AuthUser, TokenPair } from './auth.types';
|
||||
|
||||
interface TerminateOptions {
|
||||
/** When true, appends ?redirect= so the user returns to their page after re-login.
|
||||
@@ -9,78 +10,111 @@ interface TerminateOptions {
|
||||
preserveRedirect?: boolean;
|
||||
}
|
||||
|
||||
export async function terminateAuthSession(options: TerminateOptions = {}) {
|
||||
export async function persistTokenPair(tokens: TokenPair): Promise<void> {
|
||||
await appDatabase.setItem(AppDatabaseKey.ACCESS_TOKEN, tokens.accessToken);
|
||||
await appDatabase.setItem(AppDatabaseKey.REFRESH_TOKEN, tokens.refreshToken);
|
||||
}
|
||||
|
||||
export async function persistUserSession(me: AuthUser): Promise<void> {
|
||||
const label = me.isSuperadmin ? 'Superadmin' : (me.privilege?.name ?? me.username);
|
||||
|
||||
await appStorage.setItem(AppStorageKey.USER_ID, me.id);
|
||||
await appDatabase.setItem(AppDatabaseKey.USER_PROFILE, {
|
||||
id: me.id,
|
||||
username: me.username,
|
||||
isSuperadmin: me.isSuperadmin,
|
||||
privilege: me.privilege,
|
||||
name: me.username,
|
||||
label,
|
||||
});
|
||||
await appDatabase.setItem(AppDatabaseKey.USER_PRIVILEGE, mapUserPrivileges(me.permissions, me.isSuperadmin));
|
||||
}
|
||||
|
||||
export async function terminateAuthSession(options: TerminateOptions = {}): Promise<void> {
|
||||
const { preserveRedirect = false } = options;
|
||||
|
||||
/**
|
||||
* Delete invalid tokens (Clear local state)
|
||||
*/
|
||||
await appDatabase.removeItem(AppDatabaseKey.USER_PRIVILEGE);
|
||||
await appDatabase.removeItem(AppDatabaseKey.USER_PROFILE);
|
||||
await appDatabase.removeItem(AppDatabaseKey.ACCESS_TOKEN);
|
||||
await appDatabase.removeItem(AppDatabaseKey.REFRESH_TOKEN);
|
||||
await appStorage.removeItem(AppStorageKey.USER_ID);
|
||||
|
||||
/**
|
||||
* Build the login URL
|
||||
*/
|
||||
let loginUrl = '/auth/login';
|
||||
|
||||
// Check if the current page is NOT the login page
|
||||
const isNotLoginPage = !window.location.pathname.includes('/auth/login');
|
||||
|
||||
if (isNotLoginPage) {
|
||||
// Set redirect parameters only if requested AND the user is not currently on the login page
|
||||
if (preserveRedirect) {
|
||||
const currentPath = window.location.pathname + window.location.search;
|
||||
loginUrl += `?redirect=${encodeURIComponent(currentPath)}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect without saving history to prevent infinite back-loops
|
||||
*/
|
||||
window.location.replace(loginUrl);
|
||||
}
|
||||
}
|
||||
|
||||
export async function initiateAuthSession(respLogin: any) {
|
||||
try {
|
||||
const data = respLogin?.data ?? {};
|
||||
const { token, id } = data;
|
||||
const userProfile = lodash.omit(data, ['token']);
|
||||
|
||||
if (!token) throw new Error('Login response missing token');
|
||||
|
||||
// FIXME: Populate this with the mapped privilege data.
|
||||
// NOTE: The assignment below needs to be updated. Replace the empty object `{}`
|
||||
// with the actual mapped data (e.g., from mappingUserPrivilege(data)).
|
||||
// Expected structure (Record<string, PrivilegeEntity>):
|
||||
// {
|
||||
// "TRANSACTION_BOOKING": {
|
||||
// ALLOW_CREATE: true,
|
||||
// ALLOW_VIEW: true,
|
||||
// // ...
|
||||
// }
|
||||
// }
|
||||
const userPrivilege: Record<string, PrivilegeEntity> = {};
|
||||
|
||||
/**
|
||||
* Store credentials in local storage
|
||||
*/
|
||||
await appStorage.setItem(AppStorageKey.USER_ID, id);
|
||||
await appDatabase.setItem(AppDatabaseKey.ACCESS_TOKEN, token);
|
||||
await appDatabase.setItem(AppDatabaseKey.USER_PROFILE, { ...userProfile, label: userProfile.role });
|
||||
await appDatabase.setItem(AppDatabaseKey.USER_PRIVILEGE, userPrivilege);
|
||||
|
||||
/**
|
||||
* Determine redirect destination
|
||||
* If the user was redirected here from a protected page, honour that URL.
|
||||
* Otherwise fall back to the default app entry point.
|
||||
*/
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const redirectTo = params.get('redirect');
|
||||
|
||||
window.location.replace(redirectTo ? decodeURIComponent(redirectTo) : '/app');
|
||||
} catch (error) {
|
||||
throw error as any;
|
||||
export async function initiateAuthSession(tokens: TokenPair, me: AuthUser): Promise<void> {
|
||||
if (!tokens.accessToken) {
|
||||
throw new Error('Login response missing access token');
|
||||
}
|
||||
|
||||
await persistTokenPair(tokens);
|
||||
await persistUserSession(me);
|
||||
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const redirectTo = params.get('redirect');
|
||||
window.location.replace(redirectTo ? decodeURIComponent(redirectTo) : '/app');
|
||||
}
|
||||
|
||||
let refreshInFlight: Promise<TokenPair> | null = null;
|
||||
|
||||
export async function refreshAuthSession(): Promise<TokenPair> {
|
||||
if (!refreshInFlight) {
|
||||
refreshInFlight = rotateRefreshToken().finally(() => {
|
||||
refreshInFlight = null;
|
||||
});
|
||||
}
|
||||
|
||||
return refreshInFlight;
|
||||
}
|
||||
|
||||
async function rotateRefreshToken(): Promise<TokenPair> {
|
||||
const refreshToken = await appDatabase.getItem<string>(AppDatabaseKey.REFRESH_TOKEN);
|
||||
if (!refreshToken) {
|
||||
throw new Error('Missing refresh token');
|
||||
}
|
||||
|
||||
const { apiClient } = await import('./api-client');
|
||||
const response = await apiClient.request<TokenPair>({
|
||||
url: API_URL.AUTH_REFRESH,
|
||||
method: 'POST',
|
||||
data: { refreshToken },
|
||||
skipAuthRefresh: true,
|
||||
});
|
||||
const tokens: TokenPair = {
|
||||
accessToken: response.data.accessToken,
|
||||
refreshToken: response.data.refreshToken,
|
||||
};
|
||||
|
||||
await persistTokenPair(tokens);
|
||||
return tokens;
|
||||
}
|
||||
|
||||
export async function logoutAuthSession(): Promise<void> {
|
||||
const refreshToken = await appDatabase.getItem<string>(AppDatabaseKey.REFRESH_TOKEN);
|
||||
|
||||
try {
|
||||
if (refreshToken) {
|
||||
const { apiClient } = await import('./api-client');
|
||||
await apiClient.request({
|
||||
url: API_URL.AUTH_REVOKE,
|
||||
method: 'POST',
|
||||
data: { refreshToken },
|
||||
skipAuthRefresh: true,
|
||||
});
|
||||
}
|
||||
} catch {
|
||||
// Always clear the local session, even if the server revoke call fails.
|
||||
}
|
||||
|
||||
await terminateAuthSession({ preserveRedirect: false });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user