@objectstack/plugin-auth 4.0.2 → 4.0.4

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.mjs CHANGED
@@ -372,7 +372,20 @@ var AuthManager = class {
372
372
  // better-auth plugins — registered based on AuthPluginConfig flags
373
373
  plugins: this.buildPluginList(),
374
374
  // Trusted origins for CSRF protection (supports wildcards like "https://*.example.com")
375
- ...this.config.trustedOrigins?.length ? { trustedOrigins: this.config.trustedOrigins } : {},
375
+ // Auto-includes origins from CORS_ORIGIN env var so CORS and CSRF stay in sync.
376
+ ...(() => {
377
+ const origins = [...this.config.trustedOrigins || []];
378
+ const corsOrigin = process.env.CORS_ORIGIN;
379
+ if (corsOrigin && corsOrigin !== "*") {
380
+ corsOrigin.split(",").map((s) => s.trim()).filter(Boolean).forEach((o) => {
381
+ if (!origins.includes(o)) origins.push(o);
382
+ });
383
+ }
384
+ if (!origins.length && (!corsOrigin || corsOrigin === "*")) {
385
+ origins.push("http://localhost:*");
386
+ }
387
+ return origins.length ? { trustedOrigins: origins } : {};
388
+ })(),
376
389
  // Advanced options (cross-subdomain cookies, secure cookies, CSRF, etc.)
377
390
  ...this.config.advanced ? {
378
391
  advanced: {
@@ -508,6 +521,59 @@ var AuthManager = class {
508
521
  get api() {
509
522
  return this.getOrCreateAuth().api;
510
523
  }
524
+ /**
525
+ * Get public authentication configuration
526
+ * Returns safe, non-sensitive configuration that can be exposed to the frontend
527
+ *
528
+ * This allows the frontend to discover:
529
+ * - Which social/OAuth providers are available
530
+ * - Whether email/password login is enabled
531
+ * - Which advanced features are enabled (2FA, magic links, etc.)
532
+ */
533
+ getPublicConfig() {
534
+ const socialProviders = [];
535
+ if (this.config.socialProviders) {
536
+ for (const [id, providerConfig] of Object.entries(this.config.socialProviders)) {
537
+ if (providerConfig.enabled !== false) {
538
+ const nameMap = {
539
+ google: "Google",
540
+ github: "GitHub",
541
+ microsoft: "Microsoft",
542
+ apple: "Apple",
543
+ facebook: "Facebook",
544
+ twitter: "Twitter",
545
+ discord: "Discord",
546
+ gitlab: "GitLab",
547
+ linkedin: "LinkedIn"
548
+ };
549
+ socialProviders.push({
550
+ id,
551
+ name: nameMap[id] || id.charAt(0).toUpperCase() + id.slice(1),
552
+ enabled: true
553
+ });
554
+ }
555
+ }
556
+ }
557
+ const emailPasswordConfig = this.config.emailAndPassword ?? {};
558
+ const emailPassword = {
559
+ enabled: emailPasswordConfig.enabled !== false,
560
+ // Default to true
561
+ disableSignUp: emailPasswordConfig.disableSignUp ?? false,
562
+ requireEmailVerification: emailPasswordConfig.requireEmailVerification ?? false
563
+ };
564
+ const pluginConfig = this.config.plugins ?? {};
565
+ const features = {
566
+ twoFactor: pluginConfig.twoFactor ?? false,
567
+ passkeys: pluginConfig.passkeys ?? false,
568
+ magicLink: pluginConfig.magicLink ?? false,
569
+ organization: pluginConfig.organization ?? false
570
+ };
571
+ return {
572
+ emailPassword,
573
+ socialProviders,
574
+ features
575
+ };
576
+ }
511
577
  };
512
578
 
513
579
  // src/objects/sys-user.object.ts
@@ -1220,6 +1286,65 @@ var SysTwoFactor = ObjectSchema11.create({
1220
1286
  }
1221
1287
  });
1222
1288
 
1289
+ // src/objects/sys-user-preference.object.ts
1290
+ import { ObjectSchema as ObjectSchema12, Field as Field12 } from "@objectstack/spec/data";
1291
+ var SysUserPreference = ObjectSchema12.create({
1292
+ namespace: "sys",
1293
+ name: "user_preference",
1294
+ label: "User Preference",
1295
+ pluralLabel: "User Preferences",
1296
+ icon: "settings",
1297
+ isSystem: true,
1298
+ description: "Per-user key-value preferences (theme, locale, etc.)",
1299
+ titleFormat: "{key}",
1300
+ compactLayout: ["user_id", "key"],
1301
+ fields: {
1302
+ id: Field12.text({
1303
+ label: "Preference ID",
1304
+ required: true,
1305
+ readonly: true
1306
+ }),
1307
+ created_at: Field12.datetime({
1308
+ label: "Created At",
1309
+ defaultValue: "NOW()",
1310
+ readonly: true
1311
+ }),
1312
+ updated_at: Field12.datetime({
1313
+ label: "Updated At",
1314
+ defaultValue: "NOW()",
1315
+ readonly: true
1316
+ }),
1317
+ user_id: Field12.text({
1318
+ label: "User ID",
1319
+ required: true,
1320
+ maxLength: 255,
1321
+ description: "Owner user of this preference"
1322
+ }),
1323
+ key: Field12.text({
1324
+ label: "Key",
1325
+ required: true,
1326
+ maxLength: 255,
1327
+ description: "Preference key (e.g., theme, locale, plugin.ai.auto_save)"
1328
+ }),
1329
+ value: Field12.json({
1330
+ label: "Value",
1331
+ description: "Preference value (any JSON-serializable type)"
1332
+ })
1333
+ },
1334
+ indexes: [
1335
+ { fields: ["user_id", "key"], unique: true },
1336
+ { fields: ["user_id"], unique: false }
1337
+ ],
1338
+ enable: {
1339
+ trackHistory: false,
1340
+ searchable: false,
1341
+ apiEnabled: true,
1342
+ apiMethods: ["get", "list", "create", "update", "delete"],
1343
+ trash: false,
1344
+ mru: false
1345
+ }
1346
+ });
1347
+
1223
1348
  // src/auth-plugin.ts
1224
1349
  var AuthPlugin = class {
1225
1350
  constructor(options = {}) {
@@ -1265,7 +1390,8 @@ var AuthPlugin = class {
1265
1390
  SysTeam,
1266
1391
  SysTeamMember,
1267
1392
  SysApiKey,
1268
- SysTwoFactor
1393
+ SysTwoFactor,
1394
+ SysUserPreference
1269
1395
  ]
1270
1396
  });
1271
1397
  try {
@@ -1365,6 +1491,25 @@ var AuthPlugin = class {
1365
1491
  );
1366
1492
  }
1367
1493
  const rawApp = httpServer.getRawApp();
1494
+ rawApp.get(`${basePath}/config`, async (c) => {
1495
+ try {
1496
+ const config = this.authManager.getPublicConfig();
1497
+ return c.json({
1498
+ success: true,
1499
+ data: config
1500
+ });
1501
+ } catch (error) {
1502
+ const err = error instanceof Error ? error : new Error(String(error));
1503
+ ctx.logger.error("Auth config error:", err);
1504
+ return c.json({
1505
+ success: false,
1506
+ error: {
1507
+ code: "auth_config_error",
1508
+ message: err.message
1509
+ }
1510
+ }, 500);
1511
+ }
1512
+ });
1368
1513
  rawApp.all(`${basePath}/*`, async (c) => {
1369
1514
  try {
1370
1515
  const response = await this.authManager.handleRequest(c.req.raw);
@@ -1425,6 +1570,7 @@ export {
1425
1570
  SysTeamMember,
1426
1571
  SysTwoFactor,
1427
1572
  SysUser,
1573
+ SysUserPreference,
1428
1574
  SysVerification,
1429
1575
  buildOrganizationPluginSchema,
1430
1576
  buildTwoFactorPluginSchema,