diff --git a/AdminPanel/client/public/index.html b/AdminPanel/client/public/index.html index 9ae0a010..8352f721 100644 --- a/AdminPanel/client/public/index.html +++ b/AdminPanel/client/public/index.html @@ -6,7 +6,7 @@ - ONLIOFFICE Admin + ONLYOFFICE Admin diff --git a/AdminPanel/client/src/api/index.js b/AdminPanel/client/src/api/index.js index e9867873..1cddad45 100644 --- a/AdminPanel/client/src/api/index.js +++ b/AdminPanel/client/src/api/index.js @@ -62,9 +62,12 @@ export const updateConfiguration = async configData => { export const fetchCurrentUser = async () => { const response = await safeFetch(`${BACKEND_URL}${API_BASE_PATH}/me`, {credentials: 'include'}); - if (response.status === 401) throw new Error('Unauthorized'); if (!response.ok) throw new Error('Failed to fetch current user'); - return response.json(); + const data = await response.json(); + if (data && data.authorized === false) { + throw new Error('Unauthorized'); + } + return data; }; export const checkSetupRequired = async () => { diff --git a/AdminPanel/client/src/pages/AiIntegration/hooks/useAiPlugin.js b/AdminPanel/client/src/pages/AiIntegration/hooks/useAiPlugin.js index a25e9104..88d11f3c 100644 --- a/AdminPanel/client/src/pages/AiIntegration/hooks/useAiPlugin.js +++ b/AdminPanel/client/src/pages/AiIntegration/hooks/useAiPlugin.js @@ -29,7 +29,6 @@ const useAiPlugin = statisticsData => { } initAISettings(iframeId, sdkVersion); - console.log('AI Settings initialized with version:', sdkVersion); }, [statisticsData] ); @@ -50,7 +49,6 @@ const useAiPlugin = statisticsData => { return () => { localStorage.removeItem('onlyoffice_ai_actions_key'); localStorage.removeItem('onlyoffice_ai_plugin_storage_key'); - console.log('AI configuration cleared from localStorage'); }; }, [config?.aiSettings]); @@ -62,7 +60,6 @@ const useAiPlugin = statisticsData => { * @param {Object} config - Window configuration */ const handleShowWindow = (iframeId, config) => { - console.log('showPluginWindow', iframeId, config); setPluginWindows(current => { // Avoid duplicate windows with same iframeId const filtered = current.filter(w => w.iframeId !== iframeId); @@ -118,9 +115,6 @@ const useAiPlugin = statisticsData => { // Save configuration using Redux action dispatch(saveConfig(configToSave)); - console.log('AI configuration saved successfully', updatedAiSettings); - } else { - console.log('No AI configuration found in localStorage'); } } catch (error) { console.error('Error saving AI configuration:', error); diff --git a/AdminPanel/client/src/pages/RequestFiltering/RequestFiltering.js b/AdminPanel/client/src/pages/RequestFiltering/RequestFiltering.js index f9313aad..f9050987 100644 --- a/AdminPanel/client/src/pages/RequestFiltering/RequestFiltering.js +++ b/AdminPanel/client/src/pages/RequestFiltering/RequestFiltering.js @@ -23,8 +23,8 @@ function RequestFiltering() { // Configuration paths const CONFIG_PATHS = { - allowPrivateIPAddress: 'request-filtering-agent.allowPrivateIPAddress', - allowMetaIPAddress: 'request-filtering-agent.allowMetaIPAddress' + allowPrivateIPAddress: 'services.CoAuthoring.request-filtering-agent.allowPrivateIPAddress', + allowMetaIPAddress: 'services.CoAuthoring.request-filtering-agent.allowMetaIPAddress' }; const hasInitialized = useRef(false); diff --git a/AdminPanel/client/src/pages/Setup/styles.module.css b/AdminPanel/client/src/pages/Setup/styles.module.css index 28e51e59..0faf996e 100644 --- a/AdminPanel/client/src/pages/Setup/styles.module.css +++ b/AdminPanel/client/src/pages/Setup/styles.module.css @@ -13,6 +13,9 @@ width: 100%; max-width: 500px; text-align: center; + display: flex; + flex-direction: column; + align-items: center; } .title { diff --git a/AdminPanel/server/sources/jwtSecret.js b/AdminPanel/server/sources/jwtSecret.js new file mode 100644 index 00000000..9cf09be2 --- /dev/null +++ b/AdminPanel/server/sources/jwtSecret.js @@ -0,0 +1,12 @@ +'use strict'; + +const crypto = require('crypto'); + +//todo Need common secret in case of cluster deployment +// const config = require('config'); +// const adminPanelJwtSecret = config.get('adminPanel.secret'); + +// Generate random JWT secret once for cluster deployment +const adminPanelJwtSecret = crypto.randomBytes(64).toString('hex'); + +module.exports = adminPanelJwtSecret; diff --git a/AdminPanel/server/sources/middleware/auth.js b/AdminPanel/server/sources/middleware/auth.js index b34a30af..4104511b 100644 --- a/AdminPanel/server/sources/middleware/auth.js +++ b/AdminPanel/server/sources/middleware/auth.js @@ -1,10 +1,8 @@ 'use strict'; -const config = require('config'); const jwt = require('jsonwebtoken'); const operationContext = require('../../../../Common/sources/operationContext'); - -const adminPanelJwtSecret = config.get('adminPanel.secret'); +const adminPanelJwtSecret = require('../jwtSecret'); /** * JWT Authentication Middleware diff --git a/AdminPanel/server/sources/routes/adminpanel/router.js b/AdminPanel/server/sources/routes/adminpanel/router.js index bbdffa8b..4f0d1410 100644 --- a/AdminPanel/server/sources/routes/adminpanel/router.js +++ b/AdminPanel/server/sources/routes/adminpanel/router.js @@ -1,13 +1,11 @@ 'use strict'; -const config = require('config'); const express = require('express'); const jwt = require('jsonwebtoken'); const cookieParser = require('cookie-parser'); const operationContext = require('../../../../../Common/sources/operationContext'); const passwordManager = require('../../passwordManager'); const bootstrap = require('../../bootstrap'); - -const adminPanelJwtSecret = config.get('adminPanel.secret'); +const adminPanelJwtSecret = require('../../jwtSecret'); const router = express.Router(); @@ -170,8 +168,17 @@ router.post('/change-password', requireAuth, async (req, res) => { } }); -router.get('/me', requireAuth, (req, res) => { - res.json(req.user); +router.get('/me', (req, res) => { + try { + const token = req.cookies?.accessToken; + if (!token) { + return res.json({authorized: false}); + } + const decoded = jwt.verify(token, adminPanelJwtSecret); + return res.json({authorized: true, ...decoded}); + } catch { + return res.json({authorized: false}); + } }); router.post('/login', async (req, res) => { diff --git a/Common/config/default.json b/Common/config/default.json index bbc483b8..31526446 100644 --- a/Common/config/default.json +++ b/Common/config/default.json @@ -1,6 +1,5 @@ { "adminPanel": { - "secret": "secret", "port": 9000 }, "statsd": { diff --git a/Common/config/schemas/config.schema.json b/Common/config/schemas/config.schema.json index 2edb94f6..fd1295db 100644 --- a/Common/config/schemas/config.schema.json +++ b/Common/config/schemas/config.schema.json @@ -87,6 +87,21 @@ "sessionabsolute": {"type": "string", "x-scope": ["admin", "tenant"]} } }, + "request-filtering-agent": { + "type": "object", + "additionalProperties": false, + "x-scope": ["admin", "tenant"], + "properties": { + "allowPrivateIPAddress": { + "type": "boolean", + "description": "Whether to allow requests from private IP addresses" + }, + "allowMetaIPAddress": { + "type": "boolean", + "description": "Whether to allow requests from meta IP addresses" + } + } + }, "autoAssembly": { "type": "object", "additionalProperties": false, @@ -165,21 +180,6 @@ } } }, - "request-filtering-agent": { - "type": "object", - "additionalProperties": false, - "x-scope": ["admin", "tenant"], - "properties": { - "allowPrivateIPAddress": { - "type": "boolean", - "description": "Whether to allow requests from private IP addresses" - }, - "allowMetaIPAddress": { - "type": "boolean", - "description": "Whether to allow requests from meta IP addresses" - } - } - }, "FileConverter": { "type": "object", "additionalProperties": false, diff --git a/DocService/sources/canvasservice.js b/DocService/sources/canvasservice.js index 71ce3e42..5a1815fe 100644 --- a/DocService/sources/canvasservice.js +++ b/DocService/sources/canvasservice.js @@ -303,6 +303,28 @@ async function getOutputData(ctx, cmd, outputData, key, optConn, optAdditionalOu //this status has no handler break; case commonDefines.FileStatus.WaitQueue: + { + const timeout = await utils.getConvertionTimeout(ctx); + console.log(timeout); + console.log(statusInfo); + console.log(Date.now() - statusInfo * 60000); + console.log(Date.now() - statusInfo * 60000 > timeout); + if (Date.now() - statusInfo * 60000 > timeout) { + ctx.logger.warn('WaitQueue expired'); + const updateMask = new taskResult.TaskResultData(); + updateMask.tenant = ctx.tenant; + updateMask.key = key; + updateMask.status = status; + updateMask.statusInfo = statusInfo; + const updateTask = new taskResult.TaskResultData(); + updateTask.status = commonDefines.FileStatus.None; + updateTask.statusInfo = constants.NO_ERROR; + const updateIfRes = await taskResult.updateIf(ctx, updateTask, updateMask); + if (updateIfRes.affectedRows > 0) { + status = commonDefines.FileStatus.None; + } + } + } //task in the queue. response will be after convertion break; default: @@ -514,7 +536,7 @@ function* commandOpen(ctx, conn, cmd, outputData, opt_upsertRes, opt_bIsRestore) const task = new taskResult.TaskResultData(); task.status = commonDefines.FileStatus.WaitQueue; - task.statusInfo = constants.NO_ERROR; + task.statusInfo = Math.floor(Date.now() / 60000); //minutes const updateIfRes = yield taskResult.updateIf(ctx, task, updateMask); if (updateIfRes.affectedRows > 0) { @@ -570,7 +592,7 @@ function* commandReopen(ctx, conn, cmd, outputData) { const task = new taskResult.TaskResultData(); task.status = commonDefines.FileStatus.WaitQueue; - task.statusInfo = constants.NO_ERROR; + task.statusInfo = Math.floor(Date.now() / 60000); //minutes const upsertRes = yield taskResult.updateIf(ctx, task, updateMask); if (upsertRes.affectedRows > 0) { diff --git a/DocService/sources/converterservice.js b/DocService/sources/converterservice.js index 54b2b02c..385273d3 100644 --- a/DocService/sources/converterservice.js +++ b/DocService/sources/converterservice.js @@ -137,7 +137,7 @@ function* convertByCmd(ctx, cmd, async, opt_fileTo, opt_taskExist, opt_priority, task.tenant = ctx.tenant; task.key = docId; task.status = commonDefines.FileStatus.WaitQueue; - task.statusInfo = constants.NO_ERROR; + task.statusInfo = Math.floor(Date.now() / 60000); //minutes const upsertRes = yield taskResult.upsert(ctx, task); bCreate = upsertRes.isInsert; diff --git a/DocService/sources/taskresult.js b/DocService/sources/taskresult.js index 46f84a4c..22c75a35 100644 --- a/DocService/sources/taskresult.js +++ b/DocService/sources/taskresult.js @@ -297,6 +297,7 @@ function* addRandomKeyTask(ctx, key, opt_prefix, opt_size) { task.tenant = ctx.tenant; task.key = key; task.status = commonDefines.FileStatus.WaitQueue; + task.statusInfo = Math.floor(Date.now() / 60000); //minutes //nTryCount so as not to freeze if there are really problems with the DB let nTryCount = RANDOM_KEY_MAX; let addRes = null;