@loomcore/api 0.2.12 → 0.2.14
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/__tests__/common-test.utils.js +16 -3
- package/dist/__tests__/test-objects.d.ts +4 -2
- package/dist/__tests__/test-objects.js +17 -7
- package/dist/controllers/auth.controller.js +3 -9
- package/dist/databases/mongo-db/migrations/mongo-initial-schema.js +29 -1
- package/dist/databases/postgres/migrations/__tests__/test-migration-helper.js +3 -3
- package/dist/databases/postgres/migrations/postgres-initial-schema.js +35 -6
- package/dist/models/initial-database-config.interface.d.ts +1 -1
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.js +1 -0
- package/dist/services/organization-domain.service.d.ts +6 -0
- package/dist/services/organization-domain.service.js +7 -0
- package/dist/services/organization.service.d.ts +2 -0
- package/dist/services/organization.service.js +14 -0
- package/package.json +2 -2
|
@@ -11,8 +11,9 @@ import { PostgresDatabase } from "../databases/postgres/postgres.database.js";
|
|
|
11
11
|
import { GenericApiService, UserService } from "../services/index.js";
|
|
12
12
|
import { MultiTenantApiService } from "../services/multi-tenant-api.service.js";
|
|
13
13
|
import { OrganizationService } from "../services/organization.service.js";
|
|
14
|
+
import { OrganizationDomainService } from "../services/organization-domain.service.js";
|
|
14
15
|
import * as testObjectsModule from "./test-objects.js";
|
|
15
|
-
const { getTestMetaOrg, getTestMetaOrgRefererUrl, getTestOrg, getTestMetaOrgUser, getTestMetaOrgUserContext, getTestOrgUser, getTestOrgUserContext, setTestOrgId, setTestMetaOrgId, setTestMetaOrgUserId, setTestOrgUserId, } = testObjectsModule;
|
|
16
|
+
const { getTestMetaOrg, getTestMetaOrgDomain, getTestMetaOrgRefererUrl, getTestOrg, getTestOrgDomain, getTestMetaOrgUser, getTestMetaOrgUserContext, getTestOrgUser, getTestOrgUserContext, setTestOrgId, setTestMetaOrgId, setTestMetaOrgUserId, setTestOrgUserId, TEST_META_ORG_DOMAIN, TEST_ORG_DOMAIN, } = testObjectsModule;
|
|
16
17
|
import { entityUtils } from "@loomcore/common/utils";
|
|
17
18
|
import { config, setBaseApiConfig } from "../config/index.js";
|
|
18
19
|
import { attemptLogin } from "../utils/auth/index.js";
|
|
@@ -24,6 +25,7 @@ import { TestEmailClient } from "./test-email-client.js";
|
|
|
24
25
|
let deviceIdCookie;
|
|
25
26
|
let database;
|
|
26
27
|
let organizationService;
|
|
28
|
+
let organizationDomainService;
|
|
27
29
|
let userService;
|
|
28
30
|
const JWT_SECRET = "test-secret";
|
|
29
31
|
const newUser1Email = "one@test.com";
|
|
@@ -32,6 +34,7 @@ const constDeviceIdCookie = crypto.randomBytes(16).toString("hex");
|
|
|
32
34
|
function initialize(db) {
|
|
33
35
|
database = db;
|
|
34
36
|
organizationService = new OrganizationService(db);
|
|
37
|
+
organizationDomainService = new OrganizationDomainService(db);
|
|
35
38
|
userService = new UserService(db);
|
|
36
39
|
deviceIdCookie = constDeviceIdCookie;
|
|
37
40
|
}
|
|
@@ -51,7 +54,7 @@ async function createMetaOrg() {
|
|
|
51
54
|
if (!config.app.isMultiTenant) {
|
|
52
55
|
return;
|
|
53
56
|
}
|
|
54
|
-
if (!organizationService) {
|
|
57
|
+
if (!organizationService || !organizationDomainService) {
|
|
55
58
|
throw new Error("OrganizationService not initialized. Call initialize() first.");
|
|
56
59
|
}
|
|
57
60
|
try {
|
|
@@ -60,10 +63,15 @@ async function createMetaOrg() {
|
|
|
60
63
|
const metaOrgInsertResult = await organizationService.create(EmptyUserContext, getTestMetaOrg());
|
|
61
64
|
if (metaOrgInsertResult) {
|
|
62
65
|
setTestMetaOrgId(metaOrgInsertResult._id);
|
|
66
|
+
await organizationDomainService.create(EmptyUserContext, getTestMetaOrgDomain(metaOrgInsertResult._id));
|
|
63
67
|
}
|
|
64
68
|
}
|
|
65
69
|
else {
|
|
66
70
|
setTestMetaOrgId(existingMetaOrg._id);
|
|
71
|
+
const existingDomain = await organizationDomainService.findOne(EmptyUserContext, { filters: { domain: { eq: TEST_META_ORG_DOMAIN } } });
|
|
72
|
+
if (!existingDomain) {
|
|
73
|
+
await organizationDomainService.create(EmptyUserContext, getTestMetaOrgDomain(existingMetaOrg._id));
|
|
74
|
+
}
|
|
67
75
|
}
|
|
68
76
|
}
|
|
69
77
|
catch (error) {
|
|
@@ -96,7 +104,7 @@ async function setupTestUsers() {
|
|
|
96
104
|
}
|
|
97
105
|
}
|
|
98
106
|
async function createTestUsers() {
|
|
99
|
-
if (!organizationService || !userService) {
|
|
107
|
+
if (!organizationService || !organizationDomainService || !userService) {
|
|
100
108
|
throw new Error("Database not initialized. Call initialize() first.");
|
|
101
109
|
}
|
|
102
110
|
try {
|
|
@@ -112,9 +120,14 @@ async function createTestUsers() {
|
|
|
112
120
|
throw new Error("Failed to create test organization");
|
|
113
121
|
}
|
|
114
122
|
setTestOrgId(createdTestOrg._id);
|
|
123
|
+
await organizationDomainService.create(EmptyUserContext, getTestOrgDomain(createdTestOrg._id));
|
|
115
124
|
}
|
|
116
125
|
else {
|
|
117
126
|
setTestOrgId(existingTestOrg._id);
|
|
127
|
+
const existingDomain = await organizationDomainService.findOne(EmptyUserContext, { filters: { domain: { eq: TEST_ORG_DOMAIN } } });
|
|
128
|
+
if (!existingDomain) {
|
|
129
|
+
await organizationDomainService.create(EmptyUserContext, getTestOrgDomain(existingTestOrg._id));
|
|
130
|
+
}
|
|
118
131
|
}
|
|
119
132
|
const createdTestOrgUser = await userService.create(getTestOrgUserContext(), getTestOrgUser());
|
|
120
133
|
const createdMetaOrgUser = await userService.create(getTestMetaOrgUserContext(), getTestMetaOrgUser());
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { IOrganization, IUser, IUserContext } from "@loomcore/common/models";
|
|
1
|
+
import type { IOrganization, IOrganizationDomain, IUser, IUserContext } from "@loomcore/common/models";
|
|
2
2
|
export declare let TEST_META_ORG_ID: string | number;
|
|
3
3
|
export declare let TEST_META_ORG_USER_ID: string | number;
|
|
4
4
|
export declare function setTestMetaOrgId(metaOrgId: string | number): void;
|
|
@@ -6,15 +6,17 @@ export declare function setTestMetaOrgUserId(userId: string | number): void;
|
|
|
6
6
|
export declare const TEST_META_ORG_USER_PASSWORD = "test-meta-org-user-password";
|
|
7
7
|
export declare const TEST_META_ORG_DOMAIN = "test-meta-org.example.com";
|
|
8
8
|
export declare const TEST_ORG_DOMAIN = "test-org.example.com";
|
|
9
|
-
export declare function getRefererUrlForOrg(
|
|
9
|
+
export declare function getRefererUrlForOrg(domain: string): string;
|
|
10
10
|
export declare function getTestMetaOrgRefererUrl(): string;
|
|
11
11
|
export declare function getTestOrgRefererUrl(): string;
|
|
12
12
|
export declare function getTestMetaOrg(): IOrganization;
|
|
13
|
+
export declare function getTestMetaOrgDomain(organizationId?: string | number): Partial<IOrganizationDomain>;
|
|
13
14
|
export declare function getTestMetaOrgUser(): IUser;
|
|
14
15
|
export declare function getTestMetaOrgUserContext(): IUserContext;
|
|
15
16
|
export declare function setTestOrgId(orgId: string | number): void;
|
|
16
17
|
export declare function setTestOrgUserId(userId: string | number): void;
|
|
17
18
|
export declare function getTestOrg(): IOrganization;
|
|
19
|
+
export declare function getTestOrgDomain(organizationId?: string | number): Partial<IOrganizationDomain>;
|
|
18
20
|
export declare const TEST_ORG_USER_PASSWORD = "test-org-user-password";
|
|
19
21
|
export declare function getTestOrgUser(): IUser;
|
|
20
22
|
export declare function getTestOrgUserContext(): IUserContext;
|
|
@@ -9,30 +9,35 @@ export function setTestMetaOrgUserId(userId) {
|
|
|
9
9
|
export const TEST_META_ORG_USER_PASSWORD = "test-meta-org-user-password";
|
|
10
10
|
export const TEST_META_ORG_DOMAIN = "test-meta-org.example.com";
|
|
11
11
|
export const TEST_ORG_DOMAIN = "test-org.example.com";
|
|
12
|
-
export function getRefererUrlForOrg(
|
|
13
|
-
if (!
|
|
12
|
+
export function getRefererUrlForOrg(domain) {
|
|
13
|
+
if (!domain) {
|
|
14
14
|
throw new Error("Organization domain is required for auth referer URL");
|
|
15
15
|
}
|
|
16
|
-
return `https://${
|
|
16
|
+
return `https://${domain}`;
|
|
17
17
|
}
|
|
18
18
|
export function getTestMetaOrgRefererUrl() {
|
|
19
|
-
return getRefererUrlForOrg(
|
|
19
|
+
return getRefererUrlForOrg(TEST_META_ORG_DOMAIN);
|
|
20
20
|
}
|
|
21
21
|
export function getTestOrgRefererUrl() {
|
|
22
|
-
return getRefererUrlForOrg(
|
|
22
|
+
return getRefererUrlForOrg(TEST_ORG_DOMAIN);
|
|
23
23
|
}
|
|
24
24
|
export function getTestMetaOrg() {
|
|
25
25
|
return {
|
|
26
26
|
_id: TEST_META_ORG_ID,
|
|
27
27
|
name: "Test Meta Organization",
|
|
28
28
|
code: "test-meta-org",
|
|
29
|
-
domain: TEST_META_ORG_DOMAIN,
|
|
30
29
|
status: 1,
|
|
31
30
|
isMetaOrg: true,
|
|
32
31
|
_created: new Date(),
|
|
33
32
|
_createdBy: "system",
|
|
34
33
|
};
|
|
35
34
|
}
|
|
35
|
+
export function getTestMetaOrgDomain(organizationId = TEST_META_ORG_ID) {
|
|
36
|
+
return {
|
|
37
|
+
organizationId,
|
|
38
|
+
domain: TEST_META_ORG_DOMAIN,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
36
41
|
export function getTestMetaOrgUser() {
|
|
37
42
|
return {
|
|
38
43
|
_id: TEST_META_ORG_USER_ID,
|
|
@@ -73,13 +78,18 @@ export function getTestOrg() {
|
|
|
73
78
|
_id: TEST_ORG_ID,
|
|
74
79
|
name: "Test Organization",
|
|
75
80
|
code: "test-org",
|
|
76
|
-
domain: TEST_ORG_DOMAIN,
|
|
77
81
|
status: 1,
|
|
78
82
|
isMetaOrg: false,
|
|
79
83
|
_created: new Date(),
|
|
80
84
|
_createdBy: "system",
|
|
81
85
|
};
|
|
82
86
|
}
|
|
87
|
+
export function getTestOrgDomain(organizationId = TEST_ORG_ID) {
|
|
88
|
+
return {
|
|
89
|
+
organizationId,
|
|
90
|
+
domain: TEST_ORG_DOMAIN,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
83
93
|
export const TEST_ORG_USER_PASSWORD = "test-org-user-password";
|
|
84
94
|
export function getTestOrgUser() {
|
|
85
95
|
return {
|
|
@@ -38,9 +38,7 @@ export class AuthController {
|
|
|
38
38
|
if (!referer) {
|
|
39
39
|
throw new BadRequestError("Missing required fields: referer is required.");
|
|
40
40
|
}
|
|
41
|
-
organization = await this.organizationService.
|
|
42
|
-
filters: { domain: { eq: referer.split("/")[2] } },
|
|
43
|
-
});
|
|
41
|
+
organization = await this.organizationService.findByDomain(EmptyUserContext, referer.split("/")[2]);
|
|
44
42
|
if (!organization) {
|
|
45
43
|
throw new BadRequestError("Missing required fields: organization is required.");
|
|
46
44
|
}
|
|
@@ -96,9 +94,7 @@ export class AuthController {
|
|
|
96
94
|
referer = referer.replace(/\/$/, "");
|
|
97
95
|
let organization = null;
|
|
98
96
|
if (config.app.isMultiTenant) {
|
|
99
|
-
organization = await this.organizationService.
|
|
100
|
-
filters: { domain: { eq: referer.split("/")[2] } },
|
|
101
|
-
});
|
|
97
|
+
organization = await this.organizationService.findByDomain(EmptyUserContext, referer.split("/")[2]);
|
|
102
98
|
if (!organization) {
|
|
103
99
|
throw new BadRequestError("Missing required fields: organization is required.");
|
|
104
100
|
}
|
|
@@ -126,9 +122,7 @@ export class AuthController {
|
|
|
126
122
|
if (!referer) {
|
|
127
123
|
throw new BadRequestError("Missing required fields: referer is required.");
|
|
128
124
|
}
|
|
129
|
-
organization = await this.organizationService.
|
|
130
|
-
filters: { domain: { eq: referer.split("/")[2] } },
|
|
131
|
-
});
|
|
125
|
+
organization = await this.organizationService.findByDomain(EmptyUserContext, referer.split("/")[2]);
|
|
132
126
|
if (!organization) {
|
|
133
127
|
throw new BadRequestError("Missing required fields: organization is required.");
|
|
134
128
|
}
|
|
@@ -9,7 +9,7 @@ export const getMongoInitialSchema = (dbConfig) => {
|
|
|
9
9
|
throw new Error("Multi-tenant configuration is enabled but multi-tenant configuration is not provided");
|
|
10
10
|
}
|
|
11
11
|
const isAuthEnabled = dbConfig.app.isAuthEnabled;
|
|
12
|
-
if (isMultiTenant)
|
|
12
|
+
if (isMultiTenant) {
|
|
13
13
|
migrations.push({
|
|
14
14
|
name: "00000000000001_schema-organizations",
|
|
15
15
|
up: async ({ context: db }) => {
|
|
@@ -26,6 +26,22 @@ export const getMongoInitialSchema = (dbConfig) => {
|
|
|
26
26
|
await db.collection("organizations").drop();
|
|
27
27
|
},
|
|
28
28
|
});
|
|
29
|
+
migrations.push({
|
|
30
|
+
name: "00000000000001_schema-organizations-domains",
|
|
31
|
+
up: async ({ context: db }) => {
|
|
32
|
+
await db.createCollection("organization_domains");
|
|
33
|
+
await db
|
|
34
|
+
.collection("organization_domains")
|
|
35
|
+
.createIndex({ domain: 1 }, { unique: true });
|
|
36
|
+
await db
|
|
37
|
+
.collection("organization_domains")
|
|
38
|
+
.createIndex({ organizationId: 1 });
|
|
39
|
+
},
|
|
40
|
+
down: async ({ context: db }) => {
|
|
41
|
+
await db.collection("organization_domains").drop();
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
}
|
|
29
45
|
if (isAuthEnabled)
|
|
30
46
|
migrations.push({
|
|
31
47
|
name: "00000000000002_schema-users",
|
|
@@ -201,9 +217,21 @@ export const getMongoInitialSchema = (dbConfig) => {
|
|
|
201
217
|
...metaOrgDoc,
|
|
202
218
|
_id: result.insertedId,
|
|
203
219
|
};
|
|
220
|
+
const metaOrgDomains = dbConfig.multiTenant.metaOrgDomains ?? [];
|
|
221
|
+
if (metaOrgDomains.length > 0) {
|
|
222
|
+
await db.collection("organization_domains").insertMany(metaOrgDomains.map((domain) => ({
|
|
223
|
+
organizationId: metaOrg._id,
|
|
224
|
+
domain,
|
|
225
|
+
_created: new Date(),
|
|
226
|
+
_createdBy: "system",
|
|
227
|
+
_updated: new Date(),
|
|
228
|
+
_updatedBy: "system",
|
|
229
|
+
})));
|
|
230
|
+
}
|
|
204
231
|
initializeSystemUserContext(dbConfig.email?.systemEmailAddress || "system@example.com", metaOrg);
|
|
205
232
|
},
|
|
206
233
|
down: async ({ context: db }) => {
|
|
234
|
+
await db.collection("organization_domains").deleteMany({});
|
|
207
235
|
await db.collection("organizations").deleteMany({ isMetaOrg: true });
|
|
208
236
|
},
|
|
209
237
|
});
|
|
@@ -8,7 +8,7 @@ export async function runInitialSchemaMigrations(pool, config) {
|
|
|
8
8
|
app: config.app,
|
|
9
9
|
database: config.database,
|
|
10
10
|
adminUser: config.adminUser ?? { email: 'admin@test.com', password: 'admin-password' },
|
|
11
|
-
multiTenant: config.multiTenant ?? (config.app.isMultiTenant ? { metaOrgName: 'Test Meta Organization', metaOrgCode: 'TEST_META_ORG',
|
|
11
|
+
multiTenant: config.multiTenant ?? (config.app.isMultiTenant ? { metaOrgName: 'Test Meta Organization', metaOrgCode: 'TEST_META_ORG', metaOrgDomains: [TEST_META_ORG_DOMAIN] } : { metaOrgName: '', metaOrgCode: '', metaOrgDomains: [] }),
|
|
12
12
|
email: config.email,
|
|
13
13
|
};
|
|
14
14
|
const initialSchema = getPostgresInitialSchema(migrationConfig);
|
|
@@ -22,7 +22,7 @@ export async function runInitialSchemaMigrations(pool, config) {
|
|
|
22
22
|
down: async () => {
|
|
23
23
|
await m.down({ context: pool });
|
|
24
24
|
}
|
|
25
|
-
}));
|
|
25
|
+
})).sort((a, b) => a.name.localeCompare(b.name));
|
|
26
26
|
},
|
|
27
27
|
context: pool,
|
|
28
28
|
storage: {
|
|
@@ -54,7 +54,7 @@ export async function runTestSchemaMigrations(pool, config) {
|
|
|
54
54
|
down: async () => {
|
|
55
55
|
await m.down({ context: pool });
|
|
56
56
|
}
|
|
57
|
-
}));
|
|
57
|
+
})).sort((a, b) => a.name.localeCompare(b.name));
|
|
58
58
|
},
|
|
59
59
|
context: pool,
|
|
60
60
|
storage: {
|
|
@@ -34,7 +34,6 @@ export const getPostgresInitialSchema = (dbConfig) => {
|
|
|
34
34
|
"_id" INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
35
35
|
"name" VARCHAR(255) NOT NULL UNIQUE,
|
|
36
36
|
"code" VARCHAR(255) UNIQUE,
|
|
37
|
-
"domain" VARCHAR(255) UNIQUE,
|
|
38
37
|
"description" TEXT,
|
|
39
38
|
"status" INTEGER NOT NULL,
|
|
40
39
|
"is_meta_org" BOOLEAN NOT NULL,
|
|
@@ -52,6 +51,29 @@ export const getPostgresInitialSchema = (dbConfig) => {
|
|
|
52
51
|
await pool.query('DROP TABLE IF EXISTS "organizations"');
|
|
53
52
|
},
|
|
54
53
|
});
|
|
54
|
+
migrations.push({
|
|
55
|
+
name: "00000000000002_schema-organizations-domains",
|
|
56
|
+
up: async ({ context: pool }) => {
|
|
57
|
+
await pool.query(`
|
|
58
|
+
CREATE TABLE IF NOT EXISTS "organization_domains" (
|
|
59
|
+
"_id" INTEGER GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
|
|
60
|
+
"organization_id" INTEGER NOT NULL,
|
|
61
|
+
"domain" VARCHAR(255) NOT NULL UNIQUE,
|
|
62
|
+
"_created" TIMESTAMPTZ NOT NULL,
|
|
63
|
+
"_createdBy" INTEGER NOT NULL,
|
|
64
|
+
"_updated" TIMESTAMPTZ,
|
|
65
|
+
"_updatedBy" INTEGER,
|
|
66
|
+
"_deleted" TIMESTAMPTZ,
|
|
67
|
+
"_deletedBy" INTEGER,
|
|
68
|
+
CONSTRAINT "fk_organization_domains_organization"
|
|
69
|
+
FOREIGN KEY("organization_id") REFERENCES "organizations"("_id") ON DELETE CASCADE
|
|
70
|
+
)
|
|
71
|
+
`);
|
|
72
|
+
},
|
|
73
|
+
down: async ({ context: pool }) => {
|
|
74
|
+
await pool.query('DROP TABLE IF EXISTS "organization_domains"');
|
|
75
|
+
},
|
|
76
|
+
});
|
|
55
77
|
}
|
|
56
78
|
if (isAuthEnabled)
|
|
57
79
|
migrations.push({
|
|
@@ -252,18 +274,25 @@ export const getPostgresInitialSchema = (dbConfig) => {
|
|
|
252
274
|
name: "00000000000010_data-meta-org",
|
|
253
275
|
up: async ({ context: pool }) => {
|
|
254
276
|
const result = await pool.query(`
|
|
255
|
-
INSERT INTO "organizations"("name", "code", "
|
|
256
|
-
VALUES($1, $2,
|
|
257
|
-
RETURNING "_id", "name", "code", "
|
|
277
|
+
INSERT INTO "organizations"("name", "code", "status", "is_meta_org", "_created", "_createdBy")
|
|
278
|
+
VALUES($1, $2, 1, true, NOW(), 0)
|
|
279
|
+
RETURNING "_id", "name", "code", "status", "is_meta_org", "_created", "_createdBy"
|
|
258
280
|
`, [
|
|
259
281
|
dbConfig.multiTenant?.metaOrgName,
|
|
260
282
|
dbConfig.multiTenant?.metaOrgCode,
|
|
261
|
-
dbConfig.multiTenant?.metaOrgDomain,
|
|
262
283
|
]);
|
|
263
284
|
if (result.rowCount === 0) {
|
|
264
285
|
throw new Error("Failed to create meta organization");
|
|
265
286
|
}
|
|
266
|
-
|
|
287
|
+
const metaOrg = result.rows[0];
|
|
288
|
+
const metaOrgDomains = dbConfig.multiTenant?.metaOrgDomains ?? [];
|
|
289
|
+
for (const domain of metaOrgDomains) {
|
|
290
|
+
await pool.query(`
|
|
291
|
+
INSERT INTO "organization_domains"("organization_id", "domain", "_created", "_createdBy")
|
|
292
|
+
VALUES($1, $2, NOW(), 0)
|
|
293
|
+
`, [metaOrg._id, domain]);
|
|
294
|
+
}
|
|
295
|
+
initializeSystemUserContext(dbConfig.email?.systemEmailAddress || "system@example.com", metaOrg);
|
|
267
296
|
},
|
|
268
297
|
down: async ({ context: pool }) => {
|
|
269
298
|
await pool.query(`DELETE FROM "organizations" WHERE "is_meta_org" = TRUE`);
|
package/dist/services/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export * from "./generic-query-service/generic-query.service.js";
|
|
|
5
5
|
export * from "./generic-query-service/generic-query-service.interface.js";
|
|
6
6
|
export * from "./multi-tenant-api.service.js";
|
|
7
7
|
export * from "./organization.service.js";
|
|
8
|
+
export * from "./organization-domain.service.js";
|
|
8
9
|
export * from "./password-reset-token.service.js";
|
|
9
10
|
export * from "./refresh-token.service.js";
|
|
10
11
|
export * from "./tenant-query-decorator.js";
|
package/dist/services/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export * from "./generic-query-service/generic-query.service.js";
|
|
|
5
5
|
export * from "./generic-query-service/generic-query-service.interface.js";
|
|
6
6
|
export * from "./multi-tenant-api.service.js";
|
|
7
7
|
export * from "./organization.service.js";
|
|
8
|
+
export * from "./organization-domain.service.js";
|
|
8
9
|
export * from "./password-reset-token.service.js";
|
|
9
10
|
export * from "./refresh-token.service.js";
|
|
10
11
|
export * from "./tenant-query-decorator.js";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type IOrganizationDomain } from "@loomcore/common/models";
|
|
2
|
+
import type { IDatabase } from "../databases/models/index.js";
|
|
3
|
+
import { GenericApiService } from "./generic-api-service/generic-api.service.js";
|
|
4
|
+
export declare class OrganizationDomainService extends GenericApiService<IOrganizationDomain> {
|
|
5
|
+
constructor(database: IDatabase);
|
|
6
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { OrganizationDomainSpec, } from "@loomcore/common/models";
|
|
2
|
+
import { GenericApiService } from "./generic-api-service/generic-api.service.js";
|
|
3
|
+
export class OrganizationDomainService extends GenericApiService {
|
|
4
|
+
constructor(database) {
|
|
5
|
+
super(database, "organization_domains", "organization_domain", OrganizationDomainSpec);
|
|
6
|
+
}
|
|
7
|
+
}
|
|
@@ -3,9 +3,11 @@ import type { AppIdType } from "@loomcore/common/types";
|
|
|
3
3
|
import type { IDatabase } from "../databases/models/index.js";
|
|
4
4
|
import { GenericApiService } from "./generic-api-service/generic-api.service.js";
|
|
5
5
|
export declare class OrganizationService extends GenericApiService<IOrganization> {
|
|
6
|
+
private organizationDomainService;
|
|
6
7
|
constructor(database: IDatabase);
|
|
7
8
|
preProcessEntity(userContext: IUserContext, entity: Partial<IOrganization>, isCreate: boolean, allowId?: boolean): Promise<Partial<IOrganization>>;
|
|
8
9
|
getAuthTokenByRepoCode(userContext: IUserContext, orgId: AppIdType): Promise<string | null>;
|
|
9
10
|
validateRepoAuthToken(userContext: IUserContext, orgCode: string, authToken: string): Promise<AppIdType | null>;
|
|
10
11
|
getMetaOrg(userContext: IUserContext): Promise<IOrganization | null>;
|
|
12
|
+
findByDomain(userContext: IUserContext, domain: string): Promise<IOrganization | null>;
|
|
11
13
|
}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { OrganizationSpec, } from "@loomcore/common/models";
|
|
2
2
|
import { BadRequestError } from "../errors/index.js";
|
|
3
3
|
import { GenericApiService } from "./generic-api-service/generic-api.service.js";
|
|
4
|
+
import { OrganizationDomainService } from "./organization-domain.service.js";
|
|
4
5
|
export class OrganizationService extends GenericApiService {
|
|
6
|
+
organizationDomainService;
|
|
5
7
|
constructor(database) {
|
|
6
8
|
super(database, "organizations", "organization", OrganizationSpec);
|
|
9
|
+
this.organizationDomainService = new OrganizationDomainService(database);
|
|
7
10
|
}
|
|
8
11
|
async preProcessEntity(userContext, entity, isCreate, allowId = true) {
|
|
9
12
|
if (isCreate) {
|
|
@@ -38,4 +41,15 @@ export class OrganizationService extends GenericApiService {
|
|
|
38
41
|
});
|
|
39
42
|
return org;
|
|
40
43
|
}
|
|
44
|
+
async findByDomain(userContext, domain) {
|
|
45
|
+
const organizationDomain = await this.organizationDomainService.findOne(userContext, {
|
|
46
|
+
filters: { domain: { eq: domain } },
|
|
47
|
+
});
|
|
48
|
+
if (!organizationDomain) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
return this.findOne(userContext, {
|
|
52
|
+
filters: { _id: { eq: organizationDomain.organizationId } },
|
|
53
|
+
});
|
|
54
|
+
}
|
|
41
55
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loomcore/api",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.14",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Loom Core Api - An opinionated Node.js api using Typescript, Express, and MongoDb or PostgreSQL",
|
|
6
6
|
"scripts": {
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"qs": "^6.15.2"
|
|
59
59
|
},
|
|
60
60
|
"peerDependencies": {
|
|
61
|
-
"@loomcore/common": "^0.0.
|
|
61
|
+
"@loomcore/common": "^0.0.77",
|
|
62
62
|
"@sinclair/typebox": "0.34.33",
|
|
63
63
|
"cookie-parser": "^1.4.6",
|
|
64
64
|
"cors": "^2.8.5",
|