@solidstarters/solid-core 1.2.143 → 1.2.144
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/constants/error-messages.d.ts +83 -0
- package/dist/constants/error-messages.d.ts.map +1 -0
- package/dist/constants/error-messages.js +86 -0
- package/dist/constants/error-messages.js.map +1 -0
- package/dist/constants/success-messages.d.ts +11 -0
- package/dist/constants/success-messages.d.ts.map +1 -0
- package/dist/constants/success-messages.js +14 -0
- package/dist/constants/success-messages.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/services/ai-interaction.service.d.ts.map +1 -1
- package/dist/services/ai-interaction.service.js +4 -3
- package/dist/services/ai-interaction.service.js.map +1 -1
- package/dist/services/authentication.service.d.ts.map +1 -1
- package/dist/services/authentication.service.js +66 -64
- package/dist/services/authentication.service.js.map +1 -1
- package/dist/services/crud-helper.service.d.ts.map +1 -1
- package/dist/services/crud-helper.service.js +3 -2
- package/dist/services/crud-helper.service.js.map +1 -1
- package/dist/services/crud.service.d.ts.map +1 -1
- package/dist/services/crud.service.js +23 -21
- package/dist/services/crud.service.js.map +1 -1
- package/dist/services/csv.service.d.ts.map +1 -1
- package/dist/services/csv.service.js +3 -2
- package/dist/services/csv.service.js.map +1 -1
- package/dist/services/excel.service.d.ts.map +1 -1
- package/dist/services/excel.service.js +3 -2
- package/dist/services/excel.service.js.map +1 -1
- package/dist/services/export-transaction.service.d.ts.map +1 -1
- package/dist/services/export-transaction.service.js +2 -1
- package/dist/services/export-transaction.service.js.map +1 -1
- package/dist/services/field-metadata.service.d.ts.map +1 -1
- package/dist/services/field-metadata.service.js +9 -8
- package/dist/services/field-metadata.service.js.map +1 -1
- package/dist/services/file.service.d.ts.map +1 -1
- package/dist/services/file.service.js +5 -4
- package/dist/services/file.service.js.map +1 -1
- package/dist/services/import-transaction.service.d.ts.map +1 -1
- package/dist/services/import-transaction.service.js +10 -9
- package/dist/services/import-transaction.service.js.map +1 -1
- package/dist/services/media-storage-provider-metadata.service.d.ts.map +1 -1
- package/dist/services/media-storage-provider-metadata.service.js +4 -3
- package/dist/services/media-storage-provider-metadata.service.js.map +1 -1
- package/dist/services/media.service.d.ts.map +1 -1
- package/dist/services/media.service.js +2 -1
- package/dist/services/media.service.js.map +1 -1
- package/dist/services/model-metadata.service.d.ts.map +1 -1
- package/dist/services/model-metadata.service.js +10 -9
- package/dist/services/model-metadata.service.js.map +1 -1
- package/dist/services/module-metadata.service.d.ts.map +1 -1
- package/dist/services/module-metadata.service.js +11 -10
- package/dist/services/module-metadata.service.js.map +1 -1
- package/dist/services/role-metadata.service.d.ts.map +1 -1
- package/dist/services/role-metadata.service.js +3 -2
- package/dist/services/role-metadata.service.js.map +1 -1
- package/dist/services/sql-expression-resolver.service.d.ts.map +1 -1
- package/dist/services/sql-expression-resolver.service.js +2 -1
- package/dist/services/sql-expression-resolver.service.js.map +1 -1
- package/dist/services/user.service.d.ts.map +1 -1
- package/dist/services/user.service.js +11 -10
- package/dist/services/user.service.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/constants/error-messages.ts +123 -0
- package/src/constants/success-messages.ts +13 -0
- package/src/index.ts +3 -1
- package/src/services/ai-interaction.service.ts +4 -3
- package/src/services/authentication.service.ts +66 -64
- package/src/services/crud-helper.service.ts +3 -2
- package/src/services/crud.service.ts +23 -23
- package/src/services/csv.service.ts +3 -2
- package/src/services/excel.service.ts +3 -2
- package/src/services/export-transaction.service.ts +2 -1
- package/src/services/field-metadata.service.ts +9 -8
- package/src/services/file.service.ts +5 -4
- package/src/services/import-transaction.service.ts +10 -9
- package/src/services/media-storage-provider-metadata.service.ts +4 -3
- package/src/services/media.service.ts +2 -1
- package/src/services/model-metadata.service.ts +10 -9
- package/src/services/module-metadata.service.ts +11 -10
- package/src/services/role-metadata.service.ts +3 -2
- package/src/services/sql-expression-resolver.service.ts +2 -1
- package/src/services/user.service.ts +11 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidstarters/solid-core",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.144",
|
|
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",
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// backend/common/constants/error-messages.ts
|
|
2
|
+
|
|
3
|
+
export const ERROR_MESSAGES = {
|
|
4
|
+
//authentication errors
|
|
5
|
+
USER_NOT_FOUND: 'User does not exist.',
|
|
6
|
+
USER_NOT_ACTIVE: 'User profile is not activated.',
|
|
7
|
+
USER_INACTIVE: 'User is inactive.',
|
|
8
|
+
PASSWORD_INCORRECT: 'Password does not match.',
|
|
9
|
+
PUBLIC_REGISTRATION_DISABLED: 'Public registrations are disabled.',
|
|
10
|
+
UNIQUE_CONSTRAINT_VIOLATION: 'A unique constraint violation occurred.',
|
|
11
|
+
PASSWORDLESS_REGISTRATION_DISABLED: 'Passwordless registration is not enabled.',
|
|
12
|
+
REGISTRATION_REQUIRES_CONTACT: 'Either mobile or email is required for initiating registration.',
|
|
13
|
+
EMAIL_REQUIRED_FOR_VALIDATION: 'Email is required for email validation source.',
|
|
14
|
+
MOBILE_REQUIRED_FOR_VALIDATION: 'Mobile is required for mobile validation source.',
|
|
15
|
+
USER_ALREADY_EXISTS: 'User already exists. Please sign in.',
|
|
16
|
+
VALIDATION_SOURCE_REQUIRED: 'At least one validation source is required.',
|
|
17
|
+
INVALID_OTP: 'Invalid OTP.',
|
|
18
|
+
OTP_EXPIRED: 'OTP has expired.',
|
|
19
|
+
INVALID_VERIFICATION_TYPE: 'Invalid type. Must be either email or mobile.',
|
|
20
|
+
NON_LOCAL_PROVIDER: 'User seems to have used a passwordless mode to authenticate.',
|
|
21
|
+
USER_ID_MISMATCH: "User ID's do not match.",
|
|
22
|
+
USERNAME_MISMATCH: "User username's do not match.",
|
|
23
|
+
INCORRECT_CURRENT_PASSWORD: 'Incorrect current password specified.',
|
|
24
|
+
PASSWORD_REUSED: 'This password was previously used, please use a different password.',
|
|
25
|
+
INVALID_VERIFICATION_TOKEN: 'Invalid verification token',
|
|
26
|
+
ACCESS_DENIED: 'Access denied',
|
|
27
|
+
INVALID_USER_PROFILE: 'Invalid user profile',
|
|
28
|
+
GOOGLE_OAUTH_PROFILE_FETCH_FAILED: 'Failed to fetch user profile from Google OAuth service',
|
|
29
|
+
LOGOUT_FAILED: 'Logout failed due to an unexpected error.',
|
|
30
|
+
|
|
31
|
+
INVALID_CREDENTIALS: 'Invalid username or password specified.',
|
|
32
|
+
LOGIN_FAILED: 'Login Failed',
|
|
33
|
+
OLD_PASSWORD_INCORRECT: 'You have specified an incorrect old password.',
|
|
34
|
+
INVALID_NEW_PASSWORD: 'Invalid new password.',
|
|
35
|
+
PASSWORDS_DO_NOT_MATCH: 'New passwords are not matching.',
|
|
36
|
+
|
|
37
|
+
// user management errors
|
|
38
|
+
DELETE_SELF_NOT_ALLOWED: 'Deleting logged-in user is not allowed.',
|
|
39
|
+
DELETE_IDS_REQUIRED: 'At least one ID is required for deletion.',
|
|
40
|
+
USER_MISSING_ID: 'User must exist before initializing roles.',
|
|
41
|
+
ROLES_NOT_FOUND: (roles: string[]) => `The following roles were not found: ${roles.join(', ')}`,
|
|
42
|
+
USER_NOT_FOUND_BY_USERNAME: (username: string) => `User with username '${username}' not found.`,
|
|
43
|
+
ROLE_NOT_FOUND: (roleName: string) => `Role '${roleName}' not found.`,
|
|
44
|
+
PERMISSION_NOT_EXIST: (permission: string) => `Permission '${permission}' does not exist.`,
|
|
45
|
+
|
|
46
|
+
// session errors
|
|
47
|
+
SESSION_INVALID: 'Your session is no longer valid. Please log in again.',
|
|
48
|
+
SESSION_EXPIRED: 'Your session has expired. Please log in again.',
|
|
49
|
+
|
|
50
|
+
// filter errors
|
|
51
|
+
GROUP_BY_LIMIT: 'buildFilterQuery: Only 1 Group by field is supported currently.',
|
|
52
|
+
INVALID_GROUP_BY_COUNT: 'Exactly one groupBy field is required to count grouped records.',
|
|
53
|
+
|
|
54
|
+
// general errors
|
|
55
|
+
FORBIDDEN: 'Forbidden',
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
// database errors
|
|
59
|
+
DUPLICATE_ENTRY: 'Duplicate entry. A record with similar unique fields already exists.',
|
|
60
|
+
|
|
61
|
+
// validation errors
|
|
62
|
+
ID_REQUIRED_FOR_UPDATE: 'Id is required for update.',
|
|
63
|
+
ID_REQUIRED_FOR_DELETE: 'Id is required for deletion.',
|
|
64
|
+
|
|
65
|
+
// CRUD service errors
|
|
66
|
+
RELATION_TYPE_NOT_SUPPORTED: 'Relation type not supported in CRUD service.',
|
|
67
|
+
NO_SOFT_DELETED_RECORD_FOUND: 'No soft-deleted record found with the given ID.',
|
|
68
|
+
CONFLICTING_RECORD_ON_UNARCHIVE: 'Another record is conflicting with the record you are attempting to Un-Archive, either delete or change the other record so as to avoid this conflict.',
|
|
69
|
+
NO_SOFT_DELETED_RECORDS_FOUND: 'No matching soft-deleted records found.',
|
|
70
|
+
EMPTY_PATH_PARTS: 'Path parts cannot be empty',
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
// CSV/Excel service errors
|
|
74
|
+
MISSING_HEADERS_OR_FUNCTION: 'Either headers or data records function must be provided.',
|
|
75
|
+
INVALID_CHUNK_SIZE: 'Chunk size must be greater than 0 when data records function is provided.',
|
|
76
|
+
INVALID_FORMAT: (format: string) => `Invalid ${format} format`,
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
//field errors
|
|
80
|
+
INVALID_INVERSE_FIELD_TYPE: 'Only relation fields can have inverse fields.',
|
|
81
|
+
MODEL_AND_MODULE_REQUIRED_TO_UPDATE_INVERSE_FIELD: 'Model and module are required to update inverse field.',
|
|
82
|
+
MODEL_NAME_AND_MODULE_NAME_REQUIRED_TO_CREATE_INVERSE_FIELD: 'Model name and module name are required to create inverse field.',
|
|
83
|
+
FIELD_NOT_FOUND: (id: number | string) => `No field with id #${id} exists`,
|
|
84
|
+
PROVIDER_NOT_FOUND: (provider: string) => `Field incorrectly configured. No provider with name ${provider} registered in backend.`,
|
|
85
|
+
FILE_WRITE_FAILED: 'File creation failed, rolling back transaction',
|
|
86
|
+
|
|
87
|
+
// file service errors
|
|
88
|
+
FILE_NOT_FOUND: 'File not found',
|
|
89
|
+
FILE_COPY_ERROR: 'Error copying file',
|
|
90
|
+
S3_CLIENT_NOT_INITIALIZED: 'S3 Client not initialized. Please check the S3 configuration.',
|
|
91
|
+
|
|
92
|
+
// model errors
|
|
93
|
+
MODEL_METADATA_NOT_FOUND: (id: string | number) => `Model metadata with ID ${id} not found.`,
|
|
94
|
+
MODEL_SERVICE_NOT_FOUND: (model: string) => `Model service for ${model} not found.`,
|
|
95
|
+
RELATION_CO_MODEL_NOT_DEFINED_FOR_FIELD: (fieldName: string) => `Relation coModelSingularName is not defined for relation field ${fieldName}`,
|
|
96
|
+
MODEL_NOT_FOUND: (singularName?: string) => `Model${singularName ? ` with singular name "${singularName}"` : ''} not found.`,
|
|
97
|
+
MODEL_REQUIRED_FOR_CODE_GENERATION: 'Model ID or Model Name is required for generating code.',
|
|
98
|
+
|
|
99
|
+
//module errors
|
|
100
|
+
MODULE_NOT_FOUND: (moduleName: string) => `Module with name ${moduleName} not found.`,
|
|
101
|
+
MODULE_ID_NOT_FOUND: (id: string | number) => `Module with ID ${id} not found.`,
|
|
102
|
+
|
|
103
|
+
//entity errors
|
|
104
|
+
ENTITY_NOT_FOUND: (entity?: string | number) => `Entity${entity ? ' ' + entity : ''} not found.`,
|
|
105
|
+
ENTITY_NAME_REQUIRED: 'Entity name is required to find the entity.',
|
|
106
|
+
ENTITY_ID_REQUIRED: 'Entity ID is required to find the entity.',
|
|
107
|
+
|
|
108
|
+
// import errors
|
|
109
|
+
NO_ERROR_LOG_FOR_IMPORT: (id: string | number) => `No error log entries found for import transaction ID ${id}.`,
|
|
110
|
+
FILE_READ_FAILED_FROM_URL: (url: string) => `Failed to read file from URL: ${url}`,
|
|
111
|
+
|
|
112
|
+
// media storage provider errors
|
|
113
|
+
MEDIA_STORAGE_PROVIDER_ID_NOT_FOUND: (id: number | string) => `Media Storage Provider with #${id} not found.`,
|
|
114
|
+
MEDIA_STORAGE_PROVIDER_NOT_FOUND: 'Media Storage Provider not found',
|
|
115
|
+
|
|
116
|
+
// SQL errors
|
|
117
|
+
UNSUPPORTED_SQL_OPERATOR: (operator: string) => `Unsupported SQL operator: ${operator}`,
|
|
118
|
+
|
|
119
|
+
// AI interaction errors
|
|
120
|
+
PYTHON_EXECUTABLE_NOT_CONFIGURED: 'SolidX AI MCP python executable or client path not configured.',
|
|
121
|
+
UNABLE_TO_RESOLVE_SOLID_COMMAND: 'Unable to resolve a solid_ command that was used to come up with this response.',
|
|
122
|
+
UNABLE_TO_RESOLVE_MCP_HANDLER: 'Unable to resolve a mcp tool handler.',
|
|
123
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export const SUCCESS_MESSAGES = {
|
|
2
|
+
OTP_SENT_SUCCESS_REGISTRATION: 'User registration initiated. OTP sent to the user.',
|
|
3
|
+
OTP_SENT_SUCCESS_LOGIN: 'User login initiated. OTP sent to the user.',
|
|
4
|
+
FORGOT_PASSWORD_TOKEN_SENT: 'Forgot password - token generated and sent.',
|
|
5
|
+
FORGOT_PASSWORD_CONFIRMED: 'Forgot password confirmed.',
|
|
6
|
+
LOGOUT_SUCCESS: 'Logged out successfully',
|
|
7
|
+
USER_REGISTERED: 'User registered successfully.',
|
|
8
|
+
|
|
9
|
+
// CRUD service messages
|
|
10
|
+
RECORD_RECOVERED: 'Record successfully recovered',
|
|
11
|
+
SELECTED_RECORDS_RECOVERED: 'Selected records successfully recovered',
|
|
12
|
+
|
|
13
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -282,4 +282,6 @@ export * from './interfaces'
|
|
|
282
282
|
export * from './solid-core.module'
|
|
283
283
|
|
|
284
284
|
export * from './winston.logger'
|
|
285
|
-
export { default as datetimeTransformer } from './transformers/datetime-transformer'
|
|
285
|
+
export { default as datetimeTransformer } from './transformers/datetime-transformer'
|
|
286
|
+
|
|
287
|
+
export { ERROR_MESSAGES } from './constants/error-messages'
|
|
@@ -17,6 +17,7 @@ import { PublisherFactory } from './queues/publisher-factory.service';
|
|
|
17
17
|
import { RequestContextService } from './request-context.service';
|
|
18
18
|
import { ActiveUserData } from 'src/interfaces/active-user-data.interface';
|
|
19
19
|
import { McpToolResponseHandlerFactory } from './mcp-tool-response-handlers/mcp-tool-response-handler-factory.service';
|
|
20
|
+
import { ERROR_MESSAGES } from 'src/constants/error-messages';
|
|
20
21
|
|
|
21
22
|
@Injectable()
|
|
22
23
|
export class AiInteractionService extends CRUDService<AiInteraction> {
|
|
@@ -78,7 +79,7 @@ export class AiInteractionService extends CRUDService<AiInteraction> {
|
|
|
78
79
|
|
|
79
80
|
// TODO: We can return an error if the above env variables are not properly setup...
|
|
80
81
|
if (!pythonExecutable || !mcpClient) {
|
|
81
|
-
throw new BadRequestException(
|
|
82
|
+
throw new BadRequestException(ERROR_MESSAGES.PYTHON_EXECUTABLE_NOT_CONFIGURED);
|
|
82
83
|
}
|
|
83
84
|
|
|
84
85
|
// Check if both paths are valid and accessible
|
|
@@ -187,7 +188,7 @@ export class AiInteractionService extends CRUDService<AiInteraction> {
|
|
|
187
188
|
const toolsInvoked = metadata['tools_invoked'];
|
|
188
189
|
if (!toolsInvoked) {
|
|
189
190
|
// TODO: RESPONSE SHAPE ALERT Check if we want to control the shape of the response....
|
|
190
|
-
throw new Error(
|
|
191
|
+
throw new Error(ERROR_MESSAGES.UNABLE_TO_RESOLVE_SOLID_COMMAND);
|
|
191
192
|
}
|
|
192
193
|
|
|
193
194
|
// TODO: OPTIMISATION for chained tool invocation, for now we are assuming only 1 tool was used.
|
|
@@ -198,7 +199,7 @@ export class AiInteractionService extends CRUDService<AiInteraction> {
|
|
|
198
199
|
const mcpToolHandler = this.mcpToolResponseHandlerFactory.getInstance(toolInvoked);
|
|
199
200
|
if (!mcpToolHandler) {
|
|
200
201
|
// TODO: RESPONSE SHAPE ALERT Check if we want to control the shape of the response....
|
|
201
|
-
throw new Error(
|
|
202
|
+
throw new Error(ERROR_MESSAGES.UNABLE_TO_RESOLVE_MCP_HANDLER);
|
|
202
203
|
}
|
|
203
204
|
|
|
204
205
|
const handlerApplicationResponse = await mcpToolHandler.apply(aiInteraction);
|
|
@@ -46,6 +46,8 @@ import { RoleMetadataService } from './role-metadata.service';
|
|
|
46
46
|
import commonConfig from 'src/config/common.config';
|
|
47
47
|
import { UserActivityHistoryService } from './user-activity-history.service';
|
|
48
48
|
import { RequestContextService } from './request-context.service';
|
|
49
|
+
import { ERROR_MESSAGES } from 'src/constants/error-messages';
|
|
50
|
+
import { SUCCESS_MESSAGES } from 'src/constants/success-messages';
|
|
49
51
|
|
|
50
52
|
|
|
51
53
|
enum LoginProvider {
|
|
@@ -111,17 +113,17 @@ export class AuthenticationService {
|
|
|
111
113
|
const user = await this.resolveUser(signInDto.username, signInDto.email);
|
|
112
114
|
|
|
113
115
|
if (!user) {
|
|
114
|
-
throw new UnauthorizedException(
|
|
116
|
+
throw new UnauthorizedException(ERROR_MESSAGES.USER_NOT_FOUND);
|
|
115
117
|
}
|
|
116
118
|
if (!user.active) {
|
|
117
|
-
throw new UnauthorizedException(
|
|
119
|
+
throw new UnauthorizedException(ERROR_MESSAGES.USER_NOT_ACTIVE);
|
|
118
120
|
}
|
|
119
121
|
const isEqual = await this.hashingService.compare(
|
|
120
122
|
signInDto.password,
|
|
121
123
|
user.password,
|
|
122
124
|
);
|
|
123
125
|
if (!isEqual) {
|
|
124
|
-
throw new UnauthorizedException(
|
|
126
|
+
throw new UnauthorizedException(ERROR_MESSAGES.PASSWORD_INCORRECT);
|
|
125
127
|
}
|
|
126
128
|
|
|
127
129
|
return user;
|
|
@@ -130,7 +132,7 @@ export class AuthenticationService {
|
|
|
130
132
|
async signUp(signUpDto: SignUpDto, activeUser: ActiveUserData = null): Promise<User> {
|
|
131
133
|
// If public registrations are disabled and no activeUser is present when invoking signUp then we throw an exception.
|
|
132
134
|
if (!(await this.settingService.getConfigValue('allowPublicRegistration')) && !activeUser) {
|
|
133
|
-
throw new BadRequestException(
|
|
135
|
+
throw new BadRequestException(ERROR_MESSAGES.PUBLIC_REGISTRATION_DISABLED);
|
|
134
136
|
}
|
|
135
137
|
|
|
136
138
|
try {
|
|
@@ -150,7 +152,7 @@ export class AuthenticationService {
|
|
|
150
152
|
} catch (err) {
|
|
151
153
|
const pgUniqueViolationErrorCode = '23505';
|
|
152
154
|
if (err.code === pgUniqueViolationErrorCode) {
|
|
153
|
-
throw new ConflictException();
|
|
155
|
+
throw new ConflictException(ERROR_MESSAGES.USER_ALREADY_EXISTS);
|
|
154
156
|
}
|
|
155
157
|
throw err;
|
|
156
158
|
}
|
|
@@ -172,7 +174,7 @@ export class AuthenticationService {
|
|
|
172
174
|
catch (err) {
|
|
173
175
|
const pgUniqueViolationErrorCode = '23505';
|
|
174
176
|
if (err.code === pgUniqueViolationErrorCode) {
|
|
175
|
-
throw new ConflictException(parseUniqueConstraintError(err.detail ||
|
|
177
|
+
throw new ConflictException(parseUniqueConstraintError(err.detail || ERROR_MESSAGES.UNIQUE_CONSTRAINT_VIOLATION));
|
|
176
178
|
}
|
|
177
179
|
throw err;
|
|
178
180
|
}
|
|
@@ -275,17 +277,17 @@ export class AuthenticationService {
|
|
|
275
277
|
async otpInitiateRegistration(signUpDto: OTPSignUpDto) {
|
|
276
278
|
try {
|
|
277
279
|
if (!this.isPasswordlessRegistrationEnabled()) {
|
|
278
|
-
throw new BadRequestException(
|
|
280
|
+
throw new BadRequestException(ERROR_MESSAGES.PASSWORDLESS_REGISTRATION_DISABLED);
|
|
279
281
|
}
|
|
280
282
|
// Validate if either mobile or email is present.
|
|
281
283
|
if (isEmpty(signUpDto.mobile) && isEmpty(signUpDto.email)) {
|
|
282
|
-
throw new BadRequestException(
|
|
284
|
+
throw new BadRequestException(ERROR_MESSAGES.REGISTRATION_REQUIRES_CONTACT);
|
|
283
285
|
}
|
|
284
286
|
if (signUpDto.validationSources.includes(TransactionalRegistrationValidationSource.EMAIL) && isEmpty(signUpDto.email)) {
|
|
285
|
-
throw new BadRequestException(
|
|
287
|
+
throw new BadRequestException(ERROR_MESSAGES.EMAIL_REQUIRED_FOR_VALIDATION);
|
|
286
288
|
}
|
|
287
289
|
if (signUpDto.validationSources.includes(TransactionalRegistrationValidationSource.MOBILE) && isEmpty(signUpDto.mobile)) {
|
|
288
|
-
throw new BadRequestException(
|
|
290
|
+
throw new BadRequestException(ERROR_MESSAGES.MOBILE_REQUIRED_FOR_VALIDATION);
|
|
289
291
|
}
|
|
290
292
|
|
|
291
293
|
// Validate if user already exists.
|
|
@@ -297,7 +299,7 @@ export class AuthenticationService {
|
|
|
297
299
|
]
|
|
298
300
|
});
|
|
299
301
|
if (isNotEmpty(existingUser) && existingUser.active) {
|
|
300
|
-
throw new ConflictException(
|
|
302
|
+
throw new ConflictException(ERROR_MESSAGES.USER_ALREADY_EXISTS);
|
|
301
303
|
}
|
|
302
304
|
const finalRegistrationVerificationSources = this.calculateVerificationSources(this.iamConfiguration.passwordlessRegistrationValidateWhat, signUpDto);
|
|
303
305
|
let user = existingUser
|
|
@@ -314,11 +316,11 @@ export class AuthenticationService {
|
|
|
314
316
|
|
|
315
317
|
// Send OTP to the user through email or SMS, depending on the configuration.
|
|
316
318
|
this.notifyUserOnOtpInitiateRegistration(user, finalRegistrationVerificationSources);
|
|
317
|
-
return { message:
|
|
319
|
+
return { message: SUCCESS_MESSAGES.OTP_SENT_SUCCESS_REGISTRATION }
|
|
318
320
|
} catch (err) {
|
|
319
321
|
const pgUniqueViolationErrorCode = '23505';
|
|
320
322
|
if (err.code === pgUniqueViolationErrorCode) {
|
|
321
|
-
throw new ConflictException();
|
|
323
|
+
throw new ConflictException(ERROR_MESSAGES.USER_ALREADY_EXISTS);
|
|
322
324
|
}
|
|
323
325
|
throw err;
|
|
324
326
|
}
|
|
@@ -346,7 +348,7 @@ export class AuthenticationService {
|
|
|
346
348
|
// Generate the validation tokens for the user i.e (system configured + user provided)
|
|
347
349
|
private populateVerificationTokens(finalRegistrationValidationSources: string[], user: User) {
|
|
348
350
|
if (finalRegistrationValidationSources.length === 0) {
|
|
349
|
-
throw new BadRequestException(
|
|
351
|
+
throw new BadRequestException(ERROR_MESSAGES.VALIDATION_SOURCE_REQUIRED);
|
|
350
352
|
}
|
|
351
353
|
if (finalRegistrationValidationSources.includes(TransactionalRegistrationValidationSource.EMAIL)) {
|
|
352
354
|
const { token, expiresAt } = this.otp();
|
|
@@ -407,7 +409,7 @@ export class AuthenticationService {
|
|
|
407
409
|
|
|
408
410
|
async otpConfirmRegistration(confirmSignUpDto: OTPConfirmOTPDto) {
|
|
409
411
|
if (!this.isPasswordlessRegistrationEnabled()) {
|
|
410
|
-
throw new BadRequestException(
|
|
412
|
+
throw new BadRequestException(ERROR_MESSAGES.PASSWORDLESS_REGISTRATION_DISABLED);
|
|
411
413
|
}
|
|
412
414
|
|
|
413
415
|
// Based on the identifier, validate by query the user table.
|
|
@@ -418,13 +420,13 @@ export class AuthenticationService {
|
|
|
418
420
|
}
|
|
419
421
|
});
|
|
420
422
|
if (!user) {
|
|
421
|
-
throw new UnauthorizedException(
|
|
423
|
+
throw new UnauthorizedException(ERROR_MESSAGES.USER_NOT_FOUND);
|
|
422
424
|
}
|
|
423
425
|
if (user.emailVerificationTokenOnRegistration !== confirmSignUpDto.otp) {
|
|
424
|
-
throw new UnauthorizedException(
|
|
426
|
+
throw new UnauthorizedException(ERROR_MESSAGES.INVALID_OTP);
|
|
425
427
|
}
|
|
426
428
|
if (user.emailVerificationTokenOnRegistrationExpiresAt < new Date()) {
|
|
427
|
-
throw new UnauthorizedException(
|
|
429
|
+
throw new UnauthorizedException(ERROR_MESSAGES.OTP_EXPIRED);
|
|
428
430
|
}
|
|
429
431
|
user.emailVerifiedOnRegistrationAt = new Date();
|
|
430
432
|
user.emailVerificationTokenOnRegistration = null;
|
|
@@ -440,13 +442,13 @@ export class AuthenticationService {
|
|
|
440
442
|
}
|
|
441
443
|
});
|
|
442
444
|
if (!user) {
|
|
443
|
-
throw new UnauthorizedException(
|
|
445
|
+
throw new UnauthorizedException(ERROR_MESSAGES.USER_NOT_FOUND);
|
|
444
446
|
}
|
|
445
447
|
if (user.mobileVerificationTokenOnRegistration !== confirmSignUpDto.otp) {
|
|
446
|
-
throw new UnauthorizedException(
|
|
448
|
+
throw new UnauthorizedException(ERROR_MESSAGES.INVALID_OTP);
|
|
447
449
|
}
|
|
448
450
|
if (user.mobileVerificationTokenOnRegistrationExpiresAt < new Date()) {
|
|
449
|
-
throw new UnauthorizedException(
|
|
451
|
+
throw new UnauthorizedException(ERROR_MESSAGES.INVALID_OTP);
|
|
450
452
|
}
|
|
451
453
|
user.mobileVerifiedOnRegistrationAt = new Date();
|
|
452
454
|
user.mobileVerificationTokenOnRegistration = null;
|
|
@@ -456,7 +458,7 @@ export class AuthenticationService {
|
|
|
456
458
|
this.triggerRegistrationEvent(savedUser);
|
|
457
459
|
return { active: savedUser.active, message: `User registration verified for ${confirmSignUpDto.type}` }
|
|
458
460
|
}
|
|
459
|
-
throw new BadRequestException(
|
|
461
|
+
throw new BadRequestException(ERROR_MESSAGES.INVALID_VERIFICATION_TYPE);
|
|
460
462
|
}
|
|
461
463
|
|
|
462
464
|
private triggerRegistrationEvent(savedUser: User) {
|
|
@@ -512,7 +514,7 @@ export class AuthenticationService {
|
|
|
512
514
|
|
|
513
515
|
async otpInitiateLogin(signInDto: OTPSignInDto) {
|
|
514
516
|
if (!this.isPasswordlessRegistrationEnabled()) {
|
|
515
|
-
throw new BadRequestException(
|
|
517
|
+
throw new BadRequestException(ERROR_MESSAGES.PASSWORDLESS_REGISTRATION_DISABLED);
|
|
516
518
|
}
|
|
517
519
|
|
|
518
520
|
// Validate & generate otp token for the user based on the identifier type.
|
|
@@ -523,10 +525,10 @@ export class AuthenticationService {
|
|
|
523
525
|
}
|
|
524
526
|
});
|
|
525
527
|
if (!user) {
|
|
526
|
-
throw new UnauthorizedException(
|
|
528
|
+
throw new UnauthorizedException(ERROR_MESSAGES.USER_NOT_FOUND);
|
|
527
529
|
}
|
|
528
530
|
if (!user.active) {
|
|
529
|
-
throw new UnauthorizedException(
|
|
531
|
+
throw new UnauthorizedException(ERROR_MESSAGES.USER_INACTIVE);
|
|
530
532
|
}
|
|
531
533
|
const { token, expiresAt } = this.otp();
|
|
532
534
|
user.emailVerificationTokenOnLogin = token;
|
|
@@ -540,7 +542,7 @@ export class AuthenticationService {
|
|
|
540
542
|
}
|
|
541
543
|
});
|
|
542
544
|
if (!user) {
|
|
543
|
-
throw new UnauthorizedException(
|
|
545
|
+
throw new UnauthorizedException(ERROR_MESSAGES.USER_NOT_FOUND);
|
|
544
546
|
}
|
|
545
547
|
|
|
546
548
|
const { token, expiresAt } = this.otp();
|
|
@@ -550,9 +552,9 @@ export class AuthenticationService {
|
|
|
550
552
|
this.notifyUserOnOtpInititateLogin(user, RegistrationValidationSource.MOBILE);
|
|
551
553
|
}
|
|
552
554
|
else {
|
|
553
|
-
throw new BadRequestException(
|
|
555
|
+
throw new BadRequestException(ERROR_MESSAGES.INVALID_VERIFICATION_TYPE);
|
|
554
556
|
}
|
|
555
|
-
return { message:
|
|
557
|
+
return { message: SUCCESS_MESSAGES.OTP_SENT_SUCCESS_LOGIN };
|
|
556
558
|
}
|
|
557
559
|
|
|
558
560
|
private async notifyUserOnOtpInititateLogin(user: User, loginType: RegistrationValidationSource) {
|
|
@@ -595,7 +597,7 @@ export class AuthenticationService {
|
|
|
595
597
|
|
|
596
598
|
async otpConfirmLogin(confirmSignInDto: OTPConfirmOTPDto) {
|
|
597
599
|
if (!this.isPasswordlessRegistrationEnabled()) {
|
|
598
|
-
throw new BadRequestException(
|
|
600
|
+
throw new BadRequestException(ERROR_MESSAGES.PASSWORDLESS_REGISTRATION_DISABLED);
|
|
599
601
|
}
|
|
600
602
|
if (confirmSignInDto.type === RegistrationValidationSource.EMAIL) {
|
|
601
603
|
const user = await this.userRepository.findOne({
|
|
@@ -605,16 +607,16 @@ export class AuthenticationService {
|
|
|
605
607
|
relations: ['roles']
|
|
606
608
|
});
|
|
607
609
|
if (!user) {
|
|
608
|
-
throw new UnauthorizedException(
|
|
610
|
+
throw new UnauthorizedException(ERROR_MESSAGES.USER_NOT_FOUND);
|
|
609
611
|
}
|
|
610
612
|
if (!user.active) {
|
|
611
|
-
throw new UnauthorizedException(
|
|
613
|
+
throw new UnauthorizedException(ERROR_MESSAGES.USER_INACTIVE);
|
|
612
614
|
}
|
|
613
615
|
if (user.emailVerificationTokenOnLogin !== confirmSignInDto.otp) {
|
|
614
|
-
throw new UnauthorizedException(
|
|
616
|
+
throw new UnauthorizedException(ERROR_MESSAGES.INVALID_OTP);
|
|
615
617
|
}
|
|
616
618
|
if (user.emailVerificationTokenOnLoginExpiresAt < new Date()) {
|
|
617
|
-
throw new UnauthorizedException(
|
|
619
|
+
throw new UnauthorizedException(ERROR_MESSAGES.INVALID_OTP);
|
|
618
620
|
}
|
|
619
621
|
user.emailVerifiedOnLoginAt = new Date();
|
|
620
622
|
user.emailVerificationTokenOnLogin = null;
|
|
@@ -632,16 +634,16 @@ export class AuthenticationService {
|
|
|
632
634
|
relations: ['roles']
|
|
633
635
|
});
|
|
634
636
|
if (!user) {
|
|
635
|
-
throw new UnauthorizedException(
|
|
637
|
+
throw new UnauthorizedException(ERROR_MESSAGES.USER_NOT_ACTIVE);
|
|
636
638
|
}
|
|
637
639
|
if (!user.active) {
|
|
638
|
-
throw new UnauthorizedException(
|
|
640
|
+
throw new UnauthorizedException(ERROR_MESSAGES.USER_INACTIVE);
|
|
639
641
|
}
|
|
640
642
|
if (user.mobileVerificationTokenOnLogin !== confirmSignInDto.otp) {
|
|
641
|
-
throw new UnauthorizedException(
|
|
643
|
+
throw new UnauthorizedException(ERROR_MESSAGES.INVALID_OTP);
|
|
642
644
|
}
|
|
643
645
|
if (user.mobileVerificationTokenOnLoginExpiresAt < new Date()) {
|
|
644
|
-
throw new UnauthorizedException(
|
|
646
|
+
throw new UnauthorizedException(ERROR_MESSAGES.INVALID_OTP);
|
|
645
647
|
}
|
|
646
648
|
user.mobileVerifiedOnLoginAt = new Date();
|
|
647
649
|
user.mobileVerificationTokenOnLogin = null;
|
|
@@ -653,7 +655,7 @@ export class AuthenticationService {
|
|
|
653
655
|
return { accessToken, refreshToken, user: { id, username, email, mobile, lastLoginProvider, roles } };
|
|
654
656
|
|
|
655
657
|
}
|
|
656
|
-
throw new BadRequestException(
|
|
658
|
+
throw new BadRequestException(ERROR_MESSAGES.INVALID_VERIFICATION_TYPE);
|
|
657
659
|
}
|
|
658
660
|
|
|
659
661
|
async changePassword(changePasswordDto: ChangePasswordDto, activeUser: ActiveUserData) {
|
|
@@ -661,26 +663,26 @@ export class AuthenticationService {
|
|
|
661
663
|
where: { id: changePasswordDto.id }
|
|
662
664
|
});
|
|
663
665
|
if (!user) {
|
|
664
|
-
throw new NotFoundException(
|
|
666
|
+
throw new NotFoundException(ERROR_MESSAGES.USER_NOT_FOUND);
|
|
665
667
|
}
|
|
666
668
|
|
|
667
669
|
if (!user.active) {
|
|
668
|
-
throw new UnauthorizedException(
|
|
670
|
+
throw new UnauthorizedException(ERROR_MESSAGES.USER_INACTIVE);
|
|
669
671
|
}
|
|
670
672
|
|
|
671
673
|
// 2. Validate if user has used a provider which is "local", only then it makes sense for us to initiate the forgot password routine.
|
|
672
674
|
if (user.lastLoginProvider !== 'local') {
|
|
673
|
-
throw new BadRequestException(
|
|
675
|
+
throw new BadRequestException(ERROR_MESSAGES.NON_LOCAL_PROVIDER);
|
|
674
676
|
}
|
|
675
677
|
|
|
676
678
|
// Check if ID's match
|
|
677
679
|
if (!(user.id === activeUser.sub)) {
|
|
678
|
-
throw new BadRequestException(
|
|
680
|
+
throw new BadRequestException(ERROR_MESSAGES.USER_ID_MISMATCH);
|
|
679
681
|
}
|
|
680
682
|
|
|
681
683
|
// Check if username's match
|
|
682
684
|
if (!(user.username === activeUser.username)) {
|
|
683
|
-
throw new BadRequestException(
|
|
685
|
+
throw new BadRequestException(ERROR_MESSAGES.USERNAME_MISMATCH);
|
|
684
686
|
}
|
|
685
687
|
|
|
686
688
|
// Check if old password is matching.
|
|
@@ -689,7 +691,7 @@ export class AuthenticationService {
|
|
|
689
691
|
user.password,
|
|
690
692
|
);
|
|
691
693
|
if (!isEqual) {
|
|
692
|
-
throw new UnauthorizedException(
|
|
694
|
+
throw new UnauthorizedException(ERROR_MESSAGES.INCORRECT_CURRENT_PASSWORD);
|
|
693
695
|
}
|
|
694
696
|
|
|
695
697
|
// Update Password
|
|
@@ -700,7 +702,7 @@ export class AuthenticationService {
|
|
|
700
702
|
user.forcePasswordChange = false;
|
|
701
703
|
|
|
702
704
|
if (await this.isPasswordDuplicate(user)) {
|
|
703
|
-
throw new BadRequestException(
|
|
705
|
+
throw new BadRequestException(ERROR_MESSAGES.PASSWORD_REUSED);
|
|
704
706
|
}
|
|
705
707
|
await this.deleteOldPasswords(user);
|
|
706
708
|
|
|
@@ -724,15 +726,15 @@ export class AuthenticationService {
|
|
|
724
726
|
const user = await this.resolveUser(initiateForgotPasswordDto.username, initiateForgotPasswordDto.email);
|
|
725
727
|
|
|
726
728
|
if (!user) {
|
|
727
|
-
throw new NotFoundException(
|
|
729
|
+
throw new NotFoundException(ERROR_MESSAGES.USER_NOT_FOUND);
|
|
728
730
|
}
|
|
729
731
|
if (!user.active) {
|
|
730
|
-
throw new UnauthorizedException(
|
|
732
|
+
throw new UnauthorizedException(ERROR_MESSAGES.USER_INACTIVE);
|
|
731
733
|
}
|
|
732
734
|
|
|
733
735
|
// 2. Validate if user has used a provider which is "local", only then it makes sense for us to initiate the forgot password routine.
|
|
734
736
|
if (user.lastLoginProvider !== 'local') {
|
|
735
|
-
throw new BadRequestException(
|
|
737
|
+
throw new BadRequestException(ERROR_MESSAGES.NON_LOCAL_PROVIDER);
|
|
736
738
|
}
|
|
737
739
|
|
|
738
740
|
// 3. Generate a 6 digit validation token, we send this token to the user over their email & mobile number (controlled using configuration).
|
|
@@ -746,7 +748,7 @@ export class AuthenticationService {
|
|
|
746
748
|
// 5. Return.
|
|
747
749
|
return {
|
|
748
750
|
status: 'success',
|
|
749
|
-
message:
|
|
751
|
+
message: SUCCESS_MESSAGES.FORGOT_PASSWORD_TOKEN_SENT,
|
|
750
752
|
error: '',
|
|
751
753
|
errorCode: '',
|
|
752
754
|
data: {
|
|
@@ -807,23 +809,23 @@ export class AuthenticationService {
|
|
|
807
809
|
const user = await this.resolveUser(confirmForgotPasswordDto.username, confirmForgotPasswordDto.email);
|
|
808
810
|
|
|
809
811
|
if (!user) {
|
|
810
|
-
throw new NotFoundException(
|
|
812
|
+
throw new NotFoundException(ERROR_MESSAGES.USER_NOT_FOUND);
|
|
811
813
|
}
|
|
812
814
|
|
|
813
815
|
// 2. Validate if user has used a provider which is "local", only then it makes sense for us to initiate the forgot password routine.
|
|
814
816
|
if (user.lastLoginProvider !== 'local') {
|
|
815
|
-
throw new BadRequestException(
|
|
817
|
+
throw new BadRequestException(ERROR_MESSAGES.NON_LOCAL_PROVIDER);
|
|
816
818
|
}
|
|
817
819
|
if (!user.active) {
|
|
818
|
-
throw new UnauthorizedException(
|
|
820
|
+
throw new UnauthorizedException(ERROR_MESSAGES.USER_INACTIVE);
|
|
819
821
|
}
|
|
820
822
|
|
|
821
823
|
// 3. Validate the verification token is proper & update the user record.
|
|
822
824
|
if (user.verificationTokenOnForgotPassword !== confirmForgotPasswordDto.verificationToken) {
|
|
823
|
-
throw new UnauthorizedException(
|
|
825
|
+
throw new UnauthorizedException(ERROR_MESSAGES.INVALID_VERIFICATION_TOKEN);
|
|
824
826
|
}
|
|
825
827
|
if (user.verificationTokenOnForgotPasswordExpiresAt < new Date()) {
|
|
826
|
-
throw new UnauthorizedException(
|
|
828
|
+
throw new UnauthorizedException(ERROR_MESSAGES.INVALID_VERIFICATION_TOKEN);
|
|
827
829
|
}
|
|
828
830
|
user.forgotPasswordConfirmedAt = new Date();
|
|
829
831
|
user.verificationTokenOnForgotPassword = null;
|
|
@@ -834,7 +836,7 @@ export class AuthenticationService {
|
|
|
834
836
|
user.password = confirmForgotPasswordDto.password
|
|
835
837
|
|
|
836
838
|
if (await this.isPasswordDuplicate(user)) {
|
|
837
|
-
throw new BadRequestException(
|
|
839
|
+
throw new BadRequestException(ERROR_MESSAGES.PASSWORD_REUSED);
|
|
838
840
|
}
|
|
839
841
|
await this.deleteOldPasswords(user);
|
|
840
842
|
|
|
@@ -849,7 +851,7 @@ export class AuthenticationService {
|
|
|
849
851
|
|
|
850
852
|
return {
|
|
851
853
|
status: 'success',
|
|
852
|
-
message:
|
|
854
|
+
message: SUCCESS_MESSAGES.FORGOT_PASSWORD_CONFIRMED,
|
|
853
855
|
error: '',
|
|
854
856
|
errorCode: '',
|
|
855
857
|
data: {}
|
|
@@ -950,7 +952,7 @@ export class AuthenticationService {
|
|
|
950
952
|
}
|
|
951
953
|
});
|
|
952
954
|
if (!user) {
|
|
953
|
-
throw new UnauthorizedException();
|
|
955
|
+
throw new UnauthorizedException(ERROR_MESSAGES.SESSION_INVALID);
|
|
954
956
|
}
|
|
955
957
|
|
|
956
958
|
// TODO: Replace the if else condition below with a call to validateAndRotate - Done
|
|
@@ -973,10 +975,10 @@ export class AuthenticationService {
|
|
|
973
975
|
} catch (err) {
|
|
974
976
|
if (err instanceof InvalidatedRefreshTokenError) {
|
|
975
977
|
// Take action: notify user that his refresh token might have been stolen?
|
|
976
|
-
throw new UnauthorizedException(
|
|
978
|
+
throw new UnauthorizedException(ERROR_MESSAGES.ACCESS_DENIED);
|
|
977
979
|
}
|
|
978
980
|
|
|
979
|
-
throw new UnauthorizedException();
|
|
981
|
+
throw new UnauthorizedException(ERROR_MESSAGES.SESSION_EXPIRED);
|
|
980
982
|
}
|
|
981
983
|
}
|
|
982
984
|
|
|
@@ -1007,10 +1009,10 @@ export class AuthenticationService {
|
|
|
1007
1009
|
// TODO: remove the access code both from the database.
|
|
1008
1010
|
return userProfile;
|
|
1009
1011
|
} else {
|
|
1010
|
-
throw new UnauthorizedException(
|
|
1012
|
+
throw new UnauthorizedException(ERROR_MESSAGES.INVALID_USER_PROFILE);
|
|
1011
1013
|
}
|
|
1012
1014
|
} catch (error) {
|
|
1013
|
-
throw new UnauthorizedException(
|
|
1015
|
+
throw new UnauthorizedException(ERROR_MESSAGES.GOOGLE_OAUTH_PROFILE_FETCH_FAILED);
|
|
1014
1016
|
}
|
|
1015
1017
|
}
|
|
1016
1018
|
|
|
@@ -1071,11 +1073,11 @@ export class AuthenticationService {
|
|
|
1071
1073
|
await this.userActivityHistoryService.logEvent('logout', user);
|
|
1072
1074
|
|
|
1073
1075
|
|
|
1074
|
-
return { message:
|
|
1076
|
+
return { message: SUCCESS_MESSAGES.LOGOUT_SUCCESS};
|
|
1075
1077
|
} catch (err) {
|
|
1076
1078
|
throw err instanceof UnauthorizedException || err instanceof InternalServerErrorException
|
|
1077
1079
|
? err
|
|
1078
|
-
: new InternalServerErrorException(
|
|
1080
|
+
: new InternalServerErrorException(ERROR_MESSAGES.LOGOUT_FAILED);
|
|
1079
1081
|
}
|
|
1080
1082
|
}
|
|
1081
1083
|
|
|
@@ -1083,7 +1085,7 @@ export class AuthenticationService {
|
|
|
1083
1085
|
async activateUser(userId: number) {
|
|
1084
1086
|
const user = await this.userService.findOne(userId, {});
|
|
1085
1087
|
if (!user) {
|
|
1086
|
-
throw new NotFoundException(
|
|
1088
|
+
throw new NotFoundException(ERROR_MESSAGES.USER_NOT_FOUND);
|
|
1087
1089
|
}
|
|
1088
1090
|
user.active = true;
|
|
1089
1091
|
await this.userRepository.save(user);
|
|
@@ -4,6 +4,7 @@ import { classify } from "@angular-devkit/core/src/utils/strings";
|
|
|
4
4
|
import { ActiveUserData } from "src/interfaces/active-user-data.interface";
|
|
5
5
|
import { SolidRegistry } from "src/helpers/solid-registry";
|
|
6
6
|
import { Logger } from "@nestjs/common";
|
|
7
|
+
import { ERROR_MESSAGES } from "src/constants/error-messages";
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
export class CrudHelperService {
|
|
@@ -174,7 +175,7 @@ export class CrudHelperService {
|
|
|
174
175
|
const normalizedSort = this.normalize(sort);
|
|
175
176
|
const normalizedGroupBy = this.normalize(groupBy);
|
|
176
177
|
if (normalizedGroupBy.length > 1) {
|
|
177
|
-
throw new Error(
|
|
178
|
+
throw new Error(ERROR_MESSAGES.GROUP_BY_LIMIT);
|
|
178
179
|
}
|
|
179
180
|
|
|
180
181
|
// Depending upon the populate option, apply the join clause
|
|
@@ -367,7 +368,7 @@ export class CrudHelperService {
|
|
|
367
368
|
const groupByField = filteredDto.groupBy;
|
|
368
369
|
|
|
369
370
|
if (!groupByField || (Array.isArray(groupByField) && groupByField.length !== 1)) {
|
|
370
|
-
throw new Error(
|
|
371
|
+
throw new Error(ERROR_MESSAGES.INVALID_GROUP_BY_COUNT);
|
|
371
372
|
}
|
|
372
373
|
|
|
373
374
|
const field = Array.isArray(groupByField) ? groupByField[0] : groupByField;
|