fix(tasks): require board membership for admins

This commit is contained in:
lizerk 2026-08-10 11:38:44 +03:00
parent 47d48c45f4
commit f5da80ce3f
3 changed files with 36 additions and 21 deletions

View File

@ -34,9 +34,6 @@ def get_user_department_ids(user) -> list[int]:
def task_board_access_q(user):
if getattr(user, "is_staff", False) or getattr(user, "is_superuser", False):
return Q()
department_ids = get_user_department_ids(user)
q = Q(created_by=user)
non_private_q = ~Q(access_scope=TaskBoardAccessScope.PRIVATE)
@ -63,8 +60,6 @@ def task_board_group_access_q(user):
def user_can_access_task_board(user, board: TaskBoard | None) -> bool:
if not user or not user.is_authenticated or board is None:
return False
if user.is_staff or user.is_superuser:
return True
if board.created_by_id == user.id:
return True
if board.access_scope == TaskBoardAccessScope.PRIVATE:

View File

@ -5,7 +5,6 @@ from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer
from django.contrib.auth import get_user_model
from django.db import transaction
from django.db.models import Q
from employees.models import Department, EmployeeDepartment, RoleAssignment
@ -19,7 +18,6 @@ def get_task_board_recipient_ids(board: TaskBoard) -> set[int]:
return set()
User = get_user_model()
admin_q = Q(is_staff=True) | Q(is_superuser=True)
is_private = board.access_scope == TaskBoardAccessScope.PRIVATE
if (
@ -64,12 +62,6 @@ def get_task_board_recipient_ids(board: TaskBoard) -> set[int]:
).values_list("employee_id", flat=True)
)
recipient_ids.update(
User.objects.filter(is_active=True)
.filter(admin_q)
.values_list("id", flat=True)
)
return set(
User.objects.filter(
id__in={user_id for user_id in recipient_ids if user_id},

View File

@ -2428,7 +2428,7 @@ def test_create_board_accepts_members_and_departments(api_client, user):
assert TaskColumn.objects.filter(board_id=response.data["id"]).count() == 4
def test_private_board_is_available_only_to_owner_and_admin(api_client):
def test_private_board_is_available_only_to_owner(api_client):
owner = make_user("task-private-owner@example.com", "+79994440901")
selected_member = make_user("task-private-member@example.com", "+79994440902")
department_member = make_user("task-private-dept@example.com", "+79994440903")
@ -2462,9 +2462,9 @@ def test_private_board_is_available_only_to_owner_and_admin(api_client):
assert create_response.data["members"] == []
assert create_response.data["departments"] == []
board = TaskBoard.objects.get(id=create_response.data["id"])
assert get_task_board_recipient_ids(board) == {owner.id, admin.id}
assert get_task_board_recipient_ids(board) == {owner.id}
for hidden_user in (selected_member, department_member, outsider):
for hidden_user in (selected_member, department_member, outsider, admin):
api_client.force_authenticate(user=hidden_user)
list_response = api_client.get(reverse("api:v1:tasks:task-board-list"))
assert list_response.status_code == status.HTTP_200_OK
@ -2474,11 +2474,39 @@ def test_private_board_is_available_only_to_owner_and_admin(api_client):
)
assert detail_response.status_code == status.HTTP_404_NOT_FOUND
api_client.force_authenticate(user=admin)
admin_response = api_client.get(
reverse("api:v1:tasks:task-board-detail", kwargs={"pk": board.id})
def test_admin_needs_membership_to_access_restricted_board(api_client):
owner = make_user("task-restricted-owner@example.com", "+79994440911")
admin = make_user(
"task-restricted-admin@example.com",
"+79994440912",
is_staff=True,
is_superuser=True,
)
assert admin_response.status_code == status.HTTP_200_OK
board = TaskBoard.objects.create(
name="Выборочная доска",
created_by=owner,
access_scope="restricted",
)
detail_url = reverse(
"api:v1:tasks:task-board-detail",
kwargs={"pk": board.id},
)
api_client.force_authenticate(user=admin)
list_response = api_client.get(reverse("api:v1:tasks:task-board-list"))
assert list_response.status_code == status.HTTP_200_OK
assert board.id not in {item["id"] for item in list_response.data["results"]}
assert api_client.get(detail_url).status_code == status.HTTP_404_NOT_FOUND
assert (
api_client.patch(detail_url, {"name": "Чужое изменение"}, format="json").status_code
== status.HTTP_404_NOT_FOUND
)
assert api_client.delete(detail_url).status_code == status.HTTP_404_NOT_FOUND
board.members.add(admin)
assert api_client.get(detail_url).status_code == status.HTTP_200_OK
def test_board_member_can_access_private_board(api_client):
@ -2590,7 +2618,7 @@ def test_task_board_realtime_recipients_match_board_access():
assert member.id in recipients
assert department_user.id in recipients
assert role_user.id in recipients
assert admin.id in recipients
assert admin.id not in recipients
assert outsider.id not in recipients
assert inactive_member.id not in recipients