@objectstack/plugin-auth 6.9.0 → 7.1.0
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 +70 -34
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +72 -36
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -69,6 +69,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
69
69
|
|
|
70
70
|
// src/auth-plugin.ts
|
|
71
71
|
var import_apps = require("@objectstack/platform-objects/apps");
|
|
72
|
+
var import_pages = require("@objectstack/platform-objects/pages");
|
|
72
73
|
|
|
73
74
|
// src/objectql-adapter.ts
|
|
74
75
|
var import_adapters = require("better-auth/adapters");
|
|
@@ -694,8 +695,7 @@ var AuthManager = class {
|
|
|
694
695
|
relatedId: user.id
|
|
695
696
|
});
|
|
696
697
|
} catch (err) {
|
|
697
|
-
console.error(`[AuthManager] sendResetPassword failed: ${err?.message ?? err}`);
|
|
698
|
-
throw err;
|
|
698
|
+
console.error(`[AuthManager] sendResetPassword failed (swallowed): ${err?.message ?? err}`);
|
|
699
699
|
}
|
|
700
700
|
}
|
|
701
701
|
};
|
|
@@ -731,8 +731,7 @@ var AuthManager = class {
|
|
|
731
731
|
relatedId: user.id
|
|
732
732
|
});
|
|
733
733
|
} catch (err) {
|
|
734
|
-
console.error(`[AuthManager] sendVerificationEmail failed: ${err?.message ?? err}`);
|
|
735
|
-
throw err;
|
|
734
|
+
console.error(`[AuthManager] sendVerificationEmail failed (swallowed): ${err?.message ?? err}`);
|
|
736
735
|
}
|
|
737
736
|
}
|
|
738
737
|
}
|
|
@@ -873,12 +872,14 @@ var AuthManager = class {
|
|
|
873
872
|
async buildPluginList() {
|
|
874
873
|
const pluginConfig = this.config.plugins ?? {};
|
|
875
874
|
const plugins = [];
|
|
875
|
+
const oidcEnv = globalThis?.process?.env?.OS_OIDC_PROVIDER_ENABLED;
|
|
876
|
+
const oidcFromEnv = oidcEnv != null ? String(oidcEnv).toLowerCase() === "true" : void 0;
|
|
876
877
|
const enabled = {
|
|
877
878
|
organization: pluginConfig.organization ?? true,
|
|
878
879
|
twoFactor: pluginConfig.twoFactor ?? false,
|
|
879
880
|
passkeys: pluginConfig.passkeys ?? false,
|
|
880
881
|
magicLink: pluginConfig.magicLink ?? false,
|
|
881
|
-
oidcProvider: pluginConfig.oidcProvider ?? false,
|
|
882
|
+
oidcProvider: oidcFromEnv ?? pluginConfig.oidcProvider ?? false,
|
|
882
883
|
deviceAuthorization: pluginConfig.deviceAuthorization ?? false,
|
|
883
884
|
admin: pluginConfig.admin ?? false
|
|
884
885
|
};
|
|
@@ -1023,8 +1024,7 @@ var AuthManager = class {
|
|
|
1023
1024
|
relatedId: invitation.id
|
|
1024
1025
|
});
|
|
1025
1026
|
} catch (err) {
|
|
1026
|
-
console.error(`[AuthManager] sendInvitationEmail failed: ${err?.message ?? err}`);
|
|
1027
|
-
throw err;
|
|
1027
|
+
console.error(`[AuthManager] sendInvitationEmail failed (swallowed): ${err?.message ?? err}`);
|
|
1028
1028
|
}
|
|
1029
1029
|
}
|
|
1030
1030
|
}));
|
|
@@ -1355,13 +1355,15 @@ var AuthManager = class {
|
|
|
1355
1355
|
};
|
|
1356
1356
|
const termsUrl = resolveLegalUrl(rawTermsUrl, DEFAULT_TERMS_URL);
|
|
1357
1357
|
const privacyUrl = resolveLegalUrl(rawPrivacyUrl, DEFAULT_PRIVACY_URL);
|
|
1358
|
+
const oidcEnv = globalThis?.process?.env?.OS_OIDC_PROVIDER_ENABLED;
|
|
1359
|
+
const oidcFromEnv = oidcEnv != null ? String(oidcEnv).toLowerCase() === "true" : void 0;
|
|
1358
1360
|
const features = {
|
|
1359
1361
|
twoFactor: pluginConfig.twoFactor ?? false,
|
|
1360
1362
|
passkeys: pluginConfig.passkeys ?? false,
|
|
1361
1363
|
magicLink: pluginConfig.magicLink ?? false,
|
|
1362
1364
|
organization: pluginConfig.organization ?? true,
|
|
1363
1365
|
multiOrgEnabled,
|
|
1364
|
-
oidcProvider: pluginConfig.oidcProvider ?? false,
|
|
1366
|
+
oidcProvider: oidcFromEnv ?? pluginConfig.oidcProvider ?? false,
|
|
1365
1367
|
deviceAuthorization: pluginConfig.deviceAuthorization ?? false,
|
|
1366
1368
|
...termsUrl ? { termsUrl } : {},
|
|
1367
1369
|
...privacyUrl ? { privacyUrl } : {}
|
|
@@ -1453,7 +1455,12 @@ var AuthPlugin = class {
|
|
|
1453
1455
|
// @objectstack/platform-objects/apps). plugin-auth is the natural
|
|
1454
1456
|
// owner of its registration since it loads first among the trio
|
|
1455
1457
|
// (auth + security + audit) that supplies the underlying objects.
|
|
1456
|
-
apps: [import_apps.SETUP_APP, import_apps.STUDIO_APP],
|
|
1458
|
+
apps: [import_apps.SETUP_APP, import_apps.STUDIO_APP, import_apps.ACCOUNT_APP],
|
|
1459
|
+
// Slotted record-detail pages for system objects — currently
|
|
1460
|
+
// sys_organization gets a Members / Invitations / Teams tab strip
|
|
1461
|
+
// (see SysOrganizationDetailPage for the rationale and the
|
|
1462
|
+
// intentionally-omitted OAuth / SSO tabs).
|
|
1463
|
+
pages: [import_pages.SysOrganizationDetailPage, import_pages.SysUserDetailPage],
|
|
1457
1464
|
// List views for each Setup-nav object are defined on the schema
|
|
1458
1465
|
// itself via the canonical `listViews` map (e.g.
|
|
1459
1466
|
// sys_user.listViews.{all_users,unverified,two_factor}). Registering
|
|
@@ -1472,30 +1479,6 @@ var AuthPlugin = class {
|
|
|
1472
1479
|
if (!this.authManager) {
|
|
1473
1480
|
throw new Error("Auth manager not initialized");
|
|
1474
1481
|
}
|
|
1475
|
-
ctx.hook("kernel:ready", async () => {
|
|
1476
|
-
try {
|
|
1477
|
-
const i18n = ctx.getService("i18n");
|
|
1478
|
-
let loaded = 0;
|
|
1479
|
-
for (const [locale, data] of Object.entries(import_apps.SetupAppTranslations)) {
|
|
1480
|
-
if (data && typeof data === "object") {
|
|
1481
|
-
try {
|
|
1482
|
-
i18n.loadTranslations(locale, data);
|
|
1483
|
-
loaded++;
|
|
1484
|
-
} catch (err) {
|
|
1485
|
-
ctx.logger.warn(
|
|
1486
|
-
`Auth: failed to load Setup App translations for '${locale}': ${err?.message ?? err}`
|
|
1487
|
-
);
|
|
1488
|
-
}
|
|
1489
|
-
}
|
|
1490
|
-
}
|
|
1491
|
-
if (loaded > 0) {
|
|
1492
|
-
ctx.logger.info(
|
|
1493
|
-
`Auth: contributed Setup App translations (${loaded} locale${loaded > 1 ? "s" : ""})`
|
|
1494
|
-
);
|
|
1495
|
-
}
|
|
1496
|
-
} catch {
|
|
1497
|
-
}
|
|
1498
|
-
});
|
|
1499
1482
|
if (this.options.registerRoutes) {
|
|
1500
1483
|
ctx.hook("kernel:ready", async () => {
|
|
1501
1484
|
if (this.authManager) {
|
|
@@ -1713,6 +1696,56 @@ var AuthPlugin = class {
|
|
|
1713
1696
|
return c.json({ success: false, error: { code: "internal", message: err.message } }, 500);
|
|
1714
1697
|
}
|
|
1715
1698
|
});
|
|
1699
|
+
rawApp.post(`${basePath}/sys-oauth-application/register`, async (c) => {
|
|
1700
|
+
try {
|
|
1701
|
+
let body = {};
|
|
1702
|
+
try {
|
|
1703
|
+
body = await c.req.json();
|
|
1704
|
+
} catch {
|
|
1705
|
+
body = {};
|
|
1706
|
+
}
|
|
1707
|
+
const name = body?.name;
|
|
1708
|
+
const redirectUrlsInput = body?.redirectURLs;
|
|
1709
|
+
const type = body?.type;
|
|
1710
|
+
if (typeof name !== "string" || name.trim().length === 0) {
|
|
1711
|
+
return c.json({ success: false, error: { code: "invalid_request", message: "name is required" } }, 400);
|
|
1712
|
+
}
|
|
1713
|
+
if (typeof redirectUrlsInput !== "string" || redirectUrlsInput.trim().length === 0) {
|
|
1714
|
+
return c.json({ success: false, error: { code: "invalid_request", message: "redirectURLs is required" } }, 400);
|
|
1715
|
+
}
|
|
1716
|
+
const redirectUris = redirectUrlsInput.split(/[\r\n]+/).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
1717
|
+
if (redirectUris.length === 0) {
|
|
1718
|
+
return c.json({ success: false, error: { code: "invalid_request", message: "redirectURLs must contain at least one URL" } }, 400);
|
|
1719
|
+
}
|
|
1720
|
+
const allowedTypes = /* @__PURE__ */ new Set(["web", "native", "user-agent-based"]);
|
|
1721
|
+
const safeType = typeof type === "string" && allowedTypes.has(type) ? type : "web";
|
|
1722
|
+
const authApi = await this.authManager.getApi();
|
|
1723
|
+
if (!authApi?.createOAuthClient) {
|
|
1724
|
+
return c.json({ success: false, error: { code: "unavailable", message: "OIDC provider is not enabled on this environment" } }, 503);
|
|
1725
|
+
}
|
|
1726
|
+
let result;
|
|
1727
|
+
try {
|
|
1728
|
+
result = await authApi.createOAuthClient({
|
|
1729
|
+
body: {
|
|
1730
|
+
client_name: name.trim(),
|
|
1731
|
+
redirect_uris: redirectUris,
|
|
1732
|
+
type: safeType
|
|
1733
|
+
},
|
|
1734
|
+
headers: c.req.raw.headers
|
|
1735
|
+
});
|
|
1736
|
+
} catch (err) {
|
|
1737
|
+
const status = typeof err?.status === "number" ? err.status : 500;
|
|
1738
|
+
const code = err?.body?.error ?? "oauth_register_failed";
|
|
1739
|
+
const message = err?.body?.error_description ?? err?.message ?? "Unable to register OAuth client";
|
|
1740
|
+
return c.json({ success: false, error: { code, message } }, status);
|
|
1741
|
+
}
|
|
1742
|
+
return c.json({ success: true, data: { client: result } });
|
|
1743
|
+
} catch (error) {
|
|
1744
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
1745
|
+
ctx.logger.error("[AuthPlugin] sys-oauth-application/register failed", err);
|
|
1746
|
+
return c.json({ success: false, error: { code: "internal", message: err.message } }, 500);
|
|
1747
|
+
}
|
|
1748
|
+
});
|
|
1716
1749
|
rawApp.all(`${basePath}/*`, async (c) => {
|
|
1717
1750
|
try {
|
|
1718
1751
|
const response = await this.authManager.handleRequest(c.req.raw);
|
|
@@ -1753,7 +1786,10 @@ var AuthPlugin = class {
|
|
|
1753
1786
|
);
|
|
1754
1787
|
}
|
|
1755
1788
|
});
|
|
1756
|
-
|
|
1789
|
+
const oidcEnv = globalThis?.process?.env?.OS_OIDC_PROVIDER_ENABLED;
|
|
1790
|
+
const oidcFromEnv = oidcEnv != null ? String(oidcEnv).toLowerCase() === "true" : void 0;
|
|
1791
|
+
const oidcEnabled = oidcFromEnv ?? this.options.plugins?.oidcProvider ?? false;
|
|
1792
|
+
if (oidcEnabled) {
|
|
1757
1793
|
void this.registerOidcDiscoveryRoutes(rawApp, ctx).catch((error) => {
|
|
1758
1794
|
ctx.logger.error("Failed to register OIDC discovery routes", error);
|
|
1759
1795
|
});
|