diff --git a/src/backend/src/filesystem/FilesystemService.js b/src/backend/src/filesystem/FilesystemService.js index e6de744c5..48da46c71 100644 --- a/src/backend/src/filesystem/FilesystemService.js +++ b/src/backend/src/filesystem/FilesystemService.js @@ -213,17 +213,16 @@ class FilesystemService extends BaseService { return this.systemfs_; } - async owrite ({ - node, user, immutable, - file, tmp, fsentry_tmp, - message, - }) { + // NOTE: these are the parameters being passed + // (assuming this comment is up-to-date) + // { + // node, actor, immutable, + // file, tmp, fsentry_tmp, + // message, + // } + async owrite (parameters) { const ll_owrite = new LLOWrite(); - return await ll_owrite.run({ - node, user, immutable, - file, tmp, fsentry_tmp, - message, - }); + return await ll_owrite.run(parameters); } // REMINDER: There was an idea that FilesystemService implements @@ -235,9 +234,9 @@ class FilesystemService extends BaseService { return await ll_cwrite.run(parameters); } - async mkdir_2 ({parent, name, user, immutable}) { + async mkdir_2 ({parent, name, actor, immutable}) { const ll_mkdir = new LLMkdir(); - return await ll_mkdir.run({ parent, name, user, immutable }); + return await ll_mkdir.run({ parent, name, actor, immutable }); } async mkshortcut ({ parent, name, user, target }) { diff --git a/src/backend/src/filesystem/batch/BatchExecutor.js b/src/backend/src/filesystem/batch/BatchExecutor.js index f7a50ad1e..a0ed2ea5e 100644 --- a/src/backend/src/filesystem/batch/BatchExecutor.js +++ b/src/backend/src/filesystem/batch/BatchExecutor.js @@ -26,11 +26,11 @@ const config = require('../../config'); const { TeePromise } = require('../../util/promise'); class BatchExecutor extends AdvancedBase { - constructor (x, { user, log, errors }) { + constructor (x, { actor, log, errors }) { super(); this.x = x; - this.user = user; - this.pathResolver = new PathResolver({ user }); + this.actor = actor + this.pathResolver = new PathResolver({ actor }); this.expectations = x.get('services').get('expectations'); this.log = log; this.errors = errors; @@ -100,7 +100,7 @@ class BatchExecutor extends AdvancedBase { const command_ins = await command_cls.run({ getFile: () => file, pathResolver: this.pathResolver, - user: this.user + actor: this.actor, }, op); workUnit.checkpoint('operation invoked'); diff --git a/src/backend/src/filesystem/batch/commands.js b/src/backend/src/filesystem/batch/commands.js index 00459b11e..d6419a110 100644 --- a/src/backend/src/filesystem/batch/commands.js +++ b/src/backend/src/filesystem/batch/commands.js @@ -102,7 +102,7 @@ class MkdirCommand extends BatchCommand { parameters.create_missing_parents ?? false, shortcut_to: parameters.shortcut_to, - user: executor.user, + actor: executor.actor, }); if ( parameters.as ) { executor.pathResolver.putSelector( @@ -133,6 +133,9 @@ class WriteCommand extends BatchCommand { } const hl_write = new HLWrite(); + if ( ! executor.actor ) { + throw new Error('Actor is missing here'); + } const response = await hl_write.run({ destination_or_parent: destinationOrParent, specified_name: parameters.name, @@ -145,7 +148,7 @@ class WriteCommand extends BatchCommand { parameters.create_missing_ancestors ?? parameters.create_missing_parents ?? false, - user: executor.user, + actor: executor.actor, file: uploaded_file, offset: parameters.offset, @@ -208,7 +211,7 @@ class ShortcutCommand extends BatchCommand { const response = await hl_mkShortcut.run({ parent: destinationOrParent, name: parameters.name, - user: executor.user, + actor: executor.actor, target: shortcut_to, // TODO: handle these with event service instead @@ -241,7 +244,7 @@ class SymlinkCommand extends BatchCommand { const response = await hl_mkLink.run({ parent: destinationOrParent, name: parameters.name, - user: executor.user, + actor: executor.actor, target: parameters.target, // TODO: handle these with event service instead @@ -266,7 +269,7 @@ class DeleteCommand extends BatchCommand { const hl_remove = new HLRemove(); const response = await hl_remove.run({ target, - user: executor.user, + actor: executor.actor, recursive: parameters.recursive ?? false, descendants_only: parameters.descendants_only ?? false, }); diff --git a/src/backend/src/filesystem/hl_operations/hl_mkdir.js b/src/backend/src/filesystem/hl_operations/hl_mkdir.js index a4cbdb480..648c783be 100644 --- a/src/backend/src/filesystem/hl_operations/hl_mkdir.js +++ b/src/backend/src/filesystem/hl_operations/hl_mkdir.js @@ -76,7 +76,7 @@ class MkTree extends HLFilesystemOperation { const { context, values } = this; const { _path } = this.modules; const fs = context.get('services').get('filesystem'); - const user = context.get('user'); + const actor = context.get('actor'); const trunk = tree[0]; const branches = tree.slice(1); @@ -124,7 +124,7 @@ class MkTree extends HLFilesystemOperation { if ( parent_did_exist && ! parent_exists ) { const node = await fs.node(current); - const has_perm = await chkperm(await node.get('entry'), user.id, 'write'); + const has_perm = await chkperm(await node.get('entry'), actor.type.user.id, 'write'); if ( ! has_perm ) throw APIError.create('permission_denied'); } @@ -147,7 +147,7 @@ class MkTree extends HLFilesystemOperation { const node = await fs.mkdir_2({ parent: await fs.node(currentParent), name: current.name, - user, + actor, }) current = node.selector; @@ -179,7 +179,7 @@ class QuickMkdir extends HLFilesystemOperation { let { parent, path } = values; const { _path } = this.modules; const fs = context.get('services').get('filesystem'); - const user = context.get('user'); + const actor = context.get('actor'); parent = parent || await fs.node(new RootNodeSelector()); @@ -206,7 +206,7 @@ class QuickMkdir extends HLFilesystemOperation { const node = await fs.mkdir_2({ parent: await fs.node(currentParent), name: current.name, - user, + actor, }) current = node.selector; @@ -285,10 +285,12 @@ class HLMkdir extends HLFilesystemOperation { // specified under `path`. parent_node = await this._create_parents({ parent_node: top_parent, - user: values.user, + actor: values.actor, }); - const has_perm = await chkperm(await parent_node.get('entry'), values.user.id, 'write'); + const user_id = values.actor.type.user.id; + + const has_perm = await chkperm(await parent_node.get('entry'), user_id, 'write'); if ( ! has_perm ) throw APIError.create('permission_denied'); const existing = await fs.node( @@ -301,12 +303,12 @@ class HLMkdir extends HLFilesystemOperation { const { overwrite, dedupe_name, create_missing_parents } = values; if ( overwrite ) { // TODO: tag rm operation somehow - const has_perm = await chkperm(await existing.get('entry'), values.user.id, 'write'); + const has_perm = await chkperm(await existing.get('entry'), user_id, 'write'); if ( ! has_perm ) throw APIError.create('permission_denied'); const hl_remove = new HLRemove(); await hl_remove.run({ target: existing, - user: values.user, + actor: values.actor, recursive: true, }); } @@ -345,13 +347,13 @@ class HLMkdir extends HLFilesystemOperation { if ( ! shortcut_to.entry.is_dir ) { throw APIError.create('shortcut_target_is_a_directory'); } - const has_perm = await chkperm(shortcut_to.entry, values.user.id, 'read'); + const has_perm = await chkperm(shortcut_to.entry, user_id, 'read'); if ( ! has_perm ) throw APIError.create('forbidden'); this.created = await fs.mkshortcut({ parent: parent_node, name: target_basename, - user: values.user, + actor: values.actor, target: shortcut_to, }); @@ -362,7 +364,7 @@ class HLMkdir extends HLFilesystemOperation { this.created = await fs.mkdir_2({ parent: parent_node, name: target_basename, - user: values.user, + actor: values.actor, }); const all_nodes = [ @@ -382,7 +384,7 @@ class HLMkdir extends HLFilesystemOperation { return response; } - async _create_parents ({ parent_node, user }) { + async _create_parents ({ parent_node }) { const { context, values } = this; const { _path } = this.modules; const fs = context.get('services').get('filesystem'); diff --git a/src/backend/src/filesystem/hl_operations/hl_write.js b/src/backend/src/filesystem/hl_operations/hl_write.js index 70db88385..70b5b9298 100644 --- a/src/backend/src/filesystem/hl_operations/hl_write.js +++ b/src/backend/src/filesystem/hl_operations/hl_write.js @@ -59,7 +59,10 @@ class WriteCommonFeature { if ( ! this.values.file ) return; const sizeService = this.context.get('services').get('sizeService'); - const { file, user } = this.values; + const { file, user: user_let } = this.values; + let user = user_let; + + if ( ! user ) user = this.values.actor.type.user; const usage = await sizeService.get_usage(user.id); let capacity = config.is_storage_limited ? user.free_storage == undefined @@ -281,13 +284,14 @@ class HLWrite extends HLFilesystemOperation { if ( await shortcut_to.get('type') === TYPE_DIRECTORY ) { throw APIError.create('shortcut_target_is_a_directory'); } - const has_perm = await chkperm(shortcut_to.entry, values.user.id, 'read'); + // TODO: legacy check - likely not needed + const has_perm = await chkperm(shortcut_to.entry, values.actor.type.user.id, 'read'); if ( ! has_perm ) throw APIError.create('permission_denied'); this.created = await fs.mkshortcut({ parent, name: target_name, - user: values.user, + actor: values.actor, target: shortcut_to, }); @@ -381,7 +385,7 @@ class HLWrite extends HLFilesystemOperation { if ( is_overwrite ) { this.written = await fs.owrite({ node: destination, - user: values.user, + actor: values.actor, file: values.file, tmp: { socket_id: values.socket_id, @@ -397,7 +401,7 @@ class HLWrite extends HLFilesystemOperation { this.written = await fs.cwrite({ parent, name: target_name, - user: values.user, + actor: values.actor, file: values.file, tmp: { socket_id: values.socket_id, diff --git a/src/backend/src/filesystem/ll_operations/ll_mkdir.js b/src/backend/src/filesystem/ll_operations/ll_mkdir.js index 72b274d76..005df3243 100644 --- a/src/backend/src/filesystem/ll_operations/ll_mkdir.js +++ b/src/backend/src/filesystem/ll_operations/ll_mkdir.js @@ -55,7 +55,7 @@ class LLMkdir extends LLFilesystemOperation { async _locked_run () { const { _path, uuidv4 } = this.modules; const { context } = this; - const { parent, name, user, immutable, actor } = this.values; + const { parent, name, immutable, actor } = this.values; const ts = Math.round(Date.now() / 1000); const uid = uuidv4(); @@ -95,7 +95,7 @@ class LLMkdir extends LLFilesystemOperation { uuid: uid, parent_uid: await parent.get('uid'), path: _path.join(await parent.get('path'), name), - user_id: user.id, + user_id: actor.type.user.id, name, created: ts, accessed: ts, diff --git a/src/backend/src/filesystem/ll_operations/ll_write.js b/src/backend/src/filesystem/ll_operations/ll_write.js index 5985e734f..9b16fa20f 100644 --- a/src/backend/src/filesystem/ll_operations/ll_write.js +++ b/src/backend/src/filesystem/ll_operations/ll_write.js @@ -128,13 +128,11 @@ class LLWriteBase extends LLFilesystemOperation { class LLOWrite extends LLWriteBase { async _run () { const { - node, user, immutable, + node, actor, immutable, file, tmp, fsentry_tmp, message, } = this.values; - let { actor } = this.values; - const svc = Context.get('services'); const sizeService = svc.get('sizeService'); const resourceService = svc.get('resourceService'); @@ -152,8 +150,6 @@ class LLOWrite extends LLWriteBase { throw APIError.create('subject_does_not_exist'); } - actor = actor ?? Actor.adapt(user); - const svc_acl = this.context.get('services').get('acl'); if ( ! await svc_acl.check(actor, node, 'write') ) { throw await svc_acl.get_safe_acl_error(actor, node, 'write'); @@ -190,7 +186,7 @@ class LLOWrite extends LLWriteBase { }); const filesize = file.size; - sizeService.change_usage(user.id, filesize); + sizeService.change_usage(actor.type.user.id, filesize); const entryOp = await systemFSEntryService.update(uid, raw_fsentry_delta); @@ -202,7 +198,7 @@ class LLOWrite extends LLWriteBase { })(); state_upload.post_insert({ - db, user, node, uid, message, ts, + db, user: actor.type.user, node, uid, message, ts, }); const svc_fileCache = this.context.get('services').get('file-cache'); @@ -227,7 +223,7 @@ class LLCWrite extends LLWriteBase { async _run () { const { _path, uuidv4, config } = this.modules; const { - parent, name, user, immutable, + parent, name, immutable, file, tmp, fsentry_tmp, message, @@ -261,7 +257,7 @@ class LLCWrite extends LLWriteBase { } const svc_acl = this.context.get('services').get('acl'); - actor = actor ?? Actor.adapt(user) ?? Context.get('actor'); + actor = actor ?? Context.get('actor'); if ( ! await svc_acl.check(actor, parent, 'write') ) { throw await svc_acl.get_safe_acl_error(actor, parent, 'write'); } @@ -288,7 +284,7 @@ class LLCWrite extends LLWriteBase { const raw_fsentry = { uuid: uid, is_dir: 0, - user_id: user.id, + user_id: actor.type.user.id, created: ts, accessed: ts, modified: ts, @@ -317,7 +313,7 @@ class LLCWrite extends LLWriteBase { }); const filesize = file.size; - sizeService.change_usage(user.id, filesize); + sizeService.change_usage(actor.type.user.id, filesize); this.checkpoint('after change_usage'); @@ -338,7 +334,7 @@ class LLCWrite extends LLWriteBase { db.write( "INSERT INTO `fsentry_versions` (`user_id`, `fsentry_id`, `fsentry_uuid`, `version_id`, `message`, `ts_epoch`) VALUES (?, ?, ?, ?, ?, ?)", [ - user.id, + actor.type.user.id, new_item.id, new_item.uuid, store_version_id, diff --git a/src/backend/src/routers/filesystem_api/batch/PathResolver.js b/src/backend/src/routers/filesystem_api/batch/PathResolver.js index a403c5d62..d2b75d1d4 100644 --- a/src/backend/src/routers/filesystem_api/batch/PathResolver.js +++ b/src/backend/src/routers/filesystem_api/batch/PathResolver.js @@ -33,11 +33,11 @@ const ERR_UNKNOWN_PATHREF = 'Unknown path reference in path: '; * that was returned by the `mkdir` operation. */ module.exports = class PathResolver { - constructor ({ user }) { + constructor ({ actor }) { this.references = {}; this.selectors = {}; this.meta = {}; - this.user = user; + this.actor = actor; this.listeners = {}; @@ -88,11 +88,13 @@ module.exports = class PathResolver { } async awaitSelector (inputPath) { + // TODO: I feel like there's a better way to get username + const username = this.actor.type.user.username; if ( inputPath.startsWith('~/') ) { - return `/${this.user.username}/${inputPath.substring(2)}`; + return `/${username}/${inputPath.substring(2)}`; } if ( inputPath === '~' ) { - return `/${this.user.username}`; + return `/${username}`; } const refName = this.getReferenceUsed(inputPath); if ( refName === null ) return inputPath; diff --git a/src/backend/src/routers/filesystem_api/batch/all.js b/src/backend/src/routers/filesystem_api/batch/all.js index 6e92ab08d..f92d1f77d 100644 --- a/src/backend/src/routers/filesystem_api/batch/all.js +++ b/src/backend/src/routers/filesystem_api/batch/all.js @@ -127,9 +127,12 @@ module.exports = eggspress('/batch', { if ( op_spec.op === 'write' ) return true; return false; } + if ( ! req.actor ) { + throw new Error('Actor is missing here'); + } const batch_exe = new BatchExecutor(x, { log, errors, - user: req.user, + actor: req.actor, }); // --- state const pending_operations = [];