from __future__ import annotations
from dataclasses import dataclass
from typing import Any, Protocol
[документация]
class TokenStorage(Protocol):
"""Протокол хранилища токенов OAuth.
Реализации должны обеспечивать сохранение и загрузку пары
access_token / refresh_token из произвольного хранилища
(база данных, файл, переменные окружения и т.д.).
"""
[документация]
def save(self, access_token: str, refresh_token: str) -> None:
"""Сохранить токены в хранилище.
Args:
access_token: Токен доступа OAuth 2.0.
refresh_token: Токен обновления OAuth 2.0.
"""
...
[документация]
def load(self) -> tuple[str, str]:
"""Загрузить токены из хранилища.
Returns:
Кортеж ``(access_token, refresh_token)``.
"""
...
[документация]
@dataclass(kw_only=True)
class OAuthConfig:
"""Конфигурация OAuth 2.0 для подключения к AmoCRM.
Attributes:
client_id: Идентификатор интеграции из личного кабинета AmoCRM.
client_secret: Секрет интеграции.
redirect_uri: URI перенаправления, указанный при создании интеграции.
storage: Хранилище токенов, реализующее протокол :class:`TokenStorage`.
"""
client_id: str
client_secret: str
redirect_uri: str
storage: TokenStorage
[документация]
class InMemoryTokenStorage:
"""Хранилище токенов в памяти приложения.
Токены сохраняются в полях ``access_token`` и ``refresh_token``
переданного объекта и сохраняются вызовом ``instance.save()``.
"""
_access_token: str | None = None
_refresh_token: str | None = None
[документация]
def save(self, access_token: str, refresh_token: str) -> None:
"""Сохранить токены в память.
Args:
access_token: Токен доступа OAuth 2.0.
refresh_token: Токен обновления OAuth 2.0.
"""
self._access_token = access_token
self._refresh_token = refresh_token
[документация]
def load(self) -> tuple[str, str]:
"""Загрузить токены из памяти.
Returns:
Кортеж ``(access_token, refresh_token)``.
"""
return self._access_token, self._refresh_token # type: ignore[return-value]
[документация]
class DjangoTokenStorage:
"""Хранилище токенов на основе экземпляра модели Django.
Токены сохраняются в полях ``access_token`` и ``refresh_token``
переданного объекта и сохраняются вызовом ``instance.save()``.
"""
[документация]
def __init__(self, instance: Any) -> None:
"""
Args:
instance: Экземпляр модели Django с полями
``access_token`` и ``refresh_token``.
"""
self._instance = instance
[документация]
def save(self, access_token: str, refresh_token: str) -> None:
"""Сохранить токены в модель Django и вызвать ``instance.save()``.
Args:
access_token: Токен доступа OAuth 2.0.
refresh_token: Токен обновления OAuth 2.0.
"""
self._instance.access_token = access_token
self._instance.refresh_token = refresh_token
self._instance.save()
[документация]
def load(self) -> tuple[str, str]:
"""Загрузить токены из полей модели Django.
Returns:
Кортеж ``(access_token, refresh_token)``.
"""
return self._instance.access_token, self._instance.refresh_token