Przeglądaj źródła

feat: add group permission endpoints

KernelDeimos 11 miesięcy temu
rodzic
commit
c374b0cbca

+ 38 - 0
packages/backend/src/routers/auth/grant-user-group.js

@@ -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({});
+});

+ 39 - 0
packages/backend/src/routers/auth/revoke-user-group.js

@@ -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({});
+});
+

+ 3 - 3
packages/backend/src/services/PermissionAPIService.js

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

+ 79 - 0
packages/backend/src/services/auth/PermissionService.js

@@ -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) {
         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
      * specified user.