99 lines
3.2 KiB
TypeScript
99 lines
3.2 KiB
TypeScript
import { defineStore } from 'pinia';
|
|
|
|
import type { RoleView, SessionView, UserView } from '@/api/auth';
|
|
import * as authApi from '@/api/auth';
|
|
import { usePermissionStore } from '@/store';
|
|
|
|
import { hasPermissionAccess } from './menu-access';
|
|
import { resolveWorkbenchRoute } from './workbench-route';
|
|
|
|
const emptyUser: UserView = {
|
|
publicId: '',
|
|
username: '',
|
|
displayName: '',
|
|
departmentName: '',
|
|
mustChangePassword: false,
|
|
};
|
|
|
|
export const useUserStore = defineStore('user', {
|
|
state: () => ({
|
|
authenticated: false,
|
|
user: { ...emptyUser },
|
|
roles: [] as RoleView[],
|
|
currentRole: null as string | null,
|
|
permissions: [] as string[],
|
|
sessionExpiresAt: null as string | null,
|
|
absoluteSessionExpiresAt: null as string | null,
|
|
loading: false,
|
|
}),
|
|
getters: {
|
|
displayName: (state) => state.user.displayName || state.user.username,
|
|
roleName: (state) => state.roles.find((role) => role.code === state.currentRole)?.name || '',
|
|
workbenchRoute: (state) => resolveWorkbenchRoute(state.currentRole, state.roles),
|
|
hasRole: (state) => (roleCode: string) => state.roles.some((role) => role.code === roleCode),
|
|
hasPermission: (state) => (permission: string) =>
|
|
hasPermissionAccess(state.currentRole, state.permissions, permission),
|
|
},
|
|
actions: {
|
|
applySession(session: SessionView) {
|
|
this.authenticated = session.authenticated;
|
|
this.user = session.user || { ...emptyUser };
|
|
this.roles = session.roles || [];
|
|
this.currentRole = session.activeRole || null;
|
|
this.permissions = session.permissions || [];
|
|
this.sessionExpiresAt = session.sessionExpiresAt || null;
|
|
this.absoluteSessionExpiresAt = session.absoluteSessionExpiresAt || null;
|
|
},
|
|
async login(payload: authApi.LoginRequest) {
|
|
this.loading = true;
|
|
try {
|
|
this.applySession(await authApi.login(payload));
|
|
} finally {
|
|
this.loading = false;
|
|
}
|
|
},
|
|
async restoreSession() {
|
|
if (this.authenticated) return this.user;
|
|
const session = await authApi.getSession();
|
|
this.applySession(session);
|
|
if (!this.authenticated) throw new Error('Session is not authenticated');
|
|
return this.user;
|
|
},
|
|
async refreshProfile() {
|
|
this.user = await authApi.getProfile();
|
|
return this.user;
|
|
},
|
|
async selectRole(roleCode: string) {
|
|
const session = await authApi.selectRole(roleCode);
|
|
this.applySession(session);
|
|
const permissionStore = usePermissionStore();
|
|
permissionStore.resetForIdentity();
|
|
permissionStore.initRoutes();
|
|
},
|
|
async updatePassword(payload: authApi.PasswordChangeRequest) {
|
|
this.applySession(await authApi.changePassword(payload));
|
|
},
|
|
async logout() {
|
|
if (this.authenticated) {
|
|
try {
|
|
await authApi.logout();
|
|
} finally {
|
|
this.clearSession();
|
|
}
|
|
} else {
|
|
this.clearSession();
|
|
}
|
|
},
|
|
clearSession() {
|
|
this.authenticated = false;
|
|
this.user = { ...emptyUser };
|
|
this.roles = [];
|
|
this.currentRole = null;
|
|
this.permissions = [];
|
|
this.sessionExpiresAt = null;
|
|
this.absoluteSessionExpiresAt = null;
|
|
},
|
|
},
|
|
persist: false,
|
|
});
|