safeshield 1.6.1__tar.gz → 1.6.3__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.
- safeshield-1.6.3/MANIFEST.in +1 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/PKG-INFO +37 -11
- {safeshield-1.6.1 → safeshield-1.6.3}/README.md +14 -9
- safeshield-1.6.3/requirements.txt +12 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/safeshield.egg-info/PKG-INFO +37 -11
- {safeshield-1.6.1 → safeshield-1.6.3}/safeshield.egg-info/SOURCES.txt +2 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/setup.py +5 -2
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/core/validator.py +4 -1
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/database/manager.py +2 -15
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/rules/base.py +0 -3
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/rules/boolean.py +2 -2
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/rules/utilities.py +9 -6
- {safeshield-1.6.1 → safeshield-1.6.3}/LICENSE +0 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/safeshield.egg-info/dependency_links.txt +0 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/safeshield.egg-info/requires.txt +0 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/safeshield.egg-info/top_level.txt +0 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/setup.cfg +0 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/__init__.py +0 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/core/__init__.py +0 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/database/__init__.py +0 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/database/detector.py +0 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/exceptions.py +0 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/factory.py +0 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/rules/__init__.py +0 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/rules/array.py +0 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/rules/basic.py +0 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/rules/comparison.py +0 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/rules/date.py +0 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/rules/files.py +0 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/rules/format.py +0 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/rules/numeric.py +0 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/rules/string.py +0 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/services/__init__.py +0 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/services/rule_conflict.py +0 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/services/rule_error_handler.py +0 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/services/rule_preparer.py +0 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/utils/__init__.py +0 -0
- {safeshield-1.6.1 → safeshield-1.6.3}/validator/utils/string.py +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
include requirements.txt
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: safeshield
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.3
|
|
4
4
|
Summary: Library for Help Validation Control
|
|
5
5
|
Home-page: https://github.com/WunsunTarniho/py-guard
|
|
6
6
|
Author: Wunsun Tarniho
|
|
@@ -16,6 +16,27 @@ Classifier: Topic :: Security
|
|
|
16
16
|
Requires-Python: >=3.10
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
18
|
License-File: LICENSE
|
|
19
|
+
Requires-Dist: mysql-connector-python==8.0.33
|
|
20
|
+
Requires-Dist: Pillow==11.2.1
|
|
21
|
+
Requires-Dist: psycopg2-binary==2.9.9
|
|
22
|
+
Requires-Dist: python-dotenv==1.1.1
|
|
23
|
+
Requires-Dist: python_dateutil==2.9.0.post0
|
|
24
|
+
Requires-Dist: setuptools==63.2.0
|
|
25
|
+
Requires-Dist: SQLAlchemy==2.0.41
|
|
26
|
+
Requires-Dist: Werkzeug==1.0.1
|
|
27
|
+
Requires-Dist: dnspython==2.4.2
|
|
28
|
+
Requires-Dist: idna==3.4
|
|
29
|
+
Dynamic: author
|
|
30
|
+
Dynamic: author-email
|
|
31
|
+
Dynamic: classifier
|
|
32
|
+
Dynamic: description
|
|
33
|
+
Dynamic: description-content-type
|
|
34
|
+
Dynamic: home-page
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
Dynamic: project-url
|
|
37
|
+
Dynamic: requires-dist
|
|
38
|
+
Dynamic: requires-python
|
|
39
|
+
Dynamic: summary
|
|
19
40
|
|
|
20
41
|
# Safe Shield
|
|
21
42
|
Safe Shield is a robust Python library designed to validating HTTP requests and input data.
|
|
@@ -143,7 +164,10 @@ validator.validate()
|
|
|
143
164
|
|
|
144
165
|
"""
|
|
145
166
|
validator.has_errors -> True
|
|
146
|
-
validator.errors
|
|
167
|
+
validator.errors:
|
|
168
|
+
{
|
|
169
|
+
"name": ["The name field is required.", "The name must be a string"]
|
|
170
|
+
}
|
|
147
171
|
"""
|
|
148
172
|
```
|
|
149
173
|
|
|
@@ -181,10 +205,11 @@ validator.validate()
|
|
|
181
205
|
|
|
182
206
|
"""
|
|
183
207
|
validator.has_errors -> True
|
|
184
|
-
validator.errors
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
208
|
+
validator.errors:
|
|
209
|
+
{
|
|
210
|
+
"user.contact.email": ["The email must be a valid email with valid DNS records."],
|
|
211
|
+
"orders.0.price": ["The price must be a number"]
|
|
212
|
+
}
|
|
188
213
|
"""
|
|
189
214
|
```
|
|
190
215
|
|
|
@@ -207,9 +232,10 @@ validator.validate()
|
|
|
207
232
|
|
|
208
233
|
"""
|
|
209
234
|
validator.has_errors -> True
|
|
210
|
-
validator.errors
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
235
|
+
validator.errors:
|
|
236
|
+
{
|
|
237
|
+
"user.contact.email": ["This email is invalid"],
|
|
238
|
+
"orders.0.price": ["The price must be a number"]
|
|
239
|
+
}
|
|
214
240
|
"""
|
|
215
241
|
```
|
|
@@ -124,7 +124,10 @@ validator.validate()
|
|
|
124
124
|
|
|
125
125
|
"""
|
|
126
126
|
validator.has_errors -> True
|
|
127
|
-
validator.errors
|
|
127
|
+
validator.errors:
|
|
128
|
+
{
|
|
129
|
+
"name": ["The name field is required.", "The name must be a string"]
|
|
130
|
+
}
|
|
128
131
|
"""
|
|
129
132
|
```
|
|
130
133
|
|
|
@@ -162,10 +165,11 @@ validator.validate()
|
|
|
162
165
|
|
|
163
166
|
"""
|
|
164
167
|
validator.has_errors -> True
|
|
165
|
-
validator.errors
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
168
|
+
validator.errors:
|
|
169
|
+
{
|
|
170
|
+
"user.contact.email": ["The email must be a valid email with valid DNS records."],
|
|
171
|
+
"orders.0.price": ["The price must be a number"]
|
|
172
|
+
}
|
|
169
173
|
"""
|
|
170
174
|
```
|
|
171
175
|
|
|
@@ -188,9 +192,10 @@ validator.validate()
|
|
|
188
192
|
|
|
189
193
|
"""
|
|
190
194
|
validator.has_errors -> True
|
|
191
|
-
validator.errors
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
+
validator.errors:
|
|
196
|
+
{
|
|
197
|
+
"user.contact.email": ["This email is invalid"],
|
|
198
|
+
"orders.0.price": ["The price must be a number"]
|
|
199
|
+
}
|
|
195
200
|
"""
|
|
196
201
|
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: safeshield
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.3
|
|
4
4
|
Summary: Library for Help Validation Control
|
|
5
5
|
Home-page: https://github.com/WunsunTarniho/py-guard
|
|
6
6
|
Author: Wunsun Tarniho
|
|
@@ -16,6 +16,27 @@ Classifier: Topic :: Security
|
|
|
16
16
|
Requires-Python: >=3.10
|
|
17
17
|
Description-Content-Type: text/markdown
|
|
18
18
|
License-File: LICENSE
|
|
19
|
+
Requires-Dist: mysql-connector-python==8.0.33
|
|
20
|
+
Requires-Dist: Pillow==11.2.1
|
|
21
|
+
Requires-Dist: psycopg2-binary==2.9.9
|
|
22
|
+
Requires-Dist: python-dotenv==1.1.1
|
|
23
|
+
Requires-Dist: python_dateutil==2.9.0.post0
|
|
24
|
+
Requires-Dist: setuptools==63.2.0
|
|
25
|
+
Requires-Dist: SQLAlchemy==2.0.41
|
|
26
|
+
Requires-Dist: Werkzeug==1.0.1
|
|
27
|
+
Requires-Dist: dnspython==2.4.2
|
|
28
|
+
Requires-Dist: idna==3.4
|
|
29
|
+
Dynamic: author
|
|
30
|
+
Dynamic: author-email
|
|
31
|
+
Dynamic: classifier
|
|
32
|
+
Dynamic: description
|
|
33
|
+
Dynamic: description-content-type
|
|
34
|
+
Dynamic: home-page
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
Dynamic: project-url
|
|
37
|
+
Dynamic: requires-dist
|
|
38
|
+
Dynamic: requires-python
|
|
39
|
+
Dynamic: summary
|
|
19
40
|
|
|
20
41
|
# Safe Shield
|
|
21
42
|
Safe Shield is a robust Python library designed to validating HTTP requests and input data.
|
|
@@ -143,7 +164,10 @@ validator.validate()
|
|
|
143
164
|
|
|
144
165
|
"""
|
|
145
166
|
validator.has_errors -> True
|
|
146
|
-
validator.errors
|
|
167
|
+
validator.errors:
|
|
168
|
+
{
|
|
169
|
+
"name": ["The name field is required.", "The name must be a string"]
|
|
170
|
+
}
|
|
147
171
|
"""
|
|
148
172
|
```
|
|
149
173
|
|
|
@@ -181,10 +205,11 @@ validator.validate()
|
|
|
181
205
|
|
|
182
206
|
"""
|
|
183
207
|
validator.has_errors -> True
|
|
184
|
-
validator.errors
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
208
|
+
validator.errors:
|
|
209
|
+
{
|
|
210
|
+
"user.contact.email": ["The email must be a valid email with valid DNS records."],
|
|
211
|
+
"orders.0.price": ["The price must be a number"]
|
|
212
|
+
}
|
|
188
213
|
"""
|
|
189
214
|
```
|
|
190
215
|
|
|
@@ -207,9 +232,10 @@ validator.validate()
|
|
|
207
232
|
|
|
208
233
|
"""
|
|
209
234
|
validator.has_errors -> True
|
|
210
|
-
validator.errors
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
235
|
+
validator.errors:
|
|
236
|
+
{
|
|
237
|
+
"user.contact.email": ["This email is invalid"],
|
|
238
|
+
"orders.0.price": ["The price must be a number"]
|
|
239
|
+
}
|
|
214
240
|
"""
|
|
215
241
|
```
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
from setuptools import setup, find_packages
|
|
2
2
|
import os
|
|
3
3
|
|
|
4
|
+
current_dir = os.path.dirname(__file__) # Folder dimana setup.py berada
|
|
5
|
+
requirements_path = os.path.join(current_dir, 'requirements.txt')
|
|
6
|
+
|
|
4
7
|
def get_requirements():
|
|
5
|
-
with open(
|
|
8
|
+
with open(requirements_path) as f:
|
|
6
9
|
return [line.strip() for line in f.readlines() if line.strip()]
|
|
7
10
|
|
|
8
11
|
setup(
|
|
9
12
|
name="safeshield",
|
|
10
|
-
version="1.6.
|
|
13
|
+
version="1.6.3",
|
|
11
14
|
packages=find_packages(),
|
|
12
15
|
install_requires=get_requirements(),
|
|
13
16
|
author="Wunsun Tarniho",
|
|
@@ -282,7 +282,7 @@ class Validator:
|
|
|
282
282
|
combined_rules = existing_rules + new_rules
|
|
283
283
|
|
|
284
284
|
RuleConflictChecker.check_conflicts(combined_rules)
|
|
285
|
-
self._raw_rules[field] = self.rule_preparer._deduplicate_rules(
|
|
285
|
+
self._raw_rules[field] = self.rule_preparer._deduplicate_rules(combined_rules)
|
|
286
286
|
|
|
287
287
|
def set_stop_on_first_failure(self, value: bool) -> None:
|
|
288
288
|
"""Set whether to stop validation after first failure"""
|
|
@@ -293,6 +293,9 @@ class Validator:
|
|
|
293
293
|
"""Get current validation errors"""
|
|
294
294
|
return self.error_handler.errors
|
|
295
295
|
|
|
296
|
+
def get_errors(self):
|
|
297
|
+
return self.error_handler.errors or {}
|
|
298
|
+
|
|
296
299
|
@property
|
|
297
300
|
def has_errors(self) -> bool:
|
|
298
301
|
"""Check if there are any validation errors"""
|
|
@@ -111,21 +111,8 @@ class DatabaseManager:
|
|
|
111
111
|
return cursor.fetchall()
|
|
112
112
|
|
|
113
113
|
def exists(self, table: str, column: str, value: Any) -> bool:
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
if len(parts) != 2:
|
|
117
|
-
raise ValueError("Foreign key reference should be in format 'foreign_key.column'")
|
|
118
|
-
|
|
119
|
-
foreign_key, related_column = parts
|
|
120
|
-
sql = f"""
|
|
121
|
-
SELECT 1 FROM {table} t
|
|
122
|
-
JOIN {foreign_key} r ON t.{foreign_key} = r.id
|
|
123
|
-
WHERE r.{related_column} = %s
|
|
124
|
-
LIMIT 1
|
|
125
|
-
"""
|
|
126
|
-
else:
|
|
127
|
-
sql = f"SELECT 1 FROM {table} WHERE {column} = %s LIMIT 1"
|
|
128
|
-
|
|
114
|
+
"""Optimized exists check with parameterized query"""
|
|
115
|
+
sql = f"SELECT 1 FROM {table} WHERE {column} = %s LIMIT 1"
|
|
129
116
|
result = self.query(sql, (value,))
|
|
130
117
|
return bool(result)
|
|
131
118
|
|
|
@@ -45,7 +45,7 @@ class DeclinedRule(Rule):
|
|
|
45
45
|
return f"The :attribute must be declined."
|
|
46
46
|
|
|
47
47
|
class AcceptedIfRule(AcceptedRule):
|
|
48
|
-
_count_parameter =
|
|
48
|
+
_count_parameter = 2
|
|
49
49
|
|
|
50
50
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
51
51
|
condition_met = False
|
|
@@ -99,7 +99,7 @@ class AcceptedUnlessRule(AcceptedRule):
|
|
|
99
99
|
return replacements
|
|
100
100
|
|
|
101
101
|
class DeclinedIfRule(DeclinedRule):
|
|
102
|
-
_count_parameter =
|
|
102
|
+
_count_parameter = 2
|
|
103
103
|
|
|
104
104
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
105
105
|
condition_met = False
|
|
@@ -4,7 +4,7 @@ from .basic import *
|
|
|
4
4
|
from .boolean import AcceptedRule, DeclinedRule
|
|
5
5
|
|
|
6
6
|
class RequiredIfRule(RequiredRule):
|
|
7
|
-
_count_parameter =
|
|
7
|
+
_count_parameter = 1
|
|
8
8
|
_accept_closure = True
|
|
9
9
|
|
|
10
10
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -67,7 +67,8 @@ class RequiredWithRule(RequiredRule):
|
|
|
67
67
|
_count_parameter = 1
|
|
68
68
|
|
|
69
69
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
70
|
-
|
|
70
|
+
condition = [f in self.validator.data and not self.is_empty(self.get_field_value(f)) for f in params]
|
|
71
|
+
if any(condition):
|
|
71
72
|
return super().validate(field, value, params)
|
|
72
73
|
return True
|
|
73
74
|
|
|
@@ -84,7 +85,9 @@ class RequiredWithAllRule(RequiredRule):
|
|
|
84
85
|
_count_parameter = 1
|
|
85
86
|
|
|
86
87
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
87
|
-
|
|
88
|
+
condition = [f in self.validator.data and not self.is_empty(self.get_field_value(f)) for f in params]
|
|
89
|
+
|
|
90
|
+
if all(condition):
|
|
88
91
|
return super().validate(field, value, params)
|
|
89
92
|
return True
|
|
90
93
|
|
|
@@ -170,7 +173,7 @@ class RequiredArrayKeysRule(Rule):
|
|
|
170
173
|
return replacements
|
|
171
174
|
|
|
172
175
|
class ProhibitedIfRule(ProhibitedRule):
|
|
173
|
-
_count_parameter =
|
|
176
|
+
_count_parameter = 1
|
|
174
177
|
_accept_closure = True
|
|
175
178
|
|
|
176
179
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -241,7 +244,7 @@ class ProhibitedIfDeclinedRule(ProhibitedRule, DeclinedRule):
|
|
|
241
244
|
return True
|
|
242
245
|
|
|
243
246
|
class PresentIfRule(PresentRule):
|
|
244
|
-
_count_parameter =
|
|
247
|
+
_count_parameter = 1
|
|
245
248
|
_accept_closure = True
|
|
246
249
|
|
|
247
250
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
@@ -431,7 +434,7 @@ class MissingWithAllRule(MissingRule):
|
|
|
431
434
|
return replacements
|
|
432
435
|
|
|
433
436
|
class ExcludeIfRule(ExcludeRule):
|
|
434
|
-
_count_parameter =
|
|
437
|
+
_count_parameter = 1
|
|
435
438
|
_accept_closure = True
|
|
436
439
|
|
|
437
440
|
def validate(self, field: str, value: Any, params: List[str]) -> bool:
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|