diff --git a/auth_backend/auth_method/base.py b/auth_backend/auth_method/base.py index 587f903..00a88dd 100644 --- a/auth_backend/auth_method/base.py +++ b/auth_backend/auth_method/base.py @@ -8,7 +8,6 @@ from fastapi import APIRouter from sqlalchemy.orm import Session as DbSession - from auth_backend.models.db import AuthMethod, User, UserSession from auth_backend.settings import get_settings @@ -24,7 +23,6 @@ class AuthPluginMeta(metaclass=ABCMeta): router: APIRouter prefix: str tags: list[str] = [] - loginable: bool @classmethod def get_name(cls) -> str: diff --git a/auth_backend/auth_method/oauth.py b/auth_backend/auth_method/oauth.py index aa12bbf..21789aa 100644 --- a/auth_backend/auth_method/oauth.py +++ b/auth_backend/auth_method/oauth.py @@ -5,7 +5,7 @@ from fastapi_sqlalchemy import db from sqlalchemy.orm import Session as DbSession -from auth_backend.auth_method import AUTH_METHODS +from auth_backend.auth_method import AUTH_METHODS, LoginableMixin from auth_backend.base import Base from auth_backend.exceptions import LastAuthMethodDelete from auth_backend.models.db import AuthMethod, User, UserSession @@ -31,6 +31,10 @@ def __init__(self): self.router.add_api_route("/auth_url", self._auth_url, methods=["GET"], response_model=self.UrlSchema) self.router.add_api_route("", self._unregister, methods=["DELETE"]) + def __init_subclass__(cls, **kwargs): + super().__init_subclass__(**kwargs) + cls.loginable = issubclass(cls, LoginableMixin) + @staticmethod @abstractmethod async def _redirect_url(*args, **kwargs) -> UrlSchema: diff --git a/auth_backend/auth_method/outer.py b/auth_backend/auth_method/outer.py index 2315330..ae518ca 100644 --- a/auth_backend/auth_method/outer.py +++ b/auth_backend/auth_method/outer.py @@ -8,6 +8,7 @@ from starlette.status import HTTP_403_FORBIDDEN, HTTP_404_NOT_FOUND, HTTP_409_CONFLICT, HTTP_424_FAILED_DEPENDENCY from auth_backend.auth_method.base import AuthPluginMeta +from auth_backend.auth_method import LoginableMixin from auth_backend.base import Base from auth_backend.models.db import AuthMethod, UserSession from auth_backend.utils.security import UnionAuth @@ -77,6 +78,10 @@ def __init__(self): self.router.add_api_route("/{user_id}/link", self._link, methods=["POST"]) self.router.add_api_route("/{user_id}/link", self._unlink, methods=["DELETE"]) + def __init_subclass__(cls, **kwargs): + super().__init_subclass__(**kwargs) + cls.loginable = issubclass(cls, LoginableMixin) + @classmethod def get_scope(cls): """Права, необходимые пользователю для получения данных о внешнем аккаунте""" diff --git a/auth_backend/auth_plugins/airflow.py b/auth_backend/auth_plugins/airflow.py index 4a19c3e..6988011 100644 --- a/auth_backend/auth_plugins/airflow.py +++ b/auth_backend/auth_plugins/airflow.py @@ -19,7 +19,6 @@ class AirflowOuterAuthSettings(Settings): class AirflowOuterAuth(OuterAuthMeta): prefix = '/airflow' settings = AirflowOuterAuthSettings() - loginable = False @classmethod async def _is_outer_user_exists(cls, username: str) -> bool: diff --git a/auth_backend/auth_plugins/coder.py b/auth_backend/auth_plugins/coder.py index e21639c..2c1ecef 100644 --- a/auth_backend/auth_plugins/coder.py +++ b/auth_backend/auth_plugins/coder.py @@ -18,7 +18,6 @@ class CoderOuterAuthSettings(Settings): class CoderOuterAuth(OuterAuthMeta): prefix = '/coder' settings = CoderOuterAuthSettings() - loginable = False @classmethod async def _is_outer_user_exists(cls, username: str) -> bool: diff --git a/auth_backend/auth_plugins/github.py b/auth_backend/auth_plugins/github.py index 80ff480..0af7fe8 100644 --- a/auth_backend/auth_plugins/github.py +++ b/auth_backend/auth_plugins/github.py @@ -10,7 +10,7 @@ from fastapi_sqlalchemy import db from pydantic import BaseModel, Field -from auth_backend.auth_method import AuthPluginMeta, OauthMeta, Session +from auth_backend.auth_method import AuthPluginMeta, OauthMeta, Session, LoginableMixin from auth_backend.exceptions import AlreadyExists, OauthAuthFailed from auth_backend.kafka.kafka import get_kafka_producer from auth_backend.models.db import User, UserSession @@ -28,11 +28,10 @@ class GithubSettings(Settings): GITHUB_CLIENT_SECRET: str | None = None -class GithubAuth(OauthMeta): +class GithubAuth(OauthMeta, LoginableMixin): """Вход в приложение по аккаунту GitHub""" prefix = '/github' - loginable = True tags = ['github'] settings = GithubSettings() diff --git a/auth_backend/auth_plugins/google.py b/auth_backend/auth_plugins/google.py index 4ad3158..0d47cd8 100644 --- a/auth_backend/auth_plugins/google.py +++ b/auth_backend/auth_plugins/google.py @@ -12,7 +12,7 @@ from google.oauth2.id_token import verify_oauth2_token from pydantic import BaseModel, Field, Json -from auth_backend.auth_method import AuthPluginMeta, OauthMeta, Session +from auth_backend.auth_method import AuthPluginMeta, OauthMeta, Session, LoginableMixin from auth_backend.exceptions import AlreadyExists, OauthAuthFailed, OauthCredentialsIncorrect from auth_backend.kafka.kafka import get_kafka_producer from auth_backend.models.db import User, UserSession @@ -36,11 +36,10 @@ class GoogleSettings(Settings): GOOGLE_BLACKLIST_DOMAINS: list[str] | None = ['physics.msu.ru'] -class GoogleAuth(OauthMeta): +class GoogleAuth(OauthMeta, LoginableMixin): """Вход в приложение по аккаунту гугл""" prefix = '/google' - loginable = True tags = ['Google'] settings = GoogleSettings() diff --git a/auth_backend/auth_plugins/keycloak.py b/auth_backend/auth_plugins/keycloak.py index 17bf69e..d9b951e 100644 --- a/auth_backend/auth_plugins/keycloak.py +++ b/auth_backend/auth_plugins/keycloak.py @@ -10,7 +10,7 @@ from fastapi_sqlalchemy import db from pydantic import BaseModel, Field -from auth_backend.auth_method import AuthPluginMeta, OauthMeta, Session +from auth_backend.auth_method import AuthPluginMeta, OauthMeta, Session, LoginableMixin from auth_backend.exceptions import AlreadyExists, OauthAuthFailed from auth_backend.kafka.kafka import get_kafka_producer from auth_backend.models.db import User, UserSession @@ -29,11 +29,10 @@ class KeycloakSettings(Settings): KEYCLOAK_CLIENT_SECRET: str | None = None -class KeycloakAuth(OauthMeta): +class KeycloakAuth(OauthMeta, LoginableMixin): """Вход в приложение по аккаунту Keycloak""" prefix = '/keycloak' - loginable = True tags = ['keycloak'] settings = KeycloakSettings() diff --git a/auth_backend/auth_plugins/lkmsu.py b/auth_backend/auth_plugins/lkmsu.py index ce508db..1fd4d29 100644 --- a/auth_backend/auth_plugins/lkmsu.py +++ b/auth_backend/auth_plugins/lkmsu.py @@ -10,7 +10,7 @@ from pydantic import BaseModel, Field from starlette.background import BackgroundTasks -from auth_backend.auth_method import AuthPluginMeta, OauthMeta, Session +from auth_backend.auth_method import AuthPluginMeta, OauthMeta, Session, LoginableMixin from auth_backend.exceptions import AlreadyExists, OauthAuthFailed from auth_backend.kafka.kafka import get_kafka_producer from auth_backend.models.db import User, UserSession @@ -30,11 +30,10 @@ class LkmsuSettings(Settings): LKMSU_FACULTY_NAME: str = 'Физический факультет' -class LkmsuAuth(OauthMeta): +class LkmsuAuth(OauthMeta, LoginableMixin): """Вход в приложение по аккаунту гугл""" prefix = '/lk-msu' - loginable = True tags = ['lk_msu'] settings = LkmsuSettings() diff --git a/auth_backend/auth_plugins/mailu.py b/auth_backend/auth_plugins/mailu.py index af1d97d..cd1eab5 100644 --- a/auth_backend/auth_plugins/mailu.py +++ b/auth_backend/auth_plugins/mailu.py @@ -18,7 +18,6 @@ class MailuOuterAuthSettings(Settings): class MailuOuterAuth(OuterAuthMeta): prefix = '/mailu' settings = MailuOuterAuthSettings() - loginable = False @classmethod async def _is_outer_user_exists(cls, username: str) -> bool: diff --git a/auth_backend/auth_plugins/mymsu.py b/auth_backend/auth_plugins/mymsu.py index edc2fe2..9b2230e 100644 --- a/auth_backend/auth_plugins/mymsu.py +++ b/auth_backend/auth_plugins/mymsu.py @@ -1,7 +1,7 @@ from pydantic import Field from auth_backend.settings import Settings - +from auth_backend.auth_method import LoginableMixin from .yandex import YandexAuth @@ -16,9 +16,8 @@ class MyMsuSettings(Settings): YANDEX_BLACKLIST_DOMAINS: list[str] | None = None -class MyMsuAuth(YandexAuth): +class MyMsuAuth(YandexAuth, LoginableMixin): """Вход в приложение по почте @my.msu.ru""" prefix = '/my-msu' - loginable = True settings = MyMsuSettings() diff --git a/auth_backend/auth_plugins/physics.py b/auth_backend/auth_plugins/physics.py index c7c77d8..11875ba 100644 --- a/auth_backend/auth_plugins/physics.py +++ b/auth_backend/auth_plugins/physics.py @@ -1,6 +1,7 @@ from pydantic import Field, Json from auth_backend.settings import Settings +from auth_backend.auth_method import LoginableMixin from .google import GoogleAuth @@ -23,9 +24,8 @@ class PhysicsSettings(Settings): GOOGLE_BLACKLIST_DOMAINS: list[str] | None = None -class PhysicsAuth(GoogleAuth): +class PhysicsAuth(GoogleAuth, LoginableMixin): """Вход в приложение по почте @physics.msu.ru""" prefix = '/physics-msu' - loginable = True settings = PhysicsSettings() diff --git a/auth_backend/auth_plugins/postgres.py b/auth_backend/auth_plugins/postgres.py index 6830c8a..94def5b 100644 --- a/auth_backend/auth_plugins/postgres.py +++ b/auth_backend/auth_plugins/postgres.py @@ -21,7 +21,6 @@ class PostgresOuterAuthSettings(Settings): class PostgresOuterAuth(OuterAuthMeta): prefix = '/postgres' settings = PostgresOuterAuthSettings() - loginable = False __sessionmaker: type[Session] | None = None @classmethod diff --git a/auth_backend/auth_plugins/telegram.py b/auth_backend/auth_plugins/telegram.py index c364dc6..22479bd 100644 --- a/auth_backend/auth_plugins/telegram.py +++ b/auth_backend/auth_plugins/telegram.py @@ -11,7 +11,7 @@ from fastapi_sqlalchemy import db from pydantic import BaseModel, Field -from auth_backend.auth_method import AuthPluginMeta, OauthMeta, Session +from auth_backend.auth_method import AuthPluginMeta, OauthMeta, Session, LoginableMixin from auth_backend.exceptions import AlreadyExists, OauthAuthFailed from auth_backend.kafka.kafka import get_kafka_producer from auth_backend.models.db import User, UserSession @@ -29,9 +29,8 @@ class TelegramSettings(Settings): TELEGRAM_BOT_TOKEN: str | None = None -class TelegramAuth(OauthMeta): +class TelegramAuth(OauthMeta, LoginableMixin): prefix = '/telegram' - loginable = True tags = ['Telegram'] settings = TelegramSettings() diff --git a/auth_backend/auth_plugins/vk.py b/auth_backend/auth_plugins/vk.py index 0e54f3a..1497215 100644 --- a/auth_backend/auth_plugins/vk.py +++ b/auth_backend/auth_plugins/vk.py @@ -10,7 +10,7 @@ from fastapi_sqlalchemy import db from pydantic import BaseModel, Field -from auth_backend.auth_method import AuthPluginMeta, OauthMeta, Session +from auth_backend.auth_method import AuthPluginMeta, OauthMeta, Session, LoginableMixin from auth_backend.exceptions import AlreadyExists, OauthAuthFailed from auth_backend.kafka.kafka import get_kafka_producer from auth_backend.models.db import User, UserSession @@ -44,9 +44,8 @@ class VkSettings(Settings): ] # Другие данные https://dev.vk.com/ru/reference/objects/user -class VkAuth(OauthMeta): +class VkAuth(OauthMeta, LoginableMixin): prefix = '/vk' - loginable = True tags = ['vk'] settings = VkSettings() diff --git a/auth_backend/auth_plugins/yandex.py b/auth_backend/auth_plugins/yandex.py index 7c2f600..71ea87e 100644 --- a/auth_backend/auth_plugins/yandex.py +++ b/auth_backend/auth_plugins/yandex.py @@ -10,7 +10,7 @@ from fastapi_sqlalchemy import db from pydantic import BaseModel, Field -from auth_backend.auth_method import AuthPluginMeta, OauthMeta, Session +from auth_backend.auth_method import AuthPluginMeta, OauthMeta, Session, LoginableMixin from auth_backend.exceptions import AlreadyExists, OauthAuthFailed from auth_backend.kafka.kafka import get_kafka_producer from auth_backend.models.db import User, UserSession @@ -31,9 +31,8 @@ class YandexSettings(Settings): YANDEX_BLACKLIST_DOMAINS: list[str] | None = ['my.msu.ru'] -class YandexAuth(OauthMeta): +class YandexAuth(OauthMeta, LoginableMixin): prefix = '/yandex' - loginable = True tags = ['Yandex'] settings = YandexSettings()