mirror of
https://github.com/HeyPuter/puter.git
synced 2025-02-03 07:48:46 +08:00
dev: add /acl/stat-user-user
This new endpoint shows permissions granted by the current user to the specified user in the scope of a specified filesystem node, including permissions on the affecting parent nodes. This is related to two future tasks: - prevent users from sharing a file with the same user twice - add an endpoint to modify the access mode of a shared file
This commit is contained in:
parent
ea4cde82fc
commit
4396630453
@ -17,13 +17,21 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
const APIError = require("../../api/APIError");
|
||||
const FSNodeParam = require("../../api/filesystem/FSNodeParam");
|
||||
const { NodePathSelector } = require("../../filesystem/node/selectors");
|
||||
const { get_user } = require("../../helpers");
|
||||
const configurable_auth = require("../../middleware/configurable_auth");
|
||||
const { Context } = require("../../util/context");
|
||||
const { Endpoint } = require("../../util/expressutil");
|
||||
const BaseService = require("../BaseService");
|
||||
const { AppUnderUserActorType, UserActorType, Actor, SystemActorType, AccessTokenActorType } = require("./Actor");
|
||||
const { PermissionUtil } = require("./PermissionService");
|
||||
|
||||
class ACLService extends BaseService {
|
||||
static MODULES = {
|
||||
express: require('express'),
|
||||
};
|
||||
|
||||
async _init () {
|
||||
const svc_featureFlag = this.services.get('feature-flag');
|
||||
svc_featureFlag.register('public-folders', {
|
||||
@ -44,6 +52,85 @@ class ACLService extends BaseService {
|
||||
});
|
||||
}
|
||||
|
||||
async ['__on_install.routes'] (_, { app }) {
|
||||
const r_acl = (() => {
|
||||
const require = this.require;
|
||||
const express = require('express');
|
||||
return express.Router();
|
||||
})();
|
||||
|
||||
app.use('/acl', r_acl);
|
||||
|
||||
Endpoint({
|
||||
route: '/stat-user-user',
|
||||
methods: ['POST'],
|
||||
mw: [configurable_auth()],
|
||||
handler: async (req, res) => {
|
||||
// Only user actor is allowed
|
||||
if ( ! (req.actor.type instanceof UserActorType) ) {
|
||||
return res.status(403).json({
|
||||
error: 'forbidden',
|
||||
});
|
||||
}
|
||||
|
||||
const holder_user = await get_user({
|
||||
username: req.body.user,
|
||||
});
|
||||
|
||||
if ( ! holder_user ) {
|
||||
throw APIError.create('user_does_not_exist', null, {
|
||||
username: req.body.user,
|
||||
});
|
||||
}
|
||||
|
||||
const issuer = req.actor;
|
||||
const holder = new Actor({
|
||||
type: new UserActorType({
|
||||
user: holder_user,
|
||||
}),
|
||||
});
|
||||
|
||||
const node = await (new FSNodeParam('path')).consolidate({
|
||||
req,
|
||||
getParam: () => req.body.resource,
|
||||
});
|
||||
|
||||
const permissions = await this.stat_user_user(issuer, holder, node);
|
||||
|
||||
res.json({ permissions });
|
||||
}
|
||||
}).attach(r_acl);
|
||||
}
|
||||
|
||||
async stat_user_user (issuer, holder, resource) {
|
||||
const svc_perm = this.services.get('permission');
|
||||
|
||||
if ( ! (issuer.type instanceof UserActorType) ) {
|
||||
throw new Error('issuer must be a UserActorType');
|
||||
}
|
||||
if ( ! (holder.type instanceof UserActorType) ) {
|
||||
throw new Error('holder must be a UserActorType');
|
||||
}
|
||||
|
||||
const permissions = {};
|
||||
|
||||
let perm_fsNode = resource;
|
||||
while ( ! await perm_fsNode.get('is-root') ) {
|
||||
const prefix = PermissionUtil.join('fs', await perm_fsNode.get('uid'));
|
||||
|
||||
const these_permissions = await
|
||||
svc_perm.query_issuer_holder_permissions_by_prefix(issuer, holder, prefix);
|
||||
|
||||
if ( these_permissions.length > 0 ) {
|
||||
permissions[await perm_fsNode.get('path')] = these_permissions;
|
||||
}
|
||||
|
||||
perm_fsNode = await perm_fsNode.getParent();
|
||||
}
|
||||
|
||||
return permissions;
|
||||
}
|
||||
|
||||
async _check_fsNode (actor, fsNode, mode) {
|
||||
const context = Context.get();
|
||||
|
||||
|
@ -639,6 +639,34 @@ class PermissionService extends BaseService {
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* List the permissions that the specified actor (the "issuer")
|
||||
* has granted to the specified user (the "holder") which have
|
||||
* some specified prefix in the permission key (ex: "fs:FILE-UUID")
|
||||
*
|
||||
* Note that if the prefix contains a literal '%' character
|
||||
* the behavior may not be as expected.
|
||||
*
|
||||
* This is a "flat" (non-cascading) view.
|
||||
*
|
||||
* @param {*} issuer
|
||||
* @param {*} holder
|
||||
* @param {*} prefix
|
||||
* @returns
|
||||
*/
|
||||
async query_issuer_holder_permissions_by_prefix (issuer, holder, prefix) {
|
||||
const user_perms = await this.db.read(
|
||||
'SELECT permission ' +
|
||||
'FROM `user_to_user_permissions` ' +
|
||||
'WHERE issuer_user_id = ? ' +
|
||||
'AND holder_user_id = ? ' +
|
||||
'AND permission LIKE ?',
|
||||
[issuer.type.user.id, holder.type.user.id, prefix + '%'],
|
||||
);
|
||||
|
||||
return user_perms.map(row => row.permission);
|
||||
}
|
||||
|
||||
async get_higher_permissions (permission) {
|
||||
const higher_perms = new Set()
|
||||
higher_perms.add(permission);
|
||||
|
Loading…
Reference in New Issue
Block a user