tests-passed
This commit is contained in:
@@ -1,16 +1,23 @@
|
||||
"""
|
||||
Тесты для новой системы RBAC (Role-Based Access Control).
|
||||
Тесты для системы RBAC (Role-Based Access Control).
|
||||
|
||||
Проверяет работу системы ролей и разрешений на основе CSV хранения
|
||||
в таблице CommunityAuthor.
|
||||
Проверяет работу с ролями, разрешениями и наследованием ролей.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
import time
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
from auth.orm import Author
|
||||
from orm.community import Community, CommunityAuthor
|
||||
from services.rbac import get_role_permissions_for_community, get_permissions_for_role
|
||||
from orm.reaction import REACTION_KINDS
|
||||
from services.rbac import (
|
||||
initialize_community_permissions,
|
||||
get_role_permissions_for_community,
|
||||
get_permissions_for_role,
|
||||
user_has_permission,
|
||||
roles_have_permission
|
||||
)
|
||||
from services.db import local_session
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
@@ -20,7 +27,7 @@ def test_users(db_session):
|
||||
|
||||
# Создаем пользователей с ID 1-5
|
||||
for i in range(1, 6):
|
||||
user = db_session.query(Author).filter(Author.id == i).first()
|
||||
user = db_session.query(Author).where(Author.id == i).first()
|
||||
if not user:
|
||||
user = Author(id=i, email=f"user{i}@example.com", name=f"Test User {i}", slug=f"test-user-{i}")
|
||||
user.set_password("password123")
|
||||
@@ -34,7 +41,7 @@ def test_users(db_session):
|
||||
@pytest.fixture
|
||||
def test_community(db_session, test_users):
|
||||
"""Создает тестовое сообщество"""
|
||||
community = db_session.query(Community).filter(Community.id == 1).first()
|
||||
community = db_session.query(Community).where(Community.id == 1).first()
|
||||
if not community:
|
||||
community = Community(
|
||||
id=1,
|
||||
@@ -42,372 +49,283 @@ def test_community(db_session, test_users):
|
||||
slug="test-community",
|
||||
desc="Test community for RBAC tests",
|
||||
created_by=test_users[0].id,
|
||||
created_at=int(time.time())
|
||||
)
|
||||
db_session.add(community)
|
||||
db_session.commit()
|
||||
|
||||
return community
|
||||
|
||||
|
||||
class TestCommunityAuthorRoles:
|
||||
"""Тесты для управления ролями в CommunityAuthor"""
|
||||
class TestRBACRoleInheritance:
|
||||
"""Тесты для проверки наследования ролей"""
|
||||
|
||||
def test_role_list_property(self, db_session, test_users, test_community):
|
||||
"""Тест свойства role_list для CSV ролей"""
|
||||
# Очищаем существующие записи для этого пользователя
|
||||
db_session.query(CommunityAuthor).filter(
|
||||
CommunityAuthor.community_id == test_community.id, CommunityAuthor.author_id == test_users[0].id
|
||||
).delete()
|
||||
db_session.commit()
|
||||
@pytest.mark.asyncio
|
||||
async def test_role_inheritance_author_inherits_reader(self, db_session, test_community):
|
||||
"""Тест что роль author наследует разрешения от reader"""
|
||||
# Инициализируем разрешения для сообщества
|
||||
await initialize_community_permissions(test_community.id)
|
||||
|
||||
# Создаем запись с ролями
|
||||
ca = CommunityAuthor(community_id=test_community.id, author_id=test_users[0].id, roles="reader,author,expert")
|
||||
db_session.add(ca)
|
||||
db_session.commit()
|
||||
# Получаем разрешения для роли author
|
||||
author_permissions = await get_permissions_for_role("author", test_community.id)
|
||||
reader_permissions = await get_permissions_for_role("reader", test_community.id)
|
||||
|
||||
# Проверяем получение списка ролей
|
||||
assert ca.role_list == ["reader", "author", "expert"]
|
||||
# Проверяем что author имеет все разрешения reader
|
||||
for perm in reader_permissions:
|
||||
assert perm in author_permissions, f"Author должен наследовать разрешение {perm} от reader"
|
||||
|
||||
# Проверяем установку списка ролей
|
||||
ca.role_list = ["admin", "editor"]
|
||||
assert ca.roles == "admin,editor"
|
||||
# Проверяем что author имеет дополнительные разрешения
|
||||
author_specific = ["draft:read", "draft:create", "shout:create", "shout:update_own"]
|
||||
for perm in author_specific:
|
||||
assert perm in author_permissions, f"Author должен иметь разрешение {perm}"
|
||||
|
||||
# Проверяем пустые роли
|
||||
ca.role_list = []
|
||||
assert ca.roles is None
|
||||
assert ca.role_list == []
|
||||
@pytest.mark.asyncio
|
||||
async def test_role_inheritance_editor_inherits_author(self, db_session, test_community):
|
||||
"""Тест что роль editor наследует разрешения от author"""
|
||||
await initialize_community_permissions(test_community.id)
|
||||
|
||||
def test_has_role(self, db_session, test_users, test_community):
|
||||
"""Тест проверки наличия роли"""
|
||||
# Очищаем существующие записи
|
||||
db_session.query(CommunityAuthor).filter(
|
||||
CommunityAuthor.community_id == test_community.id, CommunityAuthor.author_id == test_users[1].id
|
||||
).delete()
|
||||
db_session.commit()
|
||||
editor_permissions = await get_permissions_for_role("editor", test_community.id)
|
||||
author_permissions = await get_permissions_for_role("author", test_community.id)
|
||||
|
||||
ca = CommunityAuthor(community_id=test_community.id, author_id=test_users[1].id, roles="reader,author")
|
||||
db_session.add(ca)
|
||||
db_session.commit()
|
||||
# Проверяем что editor имеет все разрешения author
|
||||
for perm in author_permissions:
|
||||
assert perm in editor_permissions, f"Editor должен наследовать разрешение {perm} от author"
|
||||
|
||||
# Проверяем существующие роли
|
||||
assert ca.has_role("reader") is True
|
||||
assert ca.has_role("author") is True
|
||||
# Проверяем что editor имеет дополнительные разрешения
|
||||
editor_specific = ["shout:delete_any", "shout:update_any", "topic:create", "community:create"]
|
||||
for perm in editor_specific:
|
||||
assert perm in editor_permissions, f"Editor должен иметь разрешение {perm}"
|
||||
|
||||
# Проверяем несуществующие роли
|
||||
assert ca.has_role("admin") is False
|
||||
assert ca.has_role("editor") is False
|
||||
@pytest.mark.asyncio
|
||||
async def test_role_inheritance_admin_inherits_editor(self, db_session, test_community):
|
||||
"""Тест что роль admin наследует разрешения от editor"""
|
||||
await initialize_community_permissions(test_community.id)
|
||||
|
||||
def test_add_role(self, db_session, test_users, test_community):
|
||||
"""Тест добавления роли"""
|
||||
# Очищаем существующие записи
|
||||
db_session.query(CommunityAuthor).filter(
|
||||
CommunityAuthor.community_id == test_community.id, CommunityAuthor.author_id == test_users[2].id
|
||||
).delete()
|
||||
db_session.commit()
|
||||
admin_permissions = await get_permissions_for_role("admin", test_community.id)
|
||||
editor_permissions = await get_permissions_for_role("editor", test_community.id)
|
||||
|
||||
ca = CommunityAuthor(community_id=test_community.id, author_id=test_users[2].id, roles="reader")
|
||||
db_session.add(ca)
|
||||
db_session.commit()
|
||||
# Проверяем что admin имеет все разрешения editor
|
||||
for perm in editor_permissions:
|
||||
assert perm in admin_permissions, f"Admin должен наследовать разрешение {perm} от editor"
|
||||
|
||||
# Добавляем новую роль
|
||||
ca.add_role("author")
|
||||
assert ca.role_list == ["reader", "author"]
|
||||
# Проверяем что admin имеет дополнительные разрешения
|
||||
admin_specific = ["author:delete_any", "author:update_any", "chat:delete_any", "message:delete_any"]
|
||||
for perm in admin_specific:
|
||||
assert perm in admin_permissions, f"Admin должен иметь разрешение {perm}"
|
||||
|
||||
# Попытка добавить существующую роль (не должна дублироваться)
|
||||
ca.add_role("reader")
|
||||
assert ca.role_list == ["reader", "author"]
|
||||
@pytest.mark.asyncio
|
||||
async def test_role_inheritance_expert_inherits_reader(self, db_session, test_community):
|
||||
"""Тест что роль expert наследует разрешения от reader"""
|
||||
await initialize_community_permissions(test_community.id)
|
||||
|
||||
# Добавляем ещё одну роль
|
||||
ca.add_role("expert")
|
||||
assert ca.role_list == ["reader", "author", "expert"]
|
||||
expert_permissions = await get_permissions_for_role("expert", test_community.id)
|
||||
reader_permissions = await get_permissions_for_role("reader", test_community.id)
|
||||
|
||||
def test_remove_role(self, db_session, test_users, test_community):
|
||||
"""Тест удаления роли"""
|
||||
# Очищаем существующие записи
|
||||
db_session.query(CommunityAuthor).filter(
|
||||
CommunityAuthor.community_id == test_community.id, CommunityAuthor.author_id == test_users[3].id
|
||||
).delete()
|
||||
db_session.commit()
|
||||
# Проверяем что expert имеет все разрешения reader
|
||||
for perm in reader_permissions:
|
||||
assert perm in expert_permissions, f"Expert должен наследовать разрешение {perm} от reader"
|
||||
|
||||
ca = CommunityAuthor(community_id=test_community.id, author_id=test_users[3].id, roles="reader,author,expert")
|
||||
db_session.add(ca)
|
||||
db_session.commit()
|
||||
# Проверяем что expert имеет дополнительные разрешения
|
||||
expert_specific = ["reaction:create:PROOF", "reaction:create:DISPROOF", "reaction:create:AGREE"]
|
||||
for perm in expert_specific:
|
||||
assert perm in expert_permissions, f"Expert должен иметь разрешение {perm}"
|
||||
|
||||
# Удаляем роль
|
||||
ca.remove_role("author")
|
||||
assert ca.role_list == ["reader", "expert"]
|
||||
@pytest.mark.asyncio
|
||||
async def test_role_inheritance_artist_inherits_author(self, db_session, test_community):
|
||||
"""Тест что роль artist наследует разрешения от author"""
|
||||
await initialize_community_permissions(test_community.id)
|
||||
|
||||
# Попытка удалить несуществующую роль (не должна ломаться)
|
||||
ca.remove_role("admin")
|
||||
assert ca.role_list == ["reader", "expert"]
|
||||
artist_permissions = await get_permissions_for_role("artist", test_community.id)
|
||||
author_permissions = await get_permissions_for_role("author", test_community.id)
|
||||
|
||||
# Удаляем все роли
|
||||
ca.remove_role("reader")
|
||||
ca.remove_role("expert")
|
||||
assert ca.role_list == []
|
||||
# Проверяем что artist имеет все разрешения author
|
||||
for perm in author_permissions:
|
||||
assert perm in artist_permissions, f"Artist должен наследовать разрешение {perm} от author"
|
||||
|
||||
def test_set_roles(self, db_session, test_users, test_community):
|
||||
"""Тест установки полного списка ролей"""
|
||||
# Очищаем существующие записи
|
||||
db_session.query(CommunityAuthor).filter(
|
||||
CommunityAuthor.community_id == test_community.id, CommunityAuthor.author_id == test_users[4].id
|
||||
).delete()
|
||||
db_session.commit()
|
||||
# Проверяем что artist имеет дополнительные разрешения
|
||||
artist_specific = ["reaction:create:CREDIT", "reaction:read:CREDIT", "reaction:update_own:CREDIT"]
|
||||
for perm in artist_specific:
|
||||
assert perm in artist_permissions, f"Artist должен иметь разрешение {perm}"
|
||||
|
||||
ca = CommunityAuthor(community_id=test_community.id, author_id=test_users[4].id, roles="reader")
|
||||
db_session.add(ca)
|
||||
db_session.commit()
|
||||
@pytest.mark.asyncio
|
||||
async def test_role_inheritance_deep_inheritance(self, db_session, test_community):
|
||||
"""Тест глубокого наследования: admin -> editor -> author -> reader"""
|
||||
await initialize_community_permissions(test_community.id)
|
||||
|
||||
# Устанавливаем новый список ролей
|
||||
ca.set_roles(["admin", "editor", "expert"])
|
||||
assert ca.role_list == ["admin", "editor", "expert"]
|
||||
admin_permissions = await get_permissions_for_role("admin", test_community.id)
|
||||
reader_permissions = await get_permissions_for_role("reader", test_community.id)
|
||||
|
||||
# Очищаем роли
|
||||
ca.set_roles([])
|
||||
assert ca.role_list == []
|
||||
# Проверяем что admin имеет все разрешения reader через цепочку наследования
|
||||
for perm in reader_permissions:
|
||||
assert perm in admin_permissions, f"Admin должен наследовать разрешение {perm} через цепочку наследования"
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_role_inheritance_no_circular_dependency(self, db_session, test_community):
|
||||
"""Тест что нет циклических зависимостей в наследовании ролей"""
|
||||
await initialize_community_permissions(test_community.id)
|
||||
|
||||
# Получаем все роли и проверяем что они корректно обрабатываются
|
||||
all_roles = ["reader", "author", "artist", "expert", "editor", "admin"]
|
||||
|
||||
for role in all_roles:
|
||||
permissions = await get_permissions_for_role(role, test_community.id)
|
||||
# Проверяем что список разрешений не пустой и не содержит циклических ссылок
|
||||
assert len(permissions) > 0, f"Роль {role} должна иметь разрешения"
|
||||
assert role not in permissions, f"Роль {role} не должна ссылаться на саму себя"
|
||||
|
||||
|
||||
class TestPermissionsSystem:
|
||||
"""Тесты для системы разрешений"""
|
||||
class TestRBACPermissionChecking:
|
||||
"""Тесты для проверки разрешений с учетом наследования"""
|
||||
|
||||
async def test_get_permissions_for_role(self):
|
||||
"""Тест получения разрешений для роли"""
|
||||
community_id = 1 # Используем основное сообщество
|
||||
@pytest.mark.asyncio
|
||||
async def test_user_with_author_role_has_reader_permissions(self, db_session, test_users, test_community):
|
||||
"""Тест что пользователь с ролью author имеет разрешения reader"""
|
||||
# Используем local_session для создания записи
|
||||
from services.db import local_session
|
||||
from orm.community import CommunityAuthor
|
||||
|
||||
# Проверяем базовые роли
|
||||
reader_perms = await get_permissions_for_role("reader", community_id)
|
||||
assert "shout:read" in reader_perms
|
||||
assert "shout:create" not in reader_perms
|
||||
with local_session() as session:
|
||||
# Удаляем существующую запись если есть
|
||||
existing_ca = session.query(CommunityAuthor).where(
|
||||
CommunityAuthor.community_id == test_community.id,
|
||||
CommunityAuthor.author_id == test_users[0].id
|
||||
).first()
|
||||
if existing_ca:
|
||||
session.delete(existing_ca)
|
||||
session.commit()
|
||||
|
||||
author_perms = await get_permissions_for_role("author", community_id)
|
||||
assert "shout:create" in author_perms
|
||||
assert "draft:create" in author_perms
|
||||
assert "shout:delete_any" not in author_perms
|
||||
# Создаем новую запись
|
||||
ca = CommunityAuthor(
|
||||
community_id=test_community.id,
|
||||
author_id=test_users[0].id,
|
||||
roles="author"
|
||||
)
|
||||
session.add(ca)
|
||||
session.commit()
|
||||
|
||||
admin_perms = await get_permissions_for_role("admin", community_id)
|
||||
assert "author:delete_any" in admin_perms
|
||||
assert "author:update_any" in admin_perms
|
||||
await initialize_community_permissions(test_community.id)
|
||||
|
||||
# Проверяем несуществующую роль
|
||||
unknown_perms = await get_permissions_for_role("unknown_role", community_id)
|
||||
assert unknown_perms == []
|
||||
# Проверяем что пользователь имеет разрешения reader
|
||||
reader_permissions = ["shout:read", "topic:read", "collection:read", "chat:read"]
|
||||
for perm in reader_permissions:
|
||||
has_permission = await user_has_permission(test_users[0].id, perm, test_community.id)
|
||||
assert has_permission, f"Пользователь с ролью author должен иметь разрешение {perm}"
|
||||
|
||||
async def test_reaction_permissions_generation(self):
|
||||
"""Тест генерации разрешений для реакций"""
|
||||
community_id = 1 # Используем основное сообщество
|
||||
@pytest.mark.asyncio
|
||||
async def test_user_with_editor_role_has_author_permissions(self, db_session, test_users, test_community):
|
||||
"""Тест что пользователь с ролью editor имеет разрешения author"""
|
||||
# Используем local_session для создания записи
|
||||
from services.db import local_session
|
||||
from orm.community import CommunityAuthor
|
||||
|
||||
# Проверяем что система генерирует разрешения для реакций
|
||||
admin_perms = await get_permissions_for_role("admin", community_id)
|
||||
with local_session() as session:
|
||||
# Удаляем существующую запись если есть
|
||||
existing_ca = session.query(CommunityAuthor).where(
|
||||
CommunityAuthor.community_id == test_community.id,
|
||||
CommunityAuthor.author_id == test_users[0].id
|
||||
).first()
|
||||
if existing_ca:
|
||||
session.delete(existing_ca)
|
||||
session.commit()
|
||||
|
||||
# Админ должен иметь все разрешения на реакции
|
||||
assert len(admin_perms) > 0, "Admin should have some permissions"
|
||||
# Создаем новую запись
|
||||
ca = CommunityAuthor(
|
||||
community_id=test_community.id,
|
||||
author_id=test_users[0].id,
|
||||
roles="editor"
|
||||
)
|
||||
session.add(ca)
|
||||
session.commit()
|
||||
|
||||
# Проверяем что есть хотя бы базовые разрешения на реакции у читателей
|
||||
reader_perms = await get_permissions_for_role("reader", community_id)
|
||||
assert len(reader_perms) > 0, "Reader should have some permissions"
|
||||
await initialize_community_permissions(test_community.id)
|
||||
|
||||
# Проверяем что у reader есть разрешения на чтение реакций
|
||||
assert any("reaction:read:" in perm for perm in reader_perms), "Reader should have reaction read permissions"
|
||||
# Проверяем что пользователь имеет разрешения author
|
||||
author_permissions = ["draft:create", "shout:create", "collection:create"]
|
||||
for perm in author_permissions:
|
||||
has_permission = await user_has_permission(test_users[0].id, perm, test_community.id)
|
||||
assert has_permission, f"Пользователь с ролью editor должен иметь разрешение {perm}"
|
||||
|
||||
async def test_community_author_get_permissions(self, db_session, test_users, test_community):
|
||||
"""Тест получения разрешений через CommunityAuthor"""
|
||||
# Очищаем существующие записи
|
||||
db_session.query(CommunityAuthor).filter(
|
||||
CommunityAuthor.community_id == test_community.id, CommunityAuthor.author_id == test_users[0].id
|
||||
).delete()
|
||||
db_session.commit()
|
||||
@pytest.mark.asyncio
|
||||
async def test_user_with_admin_role_has_all_permissions(self, db_session, test_users, test_community):
|
||||
"""Тест что пользователь с ролью admin имеет все разрешения"""
|
||||
# Используем local_session для создания записи
|
||||
from services.db import local_session
|
||||
from orm.community import CommunityAuthor
|
||||
|
||||
ca = CommunityAuthor(community_id=test_community.id, author_id=test_users[0].id, roles="reader,author")
|
||||
db_session.add(ca)
|
||||
db_session.commit()
|
||||
with local_session() as session:
|
||||
# Удаляем существующую запись если есть
|
||||
existing_ca = session.query(CommunityAuthor).where(
|
||||
CommunityAuthor.community_id == test_community.id,
|
||||
CommunityAuthor.author_id == test_users[0].id
|
||||
).first()
|
||||
if existing_ca:
|
||||
session.delete(existing_ca)
|
||||
session.commit()
|
||||
|
||||
permissions = await ca.get_permissions()
|
||||
# Создаем новую запись
|
||||
ca = CommunityAuthor(
|
||||
community_id=test_community.id,
|
||||
author_id=test_users[0].id,
|
||||
roles="admin"
|
||||
)
|
||||
session.add(ca)
|
||||
session.commit()
|
||||
|
||||
# Должны быть разрешения от обеих ролей
|
||||
assert "shout:read" in permissions # От reader
|
||||
assert "shout:create" in permissions # От author
|
||||
assert len(permissions) > 0 # Должны быть какие-то разрешения
|
||||
await initialize_community_permissions(test_community.id)
|
||||
|
||||
async def test_community_author_has_permission(self, db_session, test_users, test_community):
|
||||
"""Тест проверки разрешения через CommunityAuthor"""
|
||||
# Очищаем существующие записи
|
||||
db_session.query(CommunityAuthor).filter(
|
||||
CommunityAuthor.community_id == test_community.id, CommunityAuthor.author_id == test_users[1].id
|
||||
).delete()
|
||||
db_session.commit()
|
||||
|
||||
ca = CommunityAuthor(community_id=test_community.id, author_id=test_users[1].id, roles="expert,editor")
|
||||
db_session.add(ca)
|
||||
db_session.commit()
|
||||
|
||||
# Проверяем разрешения
|
||||
permissions = await ca.get_permissions()
|
||||
# Expert имеет разрешения на реакции PROOF/DISPROOF
|
||||
assert any("reaction:create:PROOF" in perm for perm in permissions)
|
||||
# Editor имеет разрешения на удаление и обновление шаутов
|
||||
assert "shout:delete_any" in permissions
|
||||
assert "shout:update_any" in permissions
|
||||
|
||||
|
||||
class TestClassMethods:
|
||||
"""Тесты для классовых методов CommunityAuthor"""
|
||||
|
||||
async def test_find_by_user_and_community(self, db_session, test_users, test_community):
|
||||
"""Тест поиска записи CommunityAuthor"""
|
||||
# Очищаем существующие записи
|
||||
db_session.query(CommunityAuthor).filter(
|
||||
CommunityAuthor.community_id == test_community.id, CommunityAuthor.author_id == test_users[0].id
|
||||
).delete()
|
||||
db_session.commit()
|
||||
|
||||
# Создаем запись
|
||||
ca = CommunityAuthor(community_id=test_community.id, author_id=test_users[0].id, roles="reader,author")
|
||||
db_session.add(ca)
|
||||
db_session.commit()
|
||||
|
||||
# Ищем существующую запись
|
||||
found = CommunityAuthor.find_by_user_and_community(test_users[0].id, test_community.id, db_session)
|
||||
assert found is not None
|
||||
assert found.author_id == test_users[0].id
|
||||
assert found.community_id == test_community.id
|
||||
|
||||
# Ищем несуществующую запись
|
||||
not_found = CommunityAuthor.find_by_user_and_community(test_users[1].id, test_community.id, db_session)
|
||||
assert not_found is None
|
||||
|
||||
async def test_get_users_with_role(self, db_session, test_users, test_community):
|
||||
"""Тест получения пользователей с определенной ролью"""
|
||||
# Очищаем существующие записи
|
||||
db_session.query(CommunityAuthor).filter(CommunityAuthor.community_id == test_community.id).delete()
|
||||
db_session.commit()
|
||||
|
||||
# Создаем пользователей с разными ролями
|
||||
cas = [
|
||||
CommunityAuthor(community_id=test_community.id, author_id=test_users[0].id, roles="reader,author"),
|
||||
CommunityAuthor(community_id=test_community.id, author_id=test_users[1].id, roles="reader,expert"),
|
||||
CommunityAuthor(community_id=test_community.id, author_id=test_users[2].id, roles="admin"),
|
||||
# Проверяем разрешения разных уровней
|
||||
all_permissions = [
|
||||
"shout:read", # reader
|
||||
"draft:create", # author
|
||||
"shout:delete_any", # editor
|
||||
"author:delete_any" # admin
|
||||
]
|
||||
for ca in cas:
|
||||
db_session.add(ca)
|
||||
db_session.commit()
|
||||
|
||||
# Ищем пользователей с ролью reader
|
||||
readers = CommunityAuthor.get_users_with_role(test_community.id, "reader", db_session)
|
||||
assert test_users[0].id in readers
|
||||
assert test_users[1].id in readers
|
||||
assert test_users[2].id not in readers
|
||||
for perm in all_permissions:
|
||||
has_permission = await user_has_permission(test_users[0].id, perm, test_community.id)
|
||||
assert has_permission, f"Пользователь с ролью admin должен иметь разрешение {perm}"
|
||||
|
||||
# Ищем пользователей с ролью admin
|
||||
admins = CommunityAuthor.get_users_with_role(test_community.id, "admin", db_session)
|
||||
assert test_users[2].id in admins
|
||||
assert test_users[0].id not in admins
|
||||
@pytest.mark.asyncio
|
||||
async def test_roles_have_permission_with_inheritance(self, db_session, test_community):
|
||||
"""Тест функции roles_have_permission с учетом наследования"""
|
||||
await initialize_community_permissions(test_community.id)
|
||||
|
||||
# Проверяем что editor имеет разрешения author
|
||||
has_author_permission = await roles_have_permission(["editor"], "draft:create", test_community.id)
|
||||
assert has_author_permission, "Editor должен иметь разрешение draft:create через наследование от author"
|
||||
|
||||
# Проверяем что admin имеет разрешения reader
|
||||
has_reader_permission = await roles_have_permission(["admin"], "shout:read", test_community.id)
|
||||
assert has_reader_permission, "Admin должен иметь разрешение shout:read через наследование от reader"
|
||||
|
||||
|
||||
class TestEdgeCases:
|
||||
"""Тесты для граничных случаев"""
|
||||
class TestRBACInitialization:
|
||||
"""Тесты для инициализации системы RBAC"""
|
||||
|
||||
async def test_empty_roles_handling(self, db_session, test_users, test_community):
|
||||
"""Тест обработки пустых ролей"""
|
||||
# Создаем запись с пустыми ролями
|
||||
ca = CommunityAuthor(community_id=test_community.id, author_id=test_users[0].id, roles="")
|
||||
db_session.add(ca)
|
||||
db_session.commit()
|
||||
@pytest.mark.asyncio
|
||||
async def test_initialize_community_permissions(self, db_session, test_community):
|
||||
"""Тест инициализации разрешений для сообщества"""
|
||||
await initialize_community_permissions(test_community.id)
|
||||
|
||||
assert ca.role_list == []
|
||||
permissions = await ca.get_permissions()
|
||||
assert permissions == []
|
||||
# Проверяем что разрешения инициализированы
|
||||
permissions = await get_role_permissions_for_community(test_community.id)
|
||||
assert permissions is not None
|
||||
assert len(permissions) > 0
|
||||
|
||||
async def test_none_roles_handling(self, db_session, test_users, test_community):
|
||||
"""Тест обработки NULL ролей"""
|
||||
ca = CommunityAuthor(community_id=test_community.id, author_id=test_users[0].id, roles=None)
|
||||
db_session.add(ca)
|
||||
db_session.commit()
|
||||
# Проверяем что все роли присутствуют
|
||||
expected_roles = ["reader", "author", "artist", "expert", "editor", "admin"]
|
||||
for role in expected_roles:
|
||||
assert role in permissions, f"Роль {role} должна быть в инициализированных разрешениях"
|
||||
|
||||
assert ca.role_list == []
|
||||
assert await ca.get_permissions() == []
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_role_permissions_for_community_auto_init(self, db_session, test_community):
|
||||
"""Тест автоматической инициализации при получении разрешений"""
|
||||
# Получаем разрешения без предварительной инициализации
|
||||
permissions = await get_role_permissions_for_community(test_community.id)
|
||||
|
||||
async def test_whitespace_roles_handling(self, db_session, test_users, test_community):
|
||||
"""Тест обработки ролей с пробелами"""
|
||||
ca = CommunityAuthor(
|
||||
community_id=test_community.id, author_id=test_users[0].id, roles=" reader , author , expert "
|
||||
)
|
||||
db_session.add(ca)
|
||||
db_session.commit()
|
||||
assert permissions is not None
|
||||
assert len(permissions) > 0
|
||||
|
||||
# Пробелы должны убираться
|
||||
assert ca.role_list == ["reader", "author", "expert"]
|
||||
|
||||
async def test_duplicate_roles_handling(self, db_session, test_users, test_community):
|
||||
"""Тест обработки дублирующихся ролей"""
|
||||
# Очищаем существующие записи
|
||||
db_session.query(CommunityAuthor).filter(
|
||||
CommunityAuthor.community_id == test_community.id, CommunityAuthor.author_id == test_users[0].id
|
||||
).delete()
|
||||
db_session.commit()
|
||||
|
||||
ca = CommunityAuthor(
|
||||
community_id=test_community.id, author_id=test_users[0].id, roles="reader,author,reader,expert,author"
|
||||
)
|
||||
db_session.add(ca)
|
||||
db_session.commit()
|
||||
|
||||
# При установке через set_roles дубликаты должны убираться
|
||||
unique_roles = set(["reader", "author", "reader", "expert"])
|
||||
ca.set_roles(unique_roles)
|
||||
roles = ca.role_list
|
||||
# Проверяем что нет дубликатов
|
||||
assert len(roles) == len(set(roles))
|
||||
assert "reader" in roles
|
||||
assert "author" in roles
|
||||
assert "expert" in roles
|
||||
|
||||
async def test_invalid_role(self):
|
||||
"""Тест получения разрешений для несуществующих ролей"""
|
||||
community_id = 1 # Используем основное сообщество
|
||||
|
||||
# Проверяем что несуществующая роль не ломает систему
|
||||
perms = await get_permissions_for_role("nonexistent_role", community_id)
|
||||
assert perms == []
|
||||
|
||||
|
||||
class TestPerformance:
|
||||
"""Тесты производительности (базовые)"""
|
||||
|
||||
async def test_large_role_list_performance(self, db_session, test_users, test_community):
|
||||
"""Тест производительности с большим количеством ролей"""
|
||||
# Очищаем существующие записи
|
||||
db_session.query(CommunityAuthor).filter(
|
||||
CommunityAuthor.community_id == test_community.id, CommunityAuthor.author_id == test_users[0].id
|
||||
).delete()
|
||||
db_session.commit()
|
||||
|
||||
# Создаем запись с множеством ролей
|
||||
many_roles = ",".join([f"role_{i}" for i in range(50)]) # Уменьшим количество
|
||||
ca = CommunityAuthor(community_id=test_community.id, author_id=test_users[0].id, roles=many_roles)
|
||||
db_session.add(ca)
|
||||
db_session.commit()
|
||||
|
||||
# Операции должны работать быстро даже с множеством ролей
|
||||
role_list = ca.role_list
|
||||
assert len(role_list) == 50
|
||||
assert all(role.startswith("role_") for role in role_list)
|
||||
|
||||
async def test_permissions_caching_behavior(self, db_session, test_users, test_community):
|
||||
"""Тест поведения кеширования разрешений"""
|
||||
# Очищаем существующие записи
|
||||
db_session.query(CommunityAuthor).filter(
|
||||
CommunityAuthor.community_id == test_community.id, CommunityAuthor.author_id == test_users[1].id
|
||||
).delete()
|
||||
db_session.commit()
|
||||
|
||||
ca = CommunityAuthor(community_id=test_community.id, author_id=test_users[1].id, roles="reader,author,expert")
|
||||
db_session.add(ca)
|
||||
db_session.commit()
|
||||
|
||||
# Многократный вызов get_permissions должен работать стабильно
|
||||
perms1 = await ca.get_permissions()
|
||||
perms2 = await ca.get_permissions()
|
||||
perms3 = await ca.get_permissions()
|
||||
|
||||
assert perms1.sort() == perms2.sort() == perms3.sort()
|
||||
assert len(perms1) > 0
|
||||
# Проверяем что все роли присутствуют
|
||||
expected_roles = ["reader", "author", "artist", "expert", "editor", "admin"]
|
||||
for role in expected_roles:
|
||||
assert role in permissions, f"Роль {role} должна быть в разрешениях"
|
||||
|
Reference in New Issue
Block a user