rez_core 2.2.258 → 2.2.259
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/app.module.js +2 -2
- package/dist/app.module.js.map +1 -1
- package/dist/module/integration/controller/calender-event.controller.js.map +1 -0
- package/dist/module/integration/controller/integration.controller.d.ts +113 -0
- package/dist/module/{communication/controller/communication.controller.js → integration/controller/integration.controller.js} +197 -75
- package/dist/module/integration/controller/integration.controller.js.map +1 -0
- package/dist/module/{communication → integration}/controller/wrapper.controller.d.ts +1 -1
- package/dist/module/integration/controller/wrapper.controller.js.map +1 -0
- package/dist/module/{communication → integration}/dto/create-config.dto.d.ts +48 -4
- package/dist/module/{communication → integration}/dto/create-config.dto.js +96 -18
- package/dist/module/integration/dto/create-config.dto.js.map +1 -0
- package/dist/module/{communication/entity/communication-config.entity.d.ts → integration/entity/integration-config.entity.d.ts} +11 -1
- package/dist/module/integration/entity/integration-config.entity.js +78 -0
- package/dist/module/integration/entity/integration-config.entity.js.map +1 -0
- package/dist/module/{communication → integration}/entity/integration-source.entity.d.ts +1 -1
- package/dist/module/{communication → integration}/entity/integration-source.entity.js +8 -8
- package/dist/module/integration/entity/integration-source.entity.js.map +1 -0
- package/dist/module/integration/entity/user-integration.entity.d.ts +23 -0
- package/dist/module/integration/entity/user-integration.entity.js +70 -0
- package/dist/module/integration/entity/user-integration.entity.js.map +1 -0
- package/dist/module/integration/examples/usage.example.d.ts +16 -0
- package/dist/module/integration/examples/usage.example.js +217 -0
- package/dist/module/integration/examples/usage.example.js.map +1 -0
- package/dist/module/{communication → integration}/factories/base.factory.d.ts +2 -2
- package/dist/module/integration/factories/base.factory.js.map +1 -0
- package/dist/module/{communication → integration}/factories/email.factory.d.ts +3 -7
- package/dist/module/{communication → integration}/factories/email.factory.js +1 -13
- package/dist/module/integration/factories/email.factory.js.map +1 -0
- package/dist/module/{communication/factories/communication.factory.d.ts → integration/factories/integration.factory.d.ts} +4 -4
- package/dist/module/{communication/factories/communication.factory.js → integration/factories/integration.factory.js} +26 -26
- package/dist/module/integration/factories/integration.factory.js.map +1 -0
- package/dist/module/integration/factories/sms.factory.d.ts +9 -0
- package/dist/module/integration/factories/sms.factory.js +26 -0
- package/dist/module/integration/factories/sms.factory.js.map +1 -0
- package/dist/module/{communication → integration}/factories/telephone.factory.d.ts +3 -5
- package/dist/module/{communication → integration}/factories/telephone.factory.js +11 -17
- package/dist/module/integration/factories/telephone.factory.js.map +1 -0
- package/dist/module/{communication → integration}/factories/whatsapp.factory.d.ts +2 -2
- package/dist/module/integration/factories/whatsapp.factory.js.map +1 -0
- package/dist/module/integration/integration.module.d.ts +2 -0
- package/dist/module/{communication/communication.module.js → integration/integration.module.js} +22 -42
- package/dist/module/integration/integration.module.js.map +1 -0
- package/dist/module/integration/service/calendar-event.service.js.map +1 -0
- package/dist/module/{communication/service/communication-queue.service.d.ts → integration/service/integration-queue.service.d.ts} +1 -1
- package/dist/module/{communication/service/communication-queue.service.js → integration/service/integration-queue.service.js} +8 -8
- package/dist/module/integration/service/integration-queue.service.js.map +1 -0
- package/dist/module/integration/service/integration.service.d.ts +155 -0
- package/dist/module/{communication/service/communication.service.js → integration/service/integration.service.js} +391 -307
- package/dist/module/integration/service/integration.service.js.map +1 -0
- package/dist/module/{communication → integration}/service/oauth.service.js +1 -1
- package/dist/module/integration/service/oauth.service.js.map +1 -0
- package/dist/module/{communication → integration}/service/wrapper.service.d.ts +4 -4
- package/dist/module/{communication → integration}/service/wrapper.service.js +25 -26
- package/dist/module/integration/service/wrapper.service.js.map +1 -0
- package/dist/module/{communication → integration}/strategies/email/gmail-api.strategy.d.ts +3 -3
- package/dist/module/{communication → integration}/strategies/email/gmail-api.strategy.js +2 -6
- package/dist/module/integration/strategies/email/gmail-api.strategy.js.map +1 -0
- package/dist/module/integration/strategies/email/outlook-api.strategy.d.ts +5 -0
- package/dist/module/integration/strategies/email/outlook-api.strategy.js.map +1 -0
- package/dist/module/integration/strategies/email/outlook.strategy.d.ts +5 -0
- package/dist/module/integration/strategies/email/outlook.strategy.js.map +1 -0
- package/dist/module/{communication → integration}/strategies/email/sendgrid-api.strategy.d.ts +3 -3
- package/dist/module/integration/strategies/email/sendgrid-api.strategy.js.map +1 -0
- package/dist/module/{communication/strategies/communication.strategy.d.ts → integration/strategies/integration.strategy.d.ts} +4 -3
- package/dist/module/{communication/strategies/communication.strategy.js → integration/strategies/integration.strategy.js} +1 -1
- package/dist/module/integration/strategies/integration.strategy.js.map +1 -0
- package/dist/module/integration/strategies/telephone/ozonetel-voice.strategy.d.ts +17 -0
- package/dist/module/{communication → integration}/strategies/telephone/ozonetel-voice.strategy.js +13 -5
- package/dist/module/integration/strategies/telephone/ozonetel-voice.strategy.js.map +1 -0
- package/dist/module/{communication → integration}/strategies/telephone/tubelight-voice.strategy.d.ts +6 -4
- package/dist/module/{communication → integration}/strategies/telephone/tubelight-voice.strategy.js +3 -7
- package/dist/module/integration/strategies/telephone/tubelight-voice.strategy.js.map +1 -0
- package/dist/module/{communication → integration}/strategies/whatsapp/whatsapp-cloud.strategy.d.ts +3 -3
- package/dist/module/integration/strategies/whatsapp/whatsapp-cloud.strategy.js.map +1 -0
- package/dist/module/integration/strategies/whatsapp/whatsapp.strategy.d.ts +5 -0
- package/dist/module/integration/strategies/whatsapp/whatsapp.strategy.js.map +1 -0
- package/dist/module/meta/entity/entity-master.entity.d.ts +1 -1
- package/dist/module/meta/entity/entity-master.entity.js +2 -2
- package/dist/module/meta/entity/entity-master.entity.js.map +1 -1
- package/dist/module/meta/service/entity-dynamic.service.js +47 -27
- package/dist/module/meta/service/entity-dynamic.service.js.map +1 -1
- package/dist/module/user/controller/login.controller.d.ts +3 -3
- package/dist/module/user/controller/login.controller.js +5 -5
- package/dist/module/user/controller/login.controller.js.map +1 -1
- package/dist/module/user/user.module.js +2 -2
- package/dist/module/user/user.module.js.map +1 -1
- package/dist/module/workflow-automation/entity/workflow-automation-action.entity.d.ts +1 -0
- package/dist/module/workflow-automation/entity/workflow-automation-action.entity.js +4 -0
- package/dist/module/workflow-automation/entity/workflow-automation-action.entity.js.map +1 -1
- package/dist/module/workflow-automation/service/workflow-automation.service.d.ts +2 -1
- package/dist/module/workflow-automation/service/workflow-automation.service.js +8 -4
- package/dist/module/workflow-automation/service/workflow-automation.service.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/docs/modules/event-driven-integration-design.md +92 -0
- package/docs/modules/integration.md +197 -0
- package/package.json +1 -1
- package/src/app.module.ts +2 -2
- package/src/module/integration/controller/integration.controller.ts +411 -0
- package/src/module/{communication → integration}/dto/create-config.dto.ts +110 -18
- package/src/module/{communication/entity/communication-config.entity.ts → integration/entity/integration-config.entity.ts} +33 -6
- package/src/module/{communication → integration}/entity/integration-source.entity.ts +1 -1
- package/src/module/integration/entity/user-integration.entity.ts +71 -0
- package/src/module/integration/examples/usage.example.ts +338 -0
- package/src/module/{communication → integration}/factories/base.factory.ts +2 -2
- package/src/module/{communication → integration}/factories/email.factory.ts +2 -12
- package/src/module/{communication/factories/communication.factory.ts → integration/factories/integration.factory.ts} +18 -18
- package/src/module/integration/factories/sms.factory.ts +19 -0
- package/src/module/integration/factories/telephone.factory.ts +41 -0
- package/src/module/{communication → integration}/factories/whatsapp.factory.ts +2 -2
- package/src/module/integration/integration.module.ts +86 -0
- package/src/module/{communication/service/communication-queue.service.ts → integration/service/integration-queue.service.ts} +2 -2
- package/src/module/{communication/service/communication.service.ts → integration/service/integration.service.ts} +598 -448
- package/src/module/{communication → integration}/service/oauth.service.ts +1 -1
- package/src/module/{communication → integration}/service/wrapper.service.ts +24 -25
- package/src/module/{communication → integration}/strategies/email/gmail-api.strategy.ts +6 -18
- package/src/module/{communication → integration}/strategies/email/outlook-api.strategy.ts +5 -5
- package/src/module/{communication → integration}/strategies/email/outlook.strategy.ts +5 -5
- package/src/module/{communication → integration}/strategies/email/sendgrid-api.strategy.ts +5 -5
- package/src/module/{communication/strategies/communication.strategy.ts → integration/strategies/integration.strategy.ts} +7 -3
- package/src/module/{communication → integration}/strategies/telephone/ozonetel-voice.strategy.ts +40 -12
- package/src/module/{communication → integration}/strategies/telephone/tubelight-voice.strategy.ts +24 -17
- package/src/module/{communication → integration}/strategies/whatsapp/whatsapp-cloud.strategy.ts +5 -5
- package/src/module/{communication → integration}/strategies/whatsapp/whatsapp.strategy.ts +5 -5
- package/src/module/meta/entity/entity-master.entity.ts +2 -2
- package/src/module/meta/service/entity-dynamic.service.ts +55 -28
- package/src/module/user/controller/login.controller.ts +3 -3
- package/src/module/user/user.module.ts +2 -2
- package/src/module/workflow-automation/entity/workflow-automation-action.entity.ts +3 -0
- package/src/module/workflow-automation/service/workflow-automation.service.ts +8 -4
- package/src/resources/dev.properties.yaml +3 -3
- package/.vscode/extensions.json +0 -5
- package/dist/module/communication/communication.module.d.ts +0 -2
- package/dist/module/communication/communication.module.js.map +0 -1
- package/dist/module/communication/controller/calender-event.controller.js.map +0 -1
- package/dist/module/communication/controller/communication.controller.d.ts +0 -99
- package/dist/module/communication/controller/communication.controller.js.map +0 -1
- package/dist/module/communication/controller/wrapper.controller.js.map +0 -1
- package/dist/module/communication/dto/create-config.dto.js.map +0 -1
- package/dist/module/communication/entity/communication-config.entity.js +0 -45
- package/dist/module/communication/entity/communication-config.entity.js.map +0 -1
- package/dist/module/communication/entity/communication-hub.entity.d.ts +0 -20
- package/dist/module/communication/entity/communication-hub.entity.js +0 -115
- package/dist/module/communication/entity/communication-hub.entity.js.map +0 -1
- package/dist/module/communication/entity/integration-source.entity.js.map +0 -1
- package/dist/module/communication/examples/usage.example.d.ts +0 -11
- package/dist/module/communication/examples/usage.example.js +0 -89
- package/dist/module/communication/examples/usage.example.js.map +0 -1
- package/dist/module/communication/factories/base.factory.js.map +0 -1
- package/dist/module/communication/factories/communication.factory.js.map +0 -1
- package/dist/module/communication/factories/email.factory.js.map +0 -1
- package/dist/module/communication/factories/sms.factory.d.ts +0 -15
- package/dist/module/communication/factories/sms.factory.js +0 -49
- package/dist/module/communication/factories/sms.factory.js.map +0 -1
- package/dist/module/communication/factories/telephone.factory.js.map +0 -1
- package/dist/module/communication/factories/whatsapp.factory.js.map +0 -1
- package/dist/module/communication/service/calendar-event.service.js.map +0 -1
- package/dist/module/communication/service/communication-queue.service.js.map +0 -1
- package/dist/module/communication/service/communication.service.d.ts +0 -155
- package/dist/module/communication/service/communication.service.js.map +0 -1
- package/dist/module/communication/service/oauth.service.js.map +0 -1
- package/dist/module/communication/service/wrapper.service.js.map +0 -1
- package/dist/module/communication/strategies/communication.strategy.js.map +0 -1
- package/dist/module/communication/strategies/email/gmail-api.strategy.js.map +0 -1
- package/dist/module/communication/strategies/email/gmail-smtp-v2.strategy.d.ts +0 -5
- package/dist/module/communication/strategies/email/gmail-smtp-v2.strategy.js +0 -60
- package/dist/module/communication/strategies/email/gmail-smtp-v2.strategy.js.map +0 -1
- package/dist/module/communication/strategies/email/gmail-smtp.strategy.d.ts +0 -5
- package/dist/module/communication/strategies/email/gmail-smtp.strategy.js +0 -49
- package/dist/module/communication/strategies/email/gmail-smtp.strategy.js.map +0 -1
- package/dist/module/communication/strategies/email/outlook-api.strategy.d.ts +0 -5
- package/dist/module/communication/strategies/email/outlook-api.strategy.js.map +0 -1
- package/dist/module/communication/strategies/email/outlook-smtp.strategy.d.ts +0 -5
- package/dist/module/communication/strategies/email/outlook-smtp.strategy.js +0 -65
- package/dist/module/communication/strategies/email/outlook-smtp.strategy.js.map +0 -1
- package/dist/module/communication/strategies/email/outlook.strategy.d.ts +0 -5
- package/dist/module/communication/strategies/email/outlook.strategy.js.map +0 -1
- package/dist/module/communication/strategies/email/sendgrid-api.strategy.js.map +0 -1
- package/dist/module/communication/strategies/sms/knowlarity-multi.strategy.d.ts +0 -6
- package/dist/module/communication/strategies/sms/knowlarity-multi.strategy.js +0 -121
- package/dist/module/communication/strategies/sms/knowlarity-multi.strategy.js.map +0 -1
- package/dist/module/communication/strategies/sms/knowlarity.strategy.d.ts +0 -5
- package/dist/module/communication/strategies/sms/knowlarity.strategy.js +0 -44
- package/dist/module/communication/strategies/sms/knowlarity.strategy.js.map +0 -1
- package/dist/module/communication/strategies/sms/twilio-v2.strategy.d.ts +0 -5
- package/dist/module/communication/strategies/sms/twilio-v2.strategy.js +0 -48
- package/dist/module/communication/strategies/sms/twilio-v2.strategy.js.map +0 -1
- package/dist/module/communication/strategies/sms/twilio.strategy.d.ts +0 -5
- package/dist/module/communication/strategies/sms/twilio.strategy.js +0 -44
- package/dist/module/communication/strategies/sms/twilio.strategy.js.map +0 -1
- package/dist/module/communication/strategies/telephone/knowlarity-multi.strategy.d.ts +0 -6
- package/dist/module/communication/strategies/telephone/knowlarity-multi.strategy.js +0 -121
- package/dist/module/communication/strategies/telephone/knowlarity-multi.strategy.js.map +0 -1
- package/dist/module/communication/strategies/telephone/knowlarity-voice.strategy.d.ts +0 -5
- package/dist/module/communication/strategies/telephone/knowlarity-voice.strategy.js +0 -44
- package/dist/module/communication/strategies/telephone/knowlarity-voice.strategy.js.map +0 -1
- package/dist/module/communication/strategies/telephone/ozonetel-voice.strategy.d.ts +0 -15
- package/dist/module/communication/strategies/telephone/ozonetel-voice.strategy.js.map +0 -1
- package/dist/module/communication/strategies/telephone/tubelight-voice.strategy.js.map +0 -1
- package/dist/module/communication/strategies/whatsapp/whatsapp-cloud.strategy.js.map +0 -1
- package/dist/module/communication/strategies/whatsapp/whatsapp.strategy.d.ts +0 -5
- package/dist/module/communication/strategies/whatsapp/whatsapp.strategy.js.map +0 -1
- package/docs/modules/communication.md +0 -177
- package/src/module/communication/communication.module.ts +0 -106
- package/src/module/communication/controller/communication.controller.ts +0 -293
- package/src/module/communication/entity/communication-hub.entity.ts +0 -103
- package/src/module/communication/examples/usage.example.ts +0 -170
- package/src/module/communication/factories/sms.factory.ts +0 -44
- package/src/module/communication/factories/telephone.factory.ts +0 -49
- package/src/module/communication/strategies/email/gmail-smtp-v2.strategy.ts +0 -68
- package/src/module/communication/strategies/email/gmail-smtp.strategy.ts +0 -51
- package/src/module/communication/strategies/email/outlook-smtp.strategy.ts +0 -73
- package/src/module/communication/strategies/sms/knowlarity-multi.strategy.ts +0 -158
- package/src/module/communication/strategies/sms/knowlarity.strategy.ts +0 -44
- package/src/module/communication/strategies/sms/twilio-v2.strategy.ts +0 -47
- package/src/module/communication/strategies/sms/twilio.strategy.ts +0 -44
- package/src/module/communication/strategies/telephone/knowlarity-multi.strategy.ts +0 -158
- package/src/module/communication/strategies/telephone/knowlarity-voice.strategy.ts +0 -44
- /package/dist/module/{communication → integration}/controller/calender-event.controller.d.ts +0 -0
- /package/dist/module/{communication → integration}/controller/calender-event.controller.js +0 -0
- /package/dist/module/{communication → integration}/controller/wrapper.controller.js +0 -0
- /package/dist/module/{communication → integration}/factories/base.factory.js +0 -0
- /package/dist/module/{communication → integration}/factories/whatsapp.factory.js +0 -0
- /package/dist/module/{communication → integration}/service/calendar-event.service.d.ts +0 -0
- /package/dist/module/{communication → integration}/service/calendar-event.service.js +0 -0
- /package/dist/module/{communication → integration}/service/oauth.service.d.ts +0 -0
- /package/dist/module/{communication → integration}/strategies/email/outlook-api.strategy.js +0 -0
- /package/dist/module/{communication → integration}/strategies/email/outlook.strategy.js +0 -0
- /package/dist/module/{communication → integration}/strategies/email/sendgrid-api.strategy.js +0 -0
- /package/dist/module/{communication → integration}/strategies/whatsapp/whatsapp-cloud.strategy.js +0 -0
- /package/dist/module/{communication → integration}/strategies/whatsapp/whatsapp.strategy.js +0 -0
- /package/src/module/{communication → integration}/controller/calender-event.controller.ts +0 -0
- /package/src/module/{communication → integration}/controller/wrapper.controller.ts +0 -0
- /package/src/module/{communication → integration}/service/calendar-event.service.ts +0 -0
|
@@ -3,29 +3,34 @@ import { InjectRepository } from '@nestjs/typeorm';
|
|
|
3
3
|
import { Not, Repository } from 'typeorm';
|
|
4
4
|
import { ConfigService } from '@nestjs/config';
|
|
5
5
|
import { google } from 'googleapis';
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} from '../
|
|
10
|
-
import { CommunicationConfig } from '../entity/communication-config.entity';
|
|
11
|
-
import { CommunicationFactory } from '../factories/communication.factory';
|
|
12
|
-
import { CommunicationResult } from '../strategies/communication.strategy';
|
|
6
|
+
import { IntegrationConfig } from '../entity/integration-config.entity';
|
|
7
|
+
import { UserIntegration } from '../entity/user-integration.entity';
|
|
8
|
+
import { IntegrationFactory } from '../factories/integration.factory';
|
|
9
|
+
import { IntegrationResult } from '../strategies/integration.strategy';
|
|
13
10
|
import { GmailApiStrategy } from '../strategies/email/gmail-api.strategy';
|
|
14
11
|
import { SendGridApiStrategy } from '../strategies/email/sendgrid-api.strategy';
|
|
15
|
-
import {
|
|
12
|
+
import { IntegrationQueueService } from './integration-queue.service';
|
|
13
|
+
import {
|
|
14
|
+
BulkMessageDto,
|
|
15
|
+
CreateUserIntegrationDto,
|
|
16
|
+
UpdateUserIntegrationDto,
|
|
17
|
+
} from '../dto/create-config.dto';
|
|
16
18
|
|
|
17
19
|
export interface SendMessageDto {
|
|
18
20
|
levelId: number;
|
|
19
21
|
levelType: string;
|
|
22
|
+
app_code: string;
|
|
20
23
|
to: string;
|
|
21
24
|
message: string;
|
|
22
|
-
mode?:
|
|
25
|
+
mode?: 'EMAIL' | 'SMS' | 'WA' | 'TELEPHONE';
|
|
23
26
|
priority?: number;
|
|
27
|
+
user_id?: number;
|
|
24
28
|
}
|
|
25
29
|
|
|
26
30
|
export interface GenericMessageDto {
|
|
27
31
|
levelId: number;
|
|
28
32
|
levelType: string;
|
|
33
|
+
app_code: string;
|
|
29
34
|
to: string | string[];
|
|
30
35
|
message: string;
|
|
31
36
|
subject?: string;
|
|
@@ -38,29 +43,17 @@ export interface GenericMessageDto {
|
|
|
38
43
|
mediaUrl?: string;
|
|
39
44
|
templateId?: string;
|
|
40
45
|
variables?: Record<string, any>;
|
|
46
|
+
user_id?: number;
|
|
41
47
|
}
|
|
42
48
|
|
|
43
|
-
export interface
|
|
44
|
-
|
|
45
|
-
levelType: string;
|
|
46
|
-
recipients: string[];
|
|
47
|
-
message: string;
|
|
48
|
-
subject?: string;
|
|
49
|
-
type?: 'EMAIL' | 'SMS' | 'WA' | 'TELEPHONE';
|
|
50
|
-
priority?: 'high' | 'medium' | 'low';
|
|
51
|
-
html?: string;
|
|
52
|
-
templateId?: string;
|
|
53
|
-
variables?: Record<string, any>;
|
|
54
|
-
batchSize?: number;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export interface CommunicationHubWithConfig extends CommunicationHub {
|
|
58
|
-
config: CommunicationConfig;
|
|
49
|
+
export interface IntegrationConfigWithConfig extends IntegrationConfig {
|
|
50
|
+
config?: any;
|
|
59
51
|
}
|
|
60
52
|
|
|
61
53
|
interface GmailOAuthState {
|
|
62
54
|
levelId: number;
|
|
63
55
|
levelType: string;
|
|
56
|
+
app_code: string;
|
|
64
57
|
email?: string;
|
|
65
58
|
timestamp: number;
|
|
66
59
|
}
|
|
@@ -71,63 +64,78 @@ export interface GmailSSOResult {
|
|
|
71
64
|
}
|
|
72
65
|
|
|
73
66
|
@Injectable()
|
|
74
|
-
export class
|
|
75
|
-
private readonly logger = new Logger(
|
|
67
|
+
export class IntegrationService {
|
|
68
|
+
private readonly logger = new Logger(IntegrationService.name);
|
|
76
69
|
private readonly gmailOAuthStates = new Map<string, GmailOAuthState>();
|
|
77
70
|
|
|
78
71
|
constructor(
|
|
79
|
-
@InjectRepository(
|
|
80
|
-
private readonly
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
private readonly configRepository: Repository<CommunicationConfig>,
|
|
72
|
+
@InjectRepository(IntegrationConfig)
|
|
73
|
+
private readonly configRepository: Repository<IntegrationConfig>,
|
|
74
|
+
@InjectRepository(UserIntegration)
|
|
75
|
+
private readonly userIntegrationRepository: Repository<UserIntegration>,
|
|
84
76
|
|
|
85
|
-
private readonly
|
|
77
|
+
private readonly integrationFactory: IntegrationFactory,
|
|
86
78
|
private readonly gmailApiStrategy: GmailApiStrategy,
|
|
87
79
|
private readonly sendGridApiStrategy: SendGridApiStrategy,
|
|
88
80
|
private readonly configService: ConfigService,
|
|
89
|
-
@Inject(forwardRef(() =>
|
|
90
|
-
private readonly queueService?:
|
|
81
|
+
@Inject(forwardRef(() => IntegrationQueueService))
|
|
82
|
+
private readonly queueService?: IntegrationQueueService,
|
|
91
83
|
) {}
|
|
92
84
|
|
|
85
|
+
private deriveServiceType(
|
|
86
|
+
integration_type: string,
|
|
87
|
+
integration_provider: string,
|
|
88
|
+
config_json: any,
|
|
89
|
+
): string {
|
|
90
|
+
// All integrations use API only (no SMTP support)
|
|
91
|
+
return 'API';
|
|
92
|
+
}
|
|
93
|
+
|
|
93
94
|
async sendMessage({
|
|
94
95
|
levelId,
|
|
95
96
|
levelType,
|
|
97
|
+
app_code,
|
|
96
98
|
to,
|
|
97
99
|
message,
|
|
98
100
|
mode,
|
|
99
101
|
priority = 1,
|
|
100
|
-
|
|
102
|
+
user_id,
|
|
103
|
+
}: SendMessageDto): Promise<IntegrationResult> {
|
|
101
104
|
try {
|
|
102
|
-
// Get active communication
|
|
103
|
-
const
|
|
105
|
+
// Get active communication configs for the level
|
|
106
|
+
const configs = await this.getActiveConfigs(
|
|
107
|
+
levelId,
|
|
108
|
+
levelType,
|
|
109
|
+
app_code,
|
|
110
|
+
mode,
|
|
111
|
+
);
|
|
104
112
|
|
|
105
|
-
if (!
|
|
113
|
+
if (!configs.length) {
|
|
106
114
|
throw new Error(
|
|
107
115
|
`No active communication configuration found for ${levelType} ${levelId}`,
|
|
108
116
|
);
|
|
109
117
|
}
|
|
110
118
|
|
|
111
119
|
// Sort by priority if provided
|
|
112
|
-
const
|
|
120
|
+
const sortedConfigs = this.sortConfigsByPriority(configs, priority);
|
|
113
121
|
|
|
114
|
-
// Try each
|
|
115
|
-
for (const
|
|
122
|
+
// Try each config until one succeeds
|
|
123
|
+
for (const config of sortedConfigs) {
|
|
116
124
|
try {
|
|
117
|
-
const result = await this.
|
|
125
|
+
const result = await this.sendViaConfig(config, to, message, user_id);
|
|
118
126
|
if (result.success) {
|
|
119
127
|
this.logger.log(
|
|
120
|
-
`Message sent successfully via ${
|
|
128
|
+
`Message sent successfully via ${config.integration_provider}`,
|
|
121
129
|
);
|
|
122
130
|
return result;
|
|
123
131
|
}
|
|
124
132
|
|
|
125
133
|
this.logger.warn(
|
|
126
|
-
`Failed to send via ${
|
|
134
|
+
`Failed to send via ${config.integration_provider}: ${result.error}`,
|
|
127
135
|
);
|
|
128
136
|
} catch (error) {
|
|
129
137
|
this.logger.error(
|
|
130
|
-
`Error sending via ${
|
|
138
|
+
`Error sending via ${config.integration_provider}:`,
|
|
131
139
|
error.message,
|
|
132
140
|
);
|
|
133
141
|
continue;
|
|
@@ -141,111 +149,85 @@ export class CommunicationService {
|
|
|
141
149
|
}
|
|
142
150
|
}
|
|
143
151
|
|
|
144
|
-
async
|
|
152
|
+
async getActiveConfigs(
|
|
145
153
|
levelId: number,
|
|
146
154
|
levelType: string,
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
.
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
)
|
|
156
|
-
.select([
|
|
157
|
-
'hub.id as hub_id',
|
|
158
|
-
'hub.level_id as hub_level_id',
|
|
159
|
-
'hub.level_type as hub_level_type',
|
|
160
|
-
'hub.status as hub_status',
|
|
161
|
-
'hub.config_id as hub_config_id',
|
|
162
|
-
'hub.communication_config_type as hub_communication_config_type',
|
|
163
|
-
'hub.service as hub_service',
|
|
164
|
-
'hub.provider as hub_provider',
|
|
165
|
-
'hub.priority as hub_priority',
|
|
166
|
-
'hub.is_default as hub_is_default',
|
|
167
|
-
'hub.created_at as hub_created_at',
|
|
168
|
-
'hub.updated_at as hub_updated_at',
|
|
169
|
-
'config.id as config_id',
|
|
170
|
-
'config.config_json as config_json',
|
|
171
|
-
'config.created_at as config_created_at',
|
|
172
|
-
'config.updated_at as config_updated_at',
|
|
173
|
-
])
|
|
174
|
-
.where('hub.level_id = :levelId', { levelId })
|
|
175
|
-
.andWhere('hub.level_type = :levelType', { levelType })
|
|
176
|
-
.andWhere('hub.status = :status', { status: 1 });
|
|
155
|
+
app_code: string,
|
|
156
|
+
mode?: 'EMAIL' | 'SMS' | 'WA' | 'TELEPHONE',
|
|
157
|
+
): Promise<IntegrationConfig[]> {
|
|
158
|
+
const queryBuilder = this.configRepository
|
|
159
|
+
.createQueryBuilder('config')
|
|
160
|
+
.where('config.level_id = :levelId', { levelId })
|
|
161
|
+
.andWhere('config.level_type = :levelType', { levelType })
|
|
162
|
+
.andWhere('config.app_code = :app_code', { app_code })
|
|
163
|
+
.andWhere('config.status = 1');
|
|
177
164
|
|
|
178
165
|
if (mode) {
|
|
179
|
-
|
|
166
|
+
queryBuilder.andWhere('config.integration_type = :mode', { mode });
|
|
180
167
|
}
|
|
181
168
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
// Transform the raw results into the expected format
|
|
185
|
-
const hubsWithConfig: CommunicationHubWithConfig[] = results.map((row) => ({
|
|
186
|
-
id: row.hub_id,
|
|
187
|
-
level_id: row.hub_level_id,
|
|
188
|
-
level_type: row.hub_level_type,
|
|
189
|
-
status: row.hub_status,
|
|
190
|
-
config_id: row.hub_config_id,
|
|
191
|
-
communication_config_type: row.hub_communication_config_type,
|
|
192
|
-
service: row.hub_service,
|
|
193
|
-
provider: row.hub_provider,
|
|
194
|
-
priority: row.hub_priority || 1,
|
|
195
|
-
is_default: row.hub_is_default || false,
|
|
196
|
-
created_at: row.hub_created_at,
|
|
197
|
-
updated_at: row.hub_updated_at,
|
|
198
|
-
config: {
|
|
199
|
-
id: row.config_id,
|
|
200
|
-
config_json: row.config_json,
|
|
201
|
-
created_at: row.config_created_at,
|
|
202
|
-
updated_at: row.config_updated_at,
|
|
203
|
-
},
|
|
204
|
-
}));
|
|
205
|
-
|
|
206
|
-
return hubsWithConfig;
|
|
169
|
+
return await queryBuilder.getMany();
|
|
207
170
|
}
|
|
208
171
|
|
|
209
|
-
private
|
|
210
|
-
|
|
172
|
+
private sortConfigsByPriority(
|
|
173
|
+
configs: IntegrationConfig[],
|
|
211
174
|
_priority: number,
|
|
212
|
-
):
|
|
213
|
-
|
|
214
|
-
|
|
175
|
+
): IntegrationConfig[] {
|
|
176
|
+
return configs.sort((a, b) => {
|
|
177
|
+
// First sort by default (true comes first)
|
|
178
|
+
if (a.is_default !== b.is_default) {
|
|
179
|
+
return a.is_default ? -1 : 1;
|
|
180
|
+
}
|
|
181
|
+
// Then by priority (lower number = higher priority)
|
|
182
|
+
return a.priority - b.priority;
|
|
183
|
+
});
|
|
215
184
|
}
|
|
216
185
|
|
|
217
|
-
private async
|
|
218
|
-
|
|
186
|
+
private async sendViaConfig(
|
|
187
|
+
config: IntegrationConfig,
|
|
219
188
|
to: string,
|
|
220
189
|
message: string,
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
190
|
+
user_id?: number,
|
|
191
|
+
): Promise<IntegrationResult> {
|
|
192
|
+
const strategy = this.integrationFactory.create(
|
|
193
|
+
config.integration_type,
|
|
194
|
+
'API', // service is deprecated, using default
|
|
195
|
+
config.integration_provider,
|
|
226
196
|
);
|
|
227
197
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
198
|
+
// Get user integration data if user_id provided
|
|
199
|
+
let finalConfig = config.config_json;
|
|
200
|
+
if (user_id) {
|
|
201
|
+
const userIntegrationData = await this.getUserIntegrationForStrategy(
|
|
202
|
+
user_id,
|
|
203
|
+
config.id,
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
if (userIntegrationData) {
|
|
207
|
+
finalConfig = {
|
|
208
|
+
...config.config_json,
|
|
209
|
+
external_user_id: userIntegrationData.external_user_id,
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const result = await strategy.sendMessage(to, message, finalConfig);
|
|
233
215
|
|
|
234
216
|
// If token was refreshed, update it in the database
|
|
235
217
|
if (result.refreshedToken && result.success) {
|
|
236
218
|
try {
|
|
237
|
-
const currentConfig =
|
|
219
|
+
const currentConfig = config.config_json as any;
|
|
238
220
|
const updatedConfig = {
|
|
239
221
|
...currentConfig,
|
|
240
222
|
accessToken: result.refreshedToken,
|
|
241
223
|
};
|
|
242
224
|
|
|
243
|
-
await this.configRepository.update(
|
|
225
|
+
await this.configRepository.update(config.id, {
|
|
244
226
|
config_json: updatedConfig,
|
|
245
227
|
} as any);
|
|
246
228
|
|
|
247
229
|
this.logger.log(
|
|
248
|
-
`Updated access token for ${
|
|
230
|
+
`Updated access token for ${config.integration_provider} configuration`,
|
|
249
231
|
);
|
|
250
232
|
} catch (error) {
|
|
251
233
|
this.logger.warn(
|
|
@@ -257,52 +239,66 @@ export class CommunicationService {
|
|
|
257
239
|
return result;
|
|
258
240
|
}
|
|
259
241
|
|
|
260
|
-
async
|
|
242
|
+
async createIntegrationConfig(
|
|
261
243
|
levelId: number,
|
|
262
244
|
levelType: string,
|
|
263
|
-
|
|
264
|
-
|
|
245
|
+
app_code: string,
|
|
246
|
+
configType: 'EMAIL' | 'SMS' | 'WA' | 'TELEPHONE',
|
|
265
247
|
provider: string,
|
|
248
|
+
integration_source_id: number,
|
|
266
249
|
config: any,
|
|
267
250
|
priority?: number,
|
|
268
251
|
is_default?: boolean,
|
|
269
252
|
): Promise<
|
|
270
|
-
|
|
253
|
+
IntegrationConfig | { authUrl: string; state: string; message: string }
|
|
271
254
|
> {
|
|
272
|
-
//
|
|
273
|
-
await this.validateUniqueActiveConfig(
|
|
255
|
+
// Validate that no duplicate provider configurations exist
|
|
256
|
+
await this.validateUniqueActiveConfig(
|
|
257
|
+
levelId,
|
|
258
|
+
levelType,
|
|
259
|
+
app_code,
|
|
260
|
+
configType,
|
|
261
|
+
provider,
|
|
262
|
+
);
|
|
274
263
|
|
|
275
|
-
//
|
|
264
|
+
// Deactivate all other configurations of the same integration type
|
|
265
|
+
await this.configRepository.update(
|
|
266
|
+
{
|
|
267
|
+
level_id: levelId,
|
|
268
|
+
level_type: levelType,
|
|
269
|
+
app_code: app_code,
|
|
270
|
+
integration_type: configType,
|
|
271
|
+
status: 1,
|
|
272
|
+
},
|
|
273
|
+
{ status: 0 },
|
|
274
|
+
);
|
|
275
|
+
|
|
276
|
+
// Validate provider and get service type from supported combinations
|
|
276
277
|
const supportedCombinations = await this.getSupportedCombinations();
|
|
277
|
-
const
|
|
278
|
+
const validCombination = supportedCombinations.find(
|
|
278
279
|
(combo) =>
|
|
279
280
|
combo.mode === configType &&
|
|
280
|
-
combo.service.toLowerCase() === service.toLowerCase() &&
|
|
281
281
|
combo.provider.toLowerCase() === provider.toLowerCase(),
|
|
282
282
|
);
|
|
283
283
|
|
|
284
|
-
if (!
|
|
285
|
-
throw new Error(
|
|
286
|
-
`Unsupported combination: ${configType}/${service}/${provider}`,
|
|
287
|
-
);
|
|
284
|
+
if (!validCombination) {
|
|
285
|
+
throw new Error(`Unsupported combination: ${configType}/${provider}`);
|
|
288
286
|
}
|
|
289
287
|
|
|
288
|
+
const service = validCombination.service;
|
|
289
|
+
|
|
290
290
|
// Check if this requires OAuth flow
|
|
291
|
-
const requiresOAuth = this.requiresOAuthFlow(
|
|
292
|
-
configType,
|
|
293
|
-
service,
|
|
294
|
-
provider,
|
|
295
|
-
config,
|
|
296
|
-
);
|
|
291
|
+
const requiresOAuth = this.requiresOAuthFlow(configType, provider, config);
|
|
297
292
|
|
|
298
293
|
if (requiresOAuth) {
|
|
299
294
|
// Generate OAuth URL and return it instead of creating config immediately
|
|
300
295
|
return await this.generateOAuthUrl(
|
|
301
296
|
levelId,
|
|
302
297
|
levelType,
|
|
298
|
+
app_code,
|
|
303
299
|
configType,
|
|
304
|
-
service,
|
|
305
300
|
provider,
|
|
301
|
+
integration_source_id,
|
|
306
302
|
config,
|
|
307
303
|
priority,
|
|
308
304
|
is_default,
|
|
@@ -313,9 +309,10 @@ export class CommunicationService {
|
|
|
313
309
|
return await this.createDirectConfig(
|
|
314
310
|
levelId,
|
|
315
311
|
levelType,
|
|
312
|
+
app_code,
|
|
316
313
|
configType,
|
|
317
|
-
service,
|
|
318
314
|
provider,
|
|
315
|
+
integration_source_id,
|
|
319
316
|
config,
|
|
320
317
|
priority,
|
|
321
318
|
is_default,
|
|
@@ -327,35 +324,35 @@ export class CommunicationService {
|
|
|
327
324
|
service: string;
|
|
328
325
|
provider: string;
|
|
329
326
|
}[] {
|
|
330
|
-
return this.
|
|
327
|
+
return this.integrationFactory.getAllSupportedCombinations();
|
|
331
328
|
}
|
|
332
329
|
|
|
333
330
|
async getLevelConfigs(
|
|
334
331
|
levelId: number,
|
|
335
332
|
levelType: string,
|
|
336
333
|
filters?: {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
334
|
+
app_code?: string;
|
|
335
|
+
integration_type?: 'WA' | 'SMS' | 'EMAIL' | 'TELEPHONE';
|
|
336
|
+
integration_provider?: string;
|
|
340
337
|
},
|
|
341
338
|
): Promise<
|
|
342
|
-
Array<
|
|
339
|
+
Array<IntegrationConfig & { linkedSource?: string; configDetails?: any }>
|
|
343
340
|
> {
|
|
344
341
|
const where: any = { level_id: levelId, level_type: levelType };
|
|
345
342
|
|
|
346
|
-
if (filters?.
|
|
347
|
-
where.
|
|
343
|
+
if (filters?.app_code) {
|
|
344
|
+
where.app_code = filters.app_code;
|
|
348
345
|
}
|
|
349
346
|
|
|
350
|
-
if (filters?.
|
|
351
|
-
where.
|
|
347
|
+
if (filters?.integration_type) {
|
|
348
|
+
where.integration_type = filters.integration_type;
|
|
352
349
|
}
|
|
353
350
|
|
|
354
|
-
if (filters?.
|
|
355
|
-
where.
|
|
351
|
+
if (filters?.integration_provider) {
|
|
352
|
+
where.integration_provider = filters.integration_provider;
|
|
356
353
|
}
|
|
357
354
|
|
|
358
|
-
const hubs = await this.
|
|
355
|
+
const hubs = await this.configRepository.find({
|
|
359
356
|
where,
|
|
360
357
|
order: { created_at: 'DESC' },
|
|
361
358
|
});
|
|
@@ -364,11 +361,11 @@ export class CommunicationService {
|
|
|
364
361
|
const enhancedHubs = await Promise.all(
|
|
365
362
|
hubs.map(async (hub) => {
|
|
366
363
|
try {
|
|
367
|
-
const
|
|
368
|
-
where: { id: hub.
|
|
364
|
+
const relatedConfig = await this.configRepository.findOne({
|
|
365
|
+
where: { id: hub.id },
|
|
369
366
|
});
|
|
370
367
|
|
|
371
|
-
if (!
|
|
368
|
+
if (!relatedConfig) {
|
|
372
369
|
return {
|
|
373
370
|
...hub,
|
|
374
371
|
linkedSource: 'Configuration not found',
|
|
@@ -377,17 +374,15 @@ export class CommunicationService {
|
|
|
377
374
|
}
|
|
378
375
|
|
|
379
376
|
const linkedSource = this.extractLinkedSource(
|
|
380
|
-
hub.
|
|
381
|
-
hub.
|
|
382
|
-
|
|
383
|
-
config.config_json,
|
|
377
|
+
hub.integration_type,
|
|
378
|
+
hub.integration_provider,
|
|
379
|
+
relatedConfig.config_json,
|
|
384
380
|
);
|
|
385
381
|
|
|
386
382
|
const configDetails = this.extractConfigDetails(
|
|
387
|
-
hub.
|
|
388
|
-
hub.
|
|
389
|
-
|
|
390
|
-
config.config_json,
|
|
383
|
+
hub.integration_type,
|
|
384
|
+
hub.integration_provider,
|
|
385
|
+
relatedConfig.config_json,
|
|
391
386
|
);
|
|
392
387
|
|
|
393
388
|
return {
|
|
@@ -414,21 +409,20 @@ export class CommunicationService {
|
|
|
414
409
|
|
|
415
410
|
private extractLinkedSource(
|
|
416
411
|
configType: string,
|
|
417
|
-
service: string,
|
|
418
412
|
provider: string,
|
|
419
413
|
configJson: any,
|
|
420
414
|
): string {
|
|
421
|
-
const key = `${configType.toLowerCase()}_${
|
|
415
|
+
const key = `${configType.toLowerCase()}_${provider.toLowerCase()}`;
|
|
422
416
|
|
|
423
417
|
try {
|
|
424
418
|
switch (key) {
|
|
425
419
|
// Gmail configurations
|
|
426
|
-
case '
|
|
420
|
+
case 'email_gmail':
|
|
427
421
|
case 'email_smtp_gmail':
|
|
428
422
|
return configJson?.email || 'Gmail account not configured';
|
|
429
423
|
|
|
430
424
|
// Outlook configurations
|
|
431
|
-
case '
|
|
425
|
+
case 'email_outlook':
|
|
432
426
|
case 'email_smtp_outlook':
|
|
433
427
|
return configJson?.email || 'Outlook account not configured';
|
|
434
428
|
|
|
@@ -461,8 +455,8 @@ export class CommunicationService {
|
|
|
461
455
|
: 'Ozonetel voice not configured';
|
|
462
456
|
|
|
463
457
|
// AWS SES configurations
|
|
464
|
-
case '
|
|
465
|
-
case '
|
|
458
|
+
case 'email_aws-ses':
|
|
459
|
+
case 'email_ses':
|
|
466
460
|
return configJson?.fromEmail || 'AWS SES not configured';
|
|
467
461
|
|
|
468
462
|
// SendGrid configurations
|
|
@@ -492,16 +486,15 @@ export class CommunicationService {
|
|
|
492
486
|
|
|
493
487
|
private extractConfigDetails(
|
|
494
488
|
configType: string,
|
|
495
|
-
service: string,
|
|
496
489
|
provider: string,
|
|
497
490
|
configJson: any,
|
|
498
491
|
): any {
|
|
499
|
-
const key = `${configType.toLowerCase()}_${
|
|
492
|
+
const key = `${configType.toLowerCase()}_${provider.toLowerCase()}`;
|
|
500
493
|
|
|
501
494
|
try {
|
|
502
495
|
switch (key) {
|
|
503
496
|
// Gmail configurations
|
|
504
|
-
case '
|
|
497
|
+
case 'email_gmail':
|
|
505
498
|
return {
|
|
506
499
|
email: configJson?.email,
|
|
507
500
|
authMethod: configJson?.authMethod || 'OAUTH2',
|
|
@@ -519,7 +512,7 @@ export class CommunicationService {
|
|
|
519
512
|
};
|
|
520
513
|
|
|
521
514
|
// Outlook configurations
|
|
522
|
-
case '
|
|
515
|
+
case 'email_outlook':
|
|
523
516
|
return {
|
|
524
517
|
email: configJson?.email,
|
|
525
518
|
authMethod: 'OAUTH2',
|
|
@@ -578,8 +571,8 @@ export class CommunicationService {
|
|
|
578
571
|
};
|
|
579
572
|
|
|
580
573
|
// AWS SES configurations
|
|
581
|
-
case '
|
|
582
|
-
case '
|
|
574
|
+
case 'email_aws-ses':
|
|
575
|
+
case 'email_ses':
|
|
583
576
|
return {
|
|
584
577
|
fromEmail: configJson?.fromEmail,
|
|
585
578
|
region: configJson?.region,
|
|
@@ -665,21 +658,22 @@ export class CommunicationService {
|
|
|
665
658
|
|
|
666
659
|
async updateConfigStatus(hubId: number, status: number): Promise<void> {
|
|
667
660
|
// Find the hub to get level and type information
|
|
668
|
-
const
|
|
661
|
+
const config = await this.configRepository.findOne({
|
|
669
662
|
where: { id: hubId },
|
|
670
663
|
});
|
|
671
664
|
|
|
672
|
-
if (!
|
|
673
|
-
throw new Error('
|
|
665
|
+
if (!config) {
|
|
666
|
+
throw new Error('Integration configuration not found');
|
|
674
667
|
}
|
|
675
668
|
|
|
676
|
-
// If activating, deactivate other configs
|
|
669
|
+
// If activating, deactivate ALL other configs of the same integration type
|
|
677
670
|
if (status === 1) {
|
|
678
|
-
await this.
|
|
671
|
+
await this.configRepository.update(
|
|
679
672
|
{
|
|
680
|
-
level_id:
|
|
681
|
-
level_type:
|
|
682
|
-
|
|
673
|
+
level_id: config.level_id,
|
|
674
|
+
level_type: config.level_type,
|
|
675
|
+
app_code: config.app_code,
|
|
676
|
+
integration_type: config.integration_type,
|
|
683
677
|
status: 1,
|
|
684
678
|
id: Not(hubId),
|
|
685
679
|
},
|
|
@@ -688,26 +682,22 @@ export class CommunicationService {
|
|
|
688
682
|
}
|
|
689
683
|
|
|
690
684
|
// Update the requested config
|
|
691
|
-
await this.
|
|
685
|
+
await this.configRepository.update(hubId, { status });
|
|
692
686
|
}
|
|
693
687
|
|
|
694
|
-
async deleteConfiguration(
|
|
695
|
-
// Find the hub to get the
|
|
696
|
-
const
|
|
697
|
-
where: { id:
|
|
688
|
+
async deleteConfiguration(configId: number): Promise<void> {
|
|
689
|
+
// Find the hub to get the id
|
|
690
|
+
const config = await this.configRepository.findOne({
|
|
691
|
+
where: { id: configId },
|
|
698
692
|
});
|
|
699
693
|
|
|
700
|
-
if (!
|
|
701
|
-
throw new Error('
|
|
694
|
+
if (!config) {
|
|
695
|
+
throw new Error('Integration configuration not found');
|
|
702
696
|
}
|
|
703
697
|
|
|
704
|
-
await this.
|
|
705
|
-
|
|
706
|
-
await this.configRepository.delete(hub.config_id);
|
|
698
|
+
await this.configRepository.delete(configId);
|
|
707
699
|
|
|
708
|
-
this.logger.log(
|
|
709
|
-
`Communication configuration deleted: Hub ${hubId}, Config ${hub.config_id}`,
|
|
710
|
-
);
|
|
700
|
+
this.logger.log(`Integration configuration deleted: ${configId}`);
|
|
711
701
|
}
|
|
712
702
|
|
|
713
703
|
async updateConfiguration(
|
|
@@ -718,104 +708,75 @@ export class CommunicationService {
|
|
|
718
708
|
is_default?: boolean;
|
|
719
709
|
status?: number;
|
|
720
710
|
},
|
|
721
|
-
): Promise<
|
|
711
|
+
): Promise<IntegrationConfig & { config?: any }> {
|
|
722
712
|
// Find the existing hub
|
|
723
|
-
const
|
|
713
|
+
const config = await this.configRepository.findOne({
|
|
724
714
|
where: { id: hubId },
|
|
725
715
|
});
|
|
726
716
|
|
|
727
|
-
if (!
|
|
728
|
-
throw new Error('
|
|
717
|
+
if (!config) {
|
|
718
|
+
throw new Error('Integration configuration not found');
|
|
729
719
|
}
|
|
730
720
|
|
|
731
721
|
// Update configuration JSON if provided
|
|
732
722
|
if (updateData.config) {
|
|
733
|
-
const existingConfig = await this.configRepository.findOne({
|
|
734
|
-
where: { id: hub.config_id },
|
|
735
|
-
});
|
|
736
|
-
|
|
737
|
-
if (!existingConfig) {
|
|
738
|
-
throw new Error('Configuration record not found');
|
|
739
|
-
}
|
|
740
|
-
|
|
741
723
|
// Merge the new config with existing config
|
|
742
724
|
const updatedConfigJson = {
|
|
743
|
-
...
|
|
725
|
+
...config.config_json,
|
|
744
726
|
...updateData.config,
|
|
745
727
|
};
|
|
746
728
|
|
|
747
|
-
await this.configRepository.update(
|
|
729
|
+
await this.configRepository.update(config.id, {
|
|
748
730
|
config_json: updatedConfigJson,
|
|
749
|
-
});
|
|
750
|
-
}
|
|
751
|
-
|
|
752
|
-
// Deactivate other configurations if this one is being activated
|
|
753
|
-
if (updateData.status === 1) {
|
|
754
|
-
await this.validateUniqueActiveConfig(
|
|
755
|
-
hub.level_id,
|
|
756
|
-
hub.level_type,
|
|
757
|
-
hub.communication_config_type,
|
|
758
|
-
hubId, // Exclude current hub
|
|
759
|
-
);
|
|
731
|
+
} as any);
|
|
760
732
|
}
|
|
761
733
|
|
|
762
|
-
// Handle default configuration logic
|
|
734
|
+
// Handle default configuration logic (simplified for now)
|
|
763
735
|
if (updateData.is_default === true) {
|
|
764
736
|
// Remove default from other configurations of same type and level
|
|
765
|
-
await this.
|
|
737
|
+
await this.configRepository.update(
|
|
766
738
|
{
|
|
767
|
-
level_id:
|
|
768
|
-
level_type:
|
|
769
|
-
|
|
770
|
-
id: Not(hubId),
|
|
739
|
+
level_id: config.level_id,
|
|
740
|
+
level_type: config.level_type,
|
|
741
|
+
integration_type: config.integration_type,
|
|
742
|
+
id: Not(hubId),
|
|
771
743
|
},
|
|
772
744
|
{ is_default: false },
|
|
773
745
|
);
|
|
774
746
|
}
|
|
775
747
|
|
|
776
|
-
//
|
|
777
|
-
const
|
|
778
|
-
if (updateData.priority !== undefined)
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
748
|
+
// Apply direct config updates if any
|
|
749
|
+
const directUpdates: any = {};
|
|
750
|
+
if (updateData.priority !== undefined)
|
|
751
|
+
directUpdates.priority = updateData.priority;
|
|
752
|
+
if (updateData.is_default !== undefined)
|
|
753
|
+
directUpdates.is_default = updateData.is_default;
|
|
754
|
+
if (updateData.status !== undefined)
|
|
755
|
+
directUpdates.status = updateData.status;
|
|
756
|
+
|
|
757
|
+
if (Object.keys(directUpdates).length > 0) {
|
|
758
|
+
await this.configRepository.update(config.id, directUpdates);
|
|
786
759
|
}
|
|
787
760
|
|
|
788
|
-
//
|
|
789
|
-
if (Object.keys(hubUpdateData).length > 0) {
|
|
790
|
-
await this.hubRepository.update(hubId, hubUpdateData);
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
// Fetch and return updated hub with config
|
|
794
|
-
const updatedHub = await this.hubRepository.findOne({
|
|
795
|
-
where: { id: hubId },
|
|
796
|
-
});
|
|
797
|
-
|
|
761
|
+
// Fetch and return updated config
|
|
798
762
|
const updatedConfig = await this.configRepository.findOne({
|
|
799
|
-
where: { id:
|
|
763
|
+
where: { id: hubId },
|
|
800
764
|
});
|
|
801
765
|
|
|
802
|
-
this.logger.log(
|
|
803
|
-
`Communication configuration updated: Hub ${hubId}, Type ${hub.communication_config_type}`,
|
|
804
|
-
);
|
|
805
|
-
|
|
806
766
|
return {
|
|
807
|
-
...
|
|
767
|
+
...updatedConfig,
|
|
808
768
|
config: updatedConfig?.config_json,
|
|
809
|
-
};
|
|
769
|
+
} as any;
|
|
810
770
|
}
|
|
811
771
|
|
|
812
772
|
async sendGenericMessage(
|
|
813
773
|
messageDto: GenericMessageDto,
|
|
814
|
-
): Promise<
|
|
774
|
+
): Promise<IntegrationResult> {
|
|
815
775
|
try {
|
|
816
776
|
const {
|
|
817
777
|
levelId,
|
|
818
778
|
levelType,
|
|
779
|
+
app_code,
|
|
819
780
|
to,
|
|
820
781
|
message,
|
|
821
782
|
type,
|
|
@@ -828,21 +789,23 @@ export class CommunicationService {
|
|
|
828
789
|
mediaUrl,
|
|
829
790
|
templateId,
|
|
830
791
|
variables,
|
|
792
|
+
user_id,
|
|
831
793
|
} = messageDto;
|
|
832
794
|
|
|
833
795
|
// Auto-detect communication type if not specified
|
|
834
796
|
const communicationType = this.detectCommunicationType(to, type);
|
|
835
797
|
|
|
836
|
-
// Get active
|
|
837
|
-
const
|
|
798
|
+
// Get active configs for the detected type
|
|
799
|
+
const configs = await this.getActiveConfigs(
|
|
838
800
|
levelId,
|
|
839
801
|
levelType,
|
|
802
|
+
app_code,
|
|
840
803
|
communicationType,
|
|
841
804
|
);
|
|
842
805
|
|
|
843
|
-
if (!
|
|
806
|
+
if (!configs.length) {
|
|
844
807
|
this.logger.warn(
|
|
845
|
-
`No communication hubs found for ${levelType} ${levelId}. Please configure
|
|
808
|
+
`No communication hubs found for ${levelType} ${levelId}. Please configure integration providers using the createIntegrationConfig method.`,
|
|
846
809
|
);
|
|
847
810
|
throw new Error(
|
|
848
811
|
`No active ${communicationType} configuration found for ${levelType} ${levelId}. Please configure a communication provider first.`,
|
|
@@ -850,7 +813,10 @@ export class CommunicationService {
|
|
|
850
813
|
}
|
|
851
814
|
|
|
852
815
|
// Sort hubs by priority and default preference
|
|
853
|
-
const
|
|
816
|
+
const sortedConfigs = this.sortConfigsByPriorityAndDefault(
|
|
817
|
+
configs,
|
|
818
|
+
priority,
|
|
819
|
+
);
|
|
854
820
|
|
|
855
821
|
// Prepare enhanced config with additional parameters
|
|
856
822
|
const enhancedConfig = {
|
|
@@ -864,16 +830,21 @@ export class CommunicationService {
|
|
|
864
830
|
|
|
865
831
|
// Handle multiple recipients by sending to each individually
|
|
866
832
|
if (Array.isArray(to)) {
|
|
867
|
-
const results:
|
|
833
|
+
const results: IntegrationResult[] = [];
|
|
868
834
|
let hasSuccess = false;
|
|
869
835
|
|
|
870
836
|
for (const recipient of to) {
|
|
871
|
-
for (const hub of
|
|
837
|
+
for (const hub of sortedConfigs) {
|
|
872
838
|
try {
|
|
873
|
-
const
|
|
874
|
-
hub.
|
|
875
|
-
hub.
|
|
876
|
-
hub.
|
|
839
|
+
const serviceType = this.deriveServiceType(
|
|
840
|
+
hub.integration_type,
|
|
841
|
+
hub.integration_provider,
|
|
842
|
+
hub.config_json,
|
|
843
|
+
);
|
|
844
|
+
const strategy = this.integrationFactory.create(
|
|
845
|
+
hub.integration_type,
|
|
846
|
+
serviceType,
|
|
847
|
+
hub.integration_provider,
|
|
877
848
|
);
|
|
878
849
|
|
|
879
850
|
// Process template if provided
|
|
@@ -883,13 +854,26 @@ export class CommunicationService {
|
|
|
883
854
|
}
|
|
884
855
|
|
|
885
856
|
// Merge config with enhanced parameters
|
|
886
|
-
|
|
887
|
-
...hub.
|
|
857
|
+
let finalConfig = {
|
|
858
|
+
...hub.config_json,
|
|
888
859
|
...enhancedConfig,
|
|
889
860
|
templateId,
|
|
890
861
|
variables,
|
|
891
862
|
};
|
|
892
863
|
|
|
864
|
+
// Handle user integration if user_id provided
|
|
865
|
+
if (user_id) {
|
|
866
|
+
const userIntegrationData =
|
|
867
|
+
await this.getUserIntegrationForStrategy(user_id, hub.id);
|
|
868
|
+
|
|
869
|
+
if (userIntegrationData) {
|
|
870
|
+
finalConfig = {
|
|
871
|
+
...finalConfig,
|
|
872
|
+
external_user_id: userIntegrationData.external_user_id,
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
|
|
893
877
|
const result = await strategy.sendMessage(
|
|
894
878
|
recipient,
|
|
895
879
|
processedMessage,
|
|
@@ -898,7 +882,7 @@ export class CommunicationService {
|
|
|
898
882
|
|
|
899
883
|
if (result.success) {
|
|
900
884
|
this.logger.log(
|
|
901
|
-
`Generic message sent successfully via ${hub.
|
|
885
|
+
`Generic message sent successfully via ${hub.integration_provider} to ${recipient}`,
|
|
902
886
|
);
|
|
903
887
|
results.push(result);
|
|
904
888
|
hasSuccess = true;
|
|
@@ -906,11 +890,11 @@ export class CommunicationService {
|
|
|
906
890
|
}
|
|
907
891
|
|
|
908
892
|
this.logger.warn(
|
|
909
|
-
`Failed to send via ${hub.
|
|
893
|
+
`Failed to send via ${hub.integration_provider} to ${recipient}: ${result.error}`,
|
|
910
894
|
);
|
|
911
895
|
} catch (error) {
|
|
912
896
|
this.logger.error(
|
|
913
|
-
`Error sending via ${hub.
|
|
897
|
+
`Error sending via ${hub.integration_provider} to ${recipient}:`,
|
|
914
898
|
error.message,
|
|
915
899
|
);
|
|
916
900
|
continue;
|
|
@@ -929,12 +913,17 @@ export class CommunicationService {
|
|
|
929
913
|
}
|
|
930
914
|
} else {
|
|
931
915
|
// Handle single recipient
|
|
932
|
-
for (const hub of
|
|
916
|
+
for (const hub of sortedConfigs) {
|
|
933
917
|
try {
|
|
934
|
-
const
|
|
935
|
-
hub.
|
|
936
|
-
hub.
|
|
937
|
-
hub.
|
|
918
|
+
const serviceType = this.deriveServiceType(
|
|
919
|
+
hub.integration_type,
|
|
920
|
+
hub.integration_provider,
|
|
921
|
+
hub.config_json,
|
|
922
|
+
);
|
|
923
|
+
const strategy = this.integrationFactory.create(
|
|
924
|
+
hub.integration_type,
|
|
925
|
+
serviceType,
|
|
926
|
+
hub.integration_provider,
|
|
938
927
|
);
|
|
939
928
|
|
|
940
929
|
// Process template if provided
|
|
@@ -947,13 +936,26 @@ export class CommunicationService {
|
|
|
947
936
|
}
|
|
948
937
|
|
|
949
938
|
// Merge config with enhanced parameters
|
|
950
|
-
|
|
951
|
-
...hub.
|
|
939
|
+
let finalConfig = {
|
|
940
|
+
...hub.config_json,
|
|
952
941
|
...enhancedConfig,
|
|
953
942
|
templateId,
|
|
954
943
|
variables,
|
|
955
944
|
};
|
|
956
945
|
|
|
946
|
+
// Handle user integration if user_id provided
|
|
947
|
+
if (user_id) {
|
|
948
|
+
const userIntegrationData =
|
|
949
|
+
await this.getUserIntegrationForStrategy(user_id, hub.id);
|
|
950
|
+
|
|
951
|
+
if (userIntegrationData) {
|
|
952
|
+
finalConfig = {
|
|
953
|
+
...finalConfig,
|
|
954
|
+
external_user_id: userIntegrationData.external_user_id,
|
|
955
|
+
};
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
|
|
957
959
|
const result = await strategy.sendMessage(
|
|
958
960
|
to,
|
|
959
961
|
processedMessage,
|
|
@@ -962,17 +964,17 @@ export class CommunicationService {
|
|
|
962
964
|
|
|
963
965
|
if (result.success) {
|
|
964
966
|
this.logger.log(
|
|
965
|
-
`Generic message sent successfully via ${hub.
|
|
967
|
+
`Generic message sent successfully via ${hub.integration_provider} to ${to}`,
|
|
966
968
|
);
|
|
967
969
|
return result;
|
|
968
970
|
}
|
|
969
971
|
|
|
970
972
|
this.logger.warn(
|
|
971
|
-
`Failed to send via ${hub.
|
|
973
|
+
`Failed to send via ${hub.integration_provider}: ${result.error}`,
|
|
972
974
|
);
|
|
973
975
|
} catch (error) {
|
|
974
976
|
this.logger.error(
|
|
975
|
-
`Error sending via ${hub.
|
|
977
|
+
`Error sending via ${hub.integration_provider}:`,
|
|
976
978
|
error.message,
|
|
977
979
|
);
|
|
978
980
|
continue;
|
|
@@ -989,11 +991,12 @@ export class CommunicationService {
|
|
|
989
991
|
|
|
990
992
|
async sendBulkMessage(
|
|
991
993
|
bulkDto: BulkMessageDto,
|
|
992
|
-
): Promise<{ results:
|
|
994
|
+
): Promise<{ results: IntegrationResult[]; summary: any }> {
|
|
993
995
|
try {
|
|
994
996
|
const {
|
|
995
997
|
levelId,
|
|
996
998
|
levelType,
|
|
999
|
+
app_code,
|
|
997
1000
|
recipients,
|
|
998
1001
|
message,
|
|
999
1002
|
type,
|
|
@@ -1005,7 +1008,7 @@ export class CommunicationService {
|
|
|
1005
1008
|
batchSize = 10,
|
|
1006
1009
|
} = bulkDto;
|
|
1007
1010
|
|
|
1008
|
-
const results:
|
|
1011
|
+
const results: IntegrationResult[] = [];
|
|
1009
1012
|
const batches = this.chunkArray(recipients, batchSize);
|
|
1010
1013
|
|
|
1011
1014
|
for (let i = 0; i < batches.length; i++) {
|
|
@@ -1019,6 +1022,7 @@ export class CommunicationService {
|
|
|
1019
1022
|
const messageDto: GenericMessageDto = {
|
|
1020
1023
|
levelId,
|
|
1021
1024
|
levelType,
|
|
1025
|
+
app_code,
|
|
1022
1026
|
to: recipient,
|
|
1023
1027
|
message,
|
|
1024
1028
|
type,
|
|
@@ -1037,7 +1041,7 @@ export class CommunicationService {
|
|
|
1037
1041
|
service: 'unknown',
|
|
1038
1042
|
error: error.message,
|
|
1039
1043
|
timestamp: new Date(),
|
|
1040
|
-
} as
|
|
1044
|
+
} as IntegrationResult;
|
|
1041
1045
|
}
|
|
1042
1046
|
});
|
|
1043
1047
|
|
|
@@ -1052,7 +1056,7 @@ export class CommunicationService {
|
|
|
1052
1056
|
service: 'unknown',
|
|
1053
1057
|
error: result.reason?.message || 'Unknown error',
|
|
1054
1058
|
timestamp: new Date(),
|
|
1055
|
-
} as
|
|
1059
|
+
} as IntegrationResult;
|
|
1056
1060
|
}
|
|
1057
1061
|
});
|
|
1058
1062
|
|
|
@@ -1098,7 +1102,7 @@ export class CommunicationService {
|
|
|
1098
1102
|
};
|
|
1099
1103
|
}
|
|
1100
1104
|
|
|
1101
|
-
async sendTemplateMessage(templateDto: any): Promise<
|
|
1105
|
+
async sendTemplateMessage(templateDto: any): Promise<IntegrationResult> {
|
|
1102
1106
|
// Get template content (integrate with your template system)
|
|
1103
1107
|
const template = await this.getTemplate(templateDto.templateId);
|
|
1104
1108
|
|
|
@@ -1113,6 +1117,7 @@ export class CommunicationService {
|
|
|
1113
1117
|
const messageDto: GenericMessageDto = {
|
|
1114
1118
|
levelId: templateDto.levelId,
|
|
1115
1119
|
levelType: templateDto.levelType,
|
|
1120
|
+
app_code: templateDto.app_code,
|
|
1116
1121
|
to: templateDto.to,
|
|
1117
1122
|
message: processedMessage,
|
|
1118
1123
|
subject: processedSubject,
|
|
@@ -1127,33 +1132,33 @@ export class CommunicationService {
|
|
|
1127
1132
|
private detectCommunicationType(
|
|
1128
1133
|
to: string | string[],
|
|
1129
1134
|
type?: string,
|
|
1130
|
-
):
|
|
1135
|
+
): 'EMAIL' | 'SMS' | 'WA' | 'TELEPHONE' {
|
|
1131
1136
|
if (type) {
|
|
1132
|
-
return type as
|
|
1137
|
+
return type as 'EMAIL' | 'SMS' | 'WA' | 'TELEPHONE';
|
|
1133
1138
|
}
|
|
1134
1139
|
|
|
1135
1140
|
const recipient = Array.isArray(to) ? to[0] : to;
|
|
1136
1141
|
|
|
1137
1142
|
// Email detection
|
|
1138
1143
|
if (recipient.includes('@')) {
|
|
1139
|
-
return
|
|
1144
|
+
return 'EMAIL';
|
|
1140
1145
|
}
|
|
1141
1146
|
|
|
1142
1147
|
// Phone number detection (basic)
|
|
1143
1148
|
if (/^\+?[\d\s\-\(\)]+$/.test(recipient)) {
|
|
1144
1149
|
// Could be SMS or WhatsApp, default to SMS
|
|
1145
|
-
return
|
|
1150
|
+
return 'SMS';
|
|
1146
1151
|
}
|
|
1147
1152
|
|
|
1148
1153
|
// Default to EMAIL if unsure
|
|
1149
|
-
return
|
|
1154
|
+
return 'EMAIL';
|
|
1150
1155
|
}
|
|
1151
1156
|
|
|
1152
|
-
private
|
|
1153
|
-
|
|
1157
|
+
private sortConfigsByPriorityAndDefault(
|
|
1158
|
+
configs: IntegrationConfigWithConfig[],
|
|
1154
1159
|
_priority: string,
|
|
1155
|
-
):
|
|
1156
|
-
return
|
|
1160
|
+
): IntegrationConfigWithConfig[] {
|
|
1161
|
+
return configs.sort((a, b) => {
|
|
1157
1162
|
// First sort by default (true comes first)
|
|
1158
1163
|
if (a.is_default !== b.is_default) {
|
|
1159
1164
|
return b.is_default ? 1 : -1;
|
|
@@ -1202,6 +1207,7 @@ export class CommunicationService {
|
|
|
1202
1207
|
async initGmailOAuth(
|
|
1203
1208
|
levelId: number,
|
|
1204
1209
|
levelType: string,
|
|
1210
|
+
app_code: string,
|
|
1205
1211
|
email?: string,
|
|
1206
1212
|
): Promise<{ authUrl: string; state: string }> {
|
|
1207
1213
|
try {
|
|
@@ -1222,6 +1228,7 @@ export class CommunicationService {
|
|
|
1222
1228
|
this.gmailOAuthStates.set(state, {
|
|
1223
1229
|
levelId,
|
|
1224
1230
|
levelType,
|
|
1231
|
+
app_code,
|
|
1225
1232
|
email,
|
|
1226
1233
|
timestamp: Date.now(),
|
|
1227
1234
|
});
|
|
@@ -1327,34 +1334,33 @@ export class CommunicationService {
|
|
|
1327
1334
|
await this.validateUniqueActiveConfig(
|
|
1328
1335
|
oauthState.levelId,
|
|
1329
1336
|
oauthState.levelType,
|
|
1330
|
-
|
|
1337
|
+
oauthState.app_code,
|
|
1338
|
+
'EMAIL',
|
|
1339
|
+
'gmail',
|
|
1331
1340
|
);
|
|
1332
1341
|
|
|
1333
|
-
// Create
|
|
1334
|
-
const
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
// Create communication hub
|
|
1340
|
-
const hub = this.hubRepository.create({
|
|
1342
|
+
// Create integration config
|
|
1343
|
+
const config = this.configRepository.create({
|
|
1344
|
+
app_code: oauthState.app_code,
|
|
1345
|
+
integration_type: 'EMAIL',
|
|
1346
|
+
integration_provider: 'gmail',
|
|
1347
|
+
integration_source_id: 1, // Gmail source ID
|
|
1341
1348
|
level_id: oauthState.levelId,
|
|
1342
1349
|
level_type: oauthState.levelType,
|
|
1343
|
-
config_id: savedConfig.id,
|
|
1344
|
-
communication_config_type: CommunicationConfigType.EMAIL,
|
|
1345
|
-
service: 'API',
|
|
1346
|
-
provider: 'gmail',
|
|
1347
1350
|
status: 1,
|
|
1351
|
+
priority: 1,
|
|
1352
|
+
is_default: false,
|
|
1353
|
+
config_json: gmailConfig as any,
|
|
1348
1354
|
});
|
|
1349
1355
|
|
|
1350
|
-
const
|
|
1356
|
+
const savedConfig = await this.configRepository.save(config);
|
|
1351
1357
|
|
|
1352
1358
|
this.logger.log(
|
|
1353
1359
|
`Gmail OAuth configuration created successfully for ${oauthState.levelType} ${oauthState.levelId} and email ${email}`,
|
|
1354
1360
|
);
|
|
1355
1361
|
|
|
1356
1362
|
return {
|
|
1357
|
-
hubId:
|
|
1363
|
+
hubId: savedConfig.id,
|
|
1358
1364
|
configId: savedConfig.id,
|
|
1359
1365
|
};
|
|
1360
1366
|
} catch (error) {
|
|
@@ -1390,7 +1396,9 @@ export class CommunicationService {
|
|
|
1390
1396
|
await this.validateUniqueActiveConfig(
|
|
1391
1397
|
oauthState.levelId,
|
|
1392
1398
|
oauthState.levelType,
|
|
1393
|
-
|
|
1399
|
+
oauthState.app_code,
|
|
1400
|
+
'EMAIL',
|
|
1401
|
+
'gmail',
|
|
1394
1402
|
);
|
|
1395
1403
|
|
|
1396
1404
|
// Pure SSO configuration - no client credentials stored per user
|
|
@@ -1405,31 +1413,28 @@ export class CommunicationService {
|
|
|
1405
1413
|
],
|
|
1406
1414
|
};
|
|
1407
1415
|
|
|
1408
|
-
// Create
|
|
1409
|
-
const
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
// Create communication hub
|
|
1415
|
-
const hub = this.hubRepository.create({
|
|
1416
|
+
// Create integration config
|
|
1417
|
+
const config = this.configRepository.create({
|
|
1418
|
+
app_code: oauthState.app_code,
|
|
1419
|
+
integration_type: 'EMAIL',
|
|
1420
|
+
integration_provider: 'gmail',
|
|
1421
|
+
integration_source_id: 1, // Gmail source ID
|
|
1416
1422
|
level_id: oauthState.levelId,
|
|
1417
1423
|
level_type: oauthState.levelType,
|
|
1418
|
-
config_id: savedConfig.id,
|
|
1419
|
-
communication_config_type: CommunicationConfigType.EMAIL,
|
|
1420
|
-
service: 'API',
|
|
1421
|
-
provider: 'gmail',
|
|
1422
1424
|
status: 1,
|
|
1425
|
+
priority: 1,
|
|
1426
|
+
is_default: false,
|
|
1427
|
+
config_json: gmailConfig as any,
|
|
1423
1428
|
});
|
|
1424
1429
|
|
|
1425
|
-
const
|
|
1430
|
+
const savedConfig = await this.configRepository.save(config);
|
|
1426
1431
|
|
|
1427
1432
|
this.logger.log(
|
|
1428
1433
|
`Gmail tokens configuration created successfully for ${oauthState.levelType} ${oauthState.levelId} and email ${email}`,
|
|
1429
1434
|
);
|
|
1430
1435
|
|
|
1431
1436
|
return {
|
|
1432
|
-
hubId:
|
|
1437
|
+
hubId: savedConfig.id,
|
|
1433
1438
|
configId: savedConfig.id,
|
|
1434
1439
|
};
|
|
1435
1440
|
} catch (error) {
|
|
@@ -1444,24 +1449,16 @@ export class CommunicationService {
|
|
|
1444
1449
|
hubId: number,
|
|
1445
1450
|
): Promise<{ success: boolean; error?: string }> {
|
|
1446
1451
|
try {
|
|
1447
|
-
const
|
|
1452
|
+
const integrationConfig = await this.configRepository.findOne({
|
|
1448
1453
|
where: { id: hubId },
|
|
1449
1454
|
});
|
|
1450
1455
|
|
|
1451
|
-
if (!
|
|
1452
|
-
throw new Error('
|
|
1453
|
-
}
|
|
1454
|
-
|
|
1455
|
-
const config = await this.configRepository.findOne({
|
|
1456
|
-
where: { id: hub.config_id },
|
|
1457
|
-
});
|
|
1458
|
-
|
|
1459
|
-
if (!config) {
|
|
1460
|
-
throw new Error('Configuration not found');
|
|
1456
|
+
if (!integrationConfig) {
|
|
1457
|
+
throw new Error('Integration config not found');
|
|
1461
1458
|
}
|
|
1462
1459
|
|
|
1463
1460
|
const isValid = await this.gmailApiStrategy.validateConnection(
|
|
1464
|
-
|
|
1461
|
+
integrationConfig.config_json,
|
|
1465
1462
|
);
|
|
1466
1463
|
|
|
1467
1464
|
if (!isValid) {
|
|
@@ -1485,15 +1482,19 @@ export class CommunicationService {
|
|
|
1485
1482
|
private async validateUniqueActiveConfig(
|
|
1486
1483
|
levelId: number,
|
|
1487
1484
|
levelType: string,
|
|
1488
|
-
|
|
1485
|
+
app_code: string,
|
|
1486
|
+
configType: 'EMAIL' | 'SMS' | 'WA' | 'TELEPHONE',
|
|
1487
|
+
provider: string,
|
|
1489
1488
|
excludeHubId?: number,
|
|
1490
1489
|
): Promise<void> {
|
|
1491
|
-
// Find all active configurations of the same
|
|
1492
|
-
const query = this.
|
|
1490
|
+
// Find all active configurations of the same provider for this level and app_code
|
|
1491
|
+
const query = this.configRepository
|
|
1493
1492
|
.createQueryBuilder('hub')
|
|
1494
1493
|
.where('hub.level_id = :levelId', { levelId })
|
|
1495
1494
|
.andWhere('hub.level_type = :levelType', { levelType })
|
|
1496
|
-
.andWhere('hub.
|
|
1495
|
+
.andWhere('hub.app_code = :app_code', { app_code })
|
|
1496
|
+
.andWhere('hub.integration_type = :configType', { configType })
|
|
1497
|
+
.andWhere('hub.integration_provider = :provider', { provider })
|
|
1497
1498
|
.andWhere('hub.status = :status', { status: 1 });
|
|
1498
1499
|
|
|
1499
1500
|
// Exclude current hub if updating
|
|
@@ -1503,40 +1504,28 @@ export class CommunicationService {
|
|
|
1503
1504
|
|
|
1504
1505
|
const existingActiveConfigs = await query.getMany();
|
|
1505
1506
|
|
|
1506
|
-
// If there are existing active configurations,
|
|
1507
|
+
// If there are existing active configurations of the same provider, throw error
|
|
1507
1508
|
if (existingActiveConfigs.length > 0) {
|
|
1508
|
-
|
|
1509
|
-
{
|
|
1510
|
-
level_id: levelId,
|
|
1511
|
-
level_type: levelType,
|
|
1512
|
-
communication_config_type: configType,
|
|
1513
|
-
status: 1,
|
|
1514
|
-
...(excludeHubId && { id: Not(excludeHubId) }),
|
|
1515
|
-
},
|
|
1516
|
-
{ status: 0 }, // Deactivate
|
|
1517
|
-
);
|
|
1518
|
-
|
|
1519
|
-
this.logger.log(
|
|
1520
|
-
`Deactivated ${existingActiveConfigs.length} existing ${configType} configuration(s) for ${levelType} ${levelId} to maintain single active provider rule.`,
|
|
1509
|
+
throw new Error(
|
|
1510
|
+
`A ${provider} configuration already exists for ${configType} in app_code ${app_code}, ${levelType} ${levelId}. Only one configuration per provider is allowed.`,
|
|
1521
1511
|
);
|
|
1522
1512
|
}
|
|
1523
1513
|
}
|
|
1524
1514
|
|
|
1525
1515
|
private requiresOAuthFlow(
|
|
1526
|
-
configType:
|
|
1527
|
-
service: string,
|
|
1516
|
+
configType: 'EMAIL' | 'SMS' | 'WA' | 'TELEPHONE',
|
|
1528
1517
|
provider: string,
|
|
1529
1518
|
config: any,
|
|
1530
1519
|
): boolean {
|
|
1531
1520
|
// Check if config indicates OAuth is needed (missing tokens or explicit OAuth request)
|
|
1532
|
-
const key = `${configType.toLowerCase()}_${
|
|
1521
|
+
const key = `${configType.toLowerCase()}_${provider.toLowerCase()}`;
|
|
1533
1522
|
|
|
1534
1523
|
switch (key) {
|
|
1535
|
-
case '
|
|
1524
|
+
case 'email_gmail':
|
|
1536
1525
|
// Requires OAuth if no access token provided or OAuth explicitly requested
|
|
1537
1526
|
return !config.accessToken || config.useOAuth === true;
|
|
1538
1527
|
|
|
1539
|
-
case '
|
|
1528
|
+
case 'email_outlook':
|
|
1540
1529
|
// Requires OAuth if no access token provided or OAuth explicitly requested
|
|
1541
1530
|
return !config.accessToken || config.useOAuth === true;
|
|
1542
1531
|
|
|
@@ -1549,20 +1538,22 @@ export class CommunicationService {
|
|
|
1549
1538
|
private async generateOAuthUrl(
|
|
1550
1539
|
levelId: number,
|
|
1551
1540
|
levelType: string,
|
|
1552
|
-
|
|
1553
|
-
|
|
1541
|
+
app_code: string,
|
|
1542
|
+
configType: 'EMAIL' | 'SMS' | 'WA' | 'TELEPHONE',
|
|
1554
1543
|
provider: string,
|
|
1544
|
+
integration_source_id: number,
|
|
1555
1545
|
config: any,
|
|
1556
1546
|
priority?: number,
|
|
1557
1547
|
is_default?: boolean,
|
|
1558
1548
|
): Promise<{ authUrl: string; state: string; message: string }> {
|
|
1559
|
-
const key = `${configType.toLowerCase()}_${
|
|
1549
|
+
const key = `${configType.toLowerCase()}_${provider.toLowerCase()}`;
|
|
1560
1550
|
|
|
1561
1551
|
switch (key) {
|
|
1562
|
-
case '
|
|
1552
|
+
case 'email_gmail':
|
|
1563
1553
|
const gmailResult = await this.initGmailOAuth(
|
|
1564
1554
|
levelId,
|
|
1565
1555
|
levelType,
|
|
1556
|
+
app_code,
|
|
1566
1557
|
config.email,
|
|
1567
1558
|
);
|
|
1568
1559
|
return {
|
|
@@ -1572,10 +1563,11 @@ export class CommunicationService {
|
|
|
1572
1563
|
'Please complete Gmail OAuth authorization. Configuration will be created automatically after authorization.',
|
|
1573
1564
|
};
|
|
1574
1565
|
|
|
1575
|
-
case '
|
|
1566
|
+
case 'email_outlook':
|
|
1576
1567
|
const outlookResult = await this.initOutlookOAuth(
|
|
1577
1568
|
levelId,
|
|
1578
1569
|
levelType,
|
|
1570
|
+
app_code,
|
|
1579
1571
|
config.email,
|
|
1580
1572
|
);
|
|
1581
1573
|
return {
|
|
@@ -1586,67 +1578,81 @@ export class CommunicationService {
|
|
|
1586
1578
|
};
|
|
1587
1579
|
|
|
1588
1580
|
default:
|
|
1589
|
-
throw new Error(
|
|
1590
|
-
`OAuth not supported for ${configType}/${service}/${provider}`,
|
|
1591
|
-
);
|
|
1581
|
+
throw new Error(`OAuth not supported for ${configType}/${provider}`);
|
|
1592
1582
|
}
|
|
1593
1583
|
}
|
|
1594
1584
|
|
|
1595
1585
|
private async createDirectConfig(
|
|
1596
1586
|
levelId: number,
|
|
1597
1587
|
levelType: string,
|
|
1598
|
-
|
|
1599
|
-
|
|
1588
|
+
app_code: string,
|
|
1589
|
+
configType: 'EMAIL' | 'SMS' | 'WA' | 'TELEPHONE',
|
|
1600
1590
|
provider: string,
|
|
1591
|
+
integration_source_id: number,
|
|
1601
1592
|
config: any,
|
|
1602
1593
|
priority?: number,
|
|
1603
1594
|
is_default?: boolean,
|
|
1604
|
-
): Promise<
|
|
1605
|
-
//
|
|
1606
|
-
await this.validateUniqueActiveConfig(
|
|
1595
|
+
): Promise<IntegrationConfig> {
|
|
1596
|
+
// Validate that no duplicate provider configurations exist
|
|
1597
|
+
await this.validateUniqueActiveConfig(
|
|
1598
|
+
levelId,
|
|
1599
|
+
levelType,
|
|
1600
|
+
app_code,
|
|
1601
|
+
configType,
|
|
1602
|
+
provider,
|
|
1603
|
+
);
|
|
1604
|
+
|
|
1605
|
+
// Deactivate all other configurations of the same integration type
|
|
1606
|
+
await this.configRepository.update(
|
|
1607
|
+
{
|
|
1608
|
+
level_id: levelId,
|
|
1609
|
+
level_type: levelType,
|
|
1610
|
+
app_code: app_code,
|
|
1611
|
+
integration_type: configType,
|
|
1612
|
+
status: 1,
|
|
1613
|
+
},
|
|
1614
|
+
{ status: 0 },
|
|
1615
|
+
);
|
|
1607
1616
|
|
|
1608
|
-
// If setting as default, remove default from other configurations of same type
|
|
1617
|
+
// If setting as default, remove default from other configurations of same type and app_code
|
|
1609
1618
|
if (is_default) {
|
|
1610
|
-
await this.
|
|
1619
|
+
await this.configRepository.update(
|
|
1611
1620
|
{
|
|
1612
1621
|
level_id: levelId,
|
|
1613
1622
|
level_type: levelType,
|
|
1614
|
-
|
|
1623
|
+
app_code: app_code,
|
|
1624
|
+
integration_type: configType,
|
|
1615
1625
|
},
|
|
1616
1626
|
{ is_default: false },
|
|
1617
1627
|
);
|
|
1618
1628
|
}
|
|
1619
1629
|
|
|
1620
|
-
//
|
|
1621
|
-
const
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
// Then create the hub
|
|
1627
|
-
const hub = this.hubRepository.create({
|
|
1630
|
+
// Create integration config
|
|
1631
|
+
const integrationConfig = this.configRepository.create({
|
|
1632
|
+
app_code: app_code,
|
|
1633
|
+
integration_type: configType,
|
|
1634
|
+
integration_provider: provider,
|
|
1635
|
+
integration_source_id: integration_source_id,
|
|
1628
1636
|
level_id: levelId,
|
|
1629
1637
|
level_type: levelType,
|
|
1630
|
-
|
|
1631
|
-
communication_config_type: configType,
|
|
1632
|
-
service: service as any,
|
|
1633
|
-
provider: provider as any,
|
|
1638
|
+
status: 1,
|
|
1634
1639
|
priority: priority || 1,
|
|
1635
1640
|
is_default: is_default || false,
|
|
1636
|
-
|
|
1641
|
+
config_json: config,
|
|
1637
1642
|
});
|
|
1638
1643
|
|
|
1639
|
-
const
|
|
1644
|
+
const savedConfig = await this.configRepository.save(integrationConfig);
|
|
1640
1645
|
this.logger.log(
|
|
1641
|
-
`Communication config created: ${configType}/${
|
|
1646
|
+
`Communication config created: ${configType}/${provider} for ${levelType} ${levelId}`,
|
|
1642
1647
|
);
|
|
1643
1648
|
|
|
1644
|
-
return Array.isArray(
|
|
1649
|
+
return Array.isArray(savedConfig) ? savedConfig[0] : savedConfig;
|
|
1645
1650
|
}
|
|
1646
1651
|
|
|
1647
1652
|
async initOutlookOAuth(
|
|
1648
1653
|
levelId: number,
|
|
1649
1654
|
levelType: string,
|
|
1655
|
+
app_code: string,
|
|
1650
1656
|
email?: string,
|
|
1651
1657
|
): Promise<{ authUrl: string; state: string }> {
|
|
1652
1658
|
try {
|
|
@@ -1666,6 +1672,7 @@ export class CommunicationService {
|
|
|
1666
1672
|
this.gmailOAuthStates.set(state, {
|
|
1667
1673
|
levelId,
|
|
1668
1674
|
levelType,
|
|
1675
|
+
app_code,
|
|
1669
1676
|
email,
|
|
1670
1677
|
timestamp: Date.now(),
|
|
1671
1678
|
});
|
|
@@ -1768,7 +1775,9 @@ export class CommunicationService {
|
|
|
1768
1775
|
await this.validateUniqueActiveConfig(
|
|
1769
1776
|
oauthState.levelId,
|
|
1770
1777
|
oauthState.levelType,
|
|
1771
|
-
|
|
1778
|
+
oauthState.app_code,
|
|
1779
|
+
'EMAIL',
|
|
1780
|
+
'outlook',
|
|
1772
1781
|
);
|
|
1773
1782
|
|
|
1774
1783
|
const outlookConfig = {
|
|
@@ -1782,31 +1791,28 @@ export class CommunicationService {
|
|
|
1782
1791
|
expiresIn: tokens.expires_in,
|
|
1783
1792
|
};
|
|
1784
1793
|
|
|
1785
|
-
// Create
|
|
1786
|
-
const
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
// Create communication hub
|
|
1792
|
-
const hub = this.hubRepository.create({
|
|
1794
|
+
// Create integration config
|
|
1795
|
+
const config = this.configRepository.create({
|
|
1796
|
+
app_code: oauthState.app_code,
|
|
1797
|
+
integration_type: 'EMAIL',
|
|
1798
|
+
integration_provider: 'outlook',
|
|
1799
|
+
integration_source_id: 1, // Outlook source ID
|
|
1793
1800
|
level_id: oauthState.levelId,
|
|
1794
1801
|
level_type: oauthState.levelType,
|
|
1795
|
-
config_id: savedConfig.id,
|
|
1796
|
-
communication_config_type: CommunicationConfigType.EMAIL,
|
|
1797
|
-
service: 'API',
|
|
1798
|
-
provider: 'outlook',
|
|
1799
1802
|
status: 1,
|
|
1803
|
+
priority: 1,
|
|
1804
|
+
is_default: false,
|
|
1805
|
+
config_json: outlookConfig as any,
|
|
1800
1806
|
});
|
|
1801
1807
|
|
|
1802
|
-
const
|
|
1808
|
+
const savedConfig = await this.configRepository.save(config);
|
|
1803
1809
|
|
|
1804
1810
|
this.logger.log(
|
|
1805
1811
|
`Outlook OAuth configuration created successfully for ${oauthState.levelType} ${oauthState.levelId} and email ${email}`,
|
|
1806
1812
|
);
|
|
1807
1813
|
|
|
1808
1814
|
return {
|
|
1809
|
-
hubId:
|
|
1815
|
+
hubId: savedConfig.id,
|
|
1810
1816
|
configId: savedConfig.id,
|
|
1811
1817
|
};
|
|
1812
1818
|
} catch (error) {
|
|
@@ -1818,59 +1824,40 @@ export class CommunicationService {
|
|
|
1818
1824
|
}
|
|
1819
1825
|
}
|
|
1820
1826
|
|
|
1821
|
-
async
|
|
1822
|
-
| (
|
|
1823
|
-
config:
|
|
1827
|
+
async getIntegrationConfigById(hubId: number): Promise<
|
|
1828
|
+
| (IntegrationConfig & {
|
|
1829
|
+
config: IntegrationConfig;
|
|
1824
1830
|
linkedSource?: string;
|
|
1825
1831
|
configDetails?: any;
|
|
1826
1832
|
})
|
|
1827
1833
|
| null
|
|
1828
1834
|
> {
|
|
1829
1835
|
try {
|
|
1830
|
-
// Find the
|
|
1831
|
-
const
|
|
1836
|
+
// Find the integration config by ID
|
|
1837
|
+
const integrationConfig = await this.configRepository.findOne({
|
|
1832
1838
|
where: { id: hubId },
|
|
1833
1839
|
});
|
|
1834
1840
|
|
|
1835
|
-
if (!
|
|
1841
|
+
if (!integrationConfig) {
|
|
1836
1842
|
return null;
|
|
1837
1843
|
}
|
|
1838
1844
|
|
|
1839
|
-
// Find the associated config
|
|
1840
|
-
const config = await this.configRepository.findOne({
|
|
1841
|
-
where: { id: hub.config_id },
|
|
1842
|
-
});
|
|
1843
|
-
|
|
1844
|
-
if (!config) {
|
|
1845
|
-
this.logger.warn(
|
|
1846
|
-
`Configuration not found for hub ${hubId} with config_id ${hub.config_id}`,
|
|
1847
|
-
);
|
|
1848
|
-
return {
|
|
1849
|
-
...hub,
|
|
1850
|
-
config: null as any,
|
|
1851
|
-
linkedSource: 'Configuration not found',
|
|
1852
|
-
configDetails: null,
|
|
1853
|
-
};
|
|
1854
|
-
}
|
|
1855
|
-
|
|
1856
1845
|
// Extract linked source and config details
|
|
1857
1846
|
const linkedSource = this.extractLinkedSource(
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
config.config_json,
|
|
1847
|
+
integrationConfig.integration_type,
|
|
1848
|
+
integrationConfig.integration_provider,
|
|
1849
|
+
integrationConfig.config_json,
|
|
1862
1850
|
);
|
|
1863
1851
|
|
|
1864
1852
|
const configDetails = this.extractConfigDetails(
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
config.config_json,
|
|
1853
|
+
integrationConfig.integration_type,
|
|
1854
|
+
integrationConfig.integration_provider,
|
|
1855
|
+
integrationConfig.config_json,
|
|
1869
1856
|
);
|
|
1870
1857
|
|
|
1871
1858
|
return {
|
|
1872
|
-
...
|
|
1873
|
-
config,
|
|
1859
|
+
...integrationConfig,
|
|
1860
|
+
config: integrationConfig,
|
|
1874
1861
|
linkedSource,
|
|
1875
1862
|
configDetails,
|
|
1876
1863
|
};
|
|
@@ -1888,6 +1875,7 @@ export class CommunicationService {
|
|
|
1888
1875
|
async getSendGridTemplates(
|
|
1889
1876
|
levelId: number,
|
|
1890
1877
|
levelType: string,
|
|
1878
|
+
app_code: string,
|
|
1891
1879
|
): Promise<{
|
|
1892
1880
|
success: boolean;
|
|
1893
1881
|
data?: Array<{
|
|
@@ -1898,14 +1886,17 @@ export class CommunicationService {
|
|
|
1898
1886
|
}> {
|
|
1899
1887
|
try {
|
|
1900
1888
|
// Find active SendGrid configurations for this level
|
|
1901
|
-
const hubs = await this.
|
|
1889
|
+
const hubs = await this.getActiveConfigs(
|
|
1902
1890
|
levelId,
|
|
1903
1891
|
levelType,
|
|
1904
|
-
|
|
1892
|
+
app_code,
|
|
1893
|
+
'EMAIL',
|
|
1905
1894
|
);
|
|
1906
1895
|
|
|
1907
1896
|
// Look for SendGrid provider
|
|
1908
|
-
const sendGridHub = hubs.find(
|
|
1897
|
+
const sendGridHub = hubs.find(
|
|
1898
|
+
(hub) => hub.integration_provider === 'sendgrid',
|
|
1899
|
+
);
|
|
1909
1900
|
|
|
1910
1901
|
if (!sendGridHub) {
|
|
1911
1902
|
return {
|
|
@@ -1915,7 +1906,7 @@ export class CommunicationService {
|
|
|
1915
1906
|
}
|
|
1916
1907
|
|
|
1917
1908
|
// Extract API key from configuration
|
|
1918
|
-
const apiKey = sendGridHub.
|
|
1909
|
+
const apiKey = sendGridHub.config_json?.apiKey;
|
|
1919
1910
|
|
|
1920
1911
|
if (!apiKey) {
|
|
1921
1912
|
return {
|
|
@@ -1967,4 +1958,163 @@ export class CommunicationService {
|
|
|
1967
1958
|
};
|
|
1968
1959
|
}
|
|
1969
1960
|
}
|
|
1961
|
+
|
|
1962
|
+
// UserIntegration Management Methods
|
|
1963
|
+
|
|
1964
|
+
async createUserIntegration(
|
|
1965
|
+
createDto: CreateUserIntegrationDto,
|
|
1966
|
+
): Promise<UserIntegration> {
|
|
1967
|
+
try {
|
|
1968
|
+
// Check if mapping already exists
|
|
1969
|
+
const existing = await this.userIntegrationRepository.findOne({
|
|
1970
|
+
where: {
|
|
1971
|
+
user_id: createDto.user_id,
|
|
1972
|
+
integration_config_id: createDto.integration_config_id,
|
|
1973
|
+
},
|
|
1974
|
+
});
|
|
1975
|
+
|
|
1976
|
+
if (existing) {
|
|
1977
|
+
throw new Error('User integration mapping already exists');
|
|
1978
|
+
}
|
|
1979
|
+
|
|
1980
|
+
// Verify integration config exists
|
|
1981
|
+
const config = await this.configRepository.findOne({
|
|
1982
|
+
where: { id: createDto.integration_config_id },
|
|
1983
|
+
});
|
|
1984
|
+
|
|
1985
|
+
if (!config) {
|
|
1986
|
+
throw new Error('Integration configuration not found');
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1989
|
+
const userIntegration = this.userIntegrationRepository.create(createDto);
|
|
1990
|
+
return await this.userIntegrationRepository.save(userIntegration);
|
|
1991
|
+
} catch (error) {
|
|
1992
|
+
this.logger.error(
|
|
1993
|
+
`Error creating user integration mapping: ${error.message}`,
|
|
1994
|
+
);
|
|
1995
|
+
throw error;
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
async getUserIntegrations(userId: number): Promise<UserIntegration[]> {
|
|
2000
|
+
try {
|
|
2001
|
+
return await this.userIntegrationRepository.find({
|
|
2002
|
+
where: { user_id: userId, is_active: true },
|
|
2003
|
+
order: { created_at: 'DESC' },
|
|
2004
|
+
});
|
|
2005
|
+
} catch (error) {
|
|
2006
|
+
this.logger.error(
|
|
2007
|
+
`Error fetching user integrations for user ${userId}: ${error.message}`,
|
|
2008
|
+
);
|
|
2009
|
+
throw error;
|
|
2010
|
+
}
|
|
2011
|
+
}
|
|
2012
|
+
|
|
2013
|
+
async getConfigUserIntegrations(
|
|
2014
|
+
configId: number,
|
|
2015
|
+
): Promise<UserIntegration[]> {
|
|
2016
|
+
try {
|
|
2017
|
+
return await this.userIntegrationRepository.find({
|
|
2018
|
+
where: { integration_config_id: configId, is_active: true },
|
|
2019
|
+
order: { created_at: 'DESC' },
|
|
2020
|
+
});
|
|
2021
|
+
} catch (error) {
|
|
2022
|
+
this.logger.error(
|
|
2023
|
+
`Error fetching user integrations for config ${configId}: ${error.message}`,
|
|
2024
|
+
);
|
|
2025
|
+
throw error;
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
|
|
2029
|
+
async getUserIntegrationByUserAndConfig(
|
|
2030
|
+
userId: number,
|
|
2031
|
+
configId: number,
|
|
2032
|
+
): Promise<UserIntegration | null> {
|
|
2033
|
+
try {
|
|
2034
|
+
return await this.userIntegrationRepository.findOne({
|
|
2035
|
+
where: {
|
|
2036
|
+
user_id: userId,
|
|
2037
|
+
integration_config_id: configId,
|
|
2038
|
+
is_active: true,
|
|
2039
|
+
},
|
|
2040
|
+
});
|
|
2041
|
+
} catch (error) {
|
|
2042
|
+
this.logger.error(
|
|
2043
|
+
`Error fetching user integration for user ${userId} and config ${configId}: ${error.message}`,
|
|
2044
|
+
);
|
|
2045
|
+
throw error;
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
|
|
2049
|
+
async updateUserIntegration(
|
|
2050
|
+
id: number,
|
|
2051
|
+
updateDto: UpdateUserIntegrationDto,
|
|
2052
|
+
): Promise<UserIntegration> {
|
|
2053
|
+
try {
|
|
2054
|
+
const userIntegration = await this.userIntegrationRepository.findOne({
|
|
2055
|
+
where: { id },
|
|
2056
|
+
});
|
|
2057
|
+
|
|
2058
|
+
if (!userIntegration) {
|
|
2059
|
+
throw new Error('User integration mapping not found');
|
|
2060
|
+
}
|
|
2061
|
+
|
|
2062
|
+
Object.assign(userIntegration, updateDto);
|
|
2063
|
+
return await this.userIntegrationRepository.save(userIntegration);
|
|
2064
|
+
} catch (error) {
|
|
2065
|
+
this.logger.error(
|
|
2066
|
+
`Error updating user integration ${id}: ${error.message}`,
|
|
2067
|
+
);
|
|
2068
|
+
throw error;
|
|
2069
|
+
}
|
|
2070
|
+
}
|
|
2071
|
+
|
|
2072
|
+
async deleteUserIntegration(id: number): Promise<void> {
|
|
2073
|
+
try {
|
|
2074
|
+
const userIntegration = await this.userIntegrationRepository.findOne({
|
|
2075
|
+
where: { id },
|
|
2076
|
+
});
|
|
2077
|
+
|
|
2078
|
+
if (!userIntegration) {
|
|
2079
|
+
throw new Error('User integration mapping not found');
|
|
2080
|
+
}
|
|
2081
|
+
|
|
2082
|
+
await this.userIntegrationRepository.remove(userIntegration);
|
|
2083
|
+
} catch (error) {
|
|
2084
|
+
this.logger.error(
|
|
2085
|
+
`Error deleting user integration ${id}: ${error.message}`,
|
|
2086
|
+
);
|
|
2087
|
+
throw error;
|
|
2088
|
+
}
|
|
2089
|
+
}
|
|
2090
|
+
|
|
2091
|
+
/**
|
|
2092
|
+
* Get user integration data for a specific integration strategy
|
|
2093
|
+
* This method is intended to be used by strategies that need user mapping
|
|
2094
|
+
*/
|
|
2095
|
+
async getUserIntegrationForStrategy(
|
|
2096
|
+
userId: number,
|
|
2097
|
+
integrationConfigId: number,
|
|
2098
|
+
): Promise<any | null> {
|
|
2099
|
+
try {
|
|
2100
|
+
const userIntegration = await this.getUserIntegrationByUserAndConfig(
|
|
2101
|
+
userId,
|
|
2102
|
+
integrationConfigId,
|
|
2103
|
+
);
|
|
2104
|
+
|
|
2105
|
+
if (!userIntegration) {
|
|
2106
|
+
return null;
|
|
2107
|
+
}
|
|
2108
|
+
|
|
2109
|
+
return {
|
|
2110
|
+
external_user_id: userIntegration.external_user_id,
|
|
2111
|
+
external_user_data: userIntegration.external_user_data,
|
|
2112
|
+
};
|
|
2113
|
+
} catch (error) {
|
|
2114
|
+
this.logger.error(
|
|
2115
|
+
`Error fetching user integration data for strategy: ${error.message}`,
|
|
2116
|
+
);
|
|
2117
|
+
return null;
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
1970
2120
|
}
|