2025-05-16 06:23:48 +00:00
|
|
|
|
from typing import Dict, List, Optional, Set, Any
|
2021-06-28 09:08:09 +00:00
|
|
|
|
|
2025-05-16 06:23:48 +00:00
|
|
|
|
from pydantic import BaseModel, Field
|
2023-10-26 21:07:35 +00:00
|
|
|
|
|
2023-01-10 08:15:28 +00:00
|
|
|
|
# from base.exceptions import Unauthorized
|
2025-05-16 06:23:48 +00:00
|
|
|
|
from settings import ADMIN_EMAILS as ADMIN_EMAILS_LIST
|
|
|
|
|
|
|
|
|
|
ADMIN_EMAILS = ADMIN_EMAILS_LIST.split(",")
|
2022-09-17 18:12:14 +00:00
|
|
|
|
|
2021-06-28 09:08:09 +00:00
|
|
|
|
|
|
|
|
|
class Permission(BaseModel):
|
2025-05-16 06:23:48 +00:00
|
|
|
|
"""Модель разрешения для RBAC"""
|
|
|
|
|
|
|
|
|
|
resource: str
|
|
|
|
|
operation: str
|
|
|
|
|
|
|
|
|
|
def __str__(self) -> str:
|
|
|
|
|
return f"{self.resource}:{self.operation}"
|
2021-06-28 09:08:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class AuthCredentials(BaseModel):
|
2025-05-16 06:23:48 +00:00
|
|
|
|
"""
|
|
|
|
|
Модель учетных данных авторизации.
|
|
|
|
|
Используется как часть механизма аутентификации Starlette.
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
author_id: Optional[int] = Field(None, description="ID автора")
|
|
|
|
|
scopes: Dict[str, Set[str]] = Field(default_factory=dict, description="Разрешения пользователя")
|
|
|
|
|
logged_in: bool = Field(False, description="Флаг, указывающий, авторизован ли пользователь")
|
|
|
|
|
error_message: str = Field("", description="Сообщение об ошибке аутентификации")
|
|
|
|
|
email: Optional[str] = Field(None, description="Email пользователя")
|
2025-05-19 21:00:24 +00:00
|
|
|
|
token: Optional[str] = Field(None, description="JWT токен авторизации")
|
2025-05-16 06:23:48 +00:00
|
|
|
|
|
|
|
|
|
def get_permissions(self) -> List[str]:
|
|
|
|
|
"""
|
|
|
|
|
Возвращает список строковых представлений разрешений.
|
|
|
|
|
Например: ["posts:read", "posts:write", "comments:create"].
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
List[str]: Список разрешений
|
|
|
|
|
"""
|
|
|
|
|
result = []
|
|
|
|
|
for resource, operations in self.scopes.items():
|
|
|
|
|
for operation in operations:
|
|
|
|
|
result.append(f"{resource}:{operation}")
|
|
|
|
|
return result
|
|
|
|
|
|
|
|
|
|
def has_permission(self, resource: str, operation: str) -> bool:
|
|
|
|
|
"""
|
|
|
|
|
Проверяет наличие определенного разрешения.
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
resource: Ресурс (например, "posts")
|
|
|
|
|
operation: Операция (например, "read")
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
bool: True, если пользователь имеет указанное разрешение
|
|
|
|
|
"""
|
|
|
|
|
if not self.logged_in:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
return resource in self.scopes and operation in self.scopes[resource]
|
2021-06-28 09:08:09 +00:00
|
|
|
|
|
|
|
|
|
@property
|
2025-05-16 06:23:48 +00:00
|
|
|
|
def is_admin(self) -> bool:
|
|
|
|
|
"""
|
|
|
|
|
Проверяет, является ли пользователь администратором.
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
bool: True, если email пользователя находится в списке ADMIN_EMAILS
|
|
|
|
|
"""
|
|
|
|
|
return self.email in ADMIN_EMAILS if self.email else False
|
|
|
|
|
|
|
|
|
|
def to_dict(self) -> Dict[str, Any]:
|
|
|
|
|
"""
|
|
|
|
|
Преобразует учетные данные в словарь
|
|
|
|
|
|
|
|
|
|
Returns:
|
|
|
|
|
Dict[str, Any]: Словарь с данными учетных данных
|
|
|
|
|
"""
|
|
|
|
|
return {
|
|
|
|
|
"author_id": self.author_id,
|
|
|
|
|
"logged_in": self.logged_in,
|
|
|
|
|
"is_admin": self.is_admin,
|
|
|
|
|
"permissions": self.get_permissions(),
|
|
|
|
|
}
|
2021-06-28 09:08:09 +00:00
|
|
|
|
|
|
|
|
|
async def permissions(self) -> List[Permission]:
|
2025-05-16 06:23:48 +00:00
|
|
|
|
if self.author_id is None:
|
2023-01-10 08:15:28 +00:00
|
|
|
|
# raise Unauthorized("Please login first")
|
2023-10-30 21:00:55 +00:00
|
|
|
|
return {"error": "Please login first"}
|
2022-12-01 08:12:48 +00:00
|
|
|
|
else:
|
|
|
|
|
# TODO: implement permissions logix
|
2025-05-16 06:23:48 +00:00
|
|
|
|
print(self.author_id)
|
2023-10-30 21:00:55 +00:00
|
|
|
|
return NotImplemented
|