Skip to content

Commit 4302d6d

Browse files
committed
Move URLs for RBAC service endpoints
1 parent 662d89b commit 4302d6d

File tree

6 files changed

+33
-22
lines changed

6 files changed

+33
-22
lines changed

ansible_base/rbac/models/content_type.py

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from ..remote import RemoteObject, get_local_resource_prefix, get_resource_prefix
1111

1212

13-
class DABContentTypeManager(django_models.Manager["DABContentType"]):
13+
class DABContentTypeManager(django_models.Manager[django_models.Model]):
1414
"""Manager storing DABContentType objects in a local cache like original ContentType.
1515
1616
The major structural difference is that the cache keys have to add the service reference.
@@ -20,23 +20,23 @@ class DABContentTypeManager(django_models.Manager["DABContentType"]):
2020

2121
def __init__(self, *args: Any, **kwargs: Any) -> None:
2222
super().__init__(*args, **kwargs)
23-
self._cache: Dict[str, Dict[Union[Tuple[str, str, str], int], "DABContentType"]] = {}
23+
self._cache: Dict[str, Dict[Union[Tuple[str, str, str], int], django_models.Model]] = {}
2424

2525
def clear_cache(self) -> None:
2626
self._cache.clear()
2727

28-
def create(self, *args: Any, **kwargs: Any) -> "DABContentType":
28+
def create(self, *args: Any, **kwargs: Any) -> django_models.Model:
2929
obj = super().create(*args, **kwargs)
3030
self._add_to_cache(self.db, obj)
3131
return obj
3232

33-
def _add_to_cache(self, using: str, ct: "DABContentType") -> None:
33+
def _add_to_cache(self, using: str, ct: django_models.Model) -> None:
3434
"""Store ``ct`` in the manager cache for the given database alias."""
3535
key = (ct.service, ct.app_label, ct.model)
3636
self._cache.setdefault(using, {})[key] = ct
3737
self._cache.setdefault(using, {})[ct.id] = ct
3838

39-
def _get_from_cache(self, opts: Options, service: str) -> "DABContentType":
39+
def _get_from_cache(self, opts: Options, service: str) -> django_models.Model:
4040
"""Return a cached ``DABContentType`` for ``opts`` and ``service``."""
4141
key = (service, opts.app_label, opts.model_name)
4242
return self._cache[self.db][key]
@@ -50,7 +50,7 @@ def get_for_model(
5050
model: Union[Type[django_models.Model], django_models.Model, RemoteObject, Type[RemoteObject]],
5151
for_concrete_model: bool = True,
5252
service: Optional[str] = None,
53-
) -> "DABContentType":
53+
) -> django_models.Model:
5454
# Is a remote object, we only know of these objects by virtue of their content type
5555
if isinstance(model, RemoteObject):
5656
ct = model.content_type
@@ -84,15 +84,15 @@ def get_for_models(
8484
*model_list: Union[Type[django_models.Model], django_models.Model],
8585
for_concrete_models: bool = True,
8686
service: Optional[str] = None,
87-
) -> Dict[Type[django_models.Model], "DABContentType"]:
87+
) -> Dict[Type[django_models.Model], django_models.Model]:
8888
"""Return ``DABContentType`` objects for each model in ``model_list``.
8989
9090
This gets deep into the customization of unique rules for DAB RBAC.
9191
We require that model_name must be unique for a given service,
9292
and this will rely on that assumption, which compares to app_label
9393
in the original ContentType model.
9494
"""
95-
results: Dict[Type[django_models.Model], "DABContentType"] = {}
95+
results: Dict[Type[django_models.Model], django_models.Model] = {}
9696
# A keyed by (service, app_name) unlike Django where it was just app_name
9797
needed_models: Dict[Tuple[str, str], set[str]] = defaultdict(set)
9898
# A dict of (service, app_name, model_name), differs from Django ContentType
@@ -135,8 +135,12 @@ def get_for_models(
135135
)
136136
return results
137137

138-
def get_by_natural_key(self, *args: str) -> "DABContentType":
139-
"""Return the content type identified by its natural key."""
138+
def get_by_natural_key(self, *args: str) -> django_models.Model:
139+
"""Return the content type identified by its natural key.
140+
141+
Note that we can not type hint the return value fully because it is used in migrations.
142+
Migrations will return a prior model state.
143+
"""
140144
if len(args) == 2:
141145
service = get_local_resource_prefix()
142146
app_label, model = args
@@ -160,7 +164,7 @@ def get_by_natural_key(self, *args: str) -> "DABContentType":
160164
self._add_to_cache(self.db, ct)
161165
return ct
162166

163-
def get_for_id(self, id: int) -> "DABContentType":
167+
def get_for_id(self, id: int) -> django_models.Model:
164168
"""Return the content type with primary key ``id`` from the cache."""
165169
try:
166170
return self._cache[self.db][id]
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from django.urls import include, path
2+
3+
from .router import service_router
4+
5+
# These will be included by the resource registry
6+
rbac_service_urls = [
7+
path('', include(service_router.urls)),
8+
]

ansible_base/rbac/urls.py

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,13 @@
44
from ansible_base.rbac.api.views import RoleMetadataView, TeamAccessViewSet, UserAccessViewSet
55
from ansible_base.rbac.apps import AnsibleRBACConfig
66

7-
from .service_api.router import service_router
8-
97
app_name = AnsibleRBACConfig.label
108

11-
12-
service_urls = [
13-
path('', include(service_router.urls)),
14-
]
15-
169
user_access_view = UserAccessViewSet.as_view({'get': 'list'})
1710
team_access_view = TeamAccessViewSet.as_view({'get': 'list'})
1811

1912
api_version_urls = [
2013
path('', include(router.urls)),
21-
path('service-index/', include(service_urls)),
2214
path(r'role_metadata/', RoleMetadataView.as_view(), name="role-metadata"),
2315
path('role_user_access/<str:model_name>/<int:pk>/', user_access_view, name="role-user-access"),
2416
path('role_team_access/<str:model_name>/<int:pk>/', team_access_view, name="role-team-access"),

ansible_base/resource_registry/urls.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from django.urls import include, path
44
from rest_framework import routers
55

6+
from ansible_base.rbac.service_api.urls import rbac_service_urls
67
from ansible_base.resource_registry import views
78

89
logger = logging.getLogger('ansible_base.resource-urls')
@@ -21,4 +22,5 @@
2122

2223
urlpatterns = [
2324
path('service-index/', include(service)),
25+
path('service-index/', include(rbac_service_urls)),
2426
]

ansible_base/resource_registry/views.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,11 @@ def get(self, request, format=None):
183183
data['metadata'] = get_relative_url('service-metadata')
184184
data['resources'] = get_relative_url('resource-list')
185185
data['resource-types'] = get_relative_url('resourcetype-list')
186+
if 'ansible_base.rbac' in settings.INSTALLED_APPS:
187+
data['role-types'] = get_relative_url('dabcontenttype-list')
188+
data['role-permissions'] = get_relative_url('dabpermission-list')
189+
data['role-user-assignments'] = get_relative_url('serviceuserassignment-list')
190+
data['role-team-assignments'] = get_relative_url('serviceteamassignment-list')
186191
return Response(data)
187192

188193

test_app/tests/rbac/api/test_user_permissions.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -202,19 +202,19 @@ def test_team_admins_can_add_children(self, user, user_api_client, organization,
202202
member_rd.give_permission(user, child_team)
203203
admin_rd.give_permission(user, child_team)
204204
response = user_api_client.post(url, data=data)
205-
assert response.status_code == 400
205+
assert response.status_code == 400, response.data
206206
assert 'object does not exist' in response.data['team'][0]
207207
admin_rd.remove_permission(user, child_team) # hacky, need to test (1) in isolation of (2)
208208

209209
# (2) user does not have admin permissions to the target (child) team, cannot make assignment
210210
member_rd.give_permission(user, parent_team)
211211
response = user_api_client.post(url, data=data)
212-
assert response.status_code == 403
212+
assert response.status_code == 403, response.data
213213

214214
# (3) with admin permission to child team and view permission to parent, can make assignment
215215
admin_rd.give_permission(user, child_team)
216216
response = user_api_client.post(url, data=data)
217-
assert response.status_code == 201
217+
assert response.status_code == 201, response.data
218218
assert rando.has_obj_perm(inventory, 'change')
219219

220220

0 commit comments

Comments
 (0)