Files
puter/src/backend/src/om/entitystorage/ProtectedAppES.js
T

96 lines
3.1 KiB
JavaScript

/*
* Copyright (C) 2024-present 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 { AppUnderUserActorType, UserActorType } = require('../../services/auth/Actor');
const { PermissionUtil } = require('../../services/auth/permissionUtils.mjs');
const { Context } = require('../../util/context');
const { BaseES } = require('./BaseES');
class ProtectedAppES extends BaseES {
async select (options) {
const results = await this.upstream.select(options);
const actor = Context.get('actor');
const services = Context.get('services');
for ( let i = 0 ; i < results.length ; i++ ) {
const entity = results[i];
if ( ! await this.check_({ actor, services }, entity) ) {
continue;
}
results[i] = undefined;
}
return results.filter(e => e !== undefined);
}
async read (uid) {
const entity = await this.upstream.read(uid);
if ( ! entity ) return null;
const actor = Context.get('actor');
const services = Context.get('services');
if ( await this.check_({ actor, services }, entity) ) {
return null;
}
return entity;
}
/**
* returns true if the entity should not be sent downstream
*/
async check_ ({ actor, services }, entity) {
// track: ruleset
{
// if it's not a protected app, no worries
if ( ! await entity.get('protected') ) return;
// if actor is this app, no worries
if (
actor.type instanceof AppUnderUserActorType &&
await entity.get('uid') === actor.type.app.uid
) return;
// if actor is owner of this app, no worries
if (
actor.type instanceof UserActorType &&
(await entity.get('owner')).id === actor.type.user.id
) return;
}
// now we need to check for permission
const app_uid = await entity.get('uid');
const svc_permission = services.get('permission');
const permission_to_check = `app:uid#${app_uid}:access`;
const reading = await svc_permission.scan(actor, permission_to_check);
const options = PermissionUtil.reading_to_options(reading);
if ( options.length > 0 ) return;
// `true` here means "do not send downstream"
return true;
}
};
module.exports = {
ProtectedAppES,
};