@ollaid/native-sso 2.7.8 → 2.7.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@ var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
4
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
5
- import { createContext, forwardRef, useEffect, useContext, useRef, useState, useCallback, useMemo } from "react";
5
+ import { createContext, forwardRef, useEffect, useContext, useRef, useState, useCallback, useMemo, createElement } from "react";
6
6
  const iconProps = { width: "100%", height: "100%", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round" };
7
7
  function IconShieldCheck(props) {
8
8
  return /* @__PURE__ */ jsxs("svg", { ...iconProps, ...props, children: [
@@ -11241,7 +11241,7 @@ function SuccessOrbit() {
11241
11241
  justifyContent: "center",
11242
11242
  zIndex: 2
11243
11243
  }, children: /* @__PURE__ */ jsx(IconLink, { style: { width: "1.7rem", height: "1.7rem", color: C$1.green } }) }),
11244
- orbitIcons.map((Icon, i) => {
11244
+ orbitIcons.map((Icon2, i) => {
11245
11245
  const angle = i * 360 / orbitIcons.length;
11246
11246
  return /* @__PURE__ */ jsx("div", { style: {
11247
11247
  position: "absolute",
@@ -11260,7 +11260,7 @@ function SuccessOrbit() {
11260
11260
  display: "flex",
11261
11261
  alignItems: "center",
11262
11262
  justifyContent: "center"
11263
- }, children: /* @__PURE__ */ jsx(Icon, { style: { width: "1rem", height: "1rem", color: C$1.gray500 } }) }) }, i);
11263
+ }, children: /* @__PURE__ */ jsx(Icon2, { style: { width: "1rem", height: "1rem", color: C$1.gray500 } }) }) }, i);
11264
11264
  })
11265
11265
  ] });
11266
11266
  }
@@ -13298,7 +13298,248 @@ function OnboardingModal({
13298
13298
  renderConfirmDialog()
13299
13299
  ] });
13300
13300
  }
13301
- function DebugPanel({ saasApiUrl, iamApiUrl, onOpenLogin, onOpenSignup, onOpenOnboarding, onResetProfilePrompt }) {
13301
+ /**
13302
+ * @license lucide-react v0.462.0 - ISC
13303
+ *
13304
+ * This source code is licensed under the ISC license.
13305
+ * See the LICENSE file in the root directory of this source tree.
13306
+ */
13307
+ const toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
13308
+ const mergeClasses = (...classes) => classes.filter((className, index, array) => {
13309
+ return Boolean(className) && className.trim() !== "" && array.indexOf(className) === index;
13310
+ }).join(" ").trim();
13311
+ /**
13312
+ * @license lucide-react v0.462.0 - ISC
13313
+ *
13314
+ * This source code is licensed under the ISC license.
13315
+ * See the LICENSE file in the root directory of this source tree.
13316
+ */
13317
+ var defaultAttributes = {
13318
+ xmlns: "http://www.w3.org/2000/svg",
13319
+ width: 24,
13320
+ height: 24,
13321
+ viewBox: "0 0 24 24",
13322
+ fill: "none",
13323
+ stroke: "currentColor",
13324
+ strokeWidth: 2,
13325
+ strokeLinecap: "round",
13326
+ strokeLinejoin: "round"
13327
+ };
13328
+ /**
13329
+ * @license lucide-react v0.462.0 - ISC
13330
+ *
13331
+ * This source code is licensed under the ISC license.
13332
+ * See the LICENSE file in the root directory of this source tree.
13333
+ */
13334
+ const Icon = forwardRef(
13335
+ ({
13336
+ color = "currentColor",
13337
+ size = 24,
13338
+ strokeWidth = 2,
13339
+ absoluteStrokeWidth,
13340
+ className = "",
13341
+ children,
13342
+ iconNode,
13343
+ ...rest
13344
+ }, ref) => {
13345
+ return createElement(
13346
+ "svg",
13347
+ {
13348
+ ref,
13349
+ ...defaultAttributes,
13350
+ width: size,
13351
+ height: size,
13352
+ stroke: color,
13353
+ strokeWidth: absoluteStrokeWidth ? Number(strokeWidth) * 24 / Number(size) : strokeWidth,
13354
+ className: mergeClasses("lucide", className),
13355
+ ...rest
13356
+ },
13357
+ [
13358
+ ...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),
13359
+ ...Array.isArray(children) ? children : [children]
13360
+ ]
13361
+ );
13362
+ }
13363
+ );
13364
+ /**
13365
+ * @license lucide-react v0.462.0 - ISC
13366
+ *
13367
+ * This source code is licensed under the ISC license.
13368
+ * See the LICENSE file in the root directory of this source tree.
13369
+ */
13370
+ const createLucideIcon = (iconName, iconNode) => {
13371
+ const Component = forwardRef(
13372
+ ({ className, ...props }, ref) => createElement(Icon, {
13373
+ ref,
13374
+ iconNode,
13375
+ className: mergeClasses(`lucide-${toKebabCase(iconName)}`, className),
13376
+ ...props
13377
+ })
13378
+ );
13379
+ Component.displayName = `${iconName}`;
13380
+ return Component;
13381
+ };
13382
+ /**
13383
+ * @license lucide-react v0.462.0 - ISC
13384
+ *
13385
+ * This source code is licensed under the ISC license.
13386
+ * See the LICENSE file in the root directory of this source tree.
13387
+ */
13388
+ const ExternalLink = createLucideIcon("ExternalLink", [
13389
+ ["path", { d: "M15 3h6v6", key: "1q9fwt" }],
13390
+ ["path", { d: "M10 14 21 3", key: "gplh6r" }],
13391
+ ["path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6", key: "a6xqqp" }]
13392
+ ]);
13393
+ /**
13394
+ * @license lucide-react v0.462.0 - ISC
13395
+ *
13396
+ * This source code is licensed under the ISC license.
13397
+ * See the LICENSE file in the root directory of this source tree.
13398
+ */
13399
+ const LoaderCircle = createLucideIcon("LoaderCircle", [
13400
+ ["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]
13401
+ ]);
13402
+ /**
13403
+ * @license lucide-react v0.462.0 - ISC
13404
+ *
13405
+ * This source code is licensed under the ISC license.
13406
+ * See the LICENSE file in the root directory of this source tree.
13407
+ */
13408
+ const LockKeyhole = createLucideIcon("LockKeyhole", [
13409
+ ["circle", { cx: "12", cy: "16", r: "1", key: "1au0dj" }],
13410
+ ["rect", { x: "3", y: "10", width: "18", height: "12", rx: "2", key: "6s8ecr" }],
13411
+ ["path", { d: "M7 10V7a5 5 0 0 1 10 0v3", key: "1pqi11" }]
13412
+ ]);
13413
+ /**
13414
+ * @license lucide-react v0.462.0 - ISC
13415
+ *
13416
+ * This source code is licensed under the ISC license.
13417
+ * See the LICENSE file in the root directory of this source tree.
13418
+ */
13419
+ const ShieldCheck = createLucideIcon("ShieldCheck", [
13420
+ [
13421
+ "path",
13422
+ {
13423
+ d: "M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",
13424
+ key: "oel41y"
13425
+ }
13426
+ ],
13427
+ ["path", { d: "m9 12 2 2 4-4", key: "dzmm74" }]
13428
+ ]);
13429
+ const PasswordRedirectModal = ({ open, onOpenChange, saasApiUrl, iamApiUrl }) => {
13430
+ const [confirmOpen, setConfirmOpen] = useState(false);
13431
+ const [loading, setLoading] = useState(false);
13432
+ const [errorMessage, setErrorMessage] = useState(null);
13433
+ const apiBaseUrl = useMemo(() => {
13434
+ const source = saasApiUrl || iamApiUrl;
13435
+ if (!source) {
13436
+ return "";
13437
+ }
13438
+ const normalized = source.replace(/\/$/, "");
13439
+ return normalized.endsWith("/api") ? normalized : `${normalized}/api`;
13440
+ }, [saasApiUrl, iamApiUrl]);
13441
+ const buildUrl = (redirectUrl, magicToken) => {
13442
+ if (redirectUrl) {
13443
+ return redirectUrl;
13444
+ }
13445
+ if (magicToken) {
13446
+ const fallbackUrl = new URL("/auth/auto-connect", "https://iam.ollaid.com");
13447
+ fallbackUrl.searchParams.set("magic_token", magicToken);
13448
+ return fallbackUrl.toString();
13449
+ }
13450
+ return "";
13451
+ };
13452
+ const handleRedirect = async () => {
13453
+ if (loading) return;
13454
+ setLoading(true);
13455
+ setErrorMessage(null);
13456
+ try {
13457
+ const authToken = getAuthToken();
13458
+ const appAccessTokenRef = getNativeStorage().getItem(STORAGE.APP_ACCESS_TOKEN_REF);
13459
+ if (!authToken && !appAccessTokenRef) {
13460
+ throw new Error("Session Native SSO introuvable");
13461
+ }
13462
+ if (!apiBaseUrl) {
13463
+ throw new Error("saasApiUrl non configurée");
13464
+ }
13465
+ const result = await fetchWithTimeout(
13466
+ `${apiBaseUrl}/native/password-link`,
13467
+ {
13468
+ method: "POST",
13469
+ headers: getHeaders(authToken || void 0, true)
13470
+ },
13471
+ 2e4
13472
+ );
13473
+ if (!result.success) {
13474
+ throw new Error(result.message || "Impossible de générer le lien");
13475
+ }
13476
+ const redirectUrl = buildUrl(
13477
+ typeof result.redirect_url === "string" && result.redirect_url.length > 0 ? result.redirect_url : typeof result.sso_url === "string" && result.sso_url.length > 0 ? result.sso_url : "",
13478
+ result.magic_token
13479
+ );
13480
+ if (!redirectUrl) {
13481
+ throw new Error("URL de redirection manquante");
13482
+ }
13483
+ window.open(redirectUrl, "_blank", "noopener,noreferrer");
13484
+ onOpenChange(false);
13485
+ setConfirmOpen(false);
13486
+ } catch (error) {
13487
+ const message = error instanceof ApiError ? error.message : (error == null ? void 0 : error.message) || "Impossible de lancer le flux de mot de passe";
13488
+ setErrorMessage(message);
13489
+ } finally {
13490
+ setLoading(false);
13491
+ }
13492
+ };
13493
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
13494
+ /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(DialogContent, { style: { maxWidth: "28rem", borderRadius: "16px", background: "#fff" }, children: [
13495
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
13496
+ /* @__PURE__ */ jsx("div", { style: { margin: "0 auto 12px", width: 56, height: 56, borderRadius: "50%", background: "rgba(232, 67, 10, 0.1)", display: "flex", alignItems: "center", justifyContent: "center", color: "#e8430a" }, children: /* @__PURE__ */ jsx(LockKeyhole, { size: 28 }) }),
13497
+ /* @__PURE__ */ jsx(DialogTitle, { style: { textAlign: "center" }, children: "Mot de passe géré par OLLAID SSO" }),
13498
+ /* @__PURE__ */ jsx(DialogDescription, { style: { textAlign: "center" }, children: "Ce bouton sert à tester la redirection vers IAM et l'ouverture du modal de changement de mot de passe." })
13499
+ ] }),
13500
+ /* @__PURE__ */ jsxs("div", { style: { border: "1px solid #e5e7eb", borderRadius: 12, padding: 16, background: "#f8fafc", color: "#475569", fontSize: 13, display: "grid", gap: 8 }, children: [
13501
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 8, alignItems: "flex-start" }, children: [
13502
+ /* @__PURE__ */ jsx(ShieldCheck, { size: 16, color: "#e8430a" }),
13503
+ /* @__PURE__ */ jsx("span", { children: "Le SaaS agit comme relais. Le backend SaaS appelle IAM côté serveur, puis renvoie l'URL de redirection." })
13504
+ ] }),
13505
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: 8, alignItems: "flex-start" }, children: [
13506
+ /* @__PURE__ */ jsx(ExternalLink, { size: 16, color: "#e8430a" }),
13507
+ /* @__PURE__ */ jsx("span", { children: "Une fenêtre IAM va s'ouvrir avec auto-connexion temporaire, sans appel direct du navigateur vers IAM." })
13508
+ ] })
13509
+ ] }),
13510
+ /* @__PURE__ */ jsxs(DialogFooter, { style: { gap: 12 }, children: [
13511
+ /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: () => onOpenChange(false), style: { flex: 1 }, disabled: loading, children: "Fermer" }),
13512
+ /* @__PURE__ */ jsx(Button, { onClick: () => setConfirmOpen(true), disabled: loading, style: { flex: 1 }, children: loading ? /* @__PURE__ */ jsxs(Fragment, { children: [
13513
+ /* @__PURE__ */ jsx(LoaderCircle, { size: 16, style: { marginRight: 8, animation: "spin 1s linear infinite" } }),
13514
+ "Préparation..."
13515
+ ] }) : "Changer mon mot de passe" })
13516
+ ] })
13517
+ ] }) }),
13518
+ /* @__PURE__ */ jsx(Dialog, { open: confirmOpen, onOpenChange: (nextOpen) => {
13519
+ if (!loading) {
13520
+ setConfirmOpen(nextOpen);
13521
+ }
13522
+ }, children: /* @__PURE__ */ jsxs(DialogContent, { style: { maxWidth: "26rem", borderRadius: "16px", background: "#fff" }, children: [
13523
+ /* @__PURE__ */ jsxs(DialogHeader, { children: [
13524
+ /* @__PURE__ */ jsx(DialogTitle, { children: "Êtes-vous sûr de rediriger vers le SSO ?" }),
13525
+ /* @__PURE__ */ jsx(DialogDescription, { children: "Cette action ouvre IAM dans un nouvel onglet et prépare l'auto-connexion pour tester le changement de mot de passe." })
13526
+ ] }),
13527
+ errorMessage && /* @__PURE__ */ jsx("div", { style: { border: "1px solid #fecaca", background: "#fef2f2", color: "#b91c1c", borderRadius: 12, padding: 12, fontSize: 13 }, children: errorMessage }),
13528
+ loading && /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 10, padding: "8px 0 4px" }, children: [
13529
+ /* @__PURE__ */ jsx(LoaderCircle, { size: 26, style: { animation: "spin 1s linear infinite", color: "#e8430a" } }),
13530
+ /* @__PURE__ */ jsx("div", { style: { fontSize: 13, color: "#475569", textAlign: "center" }, children: "Création de la session en cours..." })
13531
+ ] }),
13532
+ /* @__PURE__ */ jsxs(DialogFooter, { style: { gap: 12 }, children: [
13533
+ /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: () => setConfirmOpen(false), style: { flex: 1 }, disabled: loading, children: "Annuler" }),
13534
+ /* @__PURE__ */ jsx(Button, { onClick: handleRedirect, style: { flex: 1 }, disabled: loading, children: loading ? /* @__PURE__ */ jsxs(Fragment, { children: [
13535
+ /* @__PURE__ */ jsx(LoaderCircle, { size: 16, style: { marginRight: 8, animation: "spin 1s linear infinite" } }),
13536
+ "Confirmer..."
13537
+ ] }) : "Confirmer" })
13538
+ ] })
13539
+ ] }) })
13540
+ ] });
13541
+ };
13542
+ function DebugPanel({ saasApiUrl, iamApiUrl, onOpenLogin, onOpenSignup, onOpenOnboarding, onOpenPassword, onResetProfilePrompt }) {
13302
13543
  const [logs, setLogs] = useState([]);
13303
13544
  const [expanded, setExpanded] = useState(true);
13304
13545
  const [selectedLog, setSelectedLog] = useState(null);
@@ -13438,6 +13679,18 @@ function DebugPanel({ saasApiUrl, iamApiUrl, onOpenLogin, onOpenSignup, onOpenOn
13438
13679
  children: "Infos profile"
13439
13680
  }
13440
13681
  ),
13682
+ /* @__PURE__ */ jsx(
13683
+ "button",
13684
+ {
13685
+ onClick: (e) => {
13686
+ e.stopPropagation();
13687
+ onOpenPassword == null ? void 0 : onOpenPassword();
13688
+ },
13689
+ disabled: !onOpenPassword,
13690
+ style: { background: "#334155", color: "#e2e8f0", border: "none", borderRadius: "4px", padding: "2px 8px", cursor: onOpenPassword ? "pointer" : "not-allowed", fontSize: "11px", opacity: onOpenPassword ? 1 : 0.5 },
13691
+ children: "Mot de passe"
13692
+ }
13693
+ ),
13441
13694
  /* @__PURE__ */ jsx(
13442
13695
  "button",
13443
13696
  {
@@ -13631,6 +13884,7 @@ function NativeSSOPage({
13631
13884
  const [showOnboarding, setShowOnboarding] = useState(false);
13632
13885
  const [pendingSession, setPendingSession] = useState(null);
13633
13886
  const [debugOnboardingState, setDebugOnboardingState] = useState(null);
13887
+ const [passwordRedirectOpen, setPasswordRedirectOpen] = useState(false);
13634
13888
  const [redirectingTarget, setRedirectingTarget] = useState(null);
13635
13889
  const [redirectingReason, setRedirectingReason] = useState(null);
13636
13890
  const [session, setSession] = useState(() => {
@@ -14003,6 +14257,9 @@ function NativeSSOPage({
14003
14257
  setShowOnboarding(true);
14004
14258
  }
14005
14259
  }, [session, clearOnboardingTimers]);
14260
+ const openDebugPassword = useCallback(() => {
14261
+ setPasswordRedirectOpen(true);
14262
+ }, []);
14006
14263
  useEffect(() => {
14007
14264
  syncProfilePrompt(session);
14008
14265
  return () => {
@@ -14150,8 +14407,18 @@ function NativeSSOPage({
14150
14407
  onOpenLogin: openDebugLogin,
14151
14408
  onOpenSignup: openDebugSignup,
14152
14409
  onOpenOnboarding: openDebugOnboarding,
14410
+ onOpenPassword: openDebugPassword,
14153
14411
  onResetProfilePrompt: resetDebugProfilePrompt
14154
14412
  }
14413
+ ),
14414
+ /* @__PURE__ */ jsx(
14415
+ PasswordRedirectModal,
14416
+ {
14417
+ open: passwordRedirectOpen,
14418
+ onOpenChange: setPasswordRedirectOpen,
14419
+ saasApiUrl,
14420
+ iamApiUrl
14421
+ }
14155
14422
  )
14156
14423
  ] });
14157
14424
  }
@@ -14231,8 +14498,18 @@ function NativeSSOPage({
14231
14498
  onOpenLogin: openDebugLogin,
14232
14499
  onOpenSignup: openDebugSignup,
14233
14500
  onOpenOnboarding: openDebugOnboarding,
14501
+ onOpenPassword: openDebugPassword,
14234
14502
  onResetProfilePrompt: resetDebugProfilePrompt
14235
14503
  }
14504
+ ),
14505
+ /* @__PURE__ */ jsx(
14506
+ PasswordRedirectModal,
14507
+ {
14508
+ open: passwordRedirectOpen,
14509
+ onOpenChange: setPasswordRedirectOpen,
14510
+ saasApiUrl,
14511
+ iamApiUrl
14512
+ }
14236
14513
  )
14237
14514
  ] });
14238
14515
  }