diff --git a/src/backend/src/CoreModule.js b/src/backend/src/CoreModule.js index 9328d032..3a1f30bf 100644 --- a/src/backend/src/CoreModule.js +++ b/src/backend/src/CoreModule.js @@ -308,6 +308,9 @@ const install = async ({ services, app, useapi, modapi }) => { const { GroupService } = require('./services/auth/GroupService'); services.registerService('group', GroupService); + + const { VirtualGroupService } = require('./services/auth/VirtualGroupService'); + services.registerService('virtual-group', VirtualGroupService); const { PermissionAPIService } = require('./services/PermissionAPIService'); services.registerService('__permission-api', PermissionAPIService); diff --git a/src/backend/src/services/auth/VirtualGroupService.js b/src/backend/src/services/auth/VirtualGroupService.js new file mode 100644 index 00000000..e0bd0a67 --- /dev/null +++ b/src/backend/src/services/auth/VirtualGroupService.js @@ -0,0 +1,34 @@ +const BaseService = require("../BaseService"); + +class VirtualGroupService extends BaseService { + _construct () { + this.groups_ = {}; + this.membership_implicators_ = []; + } + + register_membership_implicator (implicator) { + this.membership_implicators_.push(implicator); + } + + add_group (group) { + this.groups_[group.id] = group; + } + + get_virtual_groups ({ actor }) { + const groups_set = {}; + + for ( const implicator of this.membership_implicators_ ) { + const groups = implicator.run({ actor }); + for ( const group of groups ) { + groups_set[group] = true; + } + } + + const groups = Object.keys(groups_set).map( + id => this.groups_[id]); + + return groups; + } +} + +module.exports = { VirtualGroupService }; diff --git a/src/backend/src/unstructured/permission-scanners.js b/src/backend/src/unstructured/permission-scanners.js index 90790321..4dc4ee88 100644 --- a/src/backend/src/unstructured/permission-scanners.js +++ b/src/backend/src/unstructured/permission-scanners.js @@ -202,6 +202,31 @@ const PERMISSION_SCANNERS = [ } } }, + { + name: 'user-virtual-group-user', + async scan (a) { + const svc_virtualGroup = await a.iget('services').get('virtual-group'); + const { reading, actor, permission_options } = a.values(); + const groups = svc_virtualGroup.get_virtual_groups({ actor }); + + for ( const group of groups ) { + for ( const perm_entry of group.permissions ) { + const { permission, data } = perm_entry; + if ( ! permission_options.includes(permission) ) { + continue; + } + reading.push({ + $: 'option', + permission, + data, + holder_username: actor.type.user.username, + source: 'virtual-group', + vgroup_id: group.id, + }); + } + } + } + }, { name: 'user-app', async scan (a) {