@loomcore/api 0.1.12 → 0.1.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 +18 -17
- package/dist/__tests__/mongo-db.test-database.d.ts +1 -1
- package/dist/__tests__/mongo-db.test-database.js +3 -3
- package/dist/__tests__/postgres.test-database.d.ts +1 -1
- package/dist/__tests__/postgres.test-database.js +4 -4
- package/dist/__tests__/test-database.interface.d.ts +1 -1
- package/dist/__tests__/test-express-app.js +2 -2
- package/dist/__tests__/test-objects.d.ts +23 -5
- package/dist/__tests__/test-objects.js +40 -18
- package/dist/controllers/auth.controller.js +1 -1
- package/dist/databases/postgres/migrations/001-create-migrations-table.migration.js +1 -4
- package/dist/databases/postgres/migrations/006-create-admin-user.migration.d.ts +20 -0
- package/dist/databases/postgres/migrations/006-create-admin-user.migration.js +52 -0
- package/dist/databases/postgres/migrations/setup-for-auth.migration.d.ts +1 -1
- package/dist/databases/postgres/migrations/setup-for-auth.migration.js +4 -1
- package/dist/services/organization.service.d.ts +1 -0
- package/dist/services/organization.service.js +14 -0
- package/package.json +1 -1
|
@@ -10,7 +10,7 @@ import { OrganizationService } from '../services/organization.service.js';
|
|
|
10
10
|
import { IdNotFoundError } from '../errors/index.js';
|
|
11
11
|
import { AuthService, GenericApiService } from '../services/index.js';
|
|
12
12
|
import { ObjectId } from 'mongodb';
|
|
13
|
-
import { testMetaOrg, testOrg,
|
|
13
|
+
import { testMetaOrg, testOrg, getTestMetaOrgUser, testMetaOrgUserContext } from './test-objects.js';
|
|
14
14
|
import { CategorySpec } from './models/category.model.js';
|
|
15
15
|
import { ProductSpec } from './models/product.model.js';
|
|
16
16
|
let deviceIdCookie;
|
|
@@ -33,9 +33,9 @@ async function createMetaOrg() {
|
|
|
33
33
|
throw new Error('OrganizationService not initialized. Call initialize() first.');
|
|
34
34
|
}
|
|
35
35
|
try {
|
|
36
|
-
const existingMetaOrg = await organizationService.findOne(
|
|
36
|
+
const existingMetaOrg = await organizationService.findOne(testMetaOrgUserContext, { filters: { isMetaOrg: { eq: true } } });
|
|
37
37
|
if (!existingMetaOrg) {
|
|
38
|
-
const metaOrgInsertResult = await organizationService.create(
|
|
38
|
+
const metaOrgInsertResult = await organizationService.create(testMetaOrgUserContext, testMetaOrg);
|
|
39
39
|
}
|
|
40
40
|
}
|
|
41
41
|
catch (error) {
|
|
@@ -48,7 +48,7 @@ async function deleteMetaOrg() {
|
|
|
48
48
|
return Promise.resolve();
|
|
49
49
|
}
|
|
50
50
|
try {
|
|
51
|
-
await organizationService.deleteMany(
|
|
51
|
+
await organizationService.deleteMany(testMetaOrgUserContext, { filters: { isMetaOrg: { eq: true } } });
|
|
52
52
|
}
|
|
53
53
|
catch (error) {
|
|
54
54
|
console.log('Error deleting meta org:', error);
|
|
@@ -69,23 +69,23 @@ async function createTestUser() {
|
|
|
69
69
|
throw new Error('Database not initialized. Call initialize() first.');
|
|
70
70
|
}
|
|
71
71
|
try {
|
|
72
|
-
let
|
|
72
|
+
let existingMetaOrg;
|
|
73
73
|
try {
|
|
74
|
-
|
|
74
|
+
existingMetaOrg = await organizationService.getMetaOrg(testMetaOrgUserContext);
|
|
75
75
|
}
|
|
76
76
|
catch (error) {
|
|
77
77
|
if (error instanceof IdNotFoundError) {
|
|
78
|
-
|
|
78
|
+
existingMetaOrg = null;
|
|
79
79
|
}
|
|
80
80
|
else {
|
|
81
81
|
throw error;
|
|
82
82
|
}
|
|
83
83
|
}
|
|
84
|
-
if (!
|
|
85
|
-
await organizationService.create(
|
|
84
|
+
if (!existingMetaOrg) {
|
|
85
|
+
await organizationService.create(testMetaOrgUserContext, testMetaOrg);
|
|
86
86
|
}
|
|
87
87
|
const systemUserContext = getSystemUserContext();
|
|
88
|
-
const createdUser = await authService.createUser(systemUserContext,
|
|
88
|
+
const createdUser = await authService.createUser(systemUserContext, getTestMetaOrgUser());
|
|
89
89
|
if (!createdUser) {
|
|
90
90
|
throw new Error('Failed to create test user');
|
|
91
91
|
}
|
|
@@ -97,10 +97,10 @@ async function createTestUser() {
|
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
async function deleteTestUser() {
|
|
100
|
-
await authService.deleteById(
|
|
100
|
+
await authService.deleteById(testMetaOrgUserContext, getTestMetaOrgUser()._id).catch((error) => {
|
|
101
101
|
return null;
|
|
102
102
|
});
|
|
103
|
-
await organizationService.deleteById(
|
|
103
|
+
await organizationService.deleteById(testMetaOrgUserContext, testOrg._id).catch((error) => {
|
|
104
104
|
return null;
|
|
105
105
|
});
|
|
106
106
|
}
|
|
@@ -119,19 +119,20 @@ async function simulateloginWithTestUser() {
|
|
|
119
119
|
return res;
|
|
120
120
|
}
|
|
121
121
|
};
|
|
122
|
-
const loginResponse = await authService.attemptLogin(req, res,
|
|
122
|
+
const loginResponse = await authService.attemptLogin(req, res, getTestMetaOrgUser().email, getTestMetaOrgUser().password);
|
|
123
123
|
if (!loginResponse?.tokens?.accessToken) {
|
|
124
124
|
throw new Error('Failed to login with test user');
|
|
125
125
|
}
|
|
126
126
|
return `Bearer ${loginResponse.tokens.accessToken}`;
|
|
127
127
|
}
|
|
128
128
|
function getAuthToken() {
|
|
129
|
+
const metaOrgUser = getTestMetaOrgUser();
|
|
129
130
|
const payload = {
|
|
130
131
|
user: {
|
|
131
|
-
_id:
|
|
132
|
-
email:
|
|
132
|
+
_id: metaOrgUser._id,
|
|
133
|
+
email: metaOrgUser.email
|
|
133
134
|
},
|
|
134
|
-
_orgId:
|
|
135
|
+
_orgId: metaOrgUser._orgId
|
|
135
136
|
};
|
|
136
137
|
const token = JwtService.sign(payload, JWT_SECRET, { expiresIn: 3600 });
|
|
137
138
|
return `Bearer ${token}`;
|
|
@@ -226,7 +227,7 @@ function configureJwtSecret() {
|
|
|
226
227
|
}
|
|
227
228
|
async function loginWithTestUser(agent) {
|
|
228
229
|
agent.set('Cookie', [`deviceId=${deviceIdCookie}`]);
|
|
229
|
-
const testUser =
|
|
230
|
+
const testUser = getTestMetaOrgUser();
|
|
230
231
|
const response = await agent
|
|
231
232
|
.post('/api/auth/login')
|
|
232
233
|
.send({
|
|
@@ -6,7 +6,7 @@ export declare class TestMongoDatabase implements ITestDatabase {
|
|
|
6
6
|
private mongoDb;
|
|
7
7
|
private database;
|
|
8
8
|
private initPromise;
|
|
9
|
-
init(
|
|
9
|
+
init(): Promise<IDatabase>;
|
|
10
10
|
getRandomId(): string;
|
|
11
11
|
private _performInit;
|
|
12
12
|
private createIndexes;
|
|
@@ -9,17 +9,17 @@ export class TestMongoDatabase {
|
|
|
9
9
|
mongoDb = null;
|
|
10
10
|
database = null;
|
|
11
11
|
initPromise = null;
|
|
12
|
-
async init(
|
|
12
|
+
async init() {
|
|
13
13
|
if (this.initPromise) {
|
|
14
14
|
return this.initPromise;
|
|
15
15
|
}
|
|
16
|
-
this.initPromise = this._performInit(
|
|
16
|
+
this.initPromise = this._performInit();
|
|
17
17
|
return this.initPromise;
|
|
18
18
|
}
|
|
19
19
|
getRandomId() {
|
|
20
20
|
return new ObjectId().toString();
|
|
21
21
|
}
|
|
22
|
-
async _performInit(
|
|
22
|
+
async _performInit() {
|
|
23
23
|
if (!this.database) {
|
|
24
24
|
this.mongoServer = await MongoMemoryServer.create({
|
|
25
25
|
instance: {
|
|
@@ -4,7 +4,7 @@ export declare class TestPostgresDatabase implements ITestDatabase {
|
|
|
4
4
|
private database;
|
|
5
5
|
private postgresClient;
|
|
6
6
|
private initPromise;
|
|
7
|
-
init(
|
|
7
|
+
init(adminUsername?: string, adminPassword?: string): Promise<IDatabase>;
|
|
8
8
|
getRandomId(): string;
|
|
9
9
|
private _performInit;
|
|
10
10
|
private createIndexes;
|
|
@@ -11,17 +11,17 @@ export class TestPostgresDatabase {
|
|
|
11
11
|
database = null;
|
|
12
12
|
postgresClient = null;
|
|
13
13
|
initPromise = null;
|
|
14
|
-
async init(
|
|
14
|
+
async init(adminUsername, adminPassword) {
|
|
15
15
|
if (this.initPromise) {
|
|
16
16
|
return this.initPromise;
|
|
17
17
|
}
|
|
18
|
-
this.initPromise = this._performInit(
|
|
18
|
+
this.initPromise = this._performInit(adminUsername, adminPassword);
|
|
19
19
|
return this.initPromise;
|
|
20
20
|
}
|
|
21
21
|
getRandomId() {
|
|
22
22
|
return randomUUID();
|
|
23
23
|
}
|
|
24
|
-
async _performInit(
|
|
24
|
+
async _performInit(adminUsername, adminPassword) {
|
|
25
25
|
if (!this.database) {
|
|
26
26
|
const { Client } = newDb().adapters.createPg();
|
|
27
27
|
const postgresClient = new Client();
|
|
@@ -33,7 +33,7 @@ export class TestPostgresDatabase {
|
|
|
33
33
|
if (!success) {
|
|
34
34
|
throw new Error('Failed to setup for multitenant');
|
|
35
35
|
}
|
|
36
|
-
success = (await setupDatabaseForAuth(postgresClient, testOrg._id)).success;
|
|
36
|
+
success = (await setupDatabaseForAuth(postgresClient, adminUsername || 'admin', adminPassword || 'password', testOrg._id)).success;
|
|
37
37
|
if (!success) {
|
|
38
38
|
throw new Error('Failed to setup for auth');
|
|
39
39
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { IDatabase } from "../databases/models/index.js";
|
|
2
2
|
export type ITestDatabase = {
|
|
3
|
-
init(
|
|
3
|
+
init(adminUsername?: string, adminPassword?: string): Promise<IDatabase>;
|
|
4
4
|
getRandomId(): string;
|
|
5
5
|
clearCollections(): Promise<void>;
|
|
6
6
|
cleanup(): Promise<void>;
|
|
@@ -61,12 +61,12 @@ export class TestExpressApp {
|
|
|
61
61
|
if (useMongoDb) {
|
|
62
62
|
const testMongoDb = new TestMongoDatabase();
|
|
63
63
|
this.testDatabase = testMongoDb;
|
|
64
|
-
this.database = await testMongoDb.init(
|
|
64
|
+
this.database = await testMongoDb.init();
|
|
65
65
|
}
|
|
66
66
|
else {
|
|
67
67
|
const testPostgresDb = new TestPostgresDatabase();
|
|
68
68
|
this.testDatabase = testPostgresDb;
|
|
69
|
-
this.database = await testPostgresDb.init(
|
|
69
|
+
this.database = await testPostgresDb.init('admin', 'password');
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
if (!this.app) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { IOrganization,
|
|
2
|
-
export declare const
|
|
3
|
-
export declare function
|
|
1
|
+
import { IOrganization, IUserContext } from "@loomcore/common/models";
|
|
2
|
+
export declare const testMetaOrg: IOrganization;
|
|
3
|
+
export declare function getTestMetaOrgUser(): {
|
|
4
4
|
email: string;
|
|
5
5
|
firstName?: string;
|
|
6
6
|
lastName?: string;
|
|
@@ -18,6 +18,24 @@ export declare function getTestUser(): {
|
|
|
18
18
|
_id: string;
|
|
19
19
|
_orgId?: string;
|
|
20
20
|
};
|
|
21
|
-
export declare const
|
|
22
|
-
export declare const testMetaOrg: IOrganization;
|
|
21
|
+
export declare const testMetaOrgUserContext: IUserContext;
|
|
23
22
|
export declare const testOrg: IOrganization;
|
|
23
|
+
export declare function getTestOrgUser(): {
|
|
24
|
+
email: string;
|
|
25
|
+
firstName?: string;
|
|
26
|
+
lastName?: string;
|
|
27
|
+
displayName?: string;
|
|
28
|
+
password: string;
|
|
29
|
+
roles?: string[];
|
|
30
|
+
_lastLoggedIn?: Date;
|
|
31
|
+
_lastPasswordChange?: Date;
|
|
32
|
+
_created: Date;
|
|
33
|
+
_createdBy: string;
|
|
34
|
+
_updated: Date;
|
|
35
|
+
_updatedBy: string;
|
|
36
|
+
_deleted?: Date;
|
|
37
|
+
_deletedBy?: string;
|
|
38
|
+
_id: string;
|
|
39
|
+
_orgId?: string;
|
|
40
|
+
};
|
|
41
|
+
export declare const testOrgUserContext: IUserContext;
|
|
@@ -1,4 +1,15 @@
|
|
|
1
|
-
export const
|
|
1
|
+
export const testMetaOrg = {
|
|
2
|
+
_id: '69261691f936c45f85da24d0',
|
|
3
|
+
name: 'Test Meta Organization',
|
|
4
|
+
code: 'test-meta-org',
|
|
5
|
+
status: 1,
|
|
6
|
+
isMetaOrg: true,
|
|
7
|
+
_created: new Date(),
|
|
8
|
+
_createdBy: 'system',
|
|
9
|
+
_updated: new Date(),
|
|
10
|
+
_updatedBy: 'system',
|
|
11
|
+
};
|
|
12
|
+
const testMetaOrgUser = {
|
|
2
13
|
_id: '69261672f48fb7bf76e54dfb',
|
|
3
14
|
email: 'test@example.com',
|
|
4
15
|
password: 'testpassword',
|
|
@@ -6,7 +17,7 @@ export const testUser = {
|
|
|
6
17
|
lastName: 'User',
|
|
7
18
|
displayName: 'Test User',
|
|
8
19
|
roles: ['user'],
|
|
9
|
-
_orgId:
|
|
20
|
+
_orgId: testMetaOrg._id,
|
|
10
21
|
_created: new Date(),
|
|
11
22
|
_createdBy: 'system',
|
|
12
23
|
_lastLoggedIn: new Date(),
|
|
@@ -14,23 +25,12 @@ export const testUser = {
|
|
|
14
25
|
_updated: new Date(),
|
|
15
26
|
_updatedBy: 'system',
|
|
16
27
|
};
|
|
17
|
-
export function
|
|
18
|
-
return { ...
|
|
28
|
+
export function getTestMetaOrgUser() {
|
|
29
|
+
return { ...testMetaOrgUser };
|
|
19
30
|
}
|
|
20
|
-
export const
|
|
21
|
-
user:
|
|
22
|
-
_orgId:
|
|
23
|
-
};
|
|
24
|
-
export const testMetaOrg = {
|
|
25
|
-
_id: '69261691f936c45f85da24d0',
|
|
26
|
-
name: 'Test Meta Organization',
|
|
27
|
-
code: 'test-meta-org',
|
|
28
|
-
status: 1,
|
|
29
|
-
isMetaOrg: true,
|
|
30
|
-
_created: new Date(),
|
|
31
|
-
_createdBy: 'system',
|
|
32
|
-
_updated: new Date(),
|
|
33
|
-
_updatedBy: 'system',
|
|
31
|
+
export const testMetaOrgUserContext = {
|
|
32
|
+
user: getTestMetaOrgUser(),
|
|
33
|
+
_orgId: testMetaOrg._id,
|
|
34
34
|
};
|
|
35
35
|
export const testOrg = {
|
|
36
36
|
_id: '6926167d06c0073a778a124f',
|
|
@@ -43,3 +43,25 @@ export const testOrg = {
|
|
|
43
43
|
_updated: new Date(),
|
|
44
44
|
_updatedBy: 'system',
|
|
45
45
|
};
|
|
46
|
+
const testOrgUser = {
|
|
47
|
+
_id: '6926167d06c0073a778a1250',
|
|
48
|
+
email: 'test-org-user@example.com',
|
|
49
|
+
password: 'testpassword',
|
|
50
|
+
firstName: 'Test',
|
|
51
|
+
lastName: 'User',
|
|
52
|
+
displayName: 'Test User',
|
|
53
|
+
roles: ['user'],
|
|
54
|
+
_orgId: testOrg._id,
|
|
55
|
+
_created: new Date(),
|
|
56
|
+
_createdBy: 'system',
|
|
57
|
+
_lastLoggedIn: new Date(),
|
|
58
|
+
_updated: new Date(),
|
|
59
|
+
_updatedBy: 'system',
|
|
60
|
+
};
|
|
61
|
+
export function getTestOrgUser() {
|
|
62
|
+
return { ...testOrgUser };
|
|
63
|
+
}
|
|
64
|
+
export const testOrgUserContext = {
|
|
65
|
+
user: getTestOrgUser(),
|
|
66
|
+
_orgId: testOrg._id,
|
|
67
|
+
};
|
|
@@ -13,7 +13,7 @@ export class AuthController {
|
|
|
13
13
|
}
|
|
14
14
|
mapRoutes(app) {
|
|
15
15
|
app.post(`/api/auth/login`, this.login.bind(this), this.afterAuth.bind(this));
|
|
16
|
-
app.post(`/api/auth/register`, this.registerUser.bind(this));
|
|
16
|
+
app.post(`/api/auth/register`, isAuthenticated, this.registerUser.bind(this));
|
|
17
17
|
app.get(`/api/auth/refresh`, this.requestTokenUsingRefreshToken.bind(this));
|
|
18
18
|
app.get(`/api/auth/get-user-context`, isAuthenticated, this.getUserContext.bind(this));
|
|
19
19
|
app.patch(`/api/auth/change-password`, isAuthenticated, this.changePassword.bind(this));
|
|
@@ -19,10 +19,7 @@ export class CreateMigrationTableMigration {
|
|
|
19
19
|
`);
|
|
20
20
|
}
|
|
21
21
|
catch (error) {
|
|
22
|
-
if (error.code
|
|
23
|
-
console.log(`Migrations table already exists`);
|
|
24
|
-
}
|
|
25
|
-
else {
|
|
22
|
+
if (error.code !== '42P07' && !error.data?.error?.includes('already exists')) {
|
|
26
23
|
return { success: false, error: new Error(`Error creating migrations table: ${error.message}`) };
|
|
27
24
|
}
|
|
28
25
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Client } from "pg";
|
|
2
|
+
import { IMigration } from "../index.js";
|
|
3
|
+
export declare class CreateAdminUserMigration implements IMigration {
|
|
4
|
+
private readonly client;
|
|
5
|
+
private readonly adminUsername;
|
|
6
|
+
private readonly adminPassword;
|
|
7
|
+
constructor(client: Client, adminUsername: string, adminPassword: string);
|
|
8
|
+
index: number;
|
|
9
|
+
execute(_orgId?: string): Promise<{
|
|
10
|
+
success: boolean;
|
|
11
|
+
error: Error;
|
|
12
|
+
} | {
|
|
13
|
+
success: boolean;
|
|
14
|
+
error: null;
|
|
15
|
+
}>;
|
|
16
|
+
revert(_orgId?: string): Promise<{
|
|
17
|
+
success: boolean;
|
|
18
|
+
error: Error | null;
|
|
19
|
+
}>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { PostgresDatabase } from "../index.js";
|
|
2
|
+
import { randomUUID } from "crypto";
|
|
3
|
+
import { UserService } from "../../../services/user.service.js";
|
|
4
|
+
import { getSystemUserContext } from "@loomcore/common/models";
|
|
5
|
+
export class CreateAdminUserMigration {
|
|
6
|
+
client;
|
|
7
|
+
adminUsername;
|
|
8
|
+
adminPassword;
|
|
9
|
+
constructor(client, adminUsername, adminPassword) {
|
|
10
|
+
this.client = client;
|
|
11
|
+
this.adminUsername = adminUsername;
|
|
12
|
+
this.adminPassword = adminPassword;
|
|
13
|
+
}
|
|
14
|
+
index = 6;
|
|
15
|
+
async execute(_orgId) {
|
|
16
|
+
const _id = randomUUID().toString();
|
|
17
|
+
try {
|
|
18
|
+
const database = new PostgresDatabase(this.client);
|
|
19
|
+
const userService = new UserService(database);
|
|
20
|
+
const systemUserContext = getSystemUserContext();
|
|
21
|
+
const adminUser = await userService.create(systemUserContext, {
|
|
22
|
+
_id: _id,
|
|
23
|
+
_orgId: _orgId,
|
|
24
|
+
email: this.adminUsername,
|
|
25
|
+
password: this.adminPassword,
|
|
26
|
+
firstName: 'Admin',
|
|
27
|
+
lastName: 'User',
|
|
28
|
+
displayName: 'Admin User',
|
|
29
|
+
roles: ['admin'],
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
return { success: false, error: new Error(`Error creating admin user: ${error.message}`) };
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
const result = await this.client.query(`
|
|
37
|
+
INSERT INTO "migrations" ("_id", "_orgId", "index", "hasRun", "reverted")
|
|
38
|
+
VALUES ('${_id}', '${_orgId}', ${this.index}, TRUE, FALSE);
|
|
39
|
+
`);
|
|
40
|
+
if (result.rowCount === 0) {
|
|
41
|
+
return { success: false, error: new Error(`Error inserting migration ${this.index} to migrations table: No row returned`) };
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
return { success: false, error: new Error(`Error inserting migration ${this.index} to migrations table: ${error.message}`) };
|
|
46
|
+
}
|
|
47
|
+
return { success: true, error: null };
|
|
48
|
+
}
|
|
49
|
+
async revert(_orgId) {
|
|
50
|
+
throw new Error('Not implemented');
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Client } from "pg";
|
|
2
|
-
export declare function setupDatabaseForAuth(client: Client, _orgId?: string): Promise<{
|
|
2
|
+
export declare function setupDatabaseForAuth(client: Client, adminUsername: string, adminPassword: string, _orgId?: string): Promise<{
|
|
3
3
|
success: boolean;
|
|
4
4
|
error: Error | null;
|
|
5
5
|
}>;
|
|
@@ -2,7 +2,8 @@ import { CreateRefreshTokenTableMigration } from "./004-create-refresh-tokens-ta
|
|
|
2
2
|
import { CreateMigrationTableMigration } from "./001-create-migrations-table.migration.js";
|
|
3
3
|
import { CreateUsersTableMigration } from "./003-create-users-table.migration.js";
|
|
4
4
|
import { doesTableExist } from "../utils/does-table-exist.util.js";
|
|
5
|
-
|
|
5
|
+
import { CreateAdminUserMigration } from "./006-create-admin-user.migration.js";
|
|
6
|
+
export async function setupDatabaseForAuth(client, adminUsername, adminPassword, _orgId) {
|
|
6
7
|
let runMigrations = [];
|
|
7
8
|
if (await doesTableExist(client, 'migrations')) {
|
|
8
9
|
const migrations = await client.query(`
|
|
@@ -21,6 +22,8 @@ export async function setupDatabaseForAuth(client, _orgId) {
|
|
|
21
22
|
migrationsToRun.push(new CreateUsersTableMigration(client));
|
|
22
23
|
if (!runMigrations.includes(4))
|
|
23
24
|
migrationsToRun.push(new CreateRefreshTokenTableMigration(client));
|
|
25
|
+
if (!runMigrations.includes(6))
|
|
26
|
+
migrationsToRun.push(new CreateAdminUserMigration(client, adminUsername, adminPassword));
|
|
24
27
|
for (const migration of migrationsToRun) {
|
|
25
28
|
await migration.execute(_orgId);
|
|
26
29
|
}
|
|
@@ -3,6 +3,7 @@ import { IOrganization, IUserContext } from '@loomcore/common/models';
|
|
|
3
3
|
import { IDatabase } from '../databases/models/database.interface.js';
|
|
4
4
|
export declare class OrganizationService extends GenericApiService<IOrganization> {
|
|
5
5
|
constructor(database: IDatabase);
|
|
6
|
+
preprocessEntity(userContext: IUserContext, entity: Partial<IOrganization>, isCreate: boolean, allowId?: boolean): Promise<Partial<IOrganization>>;
|
|
6
7
|
getAuthTokenByRepoCode(userContext: IUserContext, orgId: string): Promise<string | null>;
|
|
7
8
|
validateRepoAuthToken(userContext: IUserContext, orgCode: string, authToken: string): Promise<string | null>;
|
|
8
9
|
getMetaOrg(userContext: IUserContext): Promise<IOrganization | null>;
|
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
import { GenericApiService } from './generic-api-service/generic-api.service.js';
|
|
2
2
|
import { OrganizationSpec } from '@loomcore/common/models';
|
|
3
|
+
import { BadRequestError } from '../errors/index.js';
|
|
3
4
|
export class OrganizationService extends GenericApiService {
|
|
4
5
|
constructor(database) {
|
|
5
6
|
super(database, 'organizations', 'organization', OrganizationSpec);
|
|
6
7
|
}
|
|
8
|
+
async preprocessEntity(userContext, entity, isCreate, allowId = true) {
|
|
9
|
+
if (isCreate) {
|
|
10
|
+
const metaOrg = await this.getMetaOrg(userContext);
|
|
11
|
+
if (metaOrg && entity.isMetaOrg) {
|
|
12
|
+
throw new BadRequestError('Meta organization already exists');
|
|
13
|
+
}
|
|
14
|
+
if (metaOrg && userContext._orgId !== metaOrg._id) {
|
|
15
|
+
throw new BadRequestError('User is not authorized to create an organization');
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
const result = await super.preprocessEntity(userContext, entity, isCreate, allowId);
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
7
21
|
async getAuthTokenByRepoCode(userContext, orgId) {
|
|
8
22
|
const org = await this.getById(userContext, orgId);
|
|
9
23
|
return org?.authToken ?? null;
|