rez_core 2.2.224 → 2.2.225
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 -0
- package/dist/app.module.js.map +1 -1
- package/dist/module/auth/auth.module.js +5 -1
- package/dist/module/auth/auth.module.js.map +1 -1
- package/dist/module/auth/controller/auth.controller.d.ts +8 -0
- package/dist/module/auth/controller/auth.controller.js +51 -0
- package/dist/module/auth/controller/auth.controller.js.map +1 -0
- package/dist/module/auth/services/auth.service.d.ts +6 -4
- package/dist/module/auth/services/auth.service.js +12 -16
- package/dist/module/auth/services/auth.service.js.map +1 -1
- package/dist/module/communication/communication.module.js +6 -1
- package/dist/module/communication/communication.module.js.map +1 -1
- package/dist/module/rule_engine/entity/rule-engine.entity.d.ts +11 -0
- package/dist/module/rule_engine/entity/rule-engine.entity.js +55 -0
- package/dist/module/rule_engine/entity/rule-engine.entity.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/docs/modules/communication.md +177 -0
- package/package.json +1 -1
- package/src/app.module.ts +2 -0
- package/src/module/auth/auth.module.ts +6 -2
- package/src/module/auth/controller/auth.controller.ts +28 -0
- package/src/module/auth/services/auth.service.ts +34 -13
- package/src/module/communication/communication.module.ts +6 -1
- package/src/module/rule_engine/entity/rule-engine.entity.ts +32 -0
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# Communication Module Documentation
|
|
2
|
+
|
|
3
|
+
## Database Schema
|
|
4
|
+
|
|
5
|
+
### Tables: cr_communication_config & cr_communication_hub
|
|
6
|
+
```sql
|
|
7
|
+
-- Configuration storage
|
|
8
|
+
CREATE TABLE cr_communication_config (
|
|
9
|
+
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
10
|
+
config_json JSON NOT NULL,
|
|
11
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
12
|
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
-- Hub mapping level->provider
|
|
16
|
+
CREATE TABLE cr_communication_hub (
|
|
17
|
+
id INT AUTO_INCREMENT PRIMARY KEY,
|
|
18
|
+
level_id INT NOT NULL,
|
|
19
|
+
level_type VARCHAR(100) NOT NULL, -- 'organization', 'department', 'user', 'project'
|
|
20
|
+
status TINYINT DEFAULT 1,
|
|
21
|
+
config_id INT NOT NULL,
|
|
22
|
+
communication_config_type ENUM('WA','SMS','EMAIL','TELEPHONE') NOT NULL,
|
|
23
|
+
service VARCHAR(100) NOT NULL, -- API, THIRD_PARTY, SMTP
|
|
24
|
+
provider VARCHAR(100) NOT NULL, -- gmail, outlook, twilio, whatsapp, etc.
|
|
25
|
+
priority INT DEFAULT 1,
|
|
26
|
+
is_default BOOLEAN DEFAULT FALSE,
|
|
27
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
|
28
|
+
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
|
29
|
+
INDEX idx_level_status (level_id, level_type, status),
|
|
30
|
+
INDEX idx_config_type (communication_config_type)
|
|
31
|
+
);
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Architecture: Hierarchical Factory Pattern
|
|
35
|
+
|
|
36
|
+
### Strategy Interface
|
|
37
|
+
```ts
|
|
38
|
+
export interface CommunicationStrategy {
|
|
39
|
+
sendMessage(to: string, message: string, config: any): Promise<any>;
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Factory Structure (Mode → Service → Provider)
|
|
44
|
+
- **EMAIL**: API (gmail, outlook, aws-ses) | SMTP (gmail, outlook, sendgrid, generic)
|
|
45
|
+
- **SMS**: THIRD_PARTY (twilio, knowlarity)
|
|
46
|
+
- **WA**: API (whatsapp)
|
|
47
|
+
- **TELEPHONE**: THIRD_PARTY (knowlarity)
|
|
48
|
+
|
|
49
|
+
### Main Factory
|
|
50
|
+
```ts
|
|
51
|
+
@Injectable()
|
|
52
|
+
export class CommunicationFactory {
|
|
53
|
+
create(mode: string, service: string, provider: string): CommunicationStrategy {
|
|
54
|
+
// Returns appropriate strategy instance
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
getAllSupportedCombinations(): Array<{mode, service, provider}> {}
|
|
58
|
+
getSupportedCombinationsForMode(mode: string): Array<{service, provider}> {}
|
|
59
|
+
validateCombination(mode: string, service: string, provider: string): boolean {}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Service Layer
|
|
64
|
+
```ts
|
|
65
|
+
@Injectable()
|
|
66
|
+
export class CommunicationService {
|
|
67
|
+
// Main send with fallback
|
|
68
|
+
async send(orgId: number, to: string, message: string, type?: string, options: any = {}) {}
|
|
69
|
+
|
|
70
|
+
// Type-specific methods
|
|
71
|
+
async sendEmail(orgId: number, to: string, subject: string, body: string, attachments?: any[]) {}
|
|
72
|
+
async sendSMS(orgId: number, to: string, message: string) {}
|
|
73
|
+
async sendWhatsApp(orgId: number, to: string, message: string, mediaUrl?: string) {}
|
|
74
|
+
|
|
75
|
+
// Bulk & template support
|
|
76
|
+
async sendBulk(orgId: number, recipients: string[], message: string, type?: string) {}
|
|
77
|
+
async sendWithTemplate(orgId: number, to: string, templateId: string, variables: any) {}
|
|
78
|
+
|
|
79
|
+
// Configuration management
|
|
80
|
+
async createConfiguration(orgId: number, configData: any) {}
|
|
81
|
+
async updateConfiguration(hubId: number, configData: any) {}
|
|
82
|
+
async setDefaultProvider(hubId: number) {}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Provider Configuration Examples
|
|
87
|
+
|
|
88
|
+
### Gmail API
|
|
89
|
+
```json
|
|
90
|
+
{
|
|
91
|
+
"type": "EMAIL", "service": "API", "provider": "gmail",
|
|
92
|
+
"config": {
|
|
93
|
+
"clientId": "your-client-id.apps.googleusercontent.com",
|
|
94
|
+
"clientSecret": "your-client-secret",
|
|
95
|
+
"refreshToken": "your-refresh-token",
|
|
96
|
+
"accessToken": "your-access-token"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### Gmail SMTP
|
|
102
|
+
```json
|
|
103
|
+
{
|
|
104
|
+
"type": "EMAIL", "service": "SMTP", "provider": "gmail",
|
|
105
|
+
"config": {
|
|
106
|
+
"email": "your-email@gmail.com",
|
|
107
|
+
"password": "your-app-password",
|
|
108
|
+
"subject": "Default Subject"
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Twilio SMS
|
|
114
|
+
```json
|
|
115
|
+
{
|
|
116
|
+
"type": "SMS", "service": "THIRD_PARTY", "provider": "twilio",
|
|
117
|
+
"config": {
|
|
118
|
+
"accountSid": "your-twilio-account-sid",
|
|
119
|
+
"authToken": "your-twilio-auth-token",
|
|
120
|
+
"fromNumber": "+1234567890"
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### WhatsApp Cloud API
|
|
126
|
+
```json
|
|
127
|
+
{
|
|
128
|
+
"type": "WA", "service": "API", "provider": "whatsapp",
|
|
129
|
+
"config": {
|
|
130
|
+
"accessToken": "your-whatsapp-access-token",
|
|
131
|
+
"phoneNumberId": "your-phone-number-id",
|
|
132
|
+
"apiVersion": "v17.0"
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Knowlarity Voice
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"type": "TELEPHONE", "service": "THIRD_PARTY", "provider": "knowlarity",
|
|
141
|
+
"config": {
|
|
142
|
+
"apiKey": "your-knowlarity-api-key",
|
|
143
|
+
"apiSecret": "your-knowlarity-api-secret",
|
|
144
|
+
"callerNumber": "your-knowlarity-number",
|
|
145
|
+
"callType": "voice",
|
|
146
|
+
"language": "en"
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
## API Endpoints
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
POST /communication/send
|
|
155
|
+
POST /communication/config
|
|
156
|
+
GET /communication/level/:id/:type/configs
|
|
157
|
+
POST /communication/gmail/oauth/init
|
|
158
|
+
POST /communication/oauth/callback/gmail
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Module Structure
|
|
162
|
+
```
|
|
163
|
+
src/module/communication/
|
|
164
|
+
├── controller/communication.controller.ts
|
|
165
|
+
├── entity/communication-{config,hub,log}.entity.ts
|
|
166
|
+
├── service/communication.service.ts
|
|
167
|
+
├── factories/communication.factory.ts
|
|
168
|
+
├── strategies/gmail.strategy.ts (and others)
|
|
169
|
+
└── communication.module.ts
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Level Hierarchy (fallback order)
|
|
173
|
+
1. **user** (highest priority)
|
|
174
|
+
2. **team**
|
|
175
|
+
3. **project**
|
|
176
|
+
4. **department**
|
|
177
|
+
5. **organization** (lowest priority)
|
package/package.json
CHANGED
package/src/app.module.ts
CHANGED
|
@@ -18,6 +18,7 @@ import { IcsMeetingModule } from './module/ics/ics.module';
|
|
|
18
18
|
import { DashboardModule } from './module/dashboard/dashboard.module';
|
|
19
19
|
import { CommunicationModule } from './module/communication/communication.module';
|
|
20
20
|
import { ScheduleModule } from '@nestjs/schedule';
|
|
21
|
+
import { AuthModule } from './module/auth/auth.module';
|
|
21
22
|
|
|
22
23
|
@Module({
|
|
23
24
|
imports: [
|
|
@@ -39,6 +40,7 @@ import { ScheduleModule } from '@nestjs/schedule';
|
|
|
39
40
|
IcsMeetingModule,
|
|
40
41
|
DashboardModule,
|
|
41
42
|
CommunicationModule,
|
|
43
|
+
AuthModule,
|
|
42
44
|
ScheduleModule.forRoot(),
|
|
43
45
|
],
|
|
44
46
|
})
|
|
@@ -10,6 +10,9 @@ import { PassportModule } from '@nestjs/passport';
|
|
|
10
10
|
import { UserSession } from '../user/entity/user-session.entity';
|
|
11
11
|
import { GoogleStrategy } from './strategies/google.strategy';
|
|
12
12
|
import { RolesGuard } from './guards/role.guard';
|
|
13
|
+
import { AuthService } from './services/auth.service';
|
|
14
|
+
import { AuthController } from './controller/auth.controller';
|
|
15
|
+
import { UserModule } from '../user/user.module';
|
|
13
16
|
|
|
14
17
|
@Module({
|
|
15
18
|
imports: [
|
|
@@ -30,16 +33,17 @@ import { RolesGuard } from './guards/role.guard';
|
|
|
30
33
|
};
|
|
31
34
|
},
|
|
32
35
|
}),
|
|
33
|
-
|
|
34
36
|
TypeOrmModule.forFeature([UserSession]),
|
|
35
37
|
],
|
|
38
|
+
controllers: [AuthController],
|
|
36
39
|
providers: [
|
|
37
40
|
JwtAuthService,
|
|
38
41
|
JwtStrategy,
|
|
39
42
|
JwtAuthGuard,
|
|
40
43
|
GoogleStrategy,
|
|
41
44
|
RolesGuard,
|
|
45
|
+
AuthService,
|
|
42
46
|
],
|
|
43
|
-
exports: [JwtAuthService, JwtAuthGuard, RolesGuard],
|
|
47
|
+
exports: [JwtAuthService, JwtAuthGuard, RolesGuard, AuthService],
|
|
44
48
|
})
|
|
45
49
|
export class AuthModule {}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Body, Controller, Post, Req, UseGuards } from '@nestjs/common';
|
|
2
|
+
import { JwtAuthGuard } from 'src/module/auth/guards/jwt.guard';
|
|
3
|
+
import { AuthService } from '../services/auth.service';
|
|
4
|
+
import { UAParser } from 'ua-parser-js';
|
|
5
|
+
|
|
6
|
+
@Controller('auth')
|
|
7
|
+
export class AuthController {
|
|
8
|
+
constructor(private readonly authService: AuthService) {}
|
|
9
|
+
|
|
10
|
+
@Post('fcmtoken')
|
|
11
|
+
@UseGuards(JwtAuthGuard)
|
|
12
|
+
async getDashboard(@Req() req: any, @Body('fcmtoken') fcmtoken: string) {
|
|
13
|
+
const loggedInUser = req.user.userData;
|
|
14
|
+
|
|
15
|
+
const ip =
|
|
16
|
+
(req.headers['x-forwarded-for'] as string)?.split(',')[0].trim() ||
|
|
17
|
+
req.socket.remoteAddress ||
|
|
18
|
+
req.ip ||
|
|
19
|
+
'';
|
|
20
|
+
|
|
21
|
+
const userAgent = req.headers['user-agent'] || '';
|
|
22
|
+
const parser = new UAParser(userAgent);
|
|
23
|
+
const browser = parser.getBrowser().name || 'Unknown';
|
|
24
|
+
const os = parser.getOS().name || 'Unknown';
|
|
25
|
+
|
|
26
|
+
return this.authService.fcmtoken(fcmtoken, loggedInUser, ip, browser, os);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -1,29 +1,50 @@
|
|
|
1
|
-
import { BadRequestException, Injectable } from '@nestjs/common';
|
|
1
|
+
import { BadRequestException, Inject, Injectable } from '@nestjs/common';
|
|
2
2
|
import { UserService } from '../../user/service/user.service';
|
|
3
3
|
import { JwtService } from '@nestjs/jwt';
|
|
4
4
|
import { UserData } from '../../user/entity/user.entity';
|
|
5
|
+
import { DataSource } from 'typeorm';
|
|
5
6
|
|
|
6
7
|
@Injectable()
|
|
7
8
|
export class AuthService {
|
|
8
9
|
constructor(
|
|
9
|
-
private userService: UserService,
|
|
10
10
|
private jwtService: JwtService,
|
|
11
|
+
private dataSource: DataSource,
|
|
11
12
|
) {}
|
|
12
13
|
|
|
13
|
-
async validateUser(email: string, password: string): Promise<UserData> {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
14
|
+
// async validateUser(email: string, password: string): Promise<UserData> {
|
|
15
|
+
// const user = await this.userService.findByEmailId(email);
|
|
16
|
+
// if (!user) {
|
|
17
|
+
// throw new BadRequestException('User not found');
|
|
18
|
+
// }
|
|
19
|
+
// const isMatch: boolean = password === user.password;
|
|
20
|
+
// if (!isMatch) {
|
|
21
|
+
// throw new BadRequestException('Password does not match');
|
|
22
|
+
// }
|
|
23
|
+
// return user;
|
|
24
|
+
// }
|
|
24
25
|
|
|
25
26
|
async login(user: UserData) {
|
|
26
27
|
const payload = { email: user.email_id, id: user.id };
|
|
27
28
|
return { access_token: this.jwtService.sign(payload) };
|
|
28
29
|
}
|
|
30
|
+
|
|
31
|
+
async fcmtoken(
|
|
32
|
+
fcmtoken: string,
|
|
33
|
+
loggedInUser: any,
|
|
34
|
+
ip: string,
|
|
35
|
+
browser: string,
|
|
36
|
+
os: string,
|
|
37
|
+
) {
|
|
38
|
+
const { id: userId, organization_id } = loggedInUser;
|
|
39
|
+
|
|
40
|
+
// Update the cr_user table
|
|
41
|
+
await this.dataSource.query(
|
|
42
|
+
`UPDATE cr_user
|
|
43
|
+
SET fcm_token = ?, ip = ?, browser = ?, os = ?
|
|
44
|
+
WHERE id = ? AND organization_id = ?`,
|
|
45
|
+
[fcmtoken, ip, browser, os, userId, organization_id],
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
return { message: 'FCM token updated successfully' };
|
|
49
|
+
}
|
|
29
50
|
}
|
|
@@ -50,7 +50,12 @@ import { WebhookController } from './controller/webhook.controller';
|
|
|
50
50
|
TypeOrmModule.forFeature([CommunicationConfig, CommunicationHub]),
|
|
51
51
|
IcsMeetingModule,
|
|
52
52
|
],
|
|
53
|
-
controllers: [
|
|
53
|
+
controllers: [
|
|
54
|
+
CommunicationController,
|
|
55
|
+
GoogleController,
|
|
56
|
+
WrapperController,
|
|
57
|
+
WebhookController,
|
|
58
|
+
],
|
|
54
59
|
providers: [
|
|
55
60
|
// Main Services
|
|
56
61
|
CommunicationService,
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ACTION_CATEGORY } from 'src/constant/global.constant';
|
|
2
|
+
import { BaseEntity } from 'src/module/meta/entity/base-entity.entity';
|
|
3
|
+
import { Column, Entity } from 'typeorm';
|
|
4
|
+
|
|
5
|
+
@Entity({ name: 'cr_rule_' })
|
|
6
|
+
export class ActionCategory extends BaseEntity {
|
|
7
|
+
constructor() {
|
|
8
|
+
super();
|
|
9
|
+
this.entity_type = ACTION_CATEGORY;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
@Column({ type: 'varchar', nullable: true })
|
|
13
|
+
logo: string;
|
|
14
|
+
|
|
15
|
+
@Column({ type: 'varchar', nullable: true })
|
|
16
|
+
modalName: string;
|
|
17
|
+
|
|
18
|
+
@Column({ type: 'varchar', nullable: true })
|
|
19
|
+
mapped_entity_type: string;
|
|
20
|
+
|
|
21
|
+
@Column({ type: 'varchar', nullable: true })
|
|
22
|
+
reason_code: string;
|
|
23
|
+
|
|
24
|
+
@Column({ type: 'boolean', nullable: true })
|
|
25
|
+
is_template: boolean;
|
|
26
|
+
|
|
27
|
+
@Column({ type: 'boolean', nullable: true })
|
|
28
|
+
is_form: boolean;
|
|
29
|
+
|
|
30
|
+
@Column({ type: 'boolean', nullable: true })
|
|
31
|
+
is_assignment: boolean;
|
|
32
|
+
}
|