diff --git a/docs/user/basic-concepts.rst b/docs/user/basic-concepts.rst index 69ac29f7..70e0266d 100644 --- a/docs/user/basic-concepts.rst +++ b/docs/user/basic-concepts.rst @@ -160,16 +160,19 @@ Here's a summary of the default organization roles. Organization Manager ~~~~~~~~~~~~~~~~~~~~ -.. image:: https://github.com/openwisp/openwisp-users/raw/docs/docs/images/org-manager.png - :target: https://github.com/openwisp/openwisp-users/raw/docs/docs/images/org-manager.png +.. image:: https://github.com/openwisp/openwisp-users/raw/docs/docs/images/1.3/org-manager.png + :target: https://github.com/openwisp/openwisp-users/raw/docs/docs/images/1.3/org-manager.png :alt: Organization Manager -Any user with the "Is admin" flag enabled for a specific organization (as -shown in the screenshot above) is considered by the system a manager of -that organization. Organization managers have the authority to view and -interact with the data belonging to that organization according to their -set of permissions (as defined in :ref:`Permission Groups -`). +Any user with the "Organization manager" flag enabled for a specific +organization (as shown in the screenshot above) is considered by the +system a manager of that organization. Organization managers have the +authority to view and interact with the data belonging to that +organization according to their set of permissions (as defined in +:ref:`Permission Groups `). + +In the REST API and internal model field, this flag is represented as +``is_admin``. To modify this flag, navigate to the "ORGANIZATION USERS" section on the "Change user" page. @@ -177,13 +180,13 @@ To modify this flag, navigate to the "ORGANIZATION USERS" section on the Organization Members (End-Users) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -.. image:: https://github.com/openwisp/openwisp-users/raw/docs/docs/images/org-member.png - :target: https://github.com/openwisp/openwisp-users/raw/docs/docs/images/org-member.png +.. image:: https://github.com/openwisp/openwisp-users/raw/docs/docs/images/1.3/org-member.png + :target: https://github.com/openwisp/openwisp-users/raw/docs/docs/images/1.3/org-member.png :alt: Organization Member -Any user with the "Is admin" flag disabled for a specific organization (as -shown in the screenshot above) is considered by the system a regular -end-user of that organization. +Any user with the "Organization manager" flag disabled for a specific +organization (``is_admin=False`` in the REST API and internal model field) +is considered by the system a regular end-user of that organization. These users are consumers of a service provided by the organization. They will not be able to see or interact with any object of that organization diff --git a/docs/user/rest-api.rst b/docs/user/rest-api.rst index fb0a3511..d414538e 100644 --- a/docs/user/rest-api.rst +++ b/docs/user/rest-api.rst @@ -265,6 +265,10 @@ Create User users with their email address flagged as verified. This will also skip sending the verification link to their email address. + When creating organization memberships, the organization manager flag + is represented internally by the ``is_admin`` field in the + ``organization_users`` payload. + Get User Detail ~~~~~~~~~~~~~~~ @@ -279,6 +283,12 @@ Change User Detail PUT /api/v1/users/user/{id}/ +.. note:: + + When editing organization memberships, the organization manager flag + is represented internally by the ``is_admin`` field in the + ``organization_users`` payload. + Patch User Detail ~~~~~~~~~~~~~~~~~ @@ -286,6 +296,12 @@ Patch User Detail PATCH /api/v1/users/user/{id}/ +.. note:: + + When patching organization memberships, the organization manager flag + is represented internally by the ``is_admin`` field in the + ``organization_users`` payload. + Delete User ~~~~~~~~~~~ diff --git a/openwisp_users/admin.py b/openwisp_users/admin.py index d1e7dcef..af504df3 100644 --- a/openwisp_users/admin.py +++ b/openwisp_users/admin.py @@ -108,6 +108,7 @@ class OrganizationUserInline(admin.StackedInline): model = OrganizationUser formset = RequiredInlineFormSet view_on_site = False + fields = ("organization", "is_admin") autocomplete_fields = ("organization",) def get_formset(self, request, obj=None, **kwargs): @@ -591,6 +592,7 @@ class OrganizationUserAdmin( ): view_on_site = False actions = ["delete_selected_overridden"] + fields = ("user", "organization", "is_admin") search_fields = ["user__username", "organization__name"] def get_readonly_fields(self, request, obj=None): diff --git a/openwisp_users/api/serializers.py b/openwisp_users/api/serializers.py index 8bbd8404..062ae0e8 100644 --- a/openwisp_users/api/serializers.py +++ b/openwisp_users/api/serializers.py @@ -189,8 +189,8 @@ class OrganizationUserSerializer(serializers.ModelSerializer): class Meta: model = OrganizationUser fields = ( - "is_admin", "organization", + "is_admin", ) def to_internal_value(self, data): diff --git a/openwisp_users/base/models.py b/openwisp_users/base/models.py index 16365ad6..52ff71ce 100644 --- a/openwisp_users/base/models.py +++ b/openwisp_users/base/models.py @@ -485,6 +485,7 @@ class BaseOrganizationUser(models.Model): """ id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) + is_admin = models.BooleanField(_("Organization manager"), default=False) class Meta: abstract = True diff --git a/openwisp_users/migrations/0025_alter_organizationuser_is_admin.py b/openwisp_users/migrations/0025_alter_organizationuser_is_admin.py new file mode 100644 index 00000000..bb9434ec --- /dev/null +++ b/openwisp_users/migrations/0025_alter_organizationuser_is_admin.py @@ -0,0 +1,20 @@ +# Generated by Django 5.2.13 on 2026-07-06 16:59 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("openwisp_users", "0024_apikey"), + ] + + operations = [ + migrations.AlterField( + model_name="organizationuser", + name="is_admin", + field=models.BooleanField( + default=False, verbose_name="Organization manager" + ), + ), + ] diff --git a/openwisp_users/tests/test_admin.py b/openwisp_users/tests/test_admin.py index c56fdf88..ab0ad5cd 100644 --- a/openwisp_users/tests/test_admin.py +++ b/openwisp_users/tests/test_admin.py @@ -523,6 +523,25 @@ def test_organization_user_view_on_site(self): ) self.assertNotContains(response, "viewsitelink") + def test_organization_user_is_admin_label(self): + admin = self._create_admin() + self.client.force_login(admin) + org = self._create_org() + ou = self._create_org_user(organization=org, user=admin) + response = self.client.get( + reverse(f"admin:{self.app_label}_organizationuser_change", args=[ou.pk]) + ) + self.assertContains( + response, + '", + ) + content = response.content.decode() + self.assertLess( + content.index('class="form-row field-organization"'), + content.index('class="form-row field-is_admin"'), + ) + def test_admin_change_user_is_superuser_editable(self): admin = self._create_admin() self.client.force_login(admin) @@ -712,7 +731,7 @@ def test_operator_change_org_is_admin(self): self.assertNotContains( response, '' - '