204 lines
6.1 KiB
Python
204 lines
6.1 KiB
Python
"""
|
|
django-rules: декларативные правила доступа для requests_app
|
|
|
|
Правила используются для проверки permissions на уровне объектов.
|
|
https://github.com/dfunckt/django-rules
|
|
"""
|
|
|
|
import rules
|
|
|
|
from employees.positions import employee_position_search_text
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# ПРЕДИКАТЫ (predicates)
|
|
# -----------------------------------------------------------------------------
|
|
|
|
|
|
@rules.predicate
|
|
def is_superuser(user):
|
|
"""Суперпользователь имеет все права"""
|
|
return user.is_superuser
|
|
|
|
|
|
@rules.predicate
|
|
def is_request_author(user, request_obj):
|
|
"""Пользователь является автором заявки"""
|
|
if request_obj is None:
|
|
return False
|
|
return request_obj.created_by == user or request_obj.author == user
|
|
|
|
|
|
@rules.predicate
|
|
def is_request_assignee(user, request_obj):
|
|
"""Пользователь является исполнителем заявки"""
|
|
if request_obj is None:
|
|
return False
|
|
|
|
# Проверка через assigned_to (один исполнитель)
|
|
if hasattr(request_obj, "assigned_to"):
|
|
return request_obj.assigned_to == user
|
|
|
|
# Проверка через assignees (несколько исполнителей)
|
|
if hasattr(request_obj, "assignees"):
|
|
return user in request_obj.assignees.all()
|
|
|
|
return False
|
|
|
|
|
|
@rules.predicate
|
|
def is_request_approver(user, request_obj):
|
|
"""Пользователь назначен согласующим для этой заявки"""
|
|
if request_obj is None:
|
|
return False
|
|
|
|
# Проверка через approvers
|
|
if hasattr(request_obj, "approvers"):
|
|
return user in request_obj.approvers.all()
|
|
|
|
# Проверка через approval_chain
|
|
if hasattr(request_obj, "approval_chain"):
|
|
return request_obj.approval_chain.filter(approver=user).exists()
|
|
|
|
return False
|
|
|
|
|
|
@rules.predicate
|
|
def can_manage_requests(user):
|
|
"""
|
|
Пользователь может управлять заявками (по должности или роли).
|
|
Адаптируйте под вашу логику.
|
|
"""
|
|
position_name = employee_position_search_text(user)
|
|
return any(
|
|
keyword in position_name
|
|
for keyword in [
|
|
"руководитель",
|
|
"начальник",
|
|
"директор",
|
|
"менеджер",
|
|
"администратор",
|
|
]
|
|
)
|
|
|
|
|
|
@rules.predicate
|
|
def is_department_request(user, request_obj):
|
|
"""Заявка относится к отделу пользователя"""
|
|
if request_obj is None or not hasattr(user, "department"):
|
|
return False
|
|
|
|
# Проверка через department
|
|
if hasattr(request_obj, "department"):
|
|
return request_obj.department == user.department
|
|
|
|
# Проверка через автора заявки
|
|
if hasattr(request_obj, "created_by") and hasattr(
|
|
request_obj.created_by, "department"
|
|
):
|
|
return request_obj.created_by.department == user.department
|
|
|
|
return False
|
|
|
|
|
|
@rules.predicate
|
|
def is_request_watcher(user, request_obj):
|
|
"""Пользователь наблюдает за заявкой (подписан на уведомления)"""
|
|
if request_obj is None:
|
|
return False
|
|
|
|
if hasattr(request_obj, "watchers"):
|
|
return user in request_obj.watchers.all()
|
|
|
|
return False
|
|
|
|
|
|
@rules.predicate
|
|
def can_change_request_status(user, request_obj):
|
|
"""Пользователь может менять статус заявки"""
|
|
if request_obj is None:
|
|
return False
|
|
|
|
# Автор может закрывать/отменять свою заявку
|
|
if is_request_author(user, request_obj):
|
|
return True
|
|
|
|
# Исполнитель может переводить в работу/выполнено
|
|
if is_request_assignee(user, request_obj):
|
|
return True
|
|
|
|
# Менеджеры могут менять любые статусы
|
|
if can_manage_requests(user):
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# ПРАВИЛА (rules)
|
|
# -----------------------------------------------------------------------------
|
|
|
|
# Просмотр заявки
|
|
rules.add_rule(
|
|
"requests_app.view_request",
|
|
is_superuser
|
|
| is_request_author
|
|
| is_request_assignee
|
|
| is_request_approver
|
|
| is_request_watcher
|
|
| can_manage_requests,
|
|
)
|
|
|
|
# Изменение заявки
|
|
rules.add_rule(
|
|
"requests_app.change_request",
|
|
is_superuser | is_request_author | can_manage_requests,
|
|
)
|
|
|
|
# Удаление заявки (только автор и менеджеры)
|
|
rules.add_rule(
|
|
"requests_app.delete_request",
|
|
is_superuser | (is_request_author & rules.always_allow) | can_manage_requests,
|
|
)
|
|
|
|
# Назначение исполнителя
|
|
rules.add_rule(
|
|
"requests_app.assign_request",
|
|
is_superuser | can_manage_requests | is_request_author,
|
|
)
|
|
|
|
# Изменение статуса заявки
|
|
rules.add_rule("requests_app.change_status", is_superuser | can_change_request_status)
|
|
|
|
# Согласование заявки
|
|
rules.add_rule(
|
|
"requests_app.approve_request",
|
|
is_superuser | is_request_approver | can_manage_requests,
|
|
)
|
|
|
|
# Комментирование заявки
|
|
rules.add_rule(
|
|
"requests_app.comment_request",
|
|
is_superuser
|
|
| is_request_author
|
|
| is_request_assignee
|
|
| is_request_watcher
|
|
| can_manage_requests,
|
|
)
|
|
|
|
# Добавление наблюдателей
|
|
rules.add_rule(
|
|
"requests_app.add_watchers",
|
|
is_superuser | is_request_author | can_manage_requests,
|
|
)
|
|
|
|
# Просмотр всех заявок отдела
|
|
rules.add_rule(
|
|
"requests_app.view_department_requests", is_superuser | can_manage_requests
|
|
)
|
|
|
|
# Просмотр статистики по заявкам
|
|
rules.add_rule("requests_app.view_statistics", is_superuser | can_manage_requests)
|
|
|
|
|
|
# Примеры использования перенесены в проектную документацию.
|