diff --git a/authentik/core/models.py b/authentik/core/models.py index a96927355c25..6bc32c248304 100644 --- a/authentik/core/models.py +++ b/authentik/core/models.py @@ -319,10 +319,19 @@ def app_entitlements(self, app: "Application | None") -> QuerySet["ApplicationEn if not app: return [] all_groups = self.all_groups() - return app.applicationentitlement_set.filter( - Q(bindings__user=self) | Q(bindings__group__in=all_groups), + qs = app.applicationentitlement_set.filter( + Q( + Q(bindings__user=self) | Q(bindings__group__in=all_groups), + bindings__negate=False, + ) + | Q( + Q(~Q(bindings__user=self), bindings__user__isnull=False) + | Q(~Q(bindings__group__in=all_groups), bindings__group__isnull=False), + bindings__negate=True, + ), bindings__enabled=True, ) + return qs @property def serializer(self) -> Serializer: diff --git a/authentik/core/tests/test_application_entitlements.py b/authentik/core/tests/test_application_entitlements.py index b34648c8db3d..e392315c9ffc 100644 --- a/authentik/core/tests/test_application_entitlements.py +++ b/authentik/core/tests/test_application_entitlements.py @@ -17,7 +17,6 @@ def setUp(self) -> None: self.other_user = create_test_user() self.provider = OAuth2Provider.objects.create( name="test", - redirect_uris="http://some-other-domain", authorization_flow=create_test_flow(), ) self.app: Application = Application.objects.create( @@ -25,8 +24,6 @@ def setUp(self) -> None: slug=generate_id(), provider=self.provider, ) - ent = ApplicationEntitlement.objects.create(app=self.app, name=generate_id()) - PolicyBinding.objects.create(target=ent, user=self.other_user, order=0) def test_user(self): """Test user-direct assignment""" @@ -56,3 +53,20 @@ def test_group_indirect(self): ents = self.user.app_entitlements(self.app) self.assertEqual(len(ents), 1) self.assertEqual(ents[0].name, ent.name) + + def test_negate_user(self): + """Test with negate flag""" + ent = ApplicationEntitlement.objects.create(app=self.app, name=generate_id()) + PolicyBinding.objects.create(target=ent, user=self.other_user, order=0, negate=True) + ents = self.user.app_entitlements(self.app) + self.assertEqual(len(ents), 1) + self.assertEqual(ents[0].name, ent.name) + + def test_negate_group(self): + """Test with negate flag""" + other_group = Group.objects.create(name=generate_id()) + ent = ApplicationEntitlement.objects.create(app=self.app, name=generate_id()) + PolicyBinding.objects.create(target=ent, group=other_group, order=0, negate=True) + ents = self.user.app_entitlements(self.app) + self.assertEqual(len(ents), 1) + self.assertEqual(ents[0].name, ent.name) diff --git a/authentik/providers/oauth2/tests/test_userinfo.py b/authentik/providers/oauth2/tests/test_userinfo.py index e7cd42326659..0d987f3f9891 100644 --- a/authentik/providers/oauth2/tests/test_userinfo.py +++ b/authentik/providers/oauth2/tests/test_userinfo.py @@ -68,6 +68,8 @@ def test_userinfo_normal(self): "nickname": self.user.name, "groups": [group.name for group in self.user.ak_groups.all()], "sub": "bar", + "roles": [], + "entitlements": [], }, ) self.assertEqual(res.status_code, 200) @@ -90,6 +92,8 @@ def test_userinfo_invalid_scope(self): "nickname": self.user.name, "groups": [group.name for group in self.user.ak_groups.all()], "sub": "bar", + "roles": [], + "entitlements": [], }, ) self.assertEqual(res.status_code, 200)