mirror of
https://github.com/HeyPuter/puter.git
synced 2025-01-23 14:20:22 +08:00
refactor: rm legacy FSAccessContext and systemfs
This commit is contained in:
parent
539b31cc5b
commit
f7196991fc
@ -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 ) {
|
||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
};
|
@ -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
|
||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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;
|
@ -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){
|
||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
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;
|
@ -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());
|
||||
|
||||
|
@ -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() ) {
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
|
@ -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');
|
||||
|
||||
// -----------------------------------------------------------------------//
|
||||
|
@ -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;
|
||||
|
@ -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) => {
|
||||
|
@ -21,6 +21,8 @@ module.exports = async function writeFile_handle_mkdir ({
|
||||
actor,
|
||||
});
|
||||
|
||||
const newdir_node = await req.fs.node(new NodeUIDSelector(r.uid));
|
||||
const svc_fs = req.services.get('filesystem');
|
||||
|
||||
const newdir_node = await svc_fs.node(new NodeUIDSelector(r.uid));
|
||||
return res.send(await sign_file(await newdir_node.get('entry'), 'write'));
|
||||
};
|
||||
|
@ -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 = [];
|
||||
|
Loading…
Reference in New Issue
Block a user