From feb798140af684e724acb0cfcaca8626973eccfb Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Tue, 22 Dec 2020 14:23:47 +0200 Subject: Create route for adding new admins --- backend/routes/admin.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 backend/routes/admin.py diff --git a/backend/routes/admin.py b/backend/routes/admin.py new file mode 100644 index 0000000..ef01fbd --- /dev/null +++ b/backend/routes/admin.py @@ -0,0 +1,31 @@ +""" +Adds new admin user. +""" +from spectree import Response +from starlette.authentication import requires +from starlette.requests import Request +from starlette.responses import JSONResponse + +from backend.route import Route +from backend.validation import ErrorMessage, OkayResponse, api + + +class AdminRoute(Route): + """Adds new admin user.""" + + name = "admin" + path = "/admin" + + @requires(["authenticated", "admin"]) + @api.validate( + resp=Response(HTTP_200=OkayResponse, HTTP_400=ErrorMessage), + tags=["admin"] + ) + async def post(self, request: Request) -> JSONResponse: + """Inserts new administrator user to DB.""" + data = await request.json() + if "id" not in data: + return JSONResponse({"error": "missing_id"}, status_code=400) + + await request.state.db.admins.insert_one({"_id": str(data["id"])}) + return JSONResponse({"status": "ok"}) -- cgit v1.2.3 From 4976b75fd1019c824339c4996afba0bf1611b134 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Tue, 22 Dec 2020 14:21:57 +0000 Subject: Update dependency pyjwt to v2 --- poetry.lock | 19 ++++++++++--------- pyproject.toml | 2 +- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/poetry.lock b/poetry.lock index 785fec6..cf19c08 100644 --- a/poetry.lock +++ b/poetry.lock @@ -186,16 +186,17 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [[package]] name = "pyjwt" -version = "1.7.1" +version = "2.0.0" description = "JSON Web Token implementation in Python" category = "main" optional = false -python-versions = "*" +python-versions = ">=3.6" [package.extras] -crypto = ["cryptography (>=1.4)"] -flake8 = ["flake8", "flake8-import-order", "pep8-naming"] -test = ["pytest (>=4.0.1,<5.0.0)", "pytest-cov (>=2.6.0,<3.0.0)", "pytest-runner (>=4.2,<5.0.0)"] +crypto = ["cryptography (>=3.3.1,<4.0.0)"] +dev = ["sphinx", "sphinx-rtd-theme", "zope.interface", "cryptography (>=3.3.1,<4.0.0)", "pytest (>=6.0.0,<7.0.0)", "coverage[toml] (==5.0.4)", "mypy", "pre-commit"] +docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"] +tests = ["pytest (>=6.0.0,<7.0.0)", "coverage[toml] (==5.0.4)"] [[package]] name = "pymongo" @@ -232,7 +233,7 @@ version = "5.3.1" description = "YAML parser and emitter for Python" category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = "*" [[package]] name = "rfc3986" @@ -333,7 +334,7 @@ python-versions = ">=3.6.1" [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "7584e4eacc1b2615adce06899fe6e6b8d696955fea97533ccac2bd2c642e136f" +content-hash = "d863036c29d41783f127e3ebd0dce61349c5c071d5de438ab208863505d00c2d" [metadata.files] certifi = [ @@ -438,8 +439,8 @@ pyflakes = [ {file = "pyflakes-2.2.0.tar.gz", hash = "sha256:35b2d75ee967ea93b55750aa9edbbf72813e06a66ba54438df2cfac9e3c27fc8"}, ] pyjwt = [ - {file = "PyJWT-1.7.1-py2.py3-none-any.whl", hash = "sha256:5c6eca3c2940464d106b99ba83b00c6add741c9becaec087fb7ccdefea71350e"}, - {file = "PyJWT-1.7.1.tar.gz", hash = "sha256:8d59a976fb773f3e6a39c85636357c4f0e242707394cadadd9814f5cbaa20e96"}, + {file = "PyJWT-2.0.0-py3-none-any.whl", hash = "sha256:5c2ff2eb27d7e342dfc3cafcc16412781f06db2690fbef81922b0172598f085b"}, + {file = "PyJWT-2.0.0.tar.gz", hash = "sha256:7a2b271c6dac2fda9e0c33d176c4253faba2c6c6b3a99c7f28a32c3c97522779"}, ] pymongo = [ {file = "pymongo-3.11.2-cp27-cp27m-macosx_10_14_intel.whl", hash = "sha256:9be785bd4e1ba0148fb00ca84e4dbfbd1c74df3af3a648559adc60b0782f34de"}, diff --git a/pyproject.toml b/pyproject.toml index 642fb6c..8dd723d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,7 @@ nested_dict = "^1.61" uvicorn = {extras = ["standard"], version = "^0.13.0"} motor = "^2.3.0" python-dotenv = "^0.15.0" -pyjwt = "^1.7.1" +pyjwt = "^2.0.0" httpx = "^0.16.1" gunicorn = "^20.0.4" pydantic = "^1.7.2" -- cgit v1.2.3 From d30ac683746ecf92267884c2fc1ae654a7203dd4 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Thu, 24 Dec 2020 08:09:53 +0200 Subject: Use Pydantic validation instead manual validation --- backend/routes/admin.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/backend/routes/admin.py b/backend/routes/admin.py index ef01fbd..08e97ce 100644 --- a/backend/routes/admin.py +++ b/backend/routes/admin.py @@ -1,6 +1,7 @@ """ Adds new admin user. """ +from pydantic import BaseModel, Field from spectree import Response from starlette.authentication import requires from starlette.requests import Request @@ -10,6 +11,10 @@ from backend.route import Route from backend.validation import ErrorMessage, OkayResponse, api +class AdminModel(BaseModel): + id: str = Field(alias="_id") + + class AdminRoute(Route): """Adds new admin user.""" @@ -18,14 +23,14 @@ class AdminRoute(Route): @requires(["authenticated", "admin"]) @api.validate( + json=AdminModel, resp=Response(HTTP_200=OkayResponse, HTTP_400=ErrorMessage), tags=["admin"] ) async def post(self, request: Request) -> JSONResponse: """Inserts new administrator user to DB.""" data = await request.json() - if "id" not in data: - return JSONResponse({"error": "missing_id"}, status_code=400) + admin = AdminModel(**data) - await request.state.db.admins.insert_one({"_id": str(data["id"])}) + await request.state.db.admins.insert_one(admin.dict(by_alias=True)) return JSONResponse({"status": "ok"}) -- cgit v1.2.3 From e0efac856723c6c2517308d76a2be4f27bc113df Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Thu, 24 Dec 2020 08:12:35 +0200 Subject: Check is user already admin before adding --- backend/routes/admin.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/backend/routes/admin.py b/backend/routes/admin.py index 08e97ce..ff329fa 100644 --- a/backend/routes/admin.py +++ b/backend/routes/admin.py @@ -32,5 +32,10 @@ class AdminRoute(Route): data = await request.json() admin = AdminModel(**data) + if await request.state.db.admins.find_one( + {"_id": admin.id} + ): + return JSONResponse({"error": "already_exists"}, status_code=400) + await request.state.db.admins.insert_one(admin.dict(by_alias=True)) return JSONResponse({"status": "ok"}) -- cgit v1.2.3 From d04f23cc51716d49e10ea7714d6c4e2fc3815c48 Mon Sep 17 00:00:00 2001 From: ks129 <45097959+ks129@users.noreply.github.com> Date: Thu, 24 Dec 2020 08:13:59 +0200 Subject: Update admin add route docstring Co-authored-by: Joe Banks --- backend/routes/admin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/routes/admin.py b/backend/routes/admin.py index ff329fa..5254f8b 100644 --- a/backend/routes/admin.py +++ b/backend/routes/admin.py @@ -28,7 +28,7 @@ class AdminRoute(Route): tags=["admin"] ) async def post(self, request: Request) -> JSONResponse: - """Inserts new administrator user to DB.""" + """Grant a user administrator privileges.""" data = await request.json() admin = AdminModel(**data) -- cgit v1.2.3