[feature] Add licenseLimit notification; Refactor notificationService

This commit is contained in:
Sergey Konovalov
2024-04-25 16:52:23 +03:00
committed by Georgii Petrov
parent 44e4d28b55
commit 8608a070f8
3 changed files with 76 additions and 82 deletions

View File

@ -30,7 +30,8 @@
"disableUrlAccess": false
},
"contactDefaults": {
"from": "from.mail@server.com"
"from": "from.mail@server.com",
"to": "to.mail@server.com"
}
},
"notification": {
@ -47,6 +48,18 @@
"policies": {
"repeatInterval": "1d"
}
},
"licenseLimit": {
"transportType": [
"email"
],
"template": {
"title": "License",
"body": "%s limit exceeded!!!"
},
"policies": {
"repeatInterval": "1h"
}
}
}
},

View File

@ -31,27 +31,24 @@
*/
'use strict';
const util = require('util');
const config = require('config');
const ms = require('ms');
const uuid = require('uuid');
const mailService = require('./mailService');
const operationContext = require('./operationContext');
const cfgMailServer = config.get('email.smtpServerConfiguration');
const cfgMailMessageDefaults = config.get('email.contactDefaults');
const uuidNamespace = 'e071294c-e621-4195-b453-6da9344e5c72';
const ctx = new operationContext.Context();
const defaultLicenseRepeatInterval = 1000 * 60 * 60 * 24;
const recipients = new Map();
const defaultRepeatInterval = 1000 * 60 * 60 * 24;
const repeatIntervalsExpired = new Map();
const notificationTypes = {
LICENSE_EXPIRED: 0,
LICENSE_EXPIRED: "licenseExpired",
LICENSE_LIMIT: "licenseLimit"
};
class TransportInterface {
getRecipientId(messageParams) {}
async send(message) {}
async send(ctx, message) {}
contentGeneration(template, messageParams) {}
}
@ -66,26 +63,17 @@ class MailTransport extends TransportInterface {
mailService.createTransporter(this.host, this.port, this.auth, cfgMailMessageDefaults);
}
getRecipientId(messageParams) {
if (!messageParams.to) {
return uuid.NIL;
}
return uuid.v5(messageParams.to, uuidNamespace);
}
send(message) {
ctx.logger.info('!!!!!!!!!!!!!!!!!!!!!SENDONG:', message);
async send(ctx, message) {
ctx.logger.info('Notification service: MailTransport send %j', message);
return mailService.send(this.host, this.auth.user, message);
}
contentGeneration(template, messageParams) {
const messageBody = {
let text = util.format(template.body, ...messageParams);
return {
subject: template.title,
text: template.body
text: text
};
return Object.assign({}, messageBody, messageParams);
}
}
@ -99,7 +87,7 @@ class TelegramTransport extends TransportInterface {
class Transport {
transport = new TransportInterface();
constructor(transportName) {
constructor(ctx, transportName) {
this.name = transportName;
switch (transportName) {
@ -110,61 +98,38 @@ class Transport {
this.transport = new TelegramTransport();
break
default:
ctx.logger.error(`Notification service error: transport method "${transportName}" not implemented`);
ctx.logger.warn(`Notification service: error: transport method "${transportName}" not implemented`);
}
}
}
function getRecipientData(id, defaultPoliciesData) {
if (id === uuid.NIL) {
return;
}
async function notify(ctx, notificationType, messageParams) {
ctx.logger.debug('Notification service: notify "%s"', notificationType);
let tenRule;
tenRule = ctx.getCfg('notification.rules.' + notificationType, config.get('notification.rules.' + notificationType));
const recipientData = recipients.get(id);
if (!recipientData) {
recipients.set(id, defaultPoliciesData);
return defaultPoliciesData;
}
return recipientData;
}
async function notify(notificationType, messageParams) {
ctx.logger.info('!!!!!!!!!!!!!!!!!!!!!HERE:', messageParams);
switch (notificationType) {
case notificationTypes.LICENSE_EXPIRED: {
licenseExpiredNotify(messageParams);
break;
}
if (tenRule && checkRulePolicies(ctx, notificationType, tenRule)) {
await notifyRule(ctx, tenRule, messageParams);
}
}
function licenseExpiredNotify(messageParams) {
const cfgLicenseExpired = config.get('notification.rules.licenseExpired');
const transportObjects = cfgLicenseExpired.transportType.map(transport => new Transport(transport));
const { repeatInterval } = cfgLicenseExpired.policies;
const intervalMilliseconds = ms(repeatInterval) ?? defaultLicenseRepeatInterval;
const defaultPolices = {
repeatDate: Date.now(),
function checkRulePolicies(ctx, notificationType, tenRule) {
const {repeatInterval} = tenRule.policies;
const intervalMilliseconds = ms(repeatInterval) ?? defaultRepeatInterval;
let expired = repeatIntervalsExpired.get(notificationType);
if (!expired || expired <= Date.now()) {
repeatIntervalsExpired.set(notificationType, Date.now() + intervalMilliseconds);
return true;
}
ctx.logger.debug(`Notification service: skip rule "%s" due to repeat interval %s`, notificationType, repeatInterval);
return false;
}
transportObjects.forEach(object => {
const recipientId = object.transport.getRecipientId(messageParams);
const data = getRecipientData(recipientId, defaultPolices);
if (!data) {
ctx.logger.error(`Notification service error, licenseExpiredNotify() transport "${object.name}": missing recipient data in message object \n${messageParams}`);
return;
}
const currentDateMs = Date.now();
if (data.repeatDate <= currentDateMs) {
data.repeatDate = currentDateMs + intervalMilliseconds;
const message = object.transport.contentGeneration(cfgLicenseExpired.template, messageParams);
object.transport.send(message);
}
});
async function notifyRule(ctx, tenRule, messageParams) {
const transportObjects = tenRule.transportType.map(transport => new Transport(ctx, transport));
for (const transportObject of transportObjects) {
const message = transportObject.transport.contentGeneration(tenRule.template, messageParams);
await transportObject.transport.send(ctx, message);
}
}
module.exports = {

View File

@ -101,6 +101,7 @@ const wopiClient = require('./wopiClient');
const queueService = require('./../../Common/sources/taskqueueRabbitMQ');
const operationContext = require('./../../Common/sources/operationContext');
const tenantManager = require('./../../Common/sources/tenantManager');
const notificationService = require('../../Common/sources/notificationService');
const cfgEditorDataStorage = config.get('services.CoAuthoring.server.editorDataStorage');
const cfgEditorStatStorage = config.get('services.CoAuthoring.server.editorStatStorage');
@ -3479,40 +3480,55 @@ exports.install = function(server, callbackFunction) {
}
}
let logPostfix = ' limit exceeded!!!';
let notificationPrefix;
if (c_LR.UsersCount === licenseType) {
if (!licenseInfo.hasLicense) {
licenseType = c_LR.UsersCountOS;
}
ctx.logger.error(logPrefix + 'User limit exceeded!!!');
notificationPrefix = logPrefix + 'User';
ctx.logger.error(notificationPrefix + logPostfix);
} else if (c_LR.UsersViewCount === licenseType) {
if (!licenseInfo.hasLicense) {
licenseType = c_LR.UsersViewCountOS;
}
ctx.logger.error(logPrefix + 'User Live Viewer limit exceeded!!!');
if (!licenseInfo.hasLicense) {
licenseType = c_LR.UsersViewCountOS;
}
notificationPrefix = logPrefix + 'User Live Viewer';
ctx.logger.error(notificationPrefix + logPostfix);
} else if (c_LR.Connections === licenseType) {
if (!licenseInfo.hasLicense) {
licenseType = c_LR.ConnectionsOS;
}
ctx.logger.error(logPrefix + 'Connection limit exceeded!!!');
notificationPrefix = logPrefix + 'Connection';
ctx.logger.error(notificationPrefix + logPostfix);
} else if (c_LR.ConnectionsLive === licenseType) {
if (!licenseInfo.hasLicense) {
licenseType = c_LR.ConnectionsLiveOS;
}
ctx.logger.error(logPrefix + 'Connection Live Viewer limit exceeded!!!');
notificationPrefix = logPrefix + 'Connection Live Viewer';
ctx.logger.error(notificationPrefix + logPostfix);
} else {
if (licenseWarningLimitUsers) {
ctx.logger.warn(logPrefix + 'Warning User limit exceeded!!!');
notificationPrefix = logPrefix + 'Warning User';
ctx.logger.warn(notificationPrefix + logPostfix);
}
if (licenseWarningLimitUsersView) {
ctx.logger.warn(logPrefix + 'Warning User Live Viewer limit exceeded!!!');
notificationPrefix = logPrefix + 'Warning User Live Viewer';
ctx.logger.warn(notificationPrefix + logPostfix);
}
if (licenseWarningLimitConnections) {
ctx.logger.warn(logPrefix + 'Warning Connection limit exceeded!!!');
notificationPrefix = logPrefix + 'Warning Connection';
ctx.logger.warn(notificationPrefix + logPostfix);
}
if (licenseWarningLimitConnectionsLive) {
ctx.logger.warn(logPrefix + 'Warning Connection Live Viewer limit exceeded!!!');
notificationPrefix = logPrefix + 'Warning Connection Live Viewer';
ctx.logger.warn(notificationPrefix + logPostfix);
}
}
if (notificationPrefix) {
//todo with yield service could throw error
notificationService.notify(ctx, notificationService.notificationTypes.LICENSE_LIMIT, [notificationPrefix]);
}
return licenseType;
}