diff --git a/.github/workflows/docker-publish-image-stable.yml b/.github/workflows/docker-publish-image-stable.yml new file mode 100644 index 00000000..5c550c6a --- /dev/null +++ b/.github/workflows/docker-publish-image-stable.yml @@ -0,0 +1,40 @@ +name: Build and publish docker image +on: + push: + tags: '*.*.*' + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }}_stable + +jobs: + build-and-push-image: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Log in to the Container registry + uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + - name: Build and push Docker image + uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.github/workflows/docker-publish-image-unstable.yml b/.github/workflows/docker-publish-image-unstable.yml new file mode 100644 index 00000000..534771ce --- /dev/null +++ b/.github/workflows/docker-publish-image-unstable.yml @@ -0,0 +1,44 @@ +name: Build and publish docker image +on: + push: + branches: [ develop ] + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }}_unstable + +jobs: + build-and-push-image: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Log in to the Container registry + uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + + - name: Get current date + id: date + run: echo "::set-output name=date::$(date +'%Y.%m.%d')" + + - name: Build and push Docker image + uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }}_${{ steps.date.outputs.date }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 00000000..7c4c71da --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,41 @@ +name: Build and push docs +on: + push: + branches: [ master, develop ] + +jobs: + build-and-deploy: + concurrency: ci-${{ github.ref }} + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Set up Python 3.10 + uses: actions/setup-python@v2 + with: + python-version: "3.10" + + - name: Install pipenv + run: | + pip install pipenv + + - name: Install dependencies + run: | + pipenv install --dev + + - name: Create config for server + run: | + mv example_config.ini config.ini + + - name: Build docs + run: | + cd docs + pipenv run make html + + - name: Deploy + uses: JamesIves/github-pages-deploy-action@v4.2.3 + with: + branch: docs + folder: ./docs/build/html/ + target-folder: ${{ github.ref_name }} diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 00000000..1a4601cb --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,36 @@ +name: Test and Push coverage to Coveralls + +on: [push, pull_request] + +jobs: + tests: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3.10 + uses: actions/setup-python@v2 + with: + python-version: "3.10" + + - name: Install pipenv + run: | + pip install pipenv + + - name: Install dependencies + run: | + pipenv install --dev + + - name: Create config for server + run: | + mv example_config.ini config.ini + + - name: Run tests + run: | + pipenv run coverage run -m unittest discover tests + + - name: Push report to coveralls.io + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + pipenv run coveralls --service=github diff --git a/.gitignore b/.gitignore index d3d7ee82..1cfa01fd 100644 --- a/.gitignore +++ b/.gitignore @@ -139,5 +139,5 @@ dmypy.json ## Morelia stuff db_sqlite.db config.ini -t.py ngrok.exe +/docs/log/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..8dab21ca --- /dev/null +++ b/Dockerfile @@ -0,0 +1,24 @@ +# syntax=docker/dockerfile:1 + +FROM python:3.10.2-slim-bullseye + +WORKDIR /morelia-server + +COPY Pipfile Pipfile +COPY Pipfile.lock Pipfile.lock + +RUN pip3 install pipenv +RUN pipenv install --ignore-pipfile + +COPY example_config.ini config.ini + +COPY . . + +CMD [ "pipenv", "run", \ + "python", "-m", \ + "uvicorn", "server:app", \ + "--host", "0.0.0.0", \ + "--port", "8000", \ + "--reload", "--use-colors", \ + "--http", "h11", "--ws", "websockets" \ + ] diff --git a/Pipfile b/Pipfile index 3971212c..737604a4 100644 --- a/Pipfile +++ b/Pipfile @@ -8,6 +8,7 @@ flake8 = "*" pyflakes = "*" pycodestyle = "*" mccabe = "*" +coveralls = "==3.3.1" [packages] fastapi = "==0.71.0" @@ -16,7 +17,7 @@ jinja2 = "==3.0.3" aiofiles = "==0.7.0" email-validator = "==1.1.3" sqlobject = "==3.9.1" -loguru = "==0.5.3" +loguru = "==0.6.0" websockets = "==10.1" pydantic = "==1.9.0" fastapi-login = "==1.7.3" @@ -25,6 +26,8 @@ websocket-client = "==1.2.3" coverage = "==6.2" requests = "==2.27.1" win32-setctime = "*" +sphinx = "==4.4.0" +furo = "==2022.1.2" [requires] python_version = "3.10" diff --git a/Pipfile.lock b/Pipfile.lock index e5db376c..f29da7e1 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "6758f84d8690f63bbde83833ba2941743bf5e26f28a8a1cf52bc7517555d5b2f" + "sha256": "0628c267ce6c693fba4c09dc6e7555a5bf26b504ebfd00b0684590418b9cdd9e" }, "pipfile-spec": 6, "requires": { @@ -24,6 +24,13 @@ "index": "pypi", "version": "==0.7.0" }, + "alabaster": { + "hashes": [ + "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359", + "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02" + ], + "version": "==0.7.12" + }, "anyio": { "hashes": [ "sha256:a0aeffe2fb1fdf374a8e4b471444f0f3ac4fb9f5a5b542b48824475e0042a5a6", @@ -34,11 +41,27 @@ }, "asgiref": { "hashes": [ - "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9", - "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214" + "sha256:2f8abc20f7248433085eda803936d98992f1343ddb022065779f37c5da0181d0", + "sha256:88d59c13d634dcffe0510be048210188edd79aeccb6a6c9028cdad6f31d730a9" ], - "markers": "python_version >= '3.6'", - "version": "==3.4.1" + "markers": "python_version >= '3.7'", + "version": "==3.5.0" + }, + "babel": { + "hashes": [ + "sha256:ab49e12b91d937cd11f0b67cb259a57ab4ad2b59ac7a3b41d6c06c0ac5b0def9", + "sha256:bc0c176f9f6a994582230df350aa6e05ba2ebe4b3ac317eab29d9be5d2768da0" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==2.9.1" + }, + "beautifulsoup4": { + "hashes": [ + "sha256:9a315ce70049920ea4572a4055bc4bd700c940521d36fc858205ad4fcde149bf", + "sha256:c23ad23c521d818955a4151a67d81580319d4bf548d3d49f4223ae041ff98891" + ], + "markers": "python_version >= '3.1'", + "version": "==4.10.0" }, "certifi": { "hashes": [ @@ -49,11 +72,11 @@ }, "charset-normalizer": { "hashes": [ - "sha256:876d180e9d7432c5d1dfd4c5d26b72f099d503e8fcc0feb7532c9289be60fcbd", - "sha256:cb957888737fc0bbcd78e3df769addb41fd1ff8cf950dc9e7ad7793f1bf44455" + "sha256:2842d8f5e82a1f6aa437380934d5e1cd4fcf2003b06fed6940769c164a480a45", + "sha256:98398a9d69ee80548c762ba991a4728bfc3836768ed226b3945908d1a688371c" ], "markers": "python_version >= '3'", - "version": "==2.0.10" + "version": "==2.0.11" }, "click": { "hashes": [ @@ -118,11 +141,19 @@ }, "dnspython": { "hashes": [ - "sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216", - "sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4" + "sha256:081649da27ced5e75709a1ee542136eaba9842a0fe4c03da4fb0a3d3ed1f3c44", + "sha256:e79351e032d0b606b98d38a4b0e6e2275b31a5b85c873e587cc11b73aca026d6" ], - "markers": "python_version >= '3.6'", - "version": "==2.1.0" + "markers": "python_version >= '3.6' and python_version < '4.0'", + "version": "==2.2.0" + }, + "docutils": { + "hashes": [ + "sha256:686577d2e4c32380bb50cbb22f575ed742d58168cee37e99117a854bcd88f125", + "sha256:cf316c8370a737a022b72b56874f6602acf974a37a9fba42ec2876387549fc61" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", + "version": "==0.17.1" }, "email-validator": { "hashes": [ @@ -156,13 +187,21 @@ "markers": "python_version >= '3.4'", "version": "==2.0.1" }, + "furo": { + "hashes": [ + "sha256:958016bfe1387c1e8ddf5b9d71696b69c4eaa5cd8afc9492abfb008aba2d300c", + "sha256:b217f218cbcd423ffbfe69baa79389d4ecebf2d86f0d593c44ef31da7b5aed30" + ], + "index": "pypi", + "version": "==2022.1.2" + }, "h11": { "hashes": [ - "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6", - "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042" + "sha256:70813c1135087a248a4d38cc0e1a0181ffab2188141a93eaf567940c3957ff06", + "sha256:8ddd78563b633ca55346c8cd41ec0af27d3c79931828beffb46ce70a379e7442" ], "markers": "python_version >= '3.6'", - "version": "==0.12.0" + "version": "==0.13.0" }, "idna": { "hashes": [ @@ -172,6 +211,14 @@ "markers": "python_version >= '3'", "version": "==3.3" }, + "imagesize": { + "hashes": [ + "sha256:1db2f82529e53c3e929e8926a1fa9235aa82d0bd0c580359c67ec31b2fddaa8c", + "sha256:cd1750d452385ca327479d45b64d9c7729ecf0b3969a58148298c77092261f9d" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.3.0" + }, "jinja2": { "hashes": [ "sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8", @@ -182,11 +229,11 @@ }, "loguru": { "hashes": [ - "sha256:b28e72ac7a98be3d28ad28570299a393dfcd32e5e3f6a353dec94675767b6319", - "sha256:f8087ac396b5ee5f67c963b495d615ebbceac2796379599820e324419d53667c" + "sha256:066bd06758d0a513e9836fd9c6b5a75bfb3fd36841f4b996bc60b547a309d41c", + "sha256:4e2414d534a2ab57573365b3e6d0234dfb1d84b68b7f3b948e6fb743860a77c3" ], "index": "pypi", - "version": "==0.5.3" + "version": "==0.6.0" }, "markupsafe": { "hashes": [ @@ -263,6 +310,14 @@ "markers": "python_version >= '3.6'", "version": "==2.0.1" }, + "packaging": { + "hashes": [ + "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb", + "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522" + ], + "markers": "python_version >= '3.6'", + "version": "==21.3" + }, "passlib": { "hashes": [ "sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1", @@ -318,6 +373,14 @@ ], "version": "==2.0.5" }, + "pygments": { + "hashes": [ + "sha256:44238f1b60a76d78fc8ca0528ee429702aae011c265fe6a8dd8b63049ae41c65", + "sha256:4e426f72023d88d03b2fa258de560726ce890ff3b630f88c21cbb8b2503b8c6a" + ], + "markers": "python_version >= '3.5'", + "version": "==2.11.2" + }, "pyjwt": { "hashes": [ "sha256:b888b4d56f06f6dcd777210c334e69c737be74755d3e5e9ee3fe67dc18a0ee41", @@ -326,6 +389,14 @@ "markers": "python_version >= '3.6'", "version": "==2.3.0" }, + "pyparsing": { + "hashes": [ + "sha256:18ee9022775d270c55187733956460083db60b37d0d0fb357445f3094eed3eea", + "sha256:a6c06a88f252e6c322f65faf8f418b16213b51bdfaece0524c1c1bc30c63c484" + ], + "markers": "python_version >= '3.6'", + "version": "==3.0.7" + }, "python-multipart": { "hashes": [ "sha256:f7bb5f611fc600d15fa47b3974c8aa16e93724513b49b5f95c81e6624c83fa43" @@ -333,6 +404,13 @@ "index": "pypi", "version": "==0.0.5" }, + "pytz": { + "hashes": [ + "sha256:3672058bc3453457b622aab7a1c3bfd5ab0bdae451512f6cf25f64ed37f5b87c", + "sha256:acad2d8b20a1af07d4e4c9d2e9285c5ed9104354062f275f3fcd88dcef4f1326" + ], + "version": "==2021.3" + }, "requests": { "hashes": [ "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61", @@ -357,6 +435,77 @@ "markers": "python_version >= '3.5'", "version": "==1.2.0" }, + "snowballstemmer": { + "hashes": [ + "sha256:09b16deb8547d3412ad7b590689584cd0fe25ec8db3be37788be3810cbf19cb1", + "sha256:c8e1716e83cc398ae16824e5572ae04e0d9fc2c6b985fb0f900f5f0c96ecba1a" + ], + "version": "==2.2.0" + }, + "soupsieve": { + "hashes": [ + "sha256:1a3cca2617c6b38c0343ed661b1fa5de5637f257d4fe22bd9f1338010a1efefb", + "sha256:b8d49b1cd4f037c7082a9683dfa1801aa2597fb11c3a1155b7a5b94829b4f1f9" + ], + "markers": "python_version >= '3.6'", + "version": "==2.3.1" + }, + "sphinx": { + "hashes": [ + "sha256:5da895959511473857b6d0200f56865ed62c31e8f82dd338063b84ec022701fe", + "sha256:6caad9786055cb1fa22b4a365c1775816b876f91966481765d7d50e9f0dd35cc" + ], + "index": "pypi", + "version": "==4.4.0" + }, + "sphinxcontrib-applehelp": { + "hashes": [ + "sha256:806111e5e962be97c29ec4c1e7fe277bfd19e9652fb1a4392105b43e01af885a", + "sha256:a072735ec80e7675e3f432fcae8610ecf509c5f1869d17e2eecff44389cdbc58" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.2" + }, + "sphinxcontrib-devhelp": { + "hashes": [ + "sha256:8165223f9a335cc1af7ffe1ed31d2871f325254c0423bc0c4c7cd1c1e4734a2e", + "sha256:ff7f1afa7b9642e7060379360a67e9c41e8f3121f2ce9164266f61b9f4b338e4" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.2" + }, + "sphinxcontrib-htmlhelp": { + "hashes": [ + "sha256:d412243dfb797ae3ec2b59eca0e52dac12e75a241bf0e4eb861e450d06c6ed07", + "sha256:f5f8bb2d0d629f398bf47d0d69c07bc13b65f75a81ad9e2f71a63d4b7a2f6db2" + ], + "markers": "python_version >= '3.6'", + "version": "==2.0.0" + }, + "sphinxcontrib-jsmath": { + "hashes": [ + "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178", + "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.1" + }, + "sphinxcontrib-qthelp": { + "hashes": [ + "sha256:4c33767ee058b70dba89a6fc5c1892c0d57a54be67ddd3e7875a18d14cba5a72", + "sha256:bd9fc24bcb748a8d51fd4ecaade681350aa63009a347a8c14e637895444dfab6" + ], + "markers": "python_version >= '3.5'", + "version": "==1.0.3" + }, + "sphinxcontrib-serializinghtml": { + "hashes": [ + "sha256:352a9a00ae864471d3a7ead8d7d79f5fc0b57e8b3f95e9867eb9eb28999b92fd", + "sha256:aa5f6de5dfdf809ef505c4895e51ef5c9eac17d0f287933eb49ec495280b6952" + ], + "markers": "python_version >= '3.5'", + "version": "==1.1.5" + }, "sqlobject": { "hashes": [ "sha256:45064184decf7f42d386704e5f47a70dee517d3e449b610506e174025f84d921", @@ -461,14 +610,96 @@ }, "win32-setctime": { "hashes": [ - "sha256:2b72b798fdc1d909fb3cc0d25e0be52a42f4848857e3588dd3947c6a18b42609", - "sha256:7964234073ad9bc7a689ef2ebe6ce931976b644fe73fd50cf7729c996b7d8385" + "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2", + "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad" ], "index": "pypi", - "version": "==1.0.4" + "version": "==1.1.0" } }, "develop": { + "certifi": { + "hashes": [ + "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872", + "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569" + ], + "version": "==2021.10.8" + }, + "charset-normalizer": { + "hashes": [ + "sha256:2842d8f5e82a1f6aa437380934d5e1cd4fcf2003b06fed6940769c164a480a45", + "sha256:98398a9d69ee80548c762ba991a4728bfc3836768ed226b3945908d1a688371c" + ], + "markers": "python_version >= '3'", + "version": "==2.0.11" + }, + "coverage": { + "hashes": [ + "sha256:01774a2c2c729619760320270e42cd9e797427ecfddd32c2a7b639cdc481f3c0", + "sha256:03b20e52b7d31be571c9c06b74746746d4eb82fc260e594dc662ed48145e9efd", + "sha256:0a7726f74ff63f41e95ed3a89fef002916c828bb5fcae83b505b49d81a066884", + "sha256:1219d760ccfafc03c0822ae2e06e3b1248a8e6d1a70928966bafc6838d3c9e48", + "sha256:13362889b2d46e8d9f97c421539c97c963e34031ab0cb89e8ca83a10cc71ac76", + "sha256:174cf9b4bef0db2e8244f82059a5a72bd47e1d40e71c68ab055425172b16b7d0", + "sha256:17e6c11038d4ed6e8af1407d9e89a2904d573be29d51515f14262d7f10ef0a64", + "sha256:215f8afcc02a24c2d9a10d3790b21054b58d71f4b3c6f055d4bb1b15cecce685", + "sha256:22e60a3ca5acba37d1d4a2ee66e051f5b0e1b9ac950b5b0cf4aa5366eda41d47", + "sha256:2641f803ee9f95b1f387f3e8f3bf28d83d9b69a39e9911e5bfee832bea75240d", + "sha256:276651978c94a8c5672ea60a2656e95a3cce2a3f31e9fb2d5ebd4c215d095840", + "sha256:3f7c17209eef285c86f819ff04a6d4cbee9b33ef05cbcaae4c0b4e8e06b3ec8f", + "sha256:3feac4084291642165c3a0d9eaebedf19ffa505016c4d3db15bfe235718d4971", + "sha256:49dbff64961bc9bdd2289a2bda6a3a5a331964ba5497f694e2cbd540d656dc1c", + "sha256:4e547122ca2d244f7c090fe3f4b5a5861255ff66b7ab6d98f44a0222aaf8671a", + "sha256:5829192582c0ec8ca4a2532407bc14c2f338d9878a10442f5d03804a95fac9de", + "sha256:5d6b09c972ce9200264c35a1d53d43ca55ef61836d9ec60f0d44273a31aa9f17", + "sha256:600617008aa82032ddeace2535626d1bc212dfff32b43989539deda63b3f36e4", + "sha256:619346d57c7126ae49ac95b11b0dc8e36c1dd49d148477461bb66c8cf13bb521", + "sha256:63c424e6f5b4ab1cf1e23a43b12f542b0ec2e54f99ec9f11b75382152981df57", + "sha256:6dbc1536e105adda7a6312c778f15aaabe583b0e9a0b0a324990334fd458c94b", + "sha256:6e1394d24d5938e561fbeaa0cd3d356207579c28bd1792f25a068743f2d5b282", + "sha256:86f2e78b1eff847609b1ca8050c9e1fa3bd44ce755b2ec30e70f2d3ba3844644", + "sha256:8bdfe9ff3a4ea37d17f172ac0dff1e1c383aec17a636b9b35906babc9f0f5475", + "sha256:8e2c35a4c1f269704e90888e56f794e2d9c0262fb0c1b1c8c4ee44d9b9e77b5d", + "sha256:92b8c845527eae547a2a6617d336adc56394050c3ed8a6918683646328fbb6da", + "sha256:9365ed5cce5d0cf2c10afc6add145c5037d3148585b8ae0e77cc1efdd6aa2953", + "sha256:9a29311bd6429be317c1f3fe4bc06c4c5ee45e2fa61b2a19d4d1d6111cb94af2", + "sha256:9a2b5b52be0a8626fcbffd7e689781bf8c2ac01613e77feda93d96184949a98e", + "sha256:a4bdeb0a52d1d04123b41d90a4390b096f3ef38eee35e11f0b22c2d031222c6c", + "sha256:a9c8c4283e17690ff1a7427123ffb428ad6a52ed720d550e299e8291e33184dc", + "sha256:b637c57fdb8be84e91fac60d9325a66a5981f8086c954ea2772efe28425eaf64", + "sha256:bf154ba7ee2fd613eb541c2bc03d3d9ac667080a737449d1a3fb342740eb1a74", + "sha256:c254b03032d5a06de049ce8bca8338a5185f07fb76600afff3c161e053d88617", + "sha256:c332d8f8d448ded473b97fefe4a0983265af21917d8b0cdcb8bb06b2afe632c3", + "sha256:c7912d1526299cb04c88288e148c6c87c0df600eca76efd99d84396cfe00ef1d", + "sha256:cfd9386c1d6f13b37e05a91a8583e802f8059bebfccde61a418c5808dea6bbfa", + "sha256:d5d2033d5db1d58ae2d62f095e1aefb6988af65b4b12cb8987af409587cc0739", + "sha256:dca38a21e4423f3edb821292e97cec7ad38086f84313462098568baedf4331f8", + "sha256:e2cad8093172b7d1595b4ad66f24270808658e11acf43a8f95b41276162eb5b8", + "sha256:e3db840a4dee542e37e09f30859f1612da90e1c5239a6a2498c473183a50e781", + "sha256:edcada2e24ed68f019175c2b2af2a8b481d3d084798b8c20d15d34f5c733fa58", + "sha256:f467bbb837691ab5a8ca359199d3429a11a01e6dfb3d9dcc676dc035ca93c0a9", + "sha256:f506af4f27def639ba45789fa6fde45f9a217da0be05f8910458e4557eed020c", + "sha256:f614fc9956d76d8a88a88bb41ddc12709caa755666f580af3a688899721efecd", + "sha256:f9afb5b746781fc2abce26193d1c817b7eb0e11459510fba65d2bd77fe161d9e", + "sha256:fb8b8ee99b3fffe4fd86f4c81b35a6bf7e4462cba019997af2fe679365db0c49" + ], + "index": "pypi", + "version": "==6.2" + }, + "coveralls": { + "hashes": [ + "sha256:b32a8bb5d2df585207c119d6c01567b81fba690c9c10a753bfe27a335bfc43ea", + "sha256:f42015f31d386b351d4226389b387ae173207058832fbf5c8ec4b40e27b16026" + ], + "index": "pypi", + "version": "==3.3.1" + }, + "docopt": { + "hashes": [ + "sha256:49b3a825280bd66b3aa83585ef59c4a8c82f2c8a522dbe754a8bc8d08c85c491" + ], + "version": "==0.6.2" + }, "flake8": { "hashes": [ "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d", @@ -477,6 +708,14 @@ "index": "pypi", "version": "==4.0.1" }, + "idna": { + "hashes": [ + "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff", + "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d" + ], + "markers": "python_version >= '3'", + "version": "==3.3" + }, "mccabe": { "hashes": [ "sha256:ab8a6258860da4b6677da4bd2fe5dc2c659cff31b3ee4f7f5d64e79735b80d42", @@ -500,6 +739,22 @@ ], "index": "pypi", "version": "==2.4.0" + }, + "requests": { + "hashes": [ + "sha256:68d7c56fd5a8999887728ef304a6d12edc7be74f1cfa47714fc8b414525c9a61", + "sha256:f22fa1e554c9ddfd16e6e41ac79759e17be9e492b3587efa038054674760e72d" + ], + "index": "pypi", + "version": "==2.27.1" + }, + "urllib3": { + "hashes": [ + "sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed", + "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4.0'", + "version": "==1.26.8" } } } diff --git a/README.md b/README.md index d91cb8d7..40aefbdb 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ # Morelia Server - мессенджер (сервер) для Morelia Network # + +![tests](https://github.com/MoreliaTalk/morelia_server/workflows/Test%20and%20Linting/badge.svg) +[![Coverage Status](https://coveralls.io/repos/github/MoreliaTalk/morelia_server/badge.svg?branch=develop-nekrod)](https://coveralls.io/github/MoreliaTalk/morelia_server) + Language [EN](./README_ENG.md), [RU](./README.md) ## В репозитории 2 бранча ## diff --git a/README_ENG.md b/README_ENG.md index cc5fa842..890e69f2 100644 --- a/README_ENG.md +++ b/README_ENG.md @@ -1,5 +1,8 @@ # Morelia Server - messenger server for Morelia Network # +![tests](https://github.com/MoreliaTalk/morelia_server/workflows/Test%20and%20Linting/badge.svg) +[![Coverage Status](https://coveralls.io/repos/github/MoreliaTalk/morelia_server/badge.svg?branch=develop-nekrod)](https://coveralls.io/github/MoreliaTalk/morelia_server) + Language [EN](./README_ENG.md), [RU](./README.md) ## There are two brunches in repository ## @@ -57,8 +60,6 @@ Language [EN](./README_ENG.md), [RU](./README.md) * example_config.ini - file containing example server settings, just rename it to `config.ini` before running the server. * client.py - mini-customer to test the server. -Translated with www.DeepL.com/Translator (free version) - ## Installing ## Install [Python](https://www.python.org/downloads/) version 3.8 or higher. diff --git a/admin/admin.py b/admin/admin.py index a57477b2..a35ad82e 100644 --- a/admin/admin.py +++ b/admin/admin.py @@ -26,7 +26,7 @@ from starlette.responses import RedirectResponse from mod.db.dbhandler import DBHandler -from mod.config import DATABASE +from config import DATABASE from . import login from . import logs from . import control as manage @@ -45,11 +45,32 @@ @app.exception_handler(login.NotAuthenticatedException) def not_login_exception_handler(request: Request, exc: login.NotAuthenticatedException): + """ + Catches exception login.NotAuthenticatedException and redirects the user to the login page("/admin/login/") + + Args: + request(Request): request to the server + exc(login.NotAuthenticatedException): catchable user authentication error + + Returns: + (RedirectResponse): redirect response to /admin/login + """ return RedirectResponse(url="/admin/login") @app.get("/login") def login_admin(request: Request): + """ + The function is triggered when a request is received for the /login address + and returns a response generated from login.html + + Args: + request(Request): request to the server + + Returns: + (templates.TemplateResponse): response generated from login.html template + + """ return templates.TemplateResponse("login.html", { "request": request }) @@ -58,6 +79,16 @@ def login_admin(request: Request): @app.get("/") def index_admin(request: Request, user=Depends(login.login_manager)): + """ + Returns a response with the main page of the admin panel + + Args: + request(Request): request to the server + user: user authentication check + + Returns: + (templates.TemplateResponse): response generated from index_admin.html template + """ return templates.TemplateResponse("index_admin.html", { "request": request }) @@ -66,6 +97,16 @@ def index_admin(request: Request, @app.get("/status") def status_admin(request: Request, user=Depends(login.login_manager)): + """ + Returns a response with the status page of the admin panel + + Args: + request(Request): request to the server + user: user authentication check + + Returns: + (templates.TemplateResponse): response generated from status_admin.html template + """ dbquery = db_connect.get_table_count() return templates.TemplateResponse("status_admin.html", {"request": request, @@ -80,6 +121,16 @@ def status_admin(request: Request, @app.get("/manage") def manage_admin(request: Request, user=Depends(login.login_manager)): + """ + Returns a response with the mange page of the admin panel + + Args: + request(Request): request to the server + user: user authentication check + + Returns: + (templates.TemplateResponse): response generated from manage_admin.html template + """ dbquery = db_connect.get_all_user() return templates.TemplateResponse("manage_admin.html", { "request": request, @@ -90,6 +141,16 @@ def manage_admin(request: Request, @app.get("/logs") def manage_logs(request: Request, user=Depends(login.login_manager)): + """ + Returns a response with the logs view page of the admin panel + + Args: + request(Request): request to the server + user: user authentication check + + Returns: + (templates.TemplateResponse): response generated from logs_admin.html template + """ return templates.TemplateResponse("logs_admin.html", { "request": request }) diff --git a/admin/control.py b/admin/control.py index 93159095..9e74baf4 100644 --- a/admin/control.py +++ b/admin/control.py @@ -26,7 +26,7 @@ from starlette.responses import HTMLResponse from mod.db.dbhandler import DBHandler -from mod.config import DATABASE +from config import DATABASE router = APIRouter() @@ -37,6 +37,17 @@ @router.post("/manage/delete_user") def delete_user(request: Request, uuid: str = Form(...)): + """ + The function receives the request and admin uuid, delete admin user, + and returns a response, redirecting to the main page of the admin panel + + Args: + request(Request): request for server + uuid(str): uuid admin user + + Returns: + (HTMLResponse): response redirecting to the main admin page + """ fake_uuid = str(uuid4().int) db_connect.update_user(uuid=uuid, diff --git a/admin/login.py b/admin/login.py index 473ef7f5..441cd8df 100644 --- a/admin/login.py +++ b/admin/login.py @@ -27,8 +27,8 @@ from mod import lib from mod.db.dbhandler import DBHandler -from mod.config import DATABASE -from mod.config import ADMIN +from config import DATABASE +from config import ADMIN db_connect = DBHandler(DATABASE.get('URI')) @@ -37,6 +37,9 @@ class NotAuthenticatedException(Exception): + """ + An exception occurs when the user's authorization data is missing or incorrect + """ pass @@ -50,6 +53,15 @@ class NotAuthenticatedException(Exception): @login_manager.user_loader() def get_admin_user_data(username: str): + """ + The function of requesting data from the database and checking it against the username, if there is valid data, it returns it + + Args: + username(str): username admin user + + Returns: + (SQLObject) - admin user data from db + """ data = db_connect.get_admin_by_name(username=username) if data.count(): return data[0] @@ -57,6 +69,18 @@ def get_admin_user_data(username: str): @router.post("/login/token") def login_token(data: OAuth2PasswordRequestForm = Depends()): + """ + The function receives the data + and returns a response that contains the admin token for the user, + valid for 15 minutes + + Args: + data(OAuth2PasswordRequestForm): login data + + Returns: + (HTMLResponse): response with cookies embedded in it + """ + admin_user_data_db = get_admin_user_data(data.username) if not admin_user_data_db: return HTMLResponse("""