134 lines
3.8 KiB
TypeScript
134 lines
3.8 KiB
TypeScript
import { create } from "zustand";
|
|
import type { User } from "../lib/api";
|
|
|
|
const TOKEN_KEY = "pm_token";
|
|
const USER_KEY = "pm_user";
|
|
/** نشست ERP روی همین دامنه (zustand persist) — منبع تکاحراز هویت مجموعه */
|
|
const ERP_SESSION_KEY = "procurement-auth-v1";
|
|
|
|
function readErpToken(): string | null {
|
|
try {
|
|
const raw = localStorage.getItem(ERP_SESSION_KEY);
|
|
if (!raw) return null;
|
|
const parsed = JSON.parse(raw) as { state?: { token?: string | null } };
|
|
return parsed.state?.token ?? null;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function readToken(): string | null {
|
|
try {
|
|
const legacy = localStorage.getItem(TOKEN_KEY);
|
|
if (legacy) return legacy;
|
|
// SSO — توکن Casdoorِ نشست ERP همان نشست PM است
|
|
return readErpToken();
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
interface AuthState {
|
|
token: string | null;
|
|
user: User | null;
|
|
setAuth: (token: string, user: User) => void;
|
|
/** بهروزرسانی کاربر جاری (بعد از تغییر نقش/دسترسیها یا خواندن /auth/me) */
|
|
setUser: (user: User) => void;
|
|
clear: () => void;
|
|
}
|
|
|
|
function readErpUser(): User | null {
|
|
try {
|
|
const raw = localStorage.getItem(ERP_SESSION_KEY);
|
|
if (!raw) return null;
|
|
const parsed = JSON.parse(raw) as {
|
|
state?: {
|
|
user?: {
|
|
first_name?: string;
|
|
last_name?: string;
|
|
display_name?: string;
|
|
username?: string;
|
|
casdoor_id?: string;
|
|
role?: string;
|
|
role_label?: string;
|
|
} | null;
|
|
};
|
|
};
|
|
const eu = parsed.state?.user;
|
|
if (!eu) return null;
|
|
const role: import("../lib/api").Role =
|
|
eu.role === "supervisor" ? "project_supervisor" : "project_manager";
|
|
return {
|
|
id: eu.username || eu.casdoor_id || "sso",
|
|
username: eu.username || eu.casdoor_id || "user",
|
|
display_name: eu.display_name || `${eu.first_name || ""} ${eu.last_name || ""}`.trim() || eu.username || "کاربر",
|
|
role,
|
|
role_label: eu.role_label || (role === "project_supervisor" ? "سرپرست پروژه" : "مدیر پروژه"),
|
|
permissions: [],
|
|
scope: { all_projects: role === "project_manager", project_count: null },
|
|
};
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function readUser(): User | null {
|
|
try {
|
|
const erpUser = readErpUser();
|
|
const raw = localStorage.getItem(USER_KEY);
|
|
if (raw) {
|
|
const pmUser = JSON.parse(raw) as User;
|
|
if (erpUser && (pmUser.username !== erpUser.username || pmUser.role !== erpUser.role)) {
|
|
localStorage.removeItem(USER_KEY);
|
|
return erpUser;
|
|
}
|
|
return pmUser;
|
|
}
|
|
return erpUser;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function writeUser(user: User | null): void {
|
|
try {
|
|
if (user) localStorage.setItem(USER_KEY, JSON.stringify(user));
|
|
else localStorage.removeItem(USER_KEY);
|
|
} catch {
|
|
/* حافظه در دسترس نیست */
|
|
}
|
|
}
|
|
|
|
/** وضعیت احراز هویت — توکن در localStorage نگهداری میشود */
|
|
export const useAuthStore = create<AuthState>()((set) => ({
|
|
token: readToken(),
|
|
user: readUser(),
|
|
setAuth: (token, user) => {
|
|
try {
|
|
localStorage.setItem(TOKEN_KEY, token);
|
|
} catch {
|
|
/* حافظه در دسترس نیست */
|
|
}
|
|
writeUser(user);
|
|
set({ token, user });
|
|
},
|
|
setUser: (user) => {
|
|
writeUser(user);
|
|
set({ user });
|
|
},
|
|
clear: () => {
|
|
try {
|
|
localStorage.removeItem(TOKEN_KEY);
|
|
} catch {
|
|
/* حافظه در دسترس نیست */
|
|
}
|
|
writeUser(null);
|
|
set({ token: null, user: null });
|
|
},
|
|
}));
|
|
|
|
/** آیا نشست ذخیرهشده اطلاعات نقش را دارد؟ (نشستهای پیش از RBAC ندارند) */
|
|
export function sessionNeedsRefresh(user: User | null): boolean {
|
|
return !user || !user.role || !Array.isArray(user.permissions);
|
|
}
|