Merge pull request 'fix/admin-panel-bugs-5' (#76) from fix/admin-panel-bugs-5 into release/v9.1.0

Reviewed-on: https://git.onlyoffice.com/ONLYOFFICE/server/pulls/76
This commit is contained in:
Oleg Korshul
2025-10-10 19:45:35 +00:00
5 changed files with 37 additions and 16 deletions

View File

@ -38,6 +38,8 @@ const mailService = require('./mailService');
const cfgEditorDataStorage = config.get('services.CoAuthoring.server.editorDataStorage');
const cfgEditorStatStorage = config.get('services.CoAuthoring.server.editorStatStorage');
const cfgSmtpServerConfiguration = config.get('email.smtpServerConfiguration');
const cfgContactDefaults = config.get('email.contactDefaults');
const editorStatStorage = require('./../../DocService/sources/' + (cfgEditorStatStorage || cfgEditorDataStorage));
const editorStat = editorStatStorage.EditorStat ? new editorStatStorage.EditorStat() : new editorStatStorage();
@ -57,11 +59,11 @@ class MailTransport extends TransportInterface {
constructor(ctx) {
super();
const mailServerConfig = ctx.getCfg('email.smtpServerConfiguration');
const mailServerConfig = ctx.getCfg('email.smtpServerConfiguration', cfgSmtpServerConfiguration);
this.host = mailServerConfig.host;
this.port = mailServerConfig.port;
this.auth = mailServerConfig.auth;
const cfgMailMessageDefaults = ctx.getCfg('email.contactDefaults');
const cfgMailMessageDefaults = ctx.getCfg('email.contactDefaults', cfgContactDefaults);
mailService.createTransporter(ctx, this.host, this.port, this.auth, cfgMailMessageDefaults);
}

View File

@ -4695,6 +4695,15 @@ exports.shutdown = function (req, res) {
}
});
};
/**
* Get active connections array
* @returns {Array} Active connections
*/
function getConnections() {
return connections;
}
exports.getConnections = getConnections;
exports.getEditorConnectionsCount = function (req, res) {
const ctx = new operationContext.Context();
let count = 0;

View File

@ -353,10 +353,13 @@ async function getPluginSettingsForInterface(ctx) {
pluginSettings = undefined;
}
}
//remove keys from providers
if (pluginSettings && pluginSettings.providers) {
//remove keys from providers - create deep copy to avoid modifying cached config
if (pluginSettings?.providers) {
for (const key in pluginSettings.providers) {
pluginSettings.providers[key].key = '';
if (pluginSettings.providers[key]?.key) {
pluginSettings.providers[key] = JSON.parse(JSON.stringify(pluginSettings.providers[key]));
pluginSettings.providers[key].key = '';
}
}
}
return pluginSettings;

View File

@ -54,8 +54,9 @@ function getLicenseNowUtc() {
* License info endpoint handler
* @param {import('express').Request} req Express request
* @param {import('express').Response} res Express response
* @param {Function} getConnections Function to get active connections
*/
async function licenseInfo(req, res) {
async function licenseInfo(req, res, getConnections = null) {
let isError = false;
const serverDate = new Date();
// Security risk of high-precision time
@ -174,7 +175,8 @@ async function licenseInfo(req, res) {
const nowUTC = getLicenseNowUtc();
let execRes;
execRes = await editorStat.getPresenceUniqueUser(ctx, nowUTC);
output.quota.edit.connectionsCount = await editorStat.getEditorConnectionsCount(ctx, {});
const connections = getConnections ? getConnections() : null;
output.quota.edit.connectionsCount = await editorStat.getEditorConnectionsCount(ctx, connections);
output.quota.edit.usersCount.unique = execRes.length;
execRes.forEach(elem => {
if (elem.anonym) {
@ -183,7 +185,7 @@ async function licenseInfo(req, res) {
});
execRes = await editorStat.getPresenceUniqueViewUser(ctx, nowUTC);
output.quota.view.connectionsCount = await editorStat.getLiveViewerConnectionsCount(ctx, {});
output.quota.view.connectionsCount = await editorStat.getLiveViewerConnectionsCount(ctx, connections);
output.quota.view.usersCount.unique = execRes.length;
execRes.forEach(elem => {
if (elem.anonym) {
@ -218,24 +220,29 @@ async function licenseInfo(req, res) {
isError = true;
ctx.logger.error('licenseInfo error %s', err.stack);
} finally {
if (!isError) {
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify(output));
} else {
res.sendStatus(400);
if (!res.headersSent) {
if (!isError) {
res.setHeader('Content-Type', 'application/json');
res.send(JSON.stringify(output));
} else {
res.sendStatus(400);
}
}
}
}
/**
* Create shared Info router
* @param {Function} getConnections Optional function to get active connections
* @returns {import('express').Router} Router instance
*/
function createInfoRouter() {
function createInfoRouter(getConnections = null) {
const router = express.Router();
// License info endpoint with CORS and client IP check
router.get('/info.json', cors(), utils.checkClientIp, licenseInfo);
router.get('/info.json', cors(), utils.checkClientIp, async (req, res) => {
await licenseInfo(req, res, getConnections);
});
return router;
}

View File

@ -295,7 +295,7 @@ docsCoServer.install(server, app, () => {
converterService.builder(req, res);
});
// Shared Info router (provides /info.json)
app.use('/info', infoRouter());
app.use('/info', infoRouter(docsCoServer.getConnections));
app.put('/internal/cluster/inactive', utils.checkClientIp, docsCoServer.shutdown);
app.delete('/internal/cluster/inactive', utils.checkClientIp, docsCoServer.shutdown);
app.get('/internal/connections/edit', docsCoServer.getEditorConnectionsCount);