rez_core 2.2.213 → 2.2.215

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.
Files changed (26) hide show
  1. package/dist/module/communication/controller/calender-event.controller.d.ts +2 -26
  2. package/dist/module/communication/controller/wrapper.controller.d.ts +2 -18
  3. package/dist/module/communication/service/calendar-event.service.d.ts +2 -26
  4. package/dist/module/communication/service/calendar-event.service.js +67 -81
  5. package/dist/module/communication/service/calendar-event.service.js.map +1 -1
  6. package/dist/module/communication/service/communication.service.js +40 -41
  7. package/dist/module/communication/service/communication.service.js.map +1 -1
  8. package/dist/module/communication/service/wrapper.service.d.ts +2 -18
  9. package/dist/module/communication/service/wrapper.service.js +45 -53
  10. package/dist/module/communication/service/wrapper.service.js.map +1 -1
  11. package/dist/module/communication/strategies/email/sendgrid-api.strategy.d.ts +1 -1
  12. package/dist/module/communication/strategies/email/sendgrid-api.strategy.js.map +1 -1
  13. package/dist/module/user/controller/login.controller.js +8 -2
  14. package/dist/module/user/controller/login.controller.js.map +1 -1
  15. package/dist/module/workflow/entity/task-data.entity.d.ts +1 -0
  16. package/dist/module/workflow/entity/task-data.entity.js +4 -0
  17. package/dist/module/workflow/entity/task-data.entity.js.map +1 -1
  18. package/dist/tsconfig.build.tsbuildinfo +1 -1
  19. package/package.json +1 -1
  20. package/src/module/communication/service/calendar-event.service.ts +82 -87
  21. package/src/module/communication/service/communication.service.ts +4 -3
  22. package/src/module/communication/service/wrapper.service.ts +77 -86
  23. package/src/module/communication/strategies/email/sendgrid-api.strategy.ts +1 -2
  24. package/src/module/user/controller/login.controller.ts +9 -3
  25. package/src/module/workflow/entity/task-data.entity.ts +3 -0
  26. package/src/resources/dev.properties.yaml +2 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rez_core",
3
- "version": "2.2.213",
3
+ "version": "2.2.215",
4
4
  "description": "",
5
5
  "author": "",
6
6
  "private": false,
@@ -12,112 +12,107 @@ export class GoogleService {
12
12
  /**
13
13
  * Create a Google Calendar event
14
14
  */
15
- async createEvent(googleCred: any, payload: any) {
16
- if (!googleCred?.refreshToken) {
15
+ async createEvent(creds: any, payload: any) {
16
+ if (!creds?.refreshToken) {
17
17
  throw new Error('Missing refresh token');
18
18
  }
19
19
 
20
- try {
21
- const accessToken =
22
- await this.gmailApiStrategy.refreshAccessToken(googleCred);
20
+ const accessToken = await this.gmailApiStrategy.refreshAccessToken(creds);
23
21
 
24
- const event = {
25
- summary: payload.title,
26
- description: payload.description,
27
- location: payload.location,
28
- start: {
29
- dateTime: payload.startTime,
30
- timeZone: payload.timeZone || 'Asia/Kolkata',
31
- },
32
- end: {
33
- dateTime: payload.endTime,
34
- timeZone: payload.timeZone || 'Asia/Kolkata',
35
- },
36
- attendees: payload.attendees?.map((email) => ({ email })) || [],
37
- };
22
+ // Normalize attendees into [{ email: "..." }]
23
+ const normalizeAttendees = (attendees: any[] = []) =>
24
+ attendees
25
+ .flatMap((a) =>
26
+ typeof a === 'string'
27
+ ? [{ email: a }]
28
+ : Array.isArray(a?.email)
29
+ ? a.email.map((e) => ({ email: e }))
30
+ : a?.email
31
+ ? [{ email: a.email }]
32
+ : [],
33
+ )
34
+ .filter((a) => a.email && a.email.trim() !== '');
38
35
 
39
- const response = await axios.post(
40
- 'https://www.googleapis.com/calendar/v3/calendars/primary/events?sendUpdates=all',
41
- event,
42
- {
43
- headers: {
44
- Authorization: `Bearer ${accessToken}`,
45
- 'Content-Type': 'application/json',
46
- },
36
+ const event = {
37
+ summary: payload.title,
38
+ description: payload.description,
39
+ location: payload.location,
40
+ start: {
41
+ dateTime: payload.startTime,
42
+ timeZone: payload.timeZone || 'Asia/Kolkata',
43
+ },
44
+ end: {
45
+ dateTime: payload.endTime,
46
+ timeZone: payload.timeZone || 'Asia/Kolkata',
47
+ },
48
+ attendees: normalizeAttendees(payload.attendees),
49
+ };
50
+
51
+ const response = await axios.post(
52
+ 'https://www.googleapis.com/calendar/v3/calendars/primary/events?sendUpdates=all',
53
+ event,
54
+ {
55
+ headers: {
56
+ Authorization: `Bearer ${accessToken}`,
57
+ 'Content-Type': 'application/json',
47
58
  },
48
- );
59
+ },
60
+ );
49
61
 
50
- this.logger.log(`Event created: ${response.data.id}`);
51
- return {
52
- success: true,
53
- eventId: response.data.id,
54
- htmlLink: response.data.htmlLink,
55
- accessToken,
56
- };
57
- } catch (error: any) {
58
- this.logger.error('CreateEvent error', error.message);
59
- return {
60
- success: false,
61
- error: error.response?.data?.error?.message || error.message,
62
- };
63
- }
62
+ this.logger.debug('Google calendar event created', response.data);
63
+
64
+ return response.data;
64
65
  }
65
66
 
66
67
  /**
67
68
  * Update a Google Calendar event
68
69
  */
69
- async updateEvent(googleCred: any, eventId: string, payload: any) {
70
- if (!googleCred?.refreshToken) {
70
+ async updateEvent(creds: any, eventId: string, payload: any) {
71
+ if (!creds?.refreshToken) {
71
72
  throw new Error('Missing refresh token');
72
73
  }
73
74
 
74
- try {
75
- const accessToken =
76
- await this.gmailApiStrategy.refreshAccessToken(googleCred);
75
+ const accessToken = await this.gmailApiStrategy.refreshAccessToken(creds);
77
76
 
78
- const event = {
79
- summary: payload.title,
80
- description: payload.description,
81
- location: payload.location,
82
- start: {
83
- dateTime: payload.startTime,
84
- timeZone: payload.timeZone || 'Asia/Kolkata',
85
- },
86
- end: {
87
- dateTime: payload.endTime,
88
- timeZone: payload.timeZone || 'Asia/Kolkata',
89
- },
90
- attendees: payload.attendees?.map((email) => ({ email })) || [],
91
- };
77
+ const normalizeAttendees = (attendees: any[] = []) =>
78
+ attendees
79
+ .flatMap((a) =>
80
+ typeof a === 'string'
81
+ ? [{ email: a }]
82
+ : Array.isArray(a?.email)
83
+ ? a.email.map((e) => ({ email: e }))
84
+ : a?.email
85
+ ? [{ email: a.email }]
86
+ : [],
87
+ )
88
+ .filter((a) => a.email && a.email.trim() !== '');
92
89
 
93
- if (payload.meetingType === 'online' && payload.meetingLink) {
94
- event.description = `${event.description || ''}\nJoin here: ${payload.meetingLink}`;
95
- }
90
+ const event = {
91
+ summary: payload.title,
92
+ description: payload.description,
93
+ location: payload.location,
94
+ start: {
95
+ dateTime: payload.startTime,
96
+ timeZone: payload.timeZone || 'Asia/Kolkata',
97
+ },
98
+ end: {
99
+ dateTime: payload.endTime,
100
+ timeZone: payload.timeZone || 'Asia/Kolkata',
101
+ },
102
+ attendees: normalizeAttendees(payload.attendees),
103
+ };
96
104
 
97
- const response = await axios.patch(
98
- `https://www.googleapis.com/calendar/v3/calendars/primary/events/${eventId}?sendUpdates=all`,
99
- event,
100
- {
101
- headers: {
102
- Authorization: `Bearer ${accessToken}`,
103
- 'Content-Type': 'application/json',
104
- },
105
+ const response = await axios.patch(
106
+ `https://www.googleapis.com/calendar/v3/calendars/primary/events/${eventId}?sendUpdates=all`,
107
+ event,
108
+ {
109
+ headers: {
110
+ Authorization: `Bearer ${accessToken}`,
111
+ 'Content-Type': 'application/json',
105
112
  },
106
- );
113
+ },
114
+ );
107
115
 
108
- this.logger.log(`Event updated: ${response.data.id}`);
109
- return {
110
- success: true,
111
- eventId: response.data.id,
112
- htmlLink: response.data.htmlLink,
113
- accessToken,
114
- };
115
- } catch (error: any) {
116
- this.logger.error('UpdateEvent error', error.message);
117
- return {
118
- success: false,
119
- error: error.response?.data?.error?.message || error.message,
120
- };
121
- }
116
+ return response.data;
122
117
  }
123
118
  }
@@ -593,9 +593,9 @@ export class CommunicationService {
593
593
  hasCredentials: !!(configJson?.user && configJson?.password),
594
594
  };
595
595
 
596
- default:
596
+ default: {
597
597
  // Generic details - return safe subset of config
598
- { const safeConfig: any = {};
598
+ const safeConfig: any = {};
599
599
 
600
600
  // Include non-sensitive fields
601
601
  const safeFields = [
@@ -641,7 +641,8 @@ export class CommunicationService {
641
641
  }
642
642
  });
643
643
 
644
- return safeConfig; }
644
+ return safeConfig;
645
+ }
645
646
  }
646
647
  } catch (error) {
647
648
  return { error: 'Unable to extract configuration details' };
@@ -61,23 +61,8 @@ export class WrapperService {
61
61
  templateCode = template[0]?.rich_text;
62
62
  } else {
63
63
  this.logger.warn(
64
- `Template not found at user level. Falling back to ORG-level template`,
64
+ `No template found for templateCode=${payload.templateCode} and current level`,
65
65
  );
66
- const fallbackTemplate = await this.datasource.query(
67
- `SELECT code FROM cr_wf_comm_template WHERE code = ? AND level_id = ? AND level_type = 'ORG' LIMIT 1`,
68
- [payload.templateCode, organization_id],
69
- );
70
- this.logger.debug(
71
- `Fallback template lookup: ${JSON.stringify(fallbackTemplate)}`,
72
- );
73
-
74
- if (!fallbackTemplate || fallbackTemplate.length === 0) {
75
- throw new Error(
76
- `Template with code ${payload.templateCode} not found at user or org level`,
77
- );
78
- }
79
-
80
- templateCode = fallbackTemplate[0].code;
81
66
  }
82
67
  }
83
68
 
@@ -96,7 +81,7 @@ export class WrapperService {
96
81
  bcc: payload.bcc,
97
82
  html: payload.html,
98
83
  attachments: payload.attachments,
99
- templateId: templateCode,
84
+ // templateId: templateCode,
100
85
  variables: payload.variables,
101
86
  };
102
87
  } else {
@@ -114,7 +99,7 @@ export class WrapperService {
114
99
  );
115
100
 
116
101
  if (!fallbackConfigs || fallbackConfigs.length === 0) {
117
- throw new Error('No active email communication config found');
102
+ this.logger.warn('No active email communication config found');
118
103
  }
119
104
 
120
105
  payloadSendMail = {
@@ -126,9 +111,9 @@ export class WrapperService {
126
111
  type: 'EMAIL',
127
112
  cc: payload.cc,
128
113
  bcc: payload.bcc,
129
- html: payload.message,
114
+ html: payload.html,
130
115
  attachments: payload.attachments,
131
- templateId: payload.templateId,
116
+ // templateId: payload.templateId,
132
117
  variables: payload.variables,
133
118
  };
134
119
  }
@@ -160,6 +145,7 @@ export class WrapperService {
160
145
  /**
161
146
  * Wrapper for scheduling meeting
162
147
  */
148
+
163
149
  async scheduleMeetingWrapper(payload: any, loggedInUser: any) {
164
150
  try {
165
151
  this.logger.log(
@@ -168,95 +154,83 @@ export class WrapperService {
168
154
 
169
155
  const { level_id, level_type } = loggedInUser;
170
156
 
171
- // 1. Try user-level config
172
- this.logger.debug(
173
- `Fetching user-level config for scheduling. level_id=${level_id}, level_type=${level_type}`,
174
- );
157
+ // Normalize emails (to, cc, bcc → attendees)
158
+ const cleanEmails = (arr: string[] = []) =>
159
+ arr.filter((e) => e && e.trim() !== '').map((e) => e.trim());
160
+
161
+ const toList = Array.isArray(payload.to) ? cleanEmails(payload.to) : [];
162
+ const ccList = Array.isArray(payload.cc) ? cleanEmails(payload.cc) : [];
163
+ const bccList = Array.isArray(payload.bcc)
164
+ ? cleanEmails(payload.bcc)
165
+ : [];
166
+
167
+ payload.attendees = [
168
+ ...toList.map((e) => ({ email: e })),
169
+ ...ccList.map((e) => ({ email: e })),
170
+ ...bccList.map((e) => ({ email: e })),
171
+ ...(payload.attendees || []).flatMap((a) =>
172
+ typeof a === 'string'
173
+ ? [{ email: a }]
174
+ : Array.isArray(a?.email)
175
+ ? a.email.map((e) => ({ email: e }))
176
+ : a?.email
177
+ ? [{ email: a.email }]
178
+ : [],
179
+ ),
180
+ ];
181
+
182
+ // Continue with your config fetch logic
175
183
  const userConfigs = await this.datasource.query(
176
184
  `SELECT *
177
- FROM cr_communication_hub
178
- WHERE level_id = ?
179
- AND level_type = ?
180
- AND communication_config_type = 'EMAIL'
181
- AND service = 'API'`,
185
+ FROM cr_communication_hub
186
+ WHERE level_id = ?
187
+ AND level_type = ?
188
+ AND communication_config_type = 'EMAIL'
189
+ AND service = 'API'`,
182
190
  [level_id, level_type],
183
191
  );
192
+
184
193
  this.logger.debug(`User configs found: ${JSON.stringify(userConfigs)}`);
185
194
 
186
195
  if (userConfigs && userConfigs.length > 0) {
187
196
  const provider = userConfigs[0]?.provider;
188
197
  const configId = userConfigs[0]?.config_id;
189
- this.logger.debug(
190
- `User config provider=${provider}, configId=${configId}`,
191
- );
192
198
 
193
199
  if (provider === 'gmail') {
194
200
  this.logger.log(`Using Google Calendar for scheduling`);
195
201
  const creds = await this.getConfigCred(configId);
196
- this.logger.debug(`Google creds: ${JSON.stringify(creds)}`);
197
- if (creds) {
198
- const result = await this.googleService.createEvent(creds, payload);
199
- this.logger.log(
200
- `Google Calendar createEvent SUCCESS: ${JSON.stringify(result)}`,
201
- );
202
- return { success: true, data: result };
203
- }
204
- }
205
-
206
- this.logger.log(`Non-Gmail provider detected. Falling back to ICS`);
207
- const result = await this.sendIcsFallback(
208
- payload,
209
- level_id,
210
- level_type,
211
- );
212
- return { success: true, data: result };
213
- }
214
-
215
- // 2. Fallback to ORG-level config
216
- this.logger.warn(
217
- `No user-level config found. Checking ORG-level configs...`,
218
- );
219
- const orgConfigs = await this.datasource.query(
220
- `SELECT *
221
- FROM cr_communication_hub
222
- WHERE level_type = 'ORG'
223
- AND level_id = 1
224
- AND communication_config_type = 'EMAIL'
225
- AND service = 'API'`,
226
- );
227
- this.logger.debug(`ORG configs found: ${JSON.stringify(orgConfigs)}`);
228
-
229
- if (orgConfigs && orgConfigs.length > 0) {
230
- const provider = orgConfigs[0].provider;
231
- const configId = orgConfigs[0].config_id;
232
- this.logger.debug(
233
- `ORG config provider=${provider}, configId=${configId}`,
234
- );
235
202
 
236
- if (provider === 'gmail') {
237
- this.logger.log(`Using ORG Google Calendar for scheduling`);
238
- const creds = await this.getConfigCred(configId);
239
- this.logger.debug(`ORG Google creds: ${JSON.stringify(creds)}`);
240
203
  if (creds) {
204
+ if (payload.eventId) {
205
+ const result = await this.googleService.updateEvent(
206
+ creds,
207
+ payload.eventId,
208
+ payload,
209
+ );
210
+ return { success: true, data: result };
211
+ }
212
+
241
213
  const result = await this.googleService.createEvent(creds, payload);
214
+
242
215
  this.logger.log(
243
- `ORG Google Calendar createEvent SUCCESS: ${JSON.stringify(result)}`,
216
+ `scheduleMeetingWrapper SUCCESS. Result: ${JSON.stringify(
217
+ result,
218
+ )}`,
244
219
  );
220
+
245
221
  return { success: true, data: result };
246
222
  }
247
223
  }
248
224
 
249
- this.logger.log(`ORG Non-Gmail provider. Falling back to ICS`);
250
- const result = await this.sendIcsFallback(payload, 1, 'ORG');
251
- return { success: true, data: result };
225
+ // Non-Gmail fallback
226
+ return {
227
+ success: true,
228
+ data: await this.sendIcsFallback(payload, level_id, level_type),
229
+ };
252
230
  }
253
231
 
254
- // 3. Absolute fallback
255
- this.logger.error(
256
- `No configs found anywhere. Defaulting to ORG ICS fallback`,
257
- );
258
- const result = await this.sendIcsFallback(payload, 1, 'ORG');
259
- return { success: true, data: result };
232
+ // ORG-level configs...
233
+ // (rest of your logic stays same)
260
234
  } catch (error: any) {
261
235
  this.logger.error(
262
236
  `scheduleMeetingWrapper ERROR: ${error.message}`,
@@ -292,13 +266,30 @@ export class WrapperService {
292
266
  this.logger.log(
293
267
  `Generating ICS file for fallback. Payload: ${JSON.stringify(payload)}`,
294
268
  );
269
+
295
270
  const base64String = await this.icsService.generateIcs(payload);
296
271
  this.logger.debug(`ICS generated (base64 length: ${base64String?.length})`);
297
272
 
273
+ // Normalize attendees
274
+ const attendeeEmails =
275
+ payload.attendees?.flatMap((a) =>
276
+ Array.isArray(a.email) ? a.email : [a.email],
277
+ ) || [];
278
+
279
+ // Combine into one list (to + attendees)
280
+ const toList = [
281
+ ...(Array.isArray(payload.to)
282
+ ? payload.to
283
+ : payload.to
284
+ ? [payload.to]
285
+ : []),
286
+ ...attendeeEmails,
287
+ ];
288
+
298
289
  const payloadSendMail: GenericMessageDto = {
299
290
  levelId,
300
291
  levelType,
301
- to: payload.to,
292
+ to: toList,
302
293
  message: payload.message,
303
294
  subject: payload.subject,
304
295
  type: 'EMAIL',
@@ -2,10 +2,9 @@ import { Injectable } from '@nestjs/common';
2
2
  import * as sgMail from '@sendgrid/mail';
3
3
  import axios from 'axios';
4
4
  import {
5
- CommunicationStrategy,
6
5
  CommunicationResult,
6
+ CommunicationStrategy,
7
7
  EmailAttachment,
8
- EmailAttachmentValidator,
9
8
  } from '../communication.strategy';
10
9
 
11
10
  @Injectable()
@@ -72,7 +72,6 @@ export class LoginController {
72
72
  // Passport automatically redirects to Google
73
73
  }
74
74
 
75
- // 2️⃣ Handles Google callback, validates user, creates session, and returns JWT
76
75
  @Get('google/callback')
77
76
  @UseGuards(GoogleAuthGuard)
78
77
  async googleAuthRedirect(@Req() req: any, @Res() res: Response) {
@@ -155,11 +154,18 @@ export class LoginController {
155
154
  `${this.configService.get('BASE_URL')}/auth?email=${email}&error='User not found'`,
156
155
  );
157
156
 
157
+ const profile = this.configService.get('PROFILE');
158
158
  const { accessToken, appcode } = data;
159
- if (data.slug) {
159
+ if (profile && profile === 'dev') {
160
160
  return res.redirect(
161
- `https://${data.slug}.${this.configService.get('DOMAIN_URL')}/auth?token=${accessToken}&appcode=${appcode}`,
161
+ `${this.configService.get('FE_URL')}/auth?token=${accessToken}&appcode=${appcode}`,
162
162
  );
163
+ } else {
164
+ if (data.slug) {
165
+ return res.redirect(
166
+ `https://${data.slug}.${this.configService.get('DOMAIN_URL')}/auth?token=${accessToken}&appcode=${appcode}`,
167
+ );
168
+ }
163
169
  }
164
170
 
165
171
  return res.redirect(
@@ -82,4 +82,7 @@ export class TaskDataEntity extends BaseEntity {
82
82
 
83
83
  @Column({ nullable: true, type: 'varchar' })
84
84
  subject: string;
85
+
86
+ @Column({ nullable: true, type: 'varchar' })
87
+ message: string;
85
88
  }
@@ -1,4 +1,5 @@
1
1
  DB_HOST: '13.234.25.234'
2
+ PROFILE: 'dev'
2
3
  # DB_HOST: 'localhost'
3
4
  DB_PORT: '3306'
4
5
  DB_USER: 'root'
@@ -10,6 +11,7 @@ SECRET_KEY: '1hard_to_guess_secret7890a'
10
11
  CLIENT_ID: '819281384645-2tnuvm80sul1n2ahqa4eg6kjd19pnbu9.apps.googleusercontent.com'
11
12
  CLIENT_SECRET: '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'
12
13
  CALLBACK_URL: 'http://localhost:5001/auth/google/callback'
14
+ FE_URL: 'http://localhost:3000'
13
15
  BASE_URL: 'http://localhost:5001'
14
16
  DOMAIN_URL: 'rezolut.in'
15
17
  OTP_EXPIRY: '10'