From 9bc9dcafeefa809bc309ce845013c4bb121f9653 Mon Sep 17 00:00:00 2001 From: Eric Doughty-Papassideris Date: Wed, 4 Sep 2024 03:47:59 +0200 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20oo-connector:=20refactored?= =?UTF-8?q?=20router=20system=20to=20something=20more=20coherent=20(#525)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onlyoffice-connector/src/app.ts | 15 +++---- .../onlyoffice-connector/src/config/index.ts | 2 + ...roller.ts => browser-editor.controller.ts} | 13 +++--- .../src/middlewares/error.middleware.ts | 5 +-- .../src/routes/backend-callbacks.route.ts | 21 ++++----- .../src/routes/browser-editor.route.ts | 16 +++++++ .../src/routes/index.route.ts | 28 ------------ .../onlyoffice-connector/src/routes/index.ts | 43 +++++++++++++++++++ .../src/routes/onlyoffice.route.ts | 32 ++++++-------- .../onlyoffice-connector/src/server.ts | 5 +-- 10 files changed, 97 insertions(+), 83 deletions(-) rename tdrive/connectors/onlyoffice-connector/src/controllers/{index.controller.ts => browser-editor.controller.ts} (94%) create mode 100644 tdrive/connectors/onlyoffice-connector/src/routes/browser-editor.route.ts delete mode 100644 tdrive/connectors/onlyoffice-connector/src/routes/index.route.ts create mode 100644 tdrive/connectors/onlyoffice-connector/src/routes/index.ts diff --git a/tdrive/connectors/onlyoffice-connector/src/app.ts b/tdrive/connectors/onlyoffice-connector/src/app.ts index 738fb0cf..95e2d37d 100644 --- a/tdrive/connectors/onlyoffice-connector/src/app.ts +++ b/tdrive/connectors/onlyoffice-connector/src/app.ts @@ -5,24 +5,25 @@ import cors from 'cors'; import { renderFile } from 'eta'; import path from 'path'; import errorMiddleware from './middlewares/error.middleware'; -import { SERVER_PORT, SERVER_PREFIX } from '@config'; +import { SERVER_PORT } from '@config'; import logger from './lib/logger'; import cookieParser from 'cookie-parser'; import apiService from './services/api.service'; import onlyofficeService from './services/onlyoffice.service'; +import { makeURLTo, mountRoutes } from './routes'; class App { public app: express.Application; public env: string; public port: string | number; - constructor(routes: Routes[]) { + constructor() { this.app = express(); this.env = NODE_ENV; this.initViews(); this.initMiddlewares(); - this.initRoutes(routes); + this.initRoutes(); this.initErrorHandling(); } @@ -34,15 +35,13 @@ class App { public getServer = () => this.app; - private initRoutes = (routes: Routes[]) => { + private initRoutes = () => { this.app.use((req, res, next) => { logger.info(`Received request: ${req.method} ${req.originalUrl} from ${req.header('user-agent')} (${req.ip})`); next(); }); - routes.forEach(route => { - this.app.use(route.path ?? '/', route.router); - }); + mountRoutes(this.app); this.app.get('/health', (_req, res) => { Promise.all([onlyofficeService.getLatestLicence(), apiService.hasToken(), onlyofficeService.getForgottenList()]).then( @@ -58,7 +57,7 @@ class App { }); this.app.use( - SERVER_PREFIX.replace(/\/$/, '') + '/assets', + makeURLTo.assets(), (req, res, next) => { res.header('Access-Control-Allow-Origin', '*'); res.header('Access-Control-Allow-Headers', 'X-Requested-With'); diff --git a/tdrive/connectors/onlyoffice-connector/src/config/index.ts b/tdrive/connectors/onlyoffice-connector/src/config/index.ts index e25db1b8..43d33300 100644 --- a/tdrive/connectors/onlyoffice-connector/src/config/index.ts +++ b/tdrive/connectors/onlyoffice-connector/src/config/index.ts @@ -16,3 +16,5 @@ export const { export const twakeDriveTokenRefrehPeriodMS = 10 * 60 * 1000; export const onlyOfficeForgottenFilesCheckPeriodMS = 10 * 60 * 1000; export const onlyOfficeConnectivityCheckPeriodMS = 10 * 60 * 1000; + +export const SERVER_TDRIVE_API_PREFIX = '/tdriveApi/1'; diff --git a/tdrive/connectors/onlyoffice-connector/src/controllers/index.controller.ts b/tdrive/connectors/onlyoffice-connector/src/controllers/browser-editor.controller.ts similarity index 94% rename from tdrive/connectors/onlyoffice-connector/src/controllers/index.controller.ts rename to tdrive/connectors/onlyoffice-connector/src/controllers/browser-editor.controller.ts index fd05b2af..c2779403 100644 --- a/tdrive/connectors/onlyoffice-connector/src/controllers/index.controller.ts +++ b/tdrive/connectors/onlyoffice-connector/src/controllers/browser-editor.controller.ts @@ -1,13 +1,13 @@ import editorService from '@/services/editor.service'; import { NextFunction, Request, Response } from 'express'; -import { CREDENTIALS_SECRET, SERVER_ORIGIN, SERVER_PREFIX } from '@config'; +import { CREDENTIALS_SECRET } from '@config'; import jwt from 'jsonwebtoken'; import driveService from '@/services/drive.service'; import { DriveFileType } from '@/interfaces/drive.interface'; import fileService from '@/services/file.service'; import { OfficeToken } from '@/interfaces/routes.interface'; import logger from '@/lib/logger'; -import * as Utils from '@/utils'; +import { makeURLTo } from '@/routes'; interface RequestQuery { mode: string; @@ -29,7 +29,7 @@ interface RequestEditorQuery { * The user is redirected from there to open directly the OnlyOffice edition server's web UI, with appropriate preview or not * and rights checks. */ -class IndexController { +class BrowserEditorController { /** * Opened by the user's browser, proxied through the Twake Drive backend. Checks access to the * file with the backend, then redirects the user to the `editor` method but directly on this @@ -98,9 +98,8 @@ class IndexController { expiresIn: 60 * 60 * 24 * 30, }, ); - res.redirect( - Utils.joinURL([SERVER_ORIGIN ?? '', SERVER_PREFIX, 'editor'], { + makeURLTo.editorAbsolute({ token, file_id, editing_session_key: editingSessionKey, @@ -145,7 +144,7 @@ class IndexController { res.render('index', { ...initResponse, docId: preview ? file_id : editing_session_key, - server: Utils.joinURL([SERVER_ORIGIN, SERVER_PREFIX]), + server: makeURLTo.rootAbsolute(), token: inPageToken, }); } catch (error) { @@ -155,4 +154,4 @@ class IndexController { }; } -export default IndexController; +export default BrowserEditorController; diff --git a/tdrive/connectors/onlyoffice-connector/src/middlewares/error.middleware.ts b/tdrive/connectors/onlyoffice-connector/src/middlewares/error.middleware.ts index 49f1c317..d49eaa17 100644 --- a/tdrive/connectors/onlyoffice-connector/src/middlewares/error.middleware.ts +++ b/tdrive/connectors/onlyoffice-connector/src/middlewares/error.middleware.ts @@ -1,7 +1,6 @@ import logger from '@/lib/logger'; import { NextFunction, Request, Response } from 'express'; -import * as Utils from '@/utils'; -import { SERVER_ORIGIN, SERVER_PREFIX } from '@config'; +import { makeURLTo } from '@/routes'; export default (error: Error & { status?: number }, req: Request, res: Response, next: NextFunction): void => { try { @@ -12,7 +11,7 @@ export default (error: Error & { status?: number }, req: Request, res: Response, res.status(status); res.render('error', { - server: Utils.joinURL([SERVER_ORIGIN, SERVER_PREFIX]), + server: makeURLTo.rootAbsolute(), errorMessage: message, }); } catch (error) { diff --git a/tdrive/connectors/onlyoffice-connector/src/routes/backend-callbacks.route.ts b/tdrive/connectors/onlyoffice-connector/src/routes/backend-callbacks.route.ts index 527eb02e..f5b40927 100644 --- a/tdrive/connectors/onlyoffice-connector/src/routes/backend-callbacks.route.ts +++ b/tdrive/connectors/onlyoffice-connector/src/routes/backend-callbacks.route.ts @@ -1,21 +1,16 @@ import TwakeDriveBackendCallbackController from '@/controllers/backend-callbacks.controller'; -import { Routes } from '@/interfaces/routes.interface'; import authMiddleware from '@/middlewares/auth.middleware'; -import { Router } from 'express'; +import type { Router } from 'express'; /** * These routes are called by Twake Drive backend, for ex. before editing or retreiving a file, * if it has an editing_session_key still, get the status of that and force a resolution. */ -export default class TwakeDriveBackendCallbackRoutes implements Routes { - public readonly router = Router(); - public readonly path = '/tdriveApi/1'; - private readonly controller: TwakeDriveBackendCallbackController; - - constructor() { - this.controller = new TwakeDriveBackendCallbackController(); +export const TwakeDriveBackendCallbackRoutes = { + mount(router: Router) { + const controller = new TwakeDriveBackendCallbackController(); // Why post ? to garantee it is never cached and always ran - this.router.post('/session/:editing_session_key/check', authMiddleware, this.controller.checkSessionStatus); - this.router.delete('/session/:editing_session_key', authMiddleware, this.controller.deleteSessionKey); - } -} + router.post('/session/:editing_session_key/check', authMiddleware, controller.checkSessionStatus); + router.delete('/session/:editing_session_key', authMiddleware, controller.deleteSessionKey); + }, +}; diff --git a/tdrive/connectors/onlyoffice-connector/src/routes/browser-editor.route.ts b/tdrive/connectors/onlyoffice-connector/src/routes/browser-editor.route.ts new file mode 100644 index 00000000..4f02de21 --- /dev/null +++ b/tdrive/connectors/onlyoffice-connector/src/routes/browser-editor.route.ts @@ -0,0 +1,16 @@ +import BrowserEditorController from '@/controllers/browser-editor.controller'; +import authMiddleware from '@/middlewares/auth.middleware'; +import requirementsMiddleware from '@/middlewares/requirements.middleware'; +import type { Router } from 'express'; + +/** + * When the user previews or edits a file in Twake Drive, their browser is sent to these routes + * which return a webpage that instantiates the client side JS Only Office component. + */ +export const BrowserEditorRoutes = { + mount(router: Router) { + const controller = new BrowserEditorController(); + router.get('/', requirementsMiddleware, authMiddleware, controller.index); + router.get('/editor', requirementsMiddleware, authMiddleware, controller.editor); + }, +}; diff --git a/tdrive/connectors/onlyoffice-connector/src/routes/index.route.ts b/tdrive/connectors/onlyoffice-connector/src/routes/index.route.ts deleted file mode 100644 index 3e99c719..00000000 --- a/tdrive/connectors/onlyoffice-connector/src/routes/index.route.ts +++ /dev/null @@ -1,28 +0,0 @@ -import IndexController from '@/controllers/index.controller'; -import { Routes } from '@/interfaces/routes.interface'; -import authMiddleware from '@/middlewares/auth.middleware'; -import requirementsMiddleware from '@/middlewares/requirements.middleware'; -import { Router } from 'express'; -import { SERVER_PREFIX } from '@config'; - -/** - * When the user previews or edits a file in Twake Drive, their browser is sent to these routes - * which return a webpage that instantiates the client side JS Only Office component. - */ -class IndexRoute implements Routes { - public path = SERVER_PREFIX; - public router = Router(); - public indexController: IndexController; - - constructor() { - this.indexController = new IndexController(); - this.initRoutes(); - } - - private initRoutes = () => { - this.router.get('/', requirementsMiddleware, authMiddleware, this.indexController.index); - this.router.get('/editor', requirementsMiddleware, authMiddleware, this.indexController.editor); - }; -} - -export default IndexRoute; diff --git a/tdrive/connectors/onlyoffice-connector/src/routes/index.ts b/tdrive/connectors/onlyoffice-connector/src/routes/index.ts new file mode 100644 index 00000000..758ee1a7 --- /dev/null +++ b/tdrive/connectors/onlyoffice-connector/src/routes/index.ts @@ -0,0 +1,43 @@ +import { Application, Router } from 'express'; + +import * as Utils from '@/utils'; + +import { TwakeDriveBackendCallbackRoutes } from './backend-callbacks.route'; +import { BrowserEditorRoutes } from './browser-editor.route'; +import { OnlyOfficeRoutes } from './onlyoffice.route'; + +import { SERVER_ORIGIN, SERVER_PREFIX, SERVER_TDRIVE_API_PREFIX } from '@config'; + +export function mountRoutes(app: Application) { + // These routes are forwarded through the Twake Drive front, back and here + const proxiedRouter = Router(); + BrowserEditorRoutes.mount(proxiedRouter); + OnlyOfficeRoutes.mount(proxiedRouter); + console.log('Mounting at ' + SERVER_PREFIX); + app.use(SERVER_PREFIX, proxiedRouter); + + // These endpoints should only be accessible to the Twake Drive backend + const apiRouter = Router(); + console.log('Mounting at ' + SERVER_TDRIVE_API_PREFIX); + TwakeDriveBackendCallbackRoutes.mount(apiRouter); + app.use(SERVER_TDRIVE_API_PREFIX, apiRouter); +} + +export const makeURLTo = { + rootAbsolute: () => Utils.joinURL([SERVER_ORIGIN, SERVER_PREFIX]), + assets: () => Utils.joinURL([SERVER_PREFIX, 'assets']), + editorAbsolute(params: { token: string; file_id: string; editing_session_key: string; company_id: string; preview: string; office_token: string }) { + return Utils.joinURL([SERVER_ORIGIN ?? '', SERVER_PREFIX, 'editor'], params); + }, +}; + +// export function makeURLToEditor2() { +// const initResponse = await editorService.init(company_id, file_name, file_id, user, preview, drive_file_id || file_id); + +// res.render('index', { +// ...initResponse, +// docId: preview ? file_id : editing_session_key, +// server: Utils.joinURL([SERVER_ORIGIN, SERVER_PREFIX]), +// token: inPageToken, +// }); +// } diff --git a/tdrive/connectors/onlyoffice-connector/src/routes/onlyoffice.route.ts b/tdrive/connectors/onlyoffice-connector/src/routes/onlyoffice.route.ts index 504c2c7e..0392cc3c 100644 --- a/tdrive/connectors/onlyoffice-connector/src/routes/onlyoffice.route.ts +++ b/tdrive/connectors/onlyoffice-connector/src/routes/onlyoffice.route.ts @@ -1,23 +1,15 @@ import OnlyOfficeController from '@/controllers/onlyoffice.controller'; -import { Routes } from '@/interfaces/routes.interface'; import requirementsMiddleware from '@/middlewares/requirements.middleware'; -import { Router } from 'express'; -import { SERVER_PREFIX } from '@config'; +import type { Router } from 'express'; -class OnlyOfficeRoute implements Routes { - public path = SERVER_PREFIX; - public router = Router(); - public onlyOfficeController: OnlyOfficeController; - - constructor() { - this.onlyOfficeController = new OnlyOfficeController(); - this.initRoutes(); - } - - private initRoutes = () => { - this.router.get(`:mode/read`, requirementsMiddleware, this.onlyOfficeController.read); - this.router.post(`:mode/callback`, requirementsMiddleware, this.onlyOfficeController.ooCallback); - }; -} - -export default OnlyOfficeRoute; +/** + * These routes are called by the Only Office server + * when reading a document or updating an editing session + */ +export const OnlyOfficeRoutes = { + mount(router: Router) { + const controller = new OnlyOfficeController(); + router.get(`/:mode/read`, requirementsMiddleware, controller.read); + router.post(`/:mode/callback`, requirementsMiddleware, controller.ooCallback); + }, +}; diff --git a/tdrive/connectors/onlyoffice-connector/src/server.ts b/tdrive/connectors/onlyoffice-connector/src/server.ts index 0c86358e..f743c935 100644 --- a/tdrive/connectors/onlyoffice-connector/src/server.ts +++ b/tdrive/connectors/onlyoffice-connector/src/server.ts @@ -1,8 +1,5 @@ import App from '@/app'; -import IndexRoute from './routes/index.route'; -import OnlyOfficeRoute from './routes/onlyoffice.route'; -import TwakeDriveBackendCallbacksRoutes from './routes/backend-callbacks.route'; -const app = new App([new IndexRoute(), new OnlyOfficeRoute(), new TwakeDriveBackendCallbacksRoutes()]); +const app = new App(); app.listen();