Skip to content

Commit cc79b79

Browse files
authored
More customisation control in controller schemas (#26)
* refactored schema and gave them a more proper name * Added controller schemas to settings. For more dynamic support * Added schema_control helper functions and apply schemas to controller * removed ninja_schema dependency * removed ninja_schema dependency * Added some test for custom controller schema * fixed failing test * linting * added doc and some refactoring * added more test * check_authentication_fix
1 parent 42c5f44 commit cc79b79

17 files changed

+930
-161
lines changed

.pre-commit-config.yaml

Lines changed: 18 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,37 @@
11
repos:
22
- repo: https://github.com/pre-commit/pre-commit-hooks
3-
rev: 'v4.3.0'
3+
rev: v2.3.0
44
hooks:
55
- id: check-merge-conflict
66
- repo: https://github.com/asottile/yesqa
77
rev: v1.3.0
88
hooks:
99
- id: yesqa
10-
- repo: https://github.com/pycqa/isort
11-
rev: '5.10.1'
10+
- repo: local
1211
hooks:
13-
- id: isort
14-
args: ["--profile", "black"]
15-
- repo: https://github.com/psf/black
16-
rev: '22.6.0'
17-
hooks:
18-
- id: black
19-
language_version: python3 # Should be a command that runs python3.6+
12+
- id: code_formatting
13+
args: []
14+
name: Code Formatting
15+
entry: "make fmt"
16+
types: [python]
17+
language_version: python3.8
18+
language: python
19+
- id: code_linting
20+
args: [ ]
21+
name: Code Linting
22+
entry: "make lint"
23+
types: [ python ]
24+
language_version: python3.8
25+
language: python
2026
- repo: https://github.com/pre-commit/pre-commit-hooks
21-
rev: 'v4.3.0'
27+
rev: v2.3.0
2228
hooks:
2329
- id: end-of-file-fixer
2430
exclude: >-
25-
^docs/[^/]*\.svg$
31+
^examples/[^/]*\.svg$
2632
- id: requirements-txt-fixer
2733
- id: trailing-whitespace
2834
types: [python]
29-
- id: file-contents-sorter
30-
files: |
31-
CONTRIBUTORS.txt|
32-
docs/spelling_wordlist.txt|
33-
.gitignore|
34-
.gitattributes
3535
- id: check-case-conflict
3636
- id: check-json
3737
- id: check-xml
@@ -43,19 +43,4 @@ repos:
4343
- id: check-added-large-files
4444
- id: check-symlinks
4545
- id: debug-statements
46-
- id: detect-aws-credentials
47-
args: ['--allow-missing-credentials']
48-
- id: detect-private-key
4946
exclude: ^tests/
50-
- repo: https://github.com/asottile/pyupgrade
51-
rev: 'v2.37.1'
52-
hooks:
53-
- id: pyupgrade
54-
args: ['--py37-plus', '--keep-mock']
55-
56-
- repo: https://github.com/Lucas-C/pre-commit-hooks-markup
57-
rev: v1.0.1
58-
hooks:
59-
- id: rst-linter
60-
files: >-
61-
^[^/]+[.]rst$

Makefile

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ clean: ## Removing cached python compiled files
1111
find . -name __pycache__ | xargs rm -rfv
1212

1313
install: ## Install dependencies
14+
make clean
1415
flit install --deps develop --symlink
16+
pre-commit install -f
1517

1618
lint: ## Run code linters
1719
make clean
@@ -35,4 +37,8 @@ test-cov: ## Run tests with coverage
3537

3638
doc-deploy: ## Run Deploy Documentation
3739
make clean
38-
mkdocs gh-deploy --force
40+
mkdocs gh-deploy --force
41+
42+
doc-serve: ## Run Deploy Documentation
43+
make clean
44+
mkdocs serve

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ For full documentation, [visit](https://eadwincode.github.io/django-ninja-jwt/).
2020
- Python >= 3.6
2121
- Django >= 2.1
2222
- Django-Ninja >= 0.16.1
23-
- Ninja-Schema >= 0.12.8
2423
- Django-Ninja-Extra >= 0.14.2
2524

2625
## Example

docs/customizing_token_claims.md

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@ views, create a subclass for the desired controller as well as a subclass for
55
its corresponding serializer. Here\'s an example :
66

77
!!! info
8-
if you are interested in Asynchronous version of the class, checkout `AsyncNinjaJWTDefaultController` and `AsyncNinjaJWTSlidingController`
8+
if you are interested in Asynchronous version of the class, use `AsyncNinjaJWTDefaultController` and `AsyncNinjaJWTSlidingController`.
9+
Also note, it's only available for Django versions that supports asynchronous actions.
910

1011
```python
11-
from ninja_jwt.schema import TokenObtainPairSerializer
12+
from ninja_jwt.schema import TokenObtainPairInputSchema
1213
from ninja_jwt.controller import TokenObtainPairController
1314
from ninja_extra import api_controller, route
14-
from ninja_schema import Schema
15+
from ninja import Schema
1516

1617

1718
class UserSchema(Schema):
@@ -25,12 +26,13 @@ class MyTokenObtainPairOutSchema(Schema):
2526
user: UserSchema
2627

2728

28-
class MyTokenObtainPairSchema(TokenObtainPairSerializer):
29+
class MyTokenObtainPairSchema(TokenObtainPairInputSchema):
2930
def output_schema(self):
3031
out_dict = self.dict(exclude={"password"})
3132
out_dict.update(user=UserSchema.from_orm(self._user))
3233
return MyTokenObtainPairOutSchema(**out_dict)
3334

35+
3436
@api_controller('/token', tags=['Auth'])
3537
class MyTokenObtainPairController(TokenObtainPairController):
3638
@route.post(
@@ -49,7 +51,6 @@ Here is an example
4951

5052
```python
5153
from ninja import router
52-
from ninja_schema import Schema
5354

5455
router = router('/token')
5556

@@ -67,3 +68,67 @@ from ninja import NinjaAPI
6768
api = NinjaAPI()
6869
api.add_router('', tags=['Auth'], router=router)
6970
```
71+
72+
73+
### Controller Schema Swapping
74+
75+
You can now swap controller schema in `NINJA_JWT` settings without having to inherit or override Ninja JWT controller function.
76+
77+
All controller input schema must inherit from `ninja_jwt.schema.InputSchemaMixin` and token generating schema should inherit
78+
from `ninja_jwt.schema.TokenObtainInputSchemaBase` or `ninja_jwt.schema.TokenInputSchemaMixin` if you want to have more control.
79+
80+
Using the example above:
81+
82+
```python
83+
# project/schema.py
84+
from typing import Type, Dict
85+
from ninja_jwt.schema import TokenObtainInputSchemaBase
86+
from ninja import Schema
87+
from ninja_jwt.tokens import RefreshToken
88+
89+
class UserSchema(Schema):
90+
first_name: str
91+
email: str
92+
93+
94+
class MyTokenObtainPairOutSchema(Schema):
95+
refresh: str
96+
access: str
97+
user: UserSchema
98+
99+
100+
class MyTokenObtainPairInputSchema(TokenObtainInputSchemaBase):
101+
@classmethod
102+
def get_response_schema(cls) -> Type[Schema]:
103+
return MyTokenObtainPairOutSchema
104+
105+
@classmethod
106+
def get_token(cls, user) -> Dict:
107+
values = {}
108+
refresh = RefreshToken.for_user(user)
109+
values["refresh"] = str(refresh)
110+
values["access"] = str(refresh.access_token)
111+
values.update(user=UserSchema.from_orm(user)) # this will be needed when creating output schema
112+
return values
113+
```
114+
115+
In the `MyTokenObtainPairInputSchema` we override `get_token` to define our token and some data needed for our output schema.
116+
We also override `get_response_schema` to define our output schema `MyTokenObtainPairOutSchema`.
117+
118+
Next, we apply the `MyTokenObtainPairInputSchema` schema to controller. This is simply done in `NINJA_JWT` settings.
119+
120+
```python
121+
# project/settings.py
122+
123+
NINJA_JWT = {
124+
'TOKEN_OBTAIN_PAIR_INPUT_SCHEMA': 'project.schema.MyTokenObtainPairInputSchema',
125+
}
126+
```
127+
Other swappable schemas can be found in [settings](../settings)
128+
129+
![token_customization_git](./img/token_customize.gif)
130+
131+
!!! Note
132+
`Controller Schema Swapping` is only available from **v5.2.4**
133+
134+

docs/development_and_contributing.md

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,26 @@ To do development work for Ninja JWT, make your own fork on Github,
33
clone it locally, make and activate a virtualenv for it, then from
44
within the project directory:
55

6-
``` {.sourceCode .bash}
7-
make install
6+
After that, install flit
7+
8+
```shell
9+
$(venv) pip install flit
10+
```
11+
12+
Install development libraries and pre-commit hooks for code linting and styles
13+
14+
```shell
15+
$(venv) make install
816
```
917

1018
To run the tests:
1119

12-
``` {.sourceCode .bash}
13-
make test
20+
```shell
21+
$(venv) make test
1422
```
23+
1524
To run the tests with coverage:
1625

17-
``` {.sourceCode .bash}
18-
make test-cov
26+
```shell
27+
$(venv) make test-cov
1928
```

docs/getting_started.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
- Python >= 3.6
44
- Django >= 2.1
55
- Django-Ninja >= 0.16.1
6-
- Ninja-Schema >= 0.12.2
76
- Django-Ninja-Extra >= 0.11.0
87

98
These are the officially supported python and package versions. Other
@@ -12,7 +11,6 @@ see what is possible.
1211

1312
Installation
1413
============
15-
1614
Ninja JWT can be installed with pip:
1715

1816
pip install django-ninja-jwt
@@ -112,4 +110,4 @@ extra in the `django-ninja-jwt` requirement:
112110
The `django-ninja-jwt[crypto]` format is recommended in requirements
113111
files in projects using `Ninja JWT`, as a separate `cryptography` requirement
114112
line may later be mistaken for an unused requirement and removed.
115-
[cryptography](https://cryptography.io)
113+
[cryptography](https://cryptography.io)

docs/settings.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,17 @@ NINJA_JWT = {
3737
'SLIDING_TOKEN_REFRESH_EXP_CLAIM': 'refresh_exp',
3838
'SLIDING_TOKEN_LIFETIME': timedelta(minutes=5),
3939
'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1),
40+
41+
# For Controller Schemas
42+
# FOR OBTAIN PAIR
43+
'TOKEN_OBTAIN_PAIR_INPUT_SCHEMA': "ninja_jwt.schema.TokenObtainPairInputSchema",
44+
'TOKEN_OBTAIN_PAIR_REFRESH_INPUT_SCHEMA': "ninja_jwt.schema.TokenRefreshInputSchema",
45+
# FOR SLIDING TOKEN
46+
'TOKEN_OBTAIN_SLIDING_INPUT_SCHEMA': "ninja_jwt.schema.TokenObtainSlidingInputSchema",
47+
'TOKEN_OBTAIN_SLIDING_REFRESH_INPUT_SCHEMA':"ninja_jwt.schema.TokenRefreshSlidingInputSchema",
48+
49+
'TOKEN_BLACKLIST_INPUT_SCHEMA': "ninja_jwt.schema.TokenBlacklistInputSchema",
50+
'TOKEN_VERIFY_INPUT_SCHEMA': "ninja_jwt.schema.TokenVerifyInputSchema",
4051
}
4152
```
4253

@@ -247,4 +258,3 @@ More about this in the "Sliding tokens" section below.
247258

248259
The claim name that is used to store the expiration time of a sliding token's
249260
refresh period. More about this in the "Sliding tokens" section below.
250-

mkdocs.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ site_description: Django Ninja JWT - A Simple JWT plugin for Django-Ninja.
33
site_url: https://eadwincode.github.io/django-ninja-jwt/
44
repo_name: eadwinCode/django-ninja-jwt
55
repo_url: https://github.com/eadwinCode/django-ninja-jwt
6-
edit_uri: ''
6+
edit_uri: 'https://github.com/eadwinCode/django-ninja-jwt/docs'
77

88
theme:
99
name: material
@@ -44,3 +44,8 @@ nav:
4444
- Development and Contributing: development_and_contributing.md
4545
- Experimental Feature: experimental_features.md
4646
#- ninja_jwt package: index.md
47+
48+
markdown_extensions:
49+
- codehilite
50+
- admonition
51+
- pymdownx.superfences

ninja_jwt/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
"""Django Ninja JWT - JSON Web Token for Django-Ninja"""
22

3-
__version__ = "5.2.2"
3+
__version__ = "5.2.4"

0 commit comments

Comments
 (0)