@solidstarters/solid-core 1.2.157 → 1.2.159
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/config/cache.options.js +2 -7
- package/dist/config/cache.options.js.map +1 -1
- package/dist/constants/error-messages.js +1 -1
- package/dist/constants/error-messages.js.map +1 -1
- package/dist/controllers/authentication.controller.d.ts +0 -2
- package/dist/controllers/authentication.controller.d.ts.map +1 -1
- package/dist/controllers/authentication.controller.js +5 -5
- package/dist/controllers/authentication.controller.js.map +1 -1
- package/dist/factories/whatsapp.factory.d.ts.map +1 -1
- package/dist/factories/whatsapp.factory.js +1 -1
- package/dist/factories/whatsapp.factory.js.map +1 -1
- package/dist/helpers/environment.helper.d.ts +2 -0
- package/dist/helpers/environment.helper.d.ts.map +1 -1
- package/dist/helpers/environment.helper.js +7 -0
- package/dist/helpers/environment.helper.js.map +1 -1
- package/dist/helpers/index.d.ts +2 -0
- package/dist/helpers/index.d.ts.map +1 -0
- package/dist/helpers/index.js +13 -0
- package/dist/helpers/index.js.map +1 -0
- package/dist/helpers/model-metadata-helper.service.d.ts +5 -1
- package/dist/helpers/model-metadata-helper.service.d.ts.map +1 -1
- package/dist/helpers/model-metadata-helper.service.js +32 -2
- package/dist/helpers/model-metadata-helper.service.js.map +1 -1
- package/dist/helpers/string.helper.d.ts +2 -0
- package/dist/helpers/string.helper.d.ts.map +1 -0
- package/dist/helpers/string.helper.js +10 -0
- package/dist/helpers/string.helper.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/repository/security-rule.repository.d.ts.map +1 -1
- package/dist/repository/security-rule.repository.js +16 -9
- package/dist/repository/security-rule.repository.js.map +1 -1
- package/dist/repository/user.repository.d.ts +12 -0
- package/dist/repository/user.repository.d.ts.map +1 -0
- package/dist/repository/user.repository.js +34 -0
- package/dist/repository/user.repository.js.map +1 -0
- package/dist/seeders/module-metadata-seeder.service.d.ts +12 -12
- package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
- package/dist/seeders/module-metadata-seeder.service.js +33 -13
- package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
- package/dist/seeders/seed-data/solid-core-metadata.json +40 -6
- package/dist/services/authentication.service.d.ts +0 -2
- package/dist/services/authentication.service.d.ts.map +1 -1
- package/dist/services/authentication.service.js +15 -14
- package/dist/services/authentication.service.js.map +1 -1
- package/dist/services/chatter-message.service.d.ts +8 -2
- package/dist/services/chatter-message.service.d.ts.map +1 -1
- package/dist/services/chatter-message.service.js +155 -30
- package/dist/services/chatter-message.service.js.map +1 -1
- package/dist/services/crud-helper.service.d.ts +7 -3
- package/dist/services/crud-helper.service.d.ts.map +1 -1
- package/dist/services/crud-helper.service.js +17 -5
- package/dist/services/crud-helper.service.js.map +1 -1
- package/dist/services/list-of-values.service.js.map +1 -1
- package/dist/services/user.service.d.ts +3 -2
- package/dist/services/user.service.d.ts.map +1 -1
- package/dist/services/user.service.js +2 -2
- package/dist/services/user.service.js.map +1 -1
- package/dist/services/view-metadata.service.d.ts +3 -1
- package/dist/services/view-metadata.service.d.ts.map +1 -1
- package/dist/services/view-metadata.service.js +5 -2
- package/dist/services/view-metadata.service.js.map +1 -1
- package/dist/solid-core.module.d.ts.map +1 -1
- package/dist/solid-core.module.js +16 -7
- package/dist/solid-core.module.js.map +1 -1
- package/dist/subscribers/audit.subscriber.d.ts +3 -1
- package/dist/subscribers/audit.subscriber.d.ts.map +1 -1
- package/dist/subscribers/audit.subscriber.js +10 -5
- package/dist/subscribers/audit.subscriber.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -1
- package/src/config/cache.options.ts +1 -6
- package/src/constants/error-messages.ts +1 -1
- package/src/controllers/authentication.controller.ts +5 -5
- package/src/factories/whatsapp.factory.ts +2 -1
- package/src/helpers/environment.helper.ts +9 -0
- package/src/helpers/index.ts +9 -0
- package/src/helpers/model-metadata-helper.service.ts +30 -2
- package/src/helpers/string.helper.ts +4 -0
- package/src/index.ts +1 -0
- package/src/repository/security-rule.repository.ts +25 -12
- package/src/repository/user.repository.ts +17 -0
- package/src/seeders/module-metadata-seeder.service.ts +36 -15
- package/src/seeders/seed-data/solid-core-metadata.json +40 -6
- package/src/services/authentication.service.ts +20 -14
- package/src/services/chatter-message.service.ts +185 -35
- package/src/services/crud-helper.service.ts +24 -6
- package/src/services/list-of-values.service.ts +1 -1
- package/src/services/user.service.ts +3 -2
- package/src/services/view-metadata.service.ts +3 -1
- package/src/solid-core.module.ts +13 -3
- package/src/subscribers/audit.subscriber.ts +9 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidstarters/solid-core",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.159",
|
|
4
4
|
"description": "This module is a NestJS module containing all the required core providers required by a Solid application",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -38,6 +38,7 @@
|
|
|
38
38
|
"@aws-sdk/s3-request-presigner": "^3.828.0",
|
|
39
39
|
"@elasticemail/elasticemail-client": "^4.0.23",
|
|
40
40
|
"@hapi/joi": "^17.1.1",
|
|
41
|
+
"@nest-lab/throttler-storage-redis": "^1.1.0",
|
|
41
42
|
"@nestjs/schedule": "^6.0.0",
|
|
42
43
|
"@nestjs/throttler": "^6.4.0",
|
|
43
44
|
"amqplib": "^0.10.4",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CacheModuleAsyncOptions } from '@nestjs/cache-manager';
|
|
2
2
|
import { ConfigModule, ConfigService } from '@nestjs/config';
|
|
3
3
|
import { redisStore } from 'cache-manager-redis-store';
|
|
4
|
-
import {
|
|
4
|
+
import { isRedisConfigured } from 'src/helpers/environment.helper';
|
|
5
5
|
|
|
6
6
|
export const RedisOptions: CacheModuleAsyncOptions = {
|
|
7
7
|
isGlobal: true,
|
|
@@ -29,8 +29,3 @@ async function createRedisStore(configService: ConfigService<Record<string, unkn
|
|
|
29
29
|
});
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
function isRedisConfigured(configService: ConfigService): boolean {
|
|
33
|
-
const host = configService.get<string>('REDIS_HOST');
|
|
34
|
-
const port = configService.get<string>('REDIS_PORT');
|
|
35
|
-
return host && port && isNumber(parseInt(port));
|
|
36
|
-
}
|
|
@@ -28,7 +28,7 @@ export const ERROR_MESSAGES = {
|
|
|
28
28
|
GOOGLE_OAUTH_PROFILE_FETCH_FAILED: 'Failed to fetch user profile from Google OAuth service',
|
|
29
29
|
LOGOUT_FAILED: 'Logout failed due to an unexpected error.',
|
|
30
30
|
|
|
31
|
-
INVALID_CREDENTIALS: 'Invalid
|
|
31
|
+
INVALID_CREDENTIALS: 'Invalid credentials',
|
|
32
32
|
LOGIN_FAILED: 'Login Failed',
|
|
33
33
|
OLD_PASSWORD_INCORRECT: 'You have specified an incorrect old password.',
|
|
34
34
|
INVALID_NEW_PASSWORD: 'Invalid new password.',
|
|
@@ -25,7 +25,7 @@ export class AuthenticationController {
|
|
|
25
25
|
constructor(private readonly authService: AuthenticationService) { }
|
|
26
26
|
|
|
27
27
|
@Public()
|
|
28
|
-
@SkipThrottle({ login: false }) //Enable the login throttle only
|
|
28
|
+
@SkipThrottle({ login: false, short: true, burst: true, sustained: true }) //Enable the login throttle only
|
|
29
29
|
@Post('register')
|
|
30
30
|
signUp(@Body() signUpDto: SignUpDto) {
|
|
31
31
|
return this.authService.signUp(signUpDto);
|
|
@@ -39,7 +39,7 @@ export class AuthenticationController {
|
|
|
39
39
|
|
|
40
40
|
@Public()
|
|
41
41
|
// @UseGuards(LocalAuthGuard)
|
|
42
|
-
@SkipThrottle({ login: false }) //Enable the login throttle only
|
|
42
|
+
@SkipThrottle({ login: false, short: true, burst: true, sustained: true }) //Enable the login throttle only
|
|
43
43
|
@HttpCode(HttpStatus.OK) // by default @Post does 201, we wanted 200 - hence using @HttpCode(HttpStatus.OK)
|
|
44
44
|
@Post('authenticate')
|
|
45
45
|
async signIn(
|
|
@@ -62,7 +62,7 @@ export class AuthenticationController {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
@Public()
|
|
65
|
-
@SkipThrottle({ login: false }) //Enable the login throttle only
|
|
65
|
+
@SkipThrottle({ login: false, short: true, burst: true, sustained: true }) //Enable the login throttle only
|
|
66
66
|
@HttpCode(HttpStatus.OK) // changed since the default is 201
|
|
67
67
|
@Post('refresh-tokens')
|
|
68
68
|
refreshTokens(@Body() refreshTokenDto: RefreshTokenDto) {
|
|
@@ -70,14 +70,14 @@ export class AuthenticationController {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
@Public()
|
|
73
|
-
@SkipThrottle({ login: false }) //Enable the login throttle only
|
|
73
|
+
@SkipThrottle({ login: false, short: true, burst: true, sustained: true }) //Enable the login throttle only
|
|
74
74
|
@Post('initiate/forgot-password')
|
|
75
75
|
initiateForgotPassword(@Body() initiateForgotPasswordDto: InitiateForgotPasswordDto) {
|
|
76
76
|
return this.authService.initiateForgotPassword(initiateForgotPasswordDto);
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
@Public()
|
|
80
|
-
@SkipThrottle({ login: false }) //Enable the login throttle only
|
|
80
|
+
@SkipThrottle({ login: false, short: true, burst: true, sustained: true }) //Enable the login throttle only
|
|
81
81
|
@Post('confirm/forgot-password')
|
|
82
82
|
confirmForgotPassword(@Body() confirmForgotPasswordDto: ConfirmForgotPasswordDto) {
|
|
83
83
|
return this.authService.confirmForgotPassword(confirmForgotPasswordDto);
|
|
@@ -22,11 +22,12 @@ export class WhatsAppFactory {
|
|
|
22
22
|
|
|
23
23
|
getWhatsappService(name: string = null): IWhatsAppTransport {
|
|
24
24
|
// This is the default provider
|
|
25
|
-
const whatsappServiceName = this.commonConfiguration.whatsappProvider
|
|
25
|
+
const whatsappServiceName = name || this.commonConfiguration.whatsappProvider;
|
|
26
26
|
if (!whatsappServiceName) {
|
|
27
27
|
throw new Error("Unable to resolve whatsapp provider")
|
|
28
28
|
}
|
|
29
29
|
const whatsappProviders = this.solidRegistry.getWhatsappProviders();
|
|
30
|
+
|
|
30
31
|
// Return the instance which matches the whatsappServiceName
|
|
31
32
|
if (!whatsappProviders.length) {
|
|
32
33
|
// throw new Error("No mail providers are registered.");
|
|
@@ -1,7 +1,16 @@
|
|
|
1
|
+
import { ConfigService } from "@nestjs/config";
|
|
2
|
+
import { isNumber } from 'class-validator';
|
|
3
|
+
|
|
1
4
|
export function parseBooleanEnv(key: string, defaultValue: boolean = false): boolean {
|
|
2
5
|
const value = process.env[key];
|
|
3
6
|
if (value === undefined) {
|
|
4
7
|
return defaultValue;
|
|
5
8
|
}
|
|
6
9
|
return value.toLowerCase() === 'true';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function isRedisConfigured(configService: ConfigService): boolean {
|
|
13
|
+
const host = configService.get<string>('REDIS_HOST');
|
|
14
|
+
const port = configService.get<string>('REDIS_PORT');
|
|
15
|
+
return host && port && isNumber(parseInt(port));
|
|
7
16
|
}
|
|
@@ -2,13 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
import { Injectable, Logger } from "@nestjs/common";
|
|
4
4
|
import { SolidRegistry } from "./solid-registry";
|
|
5
|
-
import { In } from "typeorm";
|
|
5
|
+
import { In, Repository } from "typeorm";
|
|
6
|
+
import { InjectRepository } from "@nestjs/typeorm";
|
|
7
|
+
import { ModelMetadata } from "src/entities/model-metadata.entity";
|
|
6
8
|
|
|
7
9
|
@Injectable()
|
|
8
10
|
export class ModelMetadataHelperService {
|
|
9
11
|
private readonly logger = new Logger(ModelMetadataHelperService.name);
|
|
10
12
|
|
|
11
|
-
constructor(private readonly registry: SolidRegistry
|
|
13
|
+
constructor(private readonly registry: SolidRegistry,
|
|
14
|
+
@InjectRepository(ModelMetadata)
|
|
15
|
+
private readonly modelMetadataRepo: Repository<ModelMetadata>,
|
|
16
|
+
) {
|
|
12
17
|
}
|
|
13
18
|
|
|
14
19
|
getSystemFieldsMetadata(): any[] {
|
|
@@ -105,5 +110,28 @@ export class ModelMetadataHelperService {
|
|
|
105
110
|
return systemFieldsMetadata;
|
|
106
111
|
}
|
|
107
112
|
|
|
113
|
+
async loadFieldHierarchy(modelName: any) {
|
|
114
|
+
const model = await this.modelMetadataRepo.findOne({
|
|
115
|
+
where: {
|
|
116
|
+
singularName: modelName,
|
|
117
|
+
},
|
|
118
|
+
relations: {
|
|
119
|
+
fields: true,
|
|
120
|
+
parentModel: {
|
|
121
|
+
fields: true,
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
const fields = [];
|
|
126
|
+
if (model) {
|
|
127
|
+
// Add the fields of the current model
|
|
128
|
+
fields.push(...model.fields);
|
|
108
129
|
|
|
130
|
+
// Add the fields of the parent model
|
|
131
|
+
if (model.parentModel) {
|
|
132
|
+
fields.push(...model.parentModel.fields);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return fields;
|
|
136
|
+
}
|
|
109
137
|
}
|
package/src/index.ts
CHANGED
|
@@ -279,6 +279,7 @@ export * from './factories/mail.factory'
|
|
|
279
279
|
export * from './repository/solid-base.repository'
|
|
280
280
|
export * from './repository/security-rule.repository'
|
|
281
281
|
export * from './repository/field.repository'
|
|
282
|
+
export * from './repository/chatter-message.repository'
|
|
282
283
|
|
|
283
284
|
|
|
284
285
|
//softDeleteAwareEventSubscriber.subscriber.ts
|
|
@@ -8,8 +8,8 @@ import { RoleMetadata } from 'src/entities/role-metadata.entity';
|
|
|
8
8
|
import { SecurityRule } from 'src/entities/security-rule.entity';
|
|
9
9
|
import { SolidRegistry } from 'src/helpers/solid-registry';
|
|
10
10
|
import { ActiveUserData } from 'src/interfaces/active-user-data.interface';
|
|
11
|
-
import { CrudHelperService } from 'src/services/crud-helper.service';
|
|
12
|
-
import { DataSource, Repository, SelectQueryBuilder } from 'typeorm';
|
|
11
|
+
import { CrudHelperService, FilterCombinator } from 'src/services/crud-helper.service';
|
|
12
|
+
import { Brackets, DataSource, Repository, SelectQueryBuilder } from 'typeorm';
|
|
13
13
|
|
|
14
14
|
@Injectable()
|
|
15
15
|
export class SecurityRuleRepository extends Repository<SecurityRule> {
|
|
@@ -26,18 +26,31 @@ export class SecurityRuleRepository extends Repository<SecurityRule> {
|
|
|
26
26
|
// Fetch the security rules for the model and roles
|
|
27
27
|
const securityRules = this.solidRegistry.getSecurityRules(modelSingularName, activeUser.roles);
|
|
28
28
|
|
|
29
|
-
//
|
|
30
|
-
securityRules.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
// If no security rules, return the original query builder
|
|
30
|
+
if (!securityRules.length) {
|
|
31
|
+
return qb;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Apply each security rule to the query builder. The rules are combined with OR logic at the top level.
|
|
35
|
+
qb.andWhere(new Brackets((outerQb) => {
|
|
36
|
+
for (const rule of securityRules) {
|
|
37
|
+
try {
|
|
38
|
+
const parsedRule = JSON.parse(
|
|
39
|
+
this.resolveSecurityRuleConfig(rule.securityRuleConfig, activeUser)
|
|
40
|
+
) as SecurityRuleConfig;
|
|
41
|
+
|
|
34
42
|
if (parsedRule && parsedRule.filters) {
|
|
35
|
-
|
|
43
|
+
outerQb.orWhere( // combine each rule-group with OR at the outer level
|
|
44
|
+
new Brackets((innerQb) => {
|
|
45
|
+
this.crudHelperService.applyFilters(innerQb, parsedRule.filters, securityRuleAlias, qb); // AND within a rule
|
|
46
|
+
})
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
} catch (error) {
|
|
50
|
+
this.logger.warn(`Error parsing security rule: ${rule.securityRuleConfig}`, error);
|
|
36
51
|
}
|
|
37
|
-
} catch (error) {
|
|
38
|
-
this.logger.warn(`Error parsing security rule: ${rule.securityRuleConfig}`, error);
|
|
39
52
|
}
|
|
40
|
-
});
|
|
53
|
+
}));
|
|
41
54
|
|
|
42
55
|
return qb;
|
|
43
56
|
}
|
|
@@ -85,7 +98,7 @@ export class SecurityRuleRepository extends Repository<SecurityRule> {
|
|
|
85
98
|
},
|
|
86
99
|
});
|
|
87
100
|
createDto['role'] = role;
|
|
88
|
-
}
|
|
101
|
+
}
|
|
89
102
|
|
|
90
103
|
if (createDto.roleUserKey) {
|
|
91
104
|
const role = await roleRepository.findOne({
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Injectable } from "@nestjs/common";
|
|
2
|
+
import { User } from "src/entities/user.entity";
|
|
3
|
+
import { RequestContextService } from "src/services/request-context.service";
|
|
4
|
+
import { DataSource } from "typeorm";
|
|
5
|
+
import { SecurityRuleRepository } from "./security-rule.repository";
|
|
6
|
+
import { SolidBaseRepository } from "./solid-base.repository";
|
|
7
|
+
|
|
8
|
+
@Injectable()
|
|
9
|
+
export class UserRepository extends SolidBaseRepository<User> {
|
|
10
|
+
constructor(
|
|
11
|
+
readonly dataSource: DataSource,
|
|
12
|
+
readonly requestContextService: RequestContextService,
|
|
13
|
+
readonly securityRuleRepository: SecurityRuleRepository,
|
|
14
|
+
) {
|
|
15
|
+
super(User, dataSource, requestContextService, securityRuleRepository);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -41,7 +41,8 @@ import { CreateDashboardDto } from 'src/dtos/create-dashboard.dto';
|
|
|
41
41
|
import { DashboardRepository } from 'src/repository/dashboard.repository';
|
|
42
42
|
// import { CreateScheduledJobDto } from 'src/dtos/create-scheduled-job.dto';
|
|
43
43
|
import { ScheduledJobRepository } from 'src/repository/scheduled-job.repository';
|
|
44
|
-
import { CreateScheduledJobDto } from 'src/dtos/create-scheduled-job.dto'
|
|
44
|
+
import { CreateScheduledJobDto } from 'src/dtos/create-scheduled-job.dto'
|
|
45
|
+
import { deepFreeze } from 'src/helpers';
|
|
45
46
|
|
|
46
47
|
@Injectable()
|
|
47
48
|
export class ModuleMetadataSeederService {
|
|
@@ -128,7 +129,8 @@ export class ModuleMetadataSeederService {
|
|
|
128
129
|
for (let i = 0; i < seedDataFiles.length; i++) {
|
|
129
130
|
|
|
130
131
|
// Module, model & field handling.
|
|
131
|
-
const overallMetadata = seedDataFiles[i];
|
|
132
|
+
const overallMetadata = deepFreeze(seedDataFiles[i]);
|
|
133
|
+
|
|
132
134
|
// const fullPath = path.join(process.cwd(), seedDataFile);
|
|
133
135
|
|
|
134
136
|
// For each module metadata seed file provided, read contents, parse & convert to a variable.
|
|
@@ -317,14 +319,20 @@ export class ModuleMetadataSeederService {
|
|
|
317
319
|
}
|
|
318
320
|
}
|
|
319
321
|
|
|
320
|
-
async seedMediaStorageProviders(
|
|
322
|
+
async seedMediaStorageProviders(_mediaStorageProviders: any) {
|
|
323
|
+
const mediaStorageProviders = structuredClone(_mediaStorageProviders);
|
|
324
|
+
if (!mediaStorageProviders) {
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
321
327
|
for (let i = 0; i < mediaStorageProviders.length; i++) {
|
|
322
328
|
const mediaStorageProivder = mediaStorageProviders[i];
|
|
323
329
|
await this.mediaStorageProviderMetadataService.upsert(mediaStorageProivder);
|
|
324
330
|
}
|
|
325
331
|
}
|
|
326
332
|
|
|
327
|
-
async seedEmailTemplates(
|
|
333
|
+
async seedEmailTemplates(_emailTemplates: CreateEmailTemplateDto[], _moduleMetadata: CreateModuleMetadataDto) {
|
|
334
|
+
const emailTemplates = structuredClone(_emailTemplates);
|
|
335
|
+
const moduleMetadata = structuredClone(_moduleMetadata);
|
|
328
336
|
if (!emailTemplates) {
|
|
329
337
|
return;
|
|
330
338
|
}
|
|
@@ -360,7 +368,9 @@ export class ModuleMetadataSeederService {
|
|
|
360
368
|
|
|
361
369
|
}
|
|
362
370
|
|
|
363
|
-
async seedSmsTemplates(
|
|
371
|
+
async seedSmsTemplates(_smsTemplates: CreateSmsTemplateDto[], _moduleMetadata: CreateModuleMetadataDto) {
|
|
372
|
+
const smsTemplates = structuredClone(_smsTemplates);
|
|
373
|
+
const moduleMetadata = structuredClone(_moduleMetadata);
|
|
364
374
|
if (!smsTemplates) {
|
|
365
375
|
return;
|
|
366
376
|
}
|
|
@@ -397,6 +407,7 @@ export class ModuleMetadataSeederService {
|
|
|
397
407
|
}
|
|
398
408
|
|
|
399
409
|
async seedMenus(menus: any) {
|
|
410
|
+
// const menus = structuredClone(_menus);
|
|
400
411
|
if (!menus) {
|
|
401
412
|
return;
|
|
402
413
|
}
|
|
@@ -434,7 +445,8 @@ export class ModuleMetadataSeederService {
|
|
|
434
445
|
}
|
|
435
446
|
}
|
|
436
447
|
|
|
437
|
-
async seedActions(
|
|
448
|
+
async seedActions(_actions: any) {
|
|
449
|
+
const actions = structuredClone(_actions);
|
|
438
450
|
if (!actions) {
|
|
439
451
|
return;
|
|
440
452
|
}
|
|
@@ -455,7 +467,8 @@ export class ModuleMetadataSeederService {
|
|
|
455
467
|
}
|
|
456
468
|
}
|
|
457
469
|
|
|
458
|
-
async seedViews(
|
|
470
|
+
async seedViews(_views: any) {
|
|
471
|
+
const views = structuredClone(_views);
|
|
459
472
|
if (!views) {
|
|
460
473
|
return;
|
|
461
474
|
}
|
|
@@ -478,7 +491,8 @@ export class ModuleMetadataSeederService {
|
|
|
478
491
|
}
|
|
479
492
|
}
|
|
480
493
|
|
|
481
|
-
async seedUsers(
|
|
494
|
+
async seedUsers(_users) {
|
|
495
|
+
const users = structuredClone(_users);
|
|
482
496
|
if (!users) {
|
|
483
497
|
return;
|
|
484
498
|
}
|
|
@@ -499,8 +513,8 @@ export class ModuleMetadataSeederService {
|
|
|
499
513
|
}
|
|
500
514
|
}
|
|
501
515
|
|
|
502
|
-
async seedModuleModelFields(
|
|
503
|
-
|
|
516
|
+
async seedModuleModelFields(_moduleMetadata: CreateModuleMetadataDto) {
|
|
517
|
+
const moduleMetadata = structuredClone(_moduleMetadata);
|
|
504
518
|
// First we create the module.
|
|
505
519
|
// await this.moduleMetadataService.removeByName(moduleMetadata.name);
|
|
506
520
|
// const module = await this.moduleMetadataService.create(moduleMetadata);
|
|
@@ -561,14 +575,16 @@ export class ModuleMetadataSeederService {
|
|
|
561
575
|
}
|
|
562
576
|
}
|
|
563
577
|
|
|
564
|
-
async seedSettings(
|
|
578
|
+
async seedSettings(_createDto: CreateSettingDto) {
|
|
579
|
+
const createDto = structuredClone(_createDto);
|
|
565
580
|
const settingsArray: any[] = await this.settingsRepo.find();
|
|
566
581
|
if (!settingsArray || settingsArray.length === 0) {
|
|
567
582
|
this.seetingService.create(createDto);
|
|
568
583
|
}
|
|
569
584
|
}
|
|
570
585
|
|
|
571
|
-
async seedSecurityRules(
|
|
586
|
+
async seedSecurityRules(_rulesDto: CreateSecurityRuleDto[]) {
|
|
587
|
+
const rulesDto = structuredClone(_rulesDto);
|
|
572
588
|
if (!rulesDto || rulesDto.length === 0) {
|
|
573
589
|
this.logger.debug(`No security rules found to seed`);
|
|
574
590
|
return;
|
|
@@ -578,17 +594,21 @@ export class ModuleMetadataSeederService {
|
|
|
578
594
|
}
|
|
579
595
|
}
|
|
580
596
|
|
|
581
|
-
async seedListOfValues(
|
|
597
|
+
async seedListOfValues(_listOfValuesDto: CreateListOfValuesDto[]) {
|
|
598
|
+
const listOfValuesDto = structuredClone(_listOfValuesDto);
|
|
582
599
|
if (!listOfValuesDto || listOfValuesDto.length === 0) {
|
|
583
600
|
this.logger.debug(`No List Of Values found to seed`);
|
|
584
601
|
return;
|
|
585
602
|
}
|
|
586
603
|
for (let j = 0; j < listOfValuesDto.length; j++) {
|
|
604
|
+
const listOfValueDto = listOfValuesDto[j];
|
|
605
|
+
listOfValueDto['module'] = await this.moduleMetadataService.findOneByUserKey(listOfValueDto.moduleUserKey);
|
|
587
606
|
await this.listOfValuesService.upsert(listOfValuesDto[j]);
|
|
588
607
|
}
|
|
589
608
|
}
|
|
590
609
|
|
|
591
|
-
async seedDashboards(
|
|
610
|
+
async seedDashboards(_dashboardDtos: CreateDashboardDto[]) {
|
|
611
|
+
const dashboardDtos = structuredClone(_dashboardDtos);
|
|
592
612
|
if (!dashboardDtos || dashboardDtos.length === 0) {
|
|
593
613
|
this.logger.debug(`No dashboards found to seed`);
|
|
594
614
|
return;
|
|
@@ -598,7 +618,8 @@ export class ModuleMetadataSeederService {
|
|
|
598
618
|
}
|
|
599
619
|
}
|
|
600
620
|
|
|
601
|
-
async seedScheduledJobs(
|
|
621
|
+
async seedScheduledJobs(_createScheduledJobDto: CreateScheduledJobDto[]) {
|
|
622
|
+
const createScheduledJobDto = structuredClone(_createScheduledJobDto);
|
|
602
623
|
if (!createScheduledJobDto || createScheduledJobDto.length === 0) {
|
|
603
624
|
this.logger.debug(`No scheduled jobs found to seed`);
|
|
604
625
|
return;
|
|
@@ -1697,6 +1697,7 @@
|
|
|
1697
1697
|
"dataSourceType": "postgres",
|
|
1698
1698
|
"userKeyFieldUserKey": "username",
|
|
1699
1699
|
"isSystem": true,
|
|
1700
|
+
"enableAuditTracking": true,
|
|
1700
1701
|
"fields": [
|
|
1701
1702
|
{
|
|
1702
1703
|
"name": "fullName",
|
|
@@ -1709,7 +1710,8 @@
|
|
|
1709
1710
|
"index": false,
|
|
1710
1711
|
"private": false,
|
|
1711
1712
|
"encrypt": false,
|
|
1712
|
-
"isSystem": true
|
|
1713
|
+
"isSystem": true,
|
|
1714
|
+
"enableAuditTracking": true
|
|
1713
1715
|
},
|
|
1714
1716
|
{
|
|
1715
1717
|
"name": "username",
|
|
@@ -1722,7 +1724,8 @@
|
|
|
1722
1724
|
"index": true,
|
|
1723
1725
|
"private": false,
|
|
1724
1726
|
"encrypt": false,
|
|
1725
|
-
"isSystem": true
|
|
1727
|
+
"isSystem": true,
|
|
1728
|
+
"enableAuditTracking": true
|
|
1726
1729
|
},
|
|
1727
1730
|
{
|
|
1728
1731
|
"name": "email",
|
|
@@ -1735,7 +1738,8 @@
|
|
|
1735
1738
|
"index": true,
|
|
1736
1739
|
"private": false,
|
|
1737
1740
|
"encrypt": false,
|
|
1738
|
-
"isSystem": true
|
|
1741
|
+
"isSystem": true,
|
|
1742
|
+
"enableAuditTracking": true
|
|
1739
1743
|
},
|
|
1740
1744
|
{
|
|
1741
1745
|
"name": "mobile",
|
|
@@ -1748,7 +1752,8 @@
|
|
|
1748
1752
|
"index": true,
|
|
1749
1753
|
"private": false,
|
|
1750
1754
|
"encrypt": false,
|
|
1751
|
-
"isSystem": true
|
|
1755
|
+
"isSystem": true,
|
|
1756
|
+
"enableAuditTracking": true
|
|
1752
1757
|
},
|
|
1753
1758
|
{
|
|
1754
1759
|
"name": "password",
|
|
@@ -1884,7 +1889,8 @@
|
|
|
1884
1889
|
"relationCascade": "cascade",
|
|
1885
1890
|
"relationModelModuleName": "solid-core",
|
|
1886
1891
|
"isSystem": true,
|
|
1887
|
-
"isRelationManyToManyOwner": true
|
|
1892
|
+
"isRelationManyToManyOwner": true,
|
|
1893
|
+
"enableAuditTracking": true
|
|
1888
1894
|
},
|
|
1889
1895
|
{
|
|
1890
1896
|
"name": "forgotPasswordConfirmedAt",
|
|
@@ -12256,5 +12262,33 @@
|
|
|
12256
12262
|
],
|
|
12257
12263
|
"checksums": [],
|
|
12258
12264
|
"listOfValues": [],
|
|
12259
|
-
"scheduledJobs": []
|
|
12265
|
+
"scheduledJobs": [],
|
|
12266
|
+
"securityRules": [
|
|
12267
|
+
{
|
|
12268
|
+
"name": "model:User-role:Internal User",
|
|
12269
|
+
"description": "Show User record for the current user only",
|
|
12270
|
+
"roleUserKey": "Internal User",
|
|
12271
|
+
"modelMetadataUserKey": "user",
|
|
12272
|
+
"securityRuleConfig": {
|
|
12273
|
+
"filters": {
|
|
12274
|
+
"id": {
|
|
12275
|
+
"$eq": "$activeUserId"
|
|
12276
|
+
}
|
|
12277
|
+
}
|
|
12278
|
+
}
|
|
12279
|
+
},
|
|
12280
|
+
{
|
|
12281
|
+
"name": "model:User-role:Admin",
|
|
12282
|
+
"description": "Show All User records",
|
|
12283
|
+
"roleUserKey": "Admin",
|
|
12284
|
+
"modelMetadataUserKey": "user",
|
|
12285
|
+
"securityRuleConfig": {
|
|
12286
|
+
"filters": {
|
|
12287
|
+
"id": {
|
|
12288
|
+
"$ne": "0"
|
|
12289
|
+
}
|
|
12290
|
+
}
|
|
12291
|
+
}
|
|
12292
|
+
}
|
|
12293
|
+
]
|
|
12260
12294
|
}
|
|
@@ -126,7 +126,7 @@ export class AuthenticationService {
|
|
|
126
126
|
const user = await this.resolveUser(signInDto.username, signInDto.email);
|
|
127
127
|
|
|
128
128
|
if (!user) {
|
|
129
|
-
throw new UnauthorizedException(ERROR_MESSAGES.
|
|
129
|
+
throw new UnauthorizedException(ERROR_MESSAGES.INVALID_CREDENTIALS);
|
|
130
130
|
}
|
|
131
131
|
if (!user.active) {
|
|
132
132
|
throw new UnauthorizedException(ERROR_MESSAGES.USER_NOT_ACTIVE);
|
|
@@ -136,7 +136,7 @@ export class AuthenticationService {
|
|
|
136
136
|
user.password,
|
|
137
137
|
);
|
|
138
138
|
if (!isEqual) {
|
|
139
|
-
throw new UnauthorizedException(ERROR_MESSAGES.
|
|
139
|
+
throw new UnauthorizedException(ERROR_MESSAGES.INVALID_CREDENTIALS);
|
|
140
140
|
}
|
|
141
141
|
|
|
142
142
|
return user;
|
|
@@ -759,25 +759,31 @@ export class AuthenticationService {
|
|
|
759
759
|
// });
|
|
760
760
|
const user = await this.resolveUser(initiateForgotPasswordDto.username, initiateForgotPasswordDto.email);
|
|
761
761
|
|
|
762
|
+
let isValidUser = true // Instead of throwing exceptions we will simply return success message, this is to avoid user enumeration attacks.
|
|
762
763
|
if (!user) {
|
|
763
|
-
|
|
764
|
+
isValidUser = false
|
|
765
|
+
// throw new NotFoundException(ERROR_MESSAGES.INVALID_CREDENTIALS);
|
|
764
766
|
}
|
|
765
767
|
if (!user.active) {
|
|
766
|
-
|
|
768
|
+
isValidUser = false
|
|
769
|
+
// throw new UnauthorizedException(ERROR_MESSAGES.INVALID_CREDENTIALS);
|
|
767
770
|
}
|
|
768
771
|
|
|
769
772
|
// 2. Validate if user has used a provider which is "local", only then it makes sense for us to initiate the forgot password routine.
|
|
770
773
|
if (user.lastLoginProvider !== 'local') {
|
|
771
|
-
|
|
774
|
+
isValidUser = false
|
|
775
|
+
// throw new BadRequestException(ERROR_MESSAGES.INVALID_CREDENTIALS);
|
|
772
776
|
}
|
|
773
777
|
|
|
774
778
|
// 3. Generate a 6 digit validation token, we send this token to the user over their email & mobile number (controlled using configuration).
|
|
775
779
|
// 4. Save this validation token in new fields on the user record.
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
780
|
+
if (isValidUser) {
|
|
781
|
+
const { token, expiresAt } = this.generateForgotPasswordToken();
|
|
782
|
+
user.verificationTokenOnForgotPassword = token;
|
|
783
|
+
user.verificationTokenOnForgotPasswordExpiresAt = expiresAt;
|
|
784
|
+
await this.userRepository.save(user);
|
|
785
|
+
this.notifyUserOnForgotPassword(user);
|
|
786
|
+
}
|
|
781
787
|
|
|
782
788
|
// 5. Return.
|
|
783
789
|
return {
|
|
@@ -788,8 +794,8 @@ export class AuthenticationService {
|
|
|
788
794
|
data: {
|
|
789
795
|
user: {
|
|
790
796
|
email: user.email,
|
|
791
|
-
mobile: user.mobile,
|
|
792
|
-
username: user.username,
|
|
797
|
+
// mobile: user.mobile,
|
|
798
|
+
// username: user.username,
|
|
793
799
|
},
|
|
794
800
|
}
|
|
795
801
|
}
|
|
@@ -841,8 +847,8 @@ export class AuthenticationService {
|
|
|
841
847
|
return this.dataSource.transaction(async (m) => {
|
|
842
848
|
// Resolve the user id first (by username/email), but DON'T check the token in JS.
|
|
843
849
|
const user = await this.resolveUserByVerificationToken(confirmForgotPasswordDto.verificationToken);
|
|
844
|
-
if (!user) throw new
|
|
845
|
-
if (user.lastLoginProvider !== 'local') throw new
|
|
850
|
+
if (!user) throw new UnauthorizedException(ERROR_MESSAGES.INVALID_CREDENTIALS);
|
|
851
|
+
if (user.lastLoginProvider !== 'local') throw new UnauthorizedException(ERROR_MESSAGES.INVALID_CREDENTIALS);
|
|
846
852
|
if (!user.active) throw new UnauthorizedException(ERROR_MESSAGES.INVALID_CREDENTIALS);
|
|
847
853
|
|
|
848
854
|
// 1) Atomically consume the token (only one request can succeed)
|