@infuro/cms-core 1.0.47 → 1.0.50

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.
Files changed (34) hide show
  1. package/README.md +30 -16
  2. package/dist/admin.cjs +1172 -38
  3. package/dist/admin.js +1173 -39
  4. package/dist/api.cjs +37 -37
  5. package/dist/api.js +5 -5
  6. package/dist/auth.cjs +52 -23
  7. package/dist/auth.d.cts +101 -2
  8. package/dist/auth.d.ts +101 -2
  9. package/dist/auth.js +3 -2
  10. package/dist/chunk-3EOM4V2M.cjs +452 -0
  11. package/dist/{chunk-2HU5R2JE.js → chunk-AYERBA7I.js} +1 -7
  12. package/dist/{chunk-YXH2UUEZ.js → chunk-IPDHT2UV.js} +257 -16
  13. package/dist/{chunk-XUCKZPML.cjs → chunk-JCMOOPNX.cjs} +2696 -2601
  14. package/dist/{chunk-W42UZLQO.js → chunk-LT2WOPKA.js} +2642 -2540
  15. package/dist/chunk-RK5ETF2I.js +434 -0
  16. package/dist/{chunk-4PMK3RNA.cjs → chunk-TJ2MIQUT.cjs} +1 -7
  17. package/dist/{chunk-LMJ7RKPF.cjs → chunk-UUWAUHUW.cjs} +279 -16
  18. package/dist/{chunk-YC4NUZCS.js → chunk-WRKV6MHB.js} +414 -2
  19. package/dist/{chunk-Q3HQEM4R.cjs → chunk-YV5PK4JW.cjs} +421 -1
  20. package/dist/cli.cjs +13 -22
  21. package/dist/cli.js +13 -22
  22. package/dist/{event-order-defaults-7Z3UZOEH.cjs → event-order-defaults-DU7V3YND.cjs} +9 -9
  23. package/dist/{event-order-defaults-XQ3IDPD7.js → event-order-defaults-H4RT7NMR.js} +1 -1
  24. package/dist/index.cjs +327 -291
  25. package/dist/index.d.cts +132 -5
  26. package/dist/index.d.ts +132 -5
  27. package/dist/index.js +8 -8
  28. package/dist/migrations/1782400000000-CreateUserDeviceTokens.ts +36 -0
  29. package/dist/migrations/1782500000000-AddPushToOrderNotificationBindingsChannelEnum.ts +15 -0
  30. package/dist/{order-notification-dispatcher-6WNG24NY.js → order-notification-dispatcher-3TA4ETYJ.js} +1 -1
  31. package/dist/{order-notification-dispatcher-6XSU3AR7.cjs → order-notification-dispatcher-ZEAZ5SHV.cjs} +7 -3
  32. package/package.json +1 -1
  33. package/dist/chunk-VUQFARRT.cjs +0 -182
  34. package/dist/chunk-ZF2RQWXB.js +0 -171
@@ -1,7 +1,10 @@
1
+ import { linkUnclaimedContactToUser, ensureCustomerForUser } from './chunk-RK5ETF2I.js';
2
+ import { retireSoftDeletedUniqueValue } from './chunk-DBPSJYLZ.js';
1
3
  import { getPermissionableEntityKeys, ADMIN_GROUP_NAME, isSuperAdmin, permissionRowsToRecord, vendorPortalFlagsFromUser } from './chunk-JIWUVQ6B.js';
2
4
  import { __name } from './chunk-SHUYVCID.js';
3
5
  import { getToken } from 'next-auth/jwt';
4
6
  import _CredentialsProvider from 'next-auth/providers/credentials';
7
+ import _GoogleProvider from 'next-auth/providers/google';
5
8
 
6
9
  // src/auth/seed-permissions.ts
7
10
  async function seedAdministratorPermissions(dataSource, entityMap) {
@@ -129,6 +132,10 @@ var defaultPublicApiMethods = {
129
132
  "/api/users/invite": [
130
133
  "GET",
131
134
  "POST"
135
+ ],
136
+ /** Public keys only (e.g. googleEnabled); secrets stay private in the settings handler. */
137
+ "/api/settings/auth_providers": [
138
+ "GET"
132
139
  ]
133
140
  };
134
141
  function legacyGetSessionToken(request) {
@@ -234,7 +241,281 @@ function createCmsMiddleware(config = {}) {
234
241
  }, "cmsMiddleware");
235
242
  }
236
243
  __name(createCmsMiddleware, "createCmsMiddleware");
244
+
245
+ // src/auth/auth-providers-settings.ts
246
+ var AUTH_PROVIDERS_SETTINGS_GROUP = "auth_providers";
247
+ function parseEnabled(raw) {
248
+ if (typeof raw === "boolean") return raw;
249
+ if (typeof raw === "number") return raw !== 0;
250
+ if (typeof raw === "string") {
251
+ const n = raw.trim().toLowerCase();
252
+ return n === "true" || n === "1" || n === "yes" || n === "on";
253
+ }
254
+ return false;
255
+ }
256
+ __name(parseEnabled, "parseEnabled");
257
+ function resolveSettingsEncryptionKey() {
258
+ if (typeof process === "undefined") return void 0;
259
+ return process.env.SETTINGS_ENCRYPTION_KEY?.trim() || process.env.NEXTAUTH_SECRET?.trim() || void 0;
260
+ }
261
+ __name(resolveSettingsEncryptionKey, "resolveSettingsEncryptionKey");
262
+ function decryptSettingValue(encoded, key) {
263
+ const buf = Buffer.from(encoded, "base64");
264
+ const keyBuf = Buffer.from(key.padEnd(32, "0").slice(0, 32), "utf8");
265
+ const out = Buffer.alloc(buf.length);
266
+ for (let i = 0; i < buf.length; i++) out[i] = buf[i] ^ keyBuf[i % keyBuf.length];
267
+ return out.toString("utf8");
268
+ }
269
+ __name(decryptSettingValue, "decryptSettingValue");
270
+ async function loadAuthProvidersSettingsFromDb(dataSource, entityMap, encryptionKey) {
271
+ if (!entityMap.configs) return {};
272
+ const key = encryptionKey ?? resolveSettingsEncryptionKey();
273
+ const rows = await dataSource.getRepository(entityMap.configs).find({
274
+ where: {
275
+ settings: AUTH_PROVIDERS_SETTINGS_GROUP,
276
+ deleted: false
277
+ }
278
+ });
279
+ const out = {};
280
+ for (const row of rows) {
281
+ let val = row.value;
282
+ if (row.encrypted && key) {
283
+ try {
284
+ val = decryptSettingValue(val, key);
285
+ } catch {
286
+ }
287
+ }
288
+ out[row.key] = val;
289
+ }
290
+ return out;
291
+ }
292
+ __name(loadAuthProvidersSettingsFromDb, "loadAuthProvidersSettingsFromDb");
293
+ function fromSettingsMap(map) {
294
+ const clientId = String(map.googleClientId ?? map.GOOGLE_CLIENT_ID ?? "").trim();
295
+ const clientSecret = String(map.googleClientSecret ?? map.GOOGLE_CLIENT_SECRET ?? "").trim();
296
+ const enabledFlag = map.googleEnabled !== void 0 && map.googleEnabled !== "" ? parseEnabled(map.googleEnabled) : parseEnabled(map.enabled);
297
+ if (!enabledFlag || !clientId || !clientSecret) return null;
298
+ return {
299
+ enabled: true,
300
+ clientId,
301
+ clientSecret
302
+ };
303
+ }
304
+ __name(fromSettingsMap, "fromSettingsMap");
305
+ function fromEnv() {
306
+ const env = typeof process !== "undefined" ? process.env : void 0;
307
+ if (!env) return null;
308
+ const clientId = String(env.GOOGLE_CLIENT_ID ?? "").trim();
309
+ const clientSecret = String(env.GOOGLE_CLIENT_SECRET ?? "").trim();
310
+ const enabledRaw = env.GOOGLE_AUTH_ENABLED;
311
+ const enabled = enabledRaw === void 0 || enabledRaw === "" ? Boolean(clientId && clientSecret) : parseEnabled(enabledRaw);
312
+ if (!enabled || !clientId || !clientSecret) return null;
313
+ return {
314
+ enabled: true,
315
+ clientId,
316
+ clientSecret
317
+ };
318
+ }
319
+ __name(fromEnv, "fromEnv");
320
+ async function resolveGoogleAuthConfig(input = {}) {
321
+ if (input.settings) {
322
+ const fromExplicit = fromSettingsMap(input.settings);
323
+ if (fromExplicit?.enabled) {
324
+ logAuth("resolveGoogleAuthConfig: from explicit settings", {
325
+ enabled: true
326
+ });
327
+ return fromExplicit;
328
+ }
329
+ }
330
+ if (input.dataSource && input.entityMap?.configs) {
331
+ try {
332
+ const map = await loadAuthProvidersSettingsFromDb(input.dataSource, input.entityMap, input.encryptionKey);
333
+ const fromDb = fromSettingsMap(map);
334
+ if (fromDb?.enabled) {
335
+ logAuth("resolveGoogleAuthConfig: from DB settings", {
336
+ enabled: true
337
+ });
338
+ return fromDb;
339
+ }
340
+ if (map.googleEnabled !== void 0 || map.googleClientId !== void 0) {
341
+ logAuth("resolveGoogleAuthConfig: DB present but incomplete/disabled", {
342
+ googleEnabled: map.googleEnabled ?? null,
343
+ hasClientId: Boolean(String(map.googleClientId ?? "").trim()),
344
+ hasClientSecret: Boolean(String(map.googleClientSecret ?? "").trim())
345
+ });
346
+ }
347
+ } catch (err) {
348
+ logAuth("resolveGoogleAuthConfig: DB load failed", {
349
+ message: err instanceof Error ? err.message : String(err)
350
+ });
351
+ }
352
+ }
353
+ if (!input.skipEnvFallback) {
354
+ const envCfg = fromEnv();
355
+ if (envCfg) {
356
+ logAuth("resolveGoogleAuthConfig: from env", {
357
+ enabled: true
358
+ });
359
+ return envCfg;
360
+ }
361
+ }
362
+ return null;
363
+ }
364
+ __name(resolveGoogleAuthConfig, "resolveGoogleAuthConfig");
365
+ function googleOAuthRedirectUri(baseUrl) {
366
+ const base = (baseUrl ?? process.env.NEXTAUTH_URL ?? "").replace(/\/$/, "");
367
+ return base ? `${base}/api/auth/callback/google` : "/api/auth/callback/google";
368
+ }
369
+ __name(googleOAuthRedirectUri, "googleOAuthRedirectUri");
370
+ function isGoogleAuthPubliclyEnabled(settings) {
371
+ if (!settings) return false;
372
+ if (settings.googleEnabled !== void 0 && settings.googleEnabled !== "") {
373
+ return parseEnabled(settings.googleEnabled);
374
+ }
375
+ return parseEnabled(settings.enabled);
376
+ }
377
+ __name(isGoogleAuthPubliclyEnabled, "isGoogleAuthPubliclyEnabled");
378
+
379
+ // src/auth/create-google-customer.ts
380
+ function normalizeEmail(email) {
381
+ return email.trim().toLowerCase();
382
+ }
383
+ __name(normalizeEmail, "normalizeEmail");
384
+ async function createCustomerUserFromGoogleOAuth(input) {
385
+ const email = normalizeEmail(input.email);
386
+ if (!email || !input.entityMap.users || !input.entityMap.user_groups) {
387
+ logAuth("createCustomerUserFromGoogleOAuth skipped", {
388
+ reason: "missing_email_or_entities",
389
+ hasUsers: Boolean(input.entityMap.users),
390
+ hasGroups: Boolean(input.entityMap.user_groups)
391
+ });
392
+ return null;
393
+ }
394
+ const userRepo = input.dataSource.getRepository(input.entityMap.users);
395
+ const groupRepo = input.dataSource.getRepository(input.entityMap.user_groups);
396
+ try {
397
+ await retireSoftDeletedUniqueValue(userRepo, "email", email);
398
+ } catch {
399
+ }
400
+ const existing = await userRepo.findOne({
401
+ where: {
402
+ email,
403
+ deleted: false
404
+ },
405
+ relations: [
406
+ "group",
407
+ "group.permissions"
408
+ ]
409
+ });
410
+ if (existing) {
411
+ return existing;
412
+ }
413
+ const customerG = await groupRepo.findOne({
414
+ where: {
415
+ name: "Customer",
416
+ deleted: false
417
+ }
418
+ });
419
+ const groupId = customerG ? Number(customerG.id) : null;
420
+ if (!Number.isFinite(groupId) || groupId == null) {
421
+ logAuth("createCustomerUserFromGoogleOAuth failed", {
422
+ reason: "customer_group_missing",
423
+ email
424
+ });
425
+ return null;
426
+ }
427
+ const displayName = typeof input.name === "string" && input.name.trim() || email.split("@")[0] || "Customer";
428
+ try {
429
+ const created = await userRepo.save(userRepo.create({
430
+ name: displayName,
431
+ email,
432
+ password: null,
433
+ blocked: false,
434
+ adminAccess: false,
435
+ groupId,
436
+ inviteStatus: "active",
437
+ inviteToken: null,
438
+ emailVerifiedAt: /* @__PURE__ */ new Date()
439
+ }));
440
+ const userId = Number(created.id);
441
+ if (!Number.isFinite(userId)) {
442
+ logAuth("createCustomerUserFromGoogleOAuth failed", {
443
+ reason: "invalid_id",
444
+ email
445
+ });
446
+ return null;
447
+ }
448
+ if (input.entityMap.contacts) {
449
+ try {
450
+ await linkUnclaimedContactToUser(input.dataSource, input.entityMap.contacts, userId, email);
451
+ } catch {
452
+ }
453
+ }
454
+ if (input.entityMap.customer) {
455
+ try {
456
+ await ensureCustomerForUser(input.dataSource, input.entityMap.customer, {
457
+ id: userId,
458
+ name: displayName,
459
+ email,
460
+ phone: null
461
+ }, {
462
+ phone: null
463
+ });
464
+ } catch {
465
+ }
466
+ }
467
+ const loaded = await userRepo.findOne({
468
+ where: {
469
+ id: userId
470
+ },
471
+ relations: [
472
+ "group",
473
+ "group.permissions"
474
+ ]
475
+ });
476
+ if (!loaded) {
477
+ logAuth("createCustomerUserFromGoogleOAuth failed", {
478
+ reason: "reload_failed",
479
+ email,
480
+ userId
481
+ });
482
+ return null;
483
+ }
484
+ logAuth("createCustomerUserFromGoogleOAuth ok", {
485
+ email,
486
+ userId
487
+ });
488
+ return loaded;
489
+ } catch (err) {
490
+ const raced = await userRepo.findOne({
491
+ where: {
492
+ email,
493
+ deleted: false
494
+ },
495
+ relations: [
496
+ "group",
497
+ "group.permissions"
498
+ ]
499
+ });
500
+ if (raced) {
501
+ logAuth("createCustomerUserFromGoogleOAuth raced_to_existing", {
502
+ email,
503
+ userId: raced.id
504
+ });
505
+ return raced;
506
+ }
507
+ logAuth("createCustomerUserFromGoogleOAuth error", {
508
+ email,
509
+ message: err instanceof Error ? err.message : String(err)
510
+ });
511
+ return null;
512
+ }
513
+ }
514
+ __name(createCustomerUserFromGoogleOAuth, "createCustomerUserFromGoogleOAuth");
515
+
516
+ // src/auth/nextauth-options.ts
237
517
  var CredentialsProvider = _CredentialsProvider.default ?? _CredentialsProvider;
518
+ var GoogleProvider = _GoogleProvider.default ?? _GoogleProvider;
238
519
  function parseBooleanSetting(value) {
239
520
  if (typeof value === "boolean") return value;
240
521
  if (typeof value === "number") return value !== 0;
@@ -356,8 +637,12 @@ function permitsCustomerLogin(allowCustomerLogin, credentials) {
356
637
  return !callbackUrlTargetsAdmin(callbackUrl);
357
638
  }
358
639
  __name(permitsCustomerLogin, "permitsCustomerLogin");
640
+ function applySessionUserToAuthUser(target, sessionUser) {
641
+ Object.assign(target, sessionUser);
642
+ }
643
+ __name(applySessionUserToAuthUser, "applySessionUserToAuthUser");
359
644
  function getNextAuthOptions(config) {
360
- const { getUserByEmail, comparePassword, signInPage = "/admin/signin", secret, extend, enablePasswordLogin = true, enableOtpLogin = false, authorizeOtp, allowCustomerLogin } = config;
645
+ const { getUserByEmail, comparePassword, signInPage = "/admin/signin", secret, extend, enablePasswordLogin = true, enableOtpLogin = false, authorizeOtp, allowCustomerLogin, google, createCustomerUserFromGoogle } = config;
361
646
  logAuth("getNextAuthOptions init", nextAuthCookieDebugInfo());
362
647
  const providers = [];
363
648
  if (enablePasswordLogin) {
@@ -513,6 +798,14 @@ function getNextAuthOptions(config) {
513
798
  }
514
799
  }));
515
800
  }
801
+ if (google?.enabled && google.clientId && google.clientSecret) {
802
+ providers.push(GoogleProvider({
803
+ clientId: google.clientId,
804
+ clientSecret: google.clientSecret,
805
+ allowDangerousEmailAccountLinking: true
806
+ }));
807
+ logAuth("getNextAuthOptions: GoogleProvider registered");
808
+ }
516
809
  const options = {
517
810
  secret: secret ?? process.env.NEXTAUTH_SECRET,
518
811
  providers,
@@ -534,6 +827,94 @@ function getNextAuthOptions(config) {
534
827
  }
535
828
  },
536
829
  callbacks: {
830
+ async signIn({ user, account, profile }) {
831
+ if (account?.provider !== "google") return true;
832
+ const emailRaw = typeof user?.email === "string" && user.email || (profile && typeof profile.email === "string" ? profile.email : "");
833
+ const email = emailRaw.trim().toLowerCase();
834
+ if (!email) {
835
+ logAuth("signIn(google) rejected", {
836
+ reason: "missing_email"
837
+ });
838
+ return false;
839
+ }
840
+ try {
841
+ let dbUser = await getUserByEmail(email);
842
+ if (!dbUser && allowCustomerLogin === true && createCustomerUserFromGoogle) {
843
+ const profileName = typeof user?.name === "string" && user.name || (profile && typeof profile.name === "string" ? profile.name : null);
844
+ dbUser = await createCustomerUserFromGoogle({
845
+ email,
846
+ name: profileName
847
+ });
848
+ if (dbUser) {
849
+ logAuth("signIn(google) created customer", {
850
+ email,
851
+ userId: dbUser.id
852
+ });
853
+ }
854
+ }
855
+ if (!dbUser) {
856
+ logAuth("signIn(google) rejected", {
857
+ reason: "user_not_found",
858
+ email
859
+ });
860
+ return false;
861
+ }
862
+ if (dbUser.blocked) {
863
+ logAuth("signIn(google) rejected", {
864
+ reason: "blocked",
865
+ email,
866
+ userId: dbUser.id
867
+ });
868
+ return false;
869
+ }
870
+ if (dbUser.inviteStatus === "pending") {
871
+ logAuth("signIn(google) rejected", {
872
+ reason: "invite_pending",
873
+ email,
874
+ userId: dbUser.id
875
+ });
876
+ return false;
877
+ }
878
+ if (dbUser.deleted) {
879
+ logAuth("signIn(google) rejected", {
880
+ reason: "deleted",
881
+ email,
882
+ userId: dbUser.id
883
+ });
884
+ return false;
885
+ }
886
+ if (isCustomerGroupUser(dbUser) && allowCustomerLogin !== true) {
887
+ logAuth("signIn(google) rejected", {
888
+ reason: "customer_group",
889
+ email,
890
+ userId: dbUser.id
891
+ });
892
+ return false;
893
+ }
894
+ const sessionUser = sessionUserFromNextAuthUser(dbUser);
895
+ if (sessionUser.isVendorPortal && !sessionUser.isRBACAdmin) {
896
+ const multiVendorEnabled = await checkMultiVendorEnabledViaSettingsApi();
897
+ if (!multiVendorEnabled) {
898
+ logAuth("signIn(google) rejected", {
899
+ reason: "multi_vendor_disabled",
900
+ email,
901
+ userId: dbUser.id
902
+ });
903
+ return false;
904
+ }
905
+ }
906
+ applySessionUserToAuthUser(user, sessionUser);
907
+ logAuth("signIn(google) ok", summarizeSessionUserForLog(sessionUser));
908
+ return true;
909
+ } catch (err) {
910
+ console.error("[cms-auth] signIn error (google):", err instanceof Error ? err.message : err);
911
+ logAuth("signIn(google) error", {
912
+ email,
913
+ message: err instanceof Error ? err.message : String(err)
914
+ });
915
+ return false;
916
+ }
917
+ },
537
918
  async jwt({ token, user, trigger, session }) {
538
919
  if (user) {
539
920
  logAuth("jwt callback: new sign-in", {
@@ -602,6 +983,30 @@ function getNextAuthOptions(config) {
602
983
  return extend ? extend(options) : options;
603
984
  }
604
985
  __name(getNextAuthOptions, "getNextAuthOptions");
986
+ async function buildNextAuthOptions(config) {
987
+ const { dataSource, entityMap, settingsEncryptionKey, googleResolve, google, createCustomerUserFromGoogle, ...rest } = config;
988
+ const resolved = google ?? await resolveGoogleAuthConfig({
989
+ dataSource,
990
+ entityMap,
991
+ encryptionKey: settingsEncryptionKey,
992
+ ...googleResolve
993
+ });
994
+ let createCustomer = createCustomerUserFromGoogle;
995
+ if (!createCustomer && rest.allowCustomerLogin === true && dataSource && entityMap && entityMap.users && entityMap.user_groups) {
996
+ createCustomer = /* @__PURE__ */ __name((input) => createCustomerUserFromGoogleOAuth({
997
+ dataSource,
998
+ entityMap,
999
+ email: input.email,
1000
+ name: input.name
1001
+ }), "createCustomer");
1002
+ }
1003
+ return getNextAuthOptions({
1004
+ ...rest,
1005
+ google: resolved,
1006
+ createCustomerUserFromGoogle: createCustomer
1007
+ });
1008
+ }
1009
+ __name(buildNextAuthOptions, "buildNextAuthOptions");
605
1010
  function getStorefrontNextAuthOptions(config) {
606
1011
  return getNextAuthOptions({
607
1012
  ...config,
@@ -609,5 +1014,12 @@ function getStorefrontNextAuthOptions(config) {
609
1014
  });
610
1015
  }
611
1016
  __name(getStorefrontNextAuthOptions, "getStorefrontNextAuthOptions");
1017
+ async function buildStorefrontNextAuthOptions(config) {
1018
+ return buildNextAuthOptions({
1019
+ ...config,
1020
+ allowCustomerLogin: true
1021
+ });
1022
+ }
1023
+ __name(buildStorefrontNextAuthOptions, "buildStorefrontNextAuthOptions");
612
1024
 
613
- export { createCmsMiddleware, defaultPublicApiMethods, getNextAuthOptions, getStorefrontNextAuthOptions, isAuthDebugClientEnabled, isAuthDebugEnabled, logAuth, logAuthClient, nextAuthCookieDebugInfo, seedAdministratorPermissions, summarizeSessionUserForLog };
1025
+ export { AUTH_PROVIDERS_SETTINGS_GROUP, buildNextAuthOptions, buildStorefrontNextAuthOptions, createCmsMiddleware, createCustomerUserFromGoogleOAuth, defaultPublicApiMethods, getNextAuthOptions, getStorefrontNextAuthOptions, googleOAuthRedirectUri, isAuthDebugClientEnabled, isAuthDebugEnabled, isGoogleAuthPubliclyEnabled, logAuth, logAuthClient, nextAuthCookieDebugInfo, resolveGoogleAuthConfig, seedAdministratorPermissions, summarizeSessionUserForLog };