mirror of
https://github.com/HeyPuter/puter.git
synced 2025-02-03 07:48:46 +08:00
feat: implicit access from apps to shared appdata dirs
This commit is contained in:
parent
a2a10b94be
commit
31d4eb090e
@ -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 = {}) {
|
||||
|
@ -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 ) {
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user