diff --git a/src/auth_and_perms/api/serializers.py b/src/auth_and_perms/api/serializers.py index 36d55c240..22c52447b 100644 --- a/src/auth_and_perms/api/serializers.py +++ b/src/auth_and_perms/api/serializers.py @@ -18,7 +18,7 @@ from django.conf import settings -from laboratory.utils import check_user_access_kwargs_org_lab +from laboratory.utils import check_user_access_kwargs_org_lab, get_actions_by_perms logger = logging.getLogger('organilab') @@ -359,3 +359,40 @@ class ValidateLabOrgObjectSerializer(serializers.Serializer): allow_null=False,allow_empty=False) +class UserSerializer(serializers.ModelSerializer): + delete_msg = serializers.SerializerMethodField() + actions = serializers.SerializerMethodField() + + def get_delete_msg(self, obj): + return "%s %s %s" % (_("The user"), obj.get_full_name(), + _("could have relations with multiple elements.")) + + def get_actions(self, obj): + user = self.context["request"].user + action_list = { + "destroy": ["auth.delete_user", "auth.view_user"] + } + return get_actions_by_perms(user, action_list) + + class Meta: + model = User + fields = ['id', 'username', 'first_name', 'last_name', 'email', 'delete_msg', + 'actions'] + + +class UserDataTableSerializer(serializers.Serializer): + data = serializers.ListField(child=UserSerializer(), required=True) + draw = serializers.IntegerField(required=True) + recordsFiltered = serializers.IntegerField(required=True) + recordsTotal = serializers.IntegerField(required=True) + + +class UserFilter(FilterSet): + class Meta: + model = User + fields = {'id': ['exact'], + 'username': ['icontains'], + 'first_name': ['icontains'], + 'last_name': ['icontains'], + 'email': ['icontains'], + } diff --git a/src/auth_and_perms/api/viewsets.py b/src/auth_and_perms/api/viewsets.py index fd3250d6b..fcfc41d40 100644 --- a/src/auth_and_perms/api/viewsets.py +++ b/src/auth_and_perms/api/viewsets.py @@ -6,6 +6,7 @@ from django.shortcuts import get_object_or_404 from django.template.loader import render_to_string from django_filters.rest_framework import DjangoFilterBackend +from djgentelella.objectmanagement import AuthAllPermBaseObjectManagement from rest_framework import mixins, viewsets, status from rest_framework.authentication import SessionAuthentication from rest_framework.filters import SearchFilter, OrderingFilter @@ -23,7 +24,8 @@ ProfileAssociateOrganizationSerializer, ValidateGroupsByProfileSerializer, \ ShelfObjectSerializer, ValidateSearchShelfObjectSerializer, \ ShelfObjectDataTableSerializer, ValidateOrganizationSerializer, \ - ExternalUserSerializer, AddExternalUserSerializer + ExternalUserSerializer, AddExternalUserSerializer, UserDataTableSerializer, \ + UserSerializer, UserFilter from auth_and_perms.forms import LaboratoryAndOrganizationForm, \ OrganizationForViewsetForm, SearchShelfObjectViewsetForm from auth_and_perms.models import Rol, ProfilePermission, Profile @@ -458,3 +460,21 @@ def get(self, request): else: return JsonResponse({"errors": serializer.errors}, status=status.HTTP_400_BAD_REQUEST) + +class UserManagementViewset(AuthAllPermBaseObjectManagement): + serializer_class = { + 'list': UserDataTableSerializer, + 'destroy': UserSerializer, + } + perms = { + 'list': ["auth.view_user"], + 'destroy': ["auth.delete_user"] + } + + queryset = User.objects.all() + pagination_class = LimitOffsetPagination + filter_backends = (DjangoFilterBackend, SearchFilter, OrderingFilter) + search_fields = ['id', 'username', 'first_name', 'last_name', 'email'] # for the global search + filterset_class = UserFilter + ordering_fields = ['username', 'first_name'] + ordering = ('id',) # default order diff --git a/src/auth_and_perms/management/commands/urlname_permissions.py b/src/auth_and_perms/management/commands/urlname_permissions.py index 64b1335cf..d25f76af9 100644 --- a/src/auth_and_perms/management/commands/urlname_permissions.py +++ b/src/auth_and_perms/management/commands/urlname_permissions.py @@ -2652,5 +2652,23 @@ 'category': 'Equipment Type', 'permission': 'laboratory.delete_equipmenttype' } + ], + 'manage_users': [ + { + 'name': 'Change User', + 'category': 'User', + 'permission': 'auth.change_user' + }, + { + 'name': 'Delete User', + 'category': 'User', + 'permission': 'auth.delete_user' + }, + { + 'name': 'View User', + 'category': 'User', + 'permission': 'auth.view_user' + } ] + } diff --git a/src/auth_and_perms/templates/auth_and_perms/users_list.html b/src/auth_and_perms/templates/auth_and_perms/users_list.html new file mode 100644 index 000000000..a619e50d7 --- /dev/null +++ b/src/auth_and_perms/templates/auth_and_perms/users_list.html @@ -0,0 +1,76 @@ +{% extends 'base.html' %} +{% load i18n %} +{% load static %} +{% load urlname_tags %} +{% load gtsettings %} +{% block pre_head %} +{% define_urlname_action 'manage_users' %} +{% endblock %} + +{% block title %}{% trans 'Users List' %}{% endblock %} + +{% block content %} +

{% trans 'Users List' %}

+ +
+
+
+ +{% url "auth_and_perms:api-users-detail" 0 as delete_obj_url %} +{% include 'gentelella/blocks/modal_template_delete.html' with form=delete_form id="delete_obj_modal" form_id="delete_obj_form" url=delete_obj_url %} + + +{% endblock %} +{% block js %} +{{block.super}} + +{% endblock %} diff --git a/src/auth_and_perms/urls.py b/src/auth_and_perms/urls.py index 9566cc2e6..6165b97e1 100644 --- a/src/auth_and_perms/urls.py +++ b/src/auth_and_perms/urls.py @@ -4,7 +4,7 @@ OrganizationAPI, \ UserLaboratoryOrganization, UserInOrganization, DeleteUserFromContenttypeViewSet, \ ProfileToContenttypeObjectAPI, UpdateGroupsByProfile, SearchShelfObjectOrganization, \ - OrganizationButtons, ExternalUserToOrganizationViewSet + OrganizationButtons, ExternalUserToOrganizationViewSet, UserManagementViewset from auth_and_perms.views import organizationstructure as orgstruct from rest_framework.routers import SimpleRouter @@ -12,6 +12,7 @@ from auth_and_perms.views import user_org_creation from auth_and_perms.views import fva_rest_authentication from auth_and_perms.views.select_organization import select_organization_by_user +from auth_and_perms.views.users import users_list from authentication.views import SignDataRequestViewSet routes = SimpleRouter() @@ -24,6 +25,7 @@ routes.register('deluserorgcontt', DeleteUserFromContenttypeViewSet, 'api-deluserorgcontt' ) routes.register('relusertocontenttype', ProfileToContenttypeObjectAPI, 'api-relusertocontenttype' ) routes.register('searchshelfobjectorg', SearchShelfObjectOrganization, 'api-searchshelfobjectorg' ) +routes.register('users_list', UserManagementViewset, basename='api-users') app_name='auth_and_perms' @@ -46,5 +48,6 @@ path('organization/manage/relorgcont/add/', orgstruct.add_contenttype_to_org, name="add_contenttype_to_org"), path('digitalsignature/notify', SignDataRequestViewSet.as_view({'post': 'create'})), path('update_groups_by_profile/', UpdateGroupsByProfile.as_view(), name="api_update_groups_by_profile"), - path('organization_buttons/', OrganizationButtons.as_view(), name="api_organization_buttons") + path('organization_buttons/', OrganizationButtons.as_view(), name="api_organization_buttons"), + path('users/', users_list, name="users_list") ] diff --git a/src/auth_and_perms/views/users.py b/src/auth_and_perms/views/users.py new file mode 100644 index 000000000..2732701f8 --- /dev/null +++ b/src/auth_and_perms/views/users.py @@ -0,0 +1,5 @@ +from django.shortcuts import render + + +def users_list(request): + return render(request,"auth_and_perms/users_list.html", context={}) diff --git a/src/laboratory/utils.py b/src/laboratory/utils.py index eebc056d1..3b7a6c008 100644 --- a/src/laboratory/utils.py +++ b/src/laboratory/utils.py @@ -475,6 +475,6 @@ def has_object_permission(self, request, view, obj): def get_actions_by_perms(user, actions_list): actions = {} - for action, perms in actions_list.items() : + for action, perms in actions_list.items(): actions[action] = all_permission(user, perms) return actions diff --git a/src/locale/es/LC_MESSAGES/django.po b/src/locale/es/LC_MESSAGES/django.po index 3f8affd12..725167357 100644 --- a/src/locale/es/LC_MESSAGES/django.po +++ b/src/locale/es/LC_MESSAGES/django.po @@ -4569,3 +4569,12 @@ msgstr "Actualizar consejo de prudencia" msgid "Update the Danger indication" msgstr "Actualizar indicacion de peligro" + +msgid "Users List" +msgstr "Lista de Usuarios" + +msgid "The user" +msgstr "El usuario" + +msgid "could have relations with multiple elements." +msgstr "puede tener relaciones con múltiples elementos." diff --git a/src/locale/es/LC_MESSAGES/djangojs.po b/src/locale/es/LC_MESSAGES/djangojs.po index fd182ba72..65db8acb3 100644 --- a/src/locale/es/LC_MESSAGES/djangojs.po +++ b/src/locale/es/LC_MESSAGES/djangojs.po @@ -617,3 +617,12 @@ msgstr "¿Desea eliminar esta palabra de advertencia?" msgid "Weight" msgstr "Peso" + +msgid "Username" +msgstr "Nombre de usuario" + +msgid "First Name" +msgstr "Nombre" + +msgid "Last Name" +msgstr "Apellidos" diff --git a/src/presentation/templates/partials/auth_and_perms.html b/src/presentation/templates/partials/auth_and_perms.html index 2072a2d35..4a314777d 100644 --- a/src/presentation/templates/partials/auth_and_perms.html +++ b/src/presentation/templates/partials/auth_and_perms.html @@ -11,6 +11,11 @@ {% trans 'Manage Organizations' %} + +
  • + + {% trans 'Users' %} +