feat: add group permission endpoints

This commit is contained in:
KernelDeimos 2024-06-27 00:30:46 -04:00 committed by Eric Dubé
parent 4216346384
commit c374b0cbca
4 changed files with 159 additions and 3 deletions

View File

@ -0,0 +1,38 @@
const APIError = require("../../api/APIError");
const eggspress = require("../../api/eggspress");
const { UserActorType } = require("../../services/auth/Actor");
const { Context } = require("../../util/context");
module.exports = eggspress('/auth/grant-user-group', {
subdomain: 'api',
auth2: true,
allowedMethods: ['POST'],
}, async (req, res, next) => {
const x = Context.get();
const svc_permission = x.get('services').get('permission');
// Only users can grant user-group permissions
const actor = Context.get('actor');
if ( ! (actor.type instanceof UserActorType) ) {
throw APIError.create('forbidden');
}
if ( ! req.body.group_uid ) {
throw APIError.create('field_missing', null, {
key: 'group_uid'
});
}
if ( ! req.body.permission ) {
throw APIError.create('field_missing', null, {
key: 'permission'
});
}
await svc_permission.grant_user_group_permission(
actor, req.body.group_uid, req.body.permission,
req.body.extra || {}, req.body.meta || {}
);
res.json({});
});

View File

@ -0,0 +1,39 @@
const APIError = require("../../api/APIError");
const eggspress = require("../../api/eggspress");
const { UserActorType } = require("../../services/auth/Actor");
const { Context } = require("../../util/context");
module.exports = eggspress('/auth/revoke-user-group', {
subdomain: 'api',
auth2: true,
allowedMethods: ['POST'],
}, async (req, res, next) => {
const x = Context.get();
const svc_permission = x.get('services').get('permission');
// Only users can grant user-user permissions
const actor = Context.get('actor');
if ( ! (actor.type instanceof UserActorType) ) {
throw APIError.create('forbidden');
}
if ( ! req.body.group_uid ) {
throw APIError.create('field_missing', null, {
key: 'group_uid'
});
}
if ( ! req.body.permission ) {
throw APIError.create('field_missing', null, {
key: 'permission'
});
}
await svc_permission.revoke_user_group_permission(
actor, req.body.group_uid, req.body.permission,
req.body.meta || {}
);
res.json({});
});

View File

@ -9,14 +9,14 @@ class PermissionAPIService extends BaseService {
express: require('express'), express: require('express'),
}; };
async ['__on_install.routes'] () { async ['__on_install.routes'] (_, { app }) {
const { app } = this.services.get('web-server');
app.use(require('../routers/auth/get-user-app-token')) app.use(require('../routers/auth/get-user-app-token'))
app.use(require('../routers/auth/grant-user-app')) app.use(require('../routers/auth/grant-user-app'))
app.use(require('../routers/auth/revoke-user-app')) app.use(require('../routers/auth/revoke-user-app'))
app.use(require('../routers/auth/grant-user-user')); app.use(require('../routers/auth/grant-user-user'));
app.use(require('../routers/auth/revoke-user-user')); app.use(require('../routers/auth/revoke-user-user'));
app.use(require('../routers/auth/grant-user-group'));
app.use(require('../routers/auth/revoke-user-group'));
app.use(require('../routers/auth/list-permissions')) app.use(require('../routers/auth/list-permissions'))
// track: scoping iife // track: scoping iife

View File

@ -585,6 +585,48 @@ class PermissionService extends BaseService {
] ]
); );
} }
async grant_user_group_permission (actor, gid, permission, extra = {}, meta) {
permission = await this._rewrite_permission(permission);
const svc_group = this.services.get('group');
const group = await svc_group.get({ uid: gid });
if ( ! group ) {
throw new Error('group not found');
}
await this.db.write(
'INSERT INTO `user_to_group_permissions` (`user_id`, `group_id`, `permission`, `extra`) ' +
'VALUES (?, ?, ?, ?) ' +
this.db.case({
mysql: 'ON DUPLICATE KEY UPDATE `extra` = ?',
otherwise: 'ON CONFLICT(`user_id`, `group_id`, `permission`) DO UPDATE SET `extra` = ?',
}),
[
actor.type.user.id,
group.id,
permission,
JSON.stringify(extra),
JSON.stringify(extra),
]
);
// INSERT audit table
await this.db.write(
'INSERT INTO `audit_user_to_group_permissions` (' +
'`user_id`, `user_id_keep`, `group_id`, `group_id_keep`, ' +
'`permission`, `action`, `reason`) ' +
'VALUES (?, ?, ?, ?, ?, ?, ?)',
[
actor.type.user.id,
actor.type.user.id,
group.id,
group.id,
permission,
'grant',
meta?.reason || 'granted via PermissionService',
]
);
}
async revoke_user_user_permission (actor, username, permission, meta) { async revoke_user_user_permission (actor, username, permission, meta) {
permission = await this._rewrite_permission(permission); permission = await this._rewrite_permission(permission);
@ -623,6 +665,43 @@ class PermissionService extends BaseService {
); );
} }
async revoke_user_group_permission (actor, gid, permission, meta) {
permission = await this._rewrite_permission(permission);
const svc_group = this.services.get('group');
const group = await svc_group.get({ uid: gid });
if ( ! group ) {
throw new Error('group not found');
}
// DELETE permission
await this.db.write(
'DELETE FROM `user_to_group_permissions` ' +
'WHERE `user_id` = ? AND `group_id` = ? AND `permission` = ?',
[
actor.type.user.id,
group.id,
permission,
]
);
// INSERT audit table
await this.db.write(
'INSERT INTO `audit_user_to_group_permissions` (' +
'`user_id`, `user_id_keep`, `group_id`, `group_id_keep`, ' +
'`permission`, `action`, `reason`) ' +
'VALUES (?, ?, ?, ?, ?, ?, ?)',
[
actor.type.user.id,
actor.type.user.id,
group.id,
group.id,
permission,
'revoke',
meta?.reason || 'revoked via PermissionService',
]
);
}
/** /**
* List the users that have any permissions granted to the * List the users that have any permissions granted to the
* specified user. * specified user.