@getstrata/bootstrap 0.2.8 → 0.2.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/bootstrap/membershipService.d.ts +3 -0
- package/dist/bootstrap/public-api.d.ts +3 -1
- package/dist/bootstrap/queue/defaultJobs.d.ts +2 -0
- package/dist/core/auth/membershipService.d.ts +1 -2
- package/dist/core/queue/createAppQueue.d.ts +3 -3
- package/dist/entries/context.js +689 -686
- package/dist/entries/createWebRoutes.js +1 -0
- package/dist/entries/membershipService.js +480 -0
- package/dist/entries/providers/view.js +1 -0
- package/dist/entries/providers.js +1938 -1935
- package/dist/entries/queue/defaultJobs.js +549 -0
- package/dist/index.js +288 -123
- package/package.json +13 -3
package/dist/index.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
// ../../src/bootstrap/public-api.ts
|
|
3
|
-
import { resolveApplicationQueue as resolveApplicationQueue2, setActiveApplicationContext as setActiveApplicationContext2 } from "@getstrata/core";
|
|
4
|
-
|
|
5
2
|
// ../../src/core/scheduler/schedule.ts
|
|
6
3
|
class Schedule {
|
|
7
4
|
tasks = [];
|
|
@@ -512,8 +509,6 @@ var DEFAULT_CACHE_MAX_ENTRIES = 100;
|
|
|
512
509
|
var DEFAULT_CACHE_DRIVER = "array";
|
|
513
510
|
var DEFAULT_API_TOKEN = "";
|
|
514
511
|
var DEFAULT_QUEUE_DRIVER = "sync";
|
|
515
|
-
// ../../src/bootstrap/context.ts
|
|
516
|
-
import { setActiveApplicationContext } from "@getstrata/core";
|
|
517
512
|
|
|
518
513
|
// ../../src/bootstrap/contracts.ts
|
|
519
514
|
class ServiceContainer {
|
|
@@ -600,6 +595,41 @@ function resolveService(dependencies, token) {
|
|
|
600
595
|
return dependencies.container.resolve(token);
|
|
601
596
|
}
|
|
602
597
|
|
|
598
|
+
// ../../src/bootstrap/applicationRegistry.ts
|
|
599
|
+
var activeContext;
|
|
600
|
+
function setActiveApplicationContext(context) {
|
|
601
|
+
activeContext = context;
|
|
602
|
+
}
|
|
603
|
+
function requireActiveApplicationContext() {
|
|
604
|
+
if (!activeContext) {
|
|
605
|
+
throw new Error("The application context has not been bootstrapped.");
|
|
606
|
+
}
|
|
607
|
+
return activeContext;
|
|
608
|
+
}
|
|
609
|
+
function resolveApplicationCache() {
|
|
610
|
+
return getRequiredDependency(requireActiveApplicationContext().dependencies, "cache");
|
|
611
|
+
}
|
|
612
|
+
function resolveApplicationQueue() {
|
|
613
|
+
return requireActiveApplicationContext().container.resolve(CORE_QUEUE_TOKEN);
|
|
614
|
+
}
|
|
615
|
+
function resolveApplicationAuth() {
|
|
616
|
+
return requireActiveApplicationContext().container.resolve(CORE_AUTH_TOKEN);
|
|
617
|
+
}
|
|
618
|
+
function resolveApplicationPolicyGate() {
|
|
619
|
+
return requireActiveApplicationContext().container.resolve(CORE_POLICY_GATE_TOKEN);
|
|
620
|
+
}
|
|
621
|
+
function resolveApplicationConfig() {
|
|
622
|
+
return requireActiveApplicationContext().config;
|
|
623
|
+
}
|
|
624
|
+
function resolveApplicationLogger() {
|
|
625
|
+
return appLogger;
|
|
626
|
+
}
|
|
627
|
+
function resolveApplicationDependencies() {
|
|
628
|
+
return requireActiveApplicationContext().dependencies;
|
|
629
|
+
}
|
|
630
|
+
// ../../src/bootstrap/context.ts
|
|
631
|
+
import { setActiveApplicationContext as setActiveApplicationContext2 } from "@getstrata/core";
|
|
632
|
+
|
|
603
633
|
// ../../src/bootstrap/discoverModules.ts
|
|
604
634
|
import { readdirSync } from "fs";
|
|
605
635
|
import { join } from "path";
|
|
@@ -728,6 +758,7 @@ var db = new Proxy(function database() {}, {
|
|
|
728
758
|
return typeof value === "function" ? value.bind(connection) : value;
|
|
729
759
|
}
|
|
730
760
|
});
|
|
761
|
+
var connection_default = db;
|
|
731
762
|
|
|
732
763
|
// ../../src/modules/user/apiTokenTable.ts
|
|
733
764
|
import { defineTable } from "@getstrata/core/database";
|
|
@@ -1809,116 +1840,6 @@ class InvalidateCacheTagsJob extends Job {
|
|
|
1809
1840
|
}
|
|
1810
1841
|
var invalidateCacheTagsJob_default = InvalidateCacheTagsJob;
|
|
1811
1842
|
|
|
1812
|
-
// ../../src/bootstrap/applicationRegistry.ts
|
|
1813
|
-
var activeContext;
|
|
1814
|
-
function requireActiveApplicationContext() {
|
|
1815
|
-
if (!activeContext) {
|
|
1816
|
-
throw new Error("The application context has not been bootstrapped.");
|
|
1817
|
-
}
|
|
1818
|
-
return activeContext;
|
|
1819
|
-
}
|
|
1820
|
-
function resolveApplicationCache() {
|
|
1821
|
-
return getRequiredDependency(requireActiveApplicationContext().dependencies, "cache");
|
|
1822
|
-
}
|
|
1823
|
-
function resolveApplicationQueue() {
|
|
1824
|
-
return requireActiveApplicationContext().container.resolve(CORE_QUEUE_TOKEN);
|
|
1825
|
-
}
|
|
1826
|
-
function resolveApplicationAuth() {
|
|
1827
|
-
return requireActiveApplicationContext().container.resolve(CORE_AUTH_TOKEN);
|
|
1828
|
-
}
|
|
1829
|
-
function resolveApplicationPolicyGate() {
|
|
1830
|
-
return requireActiveApplicationContext().container.resolve(CORE_POLICY_GATE_TOKEN);
|
|
1831
|
-
}
|
|
1832
|
-
|
|
1833
|
-
// ../../src/core/jobs/dispatchWebhookJob.ts
|
|
1834
|
-
import { createHmac as createHmac2 } from "crypto";
|
|
1835
|
-
class DispatchWebhookJob extends Job {
|
|
1836
|
-
maxAttempts = 3;
|
|
1837
|
-
backoffMs = 2000;
|
|
1838
|
-
async handle(payload) {
|
|
1839
|
-
const rows = await repositoryConnection`
|
|
1840
|
-
SELECT id, url, secret
|
|
1841
|
-
FROM webhook
|
|
1842
|
-
WHERE id = ${payload.webhookId} AND active = TRUE
|
|
1843
|
-
LIMIT 1
|
|
1844
|
-
`;
|
|
1845
|
-
const webhook = rows[0];
|
|
1846
|
-
if (!webhook) {
|
|
1847
|
-
return;
|
|
1848
|
-
}
|
|
1849
|
-
const body = JSON.stringify({ event: payload.event, payload: payload.payload });
|
|
1850
|
-
const signature = createHmac2("sha256", webhook.secret).update(body).digest("hex");
|
|
1851
|
-
assertSafeOutboundUrl(webhook.url, { allowHttp: appConfig.env !== "production" });
|
|
1852
|
-
let responseStatus = null;
|
|
1853
|
-
let errorMessage = null;
|
|
1854
|
-
try {
|
|
1855
|
-
const response = await safeFetch(webhook.url, {
|
|
1856
|
-
method: "POST",
|
|
1857
|
-
headers: {
|
|
1858
|
-
"content-type": "application/json",
|
|
1859
|
-
"x-workhub-signature": signature
|
|
1860
|
-
},
|
|
1861
|
-
body
|
|
1862
|
-
}, { allowHttp: appConfig.env !== "production" });
|
|
1863
|
-
responseStatus = response.status;
|
|
1864
|
-
if (!response.ok) {
|
|
1865
|
-
throw new Error(`Webhook delivery failed with status ${response.status}.`);
|
|
1866
|
-
}
|
|
1867
|
-
} catch (error) {
|
|
1868
|
-
errorMessage = error instanceof Error ? error.message : String(error);
|
|
1869
|
-
await repositoryConnection`
|
|
1870
|
-
INSERT INTO webhook_delivery (webhook_id, event, payload, response_status, error)
|
|
1871
|
-
VALUES (
|
|
1872
|
-
${webhook.id},
|
|
1873
|
-
${payload.event},
|
|
1874
|
-
${JSON.stringify(payload.payload)}::jsonb,
|
|
1875
|
-
${responseStatus},
|
|
1876
|
-
${errorMessage}
|
|
1877
|
-
)
|
|
1878
|
-
`;
|
|
1879
|
-
throw error instanceof Error ? error : new Error(errorMessage);
|
|
1880
|
-
}
|
|
1881
|
-
await repositoryConnection`
|
|
1882
|
-
INSERT INTO webhook_delivery (webhook_id, event, payload, response_status)
|
|
1883
|
-
VALUES (
|
|
1884
|
-
${webhook.id},
|
|
1885
|
-
${payload.event},
|
|
1886
|
-
${JSON.stringify(payload.payload)}::jsonb,
|
|
1887
|
-
${responseStatus}
|
|
1888
|
-
)
|
|
1889
|
-
`;
|
|
1890
|
-
}
|
|
1891
|
-
}
|
|
1892
|
-
var dispatchWebhookJob_default = DispatchWebhookJob;
|
|
1893
|
-
|
|
1894
|
-
// ../../src/core/queue/jobRegistry.ts
|
|
1895
|
-
class JobRegistry {
|
|
1896
|
-
constructor() {}
|
|
1897
|
-
factories = new Map;
|
|
1898
|
-
instances = new WeakMap;
|
|
1899
|
-
register(name, factory) {
|
|
1900
|
-
this.factories.set(name, factory);
|
|
1901
|
-
}
|
|
1902
|
-
resolveName(job) {
|
|
1903
|
-
return this.instances.get(job);
|
|
1904
|
-
}
|
|
1905
|
-
track(name, job) {
|
|
1906
|
-
this.instances.set(job, name);
|
|
1907
|
-
return job;
|
|
1908
|
-
}
|
|
1909
|
-
create(name) {
|
|
1910
|
-
const factory = this.factories.get(name);
|
|
1911
|
-
if (!factory) {
|
|
1912
|
-
return;
|
|
1913
|
-
}
|
|
1914
|
-
return factory();
|
|
1915
|
-
}
|
|
1916
|
-
names() {
|
|
1917
|
-
return [...this.factories.keys()];
|
|
1918
|
-
}
|
|
1919
|
-
}
|
|
1920
|
-
var jobRegistry = new JobRegistry;
|
|
1921
|
-
|
|
1922
1843
|
// ../../src/core/pagination/index.ts
|
|
1923
1844
|
function buildPaginationMeta(input) {
|
|
1924
1845
|
const lastPage = Math.max(1, Math.ceil(input.total / input.perPage));
|
|
@@ -3646,6 +3567,34 @@ class FailedJobService {
|
|
|
3646
3567
|
}
|
|
3647
3568
|
var failedJobService_default = FailedJobService;
|
|
3648
3569
|
|
|
3570
|
+
// ../../src/core/queue/jobRegistry.ts
|
|
3571
|
+
class JobRegistry {
|
|
3572
|
+
constructor() {}
|
|
3573
|
+
factories = new Map;
|
|
3574
|
+
instances = new WeakMap;
|
|
3575
|
+
register(name, factory) {
|
|
3576
|
+
this.factories.set(name, factory);
|
|
3577
|
+
}
|
|
3578
|
+
resolveName(job) {
|
|
3579
|
+
return this.instances.get(job);
|
|
3580
|
+
}
|
|
3581
|
+
track(name, job) {
|
|
3582
|
+
this.instances.set(job, name);
|
|
3583
|
+
return job;
|
|
3584
|
+
}
|
|
3585
|
+
create(name) {
|
|
3586
|
+
const factory = this.factories.get(name);
|
|
3587
|
+
if (!factory) {
|
|
3588
|
+
return;
|
|
3589
|
+
}
|
|
3590
|
+
return factory();
|
|
3591
|
+
}
|
|
3592
|
+
names() {
|
|
3593
|
+
return [...this.factories.keys()];
|
|
3594
|
+
}
|
|
3595
|
+
}
|
|
3596
|
+
var jobRegistry = new JobRegistry;
|
|
3597
|
+
|
|
3649
3598
|
// ../../src/core/queue/jobRunner.ts
|
|
3650
3599
|
async function runQueueJob(envelope, failedJobs) {
|
|
3651
3600
|
const job = jobRegistry.create(envelope.name);
|
|
@@ -3760,19 +3709,82 @@ function createProductionQueue(driver, options = {}) {
|
|
|
3760
3709
|
return new ResilientQueue(failedJobs, driver === "async");
|
|
3761
3710
|
}
|
|
3762
3711
|
|
|
3763
|
-
// ../../src/core/
|
|
3764
|
-
|
|
3712
|
+
// ../../src/core/jobs/dispatchWebhookJob.ts
|
|
3713
|
+
import { createHmac as createHmac2 } from "crypto";
|
|
3714
|
+
class DispatchWebhookJob extends Job {
|
|
3715
|
+
maxAttempts = 3;
|
|
3716
|
+
backoffMs = 2000;
|
|
3717
|
+
async handle(payload) {
|
|
3718
|
+
const rows = await repositoryConnection`
|
|
3719
|
+
SELECT id, url, secret
|
|
3720
|
+
FROM webhook
|
|
3721
|
+
WHERE id = ${payload.webhookId} AND active = TRUE
|
|
3722
|
+
LIMIT 1
|
|
3723
|
+
`;
|
|
3724
|
+
const webhook = rows[0];
|
|
3725
|
+
if (!webhook) {
|
|
3726
|
+
return;
|
|
3727
|
+
}
|
|
3728
|
+
const body = JSON.stringify({ event: payload.event, payload: payload.payload });
|
|
3729
|
+
const signature = createHmac2("sha256", webhook.secret).update(body).digest("hex");
|
|
3730
|
+
assertSafeOutboundUrl(webhook.url, { allowHttp: appConfig.env !== "production" });
|
|
3731
|
+
let responseStatus = null;
|
|
3732
|
+
let errorMessage = null;
|
|
3733
|
+
try {
|
|
3734
|
+
const response = await safeFetch(webhook.url, {
|
|
3735
|
+
method: "POST",
|
|
3736
|
+
headers: {
|
|
3737
|
+
"content-type": "application/json",
|
|
3738
|
+
"x-workhub-signature": signature
|
|
3739
|
+
},
|
|
3740
|
+
body
|
|
3741
|
+
}, { allowHttp: appConfig.env !== "production" });
|
|
3742
|
+
responseStatus = response.status;
|
|
3743
|
+
if (!response.ok) {
|
|
3744
|
+
throw new Error(`Webhook delivery failed with status ${response.status}.`);
|
|
3745
|
+
}
|
|
3746
|
+
} catch (error) {
|
|
3747
|
+
errorMessage = error instanceof Error ? error.message : String(error);
|
|
3748
|
+
await repositoryConnection`
|
|
3749
|
+
INSERT INTO webhook_delivery (webhook_id, event, payload, response_status, error)
|
|
3750
|
+
VALUES (
|
|
3751
|
+
${webhook.id},
|
|
3752
|
+
${payload.event},
|
|
3753
|
+
${JSON.stringify(payload.payload)}::jsonb,
|
|
3754
|
+
${responseStatus},
|
|
3755
|
+
${errorMessage}
|
|
3756
|
+
)
|
|
3757
|
+
`;
|
|
3758
|
+
throw error instanceof Error ? error : new Error(errorMessage);
|
|
3759
|
+
}
|
|
3760
|
+
await repositoryConnection`
|
|
3761
|
+
INSERT INTO webhook_delivery (webhook_id, event, payload, response_status)
|
|
3762
|
+
VALUES (
|
|
3763
|
+
${webhook.id},
|
|
3764
|
+
${payload.event},
|
|
3765
|
+
${JSON.stringify(payload.payload)}::jsonb,
|
|
3766
|
+
${responseStatus}
|
|
3767
|
+
)
|
|
3768
|
+
`;
|
|
3769
|
+
}
|
|
3770
|
+
}
|
|
3771
|
+
var dispatchWebhookJob_default = DispatchWebhookJob;
|
|
3772
|
+
|
|
3773
|
+
// ../../src/bootstrap/queue/defaultJobs.ts
|
|
3765
3774
|
function registerDefaultJobs() {
|
|
3766
3775
|
jobRegistry.register("cache.invalidate-tags", () => {
|
|
3767
3776
|
return new invalidateCacheTagsJob_default(resolveApplicationCache());
|
|
3768
3777
|
});
|
|
3769
3778
|
jobRegistry.register("webhook.dispatch", () => new dispatchWebhookJob_default);
|
|
3770
3779
|
}
|
|
3771
|
-
|
|
3780
|
+
|
|
3781
|
+
// ../../src/core/queue/createAppQueue.ts
|
|
3782
|
+
var FAILED_JOB_SERVICE_TOKEN = "core.failedJobs";
|
|
3783
|
+
function createAppQueue(driver, redisUrl, failedJobs = createFailedJobService(), registerJobs) {
|
|
3772
3784
|
return createProductionQueue(driver, {
|
|
3773
3785
|
redisUrl,
|
|
3774
3786
|
failedJobs,
|
|
3775
|
-
registerJobs
|
|
3787
|
+
registerJobs
|
|
3776
3788
|
});
|
|
3777
3789
|
}
|
|
3778
3790
|
|
|
@@ -3880,7 +3892,7 @@ var queueProvider = {
|
|
|
3880
3892
|
config.set("queue.driver", driver);
|
|
3881
3893
|
const failedJobs = createFailedJobService();
|
|
3882
3894
|
container.set(FAILED_JOB_SERVICE_TOKEN, failedJobs);
|
|
3883
|
-
container.set(CORE_QUEUE_TOKEN, createAppQueue(driver, config.get(REDIS_URL_CONFIG_KEY) ?? process.env.REDIS_URL, failedJobs));
|
|
3895
|
+
container.set(CORE_QUEUE_TOKEN, createAppQueue(driver, config.get(REDIS_URL_CONFIG_KEY) ?? process.env.REDIS_URL, failedJobs, registerDefaultJobs));
|
|
3884
3896
|
}
|
|
3885
3897
|
};
|
|
3886
3898
|
var queue_default = queueProvider;
|
|
@@ -4357,7 +4369,7 @@ function createAppContext() {
|
|
|
4357
4369
|
config,
|
|
4358
4370
|
dependencies
|
|
4359
4371
|
};
|
|
4360
|
-
|
|
4372
|
+
setActiveApplicationContext2(appContext);
|
|
4361
4373
|
return appContext;
|
|
4362
4374
|
}
|
|
4363
4375
|
// ../../src/bootstrap/createWebRoutes.ts
|
|
@@ -4864,6 +4876,151 @@ function securedBindRouteModelByKey(param, resolver, authorization, handler) {
|
|
|
4864
4876
|
return response;
|
|
4865
4877
|
};
|
|
4866
4878
|
}
|
|
4879
|
+
// ../../src/core/auth/accessControl.ts
|
|
4880
|
+
var ROLE_RANK = {
|
|
4881
|
+
member: 1,
|
|
4882
|
+
admin: 2,
|
|
4883
|
+
owner: 3
|
|
4884
|
+
};
|
|
4885
|
+
function isGlobalAdmin(user) {
|
|
4886
|
+
return user?.role === "admin";
|
|
4887
|
+
}
|
|
4888
|
+
function hasMinimumOrgRole(role, minimum) {
|
|
4889
|
+
if (!role) {
|
|
4890
|
+
return false;
|
|
4891
|
+
}
|
|
4892
|
+
return ROLE_RANK[role] >= ROLE_RANK[minimum];
|
|
4893
|
+
}
|
|
4894
|
+
function resolveUserId(user) {
|
|
4895
|
+
const userId = typeof user.id === "number" ? user.id : Number(user.id);
|
|
4896
|
+
if (!Number.isInteger(userId) || userId <= 0) {
|
|
4897
|
+
throw new ForbiddenError("Invalid authenticated user.");
|
|
4898
|
+
}
|
|
4899
|
+
return userId;
|
|
4900
|
+
}
|
|
4901
|
+
|
|
4902
|
+
// ../../src/core/auth/membershipContext.ts
|
|
4903
|
+
import { AsyncLocalStorage as AsyncLocalStorage5 } from "async_hooks";
|
|
4904
|
+
|
|
4905
|
+
// ../../src/modules/organization/memberRepository.ts
|
|
4906
|
+
class OrganizationMemberRepository {
|
|
4907
|
+
constructor() {}
|
|
4908
|
+
async findMembership(userId, organizationId) {
|
|
4909
|
+
const rows = await connection_default`
|
|
4910
|
+
SELECT id, organization_id, user_id, role, created_at
|
|
4911
|
+
FROM organization_member
|
|
4912
|
+
WHERE user_id = ${userId} AND organization_id = ${organizationId}
|
|
4913
|
+
LIMIT 1
|
|
4914
|
+
`;
|
|
4915
|
+
return rows[0] ?? null;
|
|
4916
|
+
}
|
|
4917
|
+
async listForUser(userId) {
|
|
4918
|
+
return await connection_default`
|
|
4919
|
+
SELECT id, organization_id, user_id, role, created_at
|
|
4920
|
+
FROM organization_member
|
|
4921
|
+
WHERE user_id = ${userId}
|
|
4922
|
+
ORDER BY organization_id
|
|
4923
|
+
`;
|
|
4924
|
+
}
|
|
4925
|
+
async listForOrganization(organizationId) {
|
|
4926
|
+
return await connection_default`
|
|
4927
|
+
SELECT id, organization_id, user_id, role, created_at
|
|
4928
|
+
FROM organization_member
|
|
4929
|
+
WHERE organization_id = ${organizationId}
|
|
4930
|
+
ORDER BY id
|
|
4931
|
+
`;
|
|
4932
|
+
}
|
|
4933
|
+
async addMember(input) {
|
|
4934
|
+
const rows = await connection_default`
|
|
4935
|
+
INSERT INTO organization_member (organization_id, user_id, role)
|
|
4936
|
+
VALUES (${input.organizationId}, ${input.userId}, ${input.role ?? "member"})
|
|
4937
|
+
RETURNING id, organization_id, user_id, role, created_at
|
|
4938
|
+
`;
|
|
4939
|
+
const row = rows[0];
|
|
4940
|
+
if (!row) {
|
|
4941
|
+
throw new Error("Organization member insert did not return a row.");
|
|
4942
|
+
}
|
|
4943
|
+
return row;
|
|
4944
|
+
}
|
|
4945
|
+
async removeMember(organizationId, userId) {
|
|
4946
|
+
const rows = await connection_default`
|
|
4947
|
+
DELETE FROM organization_member
|
|
4948
|
+
WHERE organization_id = ${organizationId} AND user_id = ${userId}
|
|
4949
|
+
RETURNING id
|
|
4950
|
+
`;
|
|
4951
|
+
return rows.length > 0;
|
|
4952
|
+
}
|
|
4953
|
+
}
|
|
4954
|
+
var memberRepository_default = OrganizationMemberRepository;
|
|
4955
|
+
|
|
4956
|
+
// ../../src/core/auth/membershipContext.ts
|
|
4957
|
+
var membershipContext = new AsyncLocalStorage5;
|
|
4958
|
+
var membershipRepository = new memberRepository_default;
|
|
4959
|
+
|
|
4960
|
+
// ../../src/core/auth/membershipService.ts
|
|
4961
|
+
class MembershipService {
|
|
4962
|
+
members;
|
|
4963
|
+
constructor(members = membershipRepository) {
|
|
4964
|
+
this.members = members;
|
|
4965
|
+
}
|
|
4966
|
+
async listOrganizationIdsForUser(userId) {
|
|
4967
|
+
const memberships = await this.members.listForUser(userId);
|
|
4968
|
+
return memberships.map((membership) => membership.organization_id);
|
|
4969
|
+
}
|
|
4970
|
+
async getOrgRole(userId, organizationId) {
|
|
4971
|
+
const membership = await this.members.findMembership(userId, organizationId);
|
|
4972
|
+
return membership?.role ?? null;
|
|
4973
|
+
}
|
|
4974
|
+
async requireOrgAccess(organizationId, minimumRole = "member", user = currentAuthUser()) {
|
|
4975
|
+
if (!user) {
|
|
4976
|
+
throw new ForbiddenError("Authentication required.");
|
|
4977
|
+
}
|
|
4978
|
+
if (isGlobalAdmin(user)) {
|
|
4979
|
+
return "owner";
|
|
4980
|
+
}
|
|
4981
|
+
const role = await this.getOrgRole(resolveUserId(user), organizationId);
|
|
4982
|
+
if (!role || !hasMinimumOrgRole(role, minimumRole)) {
|
|
4983
|
+
throw new ForbiddenError("Organization membership required.");
|
|
4984
|
+
}
|
|
4985
|
+
return role;
|
|
4986
|
+
}
|
|
4987
|
+
async filterAccessibleOrganizationIds(organizationIds, user = currentAuthUser()) {
|
|
4988
|
+
if (!user) {
|
|
4989
|
+
return [];
|
|
4990
|
+
}
|
|
4991
|
+
if (isGlobalAdmin(user)) {
|
|
4992
|
+
return organizationIds;
|
|
4993
|
+
}
|
|
4994
|
+
const allowed = new Set(await this.listOrganizationIdsForUser(resolveUserId(user)));
|
|
4995
|
+
return organizationIds.filter((organizationId) => allowed.has(organizationId));
|
|
4996
|
+
}
|
|
4997
|
+
async addOwnerOnOrganizationCreate(organizationId, userId) {
|
|
4998
|
+
await this.members.addMember({
|
|
4999
|
+
organizationId,
|
|
5000
|
+
userId,
|
|
5001
|
+
role: "owner"
|
|
5002
|
+
});
|
|
5003
|
+
}
|
|
5004
|
+
listMembersForOrganization(organizationId) {
|
|
5005
|
+
return this.members.listForOrganization(organizationId);
|
|
5006
|
+
}
|
|
5007
|
+
addMember(input) {
|
|
5008
|
+
return this.members.addMember(input);
|
|
5009
|
+
}
|
|
5010
|
+
removeMember(organizationId, userId) {
|
|
5011
|
+
return this.members.removeMember(organizationId, userId);
|
|
5012
|
+
}
|
|
5013
|
+
}
|
|
5014
|
+
var membershipService_default = MembershipService;
|
|
5015
|
+
|
|
5016
|
+
// ../../src/bootstrap/membershipService.ts
|
|
5017
|
+
function resolveMembershipService() {
|
|
5018
|
+
const dependencies = resolveApplicationDependencies();
|
|
5019
|
+
if (dependencies.container.has("core.membership")) {
|
|
5020
|
+
return dependencies.container.resolve("core.membership");
|
|
5021
|
+
}
|
|
5022
|
+
return new membershipService_default;
|
|
5023
|
+
}
|
|
4867
5024
|
// ../../src/bootstrap/prefixRouteMap.ts
|
|
4868
5025
|
function prefixRouteMap(prefix, routes) {
|
|
4869
5026
|
const normalizedPrefix = prefix.replace(/\/$/, "");
|
|
@@ -5097,7 +5254,7 @@ export {
|
|
|
5097
5254
|
wrapSecuredRouteModelByKey,
|
|
5098
5255
|
toRouteRequest,
|
|
5099
5256
|
slugify,
|
|
5100
|
-
|
|
5257
|
+
setActiveApplicationContext,
|
|
5101
5258
|
securedBindRouteModelByKey,
|
|
5102
5259
|
securedBindRouteModel,
|
|
5103
5260
|
scheduleRunCommand,
|
|
@@ -5105,7 +5262,15 @@ export {
|
|
|
5105
5262
|
runDueScheduledTasks,
|
|
5106
5263
|
routeParams,
|
|
5107
5264
|
resolveService,
|
|
5108
|
-
|
|
5265
|
+
resolveMembershipService,
|
|
5266
|
+
resolveApplicationQueue,
|
|
5267
|
+
resolveApplicationPolicyGate,
|
|
5268
|
+
resolveApplicationLogger,
|
|
5269
|
+
resolveApplicationDependencies,
|
|
5270
|
+
resolveApplicationConfig,
|
|
5271
|
+
resolveApplicationCache,
|
|
5272
|
+
resolveApplicationAuth,
|
|
5273
|
+
registerDefaultJobs,
|
|
5109
5274
|
prefixRouteMap,
|
|
5110
5275
|
parseFormBody,
|
|
5111
5276
|
mergeWebRoutes,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getstrata/bootstrap",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.9",
|
|
4
4
|
"description": "Strata application bootstrap — HttpKernel, DI, web session helpers",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -50,6 +50,16 @@
|
|
|
50
50
|
"import": "./dist/entries/httpKernel.js",
|
|
51
51
|
"default": "./dist/entries/httpKernel.js"
|
|
52
52
|
},
|
|
53
|
+
"./membershipService": {
|
|
54
|
+
"types": "./dist/bootstrap/membershipService.d.ts",
|
|
55
|
+
"import": "./dist/entries/membershipService.js",
|
|
56
|
+
"default": "./dist/entries/membershipService.js"
|
|
57
|
+
},
|
|
58
|
+
"./queue/defaultJobs": {
|
|
59
|
+
"types": "./dist/bootstrap/queue/defaultJobs.d.ts",
|
|
60
|
+
"import": "./dist/entries/queue/defaultJobs.js",
|
|
61
|
+
"default": "./dist/entries/queue/defaultJobs.js"
|
|
62
|
+
},
|
|
53
63
|
"./providers": {
|
|
54
64
|
"types": "./dist/bootstrap/providers/index.d.ts",
|
|
55
65
|
"import": "./dist/entries/providers.js",
|
|
@@ -72,14 +82,14 @@
|
|
|
72
82
|
"build:bundle": "bun build index.ts --outdir dist --target bun --external bun --external eta --external @getstrata/core",
|
|
73
83
|
"build:types": "tsc -p tsconfig.types.json",
|
|
74
84
|
"prepublishOnly": "bun run build",
|
|
75
|
-
"build:subpaths": "bun build entries/applicationRegistry.ts entries/config.ts entries/context.ts entries/contracts.ts entries/createWebRoutes.ts entries/http/securedRouteModelBinding.ts entries/httpKernel.ts entries/providers.ts entries/providers/view.ts --outdir dist --root . --target bun --external bun --external eta --external @getstrata/core",
|
|
85
|
+
"build:subpaths": "bun build entries/applicationRegistry.ts entries/config.ts entries/context.ts entries/contracts.ts entries/createWebRoutes.ts entries/http/securedRouteModelBinding.ts entries/httpKernel.ts entries/membershipService.ts entries/queue/defaultJobs.ts entries/providers.ts entries/providers/view.ts --outdir dist --root . --target bun --external bun --external eta --external @getstrata/core",
|
|
76
86
|
"build:shims": "true"
|
|
77
87
|
},
|
|
78
88
|
"publishConfig": {
|
|
79
89
|
"access": "public"
|
|
80
90
|
},
|
|
81
91
|
"peerDependencies": {
|
|
82
|
-
"@getstrata/core": "^0.5.
|
|
92
|
+
"@getstrata/core": "^0.5.17",
|
|
83
93
|
"typescript": "^5.9.0"
|
|
84
94
|
}
|
|
85
95
|
}
|