role filter and login issue

This commit is contained in:
momorew
2026-09-09 19:20:19 +05:30
parent 862d5cb447
commit 34448b12ae
6 changed files with 62 additions and 67 deletions
+2 -1
View File
@@ -16,7 +16,8 @@ export const rolesApi = {
getById: (roleId: string) =>
apiClient.get<RoleWithAccesses>(`/api/role/get/${roleId}`),
getAccesses: () => apiClient.get<RoleAccess[]>("/api/access/get"),
getAccesses: (tenantId?: string) =>
apiClient.get<RoleAccess[]>(`/api/access/get${tenantId ? `?tenant_id=${encodeURIComponent(tenantId)}` : ""}`),
create: (payload: RoleCreateRequest) =>
apiClient.post<Role>("/api/role/create", payload, { successMessage: "Role created successfully", errorMessage: "Failed to create role" }),
+44 -28
View File
@@ -40,12 +40,17 @@ const AddRoles = () => {
}
let isMounted = true;
const loadAccesses = async () => {
const loadAccesses = async (tenantId?: string) => {
setIsAccessLoading(true);
try {
const data = await rolesApi.getAccesses();
const data = await rolesApi.getAccesses(tenantId || undefined);
if (isMounted) {
setAccessOptions(data);
const validIds = new Set(data.map((d) => d.id));
setFormData((prev) => ({
...prev,
access_ids: (prev.access_ids || []).filter((id) => validIds.has(id)),
}));
}
} catch (error) {
if (isMounted) {
@@ -128,44 +133,55 @@ const AddRoles = () => {
}
};
loadAccesses();
loadTenants();
return () => {
isMounted = false;
};
}, [canReadAllTenants, isAuthLoading, user?.tenant_id, user?.tenant_name]);
useEffect(() => {
if (isAuthLoading) return;
let isMounted = true;
const loadAccesses = async () => {
setIsAccessLoading(true);
try {
const data = await rolesApi.getAccesses(formData.tenant_id || undefined);
if (isMounted) {
setAccessOptions(data);
const validIds = new Set(data.map((d) => d.id));
setFormData((prev) => ({
...prev,
access_ids: (prev.access_ids || []).filter((id) => validIds.has(id)),
}));
}
} catch (error) {
if (isMounted) {
const message =
error instanceof Error
? error.message
: "Unable to load access options.";
setErrorMessage(message);
}
} finally {
if (isMounted) {
setIsAccessLoading(false);
}
}
};
loadAccesses();
return () => {
isMounted = false;
};
}, [formData.tenant_id, isAuthLoading]);
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = event.target;
setFormData((prev) => ({ ...prev, [name]: value }));
};
const availableAccessOptions = useMemo(() => {
if (canReadAllTenants) return accessOptions;
if (!user?.role?.accesses) return [];
const accessMap = new Map(accessOptions.map((a) => [a.id, a]));
const includedIds = new Set<string>();
accessOptions.forEach((option) => {
if (user.role?.accesses.includes(option.access_code)) {
let current: RoleAccess | undefined = option;
while (current) {
if (includedIds.has(current.id)) break;
includedIds.add(current.id);
if (current.parent_id) {
current = accessMap.get(current.parent_id);
} else {
current = undefined;
}
}
}
});
return accessOptions.filter((option) => includedIds.has(option.id));
}, [accessOptions, user, canReadAllTenants]);
return accessOptions;
}, [accessOptions]);
const handleSubmit = async (event: React.FormEvent) => {
event.preventDefault();
+7 -26
View File
@@ -94,31 +94,8 @@ const AllRoles = () => {
const [isDeleting, setIsDeleting] = useState(false);
const availableAccessOptions = useMemo(() => {
if (canReadAllTenants) return accessOptions;
if (!currentUser?.role?.accesses) return [];
const accessMap = new Map(accessOptions.map((a) => [a.id, a]));
const includedIds = new Set<string>();
accessOptions.forEach((option) => {
if (currentUser.role?.accesses.includes(option.access_code)) {
let current: RoleAccess | undefined = option;
while (current) {
if (includedIds.has(current.id)) break;
includedIds.add(current.id);
if (current.parent_id) {
current = accessMap.get(current.parent_id);
} else {
current = undefined;
}
}
}
});
return accessOptions.filter((option) => includedIds.has(option.id));
}, [accessOptions, currentUser, canReadAllTenants]);
return accessOptions;
}, [accessOptions]);
useEffect(() => {
let isMounted = true;
@@ -267,7 +244,11 @@ const AllRoles = () => {
setEditError("");
setIsEditOpen(true);
try {
const details = await rolesApi.getById(role.id);
const [details, tenantAccesses] = await Promise.all([
rolesApi.getById(role.id),
rolesApi.getAccesses(role.tenant_id || undefined),
]);
setAccessOptions(tenantAccesses);
setEditAccessIds(details.accesses?.map((a) => a.id) || []);
} catch (err) {
setEditError(err instanceof Error ? err.message : t('messages.error'));
+1 -6
View File
@@ -33,15 +33,10 @@ export const AuthProvider: React.FC<{ children: ReactNode }> = ({
useEffect(() => {
const bootstrapAuth = async () => {
const token = getAccessToken();
if (!token) {
setIsLoading(false);
return;
}
try {
const userData = await authApi.me();
setUser(userData);
setAuthCookies(null, true);
const preferred = userData.preferred_language;
if (preferred) {
+2
View File
@@ -17,11 +17,13 @@ const API_TOAST_OPTIONS = { autoClose: 2000 };
const hardLogout = () => {
clearAuthCookies();
if (typeof window !== "undefined" && !window.location.pathname.startsWith("/signin")) {
toast.error(
"Your session has expired. Please sign in again.",
API_TOAST_OPTIONS
);
window.location.href = "/signin";
}
};
const refreshAccessToken = async () => {
+1 -1
View File
@@ -1,5 +1,5 @@
const LOGGED_IN_KEY = "logged_in";
const LOGGED_IN_MAX_AGE_SECONDS = 60 * 15;
const LOGGED_IN_MAX_AGE_SECONDS = 60 * 60 * 24 * 30;
const buildCookieOptions = (maxAgeSeconds?: number) => {
const options = ["path=/", "samesite=lax"];