@solidxai/core 0.1.12-beta.0 → 0.1.12-beta.10
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/commands/seed.command.d.ts.map +1 -1
- package/dist/commands/seed.command.js +10 -2
- package/dist/commands/seed.command.js.map +1 -1
- package/dist/constants/error-messages.d.ts +1 -0
- package/dist/constants/error-messages.d.ts.map +1 -1
- package/dist/constants/error-messages.js +1 -0
- package/dist/constants/error-messages.js.map +1 -1
- package/dist/constants/media-file-types.d.ts +5 -0
- package/dist/constants/media-file-types.d.ts.map +1 -0
- package/dist/constants/media-file-types.js +27 -0
- package/dist/constants/media-file-types.js.map +1 -0
- package/dist/controllers/media.controller.d.ts +14 -11
- package/dist/controllers/media.controller.d.ts.map +1 -1
- package/dist/controllers/media.controller.js +72 -33
- package/dist/controllers/media.controller.js.map +1 -1
- package/dist/dtos/create-chatter-message.dto.d.ts +1 -0
- package/dist/dtos/create-chatter-message.dto.d.ts.map +1 -1
- package/dist/dtos/create-chatter-message.dto.js +7 -1
- package/dist/dtos/create-chatter-message.dto.js.map +1 -1
- package/dist/dtos/create-media.dto.d.ts +1 -0
- package/dist/dtos/create-media.dto.d.ts.map +1 -1
- package/dist/dtos/create-media.dto.js +7 -1
- package/dist/dtos/create-media.dto.js.map +1 -1
- package/dist/dtos/create-role-metadata.dto.d.ts +2 -0
- package/dist/dtos/create-role-metadata.dto.d.ts.map +1 -1
- package/dist/dtos/create-role-metadata.dto.js +3 -1
- package/dist/dtos/create-role-metadata.dto.js.map +1 -1
- package/dist/dtos/post-chatter-message.dto.d.ts +1 -0
- package/dist/dtos/post-chatter-message.dto.d.ts.map +1 -1
- package/dist/dtos/post-chatter-message.dto.js +6 -1
- package/dist/dtos/post-chatter-message.dto.js.map +1 -1
- package/dist/dtos/update-chatter-message.dto.d.ts +1 -0
- package/dist/dtos/update-chatter-message.dto.d.ts.map +1 -1
- package/dist/dtos/update-chatter-message.dto.js +8 -1
- package/dist/dtos/update-chatter-message.dto.js.map +1 -1
- package/dist/dtos/update-chatter-note-message.dto.d.ts +1 -0
- package/dist/dtos/update-chatter-note-message.dto.d.ts.map +1 -1
- package/dist/dtos/update-chatter-note-message.dto.js +7 -1
- package/dist/dtos/update-chatter-note-message.dto.js.map +1 -1
- package/dist/dtos/update-media.dto.d.ts +1 -0
- package/dist/dtos/update-media.dto.d.ts.map +1 -1
- package/dist/dtos/update-media.dto.js +7 -1
- package/dist/dtos/update-media.dto.js.map +1 -1
- package/dist/entities/chatter-message.entity.d.ts +1 -0
- package/dist/entities/chatter-message.entity.d.ts.map +1 -1
- package/dist/entities/chatter-message.entity.js +5 -1
- package/dist/entities/chatter-message.entity.js.map +1 -1
- package/dist/entities/media.entity.js.map +1 -1
- package/dist/enums/auth-type.enum.d.ts +2 -1
- package/dist/enums/auth-type.enum.d.ts.map +1 -1
- package/dist/enums/auth-type.enum.js +1 -0
- package/dist/enums/auth-type.enum.js.map +1 -1
- package/dist/guards/authentication.guard.d.ts +3 -1
- package/dist/guards/authentication.guard.d.ts.map +1 -1
- package/dist/guards/authentication.guard.js +5 -1
- package/dist/guards/authentication.guard.js.map +1 -1
- package/dist/guards/media-signed-url.guard.d.ts +9 -0
- package/dist/guards/media-signed-url.guard.d.ts.map +1 -0
- package/dist/guards/media-signed-url.guard.js +49 -0
- package/dist/guards/media-signed-url.guard.js.map +1 -0
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.d.ts.map +1 -1
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.js +10 -13
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.js.map +1 -1
- package/dist/helpers/solid-core-error-codes-provider.service.d.ts.map +1 -1
- package/dist/helpers/solid-core-error-codes-provider.service.js +9 -0
- package/dist/helpers/solid-core-error-codes-provider.service.js.map +1 -1
- package/dist/interfaces/chatter-mention-notification.interface.d.ts +27 -0
- package/dist/interfaces/chatter-mention-notification.interface.d.ts.map +1 -0
- package/dist/interfaces/chatter-mention-notification.interface.js +3 -0
- package/dist/interfaces/chatter-mention-notification.interface.js.map +1 -0
- package/dist/interfaces.d.ts +19 -1
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js +2 -0
- package/dist/interfaces.js.map +1 -1
- package/dist/jobs/chatter-mention-notification-email-queue-handler.service.d.ts +17 -0
- package/dist/jobs/chatter-mention-notification-email-queue-handler.service.d.ts.map +1 -0
- package/dist/jobs/chatter-mention-notification-email-queue-handler.service.js +106 -0
- package/dist/jobs/chatter-mention-notification-email-queue-handler.service.js.map +1 -0
- package/dist/jobs/database/chatter-mention-notification-email-publisher-database.service.d.ts +12 -0
- package/dist/jobs/database/chatter-mention-notification-email-publisher-database.service.d.ts.map +1 -0
- package/dist/jobs/database/chatter-mention-notification-email-publisher-database.service.js +39 -0
- package/dist/jobs/database/chatter-mention-notification-email-publisher-database.service.js.map +1 -0
- package/dist/jobs/database/chatter-mention-notification-email-queue-options-database.d.ts +8 -0
- package/dist/jobs/database/chatter-mention-notification-email-queue-options-database.d.ts.map +1 -0
- package/dist/jobs/database/chatter-mention-notification-email-queue-options-database.js +10 -0
- package/dist/jobs/database/chatter-mention-notification-email-queue-options-database.js.map +1 -0
- package/dist/jobs/database/chatter-mention-notification-email-subscriber-database.service.d.ts +20 -0
- package/dist/jobs/database/chatter-mention-notification-email-subscriber-database.service.d.ts.map +1 -0
- package/dist/jobs/database/chatter-mention-notification-email-subscriber-database.service.js +48 -0
- package/dist/jobs/database/chatter-mention-notification-email-subscriber-database.service.js.map +1 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-publisher.service.d.ts +12 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-publisher.service.d.ts.map +1 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-publisher.service.js +39 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-publisher.service.js.map +1 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-queue-options.d.ts +8 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-queue-options.d.ts.map +1 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-queue-options.js +10 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-queue-options.js.map +1 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-subscriber.service.d.ts +18 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-subscriber.service.d.ts.map +1 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-subscriber.service.js +45 -0
- package/dist/jobs/rabbitmq/chatter-mention-notification-email-subscriber.service.js.map +1 -0
- package/dist/jobs/redis/chatter-mention-notification-email-publisher-redis.service.d.ts +12 -0
- package/dist/jobs/redis/chatter-mention-notification-email-publisher-redis.service.d.ts.map +1 -0
- package/dist/jobs/redis/chatter-mention-notification-email-publisher-redis.service.js +39 -0
- package/dist/jobs/redis/chatter-mention-notification-email-publisher-redis.service.js.map +1 -0
- package/dist/jobs/redis/chatter-mention-notification-email-queue-options-redis.d.ts +8 -0
- package/dist/jobs/redis/chatter-mention-notification-email-queue-options-redis.d.ts.map +1 -0
- package/dist/jobs/redis/chatter-mention-notification-email-queue-options-redis.js +10 -0
- package/dist/jobs/redis/chatter-mention-notification-email-queue-options-redis.js.map +1 -0
- package/dist/jobs/redis/chatter-mention-notification-email-subscriber-redis.service.d.ts +18 -0
- package/dist/jobs/redis/chatter-mention-notification-email-subscriber-redis.service.d.ts.map +1 -0
- package/dist/jobs/redis/chatter-mention-notification-email-subscriber-redis.service.js +45 -0
- package/dist/jobs/redis/chatter-mention-notification-email-subscriber-redis.service.js.map +1 -0
- package/dist/repository/media.repository.d.ts.map +1 -1
- package/dist/repository/media.repository.js.map +1 -1
- package/dist/seeders/module-metadata-seeder.service.d.ts +7 -1
- package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
- package/dist/seeders/module-metadata-seeder.service.js +87 -3
- package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
- package/dist/seeders/permission-metadata-seeder.service.d.ts +1 -0
- package/dist/seeders/permission-metadata-seeder.service.d.ts.map +1 -1
- package/dist/seeders/permission-metadata-seeder.service.js +6 -1
- package/dist/seeders/permission-metadata-seeder.service.js.map +1 -1
- package/dist/seeders/seed-data/solid-core-metadata.json +95 -13
- package/dist/services/authentication.service.d.ts +2 -2
- package/dist/services/authentication.service.d.ts.map +1 -1
- package/dist/services/authentication.service.js +52 -43
- package/dist/services/authentication.service.js.map +1 -1
- package/dist/services/chatter-message.service.d.ts +7 -1
- package/dist/services/chatter-message.service.d.ts.map +1 -1
- package/dist/services/chatter-message.service.js +85 -4
- package/dist/services/chatter-message.service.js.map +1 -1
- package/dist/services/media-download-url.service.d.ts +22 -0
- package/dist/services/media-download-url.service.d.ts.map +1 -0
- package/dist/services/media-download-url.service.js +70 -0
- package/dist/services/media-download-url.service.js.map +1 -0
- package/dist/services/media-storage.utils.d.ts +24 -0
- package/dist/services/media-storage.utils.d.ts.map +1 -0
- package/dist/services/media-storage.utils.js +73 -0
- package/dist/services/media-storage.utils.js.map +1 -0
- package/dist/services/media.service.d.ts +20 -4
- package/dist/services/media.service.d.ts.map +1 -1
- package/dist/services/media.service.js +155 -55
- package/dist/services/media.service.js.map +1 -1
- package/dist/services/mediaStorageProviders/file-s3-storage-provider.d.ts +4 -4
- package/dist/services/mediaStorageProviders/file-s3-storage-provider.d.ts.map +1 -1
- package/dist/services/mediaStorageProviders/file-s3-storage-provider.js +34 -63
- package/dist/services/mediaStorageProviders/file-s3-storage-provider.js.map +1 -1
- package/dist/services/mediaStorageProviders/file-storage-provider.d.ts +5 -5
- package/dist/services/mediaStorageProviders/file-storage-provider.d.ts.map +1 -1
- package/dist/services/mediaStorageProviders/file-storage-provider.js +34 -38
- package/dist/services/mediaStorageProviders/file-storage-provider.js.map +1 -1
- package/dist/services/role-metadata.service.d.ts +1 -0
- package/dist/services/role-metadata.service.d.ts.map +1 -1
- package/dist/services/role-metadata.service.js +8 -5
- package/dist/services/role-metadata.service.js.map +1 -1
- package/dist/solid-core.module.d.ts.map +1 -1
- package/dist/solid-core.module.js +25 -1
- package/dist/solid-core.module.js.map +1 -1
- package/dist/subscribers/audit.subscriber.js +1 -1
- package/dist/subscribers/audit.subscriber.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/seed.command.ts +12 -3
- package/src/constants/error-messages.ts +1 -0
- package/src/constants/media-file-types.ts +44 -0
- package/src/controllers/media.controller.ts +44 -24
- package/src/dtos/create-chatter-message.dto.ts +5 -0
- package/src/dtos/create-media.dto.ts +8 -3
- package/src/dtos/create-role-metadata.dto.ts +2 -0
- package/src/dtos/post-chatter-message.dto.ts +4 -0
- package/src/dtos/update-chatter-message.dto.ts +6 -0
- package/src/dtos/update-chatter-note-message.dto.ts +5 -0
- package/src/dtos/update-media.dto.ts +8 -3
- package/src/entities/chatter-message.entity.ts +3 -0
- package/src/entities/media.entity.ts +1 -1
- package/src/enums/auth-type.enum.ts +1 -0
- package/src/guards/authentication.guard.ts +3 -0
- package/src/guards/media-signed-url.guard.ts +41 -0
- package/src/helpers/field-crud-managers/MediaFieldCrudManager.ts +12 -24
- package/src/helpers/solid-core-error-codes-provider.service.ts +9 -0
- package/src/interfaces/chatter-mention-notification.interface.ts +29 -0
- package/src/interfaces.ts +20 -0
- package/src/jobs/chatter-mention-notification-email-queue-handler.service.ts +114 -0
- package/src/jobs/database/chatter-mention-notification-email-publisher-database.service.ts +23 -0
- package/src/jobs/database/chatter-mention-notification-email-queue-options-database.ts +9 -0
- package/src/jobs/database/chatter-mention-notification-email-subscriber-database.service.ts +32 -0
- package/src/jobs/rabbitmq/chatter-mention-notification-email-publisher.service.ts +23 -0
- package/src/jobs/rabbitmq/chatter-mention-notification-email-queue-options.ts +9 -0
- package/src/jobs/rabbitmq/chatter-mention-notification-email-subscriber.service.ts +30 -0
- package/src/jobs/redis/chatter-mention-notification-email-publisher-redis.service.ts +23 -0
- package/src/jobs/redis/chatter-mention-notification-email-queue-options-redis.ts +9 -0
- package/src/jobs/redis/chatter-mention-notification-email-subscriber-redis.service.ts +30 -0
- package/src/repository/media.repository.ts +1 -0
- package/src/seeders/module-metadata-seeder.service.ts +109 -3
- package/src/seeders/permission-metadata-seeder.service.ts +6 -1
- package/src/seeders/seed-data/email-templates/chatter-mention-notification.handlebars.html +200 -0
- package/src/seeders/seed-data/solid-core-metadata.json +95 -13
- package/src/services/authentication.service.ts +66 -55
- package/src/services/chatter-message.service.ts +97 -2
- package/src/services/media-download-url.service.ts +74 -0
- package/src/services/media-storage.utils.ts +70 -0
- package/src/services/media.service.ts +187 -59
- package/src/services/mediaStorageProviders/file-s3-storage-provider.ts +49 -76
- package/src/services/mediaStorageProviders/file-storage-provider.ts +41 -48
- package/src/services/role-metadata.service.ts +17 -5
- package/src/solid-core.module.ts +35 -2
- package/src/subscribers/audit.subscriber.ts +1 -1
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { Injectable, Logger } from '@nestjs/common';
|
|
2
|
+
import { MailFactory } from 'src/factories/mail.factory';
|
|
3
|
+
import { ChatterMentionNotificationPayload } from 'src/interfaces/chatter-mention-notification.interface';
|
|
4
|
+
import { QueueMessage } from 'src/interfaces/mq';
|
|
5
|
+
import { UserRepository } from 'src/repository/user.repository';
|
|
6
|
+
import { SettingService } from 'src/services/setting.service';
|
|
7
|
+
import type { SolidCoreSetting } from 'src/services/settings/default-settings-provider.service';
|
|
8
|
+
import { In } from 'typeorm';
|
|
9
|
+
|
|
10
|
+
@Injectable()
|
|
11
|
+
export class ChatterMentionNotificationEmailQueueHandler {
|
|
12
|
+
private readonly logger = new Logger(ChatterMentionNotificationEmailQueueHandler.name);
|
|
13
|
+
|
|
14
|
+
constructor(
|
|
15
|
+
private readonly mailFactory: MailFactory,
|
|
16
|
+
private readonly userRepository: UserRepository,
|
|
17
|
+
private readonly settingService: SettingService,
|
|
18
|
+
) {}
|
|
19
|
+
|
|
20
|
+
private buildAdminRecordFormUrl(frontendAdminBaseUrl: string, moduleName: string, modelName: string, recordId: number) {
|
|
21
|
+
if (!frontendAdminBaseUrl || !moduleName || !modelName || !recordId) return '';
|
|
22
|
+
const normalizedModelName = modelName
|
|
23
|
+
.trim()
|
|
24
|
+
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
|
|
25
|
+
.replace(/[_\s]+/g, '-')
|
|
26
|
+
.toLowerCase();
|
|
27
|
+
return `${frontendAdminBaseUrl.replace(/\/+$/, '')}/admin/core/${moduleName.trim()}/${normalizedModelName}/form/${recordId}`;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async handle(message: QueueMessage<ChatterMentionNotificationPayload>) {
|
|
31
|
+
const mailService = this.mailFactory.getMailService();
|
|
32
|
+
const payload = message.payload;
|
|
33
|
+
|
|
34
|
+
if (!payload?.mentions?.length) {
|
|
35
|
+
this.logger.debug('Skipping chatter mention notification because no mentions were provided.');
|
|
36
|
+
return { sent: 0 };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const mentionUserIds = payload.mentions
|
|
40
|
+
.map(mention => Number(mention.id))
|
|
41
|
+
.filter(id => Number.isInteger(id) && id > 0);
|
|
42
|
+
const userIdsToLoad = Array.from(new Set([
|
|
43
|
+
...mentionUserIds,
|
|
44
|
+
...(payload.actor?.id ? [Number(payload.actor.id)] : []),
|
|
45
|
+
]));
|
|
46
|
+
|
|
47
|
+
if (userIdsToLoad.length === 0) {
|
|
48
|
+
this.logger.debug('Skipping chatter mention notification because mention user ids were not provided.');
|
|
49
|
+
return { sent: 0 };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const users = await this.userRepository.find({
|
|
53
|
+
where: { id: In(userIdsToLoad) },
|
|
54
|
+
});
|
|
55
|
+
const usersById = new Map(users.map(user => [Number(user.id), user]));
|
|
56
|
+
const actor = payload.actor?.id ? usersById.get(Number(payload.actor.id)) : null;
|
|
57
|
+
const recipients = Array.from(new Set(mentionUserIds))
|
|
58
|
+
.map(id => {
|
|
59
|
+
const user = usersById.get(id);
|
|
60
|
+
const mention = payload.mentions.find(item => Number(item.id) === id);
|
|
61
|
+
return {
|
|
62
|
+
id,
|
|
63
|
+
username: user?.username || mention?.username || '',
|
|
64
|
+
displayName: user?.fullName || mention?.displayName || user?.username || mention?.username || '',
|
|
65
|
+
email: user?.email || '',
|
|
66
|
+
};
|
|
67
|
+
})
|
|
68
|
+
.filter(recipient => Boolean(recipient.email));
|
|
69
|
+
|
|
70
|
+
if (recipients.length === 0) {
|
|
71
|
+
this.logger.debug('Skipping chatter mention notification because no mentioned users have email addresses.');
|
|
72
|
+
return { sent: 0 };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const frontendAdminBaseUrl = this.settingService.getConfigValue<SolidCoreSetting>('frontendAdminBaseUrl');
|
|
76
|
+
const commonTemplateParams = {
|
|
77
|
+
mentionedByDisplayName: actor?.fullName || payload.actor?.username || payload.actor?.email || 'Someone',
|
|
78
|
+
mentionedByEmail: actor?.email || payload.actor?.email,
|
|
79
|
+
noteBody: payload.noteBody,
|
|
80
|
+
entityDisplayName: payload.entity.displayName,
|
|
81
|
+
entityUserKey: payload.entity.userKey,
|
|
82
|
+
entityFormUrl: this.buildAdminRecordFormUrl(
|
|
83
|
+
frontendAdminBaseUrl,
|
|
84
|
+
payload.entity.moduleName,
|
|
85
|
+
payload.entity.modelName,
|
|
86
|
+
payload.entity.id,
|
|
87
|
+
),
|
|
88
|
+
solidAppName: this.settingService.getConfigValue<SolidCoreSetting>('appTitle'),
|
|
89
|
+
solidAppWebsiteUrl: this.settingService.getConfigValue<SolidCoreSetting>('solidAppWebsiteUrl'),
|
|
90
|
+
companyLogoUrl: this.settingService.getConfigValue<SolidCoreSetting>('companylogo'),
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
let sent = 0;
|
|
94
|
+
for (const recipient of recipients) {
|
|
95
|
+
await mailService.sendEmailUsingTemplate(
|
|
96
|
+
recipient.email,
|
|
97
|
+
payload.templateName,
|
|
98
|
+
{
|
|
99
|
+
...commonTemplateParams,
|
|
100
|
+
mentionedUserDisplayName: recipient.displayName || recipient.username,
|
|
101
|
+
mentionedUserUsername: recipient.username,
|
|
102
|
+
},
|
|
103
|
+
false,
|
|
104
|
+
null,
|
|
105
|
+
null,
|
|
106
|
+
payload.parentEntity,
|
|
107
|
+
payload.parentEntityId,
|
|
108
|
+
);
|
|
109
|
+
sent += 1;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return { sent };
|
|
113
|
+
}
|
|
114
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Injectable } from '@nestjs/common';
|
|
2
|
+
import { ChatterMentionNotificationPayload } from 'src/interfaces/chatter-mention-notification.interface';
|
|
3
|
+
import { QueuesModuleOptions } from 'src/interfaces';
|
|
4
|
+
import { MqMessageQueueService } from 'src/services/mq-message-queue.service';
|
|
5
|
+
import { MqMessageService } from 'src/services/mq-message.service';
|
|
6
|
+
import { DatabasePublisher } from 'src/services/queues/database-publisher.service';
|
|
7
|
+
import queueOptions from './chatter-mention-notification-email-queue-options-database';
|
|
8
|
+
|
|
9
|
+
@Injectable()
|
|
10
|
+
export class ChatterMentionNotificationEmailQueuePublisherDatabase extends DatabasePublisher<ChatterMentionNotificationPayload> {
|
|
11
|
+
constructor(
|
|
12
|
+
protected readonly mqMessageService: MqMessageService,
|
|
13
|
+
protected readonly mqMessageQueueService: MqMessageQueueService,
|
|
14
|
+
) {
|
|
15
|
+
super(mqMessageService, mqMessageQueueService);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
options(): QueuesModuleOptions {
|
|
19
|
+
return {
|
|
20
|
+
...queueOptions
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Injectable } from '@nestjs/common';
|
|
2
|
+
import { ChatterMentionNotificationEmailQueueHandler } from 'src/jobs/chatter-mention-notification-email-queue-handler.service';
|
|
3
|
+
import { ChatterMentionNotificationPayload } from 'src/interfaces/chatter-mention-notification.interface';
|
|
4
|
+
import { QueuesModuleOptions } from 'src/interfaces';
|
|
5
|
+
import { QueueMessage } from 'src/interfaces/mq';
|
|
6
|
+
import { MqMessageQueueService } from 'src/services/mq-message-queue.service';
|
|
7
|
+
import { MqMessageService } from 'src/services/mq-message.service';
|
|
8
|
+
import { PollerService } from 'src/services/poller.service';
|
|
9
|
+
import { DatabaseSubscriber } from 'src/services/queues/database-subscriber.service';
|
|
10
|
+
import queueOptions from './chatter-mention-notification-email-queue-options-database';
|
|
11
|
+
|
|
12
|
+
@Injectable()
|
|
13
|
+
export class ChatterMentionNotificationEmailQueueSubscriberDatabase extends DatabaseSubscriber<ChatterMentionNotificationPayload> {
|
|
14
|
+
constructor(
|
|
15
|
+
readonly mqMessageService: MqMessageService,
|
|
16
|
+
readonly mqMessageQueueService: MqMessageQueueService,
|
|
17
|
+
readonly poller: PollerService,
|
|
18
|
+
private readonly handler: ChatterMentionNotificationEmailQueueHandler,
|
|
19
|
+
) {
|
|
20
|
+
super(mqMessageService, mqMessageQueueService, poller);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
options(): QueuesModuleOptions {
|
|
24
|
+
return {
|
|
25
|
+
...queueOptions
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
subscribe(message: QueueMessage<ChatterMentionNotificationPayload>) {
|
|
30
|
+
return this.handler.handle(message);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Injectable } from '@nestjs/common';
|
|
2
|
+
import { ChatterMentionNotificationPayload } from 'src/interfaces/chatter-mention-notification.interface';
|
|
3
|
+
import { QueuesModuleOptions } from 'src/interfaces';
|
|
4
|
+
import { MqMessageQueueService } from 'src/services/mq-message-queue.service';
|
|
5
|
+
import { MqMessageService } from 'src/services/mq-message.service';
|
|
6
|
+
import { RabbitMqPublisher } from 'src/services/queues/rabbitmq-publisher.service';
|
|
7
|
+
import queueOptions from './chatter-mention-notification-email-queue-options';
|
|
8
|
+
|
|
9
|
+
@Injectable()
|
|
10
|
+
export class ChatterMentionNotificationEmailQueuePublisherRabbitmq extends RabbitMqPublisher<ChatterMentionNotificationPayload> {
|
|
11
|
+
constructor(
|
|
12
|
+
protected readonly mqMessageService: MqMessageService,
|
|
13
|
+
protected readonly mqMessageQueueService: MqMessageQueueService,
|
|
14
|
+
) {
|
|
15
|
+
super(mqMessageService, mqMessageQueueService);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
options(): QueuesModuleOptions {
|
|
19
|
+
return {
|
|
20
|
+
...queueOptions
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Injectable } from '@nestjs/common';
|
|
2
|
+
import { ChatterMentionNotificationEmailQueueHandler } from 'src/jobs/chatter-mention-notification-email-queue-handler.service';
|
|
3
|
+
import { ChatterMentionNotificationPayload } from 'src/interfaces/chatter-mention-notification.interface';
|
|
4
|
+
import { QueuesModuleOptions } from 'src/interfaces';
|
|
5
|
+
import { QueueMessage } from 'src/interfaces/mq';
|
|
6
|
+
import { MqMessageQueueService } from 'src/services/mq-message-queue.service';
|
|
7
|
+
import { MqMessageService } from 'src/services/mq-message.service';
|
|
8
|
+
import { RabbitMqSubscriber } from 'src/services/queues/rabbitmq-subscriber.service';
|
|
9
|
+
import queueOptions from './chatter-mention-notification-email-queue-options';
|
|
10
|
+
|
|
11
|
+
@Injectable()
|
|
12
|
+
export class ChatterMentionNotificationEmailQueueSubscriberRabbitmq extends RabbitMqSubscriber<ChatterMentionNotificationPayload> {
|
|
13
|
+
constructor(
|
|
14
|
+
readonly mqMessageService: MqMessageService,
|
|
15
|
+
readonly mqMessageQueueService: MqMessageQueueService,
|
|
16
|
+
private readonly handler: ChatterMentionNotificationEmailQueueHandler,
|
|
17
|
+
) {
|
|
18
|
+
super(mqMessageService, mqMessageQueueService);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
options(): QueuesModuleOptions {
|
|
22
|
+
return {
|
|
23
|
+
...queueOptions
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
subscribe(message: QueueMessage<ChatterMentionNotificationPayload>) {
|
|
28
|
+
return this.handler.handle(message);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Injectable } from '@nestjs/common';
|
|
2
|
+
import { ChatterMentionNotificationPayload } from 'src/interfaces/chatter-mention-notification.interface';
|
|
3
|
+
import { QueuesModuleOptions } from 'src/interfaces';
|
|
4
|
+
import { MqMessageQueueService } from 'src/services/mq-message-queue.service';
|
|
5
|
+
import { MqMessageService } from 'src/services/mq-message.service';
|
|
6
|
+
import { RedisPublisher } from 'src/services/queues/redis-publisher.service';
|
|
7
|
+
import queueOptions from './chatter-mention-notification-email-queue-options-redis';
|
|
8
|
+
|
|
9
|
+
@Injectable()
|
|
10
|
+
export class ChatterMentionNotificationEmailQueuePublisherRedis extends RedisPublisher<ChatterMentionNotificationPayload> {
|
|
11
|
+
constructor(
|
|
12
|
+
protected readonly mqMessageService: MqMessageService,
|
|
13
|
+
protected readonly mqMessageQueueService: MqMessageQueueService,
|
|
14
|
+
) {
|
|
15
|
+
super(mqMessageService, mqMessageQueueService);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
options(): QueuesModuleOptions {
|
|
19
|
+
return {
|
|
20
|
+
...queueOptions
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Injectable } from '@nestjs/common';
|
|
2
|
+
import { ChatterMentionNotificationEmailQueueHandler } from 'src/jobs/chatter-mention-notification-email-queue-handler.service';
|
|
3
|
+
import { ChatterMentionNotificationPayload } from 'src/interfaces/chatter-mention-notification.interface';
|
|
4
|
+
import { QueuesModuleOptions } from 'src/interfaces';
|
|
5
|
+
import { QueueMessage } from 'src/interfaces/mq';
|
|
6
|
+
import { MqMessageQueueService } from 'src/services/mq-message-queue.service';
|
|
7
|
+
import { MqMessageService } from 'src/services/mq-message.service';
|
|
8
|
+
import { RedisSubscriber } from 'src/services/queues/redis-subscriber.service';
|
|
9
|
+
import queueOptions from './chatter-mention-notification-email-queue-options-redis';
|
|
10
|
+
|
|
11
|
+
@Injectable()
|
|
12
|
+
export class ChatterMentionNotificationEmailQueueSubscriberRedis extends RedisSubscriber<ChatterMentionNotificationPayload> {
|
|
13
|
+
constructor(
|
|
14
|
+
readonly mqMessageService: MqMessageService,
|
|
15
|
+
readonly mqMessageQueueService: MqMessageQueueService,
|
|
16
|
+
private readonly handler: ChatterMentionNotificationEmailQueueHandler,
|
|
17
|
+
) {
|
|
18
|
+
super(mqMessageService, mqMessageQueueService);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
options(): QueuesModuleOptions {
|
|
22
|
+
return {
|
|
23
|
+
...queueOptions
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
subscribe(message: QueueMessage<ChatterMentionNotificationPayload>) {
|
|
28
|
+
return this.handler.handle(message);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { forwardRef, Inject, Injectable, Logger } from '@nestjs/common';
|
|
2
|
+
import { EventEmitter2 } from '@nestjs/event-emitter';
|
|
2
3
|
import * as fs from 'fs';
|
|
3
4
|
import * as os from 'os';
|
|
4
5
|
import * as path from 'path';
|
|
@@ -39,7 +40,12 @@ import { User } from '../entities/user.entity';
|
|
|
39
40
|
import { MENU_ROLE_JOIN_TABLE_NAME, MENU_ROLE_JOIN_TABLE_NAME_MENU_COL, MENU_ROLE_JOIN_TABLE_NAME_ROLE_COL } from '../dtos/create-menu-item-metadata.dto';
|
|
40
41
|
import { DEFAULT_SA_PASSWORD } from '../dtos/create-user.dto';
|
|
41
42
|
import { SignUpDto } from '../dtos/sign-up.dto';
|
|
42
|
-
import {
|
|
43
|
+
import {
|
|
44
|
+
ADMIN_ROLE_NAME,
|
|
45
|
+
ALLOWED_TO_EXPORT_ROLE_NAME,
|
|
46
|
+
ALLOWED_TO_IMPORT_ROLE_NAME,
|
|
47
|
+
CreateRoleMetadataDto,
|
|
48
|
+
} from 'src/dtos/create-role-metadata.dto';
|
|
43
49
|
import { CreateSavedFiltersDto } from 'src/dtos/create-saved-filters.dto';
|
|
44
50
|
import { CreateScheduledJobDto } from 'src/dtos/create-scheduled-job.dto';
|
|
45
51
|
import { CreateLocaleDto } from 'src/dtos/create-locale.dto';
|
|
@@ -60,6 +66,7 @@ import { FieldMetadata } from 'src/entities/field-metadata.entity';
|
|
|
60
66
|
import { ModelMetadata } from 'src/entities/model-metadata.entity';
|
|
61
67
|
import { PermissionMetadata } from 'src/entities/permission-metadata.entity';
|
|
62
68
|
import { ViewMetadata } from 'src/entities/view-metadata.entity';
|
|
69
|
+
import { EventDetails, EventType, ModuleMetadataSeederEventPayload } from 'src/interfaces';
|
|
63
70
|
|
|
64
71
|
/**
|
|
65
72
|
* Central metadata seeder for both solid-core and consuming modules.
|
|
@@ -79,6 +86,11 @@ import { ViewMetadata } from 'src/entities/view-metadata.entity';
|
|
|
79
86
|
*/
|
|
80
87
|
@Injectable()
|
|
81
88
|
export class ModuleMetadataSeederService {
|
|
89
|
+
private readonly adminPermissionExclusionPrefixes = [
|
|
90
|
+
'ImportTransactionController.',
|
|
91
|
+
'ExportTemplateController.',
|
|
92
|
+
'ExportTransactionController.',
|
|
93
|
+
];
|
|
82
94
|
private readonly logger = new Logger(ModuleMetadataSeederService.name);
|
|
83
95
|
// Stable tag used on all verbose seed timing logs so runs can be grepped quickly.
|
|
84
96
|
private readonly seedTimingTag = 'SEED_TIMING';
|
|
@@ -98,6 +110,7 @@ export class ModuleMetadataSeederService {
|
|
|
98
110
|
private readonly moduleMetadataService: ModuleMetadataService,
|
|
99
111
|
@Inject(forwardRef(() => ModelMetadataService))
|
|
100
112
|
private readonly modelMetadataService: ModelMetadataService,
|
|
113
|
+
private readonly eventEmitter: EventEmitter2,
|
|
101
114
|
private readonly fieldMetadataService: FieldMetadataService,
|
|
102
115
|
private readonly mediaStorageProviderMetadataService: MediaStorageProviderMetadataService,
|
|
103
116
|
private readonly roleService: RoleMetadataService,
|
|
@@ -131,7 +144,26 @@ export class ModuleMetadataSeederService {
|
|
|
131
144
|
let currentModule = 'global';
|
|
132
145
|
let currentStep = 'bootstrap';
|
|
133
146
|
let modulesToSeed: string[] | null = null;
|
|
147
|
+
const requestedModulesToSeed = Array.isArray(conf?.modulesToSeed) ? [...conf.modulesToSeed] : null;
|
|
134
148
|
const shouldSeedGlobalMetadata = conf?.seedGlobalMetadata !== false;
|
|
149
|
+
const seedOptions: ModuleMetadataSeederEventPayload['options'] = {
|
|
150
|
+
modulesToSeed: requestedModulesToSeed,
|
|
151
|
+
pruneMetadata: Boolean(conf?.pruneMetadata),
|
|
152
|
+
seedGlobalMetadata: shouldSeedGlobalMetadata,
|
|
153
|
+
};
|
|
154
|
+
const seedRunId = uuidv4();
|
|
155
|
+
const startedAt = new Date();
|
|
156
|
+
const seededModuleNames: string[] = [];
|
|
157
|
+
|
|
158
|
+
this.emitModuleMetadataSeederEvent(
|
|
159
|
+
EventType.MODULE_METADATA_SEEDER_STARTED,
|
|
160
|
+
{
|
|
161
|
+
seedRunId,
|
|
162
|
+
options: seedOptions,
|
|
163
|
+
startedAt: startedAt.toISOString(),
|
|
164
|
+
currentStep,
|
|
165
|
+
},
|
|
166
|
+
);
|
|
135
167
|
|
|
136
168
|
try {
|
|
137
169
|
this.enablePruning = Boolean(conf?.pruneMetadata);
|
|
@@ -190,6 +222,7 @@ export class ModuleMetadataSeederService {
|
|
|
190
222
|
|
|
191
223
|
console.log(`▶ Seeding Metadata for Module: ${moduleMetadata.name}`);
|
|
192
224
|
this.logger.log(`Seeding Metadata for Module: ${moduleMetadata.name}`);
|
|
225
|
+
seededModuleNames.push(moduleMetadata.name);
|
|
193
226
|
|
|
194
227
|
await this.timeOperation('module-total', async () => {
|
|
195
228
|
currentStep = 'seedMediaStorageProviders';
|
|
@@ -283,10 +316,37 @@ export class ModuleMetadataSeederService {
|
|
|
283
316
|
// Add a console log indicating seeding is finished. This needs to be console.log so that it looks proper when this code is run via CLI.
|
|
284
317
|
console.log(`✔ Seeding completed.`);
|
|
285
318
|
//this.logger.log(`All Seeders finished`);
|
|
319
|
+
await this.emitModuleMetadataSeederFinishedEvent(
|
|
320
|
+
EventType.MODULE_METADATA_SEEDER_FINISHED,
|
|
321
|
+
{
|
|
322
|
+
seedRunId,
|
|
323
|
+
options: seedOptions,
|
|
324
|
+
startedAt: startedAt.toISOString(),
|
|
325
|
+
finishedAt: new Date().toISOString(),
|
|
326
|
+
durationMs: Date.now() - startedAt.getTime(),
|
|
327
|
+
success: true,
|
|
328
|
+
seededModuleNames,
|
|
329
|
+
currentStep,
|
|
330
|
+
},
|
|
331
|
+
);
|
|
286
332
|
|
|
287
333
|
//FIXME: Handle displaying the created users credentials in a better way.
|
|
288
334
|
// this.logger.log(`Newly created username is: ${usersDetail?.length > 0 ? usersDetail[0]?.username : ''} and password is ${usersDetail?.length > 0 ? usersDetail[0]?.password : ''}`);
|
|
289
335
|
} catch (error: any) {
|
|
336
|
+
await this.emitModuleMetadataSeederFinishedEvent(
|
|
337
|
+
EventType.MODULE_METADATA_SEEDER_FINISHED,
|
|
338
|
+
{
|
|
339
|
+
seedRunId,
|
|
340
|
+
options: seedOptions,
|
|
341
|
+
startedAt: startedAt.toISOString(),
|
|
342
|
+
finishedAt: new Date().toISOString(),
|
|
343
|
+
durationMs: Date.now() - startedAt.getTime(),
|
|
344
|
+
success: false,
|
|
345
|
+
seededModuleNames,
|
|
346
|
+
currentStep,
|
|
347
|
+
errorMessage: error?.message,
|
|
348
|
+
},
|
|
349
|
+
);
|
|
290
350
|
this.logSeedFailureForCli(error, {
|
|
291
351
|
moduleName: currentModule,
|
|
292
352
|
step: currentStep,
|
|
@@ -297,6 +357,31 @@ export class ModuleMetadataSeederService {
|
|
|
297
357
|
}
|
|
298
358
|
}
|
|
299
359
|
|
|
360
|
+
private emitModuleMetadataSeederEvent(
|
|
361
|
+
type: EventType.MODULE_METADATA_SEEDER_STARTED | EventType.MODULE_METADATA_SEEDER_FINISHED,
|
|
362
|
+
payload: ModuleMetadataSeederEventPayload,
|
|
363
|
+
): void {
|
|
364
|
+
try {
|
|
365
|
+
this.eventEmitter.emit(type, new EventDetails<ModuleMetadataSeederEventPayload>(type, payload));
|
|
366
|
+
} catch (error: any) {
|
|
367
|
+
this.logger.warn(`Failed to emit ${type}: ${error?.message ?? error}`);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
private async emitModuleMetadataSeederFinishedEvent(
|
|
372
|
+
type: EventType.MODULE_METADATA_SEEDER_FINISHED,
|
|
373
|
+
payload: ModuleMetadataSeederEventPayload,
|
|
374
|
+
): Promise<void> {
|
|
375
|
+
try {
|
|
376
|
+
console.log(`▶ Running post-seed hooks for runId=${payload.seedRunId}`);
|
|
377
|
+
await this.eventEmitter.emitAsync(type, new EventDetails<ModuleMetadataSeederEventPayload>(type, payload));
|
|
378
|
+
console.log(`✔ Post-seed hooks completed for runId=${payload.seedRunId}`);
|
|
379
|
+
} catch (error: any) {
|
|
380
|
+
console.log(`✖ Post-seed hooks failed for runId=${payload.seedRunId}: ${error?.message ?? error}`);
|
|
381
|
+
this.logger.warn(`Failed to emit ${type}: ${error?.message ?? error}`);
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
|
|
300
385
|
private buildTimingPrefix(itemTag: string, options?: { moduleName?: string; component?: string; serviceCall?: string }): string {
|
|
301
386
|
const parts = [`[${this.seedTimingTag}]`, `[ITEM:${itemTag}]`];
|
|
302
387
|
if (options?.moduleName) {
|
|
@@ -498,10 +583,17 @@ export class ModuleMetadataSeederService {
|
|
|
498
583
|
|
|
499
584
|
private async setupDefaultRolesWithPermissions() {
|
|
500
585
|
this.logger.debug(`About to add all permissions to the Admin role`);
|
|
501
|
-
await this.timeOperation('role-add-all-permissions', () => this.roleService.
|
|
586
|
+
await this.timeOperation('role-add-all-permissions', () => this.roleService.addAllPermissionsToRoleExceptPrefixes(ADMIN_ROLE_NAME, this.adminPermissionExclusionPrefixes), {
|
|
587
|
+
moduleName: 'global',
|
|
588
|
+
component: 'default-roles',
|
|
589
|
+
serviceCall: 'roleService.addAllPermissionsToRoleExceptPrefixes',
|
|
590
|
+
details: `role=${ADMIN_ROLE_NAME}`,
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
await this.timeOperation('attach-capability-roles-to-admin-users', () => this.attachCapabilityRolesToAdminUsers(), {
|
|
502
594
|
moduleName: 'global',
|
|
503
595
|
component: 'default-roles',
|
|
504
|
-
serviceCall: '
|
|
596
|
+
serviceCall: 'attachCapabilityRolesToAdminUsers',
|
|
505
597
|
details: `role=${ADMIN_ROLE_NAME}`,
|
|
506
598
|
});
|
|
507
599
|
|
|
@@ -514,6 +606,20 @@ export class ModuleMetadataSeederService {
|
|
|
514
606
|
// await this.roleService.addPermissionToRole(PUBLIC_ROLE_NAME, ['SettingController.wrapSettings', 'AuthenticationController.logout']);
|
|
515
607
|
}
|
|
516
608
|
|
|
609
|
+
private async attachCapabilityRolesToAdminUsers(): Promise<void> {
|
|
610
|
+
const adminUsers = await this.userService.findUsersByRole(ADMIN_ROLE_NAME, {});
|
|
611
|
+
if (!adminUsers?.length) {
|
|
612
|
+
return;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
const capabilityRoles = [ALLOWED_TO_IMPORT_ROLE_NAME, ALLOWED_TO_EXPORT_ROLE_NAME];
|
|
616
|
+
for (const adminUser of adminUsers) {
|
|
617
|
+
for (const capabilityRole of capabilityRoles) {
|
|
618
|
+
await this.userService.addRoleToUser(adminUser.username, capabilityRole);
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
|
|
517
623
|
private async seedSecurityRules(overallMetadata: any): Promise<{ pruned: number; upserted: number }> {
|
|
518
624
|
const securityRules = this.getSeedArray<CreateSecurityRuleDto>(overallMetadata?.securityRules);
|
|
519
625
|
const pruned = this.enablePruning ? await this.timeOperation('prune-security-rules', () => this.pruneSecurityRules(securityRules, overallMetadata?.moduleMetadata?.name), {
|
|
@@ -6,6 +6,11 @@ import { RoleMetadataService } from '../services/role-metadata.service';
|
|
|
6
6
|
@Injectable()
|
|
7
7
|
export class PermissionMetadataSeederService {
|
|
8
8
|
private readonly logger = new Logger(PermissionMetadataSeederService.name);
|
|
9
|
+
private readonly adminPermissionExclusionPrefixes = [
|
|
10
|
+
'ImportTransactionController.',
|
|
11
|
+
'ExportTemplateController.',
|
|
12
|
+
'ExportTransactionController.',
|
|
13
|
+
];
|
|
9
14
|
|
|
10
15
|
constructor(
|
|
11
16
|
// @InjectRepository(PermissionMetadata)
|
|
@@ -58,6 +63,6 @@ export class PermissionMetadataSeederService {
|
|
|
58
63
|
}
|
|
59
64
|
|
|
60
65
|
// Associate the Admin role with all existing permissions.
|
|
61
|
-
await this.roleService.
|
|
66
|
+
await this.roleService.addAllPermissionsToRoleExceptPrefixes("Admin", this.adminPermissionExclusionPrefixes);
|
|
62
67
|
}
|
|
63
68
|
}
|