185 lines
5.2 KiB
JavaScript
185 lines
5.2 KiB
JavaScript
import { jsx as y } from "react/jsx-runtime";
|
|
import { createContext as L, useState as K, useRef as O, useCallback as h, useEffect as k, useMemo as T, useContext as R } from "react";
|
|
import { useQuery as b } from "@tanstack/react-query";
|
|
import F from "keycloak-js";
|
|
let x = null, r = null, E = null, C = !1;
|
|
const G = L(null), _ = ({ url: e, realm: s, clientId: t }) => (r || (r = new F({
|
|
url: e,
|
|
realm: s,
|
|
clientId: t
|
|
})), r), j = (e) => (x = e, x), ee = () => C, J = () => !!(r != null && r.authenticated), Q = () => (r == null ? void 0 : r.token) ?? null, te = async (e = 30) => r ? r.updateToken(e) : !1, U = (e) => r == null ? void 0 : r.logout(e), re = (e) => r == null ? void 0 : r.login(e), W = ({ config: e, initOptions: s = {} } = {}) => {
|
|
const t = e ?? x;
|
|
if (!(t != null && t.url) || !(t != null && t.realm) || !(t != null && t.clientId))
|
|
throw new Error("Keycloak config is required.");
|
|
j(t);
|
|
const n = _(t);
|
|
return E || (E = n.init({
|
|
onLoad: "login-required",
|
|
checkLoginIframe: !1,
|
|
flow: "implicit",
|
|
...s
|
|
}).then((o) => (C = !0, o)).catch((o) => {
|
|
throw C = !0, o;
|
|
})), E;
|
|
}, se = ({
|
|
children: e,
|
|
config: s,
|
|
initOptions: t,
|
|
loading: n = null
|
|
}) => {
|
|
const [o, m] = K(!1), [p, w] = K(!1), [u, c] = K(null), l = O(!1), i = h(() => {
|
|
r && (w(!!r.authenticated), c(r.token ?? null));
|
|
}, []);
|
|
k(() => (l.current = !0, W({ config: s, initOptions: t }).then((a) => {
|
|
l.current && (w(!!a), c((r == null ? void 0 : r.token) ?? null), m(!0));
|
|
}).catch(() => {
|
|
l.current && (w(!1), c(null), m(!0));
|
|
}), () => {
|
|
l.current = !1;
|
|
}), [s, t]);
|
|
const P = h(() => r == null ? void 0 : r.login(), []), d = h((a) => r == null ? void 0 : r.logout(a), []), f = h(
|
|
async (a = 30) => {
|
|
if (!r) return !1;
|
|
const z = await r.updateToken(a);
|
|
return i(), z;
|
|
},
|
|
[i]
|
|
), S = T(
|
|
() => ({
|
|
initialized: o,
|
|
authenticated: p,
|
|
token: u,
|
|
login: P,
|
|
logout: d,
|
|
updateToken: f
|
|
}),
|
|
[o, p, u, P, d, f]
|
|
);
|
|
return o ? /* @__PURE__ */ y(G.Provider, { value: S, children: e }) : n;
|
|
}, B = L(null), v = "permissions", Y = (e) => (e == null ? void 0 : e.storageKey) || v, ne = ({
|
|
user: e = null,
|
|
children: s,
|
|
config: t,
|
|
loading: n = /* @__PURE__ */ y("div", { children: "Loading permissions..." }),
|
|
errorFallback: o = /* @__PURE__ */ y("div", { children: "Error loading permissions" })
|
|
}) => {
|
|
const m = Y(t), [p, w] = K(
|
|
() => $(m)
|
|
), { data: u, isLoading: c, error: l } = V(t), i = u ?? p;
|
|
k(() => {
|
|
u && (D(m, u), w(u));
|
|
}, [u, m]);
|
|
const P = T(
|
|
() => I(i),
|
|
[i]
|
|
), d = h(
|
|
(a = "") => M(P, a),
|
|
[P]
|
|
), f = h((a = "") => !d(a), [d]), S = T(
|
|
() => ({
|
|
user: e,
|
|
can: d,
|
|
cannot: f,
|
|
permissions: i,
|
|
isLoading: c,
|
|
error: l
|
|
}),
|
|
[e, d, f, i, c, l]
|
|
);
|
|
return l && !i ? o : c && !i ? n : /* @__PURE__ */ y(B.Provider, { value: S, children: s });
|
|
}, $ = (e = v) => {
|
|
if (!(typeof window > "u"))
|
|
try {
|
|
const s = localStorage.getItem(e);
|
|
return s ? JSON.parse(s) : void 0;
|
|
} catch {
|
|
return;
|
|
}
|
|
}, D = (e = v, s) => {
|
|
if (!(typeof window > "u"))
|
|
try {
|
|
localStorage.setItem(e, JSON.stringify(s));
|
|
} catch {
|
|
}
|
|
}, oe = (e = v) => {
|
|
if (!(typeof window > "u"))
|
|
try {
|
|
localStorage.removeItem(e);
|
|
} catch {
|
|
}
|
|
}, I = (e) => e ? new Set(e.map((s) => s.name)) : /* @__PURE__ */ new Set(), M = (e, s = "") => {
|
|
if (!s) return !1;
|
|
if (e.has(s) || [...e].some((n) => n.startsWith(s))) return !0;
|
|
let t = s;
|
|
for (; t.includes(":"); )
|
|
if (t = t.slice(0, t.lastIndexOf(":")), e.has(`${t}:*`)) return !0;
|
|
return !1;
|
|
}, q = {
|
|
all: ["permissions"],
|
|
list: (e) => [...q.all, e]
|
|
}, N = async (e) => {
|
|
if (!(e != null && e.url) || !(e != null && e.clientId))
|
|
throw new Error("Permission config requires url and clientId.");
|
|
const s = Q(), t = new URL(e.url);
|
|
t.searchParams.set("client_id", e.clientId);
|
|
const n = await fetch(t.toString(), {
|
|
method: "GET",
|
|
headers: {
|
|
...s ? { Authorization: `Bearer ${s}` } : {}
|
|
}
|
|
});
|
|
if (!n.ok)
|
|
throw new Error("Failed to load permissions");
|
|
return n.json();
|
|
}, A = () => {
|
|
const e = R(B);
|
|
if (!e)
|
|
throw new Error("usePermission must be used within PermissionProvider");
|
|
return e;
|
|
}, V = (e) => b({
|
|
queryKey: q.list(e == null ? void 0 : e.clientId),
|
|
queryFn: () => N(e),
|
|
enabled: !!(e != null && e.url) && !!(e != null && e.clientId) && J(),
|
|
staleTime: 1 / 0,
|
|
refetchOnWindowFocus: !1,
|
|
refetchOnReconnect: !1
|
|
}), ie = ({
|
|
perm: e,
|
|
children: s,
|
|
fallback: t = /* @__PURE__ */ y("div", { children: "You are not allowed to do this" })
|
|
}) => {
|
|
const { can: n } = A();
|
|
return n(e) ? s : t;
|
|
}, ae = ({ children: e }) => {
|
|
const { can: s, permissions: t } = A();
|
|
return t && s("admin") ? e : null;
|
|
}, ue = ({ children: e, forceNoAccess: s = !1 }) => {
|
|
const { can: t, isLoading: n } = A();
|
|
return k(() => {
|
|
n || (s || !t("panel_access")) && U();
|
|
}, [n, t, s]), e;
|
|
};
|
|
export {
|
|
ae as A,
|
|
ie as C,
|
|
se as K,
|
|
ne as P,
|
|
te as a,
|
|
J as b,
|
|
W as c,
|
|
ue as d,
|
|
M as e,
|
|
oe as f,
|
|
Q as g,
|
|
I as h,
|
|
ee as i,
|
|
$ as j,
|
|
N as k,
|
|
U as l,
|
|
re as m,
|
|
V as n,
|
|
q as p,
|
|
D as s,
|
|
A as u
|
|
};
|