Files
tehran_taj/apps/admin-panel/src/stores/auth.ts
T

115 lines
3.8 KiB
TypeScript

// Ported from legacy henza_admin/src/store/auth/moduleAuth.js
import { defineStore } from 'pinia';
import api from '../api/client';
import { iamAppUrl, tokenName, userName } from '../utils';
import { useUsersStore } from './users';
import type { UserInfo } from './users';
/**
* LEGACY BUG, recorded in docs/ADMIN-PORT-PLAN.md (#3).
*
* Legacy declared these as FUNCTIONS in Vuex state, not values:
*
* const state = {
* user: () => JSON.parse(localStorage.getItem(...)),
* token: () => localStorage.getItem(...),
* }
*
* so `store.state.auth.token` was a function object — always truthy, even when
* logged out. The router guard's `store.state.auth.token && store.state.auth.user`
* check was therefore dead code that always passed, and the real gate was the
* separate `localStorage.getItem(token)` read in beforeEach.
*
* Here they are getters that return the actual value. The observable behaviour
* is unchanged, because the real gate was — and still is — the localStorage read;
* this only removes a permanently-true condition, it does not let anyone in.
*/
export const useAuthStore = defineStore('auth', {
state: () => ({
userPermission: [] as string[],
}),
getters: {
token: (): string | null => localStorage.getItem(tokenName),
user: (): UserInfo | null => {
const raw = localStorage.getItem(userName);
if (!raw) return null;
try {
return JSON.parse(raw);
} catch {
return null;
}
},
isLoggedIn(): boolean {
return Boolean(this.token);
},
},
actions: {
/**
* Port of legacy action `login`.
*
* Legacy: POST 'admin-login', then
* dispatch('users/getRoles', data.roles.map(x => x.rid))
* delete data.roles; delete data.ut
* commit('INJECT', data)
*
* The endpoint name is translated by the mapping layer in api/endpoints.ts.
*/
async login(payload: { phone: string; password: string }) {
const { data } = await api.post('admin-login', payload);
const users = useUsersStore();
users.getRoles((data.roles ?? []).map((x: { rid: string }) => x.rid));
users.setSuperAdmin(data.is_super_admin);
// Legacy stripped these before persisting the user blob. Kept: the panel
// reads permissions from the store, never from the cached user object.
const persisted = { ...data };
delete persisted.roles;
delete persisted.ut;
this.inject(persisted);
if (data.iamBootstrapUrl) {
window.location.assign(data.iamBootstrapUrl);
}
return persisted;
},
/** Port of legacy mutation INJECT. */
inject(payload: UserInfo & { api_token: string }) {
localStorage.setItem(tokenName, payload.api_token);
// Consumed once by App.vue to show the welcome toast, then removed.
localStorage.setItem('login', 'true');
localStorage.setItem(userName, JSON.stringify(payload));
},
/**
* Not present in legacy — legacy had no logout action at all, which is why
* its module-scoped `roles` survived a session change (bug #2). Clearing
* both storage and the roles store is the fix for that.
*/
async logout(): Promise<boolean> {
let central: string | null = null;
try {
const { data } = await api.get('admin/auth/sso/logout-url', {
params: { return_url: iamAppUrl('auth/login') },
});
central = data?.logout_url ?? null;
} catch {
central = null;
}
localStorage.removeItem(tokenName);
localStorage.removeItem(userName);
localStorage.removeItem('login');
sessionStorage.removeItem('gb_admin_iam_sso_checked');
const users = useUsersStore();
users.deleteRoles();
users.deleteUserInfo();
if (central) {
window.location.assign(central);
return true;
}
return false;
},
},
});