diff --git a/extensions/puterfs/main.js b/extensions/puterfs/main.js index 28cd366f9..6b3c522a0 100644 --- a/extensions/puterfs/main.js +++ b/extensions/puterfs/main.js @@ -16,15 +16,89 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ + +const svc_metering = extension.import('service:meteringService'); +const svc_trace = extension.import('service:traceService'); + +// TODO: these services ought to be part of this extension +const svc_size = extension.import('service:sizeService'); +const svc_fsEntry = extension.import('service:fsEntryService'); + +const { + APIError, + Actor, + Context, + UserActorType, +} = extension.import('core'); + +const { + get_user, +} = extension.import('core').util.helpers; + +const { + ParallelTasks, +} = extension.import('core').util.otelutil; + +const { + TYPE_DIRECTORY, +} = extension.import('core').fs; + class PuterFSProvider { - // + async unlink ({ context, node, options = {} }) { + if ( await node.get('type') === TYPE_DIRECTORY ) { + throw new APIError(409, 'Cannot unlink a directory.'); + } + + await this.#rmnode({ context, node, options }); + } + + async #rmnode ({ node, options }) { + console.log('USING THE NEW IMPLEMENTATION'); + // Services + if ( ! options.override_immutable && await node.get('immutable') ) { + throw new APIError(403, 'File is immutable.'); + } + + const userId = await node.get('user_id'); + const fileSize = await node.get('size'); + svc_size.change_usage(userId, + -1 * fileSize); + + const ownerActor = new Actor({ + type: new UserActorType({ + user: await get_user({ id: userId }), + }), + }); + + svc_metering.incrementUsage(ownerActor, 'filesystem:delete:bytes', fileSize); + + const tracer = svc_trace.tracer; + const tasks = new ParallelTasks({ tracer, max: 4 }); + + tasks.add('remove-fsentry', async () => { + await svc_fsEntry.delete(await node.get('uid')); + }); + + if ( await node.get('has-s3') ) { + tasks.add('remove-from-s3', async () => { + // const storage = new PuterS3StorageStrategy({ services: svc }); + const storage = Context.get('storage'); + const state_delete = storage.create_delete(); + await state_delete.run({ + node: node, + }); + }); + } + + await tasks.awaitAll(); + } } const { TmpProxyFSProvider } = extension.import('fs'); extension.on('create.filesystem-types', event => { event.createFilesystemType('puterfs', { - mount({ path }) { + mount ({ path }) { return new TmpProxyFSProvider(path, new PuterFSProvider(path)); }, }); diff --git a/src/backend/src/CoreModule.js b/src/backend/src/CoreModule.js index 587f0b868..bb4bc0094 100644 --- a/src/backend/src/CoreModule.js +++ b/src/backend/src/CoreModule.js @@ -25,6 +25,7 @@ const { Context } = require('./util/context'); const { LLOWrite } = require('./filesystem/ll_operations/ll_write'); const { LLRead } = require('./filesystem/ll_operations/ll_read'); const { RuntimeModule } = require('./extension/RuntimeModule.js'); +const { TYPE_DIRECTORY, TYPE_FILE } = require('./filesystem/FSNodeContext.js'); /** * Core module for the Puter platform that includes essential services including @@ -36,10 +37,10 @@ const { RuntimeModule } = require('./extension/RuntimeModule.js'); * and Core2Module will take on its name. */ class CoreModule extends AdvancedBase { - dirname() { + dirname () { return __dirname; } - async install(context) { + async install (context) { const services = context.get('services'); const app = context.get('app'); const useapi = context.get('useapi'); @@ -57,7 +58,7 @@ class CoreModule extends AdvancedBase { * @param {Object} context.services - Service registry for registering legacy services * @returns {Promise} Resolves when legacy services are installed */ - async install_legacy(context) { + async install_legacy (context) { const services = context.get('services'); await install_legacy({ services }); } @@ -98,6 +99,8 @@ const install = async ({ context, services, app, useapi, modapi }) => { def('core.fs', { LLOWrite, LLRead, + TYPE_DIRECTORY, + TYPE_FILE, }); def('core.fs.selectors', require('./filesystem/node/selectors')); def('core.util.stream', require('./util/streamutil')); diff --git a/src/backend/src/modules/puterfs/lib/PuterFSProvider.js b/src/backend/src/modules/puterfs/lib/PuterFSProvider.js index 5c0e93505..251303375 100644 --- a/src/backend/src/modules/puterfs/lib/PuterFSProvider.js +++ b/src/backend/src/modules/puterfs/lib/PuterFSProvider.js @@ -410,12 +410,8 @@ class PuterFSProvider extends putility.AdvancedBase { } async unlink({ context, node, options = {} }) { - if ( await node.get('type') === TYPE_DIRECTORY ) { - console.log(`\x1B[31;1m===N=====${await node.get('path')}=========\x1B[0m`); - throw new APIError(409, 'Cannot unlink a directory.'); - } - - await this.#rmnode({ context, node, options }); + console.error('This .unlink should not be called!'); + process.exit(1); } async rmdir({ context, node, options = {} }) { diff --git a/src/backend/src/services/drivers/DriverService.js b/src/backend/src/services/drivers/DriverService.js index c23c5c3c6..ceb595766 100644 --- a/src/backend/src/services/drivers/DriverService.js +++ b/src/backend/src/services/drivers/DriverService.js @@ -255,6 +255,7 @@ class DriverService extends BaseService { return await this._call(o); } catch ( e ) { this.log.error('Driver error response: ' + e.toString()); + console.error(e); if ( ! (e instanceof APIError) ) { this.errors.report('driver', { source: e,