From f7196991fc889fb5630294cae23c665f7dd7f0d0 Mon Sep 17 00:00:00 2001 From: KernelDeimos Date: Tue, 31 Dec 2024 10:34:07 -0500 Subject: [PATCH] refactor: rm legacy FSAccessContext and systemfs --- src/backend/src/api/filesystem/FSNodeParam.js | 2 +- src/backend/src/filesystem/FSAccessContext.js | 117 ------------------ .../src/filesystem/FilesystemService.js | 17 --- src/backend/src/filesystem/systemfs.js | 42 ------- src/backend/src/helpers.js | 2 - src/backend/src/middleware/fs.js | 47 ------- src/backend/src/modules/web/lib/eggspress.js | 4 - src/backend/src/routers/down.js | 6 +- .../src/routers/filesystem_api/batch/all.js | 4 +- .../src/routers/filesystem_api/delete.js | 3 +- src/backend/src/routers/suggest_apps.js | 1 - src/backend/src/routers/whoami.js | 3 +- src/backend/src/routers/writeFile.js | 1 - src/backend/src/routers/writeFile/mkdir.js | 4 +- src/backend/src/routers/writeFile/write.js | 3 +- 15 files changed, 13 insertions(+), 243 deletions(-) delete mode 100644 src/backend/src/filesystem/FSAccessContext.js delete mode 100644 src/backend/src/filesystem/systemfs.js delete mode 100644 src/backend/src/middleware/fs.js diff --git a/src/backend/src/api/filesystem/FSNodeParam.js b/src/backend/src/api/filesystem/FSNodeParam.js index a7ee048e..50ce6937 100644 --- a/src/backend/src/api/filesystem/FSNodeParam.js +++ b/src/backend/src/api/filesystem/FSNodeParam.js @@ -32,7 +32,7 @@ module.exports = class FSNodeParam { async consolidate ({ req, getParam }) { const log = globalThis.services.get('log-service').create('fsnode-param'); - const fs = req.fs ?? Context.get('services').get('filesystem'); + const fs = Context.get('services').get('filesystem'); let uidOrPath = getParam(this.srckey); if ( uidOrPath === undefined ) { diff --git a/src/backend/src/filesystem/FSAccessContext.js b/src/backend/src/filesystem/FSAccessContext.js deleted file mode 100644 index 2b6773c5..00000000 --- a/src/backend/src/filesystem/FSAccessContext.js +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright (C) 2024 Puter Technologies Inc. - * - * This file is part of Puter. - * - * Puter is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -const FSNodeContext = require("./FSNodeContext"); - -const { NodePathSelector, NodeUIDSelector, NodeInternalIDSelector } = require("./node/selectors"); - -/** - * Container for access implementations. - * - * Access implementations may vary depending on region, - * user privileges, and other factors. - * - * @class FSAccessContext - */ -module.exports = class FSAccessContext { - constructor () { - this.fsEntryFetcher = null; - } - - /** - * get_entry_by_path() returns a filesystem entry using - * the path to the entry. Use this method when you need - * to get a filesystem entry but don't need to collect - * any other information about the entry. - * - * @warning The entry returned by this method is not - * client-safe. Use FSNodeContext to get a client-safe - * entry by calling it's fetchEntry() method. - * - * @param {*} path - * @returns - * @deprecated use get_entry({ path }) instead - */ - async get_entry_by_path (path) { - return await this.get_entry({ path }); - } - - /** - * get_entry() returns a filesystem entry using - * path, uid, or id associated with a filesystem - * node. Use this method when you need to get a - * filesystem entry but don't need to collect any - * other information about the entry. - * - * @warning The entry returned by this method is not - * client-safe. Use FSNodeContext to get a client-safe - * entry by calling it's fetchEntry() method. - * - * @param {*} param0 options for getting the entry - * @param {*} param0.path - * @param {*} param0.uid - * @param {*} param0.id please use mysql_id instead - * @param {*} param0.mysql_id - */ - async get_entry ({ path, uid, id, mysql_id, ...options }) { - let fsNode = await this.node({ path, uid, id, mysql_id }); - await fsNode.fetchEntry(options); - return fsNode.entry; - } - - /** - * node() returns a filesystem node using path, uid, - * or id associated with a filesystem node. Use this - * method when you need to get a filesystem node and - * need to collect information about the entry. - * - * @param {*} location - path, uid, or id associated with a filesystem node - * @returns - */ - async node (selector) { - if ( typeof selector === 'string' ) { - if ( selector.startsWith('/') ) { - selector = new NodePathSelector(selector); - } else { - selector = new NodeUIDSelector(selector); - } - } - - // TEMP: remove when these objects aren't used anymore - if ( - typeof selector === 'object' && - selector.constructor.name === 'Object' - ) { - if ( selector.path ) { - selector = new NodePathSelector(selector.path); - } else if ( selector.uid ) { - selector = new NodeUIDSelector(selector.uid); - } else { - selector = new NodeInternalIDSelector( - 'mysql', selector.mysql_id); - } - } - - let fsNode = new FSNodeContext({ - services: this.services, - selector, - fs: this - }); - return fsNode; - } -}; diff --git a/src/backend/src/filesystem/FilesystemService.js b/src/backend/src/filesystem/FilesystemService.js index e6e2cdf4..03a2ad54 100644 --- a/src/backend/src/filesystem/FilesystemService.js +++ b/src/backend/src/filesystem/FilesystemService.js @@ -19,7 +19,6 @@ // TODO: database access can be a service const { RESOURCE_STATUS_PENDING_CREATE } = require('../modules/puterfs/ResourceService.js'); const { TraceService } = require('../services/TraceService.js'); -const FSAccessContext = require('./FSAccessContext.js'); const PerformanceMonitor = require('../monitor/PerformanceMonitor.js'); const { NodePathSelector, NodeUIDSelector, NodeInternalIDSelector } = require('./node/selectors.js'); const FSNodeContext = require('./FSNodeContext.js'); @@ -158,22 +157,6 @@ class FilesystemService extends BaseService { })); } - /** - * @deprecated - temporary migration method - */ - get_systemfs () { - if ( ! this.systemfs_ ) { - this.systemfs_ = new FSAccessContext(); - this.systemfs_.fsEntryFetcher = this.services.get('fsEntryFetcher'); - this.systemfs_.fsEntryService = this.services.get('fsEntryService'); - this.systemfs_.resourceService = this.services.get('resourceService'); - this.systemfs_.sizeService = this.services.get('sizeService'); - this.systemfs_.traceService = this.services.get('traceService'); - this.systemfs_.services = this.services; - } - return this.systemfs_; - } - async mkshortcut ({ parent, name, user, target }) { // Access Control diff --git a/src/backend/src/filesystem/systemfs.js b/src/backend/src/filesystem/systemfs.js deleted file mode 100644 index 4d2e5d56..00000000 --- a/src/backend/src/filesystem/systemfs.js +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2024 Puter Technologies Inc. - * - * This file is part of Puter. - * - * Puter is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -const fs_ = require('fs'); - -const FSAccessContext = require("./FSAccessContext"); -const DatabaseFSEntryFetcher = require("./storage/DatabaseFSEntryFetcher"); -const { DatabaseFSEntryService } = require('./storage/DatabaseFSEntryService.js'); -const { ResourceService } = require('./storage/ResourceService.js'); -const { SizeService } = require('./storage/SizeService.js'); -const config = require('../config.js'); -const { TraceService: FSTracer } = require('../services/TraceService.js'); - -const systemfs = new FSAccessContext(); - -systemfs.fsEntryFetcher = new DatabaseFSEntryFetcher(); -systemfs.fsEntryService = new DatabaseFSEntryService(); -systemfs.resourceService = new ResourceService(); -systemfs.sizeService = new SizeService(); -systemfs.traceService = new FSTracer(); - -// Log usages every 10 seconds for debugging -if ( config.usages_debug ) setInterval(async ()=>{ - await fs_.promises.writeFile('/tmp/user_usages.json', JSON.stringify(systemfs.sizeService.usages, null, 4)); -}, 10*1000); - -module.exports = systemfs; diff --git a/src/backend/src/helpers.js b/src/backend/src/helpers.js index 92fd19ae..81749042 100644 --- a/src/backend/src/helpers.js +++ b/src/backend/src/helpers.js @@ -30,12 +30,10 @@ const { Context } = require('./util/context'); const { NodeUIDSelector } = require('./filesystem/node/selectors'); const { stream_to_buffer } = require('./util/streamutil.js'); -let systemfs = null; let services = null; const tmp_provide_services = async ss => { services = ss; await services.ready; - systemfs = services.get('filesystem').get_systemfs(); } async function is_empty(dir_uuid){ diff --git a/src/backend/src/middleware/fs.js b/src/backend/src/middleware/fs.js deleted file mode 100644 index 04971103..00000000 --- a/src/backend/src/middleware/fs.js +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2024 Puter Technologies Inc. - * - * This file is part of Puter. - * - * Puter is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -const FSAccessContext = require('../filesystem/FSAccessContext.js'); - -const fs = (req, res, next)=>{ - const systemfs = req.services.get('filesystem').get_systemfs(); - try { - const fs = new FSAccessContext(); - fs.fsEntryFetcher = systemfs.fsEntryFetcher; - fs.fsEntryService = systemfs.fsEntryService; - fs.resourceService = systemfs.resourceService; - fs.sizeService = systemfs.sizeService; - fs.traceService = systemfs.traceService; - fs.user = req.user; - fs.services = req.services; - - // TODO: Decorate with AuthEntryFetcher - - req.fs = fs; - } catch (e) { - // TODO: log details about this error to another service - console.error(e); - return res.status(500).send({ - // TODO: standardize 500 errors to avoid inference attacks - error: 'the operation could not be completed' - }); - } - next(); -} - -module.exports = fs; diff --git a/src/backend/src/modules/web/lib/eggspress.js b/src/backend/src/modules/web/lib/eggspress.js index 5cfb220f..63c08e54 100644 --- a/src/backend/src/modules/web/lib/eggspress.js +++ b/src/backend/src/modules/web/lib/eggspress.js @@ -21,7 +21,6 @@ const multer = require('multer'); const multest = require('@heyputer/multest'); const api_error_handler = require('./api_error_handler.js'); -const fsBeforeMW = require('../../../middleware/fs.js'); const APIError = require('../../../api/APIError.js'); const { Context } = require('../../../util/context.js'); const { subdomain } = require('../../../helpers.js'); @@ -49,9 +48,6 @@ module.exports = function eggspress (route, settings, handler) { if ( settings.abuse ) mw.push(require('../../../middleware/abuse')(settings.abuse)); if ( settings.auth ) mw.push(require('../../../middleware/auth')); if ( settings.auth2 ) mw.push(require('../../../middleware/auth2')); - if ( settings.fs ) { - mw.push(fsBeforeMW); - } if ( settings.verified ) mw.push(require('../../../middleware/verified')); if ( settings.json ) mw.push(express.json()); diff --git a/src/backend/src/routers/down.js b/src/backend/src/routers/down.js index 78f13de3..a0e5616e 100644 --- a/src/backend/src/routers/down.js +++ b/src/backend/src/routers/down.js @@ -21,7 +21,6 @@ const express = require('express'); const router = express.Router(); const auth = require('../middleware/auth.js'); const config = require('../config.js'); -const fs = require('../middleware/fs.js'); const { DB_WRITE } = require('../services/database/consts.js'); const { NodePathSelector } = require('../filesystem/node/selectors.js'); const { HLRead } = require('../filesystem/hl_operations/hl_read.js'); @@ -30,7 +29,7 @@ const { UserActorType } = require('../services/auth/Actor.js'); // -----------------------------------------------------------------------// // GET /down // -----------------------------------------------------------------------// -router.post('/down', auth, fs, express.json(), express.urlencoded({ extended: true }), async (req, res, next)=>{ +router.post('/down', auth, express.json(), express.urlencoded({ extended: true }), async (req, res, next)=>{ // check subdomain const actor = req.actor; @@ -70,7 +69,8 @@ router.post('/down', auth, fs, express.json(), express.urlencoded({ extended: tr return res.status(400).send('Cannot download a directory.'); // resolve path to its FSEntry - const fsnode = await req.fs.node(new NodePathSelector(path)); + const svc_fs = req.services.get('filesystem'); + const fsnode = await svc_fs.node(new NodePathSelector(path)); // not found if( ! fsnode.exists() ) { diff --git a/src/backend/src/routers/filesystem_api/batch/all.js b/src/backend/src/routers/filesystem_api/batch/all.js index 700bea66..e0a8baf5 100644 --- a/src/backend/src/routers/filesystem_api/batch/all.js +++ b/src/backend/src/routers/filesystem_api/batch/all.js @@ -32,7 +32,6 @@ module.exports = eggspress('/batch', { subdomain: 'api', verified: true, auth2: true, - fs: true, // json: true, // files: ['file'], // multest: true, @@ -85,7 +84,8 @@ module.exports = eggspress('/batch', { } // Make sure usage is cached - await req.fs.sizeService.get_usage(req.user.id); + const sizeService = x.get('services').get('sizeService'); + await sizeService.get_usage(req.user.id); globalThis.average_chunk_size = new MovingMode({ alpha: 0.7, diff --git a/src/backend/src/routers/filesystem_api/delete.js b/src/backend/src/routers/filesystem_api/delete.js index b77cbae7..1cda8244 100644 --- a/src/backend/src/routers/filesystem_api/delete.js +++ b/src/backend/src/routers/filesystem_api/delete.js @@ -28,7 +28,6 @@ const FSNodeParam = require('../../api/filesystem/FSNodeParam.js'); module.exports = eggspress('/delete', { subdomain: 'api', auth2: true, - fs: true, json: true, allowedMethods: ['POST'], }, async (req, res, next) => { @@ -52,7 +51,7 @@ module.exports = eggspress('/delete', { // TODO: remove this pseudo-batch for ( const item_path of paths ) { const target = await (new FSNodeParam('path')).consolidate({ - req: { fs: req.fs, user }, + req: { user }, getParam: () => item_path, }); const hl_remove = new HLRemove(); diff --git a/src/backend/src/routers/suggest_apps.js b/src/backend/src/routers/suggest_apps.js index 53c645f6..49c5cd1c 100644 --- a/src/backend/src/routers/suggest_apps.js +++ b/src/backend/src/routers/suggest_apps.js @@ -22,7 +22,6 @@ const router = new express.Router(); const auth = require('../middleware/auth.js'); const config = require('../config'); const { Context } = require('../util/context.js'); -const fs = require('../middleware/fs.js'); const { NodeInternalIDSelector } = require('../filesystem/node/selectors.js'); // -----------------------------------------------------------------------// diff --git a/src/backend/src/routers/whoami.js b/src/backend/src/routers/whoami.js index 526df65e..31bfde42 100644 --- a/src/backend/src/routers/whoami.js +++ b/src/backend/src/routers/whoami.js @@ -29,7 +29,6 @@ const timeago = (() => { const { get_taskbar_items, is_shared_with_anyone, suggest_app_for_fsentry, get_app, get_descendants, id2uuid } = require('../helpers'); const auth = require('../middleware/auth.js'); -const fs = require('../middleware/fs.js'); const _path = require('path'); const eggspress = require('../api/eggspress'); const { Context } = require('../util/context'); @@ -122,7 +121,7 @@ const WHOAMI_GET = eggspress('/whoami', { // POST /whoami // -----------------------------------------------------------------------// const WHOAMI_POST = new express.Router(); -WHOAMI_POST.post('/whoami', auth, fs, express.json(), async (req, response, next)=>{ +WHOAMI_POST.post('/whoami', auth, express.json(), async (req, response, next)=>{ // check subdomain if(require('../helpers').subdomain(req) !== 'api') { return; diff --git a/src/backend/src/routers/writeFile.js b/src/backend/src/routers/writeFile.js index 44c4c414..140e64ab 100644 --- a/src/backend/src/routers/writeFile.js +++ b/src/backend/src/routers/writeFile.js @@ -37,7 +37,6 @@ const { HLRemove } = require('../filesystem/hl_operations/hl_remove'); // POST /writeFile // -----------------------------------------------------------------------// module.exports = eggspress('/writeFile', { - fs: true, files: ['file'], allowedMethods: ['POST'], }, async (req, res, next) => { diff --git a/src/backend/src/routers/writeFile/mkdir.js b/src/backend/src/routers/writeFile/mkdir.js index a6ac3cb2..b8d10936 100644 --- a/src/backend/src/routers/writeFile/mkdir.js +++ b/src/backend/src/routers/writeFile/mkdir.js @@ -20,7 +20,9 @@ module.exports = async function writeFile_handle_mkdir ({ user: actor.type.user, actor, }); + + const svc_fs = req.services.get('filesystem'); - const newdir_node = await req.fs.node(new NodeUIDSelector(r.uid)); + const newdir_node = await svc_fs.node(new NodeUIDSelector(r.uid)); return res.send(await sign_file(await newdir_node.get('entry'), 'write')); }; diff --git a/src/backend/src/routers/writeFile/write.js b/src/backend/src/routers/writeFile/write.js index 0b90ae21..395a50fc 100644 --- a/src/backend/src/routers/writeFile/write.js +++ b/src/backend/src/routers/writeFile/write.js @@ -25,7 +25,8 @@ module.exports = async function writeFile_handle_write ({ return res.status(500).send(e); } - const dirNode = await req.fs.node(new NodePathSelector(dirname)); + const svc_fs = req.services.get('filesystem'); + const dirNode = await svc_fs.node(new NodePathSelector(dirname)); // Upload files one by one const returns = [];