Skip to content

Commit 3a728a6

Browse files
committed
feat: add Python3.12 tenants
1 parent 76c1373 commit 3a728a6

22 files changed

Lines changed: 910 additions & 23 deletions

.github/workflows/filter-lib.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ on:
44
push:
55
paths:
66
- lib/filter_lib/**
7+
- lib/python3.12/filter_lib/**
78
- .github/worlflows/filter-lib.yml
89
pull_request:
910
paths:
1011
- lib/filter_lib/**
12+
- lib/python3.12/filter_lib/**
1113
- .github/worlflows/filter-lib.yml
1214
jobs:
1315
filter-lib-pre-commit-actions:

.github/workflows/python3.12/filter-lib renamed to .github/workflows/python_3.12_filter-lib.yml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
filter-lib-pre-commit-actions:
1414
strategy:
1515
matrix:
16-
python-version: [ "3.12.1" ]
16+
python-version: [ "3.12.0", "3.12.1" ]
1717
runs-on: ubuntu-latest
1818
steps:
1919
- uses: actions/checkout@v3
@@ -41,7 +41,7 @@ jobs:
4141
runs-on: ubuntu-latest
4242
strategy:
4343
matrix:
44-
python-version: [ "3.12.1" ]
44+
python-version: [ "3.12.0", "3.12.1" ]
4545
steps:
4646
- uses: actions/checkout@v3
4747
- name: Set up Python ${{ matrix.python-version }}
@@ -53,10 +53,8 @@ jobs:
5353
run: |
5454
python -m pip install --upgrade pip
5555
cd lib/python3.12/filter_lib
56-
pip install -r requirements.txt
57-
pip install -r requirements-dev.txt
56+
pip install ".[dev]"
5857
- name: Test with pytest
5958
run: |
6059
cd lib/python3.12/filter_lib
6160
pytest
62-
Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
1-
name: filter_lib precommit and test
2-
run-name: filter_lib precommit and test
1+
name: tenants precommit and test
2+
run-name: tenants precommit and test
33
on:
44
push:
55
paths:
6-
- lib/python3.12/filter_lib/**
7-
- .github/worlflows/python3.12/filter-lib.yml
6+
- lib/python3.12/tenants/**
7+
- .github/worlflows/python3.12/tenants.yml
88
pull_request:
99
paths:
10-
- lib/python3.12/filter_lib/**
11-
- .github/worlflows/python3.12/filter-lib.yml
10+
- lib/python3.12/tenants/**
11+
- .github/worlflows/python3.12/tenants.yml
1212
jobs:
13-
filter-lib-pre-commit-actions:
13+
tenants-pre-commit-actions:
1414
strategy:
1515
matrix:
16-
python-version: [ "3.12.1" ]
16+
python-version: [ "3.12.0", "3.12.1" ]
1717
runs-on: ubuntu-latest
1818
steps:
1919
- uses: actions/checkout@v3
@@ -24,7 +24,7 @@ jobs:
2424
- name: Run isort
2525
uses: isort/isort-action@v1.1.0
2626
with:
27-
sort-paths: lib/python3.12/filter_lib/*
27+
sort-paths: lib/python3.12/tenants/*
2828
configuration:
2929
--check-only
3030
--profile=black
@@ -33,15 +33,15 @@ jobs:
3333
- name: Black
3434
uses: psf/black@stable
3535
with:
36-
src: "lib/python3.12/filter_lib"
36+
src: "lib/python3.12/tenants"
3737
options: '--check --line-length=79 --exclude="tests" --verbose'
3838
- run: pip install flake8
39-
- run: flake8 --exclude=tests --extend-ignore=E203 lib/python3.12/filter_lib
40-
filter-lib-build:
39+
- run: flake8 --exclude=tests --extend-ignore=E203 lib/python3.12/tenants
40+
tenants-build:
4141
runs-on: ubuntu-latest
4242
strategy:
4343
matrix:
44-
python-version: [ "3.12.1" ]
44+
python-version: [ "3.12.0", "3.12.1" ]
4545
steps:
4646
- uses: actions/checkout@v3
4747
- name: Set up Python ${{ matrix.python-version }}
@@ -52,11 +52,9 @@ jobs:
5252
- name: Install dependencies
5353
run: |
5454
python -m pip install --upgrade pip
55-
cd lib/python3.12/filter_lib
56-
pip install -r requirements.txt
57-
pip install -r requirements-dev.txt
55+
cd lib/python3.12/tenants
56+
pip install ".[dev]"
5857
- name: Test with pytest
5958
run: |
60-
cd lib/python3.12/filter_lib
59+
cd lib/python3.12/tenants
6160
pytest
62-

lib/python3.12/tenants/.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/venv/
2+
/.pytest_cache/
3+
/.mypy_cache/
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
repos:
2+
- repo: https://github.com/pre-commit/pre-commit-hooks
3+
rev: v4.0.1
4+
hooks:
5+
- id: trailing-whitespace
6+
- id: end-of-file-fixer
7+
- id: check-yaml
8+
- repo: https://github.com/pycqa/isort
9+
rev: 5.9.1
10+
hooks:
11+
- id: isort
12+
args:
13+
- --profile=black
14+
- --line-length=79
15+
exclude: tests/
16+
- repo: https://github.com/psf/black
17+
rev: 21.6b0
18+
hooks:
19+
- id: black
20+
language_version: python3
21+
args:
22+
- --line-length=79
23+
- repo: https://github.com/pre-commit/mirrors-mypy
24+
rev: v0.910
25+
hooks:
26+
- id: mypy
27+
name: mypy
28+
entry: mypy
29+
language: python
30+
types: [python]
31+
args:
32+
- --ignore-missing-imports
33+
- --scripts-are-modules
34+
- --allow-untyped-decorators
35+
- --strict
36+
- --no-strict-optional
37+
require_serial: true
38+
exclude: tests/
39+
additional_dependencies:
40+
- 'pydantic'
41+
- repo: https://github.com/pycqa/pylint
42+
rev: pylint-2.8.1
43+
hooks:
44+
- id: pylint
45+
types: [ python ]
46+
args:
47+
- --max-line-length=79
48+
- --errors-only
49+
- --disable=E0401,E0611

lib/python3.12/tenants/README.md

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
## How to use with BadgerDoc
2+
3+
Import and create an instance of tenant dependency.
4+
To make this dependency work with BadgerDoc you need to provide an url to keycloak and set 'algorithm' arg to `RS256`.
5+
6+
```Python
7+
from tenant_dependency import TenantData, get_tenant_info
8+
9+
# inner url would look like this "http://badgerdoc-keycloak" (http://{keycloak_pod_name})
10+
# outer url would look like this "http://dev1.gcov.ru"
11+
12+
tenant = get_tenant_info(url="http://dev1.gcov.ru", algorithm="RS256", debug=True)
13+
```
14+
## Note:
15+
#### If you're using algorithm RS256 (Current BadgerDoc algorithm) you don't need arg "key", use only "url".
16+
#### Otherwise, if you're using algorithm HS256, you need "key" arg and don't need "url". Check `usage_example/main.py`.
17+
Param `debug` is needed to render `Authorize` button in `/openapi` docs.
18+
19+
Now you can add this dependency to your FastAPI endpoint:
20+
21+
```Python
22+
from fastapi import Depends, FastAPI
23+
from tenant_dependency import TenantData, get_tenant_info
24+
25+
app = FastAPI()
26+
tenant = get_tenant_info(url="http://dev1.gcov.ru", algorithm="RS256", debug=True)
27+
28+
29+
@app.post("/test")
30+
async def get_nums(token: TenantData = Depends(tenant)):
31+
return token.dict()
32+
```
33+
Default values for `algorithm` and `debug` is `RS256` and `True`,
34+
so you can create an instance like that:
35+
```Python
36+
tenant = get_tenant_info(url="http://dev1.gcov.ru")
37+
```
38+
39+
40+
Go to docs and check how it works.
41+
42+
1) Click `Authorize` and submit token.
43+
2) Try to use endpoint.
44+
45+
Without valid jwt this endpoint `/test` will raise 401 Error.
46+
47+
48+
```Python
49+
@app.post("/test")
50+
async def get_nums(token: TenantData = Depends(tenant)):
51+
return token.dict()
52+
```
53+
This dependency will:
54+
1) Check if incoming request came with header `Authorization`, if that header wasn't provided Error 401 will be raised.
55+
2) If header `Authorization` exists, dependency will try to validate it with signature key or url those you put as args to dependency `tenant = get_tenant_info(key="SECRET") / tenant = get_tenant_info(url="http://bagerdoc-keycloack")`. If is key invalid or token is expired 401 Error will be raised.
56+
3) It also checks header for arg "X-Current-Tenant", so if that arg isn't provided 401 will be raised. In case "X-Current-Tenant" provided dependency will check "X-Current-Tenant" containing in `tenants` array. Raises 401 if check wasn't successful.
57+
4) If token is valid dependency will parse token's body and get data from it. Token must contain data about `tenants`, `user_id` and `roles`, otherwise 403 error will be raised.
58+
5) If previous steps were successful, your endpoint can do anything further, and you can work with `token` arg that is actually is a pydantic model, so you can work with it like you work with other pydantic models.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
[tool.black]
2+
line-length = 79
3+
4+
[tool.isort]
5+
profile = "black"
6+
line_length = 79
7+
8+
[tool.mypy]
9+
plugins = "pydantic.mypy"
10+
ignore_missing_imports = "True"
11+
scripts_are_modules = "True"
12+
allow_untyped_decorators = "True"
13+
strict = "True"
14+
no_strict_optional = "True"
15+
disallow_untyped_calls = "False"
16+
17+
[tool.pylint.basic]
18+
max-line-length=79
19+
errors-only = "True"
20+
disable = ["E0401", "E0611"]
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
pytest
2+
requests
3+
pytest-cov
4+
black
5+
isort==5.9.1
6+
pylint
7+
mypy==0.910
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fastapi>=0.68.0
2+
httpx
3+
PyJWT[crypto]==2.3.0

lib/python3.12/tenants/setup.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from typing import List
2+
3+
from setuptools import setup
4+
5+
6+
def get_requirements(path: str) -> List[str]:
7+
with open(path, "r", encoding="utf-8") as file:
8+
return [row.strip() for row in file.readlines()]
9+
10+
11+
def get_long_description(path: str) -> str:
12+
with open(path, "r", encoding="utf-8") as file:
13+
return file.read()
14+
15+
16+
setup(
17+
name="tenant_dependency",
18+
version="0.1.3",
19+
description="Package for validating and parsing jwt via FastAPI dependency", # noqa
20+
long_description=get_long_description("README.md"),
21+
author="Roman Kuzianov",
22+
author_email="Roman_Kuzianov@epam.com",
23+
packages=["tenant_dependency"],
24+
package_dir={"tenant_dependency": "src"},
25+
install_requires=get_requirements("requirements.txt"),
26+
extras_require={"dev": get_requirements("requirements-dev.txt")},
27+
)

0 commit comments

Comments
 (0)