Skip to content

Commit

Permalink
[bug] Change license notification message; For bug 70325
Browse files Browse the repository at this point in the history
  • Loading branch information
konovalovsergey committed Oct 1, 2024
1 parent c3aa709 commit eb2077c
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 94 deletions.
9 changes: 5 additions & 4 deletions Common/config/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,9 @@
"email"
],
"template": {
"title": "License expiration",
"body": "%s license %s on %s!!!"
"title": "License expiration warning",
"bodyWarn": "Attention! Your license is about to expire on %s.\nUpon reaching this date, you will no longer be entitled to receive personal technical support and install new Docs versions released after this date.",
"bodyError": "Attention! Your license expired on %s.\nYou are no longer entitled to receive personal technical support and install new Docs versions released after this date.\nPlease contact sales@onlyoffice.com to discuss license renewal."
},
"policies": {
"repeatInterval": "1d"
Expand All @@ -54,8 +55,8 @@
"email"
],
"template": {
"title": "License limit",
"body": "%s limit exceeded!!!"
"title": "License connection limit warning",
"body": "Attention! You have reached %s%% of the %s limit set by your license."
},
"policies": {
"repeatInterval": "1h"
Expand Down
16 changes: 8 additions & 8 deletions Common/sources/notificationService.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const notificationTypes = {

class TransportInterface {
async send(ctx, message) {}
contentGeneration(template, messageParams) {}
contentGeneration(template, message) {}
}

class MailTransport extends TransportInterface {
Expand All @@ -71,10 +71,10 @@ class MailTransport extends TransportInterface {
return mailService.send(this.host, this.auth.user, message);
}

contentGeneration(template, messageParams) {
contentGeneration(template, message) {
return {
subject: template.title,
text: util.format(template.body, ...messageParams)
text: message
};
}
}
Expand Down Expand Up @@ -105,7 +105,7 @@ class Transport {
}
}

async function notify(ctx, notificationType, messageParams) {
async function notify(ctx, notificationType, message) {
const tenNotificationEnable = ctx.getCfg('notification.enable', cfgNotificationEnable);
if (!tenNotificationEnable) {
return;
Expand All @@ -116,7 +116,7 @@ async function notify(ctx, notificationType, messageParams) {
if (tenRule) {
let checkRes = await checkRulePolicies(ctx, notificationType, tenRule);
if (checkRes) {
await notifyRule(ctx, tenRule, messageParams);
await notifyRule(ctx, tenRule, message);
}
}
}
Expand All @@ -136,12 +136,12 @@ async function checkRulePolicies(ctx, notificationType, tenRule) {
return isLock;
}

async function notifyRule(ctx, tenRule, messageParams) {
async function notifyRule(ctx, tenRule, message) {
const transportObjects = tenRule.transportType.map(transport => new Transport(ctx, transport));
for (const transportObject of transportObjects) {
try {
const message = transportObject.transport.contentGeneration(tenRule.template, messageParams);
await transportObject.transport.send(ctx, message);
const mail = transportObject.transport.contentGeneration(tenRule.template, message);
await transportObject.transport.send(ctx, mail);
} catch (error) {
ctx.logger.error('Notification service: error: %s', error.stack);
}
Expand Down
122 changes: 45 additions & 77 deletions DocService/sources/DocsCoServer.js
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ const cfgEditorDataStorage = config.get('services.CoAuthoring.server.editorDataS
const cfgEditorStatStorage = config.get('services.CoAuthoring.server.editorStatStorage');
const editorDataStorage = require('./' + cfgEditorDataStorage);
const editorStatStorage = require('./' + (cfgEditorStatStorage || cfgEditorDataStorage));
const util = require("util");

const cfgEditSingleton = config.get('services.CoAuthoring.server.edit_singleton');
const cfgEditor = config.get('services.CoAuthoring.editor');
Expand Down Expand Up @@ -137,6 +138,7 @@ const cfgForgottenFiles = config.get('services.CoAuthoring.server.forgottenfiles
const cfgForgottenFilesName = config.get('services.CoAuthoring.server.forgottenfilesname');
const cfgMaxRequestChanges = config.get('services.CoAuthoring.server.maxRequestChanges');
const cfgWarningLimitPercents = config.get('license.warning_limit_percents');
const cfgNotificationRuleLicenseLimit = config.get('notification.rules.licenseLimit.template.body');
const cfgErrorFiles = config.get('FileConverter.converter.errorfiles');
const cfgOpenProtectedFile = config.get('services.CoAuthoring.server.openProtectedFile');
const cfgIsAnonymousSupport = config.get('services.CoAuthoring.server.isAnonymousSupport');
Expand Down Expand Up @@ -2664,19 +2666,15 @@ exports.install = function(server, callbackFunction) {
conn.licenseType = c_LR.Success;
let isLiveViewer = utils.isLiveViewer(conn);
if (!conn.user.view || isLiveViewer) {
let logPrefixTenant = 'License of tenant: ';
let logPrefixServer = 'License: ';
let logPrefix = tenantManager.isMultitenantMode(ctx) ? logPrefixTenant : logPrefixServer;

let licenseType = yield* _checkLicenseAuth(ctx, licenseInfo, conn.user.idOriginal, isLiveViewer, logPrefix);
let licenseType = yield* _checkLicenseAuth(ctx, licenseInfo, conn.user.idOriginal, isLiveViewer);
let aggregationCtx, licenseInfoAggregation;
if ((c_LR.Success === licenseType || c_LR.SuccessLimit === licenseType) && tenantManager.isMultitenantMode(ctx) && !tenantManager.isDefaultTenant(ctx)) {
//check server aggregation license
aggregationCtx = new operationContext.Context();
aggregationCtx.init(tenantManager.getDefautTenant(), ctx.docId, ctx.userId);
//yield ctx.initTenantCache(); //no need
licenseInfoAggregation = tenantManager.getServerLicense();
licenseType = yield* _checkLicenseAuth(aggregationCtx, licenseInfoAggregation, `${ctx.tenant}:${ conn.user.idOriginal}`, isLiveViewer, logPrefixServer);
licenseType = yield* _checkLicenseAuth(aggregationCtx, licenseInfoAggregation, `${ctx.tenant}:${ conn.user.idOriginal}`, isLiveViewer);
}
conn.licenseType = licenseType;
if ((c_LR.Success !== licenseType && c_LR.SuccessLimit !== licenseType) || (!tenIsAnonymousSupport && data.IsAnonymousUser)) {
Expand Down Expand Up @@ -3479,97 +3477,67 @@ exports.install = function(server, callbackFunction) {
});
}

function* _checkLicenseAuth(ctx, licenseInfo, userId, isLiveViewer, logPrefix) {
function* _checkLicenseAuth(ctx, licenseInfo, userId, isLiveViewer) {
const tenWarningLimitPercents = ctx.getCfg('license.warning_limit_percents', cfgWarningLimitPercents) / 100;

let licenseWarningLimitUsers = false;
let licenseWarningLimitUsersView = false;
let licenseWarningLimitConnections = false;
let licenseWarningLimitConnectionsLive = false;
const tenNotificationRuleLicenseLimit = ctx.getCfg(`notification.rules.licenseLimit.template.body`, cfgNotificationRuleLicenseLimit);
const c_LR = constants.LICENSE_RESULT;
let licenseType = licenseInfo.type;
if (c_LR.Success === licenseType || c_LR.SuccessLimit === licenseType) {
let notificationLimit;
let notificationPercent = 0;
if (licenseInfo.usersCount) {
const nowUTC = getLicenseNowUtc();
if(isLiveViewer) {
const arrUsers = yield editorStat.getPresenceUniqueViewUser(ctx, nowUTC);
if (arrUsers.length >= licenseInfo.usersViewCount && (-1 === arrUsers.findIndex((element) => {return element.userid === userId}))) {
licenseType = c_LR.UsersViewCount;
licenseType = licenseInfo.hasLicense ? c_LR.UsersViewCount : c_LR.UsersViewCountOS;
} else if (licenseInfo.usersViewCount * tenWarningLimitPercents <= arrUsers.length) {
notificationPercent = tenWarningLimitPercents * 100;
}
licenseWarningLimitUsersView = licenseInfo.usersViewCount * tenWarningLimitPercents <= arrUsers.length;
notificationLimit = 'live viewer users';
} else {
const arrUsers = yield editorStat.getPresenceUniqueUser(ctx, nowUTC);
if (arrUsers.length >= licenseInfo.usersCount && (-1 === arrUsers.findIndex((element) => {return element.userid === userId}))) {
licenseType = c_LR.UsersCount;
licenseType = licenseInfo.hasLicense ? c_LR.UsersCount : c_LR.UsersCountOS;
} else if(licenseInfo.usersCount * tenWarningLimitPercents <= arrUsers.length) {
notificationPercent = tenWarningLimitPercents * 100;
}
licenseWarningLimitUsers = licenseInfo.usersCount * tenWarningLimitPercents <= arrUsers.length;
}
} else if(isLiveViewer) {
const connectionsLiveCount = licenseInfo.connectionsView;
const liveViewerConnectionsCount = yield editorStat.getLiveViewerConnectionsCount(ctx, connections);
if (liveViewerConnectionsCount >= connectionsLiveCount) {
licenseType = c_LR.ConnectionsLive;
notificationLimit = 'users';
}
licenseWarningLimitConnectionsLive = connectionsLiveCount * tenWarningLimitPercents <= liveViewerConnectionsCount;
} else {
const connectionsCount = licenseInfo.connections;
const editConnectionsCount = yield editorStat.getEditorConnectionsCount(ctx, connections);
if (editConnectionsCount >= connectionsCount) {
licenseType = c_LR.Connections;
if (isLiveViewer) {
const connectionsLiveCount = licenseInfo.connectionsView;
const liveViewerConnectionsCount = yield editorStat.getLiveViewerConnectionsCount(ctx, connections);
if (liveViewerConnectionsCount >= connectionsLiveCount) {
licenseType = licenseInfo.hasLicense ? c_LR.ConnectionsLive : c_LR.ConnectionsLiveOS;
} else if(connectionsLiveCount * tenWarningLimitPercents <= liveViewerConnectionsCount){
notificationPercent = tenWarningLimitPercents * 100;
}
notificationLimit = 'live viewer connections';
} else {
const connectionsCount = licenseInfo.connections;
const editConnectionsCount = yield editorStat.getEditorConnectionsCount(ctx, connections);
if (editConnectionsCount >= connectionsCount) {
licenseType = licenseInfo.hasLicense ? c_LR.Connections : c_LR.ConnectionsOS;
} else if (connectionsCount * tenWarningLimitPercents <= editConnectionsCount) {
notificationPercent = tenWarningLimitPercents * 100;
}
notificationLimit = 'connections';
}
licenseWarningLimitConnections = connectionsCount * tenWarningLimitPercents <= editConnectionsCount;
}
}

let logPostfix = ' limit exceeded!!!';
let notificationPrefix;
if (c_LR.UsersCount === licenseType) {
if (!licenseInfo.hasLicense) {
licenseType = c_LR.UsersCountOS;
}
notificationPrefix = logPrefix + 'User';
ctx.logger.error(notificationPrefix + logPostfix);
} else if (c_LR.UsersViewCount === licenseType) {
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;
}
notificationPrefix = logPrefix + 'Connection';
ctx.logger.error(notificationPrefix + logPostfix);
} else if (c_LR.ConnectionsLive === licenseType) {
if (!licenseInfo.hasLicense) {
licenseType = c_LR.ConnectionsLiveOS;
}
notificationPrefix = logPrefix + 'Connection Live Viewer';
ctx.logger.error(notificationPrefix + logPostfix);
} else {
if (licenseWarningLimitUsers) {
notificationPrefix = logPrefix + 'Warning User';
ctx.logger.warn(notificationPrefix + logPostfix);
}
if (licenseWarningLimitUsersView) {
notificationPrefix = logPrefix + 'Warning User Live Viewer';
ctx.logger.warn(notificationPrefix + logPostfix);
}
if (licenseWarningLimitConnections) {
notificationPrefix = logPrefix + 'Warning Connection';
ctx.logger.warn(notificationPrefix + logPostfix);
}
if (licenseWarningLimitConnectionsLive) {
notificationPrefix = logPrefix + 'Warning Connection Live Viewer';
ctx.logger.warn(notificationPrefix + logPostfix);
if ((c_LR.Success !== licenseType && c_LR.SuccessLimit !== licenseType) || notificationPercent > 0) {
let message;
if (notificationPercent > 0) {
message = util.format(tenNotificationRuleLicenseLimit, notificationPercent, notificationLimit);
ctx.logger.warn(tenNotificationRuleLicenseLimit, notificationPercent, notificationLimit);
} else {
message = util.format(tenNotificationRuleLicenseLimit, 100, notificationLimit);
ctx.logger.error(tenNotificationRuleLicenseLimit, 100, notificationLimit);
}
//todo with yield service could throw error
void notificationService.notify(ctx, notificationTypes.LICENSE_LIMIT, message);
}
}

if (notificationPrefix) {
//todo with yield service could throw error
notificationService.notify(ctx, notificationTypes.LICENSE_LIMIT, [notificationPrefix]);
}
return licenseType;
}

Expand Down
17 changes: 12 additions & 5 deletions DocService/sources/utilsDocService.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@

'use strict';

const util = require("util");
const config = require('config');
const exifParser = require('exif-parser');
const Jimp = require('jimp');
Expand All @@ -42,6 +43,8 @@ const tenantManager = require('../../Common/sources/tenantManager');
const { notificationTypes, ...notificationService } = require('../../Common/sources/notificationService');

const cfgStartNotifyFrom = ms(config.get('license.warning_license_expiration'));
const cfgNotificationRuleLicenseExpirationWarning = config.get('notification.rules.licenseExpirationWarning.template.bodyWarn');
const cfgNotificationRuleLicenseExpirationError = config.get('notification.rules.licenseExpirationWarning.template.bodyError');

async function fixImageExifRotation(ctx, buffer) {
if (!buffer) {
Expand Down Expand Up @@ -123,11 +126,15 @@ async function notifyLicenseExpiration(ctx, endDate) {
const currentDate = new Date();
if (currentDate.getTime() >= endDate.getTime() - cfgStartNotifyFrom) {
const formattedExpirationTime = humanFriendlyExpirationTime(endDate);
const tenant = tenantManager.isDefaultTenant(ctx) ? 'server' : ctx.tenant;

const state = endDate < currentDate ? 'expired' : 'expires';
ctx.logger.warn('%s license %s on %s!!!', tenant, state, formattedExpirationTime);
await notificationService.notify(ctx, notificationTypes.LICENSE_EXPIRATION_WARNING, [tenant, state, formattedExpirationTime]);
//todo one body template
let message;
if (endDate < currentDate) {
message = util.format(cfgNotificationRuleLicenseExpirationError, formattedExpirationTime);
} else {
message = util.format(cfgNotificationRuleLicenseExpirationWarning, formattedExpirationTime);
}
ctx.logger.warn(message);
await notificationService.notify(ctx, notificationTypes.LICENSE_EXPIRATION_WARNING, message);
}
}

Expand Down

0 comments on commit eb2077c

Please sign in to comment.