@frank-auth/react
Version:
Flexible and customizable React UI components for Frank Authentication
192 lines (191 loc) • 7.5 kB
JavaScript
const s = (e) => {
try {
const t = e.split(".");
if (t.length !== 3) return null;
const n = JSON.parse(atob(t[0])), r = JSON.parse(atob(t[1])), i = t[2];
return { header: n, payload: r, signature: i };
} catch {
return null;
}
}, f = (e) => {
const t = s(e);
if (!t) return !0;
const n = Math.floor(Date.now() / 1e3);
return t.payload.exp < n;
}, p = (e) => {
const t = s(e);
return t ? new Date(t.payload.exp * 1e3) : null;
}, h = (e) => {
const t = s(e);
if (!t) return 0;
const n = Math.floor(Date.now() / 1e3);
return Math.max(0, t.payload.exp - n);
}, g = (e) => {
const t = /* @__PURE__ */ new Date(), n = new Date(e.expiresAt);
return e.isActive && n > t;
}, l = (e) => {
const t = /* @__PURE__ */ new Date(), n = new Date(e.expiresAt);
return Math.max(0, n.getTime() - t.getTime());
}, w = (e) => {
const t = l(e);
if (t === 0) return "Expired";
const n = Math.floor(t / (1e3 * 60 * 60)), r = Math.floor(t % (1e3 * 60 * 60) / (1e3 * 60));
return n > 0 ? `${n}h ${r}m` : `${r}m`;
}, d = (e) => e.fullName ? e.fullName : e.firstName && e.lastName ? `${e.firstName} ${e.lastName}` : e.firstName ? e.firstName : e.username ? e.username : e.emailAddress ? e.emailAddress : "Unknown User", y = (e) => d(e).split(" ").map((n) => n.charAt(0).toUpperCase()).slice(0, 2).join(""), A = (e) => e.emailVerified && (e.phoneNumber ? e.phoneVerified : !0), P = (e) => {
const t = [];
return e.emailVerified || t.push("email"), e.phoneNumber && !e.phoneVerified && t.push("phone"), {
isVerified: t.length === 0,
emailVerified: e.emailVerified,
phoneVerified: e.phoneVerified,
missingVerifications: t
};
}, b = (e, t) => e.organizations ? e.organizations.some((n) => n.id === t) : !1, S = (e, t) => e.organizations && e.organizations.find((r) => r.id === t)?.userRole || null, v = (e, t) => e.organizations ? e.organizations.find((r) => r.id === t)?.userPermissions || [] : [], o = (e, t, n) => e.permissions ? e.permissions.some((r) => r.permissionName !== t ? !1 : n ? r.contextType === "organization" && r.contextId === n : r.contextType === "system") : !1, a = (e, t, n) => e.roles ? e.roles.some((r) => r.roleName !== t ? !1 : n ? r.contextType === "organization" && r.contextId === n : r.contextType === "system") : !1, c = (e, t) => t.ownerId === e.id, x = (e, t) => c(e, t) || a(e, "admin", t.id) || o(e, "organization:manage", t.id), k = (e, t) => c(e, t) || a(e, "admin", t.id) || o(e, "members:invite", t.id), U = (e) => {
const t = {
passkey: 1,
oauth: 2,
email: 3,
phone: 4,
username: 5,
mfa: 6,
magic_link: 7
};
return e.sort((n, r) => t[n] - t[r]);
}, C = (e, t) => t.includes(e), M = (e) => ({
email: "Email",
phone: "Phone",
username: "Username",
oauth: "Social Login",
passkey: "Passkey",
magic_link: "Magic Link",
mfa: "Multi-Factor Authentication"
})[e] || e, N = (e) => {
const t = [];
let n = 0;
return e.length >= 8 ? n += 1 : t.push("Password must be at least 8 characters long"), /[a-z]/.test(e) ? n += 1 : t.push("Include lowercase letters"), /[A-Z]/.test(e) ? n += 1 : t.push("Include uppercase letters"), /\d/.test(e) ? n += 1 : t.push("Include numbers"), /[^A-Za-z0-9]/.test(e) ? n += 1 : t.push("Include special characters"), e.length >= 12 && (n += 1), /(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/.test(e) && (n += 1), {
score: Math.min(n, 5),
feedback: t,
isValid: n >= 4
};
}, T = (e) => ["Very Weak", "Weak", "Fair", "Good", "Strong"][Math.min(e, 4)] || "Very Weak", V = (e) => [
"password",
"123456",
"123456789",
"qwerty",
"abc123",
"password123",
"admin",
"letmein",
"welcome",
"monkey",
"1234567890",
"dragon",
"master",
"login",
"welcome123"
].includes(e.toLowerCase()), O = (e) => e.replace(/(.{4})/g, "$1-").replace(/-$/, ""), I = (e) => /^\d{6}$/.test(e), z = (e) => /^\d{4,8}$/.test(e), D = (e) => /^[A-Z0-9]{8}$/.test(e.replace(/-/g, "")), E = () => {
const e = navigator.userAgent;
let t = "unknown";
/Mobile|Android|iPhone|iPad/.test(e) ? t = /iPad/.test(e) ? "tablet" : "mobile" : /Windows|Mac|Linux/.test(e) && (t = "desktop");
let n;
e.includes("Chrome") ? n = "Chrome" : e.includes("Firefox") ? n = "Firefox" : e.includes("Safari") ? n = "Safari" : e.includes("Edge") && (n = "Edge");
let r;
return e.includes("Windows") ? r = "Windows" : e.includes("Mac") ? r = "macOS" : e.includes("Linux") ? r = "Linux" : e.includes("Android") ? r = "Android" : e.includes("iOS") && (r = "iOS"), {
deviceType: t,
browser: n,
operatingSystem: r,
userAgent: e
};
}, $ = () => !!(window.PublicKeyCredential && window.PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable && window.PublicKeyCredential.isConditionalMediationAvailable), L = async () => {
if (!window.PublicKeyCredential)
return {
supported: !1,
conditionalUI: !1,
platformAuthenticator: !1
};
const [e, t] = await Promise.all([
window.PublicKeyCredential.isConditionalMediationAvailable?.() || Promise.resolve(!1),
window.PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable?.() || Promise.resolve(!1)
]);
return {
supported: !0,
conditionalUI: e,
platformAuthenticator: t
};
}, R = (e, t) => {
const n = new URL(e);
for (const [r, i] of Object.entries(t))
i !== void 0 && n.searchParams.set(r, i);
return n.toString();
}, W = (e) => {
const t = new URL(e);
return {
code: t.searchParams.get("code") || void 0,
state: t.searchParams.get("state") || void 0,
error: t.searchParams.get("error") || void 0,
error_description: t.searchParams.get("error_description") || void 0
};
}, K = () => {
const e = new Uint8Array(32);
return crypto.getRandomValues(e), Array.from(e, (t) => t.toString(16).padStart(2, "0")).join("");
}, u = () => window.isSecureContext, j = () => {
if (!u())
throw new Error("This operation requires a secure context (HTTPS)");
}, q = (e, t) => {
try {
const n = new URL(e);
return t.some((r) => n.hostname === r || n.hostname.endsWith(`.${r}`)) ? e : null;
} catch {
return null;
}
}, m = (e, t = {}) => new CustomEvent(`frank-auth:${e}`, {
detail: {
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
...t
}
}), F = (e, t = {}) => {
const n = m(e, t);
window.dispatchEvent(n);
};
export {
R as buildRedirectUrl,
b as canUserAccessOrganization,
k as canUserInviteMembers,
x as canUserManageOrganization,
m as createAuthEvent,
s as decodeJWT,
F as dispatchAuthEvent,
O as formatBackupCode,
w as formatSessionDuration,
K as generateRandomState,
M as getAuthMethodDisplayName,
E as getDeviceInfo,
L as getPasskeySupport,
T as getPasswordStrengthLabel,
U as getRequiredAuthMethods,
l as getSessionTimeRemaining,
p as getTokenExpiration,
h as getTokenTimeToExpiry,
d as getUserDisplayName,
y as getUserInitials,
v as getUserPermissionsInOrganization,
S as getUserRoleInOrganization,
P as getUserVerificationStatus,
o as hasPermission,
a as hasRole,
C as isAuthMethodAvailable,
V as isCommonPassword,
$ as isPasskeySupported,
u as isSecureContext,
g as isSessionActive,
f as isTokenExpired,
c as isUserOrganizationOwner,
A as isUserVerified,
W as parseAuthCallback,
j as requireSecureContext,
q as sanitizeRedirectUrl,
D as validateBackupCode,
N as validatePasswordStrength,
z as validateSMSCode,
I as validateTOTPCode
};
//# sourceMappingURL=auth.js.map