diff --git a/DocService/npm-shrinkwrap.json b/DocService/npm-shrinkwrap.json index 4c369851..14b95ebe 100644 --- a/DocService/npm-shrinkwrap.json +++ b/DocService/npm-shrinkwrap.json @@ -713,22 +713,6 @@ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==" }, - "cookie-parser": { - "version": "1.4.7", - "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz", - "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==", - "requires": { - "cookie": "0.7.2", - "cookie-signature": "1.0.6" - }, - "dependencies": { - "cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==" - } - } - }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", diff --git a/DocService/package.json b/DocService/package.json index 6a99873f..65defc76 100644 --- a/DocService/package.json +++ b/DocService/package.json @@ -16,7 +16,6 @@ "bytes": "3.1.2", "co": "4.6.0", "config": "3.3.12", - "cookie-parser": "^1.4.7", "cors": "^2.8.5", "cron": "1.5.0", "dmdb": "1.0.36002", diff --git a/DocService/sources/routes/adminpanel/router.js b/DocService/sources/routes/adminpanel/router.js deleted file mode 100644 index f3b5a53c..00000000 --- a/DocService/sources/routes/adminpanel/router.js +++ /dev/null @@ -1,154 +0,0 @@ -/* - * (c) Copyright Ascensio System SIA 2010-2024 - * - * This program is a free software product. You can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License (AGPL) - * version 3 as published by the Free Software Foundation. In accordance with - * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect - * that Ascensio System SIA expressly excludes the warranty of non-infringement - * of any third-party rights. - * - * This program is distributed WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For - * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html - * - * You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish - * street, Riga, Latvia, EU, LV-1050. - * - * The interactive user interfaces in modified source and object code versions - * of the Program must display Appropriate Legal Notices, as required under - * Section 5 of the GNU AGPL version 3. - * - * Pursuant to Section 7(b) of the License you must retain the original Product - * logo when distributing the program. Pursuant to Section 7(e) we decline to - * grant you any rights under trademark law for use of our trademarks. - * - * All the Product's GUI elements, including illustrations and icon sets, as - * well as technical writing content are licensed under the terms of the - * Creative Commons Attribution-ShareAlike 4.0 International. See the License - * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode - * - */ - -'use strict'; -const config = require('config'); -const express = require('express'); -const operationContext = require('../../../../Common/sources/operationContext'); -const tenantBaseDir = config.get('tenants.baseDir'); -// const isMultitenantMode = config.get('tenants.isMultitenantMode'); -const defaultTenantSecret = config.get('services.CoAuthoring.secret.browser.string'); -const filenameSecret = config.get('tenants.filenameSecret'); -const jwt = require('jsonwebtoken'); -const fs = require('fs'); -const path = require('path'); -const cookieParser = require('cookie-parser'); - -const router = express.Router(); - -// Middleware to parse JSON request bodies -router.use(express.json()); - -// Middleware to parse cookies -router.use(cookieParser()); - -router.get('/me', async (req, res) => { - try { - const token = req.cookies.accessToken; - if (!token) { - return res.status(401).json({error: 'Unauthorized'}); - } - - // Try to verify with default tenant secret first - try { - const decoded = jwt.verify(token, defaultTenantSecret); - res.json(decoded); - } catch { - // If default secret fails, try to find the tenant and verify with their secret - const tenantList = fs.readdirSync(tenantBaseDir); - for (const tenant of tenantList) { - try { - const tenantSecret = fs.readFileSync(path.join(tenantBaseDir, tenant, filenameSecret), 'utf8'); - const decoded = jwt.verify(token, tenantSecret); - res.json({ - tenant: decoded.tenant, - isAdmin: decoded.isAdmin - }); - return; - } catch { - // Continue to next tenant - continue; - } - } - // If no tenant secret works, return unauthorized - return res.status(401).json({error: 'Invalid token'}); - } - } catch (error) { - console.log('error', error); - res.status(401).json({error: 'Unauthorized'}); - } -}); - -router.post('/login', async (req, res) => { - const ctx = new operationContext.Context(); - ctx.initDefault(); - try { - const {secret} = req.body; - const tenant = findTenantBySecret(secret); - if (!tenant) { - return res.status(401).json({error: 'Invalid secret'}); - } - const token = jwt.sign({...tenant}, secret, {expiresIn: '1h'}); - - res.cookie('accessToken', token, { - httpOnly: true, - sameSite: 'strict', - maxAge: 60 * 60 * 1000, - path: '/' - }); - - res.json({tenant: tenant.tenant, isAdmin: tenant.isAdmin}); - } catch (error) { - ctx.logger.error('Config get error: %s', error.stack); - res.status(500).json({error: 'Internal server error'}); - } -}); - -router.post('/logout', async (req, res) => { - try { - // Clear the httpOnly accessToken cookie - res.clearCookie('accessToken', { - httpOnly: true, - sameSite: 'strict', - path: '/' - }); - - res.json({message: 'Logged out successfully'}); - } catch (error) { - console.log('logout error', error); - res.status(500).json({error: 'Internal server error'}); - } -}); - -//TODO: make function async, use cache -function findTenantBySecret(secret) { - if (secret === defaultTenantSecret) { - return { - tenant: config.get('tenants.defaultTenant'), - isAdmin: true - }; - } - - const tenantList = fs.readdirSync(tenantBaseDir); - for (const tenant of tenantList) { - const tenantSecret = fs.readFileSync(path.join(tenantBaseDir, tenant, filenameSecret), 'utf8'); - if (tenantSecret === secret) { - return { - tenant, - isAdmin: true - }; - } - } - return null; -} - -module.exports = router; diff --git a/DocService/sources/routes/config.js b/DocService/sources/routes/config.js deleted file mode 100644 index deea9ff9..00000000 --- a/DocService/sources/routes/config.js +++ /dev/null @@ -1,92 +0,0 @@ -/* - * (c) Copyright Ascensio System SIA 2010-2024 - * - * This program is a free software product. You can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License (AGPL) - * version 3 as published by the Free Software Foundation. In accordance with - * Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect - * that Ascensio System SIA expressly excludes the warranty of non-infringement - * of any third-party rights. - * - * This program is distributed WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For - * details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html - * - * You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish - * street, Riga, Latvia, EU, LV-1050. - * - * The interactive user interfaces in modified source and object code versions - * of the Program must display Appropriate Legal Notices, as required under - * Section 5 of the GNU AGPL version 3. - * - * Pursuant to Section 7(b) of the License you must retain the original Product - * logo when distributing the program. Pursuant to Section 7(e) we decline to - * grant you any rights under trademark law for use of our trademarks. - * - * All the Product's GUI elements, including illustrations and icon sets, as - * well as technical writing content are licensed under the terms of the - * Creative Commons Attribution-ShareAlike 4.0 International. See the License - * terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode - * - */ - -const config = require('config'); -const express = require('express'); -const bodyParser = require('body-parser'); -const tenantManager = require('../../../Common/sources/tenantManager'); -const operationContext = require('../../../Common/sources/operationContext'); -const runtimeConfigManager = require('../../../Common/sources/runtimeConfigManager'); - -const router = express.Router(); - -const rawFileParser = bodyParser.raw({ - inflate: true, - limit: config.get('services.CoAuthoring.server.limits_tempfile_upload'), - type() { - return true; - } -}); - -router.get('/', async (req, res) => { - const ctx = new operationContext.Context(); - let result = '{}'; - try { - ctx.initFromRequest(req); - await ctx.initTenantCache(); - ctx.logger.debug('config get start'); - const cfg = ctx.getFullCfg(); - result = JSON.stringify(cfg); - } catch (error) { - ctx.logger.error('config get error: %s', error.stack); - } finally { - res.setHeader('Content-Type', 'application/json'); - res.send(result); - ctx.logger.debug('config end'); - } -}); - -router.post('/', rawFileParser, async (req, res) => { - const ctx = new operationContext.Context(); - try { - ctx.initFromRequest(req); - await ctx.initTenantCache(); - - const newConfig = JSON.parse(req.body); - - if (tenantManager.isMultitenantMode(ctx) && !tenantManager.isDefaultTenant(ctx)) { - await tenantManager.setTenantConfig(ctx, newConfig); - } else { - await runtimeConfigManager.saveConfig(ctx, newConfig); - } - - res.sendStatus(200); - } catch (error) { - ctx.logger.error('Configuration save error: %s', error.stack); - res.status(500).json({ - error: 'Failed to save configuration', - details: error.message - }); - } -}); - -module.exports = router; diff --git a/DocService/sources/server.js b/DocService/sources/server.js index 5c55ddb8..0c012fed 100644 --- a/DocService/sources/server.js +++ b/DocService/sources/server.js @@ -57,12 +57,9 @@ const commonDefines = require('./../../Common/sources/commondefines'); const operationContext = require('./../../Common/sources/operationContext'); const tenantManager = require('./../../Common/sources/tenantManager'); const staticRouter = require('./routes/static'); -const configRouter = require('./routes/config'); -const adminpanelRouter = require('./routes/adminpanel/router'); const infoRouter = require('./routes/info'); const ms = require('ms'); const aiProxyHandler = require('./ai/aiProxyHandler'); -const cors = require('cors'); const cfgWopiEnable = config.get('wopi.enable'); const cfgWopiDummyEnable = config.get('wopi.dummy.enable'); @@ -118,12 +115,6 @@ const updateLicense = async () => { operationContext.global.logger.error('updateLicense error: %s', err.stack); } }; -const corsWithCredentials = cors({ - origin: true, - credentials: true, - methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'], - allowedHeaders: ['Content-Type', 'Authorization'] -}); operationContext.global.logger.warn('Express server starting...'); @@ -302,8 +293,6 @@ docsCoServer.install(server, app, () => { app.post('/docbuilder', utils.checkClientIp, rawFileParser, (req, res) => { converterService.builder(req, res); }); - app.use('/info/config', corsWithCredentials, utils.checkClientIp, configRouter); - app.use('/info/adminpanel', corsWithCredentials, utils.checkClientIp, adminpanelRouter); app.get('/info/plugin/settings', utils.checkClientIp, aiProxyHandler.requestSettings); app.post('/info/plugin/models', utils.checkClientIp, rawFileParser, aiProxyHandler.requestModels); // Shared Info router (provides /info.json)