@objectstack/rest 9.9.1 → 9.11.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.cjs +43 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +43 -3
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.cts
CHANGED
|
@@ -237,7 +237,8 @@ declare class RestServer {
|
|
|
237
237
|
private sharingRulesServiceProvider?;
|
|
238
238
|
private i18nServiceProvider?;
|
|
239
239
|
private analyticsServiceProvider?;
|
|
240
|
-
|
|
240
|
+
private settingsServiceProvider?;
|
|
241
|
+
constructor(server: IHttpServer, protocol: ObjectStackProtocol, config?: RestServerConfig, kernelManager?: RestKernelManager, envRegistry?: RestEnvRegistry, defaultEnvironmentIdProvider?: () => string | undefined, authServiceProvider?: (environmentId?: string) => Promise<any | undefined>, objectQLProvider?: (environmentId?: string) => Promise<any | undefined>, emailServiceProvider?: (environmentId?: string) => Promise<any | undefined>, sharingServiceProvider?: (environmentId?: string) => Promise<any | undefined>, reportsServiceProvider?: (environmentId?: string) => Promise<any | undefined>, approvalsServiceProvider?: (environmentId?: string) => Promise<any | undefined>, sharingRulesServiceProvider?: (environmentId?: string) => Promise<any | undefined>, i18nServiceProvider?: (environmentId?: string) => Promise<any | undefined>, analyticsServiceProvider?: (environmentId?: string) => Promise<any | undefined>, settingsServiceProvider?: (environmentId?: string) => Promise<any | undefined>);
|
|
241
242
|
/**
|
|
242
243
|
* Resolve the protocol for a given request. When `environmentId` is present
|
|
243
244
|
* and a KernelManager is wired, fetch the per-project kernel's
|
package/dist/index.d.ts
CHANGED
|
@@ -237,7 +237,8 @@ declare class RestServer {
|
|
|
237
237
|
private sharingRulesServiceProvider?;
|
|
238
238
|
private i18nServiceProvider?;
|
|
239
239
|
private analyticsServiceProvider?;
|
|
240
|
-
|
|
240
|
+
private settingsServiceProvider?;
|
|
241
|
+
constructor(server: IHttpServer, protocol: ObjectStackProtocol, config?: RestServerConfig, kernelManager?: RestKernelManager, envRegistry?: RestEnvRegistry, defaultEnvironmentIdProvider?: () => string | undefined, authServiceProvider?: (environmentId?: string) => Promise<any | undefined>, objectQLProvider?: (environmentId?: string) => Promise<any | undefined>, emailServiceProvider?: (environmentId?: string) => Promise<any | undefined>, sharingServiceProvider?: (environmentId?: string) => Promise<any | undefined>, reportsServiceProvider?: (environmentId?: string) => Promise<any | undefined>, approvalsServiceProvider?: (environmentId?: string) => Promise<any | undefined>, sharingRulesServiceProvider?: (environmentId?: string) => Promise<any | undefined>, i18nServiceProvider?: (environmentId?: string) => Promise<any | undefined>, analyticsServiceProvider?: (environmentId?: string) => Promise<any | undefined>, settingsServiceProvider?: (environmentId?: string) => Promise<any | undefined>);
|
|
241
242
|
/**
|
|
242
243
|
* Resolve the protocol for a given request. When `environmentId` is present
|
|
243
244
|
* and a KernelManager is wired, fetch the per-project kernel's
|
package/dist/index.js
CHANGED
|
@@ -449,7 +449,7 @@ function rowsToCsv(fields, rows, includeHeader) {
|
|
|
449
449
|
return lines.join("\r\n") + (lines.length > 0 ? "\r\n" : "");
|
|
450
450
|
}
|
|
451
451
|
var RestServer = class {
|
|
452
|
-
constructor(server, protocol, config = {}, kernelManager, envRegistry, defaultEnvironmentIdProvider, authServiceProvider, objectQLProvider, emailServiceProvider, sharingServiceProvider, reportsServiceProvider, approvalsServiceProvider, sharingRulesServiceProvider, i18nServiceProvider, analyticsServiceProvider) {
|
|
452
|
+
constructor(server, protocol, config = {}, kernelManager, envRegistry, defaultEnvironmentIdProvider, authServiceProvider, objectQLProvider, emailServiceProvider, sharingServiceProvider, reportsServiceProvider, approvalsServiceProvider, sharingRulesServiceProvider, i18nServiceProvider, analyticsServiceProvider, settingsServiceProvider) {
|
|
453
453
|
/**
|
|
454
454
|
* Short-TTL cache for `hostname → environmentId` (P1-4). `resolveByHostname`
|
|
455
455
|
* is a control-plane lookup (typically a DB query) that otherwise runs on
|
|
@@ -480,6 +480,7 @@ var RestServer = class {
|
|
|
480
480
|
this.sharingRulesServiceProvider = sharingRulesServiceProvider;
|
|
481
481
|
this.i18nServiceProvider = i18nServiceProvider;
|
|
482
482
|
this.analyticsServiceProvider = analyticsServiceProvider;
|
|
483
|
+
this.settingsServiceProvider = settingsServiceProvider;
|
|
483
484
|
}
|
|
484
485
|
/**
|
|
485
486
|
* Resolve the protocol for a given request. When `environmentId` is present
|
|
@@ -769,6 +770,7 @@ var RestServer = class {
|
|
|
769
770
|
}
|
|
770
771
|
let userId;
|
|
771
772
|
let tenantId;
|
|
773
|
+
let email;
|
|
772
774
|
const keyPrincipal = await resolveApiKeyPrincipal(identityQl, headers).catch(() => void 0);
|
|
773
775
|
if (keyPrincipal) {
|
|
774
776
|
userId = keyPrincipal.userId;
|
|
@@ -779,6 +781,11 @@ var RestServer = class {
|
|
|
779
781
|
if (!session?.user?.id) return void 0;
|
|
780
782
|
userId = session.user.id;
|
|
781
783
|
tenantId = session.session?.activeOrganizationId ?? void 0;
|
|
784
|
+
if (session.user?.email) email = String(session.user.email);
|
|
785
|
+
}
|
|
786
|
+
if (!email && identityQl && typeof identityQl.find === "function") {
|
|
787
|
+
const urows = await identityQl.find("sys_user", { where: { id: userId }, limit: 1, context: { isSystem: true } }).catch(() => []);
|
|
788
|
+
if (urows?.[0]?.email) email = String(urows[0].email);
|
|
782
789
|
}
|
|
783
790
|
try {
|
|
784
791
|
let ql;
|
|
@@ -869,14 +876,34 @@ var RestServer = class {
|
|
|
869
876
|
} catch {
|
|
870
877
|
}
|
|
871
878
|
}
|
|
879
|
+
let timezone;
|
|
880
|
+
let locale;
|
|
881
|
+
try {
|
|
882
|
+
const settings = this.settingsServiceProvider ? await this.settingsServiceProvider(environmentId).catch(() => void 0) : void 0;
|
|
883
|
+
if (settings && typeof settings.get === "function") {
|
|
884
|
+
const sctx = { tenantId, userId };
|
|
885
|
+
const [tzRes, localeRes] = await Promise.all([
|
|
886
|
+
settings.get("localization", "timezone", sctx).catch(() => void 0),
|
|
887
|
+
settings.get("localization", "locale", sctx).catch(() => void 0)
|
|
888
|
+
]);
|
|
889
|
+
const tzVal = tzRes?.value;
|
|
890
|
+
const localeVal = localeRes?.value;
|
|
891
|
+
if (typeof tzVal === "string" && tzVal.trim()) timezone = tzVal.trim();
|
|
892
|
+
if (typeof localeVal === "string" && localeVal.trim()) locale = localeVal.trim();
|
|
893
|
+
}
|
|
894
|
+
} catch {
|
|
895
|
+
}
|
|
872
896
|
return {
|
|
873
897
|
userId,
|
|
874
898
|
tenantId,
|
|
899
|
+
email,
|
|
875
900
|
roles,
|
|
876
901
|
permissions,
|
|
877
902
|
systemPermissions,
|
|
878
903
|
isSystem: false,
|
|
879
|
-
org_user_ids
|
|
904
|
+
org_user_ids,
|
|
905
|
+
...timezone ? { timezone } : {},
|
|
906
|
+
...locale ? { locale } : {}
|
|
880
907
|
};
|
|
881
908
|
} catch {
|
|
882
909
|
return void 0;
|
|
@@ -2943,6 +2970,7 @@ var RestServer = class {
|
|
|
2943
2970
|
Object.assign(filteredData, rawBody);
|
|
2944
2971
|
}
|
|
2945
2972
|
const context = {
|
|
2973
|
+
publicFormGrant: { object: match.object },
|
|
2946
2974
|
permissions: ["guest_portal"],
|
|
2947
2975
|
anonymous: true
|
|
2948
2976
|
};
|
|
@@ -4409,6 +4437,13 @@ function createRestApiPlugin(config = {}) {
|
|
|
4409
4437
|
return void 0;
|
|
4410
4438
|
}
|
|
4411
4439
|
};
|
|
4440
|
+
const settingsServiceProvider = async (_environmentId) => {
|
|
4441
|
+
try {
|
|
4442
|
+
return ctx.getService("settings");
|
|
4443
|
+
} catch {
|
|
4444
|
+
return void 0;
|
|
4445
|
+
}
|
|
4446
|
+
};
|
|
4412
4447
|
if (!server) {
|
|
4413
4448
|
ctx.logger.warn(`RestApiPlugin: HTTP Server service '${serverService}' not found. REST routes skipped.`);
|
|
4414
4449
|
return;
|
|
@@ -4419,9 +4454,14 @@ function createRestApiPlugin(config = {}) {
|
|
|
4419
4454
|
}
|
|
4420
4455
|
ctx.logger.info("Hydrating REST API from Protocol...");
|
|
4421
4456
|
try {
|
|
4422
|
-
const restServer = new RestServer(server, protocol, config.api, kernelManager, envRegistry, defaultEnvironmentIdProvider, authServiceProvider, objectQLProvider, emailServiceProvider, sharingServiceProvider, reportsServiceProvider, approvalsServiceProvider, sharingRulesServiceProvider, i18nServiceProvider, analyticsServiceProvider);
|
|
4457
|
+
const restServer = new RestServer(server, protocol, config.api, kernelManager, envRegistry, defaultEnvironmentIdProvider, authServiceProvider, objectQLProvider, emailServiceProvider, sharingServiceProvider, reportsServiceProvider, approvalsServiceProvider, sharingRulesServiceProvider, i18nServiceProvider, analyticsServiceProvider, settingsServiceProvider);
|
|
4423
4458
|
restServer.registerRoutes();
|
|
4424
4459
|
ctx.logger.info("REST API successfully registered");
|
|
4460
|
+
if (!config.api?.requireAuth) {
|
|
4461
|
+
ctx.logger.warn(
|
|
4462
|
+
"[security] anonymous access to the data API is ALLOWED (api.requireAuth=false) \u2014 objects without OWD/RLS are world-readable. For secure-by-default set api.requireAuth=true and expose public records via share-links / publicSharing (ADR-0056 D2)."
|
|
4463
|
+
);
|
|
4464
|
+
}
|
|
4425
4465
|
} catch (err) {
|
|
4426
4466
|
ctx.logger.error("Failed to register REST API routes", { error: err.message });
|
|
4427
4467
|
throw err;
|