diff --git a/pdm.lock b/pdm.lock index 56ee2df0..2e649f45 100644 --- a/pdm.lock +++ b/pdm.lock @@ -4,8 +4,8 @@ [metadata] groups = ["default"] strategy = ["cross_platform"] -lock_version = "4.4" -content_hash = "sha256:377060918126987ee7854a1767311674ff9e2710607aaacf0de88245cf78b1cb" +lock_version = "4.4.1" +content_hash = "sha256:c1a5d1e22693f74c3174d55040fa95f5517b735391c8b4c2eced81269267fad9" [[package]] name = "anyio" @@ -549,6 +549,16 @@ files = [ {file = "typing_extensions-4.9.0.tar.gz", hash = "sha256:23478f88c37f27d76ac8aee6c905017a143b0b1b886c3c9f66bc2fd94f9f5783"}, ] +[[package]] +name = "urllib3" +version = "2.1.0" +requires_python = ">=3.8" +summary = "HTTP library with thread-safe connection pooling, file post, and more." +files = [ + {file = "urllib3-2.1.0-py3-none-any.whl", hash = "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3"}, + {file = "urllib3-2.1.0.tar.gz", hash = "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54"}, +] + [[package]] name = "werkzeug" version = "3.0.1" diff --git a/pyproject.toml b/pyproject.toml index 17b4eef6..341843a4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,6 +14,8 @@ dependencies = [ "pymysql>=1.1.0", "click>=8.1.7", "bson>=0.5.10", + "jwt>=1.3.1", + "urllib3>=2.1.0", ] requires-python = ">=3.10" readme = "README.md" diff --git a/requirements.txt b/requirements.txt index f16db853..acb280ed 100644 --- a/requirements.txt +++ b/requirements.txt @@ -34,4 +34,5 @@ six==1.16.0 sniffio==1.3.0 sqlalchemy==2.0.23 typing-extensions==4.9.0 +urllib3==2.1.0 Werkzeug==3.0.1 diff --git a/server/routes/github.py b/server/routes/github.py index f3b5af6b..07c9d1b5 100644 --- a/server/routes/github.py +++ b/server/routes/github.py @@ -9,6 +9,13 @@ @bp.route("/install", methods=["GET"]) def github_install(): + """Install GitHub App. + + If not `installation_id`, redirect to install page. + If `installation_id`, get installation token. + + If `code`, register by code. + """ installation_id = request.args.get("installation_id", None) if installation_id is None: @@ -46,4 +53,26 @@ def github_install(): return "Success!" +@bp.route("/register", methods=["GET"]) +def github_register(): + """GitHub OAuth register. + + If not `code`, redirect to GitHub OAuth page. + If `code`, register by code. + """ + code = request.args.get("code", None) + if code is None: + return redirect( + f"https://github.com/login/oauth/authorize?client_id={os.environ.get('GITHUB_CLIENT_ID')}" + ) + + print(f"code: {code}") + user_token = register_by_code(code) + if user_token is None: + return "Failed to register by code." + + print(f"user_token: {user_token}") + return user_token + + app.register_blueprint(bp) diff --git a/server/utils/github.py b/server/utils/github.py index e9eff48f..044c6b15 100644 --- a/server/utils/github.py +++ b/server/utils/github.py @@ -1,5 +1,6 @@ import os import time +from urllib.parse import parse_qs import httpx from jwt import JWT, jwk_from_pem @@ -79,14 +80,16 @@ def register_by_code(code: str) -> str | None: response = client.post( "https://github.com/login/oauth/access_token", params={ - "client_id": os.environ.get("CLIENT_ID"), - "client_secret": os.environ.get("CLIENT_SECRET"), + "client_id": os.environ.get("GITHUB_CLIENT_ID"), + "client_secret": os.environ.get("GITHUB_CLIENT_SECRET"), "code": code, }, ) - if response.status_code == 200: + if response.status_code != 200: return None - return response.text + access_token = parse_qs(response.text).get("access_token", None) + if access_token is not None: + return access_token[0] return None