diff --git a/src/backend/src/modules/apps/AppPermissionService.js b/src/backend/src/modules/apps/AppPermissionService.js new file mode 100644 index 000000000..a0c2ab7de --- /dev/null +++ b/src/backend/src/modules/apps/AppPermissionService.js @@ -0,0 +1,29 @@ +const { UserActorType } = require('../../services/auth/Actor'); +const { PermissionImplicator, PermissionUtil } = require('../../services/auth/permissionUtils.mjs'); +const BaseService = require('../../services/BaseService'); + +class AppPermissionService extends BaseService { + async _init () { + const svc_permission = this.services.get('permission'); + svc_permission.register_implicator(PermissionImplicator.create({ + id: 'user-can-grant-read-own-apps', + matcher: permission => { + return permission.startsWith('apps-of-user:'); + }, + checker: async ({ actor, permission }) => { + if ( ! (actor.type instanceof UserActorType) ) { + return undefined; + } + + const parts = PermissionUtil.split(permission); + if ( parts[1] === actor.type.user.uuid ) { + return {}; + } + }, + })); + } +} + +module.exports = { + AppPermissionService, +}; diff --git a/src/backend/src/modules/apps/AppsModule.js b/src/backend/src/modules/apps/AppsModule.js index 5cb742612..c56329d6b 100644 --- a/src/backend/src/modules/apps/AppsModule.js +++ b/src/backend/src/modules/apps/AppsModule.js @@ -37,6 +37,9 @@ class AppsModule extends AdvancedBase { const RecommendedAppsService = require('./RecommendedAppsService'); services.registerService('recommended-apps', RecommendedAppsService); + + const { AppPermissionService } = require('./AppPermissionService'); + services.registerService('app-permission', AppPermissionService); } } diff --git a/src/backend/src/om/entitystorage/AppLimitedES.js b/src/backend/src/om/entitystorage/AppLimitedES.js index a8fe6dd69..c98effb7a 100644 --- a/src/backend/src/om/entitystorage/AppLimitedES.js +++ b/src/backend/src/om/entitystorage/AppLimitedES.js @@ -17,6 +17,7 @@ * along with this program. If not, see . */ const { AppUnderUserActorType } = require('../../services/auth/Actor'); +const { PermissionUtil } = require('../../services/auth/permissionUtils.mjs'); const { Context } = require('../../util/context'); const { Eq, Or } = require('../query/query'); const { BaseES } = require('./BaseES'); @@ -28,7 +29,14 @@ class AppLimitedES extends BaseES { async select (options) { const actor = Context.get('actor'); + app_under_user_check: if ( actor.type instanceof AppUnderUserActorType ) { + const svc_permission = Context.get('services').get('permission'); + const perm = PermissionUtil.join('apps-of-user', actor.type.user.uuid, 'read'); + const can_read_any = await svc_permission.check(actor, perm); + + if ( can_read_any ) break app_under_user_check; + if ( this.exception && typeof this.exception === 'function' ) { this.exception = await this.exception(); }