From 82ac3bfc2b639806d388180808b5ee0f79d70d27 Mon Sep 17 00:00:00 2001 From: Allisson Azevedo Date: Wed, 6 Dec 2023 16:20:56 -0300 Subject: [PATCH 1/6] feat: add the basic structure for the home page --- Dockerfile | 2 + poetry.lock | 102 +++++++++++++++++++++++++++++++++++++++---- pyproject.toml | 1 + secure_qrcode/api.py | 14 +++++- static/styles.css | 3 ++ templates/index.html | 11 +++++ tests/test_api.py | 6 +++ 7 files changed, 129 insertions(+), 10 deletions(-) create mode 100644 static/styles.css create mode 100644 templates/index.html diff --git a/Dockerfile b/Dockerfile index 6288e98..af05a75 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,6 +17,8 @@ RUN poetry install --only main # Copy app files to workdir COPY secure_qrcode ./secure_qrcode +COPY templates ./templates +COPY static ./static ##### Final Stage ##### FROM python:3.12-slim-bookworm diff --git a/poetry.lock b/poetry.lock index 235b6b1..f92e057 100644 --- a/poetry.lock +++ b/poetry.lock @@ -329,6 +329,92 @@ files = [ {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, ] +[[package]] +name = "jinja2" +version = "3.1.2" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "Jinja2-3.1.2-py3-none-any.whl", hash = "sha256:6088930bfe239f0e6710546ab9c19c9ef35e29792895fed6e6e31a023a182a61"}, + {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "markupsafe" +version = "2.1.3" +description = "Safely add untrusted strings to HTML/XML markup." +optional = false +python-versions = ">=3.7" +files = [ + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:cd0f502fe016460680cd20aaa5a76d241d6f35a1c3350c474bac1273803893fa"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e09031c87a1e51556fdcb46e5bd4f59dfb743061cf93c4d6831bf894f125eb57"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68e78619a61ecf91e76aa3e6e8e33fc4894a2bebe93410754bd28fce0a8a4f9f"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:65c1a9bcdadc6c28eecee2c119465aebff8f7a584dd719facdd9e825ec61ab52"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:525808b8019e36eb524b8c68acdd63a37e75714eac50e988180b169d64480a00"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:962f82a3086483f5e5f64dbad880d31038b698494799b097bc59c2edf392fce6"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:aa7bd130efab1c280bed0f45501b7c8795f9fdbeb02e965371bbef3523627779"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c9c804664ebe8f83a211cace637506669e7890fec1b4195b505c214e50dd4eb7"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win32.whl", hash = "sha256:10bbfe99883db80bdbaff2dcf681dfc6533a614f700da1287707e8a5d78a8431"}, + {file = "MarkupSafe-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:1577735524cdad32f9f694208aa75e422adba74f1baee7551620e43a3141f559"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ad9e82fb8f09ade1c3e1b996a6337afac2b8b9e365f926f5a61aacc71adc5b3c"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3c0fae6c3be832a0a0473ac912810b2877c8cb9d76ca48de1ed31e1c68386575"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b076b6226fb84157e3f7c971a47ff3a679d837cf338547532ab866c57930dbee"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bfce63a9e7834b12b87c64d6b155fdd9b3b96191b6bd334bf37db7ff1fe457f2"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:338ae27d6b8745585f87218a3f23f1512dbf52c26c28e322dbe54bcede54ccb9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e4dd52d80b8c83fdce44e12478ad2e85c64ea965e75d66dbeafb0a3e77308fcc"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:df0be2b576a7abbf737b1575f048c23fb1d769f267ec4358296f31c2479db8f9"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, + {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca379055a47383d02a5400cb0d110cef0a776fc644cda797db0c5696cfd7e18e"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7ff0f54cb4ff66dd38bebd335a38e2c22c41a8ee45aa608efc890ac3e3931bc"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c011a4149cfbcf9f03994ec2edffcb8b1dc2d2aede7ca243746df97a5d41ce48"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:56d9f2ecac662ca1611d183feb03a3fa4406469dafe241673d521dd5ae92a155"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win32.whl", hash = "sha256:8758846a7e80910096950b67071243da3e5a20ed2546e6392603c096778d48e0"}, + {file = "MarkupSafe-2.1.3-cp37-cp37m-win_amd64.whl", hash = "sha256:787003c0ddb00500e49a10f2844fac87aa6ce977b90b0feaaf9de23c22508b24"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:2ef12179d3a291be237280175b542c07a36e7f60718296278d8593d21ca937d4"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2c1b19b3aaacc6e57b7e25710ff571c24d6c3613a45e905b1fde04d691b98ee0"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8afafd99945ead6e075b973fefa56379c5b5c53fd8937dad92c662da5d8fd5ee"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8c41976a29d078bb235fea9b2ecd3da465df42a562910f9022f1a03107bd02be"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d080e0a5eb2529460b30190fcfcc4199bd7f827663f858a226a81bc27beaa97e"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69c0f17e9f5a7afdf2cc9fb2d1ce6aabdb3bafb7f38017c0b77862bcec2bbad8"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:504b320cd4b7eff6f968eddf81127112db685e81f7e36e75f9f84f0df46041c3"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:42de32b22b6b804f42c5d98be4f7e5e977ecdd9ee9b660fda1a3edf03b11792d"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win32.whl", hash = "sha256:ceb01949af7121f9fc39f7d27f91be8546f3fb112c608bc4029aef0bab86a2a5"}, + {file = "MarkupSafe-2.1.3-cp38-cp38-win_amd64.whl", hash = "sha256:1b40069d487e7edb2676d3fbdb2b0829ffa2cd63a2ec26c4938b2d34391b4ecc"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:8023faf4e01efadfa183e863fefde0046de576c6f14659e8782065bcece22198"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6b2b56950d93e41f33b4223ead100ea0fe11f8e6ee5f641eb753ce4b77a7042b"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9dcdfd0eaf283af041973bff14a2e143b8bd64e069f4c383416ecd79a81aab58"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05fb21170423db021895e1ea1e1f3ab3adb85d1c2333cbc2310f2a26bc77272e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:282c2cb35b5b673bbcadb33a585408104df04f14b2d9b01d4c345a3b92861c2c"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab4a0df41e7c16a1392727727e7998a467472d0ad65f3ad5e6e765015df08636"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7ef3cb2ebbf91e330e3bb937efada0edd9003683db6b57bb108c4001f37a02ea"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0a4e4a1aff6c7ac4cd55792abf96c915634c2b97e3cc1c7129578aa68ebd754e"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win32.whl", hash = "sha256:fec21693218efe39aa7f8599346e90c705afa52c5b31ae019b2e57e8f6542bb2"}, + {file = "MarkupSafe-2.1.3-cp39-cp39-win_amd64.whl", hash = "sha256:3fd4abcb888d15a94f32b75d8fd18ee162ca0c064f35b11134be77050296d6ba"}, + {file = "MarkupSafe-2.1.3.tar.gz", hash = "sha256:af598ed32d6ae86f1b747b82783958b1a4ab8f617b06fe68795c7f026abbdcad"}, +] + [[package]] name = "nodeenv" version = "1.8.0" @@ -423,13 +509,13 @@ tests = ["check-manifest", "coverage", "defusedxml", "markdown2", "olefile", "pa [[package]] name = "platformdirs" -version = "4.0.0" +version = "4.1.0" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "platformdirs-4.0.0-py3-none-any.whl", hash = "sha256:118c954d7e949b35437270383a3f2531e99dd93cf7ce4dc8340d3356d30f173b"}, - {file = "platformdirs-4.0.0.tar.gz", hash = "sha256:cb633b2bcf10c51af60beb0ab06d2f1d69064b43abf4c185ca6b28865f3f9731"}, + {file = "platformdirs-4.1.0-py3-none-any.whl", hash = "sha256:11c8f37bcca40db96d8144522d925583bdb7a31f7b0e37e3ed4318400a8e2380"}, + {file = "platformdirs-4.1.0.tar.gz", hash = "sha256:906d548203468492d432bcb294d4bc2fff751bf84971fbb2c10918cc206ee420"}, ] [package.extras] @@ -933,13 +1019,13 @@ test = ["Cython (>=0.29.36,<0.30.0)", "aiohttp (==3.9.0b0)", "aiohttp (>=3.8.1)" [[package]] name = "virtualenv" -version = "20.24.7" +version = "20.25.0" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.7" files = [ - {file = "virtualenv-20.24.7-py3-none-any.whl", hash = "sha256:a18b3fd0314ca59a2e9f4b556819ed07183b3e9a3702ecfe213f593d44f7b3fd"}, - {file = "virtualenv-20.24.7.tar.gz", hash = "sha256:69050ffb42419c91f6c1284a7b24e0475d793447e35929b488bf6a0aade39353"}, + {file = "virtualenv-20.25.0-py3-none-any.whl", hash = "sha256:4238949c5ffe6876362d9c0180fc6c3a824a7b12b80604eeb8085f2ed7460de3"}, + {file = "virtualenv-20.25.0.tar.gz", hash = "sha256:bf51c0d9c7dd63ea8e44086fa1e4fb1093a31e963b86959257378aef020e1f1b"}, ] [package.dependencies] @@ -1122,4 +1208,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.12" -content-hash = "02de669f67fa8a15917e3d8e09a45ae8fc2c41eafe2c27eb6ad6aa11e076ba0b" +content-hash = "0c37d01fe0e458a3346b39fc58f277c5ddaccb8cf0f0ace0d0abf4c5fedffe84" diff --git a/pyproject.toml b/pyproject.toml index fecb4c0..9c0d514 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,6 +12,7 @@ pycryptodome = "^3.19.0" fastapi = "^0.104.1" uvicorn = {extras = ["standard"], version = "^0.24.0.post1"} pydantic-settings = "^2.1.0" +jinja2 = "^3.1.2" [tool.poetry.group.test.dependencies] pytest = "^7.4.3" diff --git a/secure_qrcode/api.py b/secure_qrcode/api.py index c034041..9f034c8 100644 --- a/secure_qrcode/api.py +++ b/secure_qrcode/api.py @@ -1,7 +1,9 @@ from base64 import b64encode from fastapi import FastAPI, Request -from fastapi.responses import JSONResponse +from fastapi.responses import HTMLResponse, JSONResponse +from fastapi.staticfiles import StaticFiles +from fastapi.templating import Jinja2Templates from secure_qrcode.config import settings from secure_qrcode.crypto import decrypt, encrypt @@ -19,6 +21,8 @@ title="Secure QR code", description="Encrypt your data using the modern ChaCha20-Poly1305 cipher and export it into a secure QR code", ) +app.mount("/static", StaticFiles(directory="static"), name="static") +templates = Jinja2Templates(directory="templates") @app.exception_handler(DecryptError) @@ -29,7 +33,12 @@ def decrypt_error_exception_handler(request: Request, exc: DecryptError): ) -@app.post("/v1/encode", status_code=201) +@app.get("/", response_class=HTMLResponse, tags=["home"]) +def index(request: Request): + return templates.TemplateResponse("index.html", {"request": request}) + + +@app.post("/v1/encode", status_code=201, tags=["api"]) def encode(request: EncodeRequest) -> EncodeResponse: encrypted_data = encrypt(request.plaintext, request.key, settings.left_padding_char) img_io = make( @@ -45,6 +54,7 @@ def encode(request: EncodeRequest) -> EncodeResponse: "/v1/decode", status_code=201, responses={400: {"model": DecryptErrorResponse, "description": "Incorrect decryption"}}, + tags=["api"], ) def decode(request: DecodeRequest) -> DecodeResponse: decrypted_data = decrypt(request.encrypted_data, request.key, settings.left_padding_char) diff --git a/static/styles.css b/static/styles.css new file mode 100644 index 0000000..3d9a2b2 --- /dev/null +++ b/static/styles.css @@ -0,0 +1,3 @@ +p { + color: red; +} diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..58a3b29 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,11 @@ + + + + + Hello World + + + +

Hello World

+ + diff --git a/tests/test_api.py b/tests/test_api.py index 839f5f6..e6bb06f 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -3,6 +3,12 @@ from secure_qrcode.models import DecodeRequest, EncodeRequest, EncryptedData +def test_index(client): + response = client.get("/") + + assert response.status_code == 200 + + def test_encode(client, plaintext, key): request = EncodeRequest(plaintext=plaintext, key=key) response = client.post("/v1/encode", json=request.model_dump()) From f359a4da1a7711a8199b6b62de3b85b8de021377 Mon Sep 17 00:00:00 2001 From: Allisson Azevedo Date: Thu, 7 Dec 2023 09:24:11 -0300 Subject: [PATCH 2/6] feat: add the healthz endpoint --- poetry.lock | 6 +++--- secure_qrcode/api.py | 6 ++++++ secure_qrcode/models.py | 4 ++++ tests/test_api.py | 6 ++++++ 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index f92e057..91562f0 100644 --- a/poetry.lock +++ b/poetry.lock @@ -295,13 +295,13 @@ socks = ["socksio (==1.*)"] [[package]] name = "identify" -version = "2.5.32" +version = "2.5.33" description = "File identification library for Python" optional = false python-versions = ">=3.8" files = [ - {file = "identify-2.5.32-py2.py3-none-any.whl", hash = "sha256:0b7656ef6cba81664b783352c73f8c24b39cf82f926f78f4550eda928e5e0545"}, - {file = "identify-2.5.32.tar.gz", hash = "sha256:5d9979348ec1a21c768ae07e0a652924538e8bce67313a73cb0f681cf08ba407"}, + {file = "identify-2.5.33-py2.py3-none-any.whl", hash = "sha256:d40ce5fcd762817627670da8a7d8d8e65f24342d14539c59488dc603bf662e34"}, + {file = "identify-2.5.33.tar.gz", hash = "sha256:161558f9fe4559e1557e1bff323e8631f6a0e4837f7497767c1782832f16b62d"}, ] [package.extras] diff --git a/secure_qrcode/api.py b/secure_qrcode/api.py index 9f034c8..a622f21 100644 --- a/secure_qrcode/api.py +++ b/secure_qrcode/api.py @@ -14,6 +14,7 @@ DecryptErrorResponse, EncodeRequest, EncodeResponse, + HealthResponse, ) from secure_qrcode.qrcode import make @@ -59,3 +60,8 @@ def encode(request: EncodeRequest) -> EncodeResponse: def decode(request: DecodeRequest) -> DecodeResponse: decrypted_data = decrypt(request.encrypted_data, request.key, settings.left_padding_char) return DecodeResponse(decrypted_data=decrypted_data) + + +@app.get("/healthz", tags=["healthcheck"]) +def healthz() -> HealthResponse: + return HealthResponse(success=True) diff --git a/secure_qrcode/models.py b/secure_qrcode/models.py index 21aa9ca..0e9a1b7 100644 --- a/secure_qrcode/models.py +++ b/secure_qrcode/models.py @@ -44,3 +44,7 @@ class DecodeResponse(BaseModel): class DecryptErrorResponse(BaseModel): message: str + + +class HealthResponse(BaseModel): + success: bool diff --git a/tests/test_api.py b/tests/test_api.py index e6bb06f..65ea3ca 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -48,3 +48,9 @@ def test_decode_error(client, plaintext, key): assert response.status_code == 400 response_data = response.json() assert response_data["message"] == "Incorrect decryption, please check your data" + + +def test_healthz(client): + response = client.get("/healthz") + + assert response.status_code == 200 From 0e2fd795aaeb43ffb7b94314f24b744a6446a480 Mon Sep 17 00:00:00 2001 From: Allisson Azevedo Date: Thu, 7 Dec 2023 09:46:58 -0300 Subject: [PATCH 3/6] docs: update the readme with the public url of the project --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f9e6ef0..86eadb8 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,12 @@ Encrypt your data using the modern ChaCha20-Poly1305 cipher and export it into a secure QR code. +## access via browser + +Open the url https://secure-qrcode.onrender.com on your browser. + +If you want to run this on your local machine, see the next section. + ## run the api The server can be started using a docker image: @@ -12,7 +18,7 @@ The server can be started using a docker image: docker run --rm -p 8000:8000 quay.io/allisson/secure-qrcode ``` -Now the API server will be running on port 8000. +Now the API server will be running on port 8000 and you can open the url http://localhost:8000 on your browser. ## api documentation From c705aa13695e11466059b5831c6191e8af950b4a Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Fri, 8 Dec 2023 23:13:55 -0300 Subject: [PATCH 4/6] feat: add first version of secure front page --- static/github.svg | 1 + static/styles.css | 127 ++++++++++- templates/index.html | 501 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 618 insertions(+), 11 deletions(-) create mode 100644 static/github.svg diff --git a/static/github.svg b/static/github.svg new file mode 100644 index 0000000..d5e6491 --- /dev/null +++ b/static/github.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/styles.css b/static/styles.css index 3d9a2b2..bc525ca 100644 --- a/static/styles.css +++ b/static/styles.css @@ -1,3 +1,126 @@ -p { - color: red; +html, +body { + margin: 0; + padding: 0; +} + +body { + background: linear-gradient(90deg, #00d2ff 0%, #3a47d5 100%); +} + +#root { + display: flex; + justify-content: center; + align-items: center; +} + +main { + display: flex; + flex-direction: column; +} + +.container { + background-color: #e8eef2; + border-radius: 2px; + box-shadow: rgba(0, 0, 0, 0.16) 0px 1px 4px; + padding: 0; +} + +img { + width: 300px; + height: 300px; +} + +.nav-link { + text-transform: uppercase; +} + +.nav-tabs .nav-item.show .nav-link, +.nav-tabs .nav-link, +.nav-tabs .nav-link.active { + background-color: transparent; + border: none; + color: white; + font-weight: bold; + margin: 2px; +} + +.nav-tabs .nav-link.active { + border-bottom: 3px solid white; +} + +.nav-tabs { + border: none; +} + +.feature { + display: flex; + flex-direction: row; +} + +@media only screen and (max-width: 600px) { + .feature { + flex-direction: column; + } +} + +form { + padding: 20px; + max-width: 400px; + width: 400px; + overflow: hidden; +} + +.qrCode { + background-color: white; + padding: 20px; + width: 340px; +} + +.json { + background: #f2f2f2; + padding: 10px; + overflow: auto; + /* first line not indented */ + & > .line { + margin-left: 0; + } + .line { + margin-left: 4px; + } + .key { + margin-right: 2px; + color: black; + font-weight: 600; + } + .string { + color: green; + } + .number { + color: blue; + } + .boolean { + color: purple; + } + .null { + color: red; + } +} + +footer a { + color: white; + font-size: 16px; +} + +img.icon-footer { + width: 24px; + height: 24px; + margin-right: 10px; +} + +.upload { + display: flex; + justify-content: center; + align-items: center; + padding: 20px 0; } diff --git a/templates/index.html b/templates/index.html index 58a3b29..2f51daa 100644 --- a/templates/index.html +++ b/templates/index.html @@ -1,11 +1,494 @@ - + - - - Hello World - - - -

Hello World

- + + + QRCode Generator + + + + + + + + +
+ + From 5c31d4d2875154fcb21f2ea16f5c37f10c79c0fc Mon Sep 17 00:00:00 2001 From: Allisson Azevedo Date: Sat, 9 Dec 2023 20:24:20 -0300 Subject: [PATCH 5/6] style: fix end of file --- static/github.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/github.svg b/static/github.svg index d5e6491..c679c23 100644 --- a/static/github.svg +++ b/static/github.svg @@ -1 +1 @@ - \ No newline at end of file + From 83133fc8ef35660aadc402c3c226fe52335bc121 Mon Sep 17 00:00:00 2001 From: Paulo Reis Date: Sun, 10 Dec 2023 03:16:23 -0300 Subject: [PATCH 6/6] feat: disable camera on unmount component --- templates/index.html | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/templates/index.html b/templates/index.html index 2f51daa..b9b5a7a 100644 --- a/templates/index.html +++ b/templates/index.html @@ -180,8 +180,9 @@ function QRReader({ onCode }) { const canvasEl = React.useRef(null); const videoEl = React.useRef(null); + const streamRef = React.useRef(null); - React.useLayoutEffect(() => { + React.useEffect(() => { if (!videoEl.current || !canvasEl.current) { return; } @@ -189,6 +190,7 @@ navigator.mediaDevices .getUserMedia({ video: { facingMode: "environment" } }) .then((stream) => { + streamRef.current = stream; let video = videoEl.current; video.srcObject = stream; video.setAttribute("playsinline", true); @@ -197,6 +199,10 @@ tick(videoEl.current, canvasEl.current, onCode) ); }); + + return () => { + streamRef.current?.getTracks().forEach((track) => track.stop()); + }; }, [videoEl, canvasEl]); return (