rez_core 2.2.201 → 2.2.203
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/module/communication/controller/wrapper.controller.d.ts +17 -1
- package/dist/module/communication/service/wrapper.service.d.ts +19 -1
- package/dist/module/communication/service/wrapper.service.js +69 -36
- package/dist/module/communication/service/wrapper.service.js.map +1 -1
- package/dist/module/communication/strategies/gmail.strategy.js +1 -1
- package/dist/module/communication/strategies/gmail.strategy.js.map +1 -1
- package/dist/module/master/service/master.service.js +15 -0
- package/dist/module/master/service/master.service.js.map +1 -1
- package/dist/module/notification/controller/otp.controller.js +0 -1
- package/dist/module/notification/controller/otp.controller.js.map +1 -1
- package/dist/module/user/controller/login.controller.js +11 -3
- package/dist/module/user/controller/login.controller.js.map +1 -1
- package/dist/module/user/service/login.service.d.ts +7 -6
- package/dist/module/user/service/login.service.js +9 -2
- package/dist/module/user/service/login.service.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/module/communication/service/wrapper.service.ts +103 -42
- package/src/module/communication/strategies/gmail.strategy.ts +1 -1
- package/src/module/master/service/master.service.ts +24 -85
- package/src/module/notification/controller/otp.controller.ts +0 -1
- package/src/module/user/controller/login.controller.ts +13 -3
- package/src/module/user/service/login.service.ts +16 -8
package/package.json
CHANGED
|
@@ -128,6 +128,7 @@ export class WrapperService {
|
|
|
128
128
|
|
|
129
129
|
/**
|
|
130
130
|
* Wrapper for scheduling meeting in Google Calendar
|
|
131
|
+
* or fallback to sending ICS as email attachment
|
|
131
132
|
*/
|
|
132
133
|
async scheduleMeetingWrapper(payload: any, loggedInUser: any) {
|
|
133
134
|
try {
|
|
@@ -137,61 +138,121 @@ export class WrapperService {
|
|
|
137
138
|
|
|
138
139
|
const { level_id, level_type } = loggedInUser;
|
|
139
140
|
|
|
140
|
-
// 1.
|
|
141
|
-
const
|
|
141
|
+
// 1. Try user-level config
|
|
142
|
+
const userConfigs = await this.datasource.query(
|
|
142
143
|
`SELECT *
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
144
|
+
FROM cr_communication_hub
|
|
145
|
+
WHERE level_id = ?
|
|
146
|
+
AND level_type = ?
|
|
147
|
+
AND communication_config_type = 'EMAIL'
|
|
148
|
+
AND service = 'API'`,
|
|
147
149
|
[level_id, level_type],
|
|
148
150
|
);
|
|
149
151
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
+
if (userConfigs && userConfigs.length > 0) {
|
|
153
|
+
const provider = userConfigs[0]?.provider;
|
|
154
|
+
const configId = userConfigs[0]?.config_id;
|
|
152
155
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
156
|
+
if (provider === 'gmail') {
|
|
157
|
+
// Gmail → Use Google Calendar
|
|
158
|
+
const creds = await this.getConfigCred(configId);
|
|
159
|
+
if (creds) {
|
|
160
|
+
const result = await this.googleService.createEvent(creds, payload);
|
|
161
|
+
return { success: true, data: result };
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Non-Gmail provider → Use ICS over email
|
|
166
|
+
const result = await this.sendIcsFallback(
|
|
167
|
+
payload,
|
|
168
|
+
level_id,
|
|
169
|
+
level_type,
|
|
160
170
|
);
|
|
171
|
+
return { success: true, data: result };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// 2. Fallback to ORG-level config
|
|
175
|
+
const orgConfigs = await this.datasource.query(
|
|
176
|
+
`SELECT *
|
|
177
|
+
FROM cr_communication_hub
|
|
178
|
+
WHERE level_type = 'ORG'
|
|
179
|
+
AND level_id = 1
|
|
180
|
+
AND communication_config_type = 'EMAIL'
|
|
181
|
+
AND service = 'API'`,
|
|
182
|
+
);
|
|
161
183
|
|
|
162
|
-
|
|
163
|
-
|
|
184
|
+
if (orgConfigs && orgConfigs.length > 0) {
|
|
185
|
+
const provider = orgConfigs[0].provider;
|
|
186
|
+
const configId = orgConfigs[0].config_id;
|
|
187
|
+
|
|
188
|
+
if (provider === 'gmail') {
|
|
189
|
+
// ORG Gmail → Google Calendar
|
|
190
|
+
const creds = await this.getConfigCred(configId);
|
|
191
|
+
if (creds) {
|
|
192
|
+
const result = await this.googleService.createEvent(creds, payload);
|
|
193
|
+
return { success: true, data: result };
|
|
194
|
+
}
|
|
164
195
|
}
|
|
165
196
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
} else {
|
|
170
|
-
const base64String = await this.icsService.generateIcs(payload);
|
|
171
|
-
|
|
172
|
-
result = await this.communicationService.sendGenericMessage({
|
|
173
|
-
...payload,
|
|
174
|
-
attachments: [
|
|
175
|
-
{
|
|
176
|
-
content: base64String,
|
|
177
|
-
type: 'text/calendar',
|
|
178
|
-
filename: 'invite.ics',
|
|
179
|
-
disposition: 'attachment',
|
|
180
|
-
},
|
|
181
|
-
],
|
|
182
|
-
});
|
|
197
|
+
// ORG Non-Gmail → ICS via email
|
|
198
|
+
const result = await this.sendIcsFallback(payload, 1, 'ORG');
|
|
199
|
+
return { success: true, data: result };
|
|
183
200
|
}
|
|
184
201
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
};
|
|
202
|
+
// 3. Absolute fallback → Default ORG with ICS
|
|
203
|
+
const result = await this.sendIcsFallback(payload, 1, 'ORG');
|
|
204
|
+
return { success: true, data: result };
|
|
189
205
|
} catch (error: any) {
|
|
190
206
|
this.logger.error('scheduleMeetingWrapper error', error.message);
|
|
191
|
-
return {
|
|
192
|
-
success: false,
|
|
193
|
-
error: error.message,
|
|
194
|
-
};
|
|
207
|
+
return { success: false, error: error.message };
|
|
195
208
|
}
|
|
196
209
|
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Fetch credentials JSON by config ID
|
|
213
|
+
*/
|
|
214
|
+
private async getConfigCred(configId: number) {
|
|
215
|
+
const configRes = await this.datasource.query(
|
|
216
|
+
`SELECT config_json
|
|
217
|
+
FROM cr_communication_config
|
|
218
|
+
WHERE id = ?`,
|
|
219
|
+
[configId],
|
|
220
|
+
);
|
|
221
|
+
return configRes?.[0]?.config_json || null;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Send ICS fallback via email
|
|
226
|
+
*/
|
|
227
|
+
private async sendIcsFallback(
|
|
228
|
+
payload: any,
|
|
229
|
+
levelId: number,
|
|
230
|
+
levelType: string,
|
|
231
|
+
) {
|
|
232
|
+
const base64String = await this.icsService.generateIcs(payload);
|
|
233
|
+
|
|
234
|
+
const payloadSendMail: GenericMessageDto = {
|
|
235
|
+
levelId,
|
|
236
|
+
levelType,
|
|
237
|
+
to: payload.to,
|
|
238
|
+
message: payload.message,
|
|
239
|
+
subject: payload.subject,
|
|
240
|
+
type: 'EMAIL',
|
|
241
|
+
cc: payload.cc,
|
|
242
|
+
bcc: payload.bcc,
|
|
243
|
+
html: payload.html,
|
|
244
|
+
attachments: [
|
|
245
|
+
{
|
|
246
|
+
content: base64String,
|
|
247
|
+
type: 'text/calendar',
|
|
248
|
+
filename: 'invite.ics',
|
|
249
|
+
disposition: 'attachment',
|
|
250
|
+
},
|
|
251
|
+
],
|
|
252
|
+
templateId: payload.templateId,
|
|
253
|
+
variables: payload.variables,
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
return this.communicationService.sendGenericMessage(payloadSendMail);
|
|
257
|
+
}
|
|
197
258
|
}
|
|
@@ -66,7 +66,7 @@ export class GmailStrategy implements CommunicationStrategy {
|
|
|
66
66
|
`Subject: ${subject}`,
|
|
67
67
|
'Content-Type: text/html; charset=utf-8',
|
|
68
68
|
'',
|
|
69
|
-
config.html
|
|
69
|
+
message || config.html,
|
|
70
70
|
].join('\n');
|
|
71
71
|
|
|
72
72
|
const encodedMessage = Buffer.from(emailContent)
|
|
@@ -240,91 +240,7 @@ export class MasterService {
|
|
|
240
240
|
throw new Error(`No unique fields found for entityType: ${entityType}`);
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
// if (row.parent_type && row.parent_id) {
|
|
246
|
-
// await this.resolveParent(row);
|
|
247
|
-
// }
|
|
248
|
-
|
|
249
|
-
// for (const attr of attributes) {
|
|
250
|
-
// console.log('inside for loop attr');
|
|
251
|
-
// if (attr.data_source_type === 'entity' && row[attr.attribute_key]) {
|
|
252
|
-
// console.log('inside if condition');
|
|
253
|
-
|
|
254
|
-
// const refEntity = await this.entityMasterService.getEntityData(
|
|
255
|
-
// attr.datasource_list,
|
|
256
|
-
// loggedInUser,
|
|
257
|
-
// );
|
|
258
|
-
// const refData = await this.entityManager.query(
|
|
259
|
-
// `SELECT * FROM ${refEntity.db_table_name} WHERE code = ? LIMIT 1`,
|
|
260
|
-
// [row[attr.attribute_key]],
|
|
261
|
-
// );
|
|
262
|
-
|
|
263
|
-
// //you will check the org id of refData and loggedInUser.organization_id
|
|
264
|
-
|
|
265
|
-
// if (!refData.length) {
|
|
266
|
-
// throw new Error(
|
|
267
|
-
// `Reference entity not found for code: ${row[attr.attribute_key]}`,
|
|
268
|
-
// );
|
|
269
|
-
// }
|
|
270
|
-
|
|
271
|
-
// row[attr.attribute_key] = refData[0].id;
|
|
272
|
-
// }
|
|
273
|
-
// }
|
|
274
|
-
// }
|
|
275
|
-
|
|
276
|
-
// const errors: any[] = [];
|
|
277
|
-
|
|
278
|
-
// for (let i = 0; i < sheetData.length; i++) {
|
|
279
|
-
// const row = sheetData[i];
|
|
280
|
-
|
|
281
|
-
// if (row.parent_type && row.parent_id) {
|
|
282
|
-
// await this.resolveParent(row);
|
|
283
|
-
// }
|
|
284
|
-
|
|
285
|
-
// for (const attr of attributes) {
|
|
286
|
-
// if (attr.data_source_type === 'entity' && row[attr.attribute_key]) {
|
|
287
|
-
// const refEntity = await this.entityMasterService.getEntityData(
|
|
288
|
-
// attr.datasource_list,
|
|
289
|
-
// loggedInUser,
|
|
290
|
-
// );
|
|
291
|
-
// const refData = await this.entityManager.query(
|
|
292
|
-
// `SELECT * FROM ${refEntity.db_table_name} WHERE code = ? LIMIT 1`,
|
|
293
|
-
// [row[attr.attribute_key]],
|
|
294
|
-
// );
|
|
295
|
-
// if (!refData.length) {
|
|
296
|
-
// throw new Error(
|
|
297
|
-
// `Reference entity not found for code: ${row[attr.attribute_key]}`,
|
|
298
|
-
// );
|
|
299
|
-
// }
|
|
300
|
-
// row[attr.attribute_key] = refData[0].id;
|
|
301
|
-
// }
|
|
302
|
-
// }
|
|
303
|
-
|
|
304
|
-
// const rowErrors = await this.entityValidationService.validateEntityData(
|
|
305
|
-
// row,
|
|
306
|
-
// entityMaster,
|
|
307
|
-
// loggedInUser,
|
|
308
|
-
// );
|
|
309
|
-
|
|
310
|
-
// if (rowErrors && rowErrors.length > 0) {
|
|
311
|
-
// errors.push({
|
|
312
|
-
// row: i + 1,
|
|
313
|
-
// errors: rowErrors,
|
|
314
|
-
// });
|
|
315
|
-
// }
|
|
316
|
-
// }
|
|
317
|
-
|
|
318
|
-
// await this.upsertViaService(
|
|
319
|
-
// entityType,
|
|
320
|
-
// sheetData,
|
|
321
|
-
// attributes,
|
|
322
|
-
// uniqueFields,
|
|
323
|
-
// loggedInUser,
|
|
324
|
-
// duplicateHandling,
|
|
325
|
-
// );
|
|
326
|
-
|
|
327
|
-
// return { message: 'Entity data uploaded successfully' };
|
|
243
|
+
|
|
328
244
|
const errors: any[] = [];
|
|
329
245
|
|
|
330
246
|
// ✅ Iterate row by row
|
|
@@ -362,6 +278,29 @@ export class MasterService {
|
|
|
362
278
|
}
|
|
363
279
|
}
|
|
364
280
|
|
|
281
|
+
|
|
282
|
+
for (const attr of attributes) {
|
|
283
|
+
if (attr.data_source_type === 'master' && row[attr.attribute_key]) {
|
|
284
|
+
const refData = await this.entityManager.query(
|
|
285
|
+
`SELECT * FROM cr_list_master_items WHERE name = ? and organization_id = ? LIMIT 1`,
|
|
286
|
+
[row[attr.attribute_key], loggedInUser.organization_id],
|
|
287
|
+
);
|
|
288
|
+
|
|
289
|
+
if (!refData.length) {
|
|
290
|
+
errors.push({
|
|
291
|
+
row: i + 1,
|
|
292
|
+
errors: [
|
|
293
|
+
`Reference master data not found for name: ${row[attr.attribute_key]}`,
|
|
294
|
+
],
|
|
295
|
+
});
|
|
296
|
+
continue; // skip further processing for this row
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// replace with reference id
|
|
300
|
+
row[attr.attribute_key] = refData[0].id;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
365
304
|
// ✅ validate single row
|
|
366
305
|
const rowErrors = await this.entityValidationService.validateImportData(
|
|
367
306
|
row,
|
|
@@ -16,6 +16,7 @@ import { Request, Response } from 'express';
|
|
|
16
16
|
import { UserSessionService } from '../service/user-session.service';
|
|
17
17
|
import { ConfigService } from '@nestjs/config';
|
|
18
18
|
import { CommunicationService } from '../../communication/service/communication.service';
|
|
19
|
+
import { UAParser } from 'ua-parser-js';
|
|
19
20
|
|
|
20
21
|
@Controller('auth')
|
|
21
22
|
export class LoginController {
|
|
@@ -77,7 +78,6 @@ export class LoginController {
|
|
|
77
78
|
async googleAuthRedirect(@Req() req: any, @Res() res: Response) {
|
|
78
79
|
const {
|
|
79
80
|
email,
|
|
80
|
-
password,
|
|
81
81
|
name,
|
|
82
82
|
accessToken: googleAccessToken,
|
|
83
83
|
refreshToken: googleRefreshToken,
|
|
@@ -86,6 +86,15 @@ export class LoginController {
|
|
|
86
86
|
} = req.user;
|
|
87
87
|
const { state } = req.query;
|
|
88
88
|
|
|
89
|
+
const ip =
|
|
90
|
+
(req.headers['x-forwarded-for'] as string)?.split(',')[0].trim() ||
|
|
91
|
+
req.socket.remoteAddress;
|
|
92
|
+
|
|
93
|
+
const userAgent = req.headers['user-agent'] || '';
|
|
94
|
+
const parser = new UAParser(userAgent);
|
|
95
|
+
const browser = parser.getBrowser().name || 'Unknown';
|
|
96
|
+
const os = parser.getOS().name || 'Unknown';
|
|
97
|
+
|
|
89
98
|
// Check if this is a Gmail configuration request
|
|
90
99
|
if (
|
|
91
100
|
state &&
|
|
@@ -114,10 +123,11 @@ export class LoginController {
|
|
|
114
123
|
// Original login flow
|
|
115
124
|
const data = await this.loginService.loginWithGoogle({
|
|
116
125
|
email,
|
|
117
|
-
password,
|
|
118
|
-
name,
|
|
119
126
|
subdomain,
|
|
120
127
|
fcm_token,
|
|
128
|
+
ip,
|
|
129
|
+
browser,
|
|
130
|
+
os,
|
|
121
131
|
});
|
|
122
132
|
|
|
123
133
|
if (!('accessToken' in data) || !data.accessToken)
|
|
@@ -41,8 +41,8 @@ export class LoginService {
|
|
|
41
41
|
async login(data: {
|
|
42
42
|
email: string;
|
|
43
43
|
password?: string;
|
|
44
|
-
subdomain
|
|
45
|
-
fcm_token
|
|
44
|
+
subdomain?: string;
|
|
45
|
+
fcm_token?: string;
|
|
46
46
|
is_otp?: boolean;
|
|
47
47
|
browser?: string;
|
|
48
48
|
ip?: string;
|
|
@@ -282,12 +282,13 @@ export class LoginService {
|
|
|
282
282
|
|
|
283
283
|
async loginWithGoogle(data: {
|
|
284
284
|
email: string;
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
285
|
+
subdomain?: string;
|
|
286
|
+
fcm_token?: string;
|
|
287
|
+
ip?: string;
|
|
288
|
+
browser?: string;
|
|
289
|
+
os?: string;
|
|
289
290
|
}) {
|
|
290
|
-
const { email,
|
|
291
|
+
const { email, subdomain, fcm_token, ip, browser, os } = data;
|
|
291
292
|
const user = await this.userService.findByEmailId(email);
|
|
292
293
|
|
|
293
294
|
if (!user) {
|
|
@@ -311,7 +312,14 @@ export class LoginService {
|
|
|
311
312
|
}
|
|
312
313
|
|
|
313
314
|
// Create session (Same as JWT login flow)
|
|
314
|
-
return await this.login(
|
|
315
|
+
return await this.login({
|
|
316
|
+
email,
|
|
317
|
+
subdomain,
|
|
318
|
+
fcm_token,
|
|
319
|
+
ip,
|
|
320
|
+
browser,
|
|
321
|
+
os,
|
|
322
|
+
});
|
|
315
323
|
}
|
|
316
324
|
|
|
317
325
|
async logout(sessionKey: string) {
|