auth and rbac improves
This commit is contained in:
59
rbac/api.py
59
rbac/api.py
@@ -13,7 +13,7 @@ from functools import wraps
|
||||
from typing import Any, Callable
|
||||
|
||||
from orm.author import Author
|
||||
from rbac.interface import get_community_queries, get_rbac_operations
|
||||
from rbac.interface import get_rbac_operations
|
||||
from settings import ADMIN_EMAILS
|
||||
from storage.db import local_session
|
||||
from utils.logger import root_logger as logger
|
||||
@@ -100,8 +100,61 @@ def get_user_roles_in_community(author_id: int, community_id: int = 1, session:
|
||||
"""
|
||||
Получает роли пользователя в сообществе через новую систему CommunityAuthor
|
||||
"""
|
||||
community_queries = get_community_queries()
|
||||
return community_queries.get_user_roles_in_community(author_id, community_id, session)
|
||||
rbac_ops = get_rbac_operations()
|
||||
return rbac_ops.get_user_roles_in_community(author_id, community_id, session)
|
||||
|
||||
|
||||
def assign_role_to_user(author_id: int, role: str, community_id: int = 1, session: Any = None) -> bool:
|
||||
"""
|
||||
Назначает роль пользователю в сообществе
|
||||
|
||||
Args:
|
||||
author_id: ID автора
|
||||
role: Название роли
|
||||
community_id: ID сообщества
|
||||
session: Сессия БД (опционально)
|
||||
|
||||
Returns:
|
||||
True если роль была добавлена, False если уже была
|
||||
"""
|
||||
rbac_ops = get_rbac_operations()
|
||||
return rbac_ops.assign_role_to_user(author_id, role, community_id, session)
|
||||
|
||||
|
||||
def remove_role_from_user(author_id: int, role: str, community_id: int = 1, session: Any = None) -> bool:
|
||||
"""
|
||||
Удаляет роль у пользователя в сообществе
|
||||
|
||||
Args:
|
||||
author_id: ID автора
|
||||
role: Название роли
|
||||
community_id: ID сообщества
|
||||
session: Сессия БД (опционально)
|
||||
|
||||
Returns:
|
||||
True если роль была удалена, False если её не было
|
||||
"""
|
||||
rbac_ops = get_rbac_operations()
|
||||
return rbac_ops.remove_role_from_user(author_id, role, community_id, session)
|
||||
|
||||
|
||||
async def check_user_permission_in_community(
|
||||
author_id: int, permission: str, community_id: int = 1, session: Any = None
|
||||
) -> bool:
|
||||
"""
|
||||
Проверяет разрешение пользователя в сообществе
|
||||
|
||||
Args:
|
||||
author_id: ID автора
|
||||
permission: Разрешение для проверки
|
||||
community_id: ID сообщества
|
||||
session: Сессия БД (опционально)
|
||||
|
||||
Returns:
|
||||
True если разрешение есть, False если нет
|
||||
"""
|
||||
rbac_ops = get_rbac_operations()
|
||||
return await rbac_ops.user_has_permission(author_id, permission, community_id, session)
|
||||
|
||||
|
||||
async def user_has_permission(author_id: int, permission: str, community_id: int, session: Any = None) -> bool:
|
||||
|
||||
@@ -40,6 +40,18 @@ class RBACOperations(Protocol):
|
||||
"""Проверяет, есть ли у набора ролей конкретное разрешение в сообществе"""
|
||||
...
|
||||
|
||||
def assign_role_to_user(self, author_id: int, role: str, community_id: int, session: Any = None) -> bool:
|
||||
"""Назначает роль пользователю в сообществе"""
|
||||
...
|
||||
|
||||
def get_user_roles_in_community(self, author_id: int, community_id: int, session: Any = None) -> list[str]:
|
||||
"""Получает роли пользователя в сообществе"""
|
||||
...
|
||||
|
||||
def remove_role_from_user(self, author_id: int, role: str, community_id: int, session: Any = None) -> bool:
|
||||
"""Удаляет роль у пользователя в сообществе"""
|
||||
...
|
||||
|
||||
|
||||
class CommunityAuthorQueries(Protocol):
|
||||
"""
|
||||
|
||||
@@ -234,6 +234,136 @@ class RBACOperationsImpl(RBACOperations):
|
||||
return True
|
||||
return False
|
||||
|
||||
def assign_role_to_user(self, author_id: int, role: str, community_id: int, session: Any = None) -> bool:
|
||||
"""
|
||||
Назначает роль пользователю в сообществе
|
||||
|
||||
Args:
|
||||
author_id: ID автора
|
||||
role: Название роли
|
||||
community_id: ID сообщества
|
||||
session: Сессия БД (опционально)
|
||||
|
||||
Returns:
|
||||
True если роль была добавлена, False если уже была
|
||||
"""
|
||||
try:
|
||||
# Поздний импорт для избежания циклических зависимостей
|
||||
from orm.community import CommunityAuthor
|
||||
|
||||
if session:
|
||||
ca = CommunityAuthor.find_author_in_community(author_id, community_id, session)
|
||||
|
||||
if ca:
|
||||
if ca.has_role(role):
|
||||
return False # Роль уже есть
|
||||
ca.add_role(role)
|
||||
else:
|
||||
# Создаем новую запись
|
||||
ca = CommunityAuthor(community_id=community_id, author_id=author_id, roles=role)
|
||||
session.add(ca)
|
||||
|
||||
session.commit()
|
||||
return True
|
||||
# Используем local_session для продакшена
|
||||
with local_session() as db_session:
|
||||
ca = CommunityAuthor.find_author_in_community(author_id, community_id, db_session)
|
||||
|
||||
if ca:
|
||||
if ca.has_role(role):
|
||||
return False # Роль уже есть
|
||||
ca.add_role(role)
|
||||
else:
|
||||
# Создаем новую запись
|
||||
ca = CommunityAuthor(community_id=community_id, author_id=author_id, roles=role)
|
||||
db_session.add(ca)
|
||||
|
||||
db_session.commit()
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[assign_role_to_user] Ошибка при назначении роли {role} пользователю {author_id}: {e}")
|
||||
return False
|
||||
|
||||
def get_user_roles_in_community(self, author_id: int, community_id: int, session: Any = None) -> list[str]:
|
||||
"""
|
||||
Получает роли пользователя в сообществе
|
||||
|
||||
Args:
|
||||
author_id: ID автора
|
||||
community_id: ID сообщества
|
||||
session: Сессия БД (опционально)
|
||||
|
||||
Returns:
|
||||
Список ролей пользователя
|
||||
"""
|
||||
try:
|
||||
# Поздний импорт для избежания циклических зависимостей
|
||||
from orm.community import CommunityAuthor
|
||||
|
||||
if session:
|
||||
ca = CommunityAuthor.find_author_in_community(author_id, community_id, session)
|
||||
return ca.role_list if ca else []
|
||||
# Используем local_session для продакшена
|
||||
with local_session() as db_session:
|
||||
ca = CommunityAuthor.find_author_in_community(author_id, community_id, db_session)
|
||||
return ca.role_list if ca else []
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[get_user_roles_in_community] Ошибка при получении ролей: {e}")
|
||||
return []
|
||||
|
||||
def remove_role_from_user(self, author_id: int, role: str, community_id: int, session: Any = None) -> bool:
|
||||
"""
|
||||
Удаляет роль у пользователя в сообществе
|
||||
|
||||
Args:
|
||||
author_id: ID автора
|
||||
role: Название роли
|
||||
community_id: ID сообщества
|
||||
session: Сессия БД (опционально)
|
||||
|
||||
Returns:
|
||||
True если роль была удалена, False если её не было
|
||||
"""
|
||||
try:
|
||||
# Поздний импорт для избежания циклических зависимостей
|
||||
from orm.community import CommunityAuthor
|
||||
|
||||
if session:
|
||||
ca = CommunityAuthor.find_author_in_community(author_id, community_id, session)
|
||||
|
||||
if ca and ca.has_role(role):
|
||||
ca.remove_role(role)
|
||||
|
||||
# Если ролей не осталось, удаляем запись
|
||||
if ca.role_list:
|
||||
session.delete(ca)
|
||||
|
||||
session.commit()
|
||||
return True
|
||||
|
||||
return False
|
||||
# Используем local_session для продакшена
|
||||
with local_session() as db_session:
|
||||
ca = CommunityAuthor.find_author_in_community(author_id, community_id, db_session)
|
||||
|
||||
if ca and ca.has_role(role):
|
||||
ca.remove_role(role)
|
||||
|
||||
# Если ролей не осталось, удаляем запись
|
||||
if not ca.role_list:
|
||||
db_session.delete(ca)
|
||||
|
||||
db_session.commit()
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[remove_role_from_user] Ошибка при удалении роли {role} у пользователя {author_id}: {e}")
|
||||
return False
|
||||
|
||||
|
||||
class CommunityAuthorQueriesImpl(CommunityAuthorQueries):
|
||||
"""Конкретная реализация запросов CommunityAuthor через поздний импорт"""
|
||||
|
||||
Reference in New Issue
Block a user