diff --git a/cmds.py b/cmds.py index 4e3ecd5..d60132e 100644 --- a/cmds.py +++ b/cmds.py @@ -29,7 +29,7 @@ def cmds(app, data): else: user = User(id=sqt.sender_id, name=sqt.sender_name, state=state) await user.save() - url = (f'{app.ctx.sio_config.validate_host}/login/oauth/authorize?' + url = (f'{app.ctx.sio_config.gitea_host}/login/oauth/authorize?' f'client_id={app.ctx.sio_config.client_id}&' f'redirect_uri={app.ctx.sio_config.localhost}/redirect&' f'response_type=code&state={state}') diff --git a/models.py b/models.py index fd631bf..625df4b 100644 --- a/models.py +++ b/models.py @@ -6,11 +6,13 @@ class User(Model): id = fields.BigIntField(pk=True, autoincrement=False) name = fields.CharField(max_length=60) state = fields.CharField(max_length=60) + gitea_users = fields.ReverseRelation['GiteaUser'] class GiteaUser(Model): id = fields.BigIntField(pk=True, autoincrement=False) - qid = fields.ForeignKeyField('models.GiteaUser') - name = fields.CharField(max_length=20) - ac_tk = fields.CharField(max_length=256) - rfs_tk = fields.CharField(max_length=256) + qid: fields.ForeignKeyRelation[User] = fields.ForeignKeyField( + 'models.User', related_name='gitea_users') + name = fields.CharField(max_length=60) + ac_tk = fields.CharField(max_length=2048) + rfs_tk = fields.CharField(max_length=2048) diff --git a/server.py b/server.py index 34fc64d..f5d81dd 100644 --- a/server.py +++ b/server.py @@ -1,6 +1,7 @@ import tomllib from typing import Dict, Any, List, Tuple +import aiohttp import casbin from casbin_tortoise_adapter import TortoiseAdapter from nacl.signing import SigningKey @@ -12,6 +13,7 @@ from tortoise.contrib.sanic import register_tortoise import cmds from gitea_model import WebHookIssueComment, WebHookIssue, GiteaEvent +from models import User, GiteaUser from sio_model import Ctx, SioConfig, Message from unit import sio_log_format, int2str, cas_log_fmt @@ -95,10 +97,64 @@ async def receive(rqt: Request): return text(rsp) +async def get_gitea_token(_app, form: dict, q_user: User): + async with aiohttp.ClientSession() as session: + url = f'{app.ctx.sio_config.gitea_host}/login/oauth/access_token' + async with session.post(url, data=form) as rps: + if rps.status == 200: + json = await rps.json() + act = json['access_token'] + rft = json['refresh_token'] + else: + logger.warn(f'Gitea: {rps}') + return f'绑定失败:{await rps.text()}' + url = f'{app.ctx.sio_config.gitea_host}/api/v1/user' + headers = {'Authorization': f'token {act}'} + async with session.get(url, headers=headers) as rps: + if rps.status == 200: + json = await rps.json() + gid = json['id'] + login = json['login'] + else: + logger.warn(f'Gitea: {rps}') + return f'绑定失败:{await rps.text()}' + + g_user = await GiteaUser.filter(id=gid).get_or_none() + if g_user: + g_user.id = gid + g_user.name = login + g_user.qid = q_user + g_user.ac_tk = act + g_user.rfs_tk = rft + await g_user.save() + else: + await GiteaUser(id=gid, name=login, qid=q_user, ac_tk=act, rfs_tk=rft).save() + return f'绑定成功:QQ:{q_user.name}, Gitea:{login}' + + @app.get('/redirect') async def redirect(rqt: Request): - print(rqt.args) - print(rqt.ctx.state) + rqt_state = rqt.args.get('state') + code = rqt.args.get('code') + if rqt_state is None or code is None: + logger.warn(f'Gitea返回消息格式错误:{rqt.args}') + return text(f'返回信息错误:{rqt.args}') + + q_user = await User.filter(state=rqt_state).get_or_none() + if q_user is None: + logger.warn(f'该请求不是从QQ中请求的链接') + return text('请从QQ处申请绑定') + + msg = Message(content='已在绑定中,可能因为意外而失败', room_id=q_user.id) + await app.ctx.sio.emit('sendMessage', msg.to_json()) + + await app.add_task(get_gitea_token(app, {'client_id': app.ctx.sio_config.client_id, + 'client_secret': app.ctx.sio_config.client_secret, + 'code': code, + 'grant_type': 'authorization_code', + 'redirect_uri': f'{app.ctx.sio_config.localhost}/redirect'}, + q_user), name=str(q_user.id)) + return text('success') diff --git a/sio_model.py b/sio_model.py index a3eac81..db3a909 100644 --- a/sio_model.py +++ b/sio_model.py @@ -69,7 +69,7 @@ class SioConfig(BaseModel): key: str = Field(alias='private_key') self_id: int admin: List[int] - validate_host: str + gitea_host: str client_id: str client_secret: str localhost: str