├── .deepsource.toml ├── .dockerignore ├── .gitignore ├── COPYING ├── Dockerfile ├── README.md ├── cli.py ├── config_example.yaml ├── docker-compose.yml ├── poetry.lock ├── pyproject.toml ├── requirements.txt └── service1 ├── __init__.py ├── helpers └── helpers.py ├── main.py ├── models ├── __init__.py ├── auth.py └── common.py ├── routes ├── __init__.py ├── auth.py └── main.py └── service ├── __init__.py ├── mail.py └── user.py /.deepsource.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | test_patterns = ["**.py"] 4 | 5 | [[analyzers]] 6 | name = "python" 7 | enabled = true 8 | 9 | [analyzers.meta] 10 | runtime_version = "3.x.x" 11 | type_checker = "mypy" 12 | 13 | [[transformers]] 14 | name = "autopep8" 15 | enabled = true 16 | 17 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | __pycache__/ -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | config.yaml 3 | *.log 4 | .vscode 5 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 2 | Version 2, December 2004 3 | 4 | Copyright (C) 2004 Sam Hocevar 5 | 6 | Everyone is permitted to copy and distribute verbatim or modified 7 | copies of this license document, and changing it is allowed as long 8 | as the name is changed. 9 | 10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE 11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 12 | 13 | 0. You just DO WHAT THE FUCK YOU WANT TO. 14 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.9 2 | 3 | RUN useradd -m jimbo 4 | 5 | # set the working directory in the container 6 | WORKDIR /home/jimbo 7 | 8 | # copy the dependencies file to the working directory 9 | COPY requirements.txt . 10 | 11 | # install dependencies 12 | RUN pip install -r requirements.txt 13 | 14 | # copy the content of the local src directory to the working directory 15 | COPY ./service1 ./service1 16 | 17 | RUN chown -R jimbo:jimbo ./ 18 | 19 | USER jimbo 20 | 21 | EXPOSE 3000 22 | 23 | CMD python3.9 -m uvicorn service1:app --port 3000 --host 0.0.0.0 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # python_jwt_example_fastapi 2 | This was a part of a microservice architecture from my private project. Feel free to use it :) 3 | -------------------------------------------------------------------------------- /cli.py: -------------------------------------------------------------------------------- 1 | import time 2 | import uuid 3 | 4 | import pymongo 5 | import yaml 6 | from loguru import logger 7 | 8 | from service1.helpers.helpers import hash_password, load_model 9 | from service1.models.auth import UserModel 10 | 11 | config = yaml.safe_load(open("config.yaml")) 12 | 13 | logger.info("Service1 CLI-TOOL ") 14 | logger.info("Please choose:") 15 | logger.info("1 - Add Admin") 16 | logger.info("2 - Add User") 17 | logger.info("3 - Show all Users") 18 | action = int(input("Action: ")) 19 | 20 | pym = pymongo.MongoClient(config["core"]["mongodb_url"]) 21 | db = pym[config["core"]["mongodb_db"]] 22 | 23 | if action == 1: 24 | name = input("Name: ") 25 | email = input("E-Mail: ") 26 | password = hash_password(input("Password: ")) 27 | token = uuid.uuid4().hex 28 | reg_time = time.time() 29 | user = UserModel( 30 | name=name, 31 | email=email, 32 | password=password, 33 | level=3, 34 | token=token, 35 | reg_time=reg_time, 36 | ) 37 | 38 | db.users.insert_one(user.dict()) 39 | logger.info(f"Your token: {token}") # for debug 40 | logger.info("Finished.") 41 | 42 | elif action == 2: 43 | name = input("Name: ") 44 | email = input("E-Mail: ") 45 | password = hash_password(input("Password: ")) 46 | token = uuid.uuid4().hex 47 | reg_time = time.time() 48 | user = UserModel( 49 | name=name, 50 | email=email, 51 | password=password, 52 | level=2, 53 | token=token, 54 | reg_time=reg_time, 55 | ) 56 | 57 | db.users.insert_one(user.dict()) 58 | logger.info(f"Your token: {token}") 59 | logger.info("Finished.") 60 | 61 | elif action == 3: 62 | users = db.users.find() 63 | 64 | for user in users: 65 | user = load_model(UserModel, user) 66 | logger.info(" --- name: " + user.name) 67 | logger.info(" - email: " + user.email) 68 | logger.info(" - level: " + str(user.level)) 69 | logger.info(" - registration date: " + str(user.reg_time)) 70 | logger.info(" - token: " + user.token) 71 | -------------------------------------------------------------------------------- /config_example.yaml: -------------------------------------------------------------------------------- 1 | core: 2 | mongodb_db: "users" 3 | mongodb_url: "mongodb://user:password@yourip:27017/" 4 | jwt: 5 | algorithm: "HS256" 6 | expire: 30 7 | secret: "SECRET" 8 | email: 9 | smtp: "mail.example.com" 10 | port: 465 11 | username: "system@example.com" 12 | password: "password123" -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3.3' 2 | networks: 3 | web: 4 | external: true 5 | services: 6 | backend: 7 | image: service1-backend:latest 8 | container_name: service1-backend 9 | volumes: 10 | - ./:/home/jimbo 11 | # extra_hosts: 12 | # - "host.docker.internal:172.17.0.1" # for non-docker MongoDB, change ip in /etc/mongo/mongod.conf too 13 | networks: 14 | - web 15 | labels: 16 | - traefik.enable=true 17 | - traefik.backend=service1-backend 18 | - traefik.docker.network=web 19 | - traefik.http.middlewares.backend-compress.compress=true 20 | - traefik.http.routers.backend.middlewares=landing-compress,stripheader 21 | - traefik.http.services.service1-backend.loadbalancer.server.port=3000 22 | - "traefik.http.routers.service1-backend-secure.rule=Host(`YOURDOMAIN`)" 23 | - "traefik.http.routers.service1-backend-secure.tls=true" 24 | - "traefik.http.routers.service1-backend-secure.tls.certresolver=lets-encrypt" 25 | - "traefik.http.routers.service1-backend-secure.service=service1-backend" 26 | - traefik.port=3000 27 | -------------------------------------------------------------------------------- /poetry.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "asgiref" 3 | version = "3.4.1" 4 | description = "ASGI specs, helper code, and adapters" 5 | category = "main" 6 | optional = false 7 | python-versions = ">=3.6" 8 | 9 | [package.extras] 10 | tests = ["pytest", "pytest-asyncio", "mypy (>=0.800)"] 11 | 12 | [[package]] 13 | name = "bcrypt" 14 | version = "3.2.0" 15 | description = "Modern password hashing for your software and your servers" 16 | category = "main" 17 | optional = false 18 | python-versions = ">=3.6" 19 | 20 | [package.dependencies] 21 | cffi = ">=1.1" 22 | six = ">=1.4.1" 23 | 24 | [package.extras] 25 | tests = ["pytest (>=3.2.1,!=3.3.0)"] 26 | typecheck = ["mypy"] 27 | 28 | [[package]] 29 | name = "cffi" 30 | version = "1.14.6" 31 | description = "Foreign Function Interface for Python calling C code." 32 | category = "main" 33 | optional = false 34 | python-versions = "*" 35 | 36 | [package.dependencies] 37 | pycparser = "*" 38 | 39 | [[package]] 40 | name = "click" 41 | version = "8.0.1" 42 | description = "Composable command line interface toolkit" 43 | category = "main" 44 | optional = false 45 | python-versions = ">=3.6" 46 | 47 | [package.dependencies] 48 | colorama = {version = "*", markers = "platform_system == \"Windows\""} 49 | 50 | [[package]] 51 | name = "colorama" 52 | version = "0.4.4" 53 | description = "Cross-platform colored terminal text." 54 | category = "main" 55 | optional = false 56 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" 57 | 58 | [[package]] 59 | name = "cryptography" 60 | version = "3.4.8" 61 | description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." 62 | category = "main" 63 | optional = false 64 | python-versions = ">=3.6" 65 | 66 | [package.dependencies] 67 | cffi = ">=1.12" 68 | 69 | [package.extras] 70 | docs = ["sphinx (>=1.6.5,!=1.8.0,!=3.1.0,!=3.1.1)", "sphinx-rtd-theme"] 71 | docstest = ["doc8", "pyenchant (>=1.6.11)", "twine (>=1.12.0)", "sphinxcontrib-spelling (>=4.0.1)"] 72 | pep8test = ["black", "flake8", "flake8-import-order", "pep8-naming"] 73 | sdist = ["setuptools-rust (>=0.11.4)"] 74 | ssh = ["bcrypt (>=3.1.5)"] 75 | test = ["pytest (>=6.0)", "pytest-cov", "pytest-subtests", "pytest-xdist", "pretend", "iso8601", "pytz", "hypothesis (>=1.11.4,!=3.79.2)"] 76 | 77 | [[package]] 78 | name = "dnspython" 79 | version = "2.1.0" 80 | description = "DNS toolkit" 81 | category = "main" 82 | optional = false 83 | python-versions = ">=3.6" 84 | 85 | [package.extras] 86 | dnssec = ["cryptography (>=2.6)"] 87 | doh = ["requests", "requests-toolbelt"] 88 | idna = ["idna (>=2.1)"] 89 | curio = ["curio (>=1.2)", "sniffio (>=1.1)"] 90 | trio = ["trio (>=0.14.0)", "sniffio (>=1.1)"] 91 | 92 | [[package]] 93 | name = "ecdsa" 94 | version = "0.17.0" 95 | description = "ECDSA cryptographic signature library (pure python)" 96 | category = "main" 97 | optional = false 98 | python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" 99 | 100 | [package.dependencies] 101 | six = ">=1.9.0" 102 | 103 | [package.extras] 104 | gmpy = ["gmpy"] 105 | gmpy2 = ["gmpy2"] 106 | 107 | [[package]] 108 | name = "fastapi" 109 | version = "0.68.1" 110 | description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" 111 | category = "main" 112 | optional = false 113 | python-versions = ">=3.6" 114 | 115 | [package.dependencies] 116 | pydantic = ">=1.6.2,<1.7 || >1.7,<1.7.1 || >1.7.1,<1.7.2 || >1.7.2,<1.7.3 || >1.7.3,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0" 117 | starlette = "0.14.2" 118 | 119 | [package.extras] 120 | all = ["requests (>=2.24.0,<3.0.0)", "aiofiles (>=0.5.0,<0.6.0)", "jinja2 (>=2.11.2,<3.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "itsdangerous (>=1.1.0,<2.0.0)", "pyyaml (>=5.3.1,<6.0.0)", "graphene (>=2.1.8,<3.0.0)", "ujson (>=4.0.1,<5.0.0)", "orjson (>=3.2.1,<4.0.0)", "email_validator (>=1.1.1,<2.0.0)", "uvicorn[standard] (>=0.12.0,<0.14.0)", "async_exit_stack (>=1.0.1,<2.0.0)", "async_generator (>=1.10,<2.0.0)"] 121 | dev = ["python-jose[cryptography] (>=3.3.0,<4.0.0)", "passlib[bcrypt] (>=1.7.2,<2.0.0)", "autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "uvicorn[standard] (>=0.12.0,<0.14.0)", "graphene (>=2.1.8,<3.0.0)"] 122 | doc = ["mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=7.1.9,<8.0.0)", "mdx-include (>=1.4.1,<2.0.0)", "mkdocs-markdownextradata-plugin (>=0.1.7,<0.2.0)", "typer-cli (>=0.0.12,<0.0.13)", "pyyaml (>=5.3.1,<6.0.0)"] 123 | test = ["pytest (>=6.2.4,<7.0.0)", "pytest-cov (>=2.12.0,<3.0.0)", "pytest-asyncio (>=0.14.0,<0.15.0)", "mypy (==0.812)", "flake8 (>=3.8.3,<4.0.0)", "black (==20.8b1)", "isort (>=5.0.6,<6.0.0)", "requests (>=2.24.0,<3.0.0)", "httpx (>=0.14.0,<0.15.0)", "email_validator (>=1.1.1,<2.0.0)", "sqlalchemy (>=1.3.18,<1.4.0)", "peewee (>=3.13.3,<4.0.0)", "databases[sqlite] (>=0.3.2,<0.4.0)", "orjson (>=3.2.1,<4.0.0)", "ujson (>=4.0.1,<5.0.0)", "async_exit_stack (>=1.0.1,<2.0.0)", "async_generator (>=1.10,<2.0.0)", "python-multipart (>=0.0.5,<0.0.6)", "aiofiles (>=0.5.0,<0.6.0)", "flask (>=1.1.2,<2.0.0)"] 124 | 125 | [[package]] 126 | name = "h11" 127 | version = "0.12.0" 128 | description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" 129 | category = "main" 130 | optional = false 131 | python-versions = ">=3.6" 132 | 133 | [[package]] 134 | name = "loguru" 135 | version = "0.5.3" 136 | description = "Python logging made (stupidly) simple" 137 | category = "main" 138 | optional = false 139 | python-versions = ">=3.5" 140 | 141 | [package.dependencies] 142 | colorama = {version = ">=0.3.4", markers = "sys_platform == \"win32\""} 143 | win32-setctime = {version = ">=1.0.0", markers = "sys_platform == \"win32\""} 144 | 145 | [package.extras] 146 | dev = ["codecov (>=2.0.15)", "colorama (>=0.3.4)", "flake8 (>=3.7.7)", "tox (>=3.9.0)", "tox-travis (>=0.12)", "pytest (>=4.6.2)", "pytest-cov (>=2.7.1)", "Sphinx (>=2.2.1)", "sphinx-autobuild (>=0.7.1)", "sphinx-rtd-theme (>=0.4.3)", "black (>=19.10b0)", "isort (>=5.1.1)"] 147 | 148 | [[package]] 149 | name = "motor" 150 | version = "2.5.1" 151 | description = "Non-blocking MongoDB driver for Tornado or asyncio" 152 | category = "main" 153 | optional = false 154 | python-versions = ">=3.5.2" 155 | 156 | [package.dependencies] 157 | pymongo = ">=3.12,<4" 158 | 159 | [package.extras] 160 | encryption = ["pymongo[encryption] (>=3.12,<4)"] 161 | 162 | [[package]] 163 | name = "passlib" 164 | version = "1.7.4" 165 | description = "comprehensive password hashing framework supporting over 30 schemes" 166 | category = "main" 167 | optional = false 168 | python-versions = "*" 169 | 170 | [package.dependencies] 171 | bcrypt = {version = ">=3.1.0", optional = true, markers = "extra == \"bcrypt\""} 172 | 173 | [package.extras] 174 | argon2 = ["argon2-cffi (>=18.2.0)"] 175 | bcrypt = ["bcrypt (>=3.1.0)"] 176 | build_docs = ["sphinx (>=1.6)", "sphinxcontrib-fulltoc (>=1.2.0)", "cloud-sptheme (>=1.10.1)"] 177 | totp = ["cryptography"] 178 | 179 | [[package]] 180 | name = "pyasn1" 181 | version = "0.4.8" 182 | description = "ASN.1 types and codecs" 183 | category = "main" 184 | optional = false 185 | python-versions = "*" 186 | 187 | [[package]] 188 | name = "pycparser" 189 | version = "2.20" 190 | description = "C parser in Python" 191 | category = "main" 192 | optional = false 193 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" 194 | 195 | [[package]] 196 | name = "pydantic" 197 | version = "1.8.2" 198 | description = "Data validation and settings management using python 3.6 type hinting" 199 | category = "main" 200 | optional = false 201 | python-versions = ">=3.6.1" 202 | 203 | [package.dependencies] 204 | typing-extensions = ">=3.7.4.3" 205 | 206 | [package.extras] 207 | dotenv = ["python-dotenv (>=0.10.4)"] 208 | email = ["email-validator (>=1.0.3)"] 209 | 210 | [[package]] 211 | name = "pymongo" 212 | version = "3.12.0" 213 | description = "Python driver for MongoDB " 214 | category = "main" 215 | optional = false 216 | python-versions = "*" 217 | 218 | [package.extras] 219 | aws = ["pymongo-auth-aws (<2.0.0)"] 220 | encryption = ["pymongocrypt (>=1.1.0,<2.0.0)"] 221 | gssapi = ["pykerberos"] 222 | ocsp = ["pyopenssl (>=17.2.0)", "requests (<3.0.0)", "service-identity (>=18.1.0)", "certifi"] 223 | snappy = ["python-snappy"] 224 | srv = ["dnspython (>=1.16.0,<1.17.0)"] 225 | tls = ["ipaddress"] 226 | zstd = ["zstandard"] 227 | 228 | [[package]] 229 | name = "python-jose" 230 | version = "3.3.0" 231 | description = "JOSE implementation in Python" 232 | category = "main" 233 | optional = false 234 | python-versions = "*" 235 | 236 | [package.dependencies] 237 | cryptography = {version = ">=3.4.0", optional = true, markers = "extra == \"cryptography\""} 238 | ecdsa = "!=0.15" 239 | pyasn1 = "*" 240 | rsa = "*" 241 | 242 | [package.extras] 243 | cryptography = ["cryptography (>=3.4.0)"] 244 | pycrypto = ["pycrypto (>=2.6.0,<2.7.0)", "pyasn1"] 245 | pycryptodome = ["pycryptodome (>=3.3.1,<4.0.0)", "pyasn1"] 246 | 247 | [[package]] 248 | name = "pyyaml" 249 | version = "5.4.1" 250 | description = "YAML parser and emitter for Python" 251 | category = "main" 252 | optional = false 253 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" 254 | 255 | [[package]] 256 | name = "rsa" 257 | version = "4.7.2" 258 | description = "Pure-Python RSA implementation" 259 | category = "main" 260 | optional = false 261 | python-versions = ">=3.5, <4" 262 | 263 | [package.dependencies] 264 | pyasn1 = ">=0.1.3" 265 | 266 | [[package]] 267 | name = "six" 268 | version = "1.16.0" 269 | description = "Python 2 and 3 compatibility utilities" 270 | category = "main" 271 | optional = false 272 | python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" 273 | 274 | [[package]] 275 | name = "starlette" 276 | version = "0.14.2" 277 | description = "The little ASGI library that shines." 278 | category = "main" 279 | optional = false 280 | python-versions = ">=3.6" 281 | 282 | [package.extras] 283 | full = ["aiofiles", "graphene", "itsdangerous", "jinja2", "python-multipart", "pyyaml", "requests"] 284 | 285 | [[package]] 286 | name = "typing-extensions" 287 | version = "3.10.0.0" 288 | description = "Backported and Experimental Type Hints for Python 3.5+" 289 | category = "main" 290 | optional = false 291 | python-versions = "*" 292 | 293 | [[package]] 294 | name = "uvicorn" 295 | version = "0.15.0" 296 | description = "The lightning-fast ASGI server." 297 | category = "main" 298 | optional = false 299 | python-versions = "*" 300 | 301 | [package.dependencies] 302 | asgiref = ">=3.4.0" 303 | click = ">=7.0" 304 | h11 = ">=0.8" 305 | 306 | [package.extras] 307 | standard = ["websockets (>=9.1)", "httptools (>=0.2.0,<0.3.0)", "watchgod (>=0.6)", "python-dotenv (>=0.13)", "PyYAML (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "colorama (>=0.4)"] 308 | 309 | [[package]] 310 | name = "win32-setctime" 311 | version = "1.0.3" 312 | description = "A small Python utility to set file creation time on Windows" 313 | category = "main" 314 | optional = false 315 | python-versions = ">=3.5" 316 | 317 | [package.extras] 318 | dev = ["pytest (>=4.6.2)", "black (>=19.3b0)"] 319 | 320 | [metadata] 321 | lock-version = "1.1" 322 | python-versions = "^3.9" 323 | content-hash = "8001ff7b5afbeb37e38a77dfd30c6c69b0ab83b075db6d78fc794ed56d0d9feb" 324 | 325 | [metadata.files] 326 | asgiref = [ 327 | {file = "asgiref-3.4.1-py3-none-any.whl", hash = "sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214"}, 328 | {file = "asgiref-3.4.1.tar.gz", hash = "sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9"}, 329 | ] 330 | bcrypt = [ 331 | {file = "bcrypt-3.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6"}, 332 | {file = "bcrypt-3.2.0-cp36-abi3-manylinux1_x86_64.whl", hash = "sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7"}, 333 | {file = "bcrypt-3.2.0-cp36-abi3-manylinux2010_x86_64.whl", hash = "sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1"}, 334 | {file = "bcrypt-3.2.0-cp36-abi3-manylinux2014_aarch64.whl", hash = "sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d"}, 335 | {file = "bcrypt-3.2.0-cp36-abi3-win32.whl", hash = "sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55"}, 336 | {file = "bcrypt-3.2.0-cp36-abi3-win_amd64.whl", hash = "sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34"}, 337 | {file = "bcrypt-3.2.0.tar.gz", hash = "sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29"}, 338 | ] 339 | cffi = [ 340 | {file = "cffi-1.14.6-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:22b9c3c320171c108e903d61a3723b51e37aaa8c81255b5e7ce102775bd01e2c"}, 341 | {file = "cffi-1.14.6-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:f0c5d1acbfca6ebdd6b1e3eded8d261affb6ddcf2186205518f1428b8569bb99"}, 342 | {file = "cffi-1.14.6-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:99f27fefe34c37ba9875f224a8f36e31d744d8083e00f520f133cab79ad5e819"}, 343 | {file = "cffi-1.14.6-cp27-cp27m-win32.whl", hash = "sha256:55af55e32ae468e9946f741a5d51f9896da6b9bf0bbdd326843fec05c730eb20"}, 344 | {file = "cffi-1.14.6-cp27-cp27m-win_amd64.whl", hash = "sha256:7bcac9a2b4fdbed2c16fa5681356d7121ecabf041f18d97ed5b8e0dd38a80224"}, 345 | {file = "cffi-1.14.6-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:ed38b924ce794e505647f7c331b22a693bee1538fdf46b0222c4717b42f744e7"}, 346 | {file = "cffi-1.14.6-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:e22dcb48709fc51a7b58a927391b23ab37eb3737a98ac4338e2448bef8559b33"}, 347 | {file = "cffi-1.14.6-cp35-cp35m-macosx_10_9_x86_64.whl", hash = "sha256:aedb15f0a5a5949ecb129a82b72b19df97bbbca024081ed2ef88bd5c0a610534"}, 348 | {file = "cffi-1.14.6-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:48916e459c54c4a70e52745639f1db524542140433599e13911b2f329834276a"}, 349 | {file = "cffi-1.14.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:f627688813d0a4140153ff532537fbe4afea5a3dffce1f9deb7f91f848a832b5"}, 350 | {file = "cffi-1.14.6-cp35-cp35m-win32.whl", hash = "sha256:f0010c6f9d1a4011e429109fda55a225921e3206e7f62a0c22a35344bfd13cca"}, 351 | {file = "cffi-1.14.6-cp35-cp35m-win_amd64.whl", hash = "sha256:57e555a9feb4a8460415f1aac331a2dc833b1115284f7ded7278b54afc5bd218"}, 352 | {file = "cffi-1.14.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:e8c6a99be100371dbb046880e7a282152aa5d6127ae01783e37662ef73850d8f"}, 353 | {file = "cffi-1.14.6-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:19ca0dbdeda3b2615421d54bef8985f72af6e0c47082a8d26122adac81a95872"}, 354 | {file = "cffi-1.14.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:d950695ae4381ecd856bcaf2b1e866720e4ab9a1498cba61c602e56630ca7195"}, 355 | {file = "cffi-1.14.6-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e9dc245e3ac69c92ee4c167fbdd7428ec1956d4e754223124991ef29eb57a09d"}, 356 | {file = "cffi-1.14.6-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a8661b2ce9694ca01c529bfa204dbb144b275a31685a075ce123f12331be790b"}, 357 | {file = "cffi-1.14.6-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b315d709717a99f4b27b59b021e6207c64620790ca3e0bde636a6c7f14618abb"}, 358 | {file = "cffi-1.14.6-cp36-cp36m-win32.whl", hash = "sha256:80b06212075346b5546b0417b9f2bf467fea3bfe7352f781ffc05a8ab24ba14a"}, 359 | {file = "cffi-1.14.6-cp36-cp36m-win_amd64.whl", hash = "sha256:a9da7010cec5a12193d1af9872a00888f396aba3dc79186604a09ea3ee7c029e"}, 360 | {file = "cffi-1.14.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4373612d59c404baeb7cbd788a18b2b2a8331abcc84c3ba40051fcd18b17a4d5"}, 361 | {file = "cffi-1.14.6-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:f10afb1004f102c7868ebfe91c28f4a712227fe4cb24974350ace1f90e1febbf"}, 362 | {file = "cffi-1.14.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:fd4305f86f53dfd8cd3522269ed7fc34856a8ee3709a5e28b2836b2db9d4cd69"}, 363 | {file = "cffi-1.14.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d6169cb3c6c2ad50db5b868db6491a790300ade1ed5d1da29289d73bbe40b56"}, 364 | {file = "cffi-1.14.6-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5d4b68e216fc65e9fe4f524c177b54964af043dde734807586cf5435af84045c"}, 365 | {file = "cffi-1.14.6-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:33791e8a2dc2953f28b8d8d300dde42dd929ac28f974c4b4c6272cb2955cb762"}, 366 | {file = "cffi-1.14.6-cp37-cp37m-win32.whl", hash = "sha256:0c0591bee64e438883b0c92a7bed78f6290d40bf02e54c5bf0978eaf36061771"}, 367 | {file = "cffi-1.14.6-cp37-cp37m-win_amd64.whl", hash = "sha256:8eb687582ed7cd8c4bdbff3df6c0da443eb89c3c72e6e5dcdd9c81729712791a"}, 368 | {file = "cffi-1.14.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba6f2b3f452e150945d58f4badd92310449876c4c954836cfb1803bdd7b422f0"}, 369 | {file = "cffi-1.14.6-cp38-cp38-manylinux1_i686.whl", hash = "sha256:64fda793737bc4037521d4899be780534b9aea552eb673b9833b01f945904c2e"}, 370 | {file = "cffi-1.14.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:9f3e33c28cd39d1b655ed1ba7247133b6f7fc16fa16887b120c0c670e35ce346"}, 371 | {file = "cffi-1.14.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26bb2549b72708c833f5abe62b756176022a7b9a7f689b571e74c8478ead51dc"}, 372 | {file = "cffi-1.14.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb687a11f0a7a1839719edd80f41e459cc5366857ecbed383ff376c4e3cc6afd"}, 373 | {file = "cffi-1.14.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d2ad4d668a5c0645d281dcd17aff2be3212bc109b33814bbb15c4939f44181cc"}, 374 | {file = "cffi-1.14.6-cp38-cp38-win32.whl", hash = "sha256:487d63e1454627c8e47dd230025780e91869cfba4c753a74fda196a1f6ad6548"}, 375 | {file = "cffi-1.14.6-cp38-cp38-win_amd64.whl", hash = "sha256:c33d18eb6e6bc36f09d793c0dc58b0211fccc6ae5149b808da4a62660678b156"}, 376 | {file = "cffi-1.14.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:06c54a68935738d206570b20da5ef2b6b6d92b38ef3ec45c5422c0ebaf338d4d"}, 377 | {file = "cffi-1.14.6-cp39-cp39-manylinux1_i686.whl", hash = "sha256:f174135f5609428cc6e1b9090f9268f5c8935fddb1b25ccb8255a2d50de6789e"}, 378 | {file = "cffi-1.14.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:f3ebe6e73c319340830a9b2825d32eb6d8475c1dac020b4f0aa774ee3b898d1c"}, 379 | {file = "cffi-1.14.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c8d896becff2fa653dc4438b54a5a25a971d1f4110b32bd3068db3722c80202"}, 380 | {file = "cffi-1.14.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4922cd707b25e623b902c86188aca466d3620892db76c0bdd7b99a3d5e61d35f"}, 381 | {file = "cffi-1.14.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c9e005e9bd57bc987764c32a1bee4364c44fdc11a3cc20a40b93b444984f2b87"}, 382 | {file = "cffi-1.14.6-cp39-cp39-win32.whl", hash = "sha256:eb9e2a346c5238a30a746893f23a9535e700f8192a68c07c0258e7ece6ff3728"}, 383 | {file = "cffi-1.14.6-cp39-cp39-win_amd64.whl", hash = "sha256:818014c754cd3dba7229c0f5884396264d51ffb87ec86e927ef0be140bfdb0d2"}, 384 | {file = "cffi-1.14.6.tar.gz", hash = "sha256:c9a875ce9d7fe32887784274dd533c57909b7b1dcadcc128a2ac21331a9765dd"}, 385 | ] 386 | click = [ 387 | {file = "click-8.0.1-py3-none-any.whl", hash = "sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6"}, 388 | {file = "click-8.0.1.tar.gz", hash = "sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a"}, 389 | ] 390 | colorama = [ 391 | {file = "colorama-0.4.4-py2.py3-none-any.whl", hash = "sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2"}, 392 | {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, 393 | ] 394 | cryptography = [ 395 | {file = "cryptography-3.4.8-cp36-abi3-macosx_10_10_x86_64.whl", hash = "sha256:a00cf305f07b26c351d8d4e1af84ad7501eca8a342dedf24a7acb0e7b7406e14"}, 396 | {file = "cryptography-3.4.8-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:f44d141b8c4ea5eb4dbc9b3ad992d45580c1d22bf5e24363f2fbf50c2d7ae8a7"}, 397 | {file = "cryptography-3.4.8-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:0a7dcbcd3f1913f664aca35d47c1331fce738d44ec34b7be8b9d332151b0b01e"}, 398 | {file = "cryptography-3.4.8-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:34dae04a0dce5730d8eb7894eab617d8a70d0c97da76b905de9efb7128ad7085"}, 399 | {file = "cryptography-3.4.8-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1eb7bb0df6f6f583dd8e054689def236255161ebbcf62b226454ab9ec663746b"}, 400 | {file = "cryptography-3.4.8-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:9965c46c674ba8cc572bc09a03f4c649292ee73e1b683adb1ce81e82e9a6a0fb"}, 401 | {file = "cryptography-3.4.8-cp36-abi3-win32.whl", hash = "sha256:21ca464b3a4b8d8e86ba0ee5045e103a1fcfac3b39319727bc0fc58c09c6aff7"}, 402 | {file = "cryptography-3.4.8-cp36-abi3-win_amd64.whl", hash = "sha256:3520667fda779eb788ea00080124875be18f2d8f0848ec00733c0ec3bb8219fc"}, 403 | {file = "cryptography-3.4.8-pp36-pypy36_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:d2a6e5ef66503da51d2110edf6c403dc6b494cc0082f85db12f54e9c5d4c3ec5"}, 404 | {file = "cryptography-3.4.8-pp36-pypy36_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a305600e7a6b7b855cd798e00278161b681ad6e9b7eca94c721d5f588ab212af"}, 405 | {file = "cryptography-3.4.8-pp36-pypy36_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:3fa3a7ccf96e826affdf1a0a9432be74dc73423125c8f96a909e3835a5ef194a"}, 406 | {file = "cryptography-3.4.8-pp37-pypy37_pp73-macosx_10_10_x86_64.whl", hash = "sha256:d9ec0e67a14f9d1d48dd87a2531009a9b251c02ea42851c060b25c782516ff06"}, 407 | {file = "cryptography-3.4.8-pp37-pypy37_pp73-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5b0fbfae7ff7febdb74b574055c7466da334a5371f253732d7e2e7525d570498"}, 408 | {file = "cryptography-3.4.8-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94fff993ee9bc1b2440d3b7243d488c6a3d9724cc2b09cdb297f6a886d040ef7"}, 409 | {file = "cryptography-3.4.8-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:8695456444f277af73a4877db9fc979849cd3ee74c198d04fc0776ebc3db52b9"}, 410 | {file = "cryptography-3.4.8-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:cd65b60cfe004790c795cc35f272e41a3df4631e2fb6b35aa7ac6ef2859d554e"}, 411 | {file = "cryptography-3.4.8.tar.gz", hash = "sha256:94cc5ed4ceaefcbe5bf38c8fba6a21fc1d365bb8fb826ea1688e3370b2e24a1c"}, 412 | ] 413 | dnspython = [ 414 | {file = "dnspython-2.1.0-py3-none-any.whl", hash = "sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216"}, 415 | {file = "dnspython-2.1.0.zip", hash = "sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4"}, 416 | ] 417 | ecdsa = [ 418 | {file = "ecdsa-0.17.0-py2.py3-none-any.whl", hash = "sha256:5cf31d5b33743abe0dfc28999036c849a69d548f994b535e527ee3cb7f3ef676"}, 419 | {file = "ecdsa-0.17.0.tar.gz", hash = "sha256:b9f500bb439e4153d0330610f5d26baaf18d17b8ced1bc54410d189385ea68aa"}, 420 | ] 421 | fastapi = [ 422 | {file = "fastapi-0.68.1-py3-none-any.whl", hash = "sha256:94d2820906c36b9b8303796fb7271337ec89c74223229e3cfcf056b5a7d59e23"}, 423 | {file = "fastapi-0.68.1.tar.gz", hash = "sha256:644bb815bae326575c4b2842469fb83053a4b974b82fa792ff9283d17fbbd99d"}, 424 | ] 425 | h11 = [ 426 | {file = "h11-0.12.0-py3-none-any.whl", hash = "sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6"}, 427 | {file = "h11-0.12.0.tar.gz", hash = "sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042"}, 428 | ] 429 | loguru = [ 430 | {file = "loguru-0.5.3-py3-none-any.whl", hash = "sha256:f8087ac396b5ee5f67c963b495d615ebbceac2796379599820e324419d53667c"}, 431 | {file = "loguru-0.5.3.tar.gz", hash = "sha256:b28e72ac7a98be3d28ad28570299a393dfcd32e5e3f6a353dec94675767b6319"}, 432 | ] 433 | motor = [ 434 | {file = "motor-2.5.1-py3-none-any.whl", hash = "sha256:961fdceacaae2c7236c939166f66415be81be8bbb762da528386738de3a0f509"}, 435 | {file = "motor-2.5.1.tar.gz", hash = "sha256:663473f4498f955d35db7b6f25651cb165514c247136f368b84419cb7635f6b8"}, 436 | ] 437 | passlib = [ 438 | {file = "passlib-1.7.4-py2.py3-none-any.whl", hash = "sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1"}, 439 | {file = "passlib-1.7.4.tar.gz", hash = "sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04"}, 440 | ] 441 | pyasn1 = [ 442 | {file = "pyasn1-0.4.8-py2.4.egg", hash = "sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3"}, 443 | {file = "pyasn1-0.4.8-py2.5.egg", hash = "sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf"}, 444 | {file = "pyasn1-0.4.8-py2.6.egg", hash = "sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00"}, 445 | {file = "pyasn1-0.4.8-py2.7.egg", hash = "sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8"}, 446 | {file = "pyasn1-0.4.8-py2.py3-none-any.whl", hash = "sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d"}, 447 | {file = "pyasn1-0.4.8-py3.1.egg", hash = "sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86"}, 448 | {file = "pyasn1-0.4.8-py3.2.egg", hash = "sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7"}, 449 | {file = "pyasn1-0.4.8-py3.3.egg", hash = "sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576"}, 450 | {file = "pyasn1-0.4.8-py3.4.egg", hash = "sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12"}, 451 | {file = "pyasn1-0.4.8-py3.5.egg", hash = "sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2"}, 452 | {file = "pyasn1-0.4.8-py3.6.egg", hash = "sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359"}, 453 | {file = "pyasn1-0.4.8-py3.7.egg", hash = "sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776"}, 454 | {file = "pyasn1-0.4.8.tar.gz", hash = "sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba"}, 455 | ] 456 | pycparser = [ 457 | {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, 458 | {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, 459 | ] 460 | pydantic = [ 461 | {file = "pydantic-1.8.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:05ddfd37c1720c392f4e0d43c484217b7521558302e7069ce8d318438d297739"}, 462 | {file = "pydantic-1.8.2-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a7c6002203fe2c5a1b5cbb141bb85060cbff88c2d78eccbc72d97eb7022c43e4"}, 463 | {file = "pydantic-1.8.2-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:589eb6cd6361e8ac341db97602eb7f354551482368a37f4fd086c0733548308e"}, 464 | {file = "pydantic-1.8.2-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:10e5622224245941efc193ad1d159887872776df7a8fd592ed746aa25d071840"}, 465 | {file = "pydantic-1.8.2-cp36-cp36m-win_amd64.whl", hash = "sha256:99a9fc39470010c45c161a1dc584997f1feb13f689ecf645f59bb4ba623e586b"}, 466 | {file = "pydantic-1.8.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:a83db7205f60c6a86f2c44a61791d993dff4b73135df1973ecd9eed5ea0bda20"}, 467 | {file = "pydantic-1.8.2-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:41b542c0b3c42dc17da70554bc6f38cbc30d7066d2c2815a94499b5684582ecb"}, 468 | {file = "pydantic-1.8.2-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:ea5cb40a3b23b3265f6325727ddfc45141b08ed665458be8c6285e7b85bd73a1"}, 469 | {file = "pydantic-1.8.2-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:18b5ea242dd3e62dbf89b2b0ec9ba6c7b5abaf6af85b95a97b00279f65845a23"}, 470 | {file = "pydantic-1.8.2-cp37-cp37m-win_amd64.whl", hash = "sha256:234a6c19f1c14e25e362cb05c68afb7f183eb931dd3cd4605eafff055ebbf287"}, 471 | {file = "pydantic-1.8.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:021ea0e4133e8c824775a0cfe098677acf6fa5a3cbf9206a376eed3fc09302cd"}, 472 | {file = "pydantic-1.8.2-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e710876437bc07bd414ff453ac8ec63d219e7690128d925c6e82889d674bb505"}, 473 | {file = "pydantic-1.8.2-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:ac8eed4ca3bd3aadc58a13c2aa93cd8a884bcf21cb019f8cfecaae3b6ce3746e"}, 474 | {file = "pydantic-1.8.2-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:4a03cbbe743e9c7247ceae6f0d8898f7a64bb65800a45cbdc52d65e370570820"}, 475 | {file = "pydantic-1.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:8621559dcf5afacf0069ed194278f35c255dc1a1385c28b32dd6c110fd6531b3"}, 476 | {file = "pydantic-1.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8b223557f9510cf0bfd8b01316bf6dd281cf41826607eada99662f5e4963f316"}, 477 | {file = "pydantic-1.8.2-cp39-cp39-manylinux1_i686.whl", hash = "sha256:244ad78eeb388a43b0c927e74d3af78008e944074b7d0f4f696ddd5b2af43c62"}, 478 | {file = "pydantic-1.8.2-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:05ef5246a7ffd2ce12a619cbb29f3307b7c4509307b1b49f456657b43529dc6f"}, 479 | {file = "pydantic-1.8.2-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:54cd5121383f4a461ff7644c7ca20c0419d58052db70d8791eacbbe31528916b"}, 480 | {file = "pydantic-1.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:4be75bebf676a5f0f87937c6ddb061fa39cbea067240d98e298508c1bda6f3f3"}, 481 | {file = "pydantic-1.8.2-py3-none-any.whl", hash = "sha256:fec866a0b59f372b7e776f2d7308511784dace622e0992a0b59ea3ccee0ae833"}, 482 | {file = "pydantic-1.8.2.tar.gz", hash = "sha256:26464e57ccaafe72b7ad156fdaa4e9b9ef051f69e175dbbb463283000c05ab7b"}, 483 | ] 484 | pymongo = [ 485 | {file = "pymongo-3.12.0-cp27-cp27m-macosx_10_14_intel.whl", hash = "sha256:072ba7cb65c8aa4d5c5659bf6722ee85781c9d7816dc00679b8b6f3dff1ddafc"}, 486 | {file = "pymongo-3.12.0-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:d6e11ffd43184d529d6752d6dcb62b994f903038a17ea2168ef1910c96324d26"}, 487 | {file = "pymongo-3.12.0-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:7412a36798966624dc4c57d64aa43c2d1100b348abd98daaac8e99e57d87e1d7"}, 488 | {file = "pymongo-3.12.0-cp27-cp27m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e8a82e35d52ad6f867e88096a1a2b9bdc7ec4d5e65c7b4976a248bf2d1a32a93"}, 489 | {file = "pymongo-3.12.0-cp27-cp27m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:dcd3d0009fbb6e454d729f8b22d0063bd9171c31a55e0f0271119bd4f2700023"}, 490 | {file = "pymongo-3.12.0-cp27-cp27m-win32.whl", hash = "sha256:1bc6fe7279ff40c6818db002bf5284aa03ec181ea1b1ceaeee33c289d412afa7"}, 491 | {file = "pymongo-3.12.0-cp27-cp27m-win_amd64.whl", hash = "sha256:e2b7670c0c8c6b501464150dd49dd0d6be6cb7f049e064124911cec5514fa19e"}, 492 | {file = "pymongo-3.12.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:316c1b8723afa9870567cd6dff35d440b2afeda53aa13da6c5ab85f98ed6f5ca"}, 493 | {file = "pymongo-3.12.0-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:255a35bf29185f44b412e31a927d9dcedda7c2c380127ecc4fbf2f61b72fa978"}, 494 | {file = "pymongo-3.12.0-cp27-cp27mu-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ffbae429ba9e42d0582d3ac63fdb410338892468a2107d8ff68228ec9a39a0ed"}, 495 | {file = "pymongo-3.12.0-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:c188db6cf9e14dbbb42f5254292be96f05374a35e7dfa087cc2140f0ff4f10f6"}, 496 | {file = "pymongo-3.12.0-cp34-cp34m-macosx_10_6_intel.whl", hash = "sha256:6fb3f85870ae26896bb44e67db94045f2ebf00c5d41e6b66cdcbb5afd644fc18"}, 497 | {file = "pymongo-3.12.0-cp34-cp34m-manylinux1_i686.whl", hash = "sha256:aaa038eafb7186a4abbb311fcf20724be9363645882bbce540bef4797e812a7a"}, 498 | {file = "pymongo-3.12.0-cp34-cp34m-manylinux1_x86_64.whl", hash = "sha256:7d98ce3c42921bb91566121b658e0d9d59a9082a9bd6f473190607ff25ab637f"}, 499 | {file = "pymongo-3.12.0-cp34-cp34m-win32.whl", hash = "sha256:b0a0cf39f589e52d801fdef418305562bc030cdf8929217463c8433c65fd5c2f"}, 500 | {file = "pymongo-3.12.0-cp34-cp34m-win_amd64.whl", hash = "sha256:ceae3ab9e11a27aaab42878f1d203600dfd24f0e43678b47298219a0f10c0d30"}, 501 | {file = "pymongo-3.12.0-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:5e574664f1468872cd40f74e4811e22b1aa4de9399d6bcfdf1ee6ea94c017fcf"}, 502 | {file = "pymongo-3.12.0-cp35-cp35m-manylinux1_i686.whl", hash = "sha256:73b400fdc22de84bae0dbf1a22613928a41612ec0a3d6ed47caf7ad4d3d0f2ff"}, 503 | {file = "pymongo-3.12.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:cbf8672edeb7b7128c4a939274801f0e32bbf5159987815e3d1eace625264a46"}, 504 | {file = "pymongo-3.12.0-cp35-cp35m-manylinux2014_aarch64.whl", hash = "sha256:a634a4730ce0b0934ed75e45beba730968e12b4dafbb22f69b3b2f616d9e644e"}, 505 | {file = "pymongo-3.12.0-cp35-cp35m-manylinux2014_i686.whl", hash = "sha256:c55782a55f4a013a78ac5b6ee4b8731a192dea7ab09f1b6b3044c96d5128edd4"}, 506 | {file = "pymongo-3.12.0-cp35-cp35m-manylinux2014_ppc64le.whl", hash = "sha256:11f9e0cfc84ade088a38df2708d0b958bb76360181df1b2e1e1a41beaa57952b"}, 507 | {file = "pymongo-3.12.0-cp35-cp35m-manylinux2014_s390x.whl", hash = "sha256:186104a94d39b8412f8e3de385acd990a628346a4402d4f3a288a82b8660bd22"}, 508 | {file = "pymongo-3.12.0-cp35-cp35m-manylinux2014_x86_64.whl", hash = "sha256:70761fd3c576b027eec882b43ee0a8e5b22ff9c20cdf4d0400e104bc29e53e34"}, 509 | {file = "pymongo-3.12.0-cp35-cp35m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:333bfad77aa9cd11711febfb75eed0bb537a1d022e1c252714dad38993590240"}, 510 | {file = "pymongo-3.12.0-cp35-cp35m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:fa8957e9a1b202cb45e6b839c241cd986c897be1e722b81d2f32e9c6aeee80b0"}, 511 | {file = "pymongo-3.12.0-cp35-cp35m-win32.whl", hash = "sha256:4ba0def4abef058c0e5101e05e3d5266e6fffb9795bbf8be0fe912a7361a0209"}, 512 | {file = "pymongo-3.12.0-cp35-cp35m-win_amd64.whl", hash = "sha256:a0e5dff6701fa615f165306e642709e1c1550d5b237c5a7a6ea299886828bd50"}, 513 | {file = "pymongo-3.12.0-cp36-cp36m-macosx_10_6_intel.whl", hash = "sha256:b542d56ed1b8d5cf3bb36326f814bd2fbe8812dfd2582b80a15689ea433c0e35"}, 514 | {file = "pymongo-3.12.0-cp36-cp36m-manylinux1_i686.whl", hash = "sha256:a325600c83e61e3c9cebc0c2b1c8c4140fa887f789085075e8f44c8ff2547eb9"}, 515 | {file = "pymongo-3.12.0-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:48d5bc80ab0af6b60c4163c5617f5cd23f2f880d7600940870ea5055816af024"}, 516 | {file = "pymongo-3.12.0-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:c5cab230e7cabdae9ff23c12271231283efefb944c1b79bed79a91beb65ba547"}, 517 | {file = "pymongo-3.12.0-cp36-cp36m-manylinux2014_i686.whl", hash = "sha256:d73e10772152605f6648ba4410318594f1043bbfe36d2fadee7c4b8912eff7c5"}, 518 | {file = "pymongo-3.12.0-cp36-cp36m-manylinux2014_ppc64le.whl", hash = "sha256:b1c4874331ab960429caca81acb9d2932170d66d6d6f87e65dc4507a85aca152"}, 519 | {file = "pymongo-3.12.0-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:a3566acfbcde46911c52810374ecc0354fdb841284a3efef6ff7105bc007e9a8"}, 520 | {file = "pymongo-3.12.0-cp36-cp36m-manylinux2014_x86_64.whl", hash = "sha256:b3b5b3cbc3fdf4fcfa292529df2a85b5d9c7053913a739d3069af1e12e12219f"}, 521 | {file = "pymongo-3.12.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd3854148005c808c485c754a184c71116372263709958b42aefbef2e5dd373a"}, 522 | {file = "pymongo-3.12.0-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f55c1ddcc1f6050b07d468ce594f55dbf6107b459e16f735d26818d7be1e9538"}, 523 | {file = "pymongo-3.12.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ced944dcdd561476deef7cb7bfd4987c69fffbfeff6d02ca4d5d4fd592d559b7"}, 524 | {file = "pymongo-3.12.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78ecb8d42f50d393af912bfb1fb1dcc9aabe9967973efb49ee577e8f1cea494c"}, 525 | {file = "pymongo-3.12.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1970cfe2aec1bf74b40cf30c130ad10cd968941694630386db33e1d044c22a2e"}, 526 | {file = "pymongo-3.12.0-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b8bf42d3b32f586f4c9e37541769993783a534ad35531ce8a4379f6fa664fba9"}, 527 | {file = "pymongo-3.12.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:bc9ac81e73573516070d24ce15da91281922811f385645df32bd3c8a45ab4684"}, 528 | {file = "pymongo-3.12.0-cp36-cp36m-win32.whl", hash = "sha256:d04ca462cb99077e6c059e97c072957caf2918e6e4191e3161c01c439e0193de"}, 529 | {file = "pymongo-3.12.0-cp36-cp36m-win_amd64.whl", hash = "sha256:f2acf9bbcd514e901f82c4ca6926bbd2ae61716728f110b4343eb0a69612d018"}, 530 | {file = "pymongo-3.12.0-cp37-cp37m-macosx_10_6_intel.whl", hash = "sha256:b754240daafecd9d5fce426b0fbaaed03f4ebb130745c8a4ae9231fffb8d75e5"}, 531 | {file = "pymongo-3.12.0-cp37-cp37m-manylinux1_i686.whl", hash = "sha256:af586e85144023686fb0af09c8cdf672484ea182f352e7ceead3d832de381e1b"}, 532 | {file = "pymongo-3.12.0-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:fe5872ce6f9627deac8314bdffd3862624227c3de4c17ef0cc78bbf0402999eb"}, 533 | {file = "pymongo-3.12.0-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:f6977a520bd96e097c8a37a8cbb9faa1ea99d21bf84190195056e25f688af73d"}, 534 | {file = "pymongo-3.12.0-cp37-cp37m-manylinux2014_i686.whl", hash = "sha256:2dbfbbded947a83a3dffc2bd1ec4750c17e40904692186e2c55a3ad314ca0222"}, 535 | {file = "pymongo-3.12.0-cp37-cp37m-manylinux2014_ppc64le.whl", hash = "sha256:a752ecd1a26000a6d67be7c9a2e93801994a8b3f866ac95b672fbc00225ca91a"}, 536 | {file = "pymongo-3.12.0-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:1bab889ae7640eba739f67fcbf8eff252dddc60d4495e6ddd3a87cd9a95fdb52"}, 537 | {file = "pymongo-3.12.0-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:f94c7d22fb36b184734dded7345a04ec5f95130421c775b8b0c65044ef073f34"}, 538 | {file = "pymongo-3.12.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ec5ca7c0007ce268048bbe0ffc6846ed1616cf3d8628b136e81d5e64ff3f52a2"}, 539 | {file = "pymongo-3.12.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7c72d08acdf573455b2b9d2b75b8237654841d63a48bc2327dc102c6ee89b75a"}, 540 | {file = "pymongo-3.12.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b6ea08758b6673610b3c5bdf47189286cf9c58b1077558706a2f6f8744922527"}, 541 | {file = "pymongo-3.12.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46d5ec90276f71af3a29917b30f2aec2315a2759b5f8d45b3b63a07ca8a070a3"}, 542 | {file = "pymongo-3.12.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:625befa3bc9b40746a749115cc6a15bf20b9bd7597ca55d646205b479a2c99c7"}, 543 | {file = "pymongo-3.12.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d1131562ddc2ea8a446f66c2648d7dabec2b3816fc818528eb978a75a6d23b2e"}, 544 | {file = "pymongo-3.12.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:eee42a1cc06565f6b21caa1f504ec15e07de7ebfd520ab57f8cb3308bc118e22"}, 545 | {file = "pymongo-3.12.0-cp37-cp37m-win32.whl", hash = "sha256:94d38eba4d1b5eb3e6bfece0651b855a35c44f32fd91f512ab4ba41b8c0d3e66"}, 546 | {file = "pymongo-3.12.0-cp37-cp37m-win_amd64.whl", hash = "sha256:e018a4921657c2d3f89c720b7b90b9182e277178a04a7e9542cc79d7d787ca51"}, 547 | {file = "pymongo-3.12.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7c6a9948916a7bbcc6d3a9f6fb75db1acb5546078023bfb3db6efabcd5a67527"}, 548 | {file = "pymongo-3.12.0-cp38-cp38-manylinux1_i686.whl", hash = "sha256:e9faf8d4712d5ea301d74abfcf6dafe4b7f4af7936e91f283b0ad7bf69ed3e3a"}, 549 | {file = "pymongo-3.12.0-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:cc2894fe91f31a513860238ede69fe47fada21f9e7ddfe73f7f9fef93a971e41"}, 550 | {file = "pymongo-3.12.0-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:053b4ebf91c7395d1fcd2ce6a9edff0024575b7b2de6781554a4114448a8adc9"}, 551 | {file = "pymongo-3.12.0-cp38-cp38-manylinux2014_i686.whl", hash = "sha256:39dafa2eaf577d1969f289dc9a44501859a1897eb45bd589e93ce843fc610800"}, 552 | {file = "pymongo-3.12.0-cp38-cp38-manylinux2014_ppc64le.whl", hash = "sha256:246ec420e4c8744fceb4e259f906211b9c198e1f345e6158dcd7cbad3737e11e"}, 553 | {file = "pymongo-3.12.0-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:208debdcf76ed39ebf24f38509f50dc1c100e31e8653817fedb8e1f867850a13"}, 554 | {file = "pymongo-3.12.0-cp38-cp38-manylinux2014_x86_64.whl", hash = "sha256:18290649759f9db660972442aa606f845c368db9b08c4c73770f6da14113569b"}, 555 | {file = "pymongo-3.12.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:657ad80de8ec9ed656f28844efc801a0802961e8c6a85038d97ff6f555ef4919"}, 556 | {file = "pymongo-3.12.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b772bab31cbd9cb911e41e1a611ebc9497f9a32a7348e2747c38210f75c00f41"}, 557 | {file = "pymongo-3.12.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2399a85b54f68008e483b2871f4a458b4c980469c7fe921595ede073e4844f1e"}, 558 | {file = "pymongo-3.12.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e66780f14c2efaf989cd3ac613b03ee6a8e3a0ba7b96c0bb14adca71a427e55"}, 559 | {file = "pymongo-3.12.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:02dc0b0f48ed3cd06c13b7e31b066bf91e00dac5f8147b0a0a45f9009bfab857"}, 560 | {file = "pymongo-3.12.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:070a4ef689c9438a999ec3830e69b208ff0d12251846e064d947f97d819d1d05"}, 561 | {file = "pymongo-3.12.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:db93608a246da44d728842b8fa9e45aa9782db76955f634a707739a8d53ff544"}, 562 | {file = "pymongo-3.12.0-cp38-cp38-win32.whl", hash = "sha256:5af390fa9faf56c93252dab09ea57cd020c9123aa921b63a0ed51832fdb492e7"}, 563 | {file = "pymongo-3.12.0-cp38-cp38-win_amd64.whl", hash = "sha256:a2239556ff7241584ce57be1facf25081669bb457a9e5cbe68cce4aae6567aa1"}, 564 | {file = "pymongo-3.12.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cda9e628b1315beec8341e8c04aac9a0b910650b05e0751e42e399d5694aeacb"}, 565 | {file = "pymongo-3.12.0-cp39-cp39-manylinux1_i686.whl", hash = "sha256:845a8b83798b2fb11b09928413cb32692866bfbc28830a433d9fa4c8c3720dd0"}, 566 | {file = "pymongo-3.12.0-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:da8288bc4a7807c6715416deed1c57d94d5e03e93537889e002bf985be503f1a"}, 567 | {file = "pymongo-3.12.0-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:a9ba2a63777027b06b116e1ea8248e66fd1bedc2c644f93124b81a91ddbf6d88"}, 568 | {file = "pymongo-3.12.0-cp39-cp39-manylinux2014_i686.whl", hash = "sha256:9a13661681d17e43009bb3e85e837aa1ec5feeea1e3654682a01b8821940f8b3"}, 569 | {file = "pymongo-3.12.0-cp39-cp39-manylinux2014_ppc64le.whl", hash = "sha256:6b89dc51206e4971c5568c797991eaaef5dc2a6118d67165858ad11752dba055"}, 570 | {file = "pymongo-3.12.0-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:701e08457183da70ed96b35a6b43e6ba1df0b47c837b063cde39a1fbe1aeda81"}, 571 | {file = "pymongo-3.12.0-cp39-cp39-manylinux2014_x86_64.whl", hash = "sha256:e7a33322e08021c37e89cae8ff06327503e8a1719e97c69f32c31cbf6c30d72c"}, 572 | {file = "pymongo-3.12.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd1f49f949a658c4e8f81ed73f9aad25fcc7d4f62f767f591e749e30038c4e1d"}, 573 | {file = "pymongo-3.12.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a6d055f01b83b1a4df8bb0c61983d3bdffa913764488910af3620e5c2450bf83"}, 574 | {file = "pymongo-3.12.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dd6ff2192f34bd622883c745a56f492b1c9ccd44e14953e8051c33024a2947d5"}, 575 | {file = "pymongo-3.12.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:19d4bd0fc29aa405bb1781456c9cfff9fceabb68543741eb17234952dbc2bbb0"}, 576 | {file = "pymongo-3.12.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24f8aeec4d6b894a6128844e50ff423dd02462ee83addf503c598ee3a80ddf3d"}, 577 | {file = "pymongo-3.12.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:0b6055e0ef451ff73c93d0348d122a0750dddf323b9361de5835dac2f6cf7fc1"}, 578 | {file = "pymongo-3.12.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:6261bee7c5abadeac7497f8f1c43e521da78dd13b0a2439f526a7b0fc3788824"}, 579 | {file = "pymongo-3.12.0-cp39-cp39-win32.whl", hash = "sha256:2e92aa32300a0b5e4175caec7769f482b292769807024a86d674b3f19b8e3755"}, 580 | {file = "pymongo-3.12.0-cp39-cp39-win_amd64.whl", hash = "sha256:3ce83f17f641a62a4dfb0ba1b8a3c1ced7c842f511b5450d90c030c7828e3693"}, 581 | {file = "pymongo-3.12.0-py2.7-macosx-10.14-intel.egg", hash = "sha256:d1740776b70367277323fafb76bcf09753a5cc9824f5d705bac22a34ff3668ea"}, 582 | {file = "pymongo-3.12.0.tar.gz", hash = "sha256:b88d1742159bc93a078733f9789f563cef26f5e370eba810476a71aa98e5fbc2"}, 583 | ] 584 | python-jose = [ 585 | {file = "python-jose-3.3.0.tar.gz", hash = "sha256:55779b5e6ad599c6336191246e95eb2293a9ddebd555f796a65f838f07e5d78a"}, 586 | {file = "python_jose-3.3.0-py2.py3-none-any.whl", hash = "sha256:9b1376b023f8b298536eedd47ae1089bcdb848f1535ab30555cd92002d78923a"}, 587 | ] 588 | pyyaml = [ 589 | {file = "PyYAML-5.4.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922"}, 590 | {file = "PyYAML-5.4.1-cp27-cp27m-win32.whl", hash = "sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393"}, 591 | {file = "PyYAML-5.4.1-cp27-cp27m-win_amd64.whl", hash = "sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8"}, 592 | {file = "PyYAML-5.4.1-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185"}, 593 | {file = "PyYAML-5.4.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253"}, 594 | {file = "PyYAML-5.4.1-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc"}, 595 | {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347"}, 596 | {file = "PyYAML-5.4.1-cp36-cp36m-manylinux2014_s390x.whl", hash = "sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541"}, 597 | {file = "PyYAML-5.4.1-cp36-cp36m-win32.whl", hash = "sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5"}, 598 | {file = "PyYAML-5.4.1-cp36-cp36m-win_amd64.whl", hash = "sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df"}, 599 | {file = "PyYAML-5.4.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018"}, 600 | {file = "PyYAML-5.4.1-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63"}, 601 | {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa"}, 602 | {file = "PyYAML-5.4.1-cp37-cp37m-manylinux2014_s390x.whl", hash = "sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0"}, 603 | {file = "PyYAML-5.4.1-cp37-cp37m-win32.whl", hash = "sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b"}, 604 | {file = "PyYAML-5.4.1-cp37-cp37m-win_amd64.whl", hash = "sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf"}, 605 | {file = "PyYAML-5.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46"}, 606 | {file = "PyYAML-5.4.1-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb"}, 607 | {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247"}, 608 | {file = "PyYAML-5.4.1-cp38-cp38-manylinux2014_s390x.whl", hash = "sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc"}, 609 | {file = "PyYAML-5.4.1-cp38-cp38-win32.whl", hash = "sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc"}, 610 | {file = "PyYAML-5.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696"}, 611 | {file = "PyYAML-5.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77"}, 612 | {file = "PyYAML-5.4.1-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183"}, 613 | {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122"}, 614 | {file = "PyYAML-5.4.1-cp39-cp39-manylinux2014_s390x.whl", hash = "sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6"}, 615 | {file = "PyYAML-5.4.1-cp39-cp39-win32.whl", hash = "sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10"}, 616 | {file = "PyYAML-5.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db"}, 617 | {file = "PyYAML-5.4.1.tar.gz", hash = "sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e"}, 618 | ] 619 | rsa = [ 620 | {file = "rsa-4.7.2-py3-none-any.whl", hash = "sha256:78f9a9bf4e7be0c5ded4583326e7461e3a3c5aae24073648b4bdfa797d78c9d2"}, 621 | {file = "rsa-4.7.2.tar.gz", hash = "sha256:9d689e6ca1b3038bc82bf8d23e944b6b6037bc02301a574935b2dd946e0353b9"}, 622 | ] 623 | six = [ 624 | {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, 625 | {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, 626 | ] 627 | starlette = [ 628 | {file = "starlette-0.14.2-py3-none-any.whl", hash = "sha256:3c8e48e52736b3161e34c9f0e8153b4f32ec5d8995a3ee1d59410d92f75162ed"}, 629 | {file = "starlette-0.14.2.tar.gz", hash = "sha256:7d49f4a27f8742262ef1470608c59ddbc66baf37c148e938c7038e6bc7a998aa"}, 630 | ] 631 | typing-extensions = [ 632 | {file = "typing_extensions-3.10.0.0-py2-none-any.whl", hash = "sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497"}, 633 | {file = "typing_extensions-3.10.0.0-py3-none-any.whl", hash = "sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84"}, 634 | {file = "typing_extensions-3.10.0.0.tar.gz", hash = "sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342"}, 635 | ] 636 | uvicorn = [ 637 | {file = "uvicorn-0.15.0-py3-none-any.whl", hash = "sha256:17f898c64c71a2640514d4089da2689e5db1ce5d4086c2d53699bf99513421c1"}, 638 | {file = "uvicorn-0.15.0.tar.gz", hash = "sha256:d9a3c0dd1ca86728d3e235182683b4cf94cd53a867c288eaeca80ee781b2caff"}, 639 | ] 640 | win32-setctime = [ 641 | {file = "win32_setctime-1.0.3-py3-none-any.whl", hash = "sha256:dc925662de0a6eb987f0b01f599c01a8236cb8c62831c22d9cada09ad958243e"}, 642 | {file = "win32_setctime-1.0.3.tar.gz", hash = "sha256:4e88556c32fdf47f64165a2180ba4552f8bb32c1103a2fafd05723a0bd42bd4b"}, 643 | ] 644 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "Service1-backend" 3 | version = "0.1.0" 4 | description = "Service1 Backend" 5 | authors = ["Billaids "] 6 | 7 | [tool.poetry.dependencies] 8 | python = "^3.9" 9 | fastapi = "^0.68.1" 10 | python-jose = {extras = ["cryptography"], version = "^3.3.0"} 11 | passlib = {extras = ["bcrypt"], version = "^1.7.4"} 12 | uvicorn = "^0.15.0" 13 | loguru = "^0.5.3" 14 | motor = "^2.5.1" 15 | PyYAML = "^5.4.1" 16 | dnspython = "^2.1.0" 17 | 18 | [tool.poetry.dev-dependencies] 19 | 20 | [build-system] 21 | requires = ["poetry-core>=1.0.0"] 22 | build-backend = "poetry.core.masonry.api" 23 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.4.1; python_version >= "3.6" \ 2 | --hash=sha256:ffc141aa908e6f175673e7b1b3b7af4fdb0ecb738fc5c8b88f69f055c2415214 \ 3 | --hash=sha256:4ef1ab46b484e3c706329cedeff284a5d40824200638503f5768edb6de7d58e9 4 | bcrypt==3.2.0; python_version >= "3.6" \ 5 | --hash=sha256:c95d4cbebffafcdd28bd28bb4e25b31c50f6da605c81ffd9ad8a3d1b2ab7b1b6 \ 6 | --hash=sha256:63d4e3ff96188e5898779b6057878fecf3f11cfe6ec3b313ea09955d587ec7a7 \ 7 | --hash=sha256:cd1ea2ff3038509ea95f687256c46b79f5fc382ad0aa3664d200047546d511d1 \ 8 | --hash=sha256:cdcdcb3972027f83fe24a48b1e90ea4b584d35f1cc279d76de6fc4b13376239d \ 9 | --hash=sha256:a67fb841b35c28a59cebed05fbd3e80eea26e6d75851f0574a9273c80f3e9b55 \ 10 | --hash=sha256:81fec756feff5b6818ea7ab031205e1d323d8943d237303baca2c5f9c7846f34 \ 11 | --hash=sha256:5b93c1726e50a93a033c36e5ca7fdcd29a5c7395af50a6892f5d9e7c6cfbfb29 12 | cffi==1.14.6 \ 13 | --hash=sha256:22b9c3c320171c108e903d61a3723b51e37aaa8c81255b5e7ce102775bd01e2c \ 14 | --hash=sha256:f0c5d1acbfca6ebdd6b1e3eded8d261affb6ddcf2186205518f1428b8569bb99 \ 15 | --hash=sha256:99f27fefe34c37ba9875f224a8f36e31d744d8083e00f520f133cab79ad5e819 \ 16 | --hash=sha256:55af55e32ae468e9946f741a5d51f9896da6b9bf0bbdd326843fec05c730eb20 \ 17 | --hash=sha256:7bcac9a2b4fdbed2c16fa5681356d7121ecabf041f18d97ed5b8e0dd38a80224 \ 18 | --hash=sha256:ed38b924ce794e505647f7c331b22a693bee1538fdf46b0222c4717b42f744e7 \ 19 | --hash=sha256:e22dcb48709fc51a7b58a927391b23ab37eb3737a98ac4338e2448bef8559b33 \ 20 | --hash=sha256:aedb15f0a5a5949ecb129a82b72b19df97bbbca024081ed2ef88bd5c0a610534 \ 21 | --hash=sha256:48916e459c54c4a70e52745639f1db524542140433599e13911b2f329834276a \ 22 | --hash=sha256:f627688813d0a4140153ff532537fbe4afea5a3dffce1f9deb7f91f848a832b5 \ 23 | --hash=sha256:f0010c6f9d1a4011e429109fda55a225921e3206e7f62a0c22a35344bfd13cca \ 24 | --hash=sha256:57e555a9feb4a8460415f1aac331a2dc833b1115284f7ded7278b54afc5bd218 \ 25 | --hash=sha256:e8c6a99be100371dbb046880e7a282152aa5d6127ae01783e37662ef73850d8f \ 26 | --hash=sha256:19ca0dbdeda3b2615421d54bef8985f72af6e0c47082a8d26122adac81a95872 \ 27 | --hash=sha256:d950695ae4381ecd856bcaf2b1e866720e4ab9a1498cba61c602e56630ca7195 \ 28 | --hash=sha256:e9dc245e3ac69c92ee4c167fbdd7428ec1956d4e754223124991ef29eb57a09d \ 29 | --hash=sha256:a8661b2ce9694ca01c529bfa204dbb144b275a31685a075ce123f12331be790b \ 30 | --hash=sha256:b315d709717a99f4b27b59b021e6207c64620790ca3e0bde636a6c7f14618abb \ 31 | --hash=sha256:80b06212075346b5546b0417b9f2bf467fea3bfe7352f781ffc05a8ab24ba14a \ 32 | --hash=sha256:a9da7010cec5a12193d1af9872a00888f396aba3dc79186604a09ea3ee7c029e \ 33 | --hash=sha256:4373612d59c404baeb7cbd788a18b2b2a8331abcc84c3ba40051fcd18b17a4d5 \ 34 | --hash=sha256:f10afb1004f102c7868ebfe91c28f4a712227fe4cb24974350ace1f90e1febbf \ 35 | --hash=sha256:fd4305f86f53dfd8cd3522269ed7fc34856a8ee3709a5e28b2836b2db9d4cd69 \ 36 | --hash=sha256:6d6169cb3c6c2ad50db5b868db6491a790300ade1ed5d1da29289d73bbe40b56 \ 37 | --hash=sha256:5d4b68e216fc65e9fe4f524c177b54964af043dde734807586cf5435af84045c \ 38 | --hash=sha256:33791e8a2dc2953f28b8d8d300dde42dd929ac28f974c4b4c6272cb2955cb762 \ 39 | --hash=sha256:0c0591bee64e438883b0c92a7bed78f6290d40bf02e54c5bf0978eaf36061771 \ 40 | --hash=sha256:8eb687582ed7cd8c4bdbff3df6c0da443eb89c3c72e6e5dcdd9c81729712791a \ 41 | --hash=sha256:ba6f2b3f452e150945d58f4badd92310449876c4c954836cfb1803bdd7b422f0 \ 42 | --hash=sha256:64fda793737bc4037521d4899be780534b9aea552eb673b9833b01f945904c2e \ 43 | --hash=sha256:9f3e33c28cd39d1b655ed1ba7247133b6f7fc16fa16887b120c0c670e35ce346 \ 44 | --hash=sha256:26bb2549b72708c833f5abe62b756176022a7b9a7f689b571e74c8478ead51dc \ 45 | --hash=sha256:eb687a11f0a7a1839719edd80f41e459cc5366857ecbed383ff376c4e3cc6afd \ 46 | --hash=sha256:d2ad4d668a5c0645d281dcd17aff2be3212bc109b33814bbb15c4939f44181cc \ 47 | --hash=sha256:487d63e1454627c8e47dd230025780e91869cfba4c753a74fda196a1f6ad6548 \ 48 | --hash=sha256:c33d18eb6e6bc36f09d793c0dc58b0211fccc6ae5149b808da4a62660678b156 \ 49 | --hash=sha256:06c54a68935738d206570b20da5ef2b6b6d92b38ef3ec45c5422c0ebaf338d4d \ 50 | --hash=sha256:f174135f5609428cc6e1b9090f9268f5c8935fddb1b25ccb8255a2d50de6789e \ 51 | --hash=sha256:f3ebe6e73c319340830a9b2825d32eb6d8475c1dac020b4f0aa774ee3b898d1c \ 52 | --hash=sha256:3c8d896becff2fa653dc4438b54a5a25a971d1f4110b32bd3068db3722c80202 \ 53 | --hash=sha256:4922cd707b25e623b902c86188aca466d3620892db76c0bdd7b99a3d5e61d35f \ 54 | --hash=sha256:c9e005e9bd57bc987764c32a1bee4364c44fdc11a3cc20a40b93b444984f2b87 \ 55 | --hash=sha256:eb9e2a346c5238a30a746893f23a9535e700f8192a68c07c0258e7ece6ff3728 \ 56 | --hash=sha256:818014c754cd3dba7229c0f5884396264d51ffb87ec86e927ef0be140bfdb0d2 \ 57 | --hash=sha256:c9a875ce9d7fe32887784274dd533c57909b7b1dcadcc128a2ac21331a9765dd 58 | click==8.0.1; python_version >= "3.6" \ 59 | --hash=sha256:fba402a4a47334742d782209a7c79bc448911afe1149d07bdabdf480b3e2f4b6 \ 60 | --hash=sha256:8c04c11192119b1ef78ea049e0a6f0463e4c48ef00a30160c704337586f3ad7a 61 | colorama==0.4.4; python_version >= "3.6" and python_full_version < "3.0.0" and sys_platform == "win32" and platform_system == "Windows" or sys_platform == "win32" and python_version >= "3.6" and python_full_version >= "3.5.0" and platform_system == "Windows" \ 62 | --hash=sha256:9f47eda37229f68eee03b24b9748937c7dc3868f906e8ba69fbcbdd3bc5dc3e2 \ 63 | --hash=sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b 64 | cryptography==3.4.8; python_version >= "3.6" \ 65 | --hash=sha256:a00cf305f07b26c351d8d4e1af84ad7501eca8a342dedf24a7acb0e7b7406e14 \ 66 | --hash=sha256:f44d141b8c4ea5eb4dbc9b3ad992d45580c1d22bf5e24363f2fbf50c2d7ae8a7 \ 67 | --hash=sha256:0a7dcbcd3f1913f664aca35d47c1331fce738d44ec34b7be8b9d332151b0b01e \ 68 | --hash=sha256:34dae04a0dce5730d8eb7894eab617d8a70d0c97da76b905de9efb7128ad7085 \ 69 | --hash=sha256:1eb7bb0df6f6f583dd8e054689def236255161ebbcf62b226454ab9ec663746b \ 70 | --hash=sha256:9965c46c674ba8cc572bc09a03f4c649292ee73e1b683adb1ce81e82e9a6a0fb \ 71 | --hash=sha256:21ca464b3a4b8d8e86ba0ee5045e103a1fcfac3b39319727bc0fc58c09c6aff7 \ 72 | --hash=sha256:3520667fda779eb788ea00080124875be18f2d8f0848ec00733c0ec3bb8219fc \ 73 | --hash=sha256:d2a6e5ef66503da51d2110edf6c403dc6b494cc0082f85db12f54e9c5d4c3ec5 \ 74 | --hash=sha256:a305600e7a6b7b855cd798e00278161b681ad6e9b7eca94c721d5f588ab212af \ 75 | --hash=sha256:3fa3a7ccf96e826affdf1a0a9432be74dc73423125c8f96a909e3835a5ef194a \ 76 | --hash=sha256:d9ec0e67a14f9d1d48dd87a2531009a9b251c02ea42851c060b25c782516ff06 \ 77 | --hash=sha256:5b0fbfae7ff7febdb74b574055c7466da334a5371f253732d7e2e7525d570498 \ 78 | --hash=sha256:94fff993ee9bc1b2440d3b7243d488c6a3d9724cc2b09cdb297f6a886d040ef7 \ 79 | --hash=sha256:8695456444f277af73a4877db9fc979849cd3ee74c198d04fc0776ebc3db52b9 \ 80 | --hash=sha256:cd65b60cfe004790c795cc35f272e41a3df4631e2fb6b35aa7ac6ef2859d554e \ 81 | --hash=sha256:94cc5ed4ceaefcbe5bf38c8fba6a21fc1d365bb8fb826ea1688e3370b2e24a1c 82 | dnspython==2.1.0; python_version >= "3.6" \ 83 | --hash=sha256:95d12f6ef0317118d2a1a6fc49aac65ffec7eb8087474158f42f26a639135216 \ 84 | --hash=sha256:e4a87f0b573201a0f3727fa18a516b055fd1107e0e5477cded4a2de497df1dd4 85 | ecdsa==0.17.0; python_version >= "2.6" and python_full_version < "3.0.0" or python_full_version >= "3.3.0" \ 86 | --hash=sha256:5cf31d5b33743abe0dfc28999036c849a69d548f994b535e527ee3cb7f3ef676 \ 87 | --hash=sha256:b9f500bb439e4153d0330610f5d26baaf18d17b8ced1bc54410d189385ea68aa 88 | fastapi==0.68.1; python_version >= "3.6" \ 89 | --hash=sha256:94d2820906c36b9b8303796fb7271337ec89c74223229e3cfcf056b5a7d59e23 \ 90 | --hash=sha256:644bb815bae326575c4b2842469fb83053a4b974b82fa792ff9283d17fbbd99d 91 | h11==0.12.0; python_version >= "3.6" \ 92 | --hash=sha256:36a3cb8c0a032f56e2da7084577878a035d3b61d104230d4bd49c0c6b555a9c6 \ 93 | --hash=sha256:47222cb6067e4a307d535814917cd98fd0a57b6788ce715755fa2b6c28b56042 94 | loguru==0.5.3; python_version >= "3.5" \ 95 | --hash=sha256:f8087ac396b5ee5f67c963b495d615ebbceac2796379599820e324419d53667c \ 96 | --hash=sha256:b28e72ac7a98be3d28ad28570299a393dfcd32e5e3f6a353dec94675767b6319 97 | motor==2.5.1; python_full_version >= "3.5.2" \ 98 | --hash=sha256:961fdceacaae2c7236c939166f66415be81be8bbb762da528386738de3a0f509 \ 99 | --hash=sha256:663473f4498f955d35db7b6f25651cb165514c247136f368b84419cb7635f6b8 100 | passlib==1.7.4 \ 101 | --hash=sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1 \ 102 | --hash=sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04 103 | pyasn1==0.4.8; python_version >= "3.5" and python_version < "4" \ 104 | --hash=sha256:fec3e9d8e36808a28efb59b489e4528c10ad0f480e57dcc32b4de5c9d8c9fdf3 \ 105 | --hash=sha256:0458773cfe65b153891ac249bcf1b5f8f320b7c2ce462151f8fa74de8934becf \ 106 | --hash=sha256:5c9414dcfede6e441f7e8f81b43b34e834731003427e5b09e4e00e3172a10f00 \ 107 | --hash=sha256:6e7545f1a61025a4e58bb336952c5061697da694db1cae97b116e9c46abcf7c8 \ 108 | --hash=sha256:39c7e2ec30515947ff4e87fb6f456dfc6e84857d34be479c9d4a4ba4bf46aa5d \ 109 | --hash=sha256:78fa6da68ed2727915c4767bb386ab32cdba863caa7dbe473eaae45f9959da86 \ 110 | --hash=sha256:08c3c53b75eaa48d71cf8c710312316392ed40899cb34710d092e96745a358b7 \ 111 | --hash=sha256:03840c999ba71680a131cfaee6fab142e1ed9bbd9c693e285cc6aca0d555e576 \ 112 | --hash=sha256:7ab8a544af125fb704feadb008c99a88805126fb525280b2270bb25cc1d78a12 \ 113 | --hash=sha256:e89bf84b5437b532b0803ba5c9a5e054d21fec423a89952a74f87fa2c9b7bce2 \ 114 | --hash=sha256:014c0e9976956a08139dc0712ae195324a75e142284d5f87f1a87ee1b068a359 \ 115 | --hash=sha256:99fcc3c8d804d1bc6d9a099921e39d827026409a58f2a720dcdb89374ea0c776 \ 116 | --hash=sha256:aef77c9fb94a3ac588e87841208bdec464471d9871bd5050a287cc9a475cd0ba 117 | pycparser==2.20; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.4.0" \ 118 | --hash=sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705 \ 119 | --hash=sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0 120 | pydantic==1.8.2; python_full_version >= "3.6.1" and python_version >= "3.6" \ 121 | --hash=sha256:05ddfd37c1720c392f4e0d43c484217b7521558302e7069ce8d318438d297739 \ 122 | --hash=sha256:a7c6002203fe2c5a1b5cbb141bb85060cbff88c2d78eccbc72d97eb7022c43e4 \ 123 | --hash=sha256:589eb6cd6361e8ac341db97602eb7f354551482368a37f4fd086c0733548308e \ 124 | --hash=sha256:10e5622224245941efc193ad1d159887872776df7a8fd592ed746aa25d071840 \ 125 | --hash=sha256:99a9fc39470010c45c161a1dc584997f1feb13f689ecf645f59bb4ba623e586b \ 126 | --hash=sha256:a83db7205f60c6a86f2c44a61791d993dff4b73135df1973ecd9eed5ea0bda20 \ 127 | --hash=sha256:41b542c0b3c42dc17da70554bc6f38cbc30d7066d2c2815a94499b5684582ecb \ 128 | --hash=sha256:ea5cb40a3b23b3265f6325727ddfc45141b08ed665458be8c6285e7b85bd73a1 \ 129 | --hash=sha256:18b5ea242dd3e62dbf89b2b0ec9ba6c7b5abaf6af85b95a97b00279f65845a23 \ 130 | --hash=sha256:234a6c19f1c14e25e362cb05c68afb7f183eb931dd3cd4605eafff055ebbf287 \ 131 | --hash=sha256:021ea0e4133e8c824775a0cfe098677acf6fa5a3cbf9206a376eed3fc09302cd \ 132 | --hash=sha256:e710876437bc07bd414ff453ac8ec63d219e7690128d925c6e82889d674bb505 \ 133 | --hash=sha256:ac8eed4ca3bd3aadc58a13c2aa93cd8a884bcf21cb019f8cfecaae3b6ce3746e \ 134 | --hash=sha256:4a03cbbe743e9c7247ceae6f0d8898f7a64bb65800a45cbdc52d65e370570820 \ 135 | --hash=sha256:8621559dcf5afacf0069ed194278f35c255dc1a1385c28b32dd6c110fd6531b3 \ 136 | --hash=sha256:8b223557f9510cf0bfd8b01316bf6dd281cf41826607eada99662f5e4963f316 \ 137 | --hash=sha256:244ad78eeb388a43b0c927e74d3af78008e944074b7d0f4f696ddd5b2af43c62 \ 138 | --hash=sha256:05ef5246a7ffd2ce12a619cbb29f3307b7c4509307b1b49f456657b43529dc6f \ 139 | --hash=sha256:54cd5121383f4a461ff7644c7ca20c0419d58052db70d8791eacbbe31528916b \ 140 | --hash=sha256:4be75bebf676a5f0f87937c6ddb061fa39cbea067240d98e298508c1bda6f3f3 \ 141 | --hash=sha256:fec866a0b59f372b7e776f2d7308511784dace622e0992a0b59ea3ccee0ae833 \ 142 | --hash=sha256:26464e57ccaafe72b7ad156fdaa4e9b9ef051f69e175dbbb463283000c05ab7b 143 | pymongo==3.12.0; python_full_version >= "3.5.2" \ 144 | --hash=sha256:072ba7cb65c8aa4d5c5659bf6722ee85781c9d7816dc00679b8b6f3dff1ddafc \ 145 | --hash=sha256:d6e11ffd43184d529d6752d6dcb62b994f903038a17ea2168ef1910c96324d26 \ 146 | --hash=sha256:7412a36798966624dc4c57d64aa43c2d1100b348abd98daaac8e99e57d87e1d7 \ 147 | --hash=sha256:e8a82e35d52ad6f867e88096a1a2b9bdc7ec4d5e65c7b4976a248bf2d1a32a93 \ 148 | --hash=sha256:dcd3d0009fbb6e454d729f8b22d0063bd9171c31a55e0f0271119bd4f2700023 \ 149 | --hash=sha256:1bc6fe7279ff40c6818db002bf5284aa03ec181ea1b1ceaeee33c289d412afa7 \ 150 | --hash=sha256:e2b7670c0c8c6b501464150dd49dd0d6be6cb7f049e064124911cec5514fa19e \ 151 | --hash=sha256:316c1b8723afa9870567cd6dff35d440b2afeda53aa13da6c5ab85f98ed6f5ca \ 152 | --hash=sha256:255a35bf29185f44b412e31a927d9dcedda7c2c380127ecc4fbf2f61b72fa978 \ 153 | --hash=sha256:ffbae429ba9e42d0582d3ac63fdb410338892468a2107d8ff68228ec9a39a0ed \ 154 | --hash=sha256:c188db6cf9e14dbbb42f5254292be96f05374a35e7dfa087cc2140f0ff4f10f6 \ 155 | --hash=sha256:6fb3f85870ae26896bb44e67db94045f2ebf00c5d41e6b66cdcbb5afd644fc18 \ 156 | --hash=sha256:aaa038eafb7186a4abbb311fcf20724be9363645882bbce540bef4797e812a7a \ 157 | --hash=sha256:7d98ce3c42921bb91566121b658e0d9d59a9082a9bd6f473190607ff25ab637f \ 158 | --hash=sha256:b0a0cf39f589e52d801fdef418305562bc030cdf8929217463c8433c65fd5c2f \ 159 | --hash=sha256:ceae3ab9e11a27aaab42878f1d203600dfd24f0e43678b47298219a0f10c0d30 \ 160 | --hash=sha256:5e574664f1468872cd40f74e4811e22b1aa4de9399d6bcfdf1ee6ea94c017fcf \ 161 | --hash=sha256:73b400fdc22de84bae0dbf1a22613928a41612ec0a3d6ed47caf7ad4d3d0f2ff \ 162 | --hash=sha256:cbf8672edeb7b7128c4a939274801f0e32bbf5159987815e3d1eace625264a46 \ 163 | --hash=sha256:a634a4730ce0b0934ed75e45beba730968e12b4dafbb22f69b3b2f616d9e644e \ 164 | --hash=sha256:c55782a55f4a013a78ac5b6ee4b8731a192dea7ab09f1b6b3044c96d5128edd4 \ 165 | --hash=sha256:11f9e0cfc84ade088a38df2708d0b958bb76360181df1b2e1e1a41beaa57952b \ 166 | --hash=sha256:186104a94d39b8412f8e3de385acd990a628346a4402d4f3a288a82b8660bd22 \ 167 | --hash=sha256:70761fd3c576b027eec882b43ee0a8e5b22ff9c20cdf4d0400e104bc29e53e34 \ 168 | --hash=sha256:333bfad77aa9cd11711febfb75eed0bb537a1d022e1c252714dad38993590240 \ 169 | --hash=sha256:fa8957e9a1b202cb45e6b839c241cd986c897be1e722b81d2f32e9c6aeee80b0 \ 170 | --hash=sha256:4ba0def4abef058c0e5101e05e3d5266e6fffb9795bbf8be0fe912a7361a0209 \ 171 | --hash=sha256:a0e5dff6701fa615f165306e642709e1c1550d5b237c5a7a6ea299886828bd50 \ 172 | --hash=sha256:b542d56ed1b8d5cf3bb36326f814bd2fbe8812dfd2582b80a15689ea433c0e35 \ 173 | --hash=sha256:a325600c83e61e3c9cebc0c2b1c8c4140fa887f789085075e8f44c8ff2547eb9 \ 174 | --hash=sha256:48d5bc80ab0af6b60c4163c5617f5cd23f2f880d7600940870ea5055816af024 \ 175 | --hash=sha256:c5cab230e7cabdae9ff23c12271231283efefb944c1b79bed79a91beb65ba547 \ 176 | --hash=sha256:d73e10772152605f6648ba4410318594f1043bbfe36d2fadee7c4b8912eff7c5 \ 177 | --hash=sha256:b1c4874331ab960429caca81acb9d2932170d66d6d6f87e65dc4507a85aca152 \ 178 | --hash=sha256:a3566acfbcde46911c52810374ecc0354fdb841284a3efef6ff7105bc007e9a8 \ 179 | --hash=sha256:b3b5b3cbc3fdf4fcfa292529df2a85b5d9c7053913a739d3069af1e12e12219f \ 180 | --hash=sha256:fd3854148005c808c485c754a184c71116372263709958b42aefbef2e5dd373a \ 181 | --hash=sha256:f55c1ddcc1f6050b07d468ce594f55dbf6107b459e16f735d26818d7be1e9538 \ 182 | --hash=sha256:ced944dcdd561476deef7cb7bfd4987c69fffbfeff6d02ca4d5d4fd592d559b7 \ 183 | --hash=sha256:78ecb8d42f50d393af912bfb1fb1dcc9aabe9967973efb49ee577e8f1cea494c \ 184 | --hash=sha256:1970cfe2aec1bf74b40cf30c130ad10cd968941694630386db33e1d044c22a2e \ 185 | --hash=sha256:b8bf42d3b32f586f4c9e37541769993783a534ad35531ce8a4379f6fa664fba9 \ 186 | --hash=sha256:bc9ac81e73573516070d24ce15da91281922811f385645df32bd3c8a45ab4684 \ 187 | --hash=sha256:d04ca462cb99077e6c059e97c072957caf2918e6e4191e3161c01c439e0193de \ 188 | --hash=sha256:f2acf9bbcd514e901f82c4ca6926bbd2ae61716728f110b4343eb0a69612d018 \ 189 | --hash=sha256:b754240daafecd9d5fce426b0fbaaed03f4ebb130745c8a4ae9231fffb8d75e5 \ 190 | --hash=sha256:af586e85144023686fb0af09c8cdf672484ea182f352e7ceead3d832de381e1b \ 191 | --hash=sha256:fe5872ce6f9627deac8314bdffd3862624227c3de4c17ef0cc78bbf0402999eb \ 192 | --hash=sha256:f6977a520bd96e097c8a37a8cbb9faa1ea99d21bf84190195056e25f688af73d \ 193 | --hash=sha256:2dbfbbded947a83a3dffc2bd1ec4750c17e40904692186e2c55a3ad314ca0222 \ 194 | --hash=sha256:a752ecd1a26000a6d67be7c9a2e93801994a8b3f866ac95b672fbc00225ca91a \ 195 | --hash=sha256:1bab889ae7640eba739f67fcbf8eff252dddc60d4495e6ddd3a87cd9a95fdb52 \ 196 | --hash=sha256:f94c7d22fb36b184734dded7345a04ec5f95130421c775b8b0c65044ef073f34 \ 197 | --hash=sha256:ec5ca7c0007ce268048bbe0ffc6846ed1616cf3d8628b136e81d5e64ff3f52a2 \ 198 | --hash=sha256:7c72d08acdf573455b2b9d2b75b8237654841d63a48bc2327dc102c6ee89b75a \ 199 | --hash=sha256:b6ea08758b6673610b3c5bdf47189286cf9c58b1077558706a2f6f8744922527 \ 200 | --hash=sha256:46d5ec90276f71af3a29917b30f2aec2315a2759b5f8d45b3b63a07ca8a070a3 \ 201 | --hash=sha256:625befa3bc9b40746a749115cc6a15bf20b9bd7597ca55d646205b479a2c99c7 \ 202 | --hash=sha256:d1131562ddc2ea8a446f66c2648d7dabec2b3816fc818528eb978a75a6d23b2e \ 203 | --hash=sha256:eee42a1cc06565f6b21caa1f504ec15e07de7ebfd520ab57f8cb3308bc118e22 \ 204 | --hash=sha256:94d38eba4d1b5eb3e6bfece0651b855a35c44f32fd91f512ab4ba41b8c0d3e66 \ 205 | --hash=sha256:e018a4921657c2d3f89c720b7b90b9182e277178a04a7e9542cc79d7d787ca51 \ 206 | --hash=sha256:7c6a9948916a7bbcc6d3a9f6fb75db1acb5546078023bfb3db6efabcd5a67527 \ 207 | --hash=sha256:e9faf8d4712d5ea301d74abfcf6dafe4b7f4af7936e91f283b0ad7bf69ed3e3a \ 208 | --hash=sha256:cc2894fe91f31a513860238ede69fe47fada21f9e7ddfe73f7f9fef93a971e41 \ 209 | --hash=sha256:053b4ebf91c7395d1fcd2ce6a9edff0024575b7b2de6781554a4114448a8adc9 \ 210 | --hash=sha256:39dafa2eaf577d1969f289dc9a44501859a1897eb45bd589e93ce843fc610800 \ 211 | --hash=sha256:246ec420e4c8744fceb4e259f906211b9c198e1f345e6158dcd7cbad3737e11e \ 212 | --hash=sha256:208debdcf76ed39ebf24f38509f50dc1c100e31e8653817fedb8e1f867850a13 \ 213 | --hash=sha256:18290649759f9db660972442aa606f845c368db9b08c4c73770f6da14113569b \ 214 | --hash=sha256:657ad80de8ec9ed656f28844efc801a0802961e8c6a85038d97ff6f555ef4919 \ 215 | --hash=sha256:b772bab31cbd9cb911e41e1a611ebc9497f9a32a7348e2747c38210f75c00f41 \ 216 | --hash=sha256:2399a85b54f68008e483b2871f4a458b4c980469c7fe921595ede073e4844f1e \ 217 | --hash=sha256:6e66780f14c2efaf989cd3ac613b03ee6a8e3a0ba7b96c0bb14adca71a427e55 \ 218 | --hash=sha256:02dc0b0f48ed3cd06c13b7e31b066bf91e00dac5f8147b0a0a45f9009bfab857 \ 219 | --hash=sha256:070a4ef689c9438a999ec3830e69b208ff0d12251846e064d947f97d819d1d05 \ 220 | --hash=sha256:db93608a246da44d728842b8fa9e45aa9782db76955f634a707739a8d53ff544 \ 221 | --hash=sha256:5af390fa9faf56c93252dab09ea57cd020c9123aa921b63a0ed51832fdb492e7 \ 222 | --hash=sha256:a2239556ff7241584ce57be1facf25081669bb457a9e5cbe68cce4aae6567aa1 \ 223 | --hash=sha256:cda9e628b1315beec8341e8c04aac9a0b910650b05e0751e42e399d5694aeacb \ 224 | --hash=sha256:845a8b83798b2fb11b09928413cb32692866bfbc28830a433d9fa4c8c3720dd0 \ 225 | --hash=sha256:da8288bc4a7807c6715416deed1c57d94d5e03e93537889e002bf985be503f1a \ 226 | --hash=sha256:a9ba2a63777027b06b116e1ea8248e66fd1bedc2c644f93124b81a91ddbf6d88 \ 227 | --hash=sha256:9a13661681d17e43009bb3e85e837aa1ec5feeea1e3654682a01b8821940f8b3 \ 228 | --hash=sha256:6b89dc51206e4971c5568c797991eaaef5dc2a6118d67165858ad11752dba055 \ 229 | --hash=sha256:701e08457183da70ed96b35a6b43e6ba1df0b47c837b063cde39a1fbe1aeda81 \ 230 | --hash=sha256:e7a33322e08021c37e89cae8ff06327503e8a1719e97c69f32c31cbf6c30d72c \ 231 | --hash=sha256:dd1f49f949a658c4e8f81ed73f9aad25fcc7d4f62f767f591e749e30038c4e1d \ 232 | --hash=sha256:a6d055f01b83b1a4df8bb0c61983d3bdffa913764488910af3620e5c2450bf83 \ 233 | --hash=sha256:dd6ff2192f34bd622883c745a56f492b1c9ccd44e14953e8051c33024a2947d5 \ 234 | --hash=sha256:19d4bd0fc29aa405bb1781456c9cfff9fceabb68543741eb17234952dbc2bbb0 \ 235 | --hash=sha256:24f8aeec4d6b894a6128844e50ff423dd02462ee83addf503c598ee3a80ddf3d \ 236 | --hash=sha256:0b6055e0ef451ff73c93d0348d122a0750dddf323b9361de5835dac2f6cf7fc1 \ 237 | --hash=sha256:6261bee7c5abadeac7497f8f1c43e521da78dd13b0a2439f526a7b0fc3788824 \ 238 | --hash=sha256:2e92aa32300a0b5e4175caec7769f482b292769807024a86d674b3f19b8e3755 \ 239 | --hash=sha256:3ce83f17f641a62a4dfb0ba1b8a3c1ced7c842f511b5450d90c030c7828e3693 \ 240 | --hash=sha256:d1740776b70367277323fafb76bcf09753a5cc9824f5d705bac22a34ff3668ea \ 241 | --hash=sha256:b88d1742159bc93a078733f9789f563cef26f5e370eba810476a71aa98e5fbc2 242 | python-jose==3.3.0 \ 243 | --hash=sha256:55779b5e6ad599c6336191246e95eb2293a9ddebd555f796a65f838f07e5d78a \ 244 | --hash=sha256:9b1376b023f8b298536eedd47ae1089bcdb848f1535ab30555cd92002d78923a 245 | pyyaml==5.4.1; (python_version >= "2.7" and python_full_version < "3.0.0") or (python_full_version >= "3.6.0") \ 246 | --hash=sha256:3b2b1824fe7112845700f815ff6a489360226a5609b96ec2190a45e62a9fc922 \ 247 | --hash=sha256:129def1b7c1bf22faffd67b8f3724645203b79d8f4cc81f674654d9902cb4393 \ 248 | --hash=sha256:4465124ef1b18d9ace298060f4eccc64b0850899ac4ac53294547536533800c8 \ 249 | --hash=sha256:bb4191dfc9306777bc594117aee052446b3fa88737cd13b7188d0e7aa8162185 \ 250 | --hash=sha256:6c78645d400265a062508ae399b60b8c167bf003db364ecb26dcab2bda048253 \ 251 | --hash=sha256:4e0583d24c881e14342eaf4ec5fbc97f934b999a6828693a99157fde912540cc \ 252 | --hash=sha256:72a01f726a9c7851ca9bfad6fd09ca4e090a023c00945ea05ba1638c09dc3347 \ 253 | --hash=sha256:895f61ef02e8fed38159bb70f7e100e00f471eae2bc838cd0f4ebb21e28f8541 \ 254 | --hash=sha256:3bd0e463264cf257d1ffd2e40223b197271046d09dadf73a0fe82b9c1fc385a5 \ 255 | --hash=sha256:e4fac90784481d221a8e4b1162afa7c47ed953be40d31ab4629ae917510051df \ 256 | --hash=sha256:5accb17103e43963b80e6f837831f38d314a0495500067cb25afab2e8d7a4018 \ 257 | --hash=sha256:e1d4970ea66be07ae37a3c2e48b5ec63f7ba6804bdddfdbd3cfd954d25a82e63 \ 258 | --hash=sha256:cb333c16912324fd5f769fff6bc5de372e9e7a202247b48870bc251ed40239aa \ 259 | --hash=sha256:fe69978f3f768926cfa37b867e3843918e012cf83f680806599ddce33c2c68b0 \ 260 | --hash=sha256:dd5de0646207f053eb0d6c74ae45ba98c3395a571a2891858e87df7c9b9bd51b \ 261 | --hash=sha256:08682f6b72c722394747bddaf0aa62277e02557c0fd1c42cb853016a38f8dedf \ 262 | --hash=sha256:d2d9808ea7b4af864f35ea216be506ecec180628aced0704e34aca0b040ffe46 \ 263 | --hash=sha256:8c1be557ee92a20f184922c7b6424e8ab6691788e6d86137c5d93c1a6ec1b8fb \ 264 | --hash=sha256:fd7f6999a8070df521b6384004ef42833b9bd62cfee11a09bda1079b4b704247 \ 265 | --hash=sha256:bfb51918d4ff3d77c1c856a9699f8492c612cde32fd3bcd344af9be34999bfdc \ 266 | --hash=sha256:fa5ae20527d8e831e8230cbffd9f8fe952815b2b7dae6ffec25318803a7528fc \ 267 | --hash=sha256:0f5f5786c0e09baddcd8b4b45f20a7b5d61a7e7e99846e3c799b05c7c53fa696 \ 268 | --hash=sha256:294db365efa064d00b8d1ef65d8ea2c3426ac366c0c4368d930bf1c5fb497f77 \ 269 | --hash=sha256:74c1485f7707cf707a7aef42ef6322b8f97921bd89be2ab6317fd782c2d53183 \ 270 | --hash=sha256:d483ad4e639292c90170eb6f7783ad19490e7a8defb3e46f97dfe4bacae89122 \ 271 | --hash=sha256:fdc842473cd33f45ff6bce46aea678a54e3d21f1b61a7750ce3c498eedfe25d6 \ 272 | --hash=sha256:49d4cdd9065b9b6e206d0595fee27a96b5dd22618e7520c33204a4a3239d5b10 \ 273 | --hash=sha256:c20cfa2d49991c8b4147af39859b167664f2ad4561704ee74c1de03318e898db \ 274 | --hash=sha256:607774cbba28732bfa802b54baa7484215f530991055bb562efbed5b2f20a45e 275 | rsa==4.7.2; python_version >= "3.5" and python_version < "4" \ 276 | --hash=sha256:78f9a9bf4e7be0c5ded4583326e7461e3a3c5aae24073648b4bdfa797d78c9d2 \ 277 | --hash=sha256:9d689e6ca1b3038bc82bf8d23e944b6b6037bc02301a574935b2dd946e0353b9 278 | six==1.16.0; python_version >= "3.6" and python_full_version < "3.0.0" or python_version >= "3.6" and python_full_version >= "3.3.0" \ 279 | --hash=sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254 \ 280 | --hash=sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926 281 | starlette==0.14.2; python_version >= "3.6" \ 282 | --hash=sha256:3c8e48e52736b3161e34c9f0e8153b4f32ec5d8995a3ee1d59410d92f75162ed \ 283 | --hash=sha256:7d49f4a27f8742262ef1470608c59ddbc66baf37c148e938c7038e6bc7a998aa 284 | typing-extensions==3.10.0.0; python_full_version >= "3.6.1" and python_version >= "3.6" \ 285 | --hash=sha256:0ac0f89795dd19de6b97debb0c6af1c70987fd80a2d62d1958f7e56fcc31b497 \ 286 | --hash=sha256:779383f6086d90c99ae41cf0ff39aac8a7937a9283ce0a414e5dd782f4c94a84 \ 287 | --hash=sha256:50b6f157849174217d0656f99dc82fe932884fb250826c18350e159ec6cdf342 288 | uvicorn==0.15.0 \ 289 | --hash=sha256:17f898c64c71a2640514d4089da2689e5db1ce5d4086c2d53699bf99513421c1 \ 290 | --hash=sha256:d9a3c0dd1ca86728d3e235182683b4cf94cd53a867c288eaeca80ee781b2caff 291 | win32-setctime==1.0.3; sys_platform == "win32" and python_version >= "3.5" \ 292 | --hash=sha256:dc925662de0a6eb987f0b01f599c01a8236cb8c62831c22d9cada09ad958243e \ 293 | --hash=sha256:4e88556c32fdf47f64165a2180ba4552f8bb32c1103a2fafd05723a0bd42bd4b 294 | -------------------------------------------------------------------------------- /service1/__init__.py: -------------------------------------------------------------------------------- 1 | from fastapi import FastAPI, Request 2 | from loguru import logger 3 | from motor import motor_asyncio 4 | from fastapi.middleware.cors import CORSMiddleware 5 | from starlette.routing import Match 6 | 7 | import yaml 8 | import secrets 9 | import sys 10 | 11 | from .service import UserService 12 | 13 | VERSION = "1.0" 14 | 15 | config = yaml.safe_load(open("config.yaml", "r")) 16 | 17 | logger.add("backend.log", rotation="1 week") 18 | # jwt_secret = secrets.token_hex(32) 19 | 20 | try: 21 | motor = motor_asyncio.AsyncIOMotorClient(config["core"]["mongodb_url"]) 22 | db = motor[config["core"]["mongodb_db"]] 23 | jwt_algorithm = config["jwt"]["algorithm"] 24 | jwt_expire = config["jwt"]["expire"] 25 | username = config["email"]["username"] 26 | password = config["email"]["password"] 27 | smtp_server = config["email"]["smtp"] 28 | port = config["email"]["port"] 29 | jwt_secret = config["jwt"]["secret"] 30 | except KeyError as e: 31 | logger.error(f"{e}") 32 | sys.exit(1) 33 | 34 | user_service = UserService(db.users) 35 | 36 | app = FastAPI(title="Service 1 Backend", version=VERSION) 37 | app.add_middleware( 38 | CORSMiddleware, 39 | allow_origins=["*"], 40 | allow_methods=["*"], 41 | allow_headers=["*"], 42 | ) 43 | 44 | from .routes import auth, main # noqa: E402 45 | 46 | app.include_router(router=main.router) 47 | app.include_router(router=auth.router) 48 | 49 | 50 | # https://stackoverflow.com/a/63413392 51 | @app.middleware("http") 52 | async def log_middle(request: Request, call_next): 53 | logger.debug(f"{request.method} {request.url}") 54 | routes = request.app.router.routes 55 | logger.debug("Params:") 56 | for route in routes: 57 | match, scope = route.matches(request) 58 | if match == Match.FULL: 59 | for name, value in scope["path_params"].items(): 60 | logger.debug(f"\t{name}: {value}") 61 | # logger.debug("Headers:") 62 | # for name, value in request.headers.items(): 63 | # logger.debug(f"\t{name}: {value}") 64 | 65 | response = await call_next(request) 66 | return response 67 | -------------------------------------------------------------------------------- /service1/helpers/helpers.py: -------------------------------------------------------------------------------- 1 | import uuid 2 | from pydantic import BaseModel 3 | from loguru import logger 4 | from typing import Type, TypeVar 5 | from passlib.context import CryptContext 6 | from datetime import datetime, timedelta 7 | from jose import JWTError, jwt 8 | 9 | 10 | Model = TypeVar("Model", bound=BaseModel) 11 | pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") 12 | 13 | 14 | # https://gist.github.com/henriklindgren/f0f05034ac4b36eafdb7c877e5088f33 15 | def load_model(t: Type[Model], o: dict) -> Model: 16 | populated_keys = o.keys() 17 | required_keys = set(t.schema()["required"]) 18 | missing_keys = required_keys.difference(populated_keys) 19 | if missing_keys: 20 | raise ValueError(f"Required keys missing: {missing_keys}") 21 | all_definition_keys = t.schema()["properties"].keys() 22 | return t(**{k: v for k, v in o.items() if k in all_definition_keys}) 23 | 24 | 25 | def hash_password(password) -> str: 26 | return pwd_context.hash(password) 27 | 28 | 29 | def check_password(hashed_password, plain_password) -> bool: 30 | return pwd_context.verify(plain_password, hashed_password) 31 | 32 | 33 | def create_access_token(data: dict, jwt_expire: int, jwt_secret: str, jwt_algorithm: str) -> dict: 34 | to_encode = data.copy() 35 | expire = datetime.utcnow() + timedelta(minutes=jwt_expire) 36 | to_encode.update({"exp": expire}) 37 | return jwt.encode(to_encode, jwt_secret, algorithm=jwt_algorithm) 38 | 39 | 40 | def verify_access_token(access_token: str, jwt_secret: str, jwt_algorithm: str) -> dict: 41 | try: 42 | return jwt.decode( 43 | access_token, jwt_secret, algorithms=[jwt_algorithm]) 44 | except JWTError as e: 45 | raise JWTError(f"Invalid token: {e}") 46 | 47 | 48 | async def refresh_session(jwt_expire: int, jwt_secret: str, jwt_algorithm: str, decoded_token: dict, user_service: object) -> dict: 49 | if decoded_token["exp"] < datetime.utcnow().timestamp(): 50 | token = decoded_token["token"] 51 | new_token = uuid.uuid4().hex 52 | await user_service.refresh_session(token, new_token) 53 | return create_access_token( 54 | data={"token": new_token}, 55 | jwt_expire=jwt_expire, 56 | jwt_secret=jwt_secret, 57 | jwt_algorithm=jwt_algorithm 58 | ) 59 | -------------------------------------------------------------------------------- /service1/main.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnelle/python_jwt_example_fastapi/813f6ae946535cbf30bfcbd7837a5e71aa899bd8/service1/main.py -------------------------------------------------------------------------------- /service1/models/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnelle/python_jwt_example_fastapi/813f6ae946535cbf30bfcbd7837a5e71aa899bd8/service1/models/__init__.py -------------------------------------------------------------------------------- /service1/models/auth.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | from pydantic import BaseModel 3 | 4 | 5 | class UserModel(BaseModel): 6 | name: str 7 | level: int 8 | token: str 9 | password: str 10 | email: str 11 | reg_time: float 12 | payment_method: Optional[str] 13 | 14 | 15 | class LoginUserModel(BaseModel): 16 | email: str 17 | password: str 18 | 19 | 20 | class AddUserModel(BaseModel): 21 | email: str 22 | name: str 23 | level: int 24 | password: str 25 | 26 | 27 | class AddUserRequest(BaseModel): 28 | user: AddUserModel 29 | token: str 30 | 31 | class TokenModel(BaseModel): 32 | access_token: str 33 | token_type: str 34 | message: Optional[str] 35 | -------------------------------------------------------------------------------- /service1/models/common.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | from pydantic import BaseModel 3 | 4 | 5 | class APIResponse(BaseModel): 6 | status: Optional[int] 7 | message: str 8 | -------------------------------------------------------------------------------- /service1/routes/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jnelle/python_jwt_example_fastapi/813f6ae946535cbf30bfcbd7837a5e71aa899bd8/service1/routes/__init__.py -------------------------------------------------------------------------------- /service1/routes/auth.py: -------------------------------------------------------------------------------- 1 | import time 2 | import uuid 3 | 4 | from loguru import logger 5 | from fastapi import APIRouter, status, Response 6 | 7 | from .. import user_service, jwt_expire, jwt_secret, jwt_algorithm 8 | from service1.helpers.helpers import check_password, create_access_token, hash_password, refresh_session, verify_access_token 9 | from ..models.auth import AddUserRequest, LoginUserModel, TokenModel, UserModel 10 | from ..models.common import APIResponse 11 | 12 | 13 | router = APIRouter(prefix="/auth") 14 | 15 | 16 | @logger.catch 17 | @router.post("/login") 18 | async def login(request: LoginUserModel, response: Response) -> APIResponse: 19 | """ 20 | email: String (required)\n 21 | password: String (required) 22 | """ 23 | user = await user_service.get_by_email(request.email) 24 | 25 | if not user: 26 | response.status_code = status.HTTP_404_NOT_FOUND 27 | return APIResponse(message="USER_NOT_FOUND") 28 | else: 29 | if check_password(user.password, request.password): 30 | access_token = create_access_token( 31 | data={"token": user.token}, jwt_expire=jwt_expire, jwt_secret=jwt_secret, jwt_algorithm=jwt_algorithm) 32 | response.status_code = status.HTTP_200_OK 33 | return TokenModel(access_token=access_token, token_type="bearer") 34 | 35 | else: 36 | response.status_code = status.HTTP_401_UNAUTHORIZED 37 | return APIResponse(message="INVALID_CREDENTAILS") 38 | 39 | 40 | @logger.catch 41 | @router.post("/add_user") 42 | async def add_user(request: AddUserRequest, response: Response) -> APIResponse: 43 | 44 | decoded_jwt = verify_access_token(request.token, jwt_secret, jwt_algorithm) 45 | 46 | if decoded_jwt: 47 | request_user = await user_service.get_by_token(decoded_jwt["token"]) 48 | if not request_user: 49 | response.status_code = status.HTTP_401_UNAUTHORIZED 50 | return APIResponse(message="INVALID_TOKEN") 51 | else: 52 | if request_user.level == 1 or ( 53 | request_user.level == 2 and request.user.level > 1 54 | ): 55 | response.status_code = status.HTTP_403_FORBIDDEN 56 | return APIResponse(message="NOT_ENOUGH_PERMISSION") 57 | 58 | try: 59 | await user_service.add(UserModel( 60 | name=request.user.name, 61 | email=request.user.email, 62 | password=hash_password(request.user.password), 63 | level=request_user.level, # user level 64 | token=uuid.uuid4().hex, 65 | reg_time=time.time(), 66 | )) 67 | except: 68 | response.status_code = status.HTTP_409_CONFLICT 69 | return APIResponse(message="EMAIL_OR_USERNAME_EXISTS") 70 | 71 | response.status_code = status.HTTP_200_OK 72 | access_token = await refresh_session( 73 | decoded_token=decoded_jwt, jwt_secret=jwt_secret, jwt_algorithm=jwt_algorithm, jwt_expire=jwt_expire, user_service=user_service) 74 | if not access_token: 75 | access_token = request.token 76 | return TokenModel(access_token=access_token, token_type="bearer", message="SUCCESS") 77 | -------------------------------------------------------------------------------- /service1/routes/main.py: -------------------------------------------------------------------------------- 1 | from loguru import logger 2 | from fastapi import APIRouter 3 | 4 | from ..models.common import APIResponse 5 | 6 | router = APIRouter() 7 | 8 | 9 | @logger.catch 10 | @router.get("/") 11 | async def main_page(): 12 | """Main page. Just for example.""" 13 | 14 | return APIResponse(message="ok") 15 | -------------------------------------------------------------------------------- /service1/service/__init__.py: -------------------------------------------------------------------------------- 1 | from .user import UserService 2 | -------------------------------------------------------------------------------- /service1/service/mail.py: -------------------------------------------------------------------------------- 1 | # flake8: noqa: E501 2 | import smtplib 3 | 4 | from loguru import logger 5 | from email.mime.text import MIMEText 6 | from email.mime.multipart import MIMEMultipart 7 | from jinja2 import Environment, FileSystemLoader 8 | 9 | 10 | class SendMail: 11 | def __init__(self, username, password, port, smtp_server): 12 | self.username = username 13 | self.password = password 14 | self.port = port 15 | self.smtp_server = smtp_server 16 | 17 | def send_mail(self, receiver_email, subject): 18 | msg = MIMEMultipart("alternative") 19 | msg["From"] = self.username 20 | msg["To"] = receiver_email 21 | msg["Subject"] = subject 22 | # TODO: Add template 23 | # templates_env = Environment(loader=FileSystemLoader(searchpath="service1/templates")) 24 | # template = templates_env.get_template('email.html') 25 | # html = template.render(button_href=button_href, button_text=button_text, 26 | # sent_message=sent_message, user_name=user_name) 27 | 28 | mime_text = MIMEText("Lorem ip.", "html") 29 | msg.attach(mime_text) 30 | 31 | try: 32 | server = smtplib.SMTP_SSL(self.smtp_server, self.port) 33 | server.login(self.username, self.password) 34 | server.sendmail(self.username, receiver_email, msg.as_string()) 35 | server.quit() 36 | logger.info(f"Mail sent to {receiver_email}") 37 | except Exception as e: 38 | logger.error(f"Mail not sent to {receiver_email}") 39 | logger.error(e) 40 | -------------------------------------------------------------------------------- /service1/service/user.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from service1.helpers.helpers import load_model 4 | from service1.models.auth import UserModel 5 | 6 | 7 | class UserService: 8 | def __init__(self, collection) -> None: 9 | self.collection = collection 10 | 11 | async def get_by_email(self, email: str) -> Optional[UserModel]: 12 | user = await self.collection.find_one({"email": email}) 13 | if user: 14 | return load_model(UserModel, user) 15 | 16 | async def get_by_token(self, token: str) -> Optional[UserModel]: 17 | user = await self.collection.find_one({"token": token}) 18 | if user: 19 | return load_model(UserModel, user) 20 | 21 | async def add(self, user: UserModel): 22 | await self.collection.insert_one(user.dict()) 23 | 24 | async def refresh_session(self, token: str, new_token: str) -> None: 25 | user = await self.collection.find_one({"token": token}) 26 | user["token"] = new_token 27 | await self.collection.update_one({"token": token}, {"$set": user}) 28 | --------------------------------------------------------------------------------