From 869ebd0a93c71f24e27286aeb79b3c1f0e2a94de Mon Sep 17 00:00:00 2001 From: PauI Ostrovckij Date: Thu, 9 Oct 2025 15:50:39 +0300 Subject: [PATCH 1/5] [bug] Fix rotate wopi keys; for bug 76979 --- AdminPanel/server/sources/routes/wopi/router.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/AdminPanel/server/sources/routes/wopi/router.js b/AdminPanel/server/sources/routes/wopi/router.js index 85e9b797..3b5392ab 100644 --- a/AdminPanel/server/sources/routes/wopi/router.js +++ b/AdminPanel/server/sources/routes/wopi/router.js @@ -38,7 +38,7 @@ const utils = require('../../../../../Common/sources/utils'); const runtimeConfigManager = require('../../../../../Common/sources/runtimeConfigManager'); const tenantManager = require('../../../../../Common/sources/tenantManager'); const {validateJWT} = require('../../middleware/auth'); -const {getScopedConfig} = require('../config/config.service'); +const {getConfig} = require('../../../../../Common/sources/runtimeConfigManager'); const cookieParser = require('cookie-parser'); const router = express.Router(); @@ -156,8 +156,8 @@ router.post('/rotate-keys', validateJWT, express.json(), async (req, res) => { try { ctx.logger.info('WOPI key rotation start'); - const currentConfig = ctx.getFullCfg(); - const wopiConfig = utils.getImpl(currentConfig, 'wopi') || {}; + const currentConfig = await getConfig(ctx); + const wopiConfig = currentConfig.wopi || {}; const newWopiConfig = generateWopiKeys(); @@ -184,9 +184,7 @@ router.post('/rotate-keys', validateJWT, express.json(), async (req, res) => { await runtimeConfigManager.saveConfig(ctx, newConfig); } - await ctx.initTenantCache(); - const filteredConfig = getScopedConfig(ctx); - res.status(200).json(filteredConfig); + res.status(200).json(newConfig); } catch (error) { ctx.logger.error('WOPI key rotation error: %s', error.stack); res.status(500).json({ From 024bdf2e600783607fde409f187ccb79b09ca370 Mon Sep 17 00:00:00 2001 From: PauI Ostrovckij Date: Thu, 9 Oct 2025 16:06:20 +0300 Subject: [PATCH 2/5] [fix] Remove race condition in response config --- AdminPanel/server/sources/routes/config/router.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/AdminPanel/server/sources/routes/config/router.js b/AdminPanel/server/sources/routes/config/router.js index e33248ac..9a0c586c 100644 --- a/AdminPanel/server/sources/routes/config/router.js +++ b/AdminPanel/server/sources/routes/config/router.js @@ -67,9 +67,9 @@ router.patch('/', validateJWT, rawFileParser, async (req, res) => { await runtimeConfigManager.saveConfig(ctx, validationResult.value); } - await ctx.initTenantCache(); - const filteredConfig = getScopedConfig(ctx); - res.status(200).json(filteredConfig); + const newConfig = await runtimeConfigManager.getConfig(ctx); + + res.status(200).json(newConfig); } catch (error) { ctx.logger.error('Configuration save error: %s', error.stack); res.status(500).json({error: 'Internal server error', details: error.message}); From 8a9c901c900f376fca8d13f3a6604e08d5dc20a3 Mon Sep 17 00:00:00 2001 From: PauI Ostrovckij Date: Thu, 9 Oct 2025 19:47:36 +0300 Subject: [PATCH 3/5] [bug] Refactor routing; For bug 77260 --- .../src/components/AuthWrapper/AuthWrapper.js | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/AdminPanel/client/src/components/AuthWrapper/AuthWrapper.js b/AdminPanel/client/src/components/AuthWrapper/AuthWrapper.js index 8d716516..ec254143 100644 --- a/AdminPanel/client/src/components/AuthWrapper/AuthWrapper.js +++ b/AdminPanel/client/src/components/AuthWrapper/AuthWrapper.js @@ -1,6 +1,5 @@ import {useEffect, useState} from 'react'; import {useDispatch, useSelector} from 'react-redux'; -import {useLocation, useNavigate} from 'react-router-dom'; import {fetchUser, selectUser, selectUserLoading, selectIsAuthenticated} from '../../store/slices/userSlice'; import {checkSetupRequired} from '../../api'; import Spinner from '../../assets/Spinner.svg'; @@ -10,8 +9,6 @@ import ServerUnavailable from '../ServerUnavailable/ServerUnavailable'; export default function AuthWrapper({children}) { const dispatch = useDispatch(); - const location = useLocation(); - const navigate = useNavigate(); const user = useSelector(selectUser); const loading = useSelector(selectUserLoading); const isAuthenticated = useSelector(selectIsAuthenticated); @@ -20,24 +17,6 @@ export default function AuthWrapper({children}) { const [checkingSetup, setCheckingSetup] = useState(true); const [serverUnavailable, setServerUnavailable] = useState(false); - // Save intended URL for redirect after setup/login - useEffect(() => { - if (!isAuthenticated && location.pathname !== '/admin/setup' && location.pathname !== '/admin/login') { - sessionStorage.setItem('redirectAfterAuth', location.pathname + location.search); - } - }, [location, isAuthenticated]); - - // Redirect after successful authentication - useEffect(() => { - if (isAuthenticated && user) { - const redirectUrl = sessionStorage.getItem('redirectAfterAuth'); - if (redirectUrl) { - sessionStorage.removeItem('redirectAfterAuth'); - navigate(redirectUrl, {replace: true}); - } - } - }, [isAuthenticated, user, navigate]); - useEffect(() => { const checkSetup = async () => { try { From 23f0d556356cfd1dd15bc2c62c3e1ea475d00e8c Mon Sep 17 00:00:00 2001 From: Sergey Konovalov Date: Thu, 9 Oct 2025 23:21:41 +0300 Subject: [PATCH 4/5] [bug] Wait onLoadInternalProviders event before render; Fix bug 77427 --- .../ai/scripts/engine/providers/base.js | 2 ++ .../pages/AiIntegration/hooks/useAiPlugin.js | 18 ++++++++++++++++-- .../client/src/pages/AiIntegration/index.js | 5 +++-- .../src/pages/AiIntegration/js/plugins-sdk.js | 16 +++++++++++++++- 4 files changed, 36 insertions(+), 5 deletions(-) diff --git a/AdminPanel/client/src/pages/AiIntegration/ai/scripts/engine/providers/base.js b/AdminPanel/client/src/pages/AiIntegration/ai/scripts/engine/providers/base.js index 06b6fffd..df6a80b3 100644 --- a/AdminPanel/client/src/pages/AiIntegration/ai/scripts/engine/providers/base.js +++ b/AdminPanel/client/src/pages/AiIntegration/ai/scripts/engine/providers/base.js @@ -194,6 +194,8 @@ } AI.onLoadInternalProviders(); + if (Asc.plugin.sendEvent) + Asc.plugin.sendEvent("ai_onLoadInternalProviders"); }; AI.InternalCustomProvidersSources = {}; diff --git a/AdminPanel/client/src/pages/AiIntegration/hooks/useAiPlugin.js b/AdminPanel/client/src/pages/AiIntegration/hooks/useAiPlugin.js index 88d11f3c..03787324 100644 --- a/AdminPanel/client/src/pages/AiIntegration/hooks/useAiPlugin.js +++ b/AdminPanel/client/src/pages/AiIntegration/hooks/useAiPlugin.js @@ -1,7 +1,13 @@ import {useState, useEffect, useCallback} from 'react'; import {useSelector, useDispatch} from 'react-redux'; import {selectConfig, saveConfig} from '../../../store/slices/configSlice'; -import {registerShowWindowCallback, registerCloseWindowCallback, registerSaveCallback, initAISettings} from '../js/plugins-sdk'; +import { + registerShowWindowCallback, + registerCloseWindowCallback, + registerSaveCallback, + registerLoadInternalProvidersCallback, + initAISettings +} from '../js/plugins-sdk'; /** * Custom hook for managing complete AI plugin functionality @@ -11,6 +17,7 @@ import {registerShowWindowCallback, registerCloseWindowCallback, registerSaveCal */ const useAiPlugin = statisticsData => { const [pluginWindows, setPluginWindows] = useState([]); + const [internalProvidersLoaded, setInternalProvidersLoaded] = useState(false); const dispatch = useDispatch(); const config = useSelector(selectConfig); @@ -121,16 +128,22 @@ const useAiPlugin = statisticsData => { } }; + const handleLoadInternalProviders = () => { + setInternalProvidersLoaded(true); + }; + // Register all callbacks with SDK registerShowWindowCallback(handleShowWindow); registerCloseWindowCallback(handleCloseWindow); registerSaveCallback(handleSave); + registerLoadInternalProvidersCallback(handleLoadInternalProviders); // Cleanup: unregister all callbacks return () => { registerShowWindowCallback(null); registerCloseWindowCallback(null); registerSaveCallback(null); + registerLoadInternalProvidersCallback(null); }; }, [config, dispatch]); @@ -139,7 +152,8 @@ const useAiPlugin = statisticsData => { return { pluginWindows, currentWindow, - handleIframeLoad + handleIframeLoad, + internalProvidersLoaded }; }; diff --git a/AdminPanel/client/src/pages/AiIntegration/index.js b/AdminPanel/client/src/pages/AiIntegration/index.js index 903a68e0..931bb89c 100644 --- a/AdminPanel/client/src/pages/AiIntegration/index.js +++ b/AdminPanel/client/src/pages/AiIntegration/index.js @@ -23,7 +23,7 @@ export default function AiIntegration() { }); // Use custom hook for complete AI plugin functionality - const {currentWindow, handleIframeLoad} = useAiPlugin(data); + const {currentWindow, handleIframeLoad, internalProvidersLoaded} = useAiPlugin(data); // Constants const AI_IFRAME_SRC = `ai/index.html`; @@ -58,7 +58,8 @@ export default function AiIntegration() { return (