From df912c4cc4f459be49170548de0292046893ebef Mon Sep 17 00:00:00 2001 From: Paul Marillonnet Date: Thu, 4 Jan 2018 09:18:54 +0100 Subject: [PATCH] WIP add role creation api (#20706) --- src/authentic2/api_urls.py | 7 +++-- src/authentic2/api_views.py | 61 +++++++++++++++++++++++++++++++++++++++--- src/authentic2/app_settings.py | 3 +++ 3 files changed, 66 insertions(+), 5 deletions(-) diff --git a/src/authentic2/api_urls.py b/src/authentic2/api_urls.py index 7175e148..1a986071 100644 --- a/src/authentic2/api_urls.py +++ b/src/authentic2/api_urls.py @@ -9,9 +9,12 @@ urlpatterns = patterns('', name='a2-api-password-change'), url(r'^user/$', api_views.user, name='a2-api-user'), - url(r'^roles/(?P[\w+]*)/members/(?P[^/]+)/$', api_views.roles, - name='a2-api-role-member'), + url(r'^roles/(?P[\w+]*)/members/(?P[^/]+)/$', + api_views.role_memberships, name='a2-api-role-member'), url(r'^check-password/$', api_views.check_password, name='a2-api-check-password'), + url(r'^ous/(?P[\w+]*)/roles/', + api_views.roles, name='a2-api-role'), ) + urlpatterns += api_views.router.urls diff --git a/src/authentic2/api_views.py b/src/authentic2/api_views.py index 928cb8e4..3bd38ba9 100644 --- a/src/authentic2/api_views.py +++ b/src/authentic2/api_views.py @@ -532,7 +532,6 @@ class UsersAPI(HookMixin, ExceptionHandlerMixin, ModelViewSet): User = get_user_model() known_uuids = User.objects.filter(uuid__in=uuids).values_list('uuid', flat=True) return set(uuids) - set(known_uuids) - @list_route(methods=['post'], permission_classes=(DjangoPermission('custom_user.search_user'),)) def synchronization(self, request): serializer = self.SynchronizationSerializer(data=request.data) @@ -576,11 +575,67 @@ class UsersAPI(HookMixin, ExceptionHandlerMixin, ModelViewSet): return Response({'result': 1}) +class ApiMissingFieldsError(Exception): + pass + + +class RoleAlreadyExistsError(Exception): + pass + + class RolesAPI(ExceptionHandlerMixin, APIView): + queryset = get_role_model() + permission_classes = (permissions.IsAuthenticated,) + + _api_fetched_fields = ['uuid', 'name', 'slug', 'admin_scope_ct', + 'admin_scope_id', 'service'] + + def post(self, request, *args, **kwargs): + logger = logging.getLogger(__name__) + + try: + Role = get_role_model() + ou_id_or_ou_slug = kwargs['ou_id_or_ou_slug'] + role_data = request.body['role_data'] + missing_fields = app_settings.A2_ROLES_REQUIRED_FIELDS - role_data.keys() + if missing_fields: + raise ApiMissingFieldsError('No such fields in API request: %r', + missing_fields) + if count(Role.objects.filter(slug=role_data['slug'])): + raise RoleAlreadyExistsError('Error: role already existing in the A2 database') + if 'ou_id_or_ou_slug' not in role_data: + raise Exception('Error: no OU identifier provided, role can\'t be created') + + role = Role.objects.create() + for api_field in self._api_fetched_fields: + if api_field in role_data: + setattr(self, api_field, role_data[api_field]) + OU = get_ou_model() + + # try first on the OU uuid then on its slug + try: + ou = OU.objects.get(uuid=role_data.get('ou_id_or_ou_slug')) + except MultipleObjectsReturned: + ou = OU.objects.get(slug=role_data.get('ou_id_or_ou_slug')) + role.ou = ou + role.save() + + except Exception as e: + logger.error('Couldn\'t create role') + return Response({'result': 0, 'detail': e}, + status=status.HTTP_400_BAD_REQUEST) + + return Response({'result': 1, 'detail': _('Role created')}, + status=status.HTTP_201_CREATED) + +roles = RolesAPI.as_view() + + +class RoleMembershipsAPI(ExceptionHandlerMixin, APIView): permission_classes = (permissions.IsAuthenticated,) def initial(self, request, *args, **kwargs): - super(RolesAPI, self).initial(request, *args, **kwargs) + super(RoleMembershipsAPI, self).initial(request, *args, **kwargs) Role = get_role_model() User = get_user_model() self.role = get_object_or_404(Role, uuid=kwargs['role_uuid']) @@ -601,7 +656,7 @@ class RolesAPI(ExceptionHandlerMixin, APIView): return Response({'result': 1, 'detail': _('User successfully removed from role')}, status=status.HTTP_200_OK) -roles = RolesAPI.as_view() +role_memberships = RoleMembershipsAPI.as_view() class BaseOrganizationalUnitSerializer(serializers.ModelSerializer): diff --git a/src/authentic2/app_settings.py b/src/authentic2/app_settings.py index a5b4d3e0..c94b573a 100644 --- a/src/authentic2/app_settings.py +++ b/src/authentic2/app_settings.py @@ -176,6 +176,9 @@ default_settings = dict( A2_API_USERS_REQUIRED_FIELDS=Setting( default=(), definition='List of fields to require on user\'s API, override other settings'), + A2_API_ROLES_REQUIRED_FIELDS=Setting( + default=(), + definition='List of required fields the role API, override other settings'), A2_USER_FILTER=Setting( default={}, definition='Filters (as in QuerySet.filter() to apply to User queryset before ' -- 2.11.0