Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Group managers UI #108

Merged
merged 13 commits into from
Jan 23, 2025
9 changes: 8 additions & 1 deletion imperial_coldfront_plugin/templates/group_members.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@ <h1>Group Members</h1>
<ul>
{% for member in group_members %}
<li>
{{ member.member.get_full_name }} - <a href="{% url 'imperial_coldfront_plugin:remove_group_member' member.pk %}">Remove access</a>
{{ member.member.get_full_name }} -
<a href="{% url 'imperial_coldfront_plugin:remove_group_member' member.pk %}">Remove access</a>
{% if is_manager == False and member.is_manager == False %}
| <a href="{% url 'imperial_coldfront_plugin:make_manager' member.pk %}">Make manager</a>
{% endif %}
{% if member.is_manager and is_manager == False %}
| <a href="{% url 'imperial_coldfront_plugin:remove_manager' member.pk %}">Remove manager</a>
{% endif %}
</li>
{% endfor %}
</ul>
Expand Down
10 changes: 10 additions & 0 deletions imperial_coldfront_plugin/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,14 @@
),
path("active_users/", views.get_active_users, name="get_active_users"),
path("user_search/", views.user_search, name="user_search"),
path(
"make_manager/<int:group_membership_pk>/",
views.make_group_manager,
name="make_manager",
),
path(
"remove_manager/<int:group_membership_pk>/",
views.remove_group_manager,
name="remove_manager",
),
]
71 changes: 70 additions & 1 deletion imperial_coldfront_plugin/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,18 @@ def group_members_view(request: HttpRequest, user_pk: int) -> HttpResponse:
return render(request, "no_group.html", {"message": "You do not own a group."})

group_members = GroupMembership.objects.filter(group__owner=user)
return render(request, "group_members.html", {"group_members": group_members})
is_manager = GroupMembership.objects.filter(
group__owner=user, member=request.user, is_manager=True
).exists()

return render(
request,
"group_members.html",
{
"group_members": group_members,
"is_manager": is_manager,
},
)


@login_required
Expand Down Expand Up @@ -271,3 +282,61 @@ def get_active_users(request: HttpRequest) -> HttpResponse:
)

return HttpResponse(passwd)


@login_required
def make_group_manager(request: HttpRequest, group_membership_pk: int) -> HttpResponse:
"""Make a group member a manager.

Args:
request: The HTTP request object containing metadata about the request.
group_membership_pk: The primary key of the group membership to be updated.
"""
group_membership = get_object_or_404(GroupMembership, pk=group_membership_pk)
group = group_membership.group

if (
request.user != group.owner
and not request.user.is_superuser
and not GroupMembership.objects.filter(
group=group, member=request.user
).exists()
):
return HttpResponseForbidden("Permission denied")

group_membership.is_manager = True
group_membership.save()

return redirect(
reverse("imperial_coldfront_plugin:group_members", args=[group.owner.pk])
)


@login_required
def remove_group_manager(
request: HttpRequest, group_membership_pk: int
) -> HttpResponse:
"""Remove a group manager.

Args:
request: The HTTP request object containing metadata about the request.
group_membership_pk: The primary key of the group membership to be updated.
"""
group_membership = get_object_or_404(GroupMembership, pk=group_membership_pk)
group = group_membership.group

if (
request.user != group.owner
and not request.user.is_superuser
and not GroupMembership.objects.filter(
group=group, member=request.user
).exists()
):
return HttpResponseForbidden("Permission denied")

group_membership.is_manager = False
group_membership.save()

return redirect(
reverse("imperial_coldfront_plugin:group_members", args=[group.owner.pk])
)
72 changes: 72 additions & 0 deletions tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -413,3 +413,75 @@ def test_no_unixuid(self, auth_client_factory, research_group_factory):
response = auth_client_factory(group.owner).get(self._get_url())
assert response.status_code == HTTPStatus.OK
assert b"" == response.content


class TestMakeGroupManagerView(LoginRequiredMixin):
"""Tests for the make group manager view."""

def _get_url(self, group_membership_pk=1):
return reverse(
"imperial_coldfront_plugin:make_manager", args=[group_membership_pk]
)

def test_not_group_owner(
self, research_group_factory, auth_client_factory, user_client, pi_group
):
"""Test non group owner or manager cannot access the view."""
group, memberships = research_group_factory(number_of_members=1)
client = auth_client_factory(group.owner)
response = client.get(self._get_url())
assert response.status_code == HTTPStatus.FORBIDDEN
assert response.content == b"Permission denied"

def test_group_owner(self, pi_client, pi_group):
"""Test that the group owner can make a group member a manager."""
group_membership = pi_group.groupmembership_set.first()
response = pi_client.get(self._get_url(group_membership.pk))
assertRedirects(
response,
reverse(
"imperial_coldfront_plugin:group_members",
args=[group_membership.group.owner.pk],
),
)

def test_invalid_groupmembership(self, user_client):
"""Test the view response for an invalid group membership."""
response = user_client.get(self._get_url(1))
assert response.status_code == HTTPStatus.NOT_FOUND


class TestRemoveGroupManagerView(LoginRequiredMixin):
"""Tests for the remove group manager view."""

def _get_url(self, group_membership_pk=1):
return reverse(
"imperial_coldfront_plugin:remove_manager", args=[group_membership_pk]
)

def test_not_group_owner(
self, research_group_factory, auth_client_factory, user_client, pi_group
):
"""Test non group owner or manager cannot access the view."""
group, memberships = research_group_factory(number_of_members=1)
client = auth_client_factory(group.owner)
response = client.get(self._get_url())
assert response.status_code == HTTPStatus.FORBIDDEN
assert response.content == b"Permission denied"

def test_group_owner(self, pi_client, pi_group):
"""Test that the group owner can remove a group manager."""
group_membership = pi_group.groupmembership_set.first()
response = pi_client.get(self._get_url(group_membership.pk))
assertRedirects(
response,
reverse(
"imperial_coldfront_plugin:group_members",
args=[group_membership.group.owner.pk],
),
)

def test_invalid_groupmembership(self, user_client):
"""Test the view response for an invalid group membership."""
response = user_client.get(self._get_url(1))
assert response.status_code == HTTPStatus.NOT_FOUND
Loading