tina4-python 0.1.43__tar.gz → 0.1.45__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {tina4_python-0.1.43 → tina4_python-0.1.45}/PKG-INFO +36 -1
- {tina4_python-0.1.43 → tina4_python-0.1.45}/README.md +35 -0
- {tina4_python-0.1.43 → tina4_python-0.1.45}/pyproject.toml +1 -1
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/Auth.py +13 -0
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/Router.py +16 -7
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/Webserver.py +21 -5
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/Constant.py +0 -0
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/Debug.py +0 -0
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/Env.py +0 -0
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/Localization.py +0 -0
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/Messages.py +0 -0
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/Request.py +0 -0
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/Response.py +0 -0
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/Template.py +0 -0
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/__init__.py +0 -0
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/messages.pot +0 -0
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/public/css/readme.md +0 -0
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/public/favicon.ico +0 -0
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/public/images/403.png +0 -0
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/public/images/404.png +0 -0
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/public/images/logo.png +0 -0
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/public/images/readme.md +0 -0
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/public/js/readme.md +0 -0
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/templates/errors/403.twig +0 -0
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/templates/errors/404.twig +0 -0
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/templates/readme.md +0 -0
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/translations/en/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/translations/en/LC_MESSAGES/messages.po +0 -0
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/translations/fr/LC_MESSAGES/messages.mo +0 -0
- {tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/translations/fr/LC_MESSAGES/messages.po +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: tina4-python
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.45
|
|
4
4
|
Summary: Tina4Python - This is not another framework for Python
|
|
5
5
|
Author: Andre van Zuydam
|
|
6
6
|
Author-email: andrevanzuydam@gmail.com
|
|
@@ -169,6 +169,41 @@ Example:
|
|
|
169
169
|
Authorization: Bearer <token>
|
|
170
170
|
```
|
|
171
171
|
You can generate tokens using tina4_python.tina4_auth which takes in a payload parameter which is a dictionary:
|
|
172
|
+
#### Example of a post with a form, assume the route is ```/capture```
|
|
173
|
+
|
|
174
|
+
You need the following twig file in the ```src/templates``` folder called ```something.twig```
|
|
175
|
+
|
|
176
|
+
```twig something.twig
|
|
177
|
+
<form method="post">
|
|
178
|
+
<input name="email" type="text" placeholder="Email">
|
|
179
|
+
<button type="submit">Send</button>
|
|
180
|
+
<input type="hidden" name="formToken" value="{{ token }}" >
|
|
181
|
+
</form>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
You can add the following code to ```src/routes/example.py```
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
# get router which renders the twig form html
|
|
188
|
+
@get("/capture")
|
|
189
|
+
async def capture_get(request, response):
|
|
190
|
+
# get a token to add to the form
|
|
191
|
+
token = tina4_python.tina4_auth.get_token({"data": {"formName": "capture"}})
|
|
192
|
+
html = Template.render_twig_template("somefile.twig", {"token": token})
|
|
193
|
+
return response(html)
|
|
194
|
+
|
|
195
|
+
# returns back to the user the form data that has been posted
|
|
196
|
+
@post("/capture")
|
|
197
|
+
async def capture_post(request, response):
|
|
198
|
+
return response(request.body)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
In your ```src/__init__.py``` add the following code
|
|
202
|
+
|
|
203
|
+
```python
|
|
204
|
+
from .routes.example import *
|
|
205
|
+
```
|
|
206
|
+
Generate tokens with the following code as per the example above, tokens carry a payload and we add an additional ```expires``` value to the token based on the env variable ```TINA4_TOKEN_LIMIT```
|
|
172
207
|
|
|
173
208
|
```python
|
|
174
209
|
import tina4_python
|
|
@@ -150,6 +150,41 @@ Example:
|
|
|
150
150
|
Authorization: Bearer <token>
|
|
151
151
|
```
|
|
152
152
|
You can generate tokens using tina4_python.tina4_auth which takes in a payload parameter which is a dictionary:
|
|
153
|
+
#### Example of a post with a form, assume the route is ```/capture```
|
|
154
|
+
|
|
155
|
+
You need the following twig file in the ```src/templates``` folder called ```something.twig```
|
|
156
|
+
|
|
157
|
+
```twig something.twig
|
|
158
|
+
<form method="post">
|
|
159
|
+
<input name="email" type="text" placeholder="Email">
|
|
160
|
+
<button type="submit">Send</button>
|
|
161
|
+
<input type="hidden" name="formToken" value="{{ token }}" >
|
|
162
|
+
</form>
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
You can add the following code to ```src/routes/example.py```
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
# get router which renders the twig form html
|
|
169
|
+
@get("/capture")
|
|
170
|
+
async def capture_get(request, response):
|
|
171
|
+
# get a token to add to the form
|
|
172
|
+
token = tina4_python.tina4_auth.get_token({"data": {"formName": "capture"}})
|
|
173
|
+
html = Template.render_twig_template("somefile.twig", {"token": token})
|
|
174
|
+
return response(html)
|
|
175
|
+
|
|
176
|
+
# returns back to the user the form data that has been posted
|
|
177
|
+
@post("/capture")
|
|
178
|
+
async def capture_post(request, response):
|
|
179
|
+
return response(request.body)
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
In your ```src/__init__.py``` add the following code
|
|
183
|
+
|
|
184
|
+
```python
|
|
185
|
+
from .routes.example import *
|
|
186
|
+
```
|
|
187
|
+
Generate tokens with the following code as per the example above, tokens carry a payload and we add an additional ```expires``` value to the token based on the env variable ```TINA4_TOKEN_LIMIT```
|
|
153
188
|
|
|
154
189
|
```python
|
|
155
190
|
import tina4_python
|
|
@@ -105,6 +105,10 @@ class Auth:
|
|
|
105
105
|
|
|
106
106
|
def get_token(self, payload_data):
|
|
107
107
|
private_key = self.load_private_key()
|
|
108
|
+
now = datetime.datetime.now()
|
|
109
|
+
token_limit_minutes = os.environ.get("TINA4_TOKEN_LIMIT", 2)
|
|
110
|
+
expiry_time = now + datetime.timedelta(minutes=token_limit_minutes)
|
|
111
|
+
payload_data["expires"] = expiry_time.isoformat()
|
|
108
112
|
token = jwt.encode(
|
|
109
113
|
payload=payload_data,
|
|
110
114
|
key=private_key,
|
|
@@ -130,6 +134,15 @@ class Auth:
|
|
|
130
134
|
public_key = self.load_public_key()
|
|
131
135
|
try:
|
|
132
136
|
payload = jwt.decode(token, key=public_key, algorithms=['RS256'])
|
|
137
|
+
if "expires" not in payload:
|
|
138
|
+
return False
|
|
139
|
+
|
|
140
|
+
if "expires" in payload:
|
|
141
|
+
now = datetime.datetime.now()
|
|
142
|
+
expiry_time = datetime.datetime.fromisoformat(payload["expires"])
|
|
143
|
+
print("TOKEN EXPIRY", now, expiry_time)
|
|
144
|
+
if now > expiry_time:
|
|
145
|
+
return False
|
|
133
146
|
except Exception:
|
|
134
147
|
return False
|
|
135
148
|
|
|
@@ -61,15 +61,24 @@ class Router:
|
|
|
61
61
|
if method in [Constant.TINA4_POST, Constant.TINA4_PUT, Constant.TINA4_PATCH, Constant.TINA4_DELETE]:
|
|
62
62
|
content = Template.render_twig_template(
|
|
63
63
|
"errors/403.twig", {"server": {"url": url}})
|
|
64
|
-
# check for token in the headers
|
|
65
|
-
if "Authorization" not in headers:
|
|
66
|
-
return Response(content, Constant.HTTP_FORBIDDEN, Constant.TEXT_HTML)
|
|
67
64
|
|
|
68
|
-
|
|
69
|
-
if
|
|
70
|
-
|
|
65
|
+
validated = False
|
|
66
|
+
# check to see if we have an auth ability
|
|
67
|
+
if "Authorization" in headers:
|
|
68
|
+
token = headers["Authorization"].replace("Bearer", "").strip()
|
|
69
|
+
if tina4_python.tina4_auth.valid(token):
|
|
70
|
+
validated = True
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
if "formToken" in request["body"]:
|
|
73
|
+
token = request["body"]["formToken"]
|
|
74
|
+
if tina4_python.tina4_auth.valid(token):
|
|
75
|
+
validated = True
|
|
76
|
+
|
|
77
|
+
if not validated:
|
|
78
|
+
return Response(content, Constant.HTTP_FORBIDDEN, Constant.TEXT_HTML)
|
|
79
|
+
else:
|
|
80
|
+
if "formToken" in request["body"]:
|
|
81
|
+
del request["body"]["formToken"]
|
|
73
82
|
|
|
74
83
|
# default response
|
|
75
84
|
result = Response("", Constant.HTTP_NOT_FOUND, Constant.TEXT_HTML)
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import asyncio
|
|
7
7
|
import json
|
|
8
8
|
import random
|
|
9
|
+
from urllib.parse import unquote
|
|
9
10
|
from urllib.parse import urlparse, parse_qsl
|
|
10
11
|
|
|
11
12
|
import tina4_python
|
|
@@ -26,15 +27,27 @@ class Webserver:
|
|
|
26
27
|
async def get_content_body(self, content_length):
|
|
27
28
|
# get lines of content where at the end of the request
|
|
28
29
|
content = self.request_raw[-content_length:]
|
|
29
|
-
|
|
30
30
|
try:
|
|
31
|
+
print("JSON", content)
|
|
31
32
|
content = json.loads(content)
|
|
32
33
|
except Exception as e:
|
|
33
|
-
|
|
34
|
+
# check for form body
|
|
35
|
+
if content != "":
|
|
36
|
+
body = {}
|
|
37
|
+
variables = content.split("&", 1)
|
|
38
|
+
for variable in variables:
|
|
39
|
+
variable = variable.split("=", 1)
|
|
40
|
+
body[variable[0]] = unquote(variable[1])
|
|
41
|
+
return body
|
|
34
42
|
|
|
35
43
|
return content
|
|
36
44
|
|
|
37
45
|
async def get_response(self, method):
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
:param method: GET, POST, PATCH, DELETE, PUT
|
|
49
|
+
:return:
|
|
50
|
+
"""
|
|
38
51
|
headers = []
|
|
39
52
|
if method == "OPTIONS":
|
|
40
53
|
self.send_header("Access-Control-Allow-Origin", "*", headers)
|
|
@@ -48,7 +61,10 @@ class Webserver:
|
|
|
48
61
|
params = dict(parse_qsl(urlparse(self.path).query, keep_blank_values=True))
|
|
49
62
|
|
|
50
63
|
content_length = await self.get_content_length()
|
|
51
|
-
|
|
64
|
+
if method != TINA4_GET:
|
|
65
|
+
body = await self.get_content_body(content_length)
|
|
66
|
+
else:
|
|
67
|
+
body = None
|
|
52
68
|
request = {"params": params, "body": body, "raw": self.request}
|
|
53
69
|
|
|
54
70
|
tina4_python.tina4_current_request = request
|
|
@@ -143,9 +159,9 @@ class Webserver:
|
|
|
143
159
|
|
|
144
160
|
self.method = self.request.split(" ")[0]
|
|
145
161
|
|
|
146
|
-
|
|
162
|
+
body_parts = self.request.split("\n\n")
|
|
147
163
|
|
|
148
|
-
self.headers =
|
|
164
|
+
self.headers = body_parts[0].split("\n")
|
|
149
165
|
|
|
150
166
|
# parse headers into a dictionary for more efficient use
|
|
151
167
|
headers_list = {}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/translations/en/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/translations/en/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|
{tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/translations/fr/LC_MESSAGES/messages.mo
RENAMED
|
File without changes
|
{tina4_python-0.1.43 → tina4_python-0.1.45}/tina4_python/translations/fr/LC_MESSAGES/messages.po
RENAMED
|
File without changes
|