- ${msg("This application does currently not have any application entitlement defined.")}
+ ${msg(
+ "This application does currently not have any application entitlement defined.",
+ )}
`,
@@ -156,7 +161,9 @@ export class ApplicationEntitlementsPage extends Table {
${msg("Create Entitlement")}
-
+
`;
}
}
From 50711d167f29eba0a910ed2815ba7518fb0f6d9d Mon Sep 17 00:00:00 2001
From: Jens Langhammer
Date: Wed, 20 Nov 2024 15:11:18 +0100
Subject: [PATCH 03/12] add tests and oauth2
Signed-off-by: Jens Langhammer
---
authentik/core/models.py | 7 +++
.../tests/test_application_entitlements.py | 58 +++++++++++++++++++
blueprints/system/providers-oauth2.yaml | 4 +-
3 files changed, 68 insertions(+), 1 deletion(-)
create mode 100644 authentik/core/tests/test_application_entitlements.py
diff --git a/authentik/core/models.py b/authentik/core/models.py
index 9e0ddee784c0..1092a0e44baf 100644
--- a/authentik/core/models.py
+++ b/authentik/core/models.py
@@ -314,6 +314,13 @@ def group_attributes(self, request: HttpRequest | None = None) -> dict[str, Any]
always_merger.merge(final_attributes, self.attributes)
return final_attributes
+ def app_entitlements(self, app: "Application | None") -> QuerySet["ApplicationEntitlement"]:
+ """Get all entitlements this user has for `app`."""
+ if not app:
+ return []
+ all_groups = self.all_groups()
+ return app.applicationentitlement_set.filter(Q(user=self) | Q(group__in=all_groups))
+
@property
def serializer(self) -> Serializer:
from authentik.core.api.users import UserSerializer
diff --git a/authentik/core/tests/test_application_entitlements.py b/authentik/core/tests/test_application_entitlements.py
new file mode 100644
index 000000000000..f01b7744648c
--- /dev/null
+++ b/authentik/core/tests/test_application_entitlements.py
@@ -0,0 +1,58 @@
+"""Test Application Entitlements API"""
+
+
+from rest_framework.test import APITestCase
+
+from authentik.core.models import Application, ApplicationEntitlement, Group
+from authentik.core.tests.utils import create_test_flow, create_test_user
+from authentik.lib.generators import generate_id
+from authentik.providers.oauth2.models import OAuth2Provider
+
+
+class TestApplicationEntitlements(APITestCase):
+ """Test application entitlements"""
+
+ def setUp(self) -> None:
+ self.user = create_test_user()
+ 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(
+ name=generate_id(),
+ slug=generate_id(),
+ provider=self.provider,
+ )
+ ApplicationEntitlement.objects.create(
+ user=self.other_user, app=self.app, name=generate_id()
+ )
+
+ def test_user(self):
+ """Test user-direct assignment"""
+ ent = ApplicationEntitlement.objects.create(
+ user=self.user, app=self.app, name=generate_id()
+ )
+ ents = self.user.app_entitlements(self.app)
+ self.assertEqual(len(ents), 1)
+ self.assertEqual(ents[0].name, ent.name)
+
+ def test_group(self):
+ """Test direct group"""
+ group = Group.objects.create(name=generate_id())
+ self.user.ak_groups.add(group)
+ ent = ApplicationEntitlement.objects.create(group=group, app=self.app, name=generate_id())
+ ents = self.user.app_entitlements(self.app)
+ self.assertEqual(len(ents), 1)
+ self.assertEqual(ents[0].name, ent.name)
+
+ def test_group_indirect(self):
+ """Test indirect group"""
+ parent = Group.objects.create(name=generate_id())
+ group = Group.objects.create(name=generate_id(), parent=parent)
+ self.user.ak_groups.add(group)
+ ent = ApplicationEntitlement.objects.create(group=parent, app=self.app, name=generate_id())
+ ents = self.user.app_entitlements(self.app)
+ self.assertEqual(len(ents), 1)
+ self.assertEqual(ents[0].name, ent.name)
diff --git a/blueprints/system/providers-oauth2.yaml b/blueprints/system/providers-oauth2.yaml
index 7975dd4dcfab..54d304bd90c8 100644
--- a/blueprints/system/providers-oauth2.yaml
+++ b/blueprints/system/providers-oauth2.yaml
@@ -34,6 +34,7 @@ entries:
scope_name: profile
description: "General Profile Information"
expression: |
+ entitlements = [entitlement.name for entitlement in request.user.app_entitlements(provider.application)]
return {
# Because authentik only saves the user's full name, and has no concept of first and last names,
# the full name is used as given name.
@@ -42,8 +43,9 @@ entries:
"given_name": request.user.name,
"preferred_username": request.user.username,
"nickname": request.user.username,
- # groups is not part of the official userinfo schema, but is a quasi-standard
"groups": [group.name for group in request.user.ak_groups.all()],
+ "entitlements": entitlements,
+ "roles": entitlements,
}
- identifiers:
managed: goauthentik.io/providers/oauth2/scope-offline_access
From da3ac785bff380e610b1bf8f5f827fb973578b5b Mon Sep 17 00:00:00 2001
From: Jens Langhammer
Date: Wed, 20 Nov 2024 15:11:28 +0100
Subject: [PATCH 04/12] add to proxy
Signed-off-by: Jens Langhammer
---
authentik/providers/proxy/controllers/k8s/traefik_3.py | 1 +
internal/outpost/proxyv2/application/claims.go | 1 +
internal/outpost/proxyv2/application/mode_common.go | 1 +
tests/e2e/proxy_forward_auth/caddy_single/Caddyfile | 2 +-
tests/e2e/proxy_forward_auth/nginx_single/nginx.conf | 2 ++
.../proxy_forward_auth/traefik_single/config-static.yaml | 1 +
.../add-secure-apps/providers/proxy/_caddy_standalone.md | 2 +-
.../docs/add-secure-apps/providers/proxy/_nginx_ingress.md | 2 +-
.../add-secure-apps/providers/proxy/_nginx_proxy_manager.md | 2 ++
.../add-secure-apps/providers/proxy/_nginx_standalone.md | 2 ++
.../add-secure-apps/providers/proxy/_traefik_compose.md | 2 +-
.../add-secure-apps/providers/proxy/_traefik_ingress.md | 1 +
.../add-secure-apps/providers/proxy/_traefik_standalone.md | 1 +
website/docs/add-secure-apps/providers/proxy/index.md | 6 ++++++
14 files changed, 22 insertions(+), 4 deletions(-)
diff --git a/authentik/providers/proxy/controllers/k8s/traefik_3.py b/authentik/providers/proxy/controllers/k8s/traefik_3.py
index c807ecb63080..132f7621e4d9 100644
--- a/authentik/providers/proxy/controllers/k8s/traefik_3.py
+++ b/authentik/providers/proxy/controllers/k8s/traefik_3.py
@@ -127,6 +127,7 @@ def get_reference_object(self) -> TraefikMiddleware:
authResponseHeaders=[
"X-authentik-username",
"X-authentik-groups",
+ "X-authentik-entitlements",
"X-authentik-email",
"X-authentik-name",
"X-authentik-uid",
diff --git a/internal/outpost/proxyv2/application/claims.go b/internal/outpost/proxyv2/application/claims.go
index 32f4d26ebe88..caf765b40009 100644
--- a/internal/outpost/proxyv2/application/claims.go
+++ b/internal/outpost/proxyv2/application/claims.go
@@ -14,6 +14,7 @@ type Claims struct {
Name string `json:"name"`
PreferredUsername string `json:"preferred_username"`
Groups []string `json:"groups"`
+ Entitlements []string `json:"entitlements"`
Sid string `json:"sid"`
Proxy *ProxyClaims `json:"ak_proxy"`
diff --git a/internal/outpost/proxyv2/application/mode_common.go b/internal/outpost/proxyv2/application/mode_common.go
index 5866f5850b97..30142410922b 100644
--- a/internal/outpost/proxyv2/application/mode_common.go
+++ b/internal/outpost/proxyv2/application/mode_common.go
@@ -41,6 +41,7 @@ func (a *Application) addHeaders(headers http.Header, c *Claims) {
// https://goauthentik.io/docs/providers/proxy/proxy
headers.Set("X-authentik-username", c.PreferredUsername)
headers.Set("X-authentik-groups", strings.Join(c.Groups, "|"))
+ headers.Set("X-authentik-entitlements", strings.Join(c.Entitlements, "|"))
headers.Set("X-authentik-email", c.Email)
headers.Set("X-authentik-name", c.Name)
headers.Set("X-authentik-uid", c.Sub)
diff --git a/tests/e2e/proxy_forward_auth/caddy_single/Caddyfile b/tests/e2e/proxy_forward_auth/caddy_single/Caddyfile
index 741ccee4d5e0..a053fbf84a14 100644
--- a/tests/e2e/proxy_forward_auth/caddy_single/Caddyfile
+++ b/tests/e2e/proxy_forward_auth/caddy_single/Caddyfile
@@ -9,7 +9,7 @@ http://localhost {
uri /outpost.goauthentik.io/auth/caddy
# capitalization of the headers is important, otherwise they will be empty
- copy_headers X-Authentik-Username X-Authentik-Groups X-Authentik-Email X-Authentik-Name X-Authentik-Uid X-Authentik-Jwt X-Authentik-Meta-Jwks X-Authentik-Meta-Outpost X-Authentik-Meta-Provider X-Authentik-Meta-App X-Authentik-Meta-Version
+ copy_headers X-Authentik-Username X-Authentik-Groups X-Authentik-Entitlements X-Authentik-Email X-Authentik-Name X-Authentik-Uid X-Authentik-Jwt X-Authentik-Meta-Jwks X-Authentik-Meta-Outpost X-Authentik-Meta-Provider X-Authentik-Meta-App X-Authentik-Meta-Version
# optional, in this config trust all private ranges, should probably be set to the outposts IP
trusted_proxies private_ranges
diff --git a/tests/e2e/proxy_forward_auth/nginx_single/nginx.conf b/tests/e2e/proxy_forward_auth/nginx_single/nginx.conf
index 50a34064a48c..4697282d1b48 100644
--- a/tests/e2e/proxy_forward_auth/nginx_single/nginx.conf
+++ b/tests/e2e/proxy_forward_auth/nginx_single/nginx.conf
@@ -23,12 +23,14 @@ server {
# translate headers from the outposts back to the actual upstream
auth_request_set $authentik_username $upstream_http_x_authentik_username;
auth_request_set $authentik_groups $upstream_http_x_authentik_groups;
+ auth_request_set $authentik_entitlements $upstream_http_x_authentik_entitlements;
auth_request_set $authentik_email $upstream_http_x_authentik_email;
auth_request_set $authentik_name $upstream_http_x_authentik_name;
auth_request_set $authentik_uid $upstream_http_x_authentik_uid;
proxy_set_header X-authentik-username $authentik_username;
proxy_set_header X-authentik-groups $authentik_groups;
+ proxy_set_header X-authentik-entitlements $authentik_entitlements;
proxy_set_header X-authentik-email $authentik_email;
proxy_set_header X-authentik-name $authentik_name;
proxy_set_header X-authentik-uid $authentik_uid;
diff --git a/tests/e2e/proxy_forward_auth/traefik_single/config-static.yaml b/tests/e2e/proxy_forward_auth/traefik_single/config-static.yaml
index 3d87d4f2ebdd..e08cc99754b2 100644
--- a/tests/e2e/proxy_forward_auth/traefik_single/config-static.yaml
+++ b/tests/e2e/proxy_forward_auth/traefik_single/config-static.yaml
@@ -26,6 +26,7 @@ http:
authResponseHeaders:
- X-authentik-username
- X-authentik-groups
+ - X-authentik-entitlements
- X-authentik-email
- X-authentik-name
- X-authentik-uid
diff --git a/website/docs/add-secure-apps/providers/proxy/_caddy_standalone.md b/website/docs/add-secure-apps/providers/proxy/_caddy_standalone.md
index 2ee6b700cc7a..83582dd6324d 100644
--- a/website/docs/add-secure-apps/providers/proxy/_caddy_standalone.md
+++ b/website/docs/add-secure-apps/providers/proxy/_caddy_standalone.md
@@ -12,7 +12,7 @@ app.company {
uri /outpost.goauthentik.io/auth/caddy
# capitalization of the headers is important, otherwise they will be empty
- copy_headers X-Authentik-Username X-Authentik-Groups X-Authentik-Email X-Authentik-Name X-Authentik-Uid X-Authentik-Jwt X-Authentik-Meta-Jwks X-Authentik-Meta-Outpost X-Authentik-Meta-Provider X-Authentik-Meta-App X-Authentik-Meta-Version
+ copy_headers X-Authentik-Username X-Authentik-Groups X-Authentik-Entitlements X-Authentik-Email X-Authentik-Name X-Authentik-Uid X-Authentik-Jwt X-Authentik-Meta-Jwks X-Authentik-Meta-Outpost X-Authentik-Meta-Provider X-Authentik-Meta-App X-Authentik-Meta-Version
# optional, in this config trust all private ranges, should probably be set to the outposts IP
trusted_proxies private_ranges
diff --git a/website/docs/add-secure-apps/providers/proxy/_nginx_ingress.md b/website/docs/add-secure-apps/providers/proxy/_nginx_ingress.md
index 9ad59e670e4b..e8feee64c2c0 100644
--- a/website/docs/add-secure-apps/providers/proxy/_nginx_ingress.md
+++ b/website/docs/add-secure-apps/providers/proxy/_nginx_ingress.md
@@ -40,7 +40,7 @@ metadata:
nginx.ingress.kubernetes.io/auth-signin: |-
https://app.company/outpost.goauthentik.io/start?rd=$scheme://$http_host$escaped_request_uri
nginx.ingress.kubernetes.io/auth-response-headers: |-
- Set-Cookie,X-authentik-username,X-authentik-groups,X-authentik-email,X-authentik-name,X-authentik-uid
+ Set-Cookie,X-authentik-username,X-authentik-groups,X-authentik-entitlements,X-authentik-email,X-authentik-name,X-authentik-uid
nginx.ingress.kubernetes.io/auth-snippet: |
proxy_set_header X-Forwarded-Host $http_host;
```
diff --git a/website/docs/add-secure-apps/providers/proxy/_nginx_proxy_manager.md b/website/docs/add-secure-apps/providers/proxy/_nginx_proxy_manager.md
index d2f37bd1f05f..93cc153360b1 100644
--- a/website/docs/add-secure-apps/providers/proxy/_nginx_proxy_manager.md
+++ b/website/docs/add-secure-apps/providers/proxy/_nginx_proxy_manager.md
@@ -26,12 +26,14 @@ location / {
# translate headers from the outposts back to the actual upstream
auth_request_set $authentik_username $upstream_http_x_authentik_username;
auth_request_set $authentik_groups $upstream_http_x_authentik_groups;
+ auth_request_set $authentik_entitlements $upstream_http_x_authentik_entitlements;
auth_request_set $authentik_email $upstream_http_x_authentik_email;
auth_request_set $authentik_name $upstream_http_x_authentik_name;
auth_request_set $authentik_uid $upstream_http_x_authentik_uid;
proxy_set_header X-authentik-username $authentik_username;
proxy_set_header X-authentik-groups $authentik_groups;
+ proxy_set_header X-authentik-entitlements $authentik_entitlements;
proxy_set_header X-authentik-email $authentik_email;
proxy_set_header X-authentik-name $authentik_name;
proxy_set_header X-authentik-uid $authentik_uid;
diff --git a/website/docs/add-secure-apps/providers/proxy/_nginx_standalone.md b/website/docs/add-secure-apps/providers/proxy/_nginx_standalone.md
index 3519f4a4c26d..891d9578c886 100644
--- a/website/docs/add-secure-apps/providers/proxy/_nginx_standalone.md
+++ b/website/docs/add-secure-apps/providers/proxy/_nginx_standalone.md
@@ -39,12 +39,14 @@ server {
# translate headers from the outposts back to the actual upstream
auth_request_set $authentik_username $upstream_http_x_authentik_username;
auth_request_set $authentik_groups $upstream_http_x_authentik_groups;
+ auth_request_set $authentik_entitlements $upstream_http_x_authentik_entitlements;
auth_request_set $authentik_email $upstream_http_x_authentik_email;
auth_request_set $authentik_name $upstream_http_x_authentik_name;
auth_request_set $authentik_uid $upstream_http_x_authentik_uid;
proxy_set_header X-authentik-username $authentik_username;
proxy_set_header X-authentik-groups $authentik_groups;
+ proxy_set_header X-authentik-entitlements $authentik_entitlements;
proxy_set_header X-authentik-email $authentik_email;
proxy_set_header X-authentik-name $authentik_name;
proxy_set_header X-authentik-uid $authentik_uid;
diff --git a/website/docs/add-secure-apps/providers/proxy/_traefik_compose.md b/website/docs/add-secure-apps/providers/proxy/_traefik_compose.md
index f749224ef925..b505a08b911e 100644
--- a/website/docs/add-secure-apps/providers/proxy/_traefik_compose.md
+++ b/website/docs/add-secure-apps/providers/proxy/_traefik_compose.md
@@ -32,7 +32,7 @@ services:
# `authentik-proxy` refers to the service name in the compose file.
traefik.http.middlewares.authentik.forwardauth.address: http://authentik-proxy:9000/outpost.goauthentik.io/auth/traefik
traefik.http.middlewares.authentik.forwardauth.trustForwardHeader: true
- traefik.http.middlewares.authentik.forwardauth.authResponseHeaders: X-authentik-username,X-authentik-groups,X-authentik-email,X-authentik-name,X-authentik-uid,X-authentik-jwt,X-authentik-meta-jwks,X-authentik-meta-outpost,X-authentik-meta-provider,X-authentik-meta-app,X-authentik-meta-version
+ traefik.http.middlewares.authentik.forwardauth.authResponseHeaders: X-authentik-username,X-authentik-groups,X-authentik-entitlements,X-authentik-email,X-authentik-name,X-authentik-uid,X-authentik-jwt,X-authentik-meta-jwks,X-authentik-meta-outpost,X-authentik-meta-provider,X-authentik-meta-app,X-authentik-meta-version
restart: unless-stopped
whoami:
diff --git a/website/docs/add-secure-apps/providers/proxy/_traefik_ingress.md b/website/docs/add-secure-apps/providers/proxy/_traefik_ingress.md
index cbf3014b5bc7..4eb8621cfeec 100644
--- a/website/docs/add-secure-apps/providers/proxy/_traefik_ingress.md
+++ b/website/docs/add-secure-apps/providers/proxy/_traefik_ingress.md
@@ -13,6 +13,7 @@ spec:
authResponseHeaders:
- X-authentik-username
- X-authentik-groups
+ - X-authentik-entitlements
- X-authentik-email
- X-authentik-name
- X-authentik-uid
diff --git a/website/docs/add-secure-apps/providers/proxy/_traefik_standalone.md b/website/docs/add-secure-apps/providers/proxy/_traefik_standalone.md
index 1423c747cbb1..138020f396ed 100644
--- a/website/docs/add-secure-apps/providers/proxy/_traefik_standalone.md
+++ b/website/docs/add-secure-apps/providers/proxy/_traefik_standalone.md
@@ -8,6 +8,7 @@ http:
authResponseHeaders:
- X-authentik-username
- X-authentik-groups
+ - X-authentik-entitlements
- X-authentik-email
- X-authentik-name
- X-authentik-uid
diff --git a/website/docs/add-secure-apps/providers/proxy/index.md b/website/docs/add-secure-apps/providers/proxy/index.md
index e3f0c124e66b..6b81f1af2085 100644
--- a/website/docs/add-secure-apps/providers/proxy/index.md
+++ b/website/docs/add-secure-apps/providers/proxy/index.md
@@ -36,6 +36,12 @@ Example value: `foo|bar|baz`
The groups the user is member of, separated by a pipe
+### `X-authentik-entitlements`
+
+Example value: `foo|bar|baz`
+
+The entitlements on the application this user has access to, separated by a pipe
+
### `X-authentik-email`
Example value: `root@localhost`
From 480b7d4167973e36b6a551b1163eb9b52fd6e68d Mon Sep 17 00:00:00 2001
From: Jens Langhammer
Date: Wed, 20 Nov 2024 16:25:51 +0100
Subject: [PATCH 05/12] rewrite to use bindings
Signed-off-by: Jens Langhammer
---
.../core/api/application_entitlements.py | 13 --
.../migrations/0041_applicationentitlement.py | 19 +--
authentik/core/models.py | 7 +-
.../tests/test_application_entitlements.py | 18 +--
authentik/policies/models.py | 4 +-
blueprints/schema.json | 9 --
schema.yml | 40 ------
.../ApplicationEntitlementForm.ts | 114 +-----------------
.../ApplicationEntitlementPage.ts | 89 ++++----------
9 files changed, 44 insertions(+), 269 deletions(-)
diff --git a/authentik/core/api/application_entitlements.py b/authentik/core/api/application_entitlements.py
index 8fa27112157f..7062555c5498 100644
--- a/authentik/core/api/application_entitlements.py
+++ b/authentik/core/api/application_entitlements.py
@@ -2,9 +2,7 @@
from rest_framework.viewsets import ModelViewSet
-from authentik.core.api.groups import GroupSerializer
from authentik.core.api.used_by import UsedByMixin
-from authentik.core.api.users import UserSerializer
from authentik.core.api.utils import ModelSerializer
from authentik.core.models import (
ApplicationEntitlement,
@@ -14,20 +12,13 @@
class ApplicationEntitlementSerializer(ModelSerializer):
"""ApplicationEntitlement Serializer"""
- group_obj = GroupSerializer(required=False, read_only=True, source="group")
- user_obj = UserSerializer(required=False, read_only=True, source="user")
-
class Meta:
model = ApplicationEntitlement
fields = [
"pbm_uuid",
"name",
"app",
- "user",
- "group",
"attributes",
- "group_obj",
- "user_obj",
]
@@ -40,15 +31,11 @@ class ApplicationEntitlementViewSet(UsedByMixin, ModelViewSet):
"pbm_uuid",
"name",
"app",
- "user",
- "group",
"attributes",
]
filterset_fields = [
"pbm_uuid",
"name",
"app",
- "user",
- "group",
]
ordering = ["name"]
diff --git a/authentik/core/migrations/0041_applicationentitlement.py b/authentik/core/migrations/0041_applicationentitlement.py
index 639d037981cf..09c5f9300bb4 100644
--- a/authentik/core/migrations/0041_applicationentitlement.py
+++ b/authentik/core/migrations/0041_applicationentitlement.py
@@ -1,7 +1,6 @@
-# Generated by Django 5.0.9 on 2024-11-20 13:33
+# Generated by Django 5.0.9 on 2024-11-20 15:16
import django.db.models.deletion
-from django.conf import settings
from django.db import migrations, models
@@ -35,22 +34,6 @@ class Migration(migrations.Migration):
on_delete=django.db.models.deletion.CASCADE, to="authentik_core.application"
),
),
- (
- "group",
- models.ForeignKey(
- null=True,
- on_delete=django.db.models.deletion.CASCADE,
- to="authentik_core.group",
- ),
- ),
- (
- "user",
- models.ForeignKey(
- null=True,
- on_delete=django.db.models.deletion.CASCADE,
- to=settings.AUTH_USER_MODEL,
- ),
- ),
],
options={
"verbose_name": "Application Entitlement",
diff --git a/authentik/core/models.py b/authentik/core/models.py
index 1092a0e44baf..a96927355c25 100644
--- a/authentik/core/models.py
+++ b/authentik/core/models.py
@@ -319,7 +319,10 @@ def app_entitlements(self, app: "Application | None") -> QuerySet["ApplicationEn
if not app:
return []
all_groups = self.all_groups()
- return app.applicationentitlement_set.filter(Q(user=self) | Q(group__in=all_groups))
+ return app.applicationentitlement_set.filter(
+ Q(bindings__user=self) | Q(bindings__group__in=all_groups),
+ bindings__enabled=True,
+ )
@property
def serializer(self) -> Serializer:
@@ -594,8 +597,6 @@ class ApplicationEntitlement(AttributesMixin, SerializerModel, PolicyBindingMode
name = models.TextField()
app = models.ForeignKey(Application, on_delete=models.CASCADE)
- user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
- group = models.ForeignKey(Group, on_delete=models.CASCADE, null=True)
class Meta:
verbose_name = _("Application Entitlement")
diff --git a/authentik/core/tests/test_application_entitlements.py b/authentik/core/tests/test_application_entitlements.py
index f01b7744648c..b34648c8db3d 100644
--- a/authentik/core/tests/test_application_entitlements.py
+++ b/authentik/core/tests/test_application_entitlements.py
@@ -1,11 +1,11 @@
"""Test Application Entitlements API"""
-
from rest_framework.test import APITestCase
from authentik.core.models import Application, ApplicationEntitlement, Group
from authentik.core.tests.utils import create_test_flow, create_test_user
from authentik.lib.generators import generate_id
+from authentik.policies.models import PolicyBinding
from authentik.providers.oauth2.models import OAuth2Provider
@@ -25,15 +25,13 @@ def setUp(self) -> None:
slug=generate_id(),
provider=self.provider,
)
- ApplicationEntitlement.objects.create(
- user=self.other_user, app=self.app, name=generate_id()
- )
+ 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"""
- ent = ApplicationEntitlement.objects.create(
- user=self.user, app=self.app, name=generate_id()
- )
+ ent = ApplicationEntitlement.objects.create(app=self.app, name=generate_id())
+ PolicyBinding.objects.create(target=ent, user=self.user, order=0)
ents = self.user.app_entitlements(self.app)
self.assertEqual(len(ents), 1)
self.assertEqual(ents[0].name, ent.name)
@@ -42,7 +40,8 @@ def test_group(self):
"""Test direct group"""
group = Group.objects.create(name=generate_id())
self.user.ak_groups.add(group)
- ent = ApplicationEntitlement.objects.create(group=group, app=self.app, name=generate_id())
+ ent = ApplicationEntitlement.objects.create(app=self.app, name=generate_id())
+ PolicyBinding.objects.create(target=ent, group=group, order=0)
ents = self.user.app_entitlements(self.app)
self.assertEqual(len(ents), 1)
self.assertEqual(ents[0].name, ent.name)
@@ -52,7 +51,8 @@ def test_group_indirect(self):
parent = Group.objects.create(name=generate_id())
group = Group.objects.create(name=generate_id(), parent=parent)
self.user.ak_groups.add(group)
- ent = ApplicationEntitlement.objects.create(group=parent, app=self.app, name=generate_id())
+ ent = ApplicationEntitlement.objects.create(app=self.app, name=generate_id())
+ PolicyBinding.objects.create(target=ent, group=parent, order=0)
ents = self.user.app_entitlements(self.app)
self.assertEqual(len(ents), 1)
self.assertEqual(ents[0].name, ent.name)
diff --git a/authentik/policies/models.py b/authentik/policies/models.py
index 2364dfeb282f..ca78d7eaa9b6 100644
--- a/authentik/policies/models.py
+++ b/authentik/policies/models.py
@@ -81,7 +81,9 @@ class PolicyBinding(SerializerModel):
blank=True,
)
- target = InheritanceForeignKey(PolicyBindingModel, on_delete=models.CASCADE, related_name="+")
+ target = InheritanceForeignKey(
+ PolicyBindingModel, on_delete=models.CASCADE, related_name="bindings"
+ )
negate = models.BooleanField(
default=False,
help_text=_("Negates the outcome of the policy. Messages are unaffected."),
diff --git a/blueprints/schema.json b/blueprints/schema.json
index 4b58b5e6a636..f273ba576d66 100644
--- a/blueprints/schema.json
+++ b/blueprints/schema.json
@@ -13025,15 +13025,6 @@
"type": "integer",
"title": "App"
},
- "user": {
- "type": "integer",
- "title": "User"
- },
- "group": {
- "type": "string",
- "format": "uuid",
- "title": "Group"
- },
"attributes": {
"type": "object",
"additionalProperties": true,
diff --git a/schema.yml b/schema.yml
index 0a917e5449ef..97b966ef1c25 100644
--- a/schema.yml
+++ b/schema.yml
@@ -3107,11 +3107,6 @@ paths:
schema:
type: string
format: uuid
- - in: query
- name: group
- schema:
- type: string
- format: uuid
- in: query
name: name
schema:
@@ -3145,10 +3140,6 @@ paths:
description: A search term.
schema:
type: string
- - in: query
- name: user
- schema:
- type: integer
tags:
- core
security:
@@ -38090,28 +38081,11 @@ components:
app:
type: string
format: uuid
- user:
- type: integer
- nullable: true
- group:
- type: string
- format: uuid
- nullable: true
attributes: {}
- group_obj:
- allOf:
- - $ref: '#/components/schemas/Group'
- readOnly: true
- user_obj:
- allOf:
- - $ref: '#/components/schemas/User'
- readOnly: true
required:
- app
- - group_obj
- name
- pbm_uuid
- - user_obj
ApplicationEntitlementRequest:
type: object
description: ApplicationEntitlement Serializer
@@ -38122,13 +38096,6 @@ components:
app:
type: string
format: uuid
- user:
- type: integer
- nullable: true
- group:
- type: string
- format: uuid
- nullable: true
attributes: {}
required:
- app
@@ -47762,13 +47729,6 @@ components:
app:
type: string
format: uuid
- user:
- type: integer
- nullable: true
- group:
- type: string
- format: uuid
- nullable: true
attributes: {}
PatchedApplicationRequest:
type: object
diff --git a/web/src/admin/applications/entitlements/ApplicationEntitlementForm.ts b/web/src/admin/applications/entitlements/ApplicationEntitlementForm.ts
index 59551462195f..fd93ae611578 100644
--- a/web/src/admin/applications/entitlements/ApplicationEntitlementForm.ts
+++ b/web/src/admin/applications/entitlements/ApplicationEntitlementForm.ts
@@ -1,6 +1,5 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
-import "@goauthentik/components/ak-toggle-group";
import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/forms/HorizontalFormElement";
@@ -12,45 +11,26 @@ import YAML from "yaml";
import { msg } from "@lit/localize";
import { CSSResult } from "lit";
import { TemplateResult, html } from "lit";
-import { customElement, property, state } from "lit/decorators.js";
+import { customElement, property } from "lit/decorators.js";
import PFContent from "@patternfly/patternfly/components/Content/content.css";
import {
ApplicationEntitlement,
CoreApi,
- CoreGroupsListRequest,
- CoreUsersListRequest,
- Group,
- User,
} from "@goauthentik/api";
-enum target {
- group = "group",
- user = "user",
-}
-
@customElement("ak-application-entitlement-form")
export class ApplicationEntitlementForm extends ModelForm {
async loadInstance(pk: string): Promise {
- const entitlement = await new CoreApi(DEFAULT_CONFIG).coreApplicationEntitlementsRetrieve({
+ return new CoreApi(DEFAULT_CONFIG).coreApplicationEntitlementsRetrieve({
pbmUuid: pk,
});
- if (entitlement?.groupObj) {
- this.policyGroupUser = target.group;
- }
- if (entitlement?.userObj) {
- this.policyGroupUser = target.user;
- }
- return entitlement;
}
@property()
targetPk?: string;
- @state()
- policyGroupUser: target = target.group;
-
getSuccessMessage(): string {
if (this.instance?.pbmUuid) {
return msg("Successfully updated entitlement.");
@@ -67,15 +47,6 @@ export class ApplicationEntitlementForm extends ModelForm) => {
- this.policyGroupUser = ev.detail.value;
- }}
- >
-
-
- `;
- }
-
renderForm(): TemplateResult {
return html`
-