diff --git a/backend/plugin/oauth2/api/v1/user_social.py b/backend/plugin/oauth2/api/v1/user_social.py new file mode 100644 index 000000000..0f81628d1 --- /dev/null +++ b/backend/plugin/oauth2/api/v1/user_social.py @@ -0,0 +1,15 @@ +from fastapi import APIRouter, Request + +from backend.common.response.response_schema import ResponseModel, response_base +from backend.common.security.jwt import DependsJwtAuth +from backend.database.db import CurrentSessionTransaction +from backend.plugin.oauth2.enums import UserSocialType +from backend.plugin.oauth2.service.user_social import user_social_service + +router = APIRouter() + + +@router.delete('/me', summary='解绑用户社交账号', dependencies=[DependsJwtAuth]) +async def unbinding_user(db: CurrentSessionTransaction, request: Request, source: UserSocialType) -> ResponseModel: + await user_social_service.unbinding(db=db, user_id=request.user.id, source=source) + return response_base.success() diff --git a/backend/plugin/oauth2/crud/crud_user_social.py b/backend/plugin/oauth2/crud/crud_user_social.py index d3fab440a..6efbae745 100644 --- a/backend/plugin/oauth2/crud/crud_user_social.py +++ b/backend/plugin/oauth2/crud/crud_user_social.py @@ -8,23 +8,23 @@ class CRUDUserSocial(CRUDPlus[UserSocial]): """用户社交账号数据库操作类""" - async def check_binding(self, db: AsyncSession, pk: int, source: str) -> UserSocial | None: + async def check_binding(self, db: AsyncSession, user_id: int, source: str) -> UserSocial | None: """ 检查系统用户社交账号绑定 :param db: 数据库会话 - :param pk: 用户 ID + :param user_id: 用户 ID :param source: 社交账号类型 :return: """ - return await self.select_model_by_column(db, user_id=pk, source=source) + return await self.select_model_by_column(db, user_id=user_id, source=source) async def get_by_sid(self, db: AsyncSession, sid: str, source: str) -> UserSocial | None: """ - 通过 UUID 获取社交用户 + 通过 sid 获取社交用户 :param db: 数据库会话 - :param sid: 第三方 UUID + :param sid: 第三方用户唯一编码 :param source: 社交账号类型 :return: """ @@ -40,15 +40,16 @@ async def create(self, db: AsyncSession, obj: CreateUserSocialParam) -> None: """ await self.create_model(db, obj) - async def delete(self, db: AsyncSession, social_id: int) -> int: + async def delete(self, db: AsyncSession, user_id: int, source: str) -> int: """ 删除用户社交账号绑定 :param db: 数据库会话 - :param social_id: 社交账号绑定 ID + :param user_id: 用户 ID + :param source: 社交账号类型 :return: """ - return await self.delete_model(db, social_id) + return await self.delete_model_by_column(db, user_id=user_id, source=source) user_social_dao: CRUDUserSocial = CRUDUserSocial(UserSocial) diff --git a/backend/plugin/oauth2/plugin.toml b/backend/plugin/oauth2/plugin.toml index 8b6e3f243..f93e78566 100644 --- a/backend/plugin/oauth2/plugin.toml +++ b/backend/plugin/oauth2/plugin.toml @@ -1,6 +1,6 @@ [plugin] summary = 'OAuth 2.0' -version = '0.0.7' +version = '0.0.8' description = '通过 OAuth 2.0 的方式登录系统' author = 'wu-clan' diff --git a/backend/plugin/oauth2/service/user_social.py b/backend/plugin/oauth2/service/user_social.py new file mode 100644 index 000000000..4230de88f --- /dev/null +++ b/backend/plugin/oauth2/service/user_social.py @@ -0,0 +1,25 @@ +from sqlalchemy.ext.asyncio import AsyncSession + +from backend.common.exception import errors +from backend.plugin.oauth2.crud.crud_user_social import user_social_dao +from backend.plugin.oauth2.enums import UserSocialType + + +class UserSocialService: + @staticmethod + async def unbinding(*, db: AsyncSession, user_id: int, source: UserSocialType) -> int: + """ + 解绑用户社交账号 + + :param db: 数据库会话 + :param user_id: 用户 ID + :param source: 解绑源 + :return: + """ + bind = user_social_dao.check_binding(db, user_id, source.value) + if not bind: + raise errors.NotFoundError(msg=f'用户未绑定 {source.value} 账号') + return await user_social_dao.delete(db, user_id, source.value) + + +user_social_service: UserSocialService = UserSocialService()