From 264e274f4baa564b41983a15deff5a309200afee Mon Sep 17 00:00:00 2001 From: Untone Date: Sat, 2 Dec 2023 08:44:06 +0300 Subject: [PATCH] auth --- .gitignore | 9 ++++++++- Dockerfile | 12 +++++++++--- README.md | 13 +++++++++++- auth.py | 51 ++++++++++++++++++++++++++++++++++++++++++++++++ main.py | 6 +++++- pyproject.toml | 47 ++++++++++++++++++++++++++++++++++++++++++++ requirements.txt | 4 ---- 7 files changed, 132 insertions(+), 10 deletions(-) create mode 100644 auth.py create mode 100644 pyproject.toml delete mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore index 49f8970..871cfd6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,10 @@ venv .idea -.vscode \ No newline at end of file +.vscode +.DS_Store +poetry.lock +__pycache__ +.ruff_cache +.pytest_cache +.venv +*.gz.tar \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index fbb5fc3..af0d19e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,12 @@ FROM python:slim WORKDIR /app -ADD . /app -RUN pip install --no-cache-dir -r requirements.txt -EXPOSE 80 +COPY . /app + +RUN apt-get update && apt-get install -y git gcc curl postgresql && \ + curl -sSL https://install.python-poetry.org | python - && \ + echo "export PATH=$PATH:/root/.local/bin" >> ~/.bashrc && \ + . ~/.bashrc && \ + poetry config virtualenvs.create false && \ + poetry install --no-dev + CMD ["python", "main.py"] \ No newline at end of file diff --git a/README.md b/README.md index 2a26ff9..73699d8 100644 --- a/README.md +++ b/README.md @@ -12,4 +12,15 @@ - STORJ_SECRET_KEY - STORJ_END_POINT - STORJ_BUCKET_NAME - - CDN_DOMAIN \ No newline at end of file + - CDN_DOMAIN + + +### Локальная разработка + +```shell +mkdir .venv +python3.12 -m venv .venv +poetry env use .venv/bin/python3.12 +poetry update +poetry run python main.py +``` diff --git a/auth.py b/auth.py new file mode 100644 index 0000000..30e3d09 --- /dev/null +++ b/auth.py @@ -0,0 +1,51 @@ +from functools import wraps +import aiohttp +from aiohttp import web + +AUTH_URL = 'https://auth.discours.io' + + +async def check_auth(req): + token = req.headers.get("Authorization") + headers = {"Authorization": token, "Content-Type": "application/json"} # "Bearer " + removed + print(f"[services.auth] checking auth token: {token}") + + query_name = "session" + query_type = "query" + operation = "GetUserId" + + gql = { + "query": query_type + " " + operation + " { " + query_name + " { user { id } } }", + "operationName": operation, + "variables": None, + } + + async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=30.0)) as session: + async with session.post(AUTH_URL, headers=headers, json=gql) as response: + print(f"[services.auth] {AUTH_URL} response: {response.status}") + if response.status != 200: + return False, None + r = await response.json() + if r: + user_id = r.get("data", {}).get(query_name, {}).get("user", {}).get("id", None) + is_authenticated = user_id is not None + return is_authenticated, user_id + return False, None + + +def login_required(f): + @wraps(f) + async def decorated_function(*args, **kwargs): + info = args[1] + context = info.context + req = context.get("request") + is_authenticated, user_id = await check_auth(req) + if not is_authenticated: + raise web.HTTPUnauthorized(text="You are not logged in") # Return HTTP 401 Unauthorized + else: + context["user_id"] = user_id + + # If the user is authenticated, execute the resolver + return await f(*args, **kwargs) + + return decorated_function diff --git a/main.py b/main.py index 3317564..e62d46b 100644 --- a/main.py +++ b/main.py @@ -7,6 +7,8 @@ from starlette.applications import Starlette from starlette.responses import JSONResponse from starlette.routing import Route from starlette.requests import Request +from auth import check_auth + STORJ_ACCESS_KEY = os.environ.get('STORJ_ACCESS_KEY') STORJ_SECRET_KEY = os.environ.get('STORJ_SECRET_KEY') @@ -14,6 +16,8 @@ STORJ_END_POINT = os.environ.get('STORJ_END_POINT') STORJ_BUCKET_NAME = os.environ.get('STORJ_BUCKET_NAME') CDN_DOMAIN = os.environ.get('CDN_DOMAIN') + +@check_auth async def upload_handler(request: Request): form = await request.form() file = form.get('file') @@ -62,4 +66,4 @@ app = Starlette(debug=True, routes=routes) if __name__ == "__main__": import uvicorn - uvicorn.run(app, host='0.0.0.0', port=8000) \ No newline at end of file + uvicorn.run(app, host='0.0.0.0', port=80) \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..ed67076 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,47 @@ +[tool.poetry] +name = "discoursio-migrator" +version = "0.2.6" +description = "" +authors = ["discoursio devteam"] +license = "MIT" +readme = "README.md" + +[tool.poetry.dependencies] +python = "^3.12" +aiohttp = "^3.9.1" +uvicorn = "^0.24.0.post1" +starlette = "^0.33.0" +boto3 = "^1.33.6" +botocore = "^1.33.6" + +[tool.poetry.dev-dependencies] +black = "^23.10.1" + +[tool.poetry.group.dev.dependencies] +setuptools = "^69.0.2" + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" + +[tool.black] +line-length = 120 +target-version = ['py312'] +include = '\.pyi?$' +exclude = ''' +( + /( + \.eggs + | \.git + | \.hg + | \.mypy_cache + | \.tox + | \.venv + | _build + | buck-out + | build + | dist + )/ + | foo.py +) +''' diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index d04c8c6..0000000 --- a/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -uvicorn -starlette -boto3 -botocore \ No newline at end of file