Merge branch 'main' of https://github.com/HeyPuter/puter into main

This commit is contained in:
Nariman Jelveh 2024-06-16 18:35:50 -07:00
commit 2a0fb8fe6d
3 changed files with 49 additions and 11 deletions

View File

@ -165,15 +165,24 @@ module.exports = class FSNodeContext {
return ! this.entry.parent_uid;
}
async getUserPart () {
if ( this.isRoot ) return;
async getPathComponents () {
if ( this.isRoot ) return [];
let path = await this.get('path');
if ( path.startsWith('/') ) path = path.slice(1);
const components = path.split('/');
const userpart = components[0];
return path.split('/');
}
return userpart;
async getUserPart () {
if ( this.isRoot ) return;
const components = await this.getPathComponents();
return components[0];
}
async getPathSize () {
if ( this.isRoot ) return;
const components = await this.getPathComponents();
return components.length;
}
async exists (fetch_options = {}) {

View File

@ -31,6 +31,7 @@ const { RootNodeSelector, NodePathSelector } = require("../node/selectors");
const { is_valid_node_name } = require("../validation");
const { HLFilesystemOperation } = require("./definitions");
const { MkTree } = require("./hl_mkdir");
const { Actor } = require("../../services/auth/Actor");
class WriteCommonTrait {
install_in_instance (instance) {
@ -186,10 +187,6 @@ class HLWrite extends HLFilesystemOperation {
throw APIError.create('cannot_write_to_root');
}
if ( values.user && ! await chkperm(await parent.get('entry'), values.user.id, 'write') ) {
throw APIError.create('forbidden');
}
try {
// old validator is kept here to avoid changing the
// error messages; eventually is_valid_node_name
@ -223,6 +220,21 @@ class HLWrite extends HLFilesystemOperation {
throw APIError.create('offset_without_existing_file');
}
// The correct ACL check here depends on context.
// ll_write checks ACL, but we need to shortcut it here
// or else we might send the user too much information.
{
const node_to_check =
( dest_exists && overwrite && ! dedupe_name )
? destination : parent;
const actor = values.actor ?? Actor.adapt(values.user);
const svc_acl = context.get('services').get('acl');
if ( ! await svc_acl.check(actor, node_to_check, 'write') ) {
throw await svc_acl.get_safe_acl_error(actor, node_to_check, 'write');
}
}
if ( dest_exists ) {
console.log('DESTINATION EXISTS', dedupe_name)
if ( ! overwrite && ! dedupe_name ) {

View File

@ -89,6 +89,23 @@ class ACLService extends BaseService {
if ( ! user_perm ) return false;
}
// Hard rule: if app-under-user is accessing appdata directory
// under a **different user**, allow,
// IFF that appdata directory is shared with user
// (by "user also has permission" check above)
if (await (async () => {
if ( ! (actor.type instanceof AppUnderUserActorType) ) {
return false;
}
if ( await fsNode.getUserPart() === actor.type.user.username ) {
return false;
}
const components = await fsNode.getPathComponents();
if ( components[1] !== 'AppData' ) return false;
if ( components[2] !== actor.type.app.uid ) return false;
return true;
})()) return true;
const svc_permission = await context.get('services').get('permission');
const modes = this._higher_modes(mode);