@loomcore/api 0.1.53 → 0.1.57
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.d.ts +8 -2
- package/dist/__tests__/common-test.utils.js +50 -16
- package/dist/__tests__/index.d.ts +0 -1
- package/dist/__tests__/index.js +0 -1
- package/dist/__tests__/postgres-test-migrations/postgres-test-schema.d.ts +3 -0
- package/dist/__tests__/postgres-test-migrations/postgres-test-schema.js +97 -0
- package/dist/__tests__/postgres.test-database.js +9 -8
- package/dist/__tests__/setup/vitest-setup.js +15 -0
- package/dist/__tests__/test-objects.d.ts +6 -3
- package/dist/__tests__/test-objects.js +10 -2
- package/dist/controllers/api.controller.d.ts +2 -0
- package/dist/controllers/api.controller.js +66 -11
- package/dist/databases/migrations/migration-runner.js +6 -6
- package/dist/databases/models/database.interface.d.ts +9 -8
- package/dist/databases/mongo-db/commands/mongo-delete-by-id.command.d.ts +2 -1
- package/dist/databases/mongo-db/commands/mongo-full-updateby-id.command.d.ts +2 -1
- package/dist/databases/mongo-db/commands/mongo-partial-update-by-id.command.d.ts +2 -1
- package/dist/databases/mongo-db/migrations/{mongo-foundational.d.ts → mongo-initial-schema.d.ts} +1 -1
- package/dist/databases/mongo-db/migrations/mongo-initial-schema.js +264 -0
- package/dist/databases/mongo-db/mongo-db.database.d.ts +9 -8
- package/dist/databases/mongo-db/mongo-db.database.js +2 -2
- package/dist/databases/mongo-db/queries/mongo-get-by-id.query.d.ts +2 -1
- package/dist/databases/postgres/commands/postgres-batch-update.command.js +1 -1
- package/dist/databases/postgres/commands/postgres-create-many.command.d.ts +2 -1
- package/dist/databases/postgres/commands/postgres-create-many.command.js +23 -28
- package/dist/databases/postgres/commands/postgres-create.command.d.ts +2 -1
- package/dist/databases/postgres/commands/postgres-create.command.js +6 -5
- package/dist/databases/postgres/commands/postgres-delete-by-id.command.d.ts +2 -1
- package/dist/databases/postgres/commands/postgres-full-update-by-id.command.d.ts +2 -1
- package/dist/databases/postgres/commands/postgres-partial-update-by-id.command.d.ts +2 -1
- package/dist/databases/postgres/migrations/__tests__/test-migration-helper.d.ts +4 -0
- package/dist/databases/postgres/migrations/__tests__/test-migration-helper.js +67 -0
- package/dist/databases/postgres/migrations/index.d.ts +1 -2
- package/dist/databases/postgres/migrations/index.js +1 -2
- package/dist/databases/postgres/migrations/{postgres-foundational.d.ts → postgres-initial-schema.d.ts} +1 -1
- package/dist/databases/postgres/migrations/postgres-initial-schema.js +436 -0
- package/dist/databases/postgres/postgres.database.d.ts +10 -9
- package/dist/databases/postgres/postgres.database.js +2 -2
- package/dist/databases/postgres/queries/postgres-get-by-id.query.d.ts +2 -1
- package/dist/models/refresh-token.model.d.ts +5 -4
- package/dist/models/refresh-token.model.js +3 -3
- package/dist/services/auth.service.d.ts +3 -2
- package/dist/services/auth.service.js +4 -4
- package/dist/services/generic-api-service/generic-api-service.interface.d.ts +8 -7
- package/dist/services/generic-api-service/generic-api.service.d.ts +8 -7
- package/dist/services/generic-api-service/generic-api.service.js +23 -23
- package/dist/services/multi-tenant-api.service.d.ts +1 -1
- package/dist/services/multi-tenant-api.service.js +3 -3
- package/dist/services/organization.service.d.ts +4 -3
- package/dist/services/organization.service.js +3 -3
- package/dist/services/user.service.d.ts +3 -2
- package/dist/services/user.service.js +2 -2
- package/dist/services/utils/audit-for-create.util.js +2 -1
- package/dist/services/utils/audit-for-update.util.js +2 -1
- package/dist/services/utils/strip-sender-provided-system-properties.util.js +2 -1
- package/package.json +2 -2
- package/dist/__tests__/postgres-test-migrations/100-create-test-entities-table.migration.d.ts +0 -21
- package/dist/__tests__/postgres-test-migrations/100-create-test-entities-table.migration.js +0 -61
- package/dist/__tests__/postgres-test-migrations/101-create-categories-table.migration.d.ts +0 -21
- package/dist/__tests__/postgres-test-migrations/101-create-categories-table.migration.js +0 -51
- package/dist/__tests__/postgres-test-migrations/102-create-products-table.migration.d.ts +0 -21
- package/dist/__tests__/postgres-test-migrations/102-create-products-table.migration.js +0 -60
- package/dist/__tests__/postgres-test-migrations/103-create-test-items-table.migration.d.ts +0 -21
- package/dist/__tests__/postgres-test-migrations/103-create-test-items-table.migration.js +0 -59
- package/dist/__tests__/postgres-test-migrations/test-migrations.d.ts +0 -3
- package/dist/__tests__/postgres-test-migrations/test-migrations.js +0 -12
- package/dist/databases/mongo-db/migrations/mongo-foundational.js +0 -30
- package/dist/databases/postgres/migrations/001-create-migrations-table.migration.d.ts +0 -21
- package/dist/databases/postgres/migrations/001-create-migrations-table.migration.js +0 -51
- package/dist/databases/postgres/migrations/002-create-organizations-table.migration.d.ts +0 -21
- package/dist/databases/postgres/migrations/002-create-organizations-table.migration.js +0 -76
- package/dist/databases/postgres/migrations/003-create-users-table.migration.d.ts +0 -21
- package/dist/databases/postgres/migrations/003-create-users-table.migration.js +0 -77
- package/dist/databases/postgres/migrations/004-create-refresh-tokens-table.migration.d.ts +0 -21
- package/dist/databases/postgres/migrations/004-create-refresh-tokens-table.migration.js +0 -72
- package/dist/databases/postgres/migrations/005-create-meta-org.migration.d.ts +0 -22
- package/dist/databases/postgres/migrations/005-create-meta-org.migration.js +0 -64
- package/dist/databases/postgres/migrations/006-create-admin-user.migration.d.ts +0 -19
- package/dist/databases/postgres/migrations/006-create-admin-user.migration.js +0 -52
- package/dist/databases/postgres/migrations/007-create-roles-table.migration.d.ts +0 -21
- package/dist/databases/postgres/migrations/007-create-roles-table.migration.js +0 -65
- package/dist/databases/postgres/migrations/008-create-user-roles-table.migration.d.ts +0 -21
- package/dist/databases/postgres/migrations/008-create-user-roles-table.migration.js +0 -75
- package/dist/databases/postgres/migrations/009-create-features-table.migration.d.ts +0 -21
- package/dist/databases/postgres/migrations/009-create-features-table.migration.js +0 -65
- package/dist/databases/postgres/migrations/010-create-authorizations-table.migration.d.ts +0 -21
- package/dist/databases/postgres/migrations/010-create-authorizations-table.migration.js +0 -77
- package/dist/databases/postgres/migrations/011-create-admin-authorization.migration.d.ts +0 -23
- package/dist/databases/postgres/migrations/011-create-admin-authorization.migration.js +0 -130
- package/dist/databases/postgres/migrations/database-builder.d.ts +0 -15
- package/dist/databases/postgres/migrations/database-builder.interface.d.ts +0 -10
- package/dist/databases/postgres/migrations/database-builder.js +0 -65
- package/dist/databases/postgres/migrations/migration.interface.d.ts +0 -11
- package/dist/databases/postgres/migrations/migration.interface.js +0 -1
- package/dist/databases/postgres/migrations/postgres-foundational.js +0 -47
- /package/dist/{databases/postgres/migrations/database-builder.interface.js → __tests__/setup/vitest-setup.d.ts} +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ValueError } from '@sinclair/typebox/errors';
|
|
2
2
|
import { IUserContext, IEntity, IQueryOptions, IPagedResult, IModelSpec } from '@loomcore/common/models';
|
|
3
|
+
import type { AppIdType } from '@loomcore/common/types';
|
|
3
4
|
import { IGenericApiService } from './generic-api-service.interface.js';
|
|
4
5
|
import { Operation } from '../../databases/operations/operation.js';
|
|
5
6
|
import { DeleteResult } from '../../databases/models/delete-result.js';
|
|
@@ -17,20 +18,20 @@ export declare class GenericApiService<T extends IEntity> implements IGenericApi
|
|
|
17
18
|
};
|
|
18
19
|
validate(doc: any, isPartial?: boolean): ValueError[] | null;
|
|
19
20
|
validateMany(docs: any[], isPartial?: boolean): ValueError[] | null;
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
preProcessEntity(userContext: IUserContext, entity: Partial<T>, isCreate: boolean, allowId?: boolean): Promise<Partial<T>>;
|
|
22
|
+
postProcessEntity(userContext: IUserContext, entity: T): T;
|
|
22
23
|
get(userContext: IUserContext, queryOptions?: IQueryOptions): Promise<IPagedResult<T>>;
|
|
23
24
|
protected prepareQueryOptions(userContext: IUserContext | undefined, queryOptions: IQueryOptions): IQueryOptions;
|
|
24
|
-
getById(userContext: IUserContext, id:
|
|
25
|
+
getById(userContext: IUserContext, id: AppIdType): Promise<T>;
|
|
25
26
|
getCount(userContext: IUserContext): Promise<number>;
|
|
26
27
|
create(userContext: IUserContext, entity: Partial<T>): Promise<T | null>;
|
|
27
28
|
createMany(userContext: IUserContext, entities: Partial<T>[]): Promise<T[]>;
|
|
28
29
|
batchUpdate(userContext: IUserContext, entities: Partial<T>[]): Promise<T[]>;
|
|
29
|
-
fullUpdateById(userContext: IUserContext, id:
|
|
30
|
-
partialUpdateById(userContext: IUserContext, id:
|
|
31
|
-
partialUpdateByIdWithoutPreAndPostProcessing(userContext: IUserContext, id:
|
|
30
|
+
fullUpdateById(userContext: IUserContext, id: AppIdType, entity: T): Promise<T>;
|
|
31
|
+
partialUpdateById(userContext: IUserContext, id: AppIdType, entity: Partial<T>): Promise<T>;
|
|
32
|
+
partialUpdateByIdWithoutPreAndPostProcessing(userContext: IUserContext, id: AppIdType, entity: Partial<T>): Promise<T>;
|
|
32
33
|
update(userContext: IUserContext, queryObject: IQueryOptions, entity: Partial<T>): Promise<T[]>;
|
|
33
|
-
deleteById(userContext: IUserContext, id:
|
|
34
|
+
deleteById(userContext: IUserContext, id: AppIdType): Promise<DeleteResult>;
|
|
34
35
|
deleteMany(userContext: IUserContext, queryObject: IQueryOptions): Promise<DeleteResult>;
|
|
35
36
|
find(userContext: IUserContext, queryObject: IQueryOptions): Promise<T[]>;
|
|
36
37
|
findOne(userContext: IUserContext, queryObject: IQueryOptions): Promise<T | null>;
|
|
@@ -19,7 +19,7 @@ export class GenericApiService {
|
|
|
19
19
|
async getAll(userContext) {
|
|
20
20
|
const { operations } = this.prepareQuery(userContext, {}, []);
|
|
21
21
|
const entities = await this.database.getAll(operations, this.pluralResourceName);
|
|
22
|
-
return entities.map(entity => this.
|
|
22
|
+
return entities.map(entity => this.postProcessEntity(userContext, entity));
|
|
23
23
|
}
|
|
24
24
|
prepareQuery(userContext, queryObject, operations) {
|
|
25
25
|
return { queryObject, operations };
|
|
@@ -39,7 +39,7 @@ export class GenericApiService {
|
|
|
39
39
|
}
|
|
40
40
|
return allErrors.length > 0 ? allErrors : null;
|
|
41
41
|
}
|
|
42
|
-
async
|
|
42
|
+
async preProcessEntity(userContext, entity, isCreate, allowId = true) {
|
|
43
43
|
let preparedEntity = _.clone(entity);
|
|
44
44
|
stripSenderProvidedSystemProperties(userContext, preparedEntity, allowId);
|
|
45
45
|
if (this.modelSpec.isAuditable) {
|
|
@@ -57,17 +57,17 @@ export class GenericApiService {
|
|
|
57
57
|
if (this.modelSpec) {
|
|
58
58
|
cleanedEntity = this.modelSpec.decode(preparedEntity);
|
|
59
59
|
}
|
|
60
|
-
preparedEntity = this.database.
|
|
60
|
+
preparedEntity = this.database.preProcessEntity(cleanedEntity, this.modelSpec.fullSchema);
|
|
61
61
|
return preparedEntity;
|
|
62
62
|
}
|
|
63
|
-
|
|
64
|
-
return this.database.
|
|
63
|
+
postProcessEntity(userContext, entity) {
|
|
64
|
+
return this.database.postProcessEntity(entity, this.modelSpec.fullSchema);
|
|
65
65
|
}
|
|
66
66
|
async get(userContext, queryOptions = { ...DefaultQueryOptions }) {
|
|
67
67
|
const preparedOptions = this.prepareQueryOptions(userContext, queryOptions);
|
|
68
68
|
const { operations } = this.prepareQuery(userContext, {}, []);
|
|
69
69
|
const pagedResult = await this.database.get(operations, preparedOptions, this.modelSpec, this.pluralResourceName);
|
|
70
|
-
const transformedEntities = (pagedResult.entities || []).map(entity => this.
|
|
70
|
+
const transformedEntities = (pagedResult.entities || []).map(entity => this.postProcessEntity(userContext, entity));
|
|
71
71
|
return {
|
|
72
72
|
...pagedResult,
|
|
73
73
|
entities: transformedEntities
|
|
@@ -82,7 +82,7 @@ export class GenericApiService {
|
|
|
82
82
|
if (!entity) {
|
|
83
83
|
throw new IdNotFoundError();
|
|
84
84
|
}
|
|
85
|
-
return this.
|
|
85
|
+
return this.postProcessEntity(userContext, entity);
|
|
86
86
|
}
|
|
87
87
|
async getCount(userContext) {
|
|
88
88
|
this.prepareQuery(userContext, {}, []);
|
|
@@ -90,20 +90,20 @@ export class GenericApiService {
|
|
|
90
90
|
}
|
|
91
91
|
async create(userContext, entity) {
|
|
92
92
|
let createdEntity = null;
|
|
93
|
-
const preparedEntity = await this.
|
|
93
|
+
const preparedEntity = await this.preProcessEntity(userContext, entity, true, true);
|
|
94
94
|
const insertResult = await this.database.create(preparedEntity, this.pluralResourceName);
|
|
95
95
|
if (insertResult.insertedId) {
|
|
96
|
-
createdEntity = this.
|
|
96
|
+
createdEntity = this.postProcessEntity(userContext, insertResult.entity);
|
|
97
97
|
}
|
|
98
98
|
return createdEntity;
|
|
99
99
|
}
|
|
100
100
|
async createMany(userContext, entities) {
|
|
101
101
|
let createdEntities = [];
|
|
102
102
|
if (entities.length) {
|
|
103
|
-
const preparedEntities = await Promise.all(entities.map(entity => this.
|
|
103
|
+
const preparedEntities = await Promise.all(entities.map(entity => this.preProcessEntity(userContext, entity, true, true)));
|
|
104
104
|
const insertResult = await this.database.createMany(preparedEntities, this.pluralResourceName);
|
|
105
105
|
if (insertResult.insertedIds) {
|
|
106
|
-
createdEntities = insertResult.entities.map(entity => this.
|
|
106
|
+
createdEntities = insertResult.entities.map(entity => this.postProcessEntity(userContext, entity));
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
return createdEntities;
|
|
@@ -112,10 +112,10 @@ export class GenericApiService {
|
|
|
112
112
|
if (!entities || entities.length === 0) {
|
|
113
113
|
return [];
|
|
114
114
|
}
|
|
115
|
-
const preparedEntities = await Promise.all(entities.map(entity => this.
|
|
115
|
+
const preparedEntities = await Promise.all(entities.map(entity => this.preProcessEntity(userContext, entity, false, true)));
|
|
116
116
|
const { queryObject, operations } = this.prepareQuery(userContext, {}, []);
|
|
117
117
|
const rawUpdatedEntities = await this.database.batchUpdate(preparedEntities, operations, queryObject, this.pluralResourceName);
|
|
118
|
-
const updatedEntities = rawUpdatedEntities.map(entity => this.
|
|
118
|
+
const updatedEntities = rawUpdatedEntities.map(entity => this.postProcessEntity(userContext, entity));
|
|
119
119
|
return updatedEntities;
|
|
120
120
|
}
|
|
121
121
|
async fullUpdateById(userContext, id, entity) {
|
|
@@ -128,29 +128,29 @@ export class GenericApiService {
|
|
|
128
128
|
_created: existingEntity._created,
|
|
129
129
|
_createdBy: existingEntity._createdBy,
|
|
130
130
|
};
|
|
131
|
-
const preparedEntity = await this.
|
|
131
|
+
const preparedEntity = await this.preProcessEntity(userContext, entity, false, true);
|
|
132
132
|
Object.assign(preparedEntity, auditProperties);
|
|
133
133
|
const rawUpdatedEntity = await this.database.fullUpdateById(operations, id, preparedEntity, this.pluralResourceName);
|
|
134
|
-
const updatedEntity = this.
|
|
134
|
+
const updatedEntity = this.postProcessEntity(userContext, rawUpdatedEntity);
|
|
135
135
|
return updatedEntity;
|
|
136
136
|
}
|
|
137
137
|
async partialUpdateById(userContext, id, entity) {
|
|
138
138
|
const { operations } = this.prepareQuery(userContext, {}, []);
|
|
139
|
-
const preparedEntity = await this.
|
|
139
|
+
const preparedEntity = await this.preProcessEntity(userContext, entity, false, true);
|
|
140
140
|
const rawUpdatedEntity = await this.database.partialUpdateById(operations, id, preparedEntity, this.pluralResourceName);
|
|
141
|
-
const updatedEntity = this.
|
|
141
|
+
const updatedEntity = this.postProcessEntity(userContext, rawUpdatedEntity);
|
|
142
142
|
return updatedEntity;
|
|
143
143
|
}
|
|
144
144
|
async partialUpdateByIdWithoutPreAndPostProcessing(userContext, id, entity) {
|
|
145
|
-
const preparedEntity = this.database.
|
|
145
|
+
const preparedEntity = this.database.preProcessEntity(entity, this.modelSpec.fullSchema);
|
|
146
146
|
const rawUpdatedEntity = await this.database.partialUpdateById([], id, preparedEntity, this.pluralResourceName);
|
|
147
|
-
return this.database.
|
|
147
|
+
return this.database.postProcessEntity(rawUpdatedEntity, this.modelSpec.fullSchema);
|
|
148
148
|
}
|
|
149
149
|
async update(userContext, queryObject, entity) {
|
|
150
150
|
const { queryObject: preparedQuery, operations } = this.prepareQuery(userContext, queryObject, []);
|
|
151
|
-
const preparedEntity = await this.
|
|
151
|
+
const preparedEntity = await this.preProcessEntity(userContext, entity, false, true);
|
|
152
152
|
const rawUpdatedEntities = await this.database.update(preparedQuery, preparedEntity, operations, this.pluralResourceName);
|
|
153
|
-
const updatedEntities = rawUpdatedEntities.map(entity => this.
|
|
153
|
+
const updatedEntities = rawUpdatedEntities.map(entity => this.postProcessEntity(userContext, entity));
|
|
154
154
|
return updatedEntities;
|
|
155
155
|
}
|
|
156
156
|
async deleteById(userContext, id) {
|
|
@@ -168,11 +168,11 @@ export class GenericApiService {
|
|
|
168
168
|
async find(userContext, queryObject) {
|
|
169
169
|
const { queryObject: preparedQuery, operations } = this.prepareQuery(userContext, queryObject, []);
|
|
170
170
|
const rawEntities = await this.database.find(preparedQuery, this.pluralResourceName);
|
|
171
|
-
return rawEntities.map(entity => this.
|
|
171
|
+
return rawEntities.map(entity => this.postProcessEntity(userContext, entity));
|
|
172
172
|
}
|
|
173
173
|
async findOne(userContext, queryObject) {
|
|
174
174
|
const { queryObject: preparedQuery, operations } = this.prepareQuery(userContext, queryObject, []);
|
|
175
175
|
const rawEntity = await this.database.findOne(preparedQuery, this.pluralResourceName);
|
|
176
|
-
return rawEntity ? this.
|
|
176
|
+
return rawEntity ? this.postProcessEntity(userContext, rawEntity) : null;
|
|
177
177
|
}
|
|
178
178
|
}
|
|
@@ -9,5 +9,5 @@ export declare class MultiTenantApiService<T extends IEntity> extends GenericApi
|
|
|
9
9
|
queryObject: IQueryOptions;
|
|
10
10
|
operations: Operation[];
|
|
11
11
|
};
|
|
12
|
-
|
|
12
|
+
preProcessEntity(userContext: IUserContext, entity: Partial<T>, isCreate: boolean, allowId?: boolean): Promise<Partial<T>>;
|
|
13
13
|
}
|
|
@@ -20,14 +20,14 @@ export class MultiTenantApiService extends GenericApiService {
|
|
|
20
20
|
const queryObject = this.tenantDecorator.applyTenantToQuery(userContext, queryOptions, this.pluralResourceName);
|
|
21
21
|
return { queryObject, operations };
|
|
22
22
|
}
|
|
23
|
-
async
|
|
23
|
+
async preProcessEntity(userContext, entity, isCreate, allowId = false) {
|
|
24
24
|
if (!config?.app?.isMultiTenant) {
|
|
25
|
-
return super.
|
|
25
|
+
return super.preProcessEntity(userContext, entity, isCreate, allowId);
|
|
26
26
|
}
|
|
27
27
|
if (!userContext || !userContext.organization?._id) {
|
|
28
28
|
throw new BadRequestError('A valid userContext was not provided to MultiTenantApiService.prepareEntity');
|
|
29
29
|
}
|
|
30
|
-
const preparedEntity = await super.
|
|
30
|
+
const preparedEntity = await super.preProcessEntity(userContext, entity, isCreate, allowId);
|
|
31
31
|
if (isCreate && userContext.user._id !== 'system') {
|
|
32
32
|
preparedEntity._orgId = userContext.organization?._id;
|
|
33
33
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { IOrganization, IUserContext } from '@loomcore/common/models';
|
|
2
2
|
import { IDatabase } from '../databases/models/database.interface.js';
|
|
3
3
|
import { GenericApiService } from './generic-api-service/generic-api.service.js';
|
|
4
|
+
import { AppIdType } from '@loomcore/common/types';
|
|
4
5
|
export declare class OrganizationService extends GenericApiService<IOrganization> {
|
|
5
6
|
constructor(database: IDatabase);
|
|
6
|
-
|
|
7
|
-
getAuthTokenByRepoCode(userContext: IUserContext, orgId:
|
|
8
|
-
validateRepoAuthToken(userContext: IUserContext, orgCode: string, authToken: string): Promise<
|
|
7
|
+
preProcessEntity(userContext: IUserContext, entity: Partial<IOrganization>, isCreate: boolean, allowId?: boolean): Promise<Partial<IOrganization>>;
|
|
8
|
+
getAuthTokenByRepoCode(userContext: IUserContext, orgId: AppIdType): Promise<string | null>;
|
|
9
|
+
validateRepoAuthToken(userContext: IUserContext, orgCode: string, authToken: string): Promise<AppIdType | null>;
|
|
9
10
|
getMetaOrg(userContext: IUserContext): Promise<IOrganization | null>;
|
|
10
11
|
}
|
|
@@ -5,7 +5,7 @@ export class OrganizationService extends GenericApiService {
|
|
|
5
5
|
constructor(database) {
|
|
6
6
|
super(database, 'organizations', 'organization', OrganizationSpec);
|
|
7
7
|
}
|
|
8
|
-
async
|
|
8
|
+
async preProcessEntity(userContext, entity, isCreate, allowId = true) {
|
|
9
9
|
if (isCreate) {
|
|
10
10
|
const metaOrg = await this.getMetaOrg(userContext);
|
|
11
11
|
if (metaOrg && entity.isMetaOrg) {
|
|
@@ -15,7 +15,7 @@ export class OrganizationService extends GenericApiService {
|
|
|
15
15
|
throw new BadRequestError('User is not authorized to create an organization');
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
|
-
const result = await super.
|
|
18
|
+
const result = await super.preProcessEntity(userContext, entity, isCreate, allowId);
|
|
19
19
|
return result;
|
|
20
20
|
}
|
|
21
21
|
async getAuthTokenByRepoCode(userContext, orgId) {
|
|
@@ -27,7 +27,7 @@ export class OrganizationService extends GenericApiService {
|
|
|
27
27
|
if (!org) {
|
|
28
28
|
return null;
|
|
29
29
|
}
|
|
30
|
-
const orgId = org.authToken === authToken ? org._id
|
|
30
|
+
const orgId = org.authToken === authToken ? org._id : null;
|
|
31
31
|
return orgId;
|
|
32
32
|
}
|
|
33
33
|
async getMetaOrg(userContext) {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { IUser, IUserContext } from '@loomcore/common/models';
|
|
2
|
+
import type { AppIdType } from '@loomcore/common/types';
|
|
2
3
|
import { MultiTenantApiService } from './index.js';
|
|
3
4
|
import { IDatabase } from '../databases/models/index.js';
|
|
4
5
|
export declare class UserService extends MultiTenantApiService<IUser> {
|
|
5
6
|
constructor(database: IDatabase);
|
|
6
|
-
fullUpdateById(userContext: IUserContext, id:
|
|
7
|
-
|
|
7
|
+
fullUpdateById(userContext: IUserContext, id: AppIdType, entity: IUser): Promise<IUser>;
|
|
8
|
+
preProcessEntity(userContext: IUserContext, entity: Partial<IUser>, isCreate: boolean, allowId?: boolean): Promise<Partial<IUser>>;
|
|
8
9
|
}
|
|
@@ -9,8 +9,8 @@ export class UserService extends MultiTenantApiService {
|
|
|
9
9
|
async fullUpdateById(userContext, id, entity) {
|
|
10
10
|
throw new ServerError('Cannot full update a user. Either use PATCH or /auth/change-password to update password.');
|
|
11
11
|
}
|
|
12
|
-
async
|
|
13
|
-
const preparedEntity = await super.
|
|
12
|
+
async preProcessEntity(userContext, entity, isCreate, allowId = false) {
|
|
13
|
+
const preparedEntity = await super.preProcessEntity(userContext, entity, isCreate);
|
|
14
14
|
if (preparedEntity.email) {
|
|
15
15
|
preparedEntity.email = preparedEntity.email.toLowerCase();
|
|
16
16
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import { getSystemUserId } from "@loomcore/common/validation";
|
|
1
2
|
import moment from "moment";
|
|
2
3
|
export function auditForCreate(userContext, doc) {
|
|
3
4
|
const now = moment().utc().toDate();
|
|
4
|
-
const userId = userContext.user?._id
|
|
5
|
+
const userId = userContext.user?._id ?? getSystemUserId();
|
|
5
6
|
doc._created = now;
|
|
6
7
|
doc._createdBy = userId;
|
|
7
8
|
doc._updated = now;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { getSystemUserId } from "@loomcore/common/validation";
|
|
1
2
|
import moment from "moment";
|
|
2
3
|
export function auditForUpdate(userContext, doc) {
|
|
3
|
-
const userId = userContext.user?._id
|
|
4
|
+
const userId = userContext.user?._id ?? getSystemUserId();
|
|
4
5
|
doc._updated = moment().utc().toDate();
|
|
5
6
|
doc._updatedBy = userId;
|
|
6
7
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { getSystemUserId } from "@loomcore/common/validation";
|
|
1
2
|
export function stripSenderProvidedSystemProperties(userContext, entity, allowId = false) {
|
|
2
|
-
const isSystemUser = userContext.user?._id ===
|
|
3
|
+
const isSystemUser = userContext.user?._id === getSystemUserId();
|
|
3
4
|
if (isSystemUser) {
|
|
4
5
|
return;
|
|
5
6
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loomcore/api",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.57",
|
|
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": {
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"qs": "^6.14.0"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"@loomcore/common": "^0.0.
|
|
56
|
+
"@loomcore/common": "^0.0.43",
|
|
57
57
|
"@sinclair/typebox": "0.34.33",
|
|
58
58
|
"cookie-parser": "^1.4.6",
|
|
59
59
|
"cors": "^2.8.5",
|
package/dist/__tests__/postgres-test-migrations/100-create-test-entities-table.migration.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { Client } from "pg";
|
|
2
|
-
import { IMigration } from "../../databases/postgres/migrations/migration.interface.js";
|
|
3
|
-
export declare class CreateTestEntitiesTableMigration implements IMigration {
|
|
4
|
-
private readonly client;
|
|
5
|
-
constructor(client: Client);
|
|
6
|
-
index: number;
|
|
7
|
-
execute(): Promise<{
|
|
8
|
-
success: boolean;
|
|
9
|
-
error: Error;
|
|
10
|
-
} | {
|
|
11
|
-
success: boolean;
|
|
12
|
-
error: null;
|
|
13
|
-
}>;
|
|
14
|
-
revert(): Promise<{
|
|
15
|
-
success: boolean;
|
|
16
|
-
error: Error;
|
|
17
|
-
} | {
|
|
18
|
-
success: boolean;
|
|
19
|
-
error: null;
|
|
20
|
-
}>;
|
|
21
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from "crypto";
|
|
2
|
-
export class CreateTestEntitiesTableMigration {
|
|
3
|
-
client;
|
|
4
|
-
constructor(client) {
|
|
5
|
-
this.client = client;
|
|
6
|
-
}
|
|
7
|
-
index = 100;
|
|
8
|
-
async execute() {
|
|
9
|
-
const _id = randomUUID().toString();
|
|
10
|
-
try {
|
|
11
|
-
await this.client.query(`
|
|
12
|
-
CREATE TABLE "testEntities" (
|
|
13
|
-
"_id" VARCHAR(255) PRIMARY KEY,
|
|
14
|
-
"_orgId" VARCHAR(255),
|
|
15
|
-
"name" VARCHAR(255) NOT NULL,
|
|
16
|
-
"description" TEXT,
|
|
17
|
-
"isActive" BOOLEAN,
|
|
18
|
-
"tags" TEXT[],
|
|
19
|
-
"count" INTEGER,
|
|
20
|
-
"_created" TIMESTAMP NOT NULL,
|
|
21
|
-
"_createdBy" VARCHAR(255) NOT NULL,
|
|
22
|
-
"_updated" TIMESTAMP NOT NULL,
|
|
23
|
-
"_updatedBy" VARCHAR(255) NOT NULL,
|
|
24
|
-
"_deleted" TIMESTAMP,
|
|
25
|
-
"_deletedBy" VARCHAR(255)
|
|
26
|
-
)
|
|
27
|
-
`);
|
|
28
|
-
}
|
|
29
|
-
catch (error) {
|
|
30
|
-
return { success: false, error: new Error(`Error creating test entities table: ${error.message}`) };
|
|
31
|
-
}
|
|
32
|
-
try {
|
|
33
|
-
await this.client.query(`
|
|
34
|
-
Insert into "migrations" ("_id", "index", "hasRun", "reverted") values ('${_id}', ${this.index}, TRUE, FALSE);
|
|
35
|
-
`);
|
|
36
|
-
}
|
|
37
|
-
catch (error) {
|
|
38
|
-
return { success: false, error: new Error(`Error inserting migration ${this.index} to migrations table: ${error.message}`) };
|
|
39
|
-
}
|
|
40
|
-
return { success: true, error: null };
|
|
41
|
-
}
|
|
42
|
-
async revert() {
|
|
43
|
-
try {
|
|
44
|
-
await this.client.query(`
|
|
45
|
-
DROP TABLE test_entities;
|
|
46
|
-
`);
|
|
47
|
-
}
|
|
48
|
-
catch (error) {
|
|
49
|
-
return { success: false, error: new Error(`Error dropping test entities table: ${error.message}`) };
|
|
50
|
-
}
|
|
51
|
-
try {
|
|
52
|
-
await this.client.query(`
|
|
53
|
-
Update "migrations" SET "reverted" = TRUE WHERE "index" = '${this.index}';
|
|
54
|
-
`);
|
|
55
|
-
}
|
|
56
|
-
catch (error) {
|
|
57
|
-
return { success: false, error: new Error(`Error updating migration record: ${error.message}`) };
|
|
58
|
-
}
|
|
59
|
-
return { success: true, error: null };
|
|
60
|
-
}
|
|
61
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { IMigration } from "../../databases/postgres/migrations/index.js";
|
|
2
|
-
import { Client } from "pg";
|
|
3
|
-
export declare class CreateCategoriesTableMigration implements IMigration {
|
|
4
|
-
private readonly client;
|
|
5
|
-
constructor(client: Client);
|
|
6
|
-
index: number;
|
|
7
|
-
execute(): Promise<{
|
|
8
|
-
success: boolean;
|
|
9
|
-
error: Error;
|
|
10
|
-
} | {
|
|
11
|
-
success: boolean;
|
|
12
|
-
error: null;
|
|
13
|
-
}>;
|
|
14
|
-
revert(): Promise<{
|
|
15
|
-
success: boolean;
|
|
16
|
-
error: Error;
|
|
17
|
-
} | {
|
|
18
|
-
success: boolean;
|
|
19
|
-
error: null;
|
|
20
|
-
}>;
|
|
21
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from "crypto";
|
|
2
|
-
export class CreateCategoriesTableMigration {
|
|
3
|
-
client;
|
|
4
|
-
constructor(client) {
|
|
5
|
-
this.client = client;
|
|
6
|
-
}
|
|
7
|
-
index = 101;
|
|
8
|
-
async execute() {
|
|
9
|
-
const _id = randomUUID().toString();
|
|
10
|
-
try {
|
|
11
|
-
await this.client.query(`
|
|
12
|
-
CREATE TABLE "categories" (
|
|
13
|
-
"_id" VARCHAR(255) PRIMARY KEY,
|
|
14
|
-
"_orgId" VARCHAR(255),
|
|
15
|
-
"name" VARCHAR(255) NOT NULL
|
|
16
|
-
)
|
|
17
|
-
`);
|
|
18
|
-
}
|
|
19
|
-
catch (error) {
|
|
20
|
-
return { success: false, error: new Error(`Error creating categories table: ${error.message}`) };
|
|
21
|
-
}
|
|
22
|
-
try {
|
|
23
|
-
await this.client.query(`
|
|
24
|
-
Insert into "migrations" ("_id", "index", "hasRun", "reverted") values ('${_id}', ${this.index}, TRUE, FALSE);
|
|
25
|
-
`);
|
|
26
|
-
}
|
|
27
|
-
catch (error) {
|
|
28
|
-
return { success: false, error: new Error(`Error inserting migration ${this.index} to migrations table: ${error.message}`) };
|
|
29
|
-
}
|
|
30
|
-
return { success: true, error: null };
|
|
31
|
-
}
|
|
32
|
-
async revert() {
|
|
33
|
-
try {
|
|
34
|
-
await this.client.query(`
|
|
35
|
-
DROP TABLE "categories";
|
|
36
|
-
`);
|
|
37
|
-
}
|
|
38
|
-
catch (error) {
|
|
39
|
-
return { success: false, error: new Error(`Error dropping categories table: ${error.message}`) };
|
|
40
|
-
}
|
|
41
|
-
try {
|
|
42
|
-
await this.client.query(`
|
|
43
|
-
Update "migrations" SET "reverted" = TRUE WHERE "index" = '${this.index}';
|
|
44
|
-
`);
|
|
45
|
-
}
|
|
46
|
-
catch (error) {
|
|
47
|
-
return { success: false, error: new Error(`Error updating migration record: ${error.message}`) };
|
|
48
|
-
}
|
|
49
|
-
return { success: true, error: null };
|
|
50
|
-
}
|
|
51
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { Client } from "pg";
|
|
2
|
-
import { IMigration } from "../../databases/postgres/migrations/index.js";
|
|
3
|
-
export declare class CreateProductsTableMigration implements IMigration {
|
|
4
|
-
private readonly client;
|
|
5
|
-
constructor(client: Client);
|
|
6
|
-
index: number;
|
|
7
|
-
execute(): Promise<{
|
|
8
|
-
success: boolean;
|
|
9
|
-
error: Error;
|
|
10
|
-
} | {
|
|
11
|
-
success: boolean;
|
|
12
|
-
error: null;
|
|
13
|
-
}>;
|
|
14
|
-
revert(): Promise<{
|
|
15
|
-
success: boolean;
|
|
16
|
-
error: Error;
|
|
17
|
-
} | {
|
|
18
|
-
success: boolean;
|
|
19
|
-
error: null;
|
|
20
|
-
}>;
|
|
21
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from "crypto";
|
|
2
|
-
export class CreateProductsTableMigration {
|
|
3
|
-
client;
|
|
4
|
-
constructor(client) {
|
|
5
|
-
this.client = client;
|
|
6
|
-
}
|
|
7
|
-
index = 102;
|
|
8
|
-
async execute() {
|
|
9
|
-
const _id = randomUUID().toString();
|
|
10
|
-
try {
|
|
11
|
-
await this.client.query(`
|
|
12
|
-
CREATE TABLE "products" (
|
|
13
|
-
"_id" VARCHAR(255) PRIMARY KEY,
|
|
14
|
-
"_orgId" VARCHAR(255),
|
|
15
|
-
"name" VARCHAR(255) NOT NULL,
|
|
16
|
-
"description" TEXT,
|
|
17
|
-
"internalNumber" VARCHAR(255),
|
|
18
|
-
"categoryId" VARCHAR(255) NOT NULL REFERENCES "categories"("_id"),
|
|
19
|
-
"_created" TIMESTAMP NOT NULL,
|
|
20
|
-
"_createdBy" VARCHAR(255) NOT NULL,
|
|
21
|
-
"_updated" TIMESTAMP NOT NULL,
|
|
22
|
-
"_updatedBy" VARCHAR(255) NOT NULL,
|
|
23
|
-
"_deleted" TIMESTAMP,
|
|
24
|
-
"_deletedBy" VARCHAR(255)
|
|
25
|
-
)
|
|
26
|
-
`);
|
|
27
|
-
}
|
|
28
|
-
catch (error) {
|
|
29
|
-
return { success: false, error: new Error(`Error creating products table: ${error.message}`) };
|
|
30
|
-
}
|
|
31
|
-
try {
|
|
32
|
-
await this.client.query(`
|
|
33
|
-
Insert into "migrations" ("_id", "index", "hasRun", "reverted") values ('${_id}', ${this.index}, TRUE, FALSE);
|
|
34
|
-
`);
|
|
35
|
-
}
|
|
36
|
-
catch (error) {
|
|
37
|
-
return { success: false, error: new Error(`Error inserting migration ${this.index} to migrations table: ${error.message}`) };
|
|
38
|
-
}
|
|
39
|
-
return { success: true, error: null };
|
|
40
|
-
}
|
|
41
|
-
async revert() {
|
|
42
|
-
try {
|
|
43
|
-
await this.client.query(`
|
|
44
|
-
DROP TABLE "products";
|
|
45
|
-
`);
|
|
46
|
-
}
|
|
47
|
-
catch (error) {
|
|
48
|
-
return { success: false, error: new Error(`Error dropping products table: ${error.message}`) };
|
|
49
|
-
}
|
|
50
|
-
try {
|
|
51
|
-
await this.client.query(`
|
|
52
|
-
Update "migrations" SET "reverted" = TRUE WHERE "index" = '${this.index}';
|
|
53
|
-
`);
|
|
54
|
-
}
|
|
55
|
-
catch (error) {
|
|
56
|
-
return { success: false, error: new Error(`Error updating migration record: ${error.message}`) };
|
|
57
|
-
}
|
|
58
|
-
return { success: true, error: null };
|
|
59
|
-
}
|
|
60
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { Client } from "pg";
|
|
2
|
-
import { IMigration } from "../../databases/postgres/migrations/index.js";
|
|
3
|
-
export declare class CreateTestItemsTableMigration implements IMigration {
|
|
4
|
-
private readonly client;
|
|
5
|
-
constructor(client: Client);
|
|
6
|
-
index: number;
|
|
7
|
-
execute(): Promise<{
|
|
8
|
-
success: boolean;
|
|
9
|
-
error: Error;
|
|
10
|
-
} | {
|
|
11
|
-
success: boolean;
|
|
12
|
-
error: null;
|
|
13
|
-
}>;
|
|
14
|
-
revert(): Promise<{
|
|
15
|
-
success: boolean;
|
|
16
|
-
error: Error;
|
|
17
|
-
} | {
|
|
18
|
-
success: boolean;
|
|
19
|
-
error: null;
|
|
20
|
-
}>;
|
|
21
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { randomUUID } from "crypto";
|
|
2
|
-
export class CreateTestItemsTableMigration {
|
|
3
|
-
client;
|
|
4
|
-
constructor(client) {
|
|
5
|
-
this.client = client;
|
|
6
|
-
}
|
|
7
|
-
index = 103;
|
|
8
|
-
async execute() {
|
|
9
|
-
const _id = randomUUID().toString();
|
|
10
|
-
try {
|
|
11
|
-
await this.client.query(`
|
|
12
|
-
CREATE TABLE "testItems" (
|
|
13
|
-
"_id" VARCHAR(255) PRIMARY KEY,
|
|
14
|
-
"_orgId" VARCHAR(255),
|
|
15
|
-
"name" VARCHAR(255) NOT NULL,
|
|
16
|
-
"value" INTEGER,
|
|
17
|
-
"eventDate" TIMESTAMP,
|
|
18
|
-
"_created" TIMESTAMP NOT NULL,
|
|
19
|
-
"_createdBy" VARCHAR(255) NOT NULL,
|
|
20
|
-
"_updated" TIMESTAMP NOT NULL,
|
|
21
|
-
"_updatedBy" VARCHAR(255) NOT NULL,
|
|
22
|
-
"_deleted" TIMESTAMP,
|
|
23
|
-
"_deletedBy" VARCHAR(255)
|
|
24
|
-
)
|
|
25
|
-
`);
|
|
26
|
-
}
|
|
27
|
-
catch (error) {
|
|
28
|
-
return { success: false, error: new Error(`Error creating test items table: ${error.message}`) };
|
|
29
|
-
}
|
|
30
|
-
try {
|
|
31
|
-
await this.client.query(`
|
|
32
|
-
Insert into "migrations" ("_id", "index", "hasRun", "reverted") values ('${_id}', ${this.index}, TRUE, FALSE);
|
|
33
|
-
`);
|
|
34
|
-
}
|
|
35
|
-
catch (error) {
|
|
36
|
-
return { success: false, error: new Error(`Error inserting migration ${this.index} to migrations table: ${error.message}`) };
|
|
37
|
-
}
|
|
38
|
-
return { success: true, error: null };
|
|
39
|
-
}
|
|
40
|
-
async revert() {
|
|
41
|
-
try {
|
|
42
|
-
await this.client.query(`
|
|
43
|
-
DROP TABLE "testItems";
|
|
44
|
-
`);
|
|
45
|
-
}
|
|
46
|
-
catch (error) {
|
|
47
|
-
return { success: false, error: new Error(`Error dropping test items table: ${error.message}`) };
|
|
48
|
-
}
|
|
49
|
-
try {
|
|
50
|
-
await this.client.query(`
|
|
51
|
-
Update "migrations" SET "reverted" = TRUE WHERE "index" = '${this.index}';
|
|
52
|
-
`);
|
|
53
|
-
}
|
|
54
|
-
catch (error) {
|
|
55
|
-
return { success: false, error: new Error(`Error updating migration record: ${error.message}`) };
|
|
56
|
-
}
|
|
57
|
-
return { success: true, error: null };
|
|
58
|
-
}
|
|
59
|
-
}
|