Skip to content

Commit ad139de

Browse files
committed
Upgrade to Django 3.2 and a bunch of other enhancements to codestyle and organization.
1 parent e1fe062 commit ad139de

34 files changed

Lines changed: 792 additions & 752 deletions

README.md

Lines changed: 131 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,58 +4,50 @@ Django-based REST Micro-Framework
44

55
# Install requires
66

7-
```PHP
7+
```bash
88
pip install rinzler
99
```
1010

1111
# Usage
1212
```Python
13-
1413
# urls.py
15-
16-
import os
17-
import rinzler
14+
from rinzler import boot, Rinzler
1815

1916
from rinzler.core.main_controller import MainController
2017
from your_controller import Controller
2118

22-
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
2319

24-
app = rinzler.boot(BASE_DIR)
25-
assembler = app['url_assembler']
20+
app: Rinzler = boot("MyApp")
2621

2722
urlpatterns = [
28-
assembler.mount('hello', Controller),
29-
assembler.mount('', MainController),
23+
app.mount('hello', Controller),
24+
app.mount('', MainController),
3025
]
31-
3226
```
3327

3428
```Python
3529
# your_controller.py
36-
from collections import OrderedDict
37-
3830
from django.http.request import HttpRequest
39-
from django.views.generic import TemplateView
4031

32+
from rinzler import Rinzler
4133
from rinzler.core.response import Response
4234

4335

44-
class Controller(TemplateView):
36+
class Controller:
4537

4638
def connect(self, app):
4739

48-
router = app['router']
40+
router = app.get_end_point_register()
4941

5042
# map end-points to callbacks here
5143
router.get('/world/', self.hello_world)
5244
router.get('/{name}/', self.hello_user)
5345

54-
return app
46+
return router
5547

5648
# end-point callbacks here:
5749
@staticmethod
58-
def hello_world(request: HttpRequest, app: dict(), **params: dict):
50+
def hello_world(request: HttpRequest, app: Rinzler, **params: dict):
5951
"""
6052
Default route callback
6153
:param request HttpRequest
@@ -64,41 +56,34 @@ class Controller(TemplateView):
6456
:rtype: Response
6557
"""
6658
try:
67-
response = OrderedDict()
68-
response["status"] = True
69-
response["data"] = "Hello World!"
70-
59+
response = {
60+
"status": True,
61+
"data": "Hello World!",
62+
}
7163
return Response(response, content_type="application/json")
7264
except BaseException as e:
73-
response = OrderedDict()
74-
response["status"] = False
75-
response["mensagem"] = str(e)
76-
65+
response = {
66+
"status": False,
67+
"mensagem": str(e),
68+
}
7769
return Response(response, content_type="application/json", status=500)\
7870

7971
@staticmethod
80-
def hello_user(request: HttpRequest, app: dict(), **params: dict):
81-
"""
82-
Default route callback
83-
:param request HttpRequest
84-
:param app Rinzler's object
85-
:param params dict url params, if present
86-
:rtype: Response
87-
"""
72+
def hello_user(request: HttpRequest, app: Rinzler, **params: dict) -> Response:
8873
try:
8974
user = params['name']
90-
response = OrderedDict()
91-
response["status"] = True
92-
response["data"] = "Hello {0}!".format(user)
75+
response = {
76+
"status": True,
77+
"data": f"Hello {user}!",
78+
}
9379

9480
return Response(response, content_type="application/json")
9581
except BaseException as e:
96-
response = OrderedDict()
97-
response["status"] = False
98-
response["mensagem"] = str(e)
99-
82+
response = {
83+
"status": False,
84+
"mensagem": str(e),
85+
}
10086
return Response(response, content_type="application/json", status=500)
101-
10287
```
10388
### Run django
10489
```shell
@@ -140,5 +125,109 @@ curl http://localhost:8000/foo/bar/
140125
},
141126
"message": "We are sorry, but something went terribly wrong."
142127
}
128+
# If project's settings has DEBUG=True, otherwise: empty response body with status-code 404
129+
```
130+
131+
132+
### Authentication
133+
Authentication can be done on a per-route basis thus allowing to have authenticated and non-authenticated routes on the application.
134+
135+
To do so, first you need to create a class that inherits from `BaseAuthService` and implements the `authenticate` method.
136+
137+
```Python
138+
from django.http.request import HttpRequest
139+
140+
from rinzler.auth.base_auth_service import BaseAuthService
141+
142+
class MyAuthenticationService(BaseAuthService):
143+
def authenticate(self, request: HttpRequest, auth_route: str, params: dict) -> bool:
144+
"""
145+
Implement your authentication logic here
146+
:param request: HttpRequest Django's request object
147+
:param auth_route: str route being requested
148+
:param params: dict url params, if present
149+
:return: bool if not True, the request will be promptly returned with status-code 403
150+
"""
151+
# Non-authenticated route
152+
if auth_route == 'GET_v1/hello/world/':
153+
return True
154+
155+
# Authenticated routes
156+
if request.META.get("HTTP_AUTHORIZATION"):
157+
# after performing your authentication logic, you can append user data to the Rinzler object so it'll be available on the controller
158+
self.auth_data = {
159+
"user_id": 1,
160+
}
161+
return True
162+
```
163+
164+
Then, you need to register your authentication service on the application's `urls.py` file.
165+
166+
```Python
167+
# urls.py
168+
from rinzler import boot, Rinzler
169+
170+
from rinzler.core.main_controller import MainController
171+
from your_controller import Controller
172+
from my_auth_service import MyAuthenticationService
173+
174+
175+
app: Rinzler = boot("MyApp")
176+
app.set_auth_service(MyAuthenticationService())
177+
178+
urlpatterns = [
179+
app.mount('hello', Controller),
180+
app.mount('', MainController),
181+
]
182+
```
183+
184+
Finally, you can access the user data on the controller by accessing the `auth_data` attribute on the Rinzler object.
185+
```Python
186+
# your_controller.py
187+
from django.http.request import HttpRequest
188+
189+
from rinzler import Rinzler
190+
from rinzler.core.response import Response
191+
192+
193+
class Controller:
194+
# ...
195+
@staticmethod
196+
def hello_user(request: HttpRequest, app: Rinzler, **params: dict) -> Response:
197+
try:
198+
user = params['name']
199+
user_id = app.auth_data['user_id']
200+
response = {
201+
"status": True,
202+
"data": f"Hello {user}! Your user id is {user_id}.",
203+
}
204+
205+
return Response(response, content_type="application/json")
206+
except BaseException as e:
207+
response = {
208+
"status": False,
209+
"mensagem": str(e),
210+
}
211+
return Response(response, content_type="application/json", status=500)
212+
```
213+
### Sample requests
214+
215+
```shell
216+
# Non-authenticated request
217+
curl http://localhost:8000/hello/world/
218+
{
219+
"status": true,
220+
"data": "Hello World!"
221+
}
222+
223+
# Improperly authenticated request
224+
curl http://localhost:8000/hello/bob/
225+
# (empty response body with status-code 403)
143226

227+
# Properly authenticated request
228+
curl http://localhost:8000/hello/bob/ -H "Authorization: XYZ"
229+
{
230+
"status": true,
231+
"data": "Hello bob! Your user id is 1"
232+
}
144233
```

pyproject.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[tool.black]
2+
line-length = 120
3+
4+
[tool.flake8]
5+
max-line-length = 120
6+
exclude = ".tox,.git,*/migrations/*,*/static/CACHE/*,docs,venv"

requirements.txt

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
Django==2.2.12
2-
pytz==2020.1
3-
PyYAML==5.3.1
4-
raven==6.9.0
5-
setuptools==40.6.2
6-
wheel==0.35.1
7-
twine==3.2.0
1+
Django~=3.2
2+
PyYAML==6.0.1
3+
setuptools==68.2.2
4+
wheel==0.41.2
5+
twine==4.0.2
6+
tox==4.11.3

0 commit comments

Comments
 (0)