clear-skies 1.22.31__py3-none-any.whl → 2.0.0__py3-none-any.whl
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.
Potentially problematic release.
This version of clear-skies might be problematic. Click here for more details.
- {clear_skies-1.22.31.dist-info → clear_skies-2.0.0.dist-info}/METADATA +11 -13
- clear_skies-2.0.0.dist-info/RECORD +248 -0
- {clear_skies-1.22.31.dist-info → clear_skies-2.0.0.dist-info}/WHEEL +1 -1
- clearskies/__init__.py +42 -25
- clearskies/action.py +7 -0
- clearskies/authentication/__init__.py +8 -41
- clearskies/authentication/authentication.py +42 -0
- clearskies/authentication/authorization.py +4 -9
- clearskies/authentication/authorization_pass_through.py +11 -9
- clearskies/authentication/jwks.py +128 -58
- clearskies/authentication/public.py +3 -38
- clearskies/authentication/secret_bearer.py +516 -54
- clearskies/autodoc/formats/oai3_json/__init__.py +1 -1
- clearskies/autodoc/formats/oai3_json/oai3_json.py +9 -7
- clearskies/autodoc/formats/oai3_json/parameter.py +6 -3
- clearskies/autodoc/formats/oai3_json/request.py +7 -5
- clearskies/autodoc/formats/oai3_json/response.py +7 -4
- clearskies/autodoc/formats/oai3_json/schema/object.py +4 -1
- clearskies/autodoc/request/__init__.py +2 -0
- clearskies/autodoc/request/header.py +4 -6
- clearskies/autodoc/request/json_body.py +4 -6
- clearskies/autodoc/request/parameter.py +8 -0
- clearskies/autodoc/request/request.py +7 -4
- clearskies/autodoc/request/url_parameter.py +4 -6
- clearskies/autodoc/request/url_path.py +4 -6
- clearskies/autodoc/schema/__init__.py +4 -2
- clearskies/autodoc/schema/array.py +5 -6
- clearskies/autodoc/schema/boolean.py +4 -10
- clearskies/autodoc/schema/date.py +0 -3
- clearskies/autodoc/schema/datetime.py +1 -4
- clearskies/autodoc/schema/double.py +0 -3
- clearskies/autodoc/schema/enum.py +4 -2
- clearskies/autodoc/schema/integer.py +4 -9
- clearskies/autodoc/schema/long.py +0 -3
- clearskies/autodoc/schema/number.py +4 -9
- clearskies/autodoc/schema/object.py +5 -7
- clearskies/autodoc/schema/password.py +0 -3
- clearskies/autodoc/schema/schema.py +11 -0
- clearskies/autodoc/schema/string.py +4 -10
- clearskies/backends/__init__.py +55 -20
- clearskies/backends/api_backend.py +1100 -284
- clearskies/backends/backend.py +40 -84
- clearskies/backends/cursor_backend.py +236 -186
- clearskies/backends/memory_backend.py +519 -226
- clearskies/backends/secrets_backend.py +75 -31
- clearskies/column.py +1232 -0
- clearskies/columns/__init__.py +71 -0
- clearskies/columns/audit.py +205 -0
- clearskies/columns/belongs_to_id.py +483 -0
- clearskies/columns/belongs_to_model.py +128 -0
- clearskies/columns/belongs_to_self.py +105 -0
- clearskies/columns/boolean.py +109 -0
- clearskies/columns/category_tree.py +275 -0
- clearskies/columns/category_tree_ancestors.py +51 -0
- clearskies/columns/category_tree_children.py +127 -0
- clearskies/columns/category_tree_descendants.py +48 -0
- clearskies/columns/created.py +94 -0
- clearskies/columns/created_by_authorization_data.py +116 -0
- clearskies/columns/created_by_header.py +99 -0
- clearskies/columns/created_by_ip.py +92 -0
- clearskies/columns/created_by_routing_data.py +96 -0
- clearskies/columns/created_by_user_agent.py +92 -0
- clearskies/columns/date.py +230 -0
- clearskies/columns/datetime.py +278 -0
- clearskies/columns/email.py +76 -0
- clearskies/columns/float.py +149 -0
- clearskies/columns/has_many.py +505 -0
- clearskies/columns/has_many_self.py +56 -0
- clearskies/columns/has_one.py +14 -0
- clearskies/columns/integer.py +156 -0
- clearskies/columns/json.py +122 -0
- clearskies/columns/many_to_many_ids.py +333 -0
- clearskies/columns/many_to_many_ids_with_data.py +270 -0
- clearskies/columns/many_to_many_models.py +154 -0
- clearskies/columns/many_to_many_pivots.py +133 -0
- clearskies/columns/phone.py +158 -0
- clearskies/columns/select.py +91 -0
- clearskies/columns/string.py +98 -0
- clearskies/columns/timestamp.py +160 -0
- clearskies/columns/updated.py +110 -0
- clearskies/columns/uuid.py +86 -0
- clearskies/configs/README.md +105 -0
- clearskies/configs/__init__.py +159 -0
- clearskies/configs/actions.py +43 -0
- clearskies/configs/any.py +13 -0
- clearskies/configs/any_dict.py +22 -0
- clearskies/configs/any_dict_or_callable.py +23 -0
- clearskies/configs/authentication.py +23 -0
- clearskies/configs/authorization.py +23 -0
- clearskies/configs/boolean.py +16 -0
- clearskies/configs/boolean_or_callable.py +18 -0
- clearskies/configs/callable_config.py +18 -0
- clearskies/configs/columns.py +34 -0
- clearskies/configs/conditions.py +30 -0
- clearskies/configs/config.py +21 -0
- clearskies/configs/datetime.py +18 -0
- clearskies/configs/datetime_or_callable.py +19 -0
- clearskies/configs/endpoint.py +23 -0
- clearskies/configs/float.py +16 -0
- clearskies/configs/float_or_callable.py +18 -0
- clearskies/configs/integer.py +16 -0
- clearskies/configs/integer_or_callable.py +18 -0
- clearskies/configs/joins.py +30 -0
- clearskies/configs/list_any_dict.py +30 -0
- clearskies/configs/list_any_dict_or_callable.py +31 -0
- clearskies/configs/model_class.py +35 -0
- clearskies/configs/model_column.py +65 -0
- clearskies/configs/model_columns.py +56 -0
- clearskies/configs/model_destination_name.py +25 -0
- clearskies/configs/model_to_id_column.py +43 -0
- clearskies/configs/readable_model_column.py +9 -0
- clearskies/configs/readable_model_columns.py +9 -0
- clearskies/configs/schema.py +23 -0
- clearskies/configs/searchable_model_columns.py +9 -0
- clearskies/configs/security_headers.py +39 -0
- clearskies/configs/select.py +26 -0
- clearskies/configs/select_list.py +47 -0
- clearskies/configs/string.py +29 -0
- clearskies/configs/string_dict.py +32 -0
- clearskies/configs/string_list.py +32 -0
- clearskies/configs/string_list_or_callable.py +35 -0
- clearskies/configs/string_or_callable.py +18 -0
- clearskies/configs/timedelta.py +18 -0
- clearskies/configs/timezone.py +18 -0
- clearskies/configs/url.py +23 -0
- clearskies/configs/validators.py +45 -0
- clearskies/configs/writeable_model_column.py +9 -0
- clearskies/configs/writeable_model_columns.py +9 -0
- clearskies/configurable.py +76 -0
- clearskies/contexts/__init__.py +8 -8
- clearskies/contexts/cli.py +5 -42
- clearskies/contexts/context.py +78 -56
- clearskies/contexts/wsgi.py +13 -30
- clearskies/contexts/wsgi_ref.py +49 -0
- clearskies/di/__init__.py +10 -7
- clearskies/di/additional_config.py +115 -4
- clearskies/di/additional_config_auto_import.py +12 -0
- clearskies/di/di.py +742 -121
- clearskies/di/inject/__init__.py +23 -0
- clearskies/di/inject/by_class.py +21 -0
- clearskies/di/inject/by_name.py +18 -0
- clearskies/di/inject/di.py +13 -0
- clearskies/di/inject/environment.py +14 -0
- clearskies/di/inject/input_output.py +20 -0
- clearskies/di/inject/now.py +13 -0
- clearskies/di/inject/requests.py +13 -0
- clearskies/di/inject/secrets.py +14 -0
- clearskies/di/inject/utcnow.py +13 -0
- clearskies/di/inject/uuid.py +15 -0
- clearskies/di/injectable.py +29 -0
- clearskies/di/injectable_properties.py +131 -0
- clearskies/end.py +183 -0
- clearskies/endpoint.py +1309 -0
- clearskies/endpoint_group.py +297 -0
- clearskies/endpoints/__init__.py +23 -0
- clearskies/endpoints/advanced_search.py +526 -0
- clearskies/endpoints/callable.py +387 -0
- clearskies/endpoints/create.py +202 -0
- clearskies/endpoints/delete.py +139 -0
- clearskies/endpoints/get.py +275 -0
- clearskies/endpoints/health_check.py +181 -0
- clearskies/endpoints/list.py +573 -0
- clearskies/endpoints/restful_api.py +427 -0
- clearskies/endpoints/simple_search.py +286 -0
- clearskies/endpoints/update.py +190 -0
- clearskies/environment.py +5 -3
- clearskies/exceptions/__init__.py +17 -0
- clearskies/{handlers/exceptions/input_error.py → exceptions/input_errors.py} +1 -1
- clearskies/exceptions/moved_permanently.py +3 -0
- clearskies/exceptions/moved_temporarily.py +3 -0
- clearskies/exceptions/not_found.py +2 -0
- clearskies/functional/__init__.py +2 -2
- clearskies/functional/routing.py +92 -0
- clearskies/functional/string.py +19 -11
- clearskies/functional/validations.py +61 -9
- clearskies/input_outputs/__init__.py +9 -7
- clearskies/input_outputs/cli.py +130 -142
- clearskies/input_outputs/exceptions/__init__.py +1 -1
- clearskies/input_outputs/headers.py +45 -0
- clearskies/input_outputs/input_output.py +91 -122
- clearskies/input_outputs/programmatic.py +69 -0
- clearskies/input_outputs/wsgi.py +23 -38
- clearskies/model.py +489 -184
- clearskies/parameters_to_properties.py +31 -0
- clearskies/query/__init__.py +12 -0
- clearskies/query/condition.py +223 -0
- clearskies/query/join.py +136 -0
- clearskies/query/query.py +196 -0
- clearskies/query/sort.py +27 -0
- clearskies/schema.py +82 -0
- clearskies/secrets/__init__.py +3 -31
- clearskies/secrets/additional_configs/mysql_connection_dynamic_producer.py +15 -4
- clearskies/secrets/additional_configs/mysql_connection_dynamic_producer_via_ssh_cert_bastion.py +11 -5
- clearskies/secrets/akeyless.py +88 -147
- clearskies/secrets/secrets.py +8 -8
- clearskies/security_header.py +8 -0
- clearskies/security_headers/__init__.py +8 -8
- clearskies/security_headers/cache_control.py +47 -110
- clearskies/security_headers/cors.py +40 -95
- clearskies/security_headers/csp.py +76 -151
- clearskies/security_headers/hsts.py +14 -16
- clearskies/test_base.py +8 -0
- clearskies/typing.py +11 -0
- clearskies/validator.py +25 -0
- clearskies/validators/__init__.py +33 -0
- clearskies/validators/after_column.py +62 -0
- clearskies/validators/before_column.py +13 -0
- clearskies/validators/in_the_future.py +32 -0
- clearskies/validators/in_the_future_at_least.py +11 -0
- clearskies/validators/in_the_future_at_most.py +10 -0
- clearskies/validators/in_the_past.py +32 -0
- clearskies/validators/in_the_past_at_least.py +10 -0
- clearskies/validators/in_the_past_at_most.py +10 -0
- clearskies/validators/maximum_length.py +26 -0
- clearskies/validators/maximum_value.py +29 -0
- clearskies/validators/minimum_length.py +26 -0
- clearskies/validators/minimum_value.py +29 -0
- clearskies/validators/required.py +35 -0
- clearskies/validators/timedelta.py +59 -0
- clearskies/validators/unique.py +31 -0
- clear_skies-1.22.31.dist-info/RECORD +0 -214
- clearskies/application.py +0 -29
- clearskies/authentication/auth0_jwks.py +0 -118
- clearskies/authentication/auth_exception.py +0 -2
- clearskies/authentication/jwks_jwcrypto.py +0 -51
- clearskies/backends/api_get_only_backend.py +0 -48
- clearskies/backends/example_backend.py +0 -43
- clearskies/backends/file_backend.py +0 -48
- clearskies/backends/json_backend.py +0 -7
- clearskies/backends/restful_api_advanced_search_backend.py +0 -103
- clearskies/binding_config.py +0 -16
- clearskies/column_types/__init__.py +0 -203
- clearskies/column_types/audit.py +0 -249
- clearskies/column_types/belongs_to.py +0 -271
- clearskies/column_types/boolean.py +0 -60
- clearskies/column_types/category_tree.py +0 -304
- clearskies/column_types/column.py +0 -373
- clearskies/column_types/created.py +0 -26
- clearskies/column_types/created_by_authorization_data.py +0 -26
- clearskies/column_types/created_by_header.py +0 -24
- clearskies/column_types/created_by_ip.py +0 -17
- clearskies/column_types/created_by_routing_data.py +0 -25
- clearskies/column_types/created_by_user_agent.py +0 -17
- clearskies/column_types/created_micro.py +0 -26
- clearskies/column_types/datetime.py +0 -109
- clearskies/column_types/datetime_micro.py +0 -12
- clearskies/column_types/email.py +0 -18
- clearskies/column_types/float.py +0 -43
- clearskies/column_types/has_many.py +0 -179
- clearskies/column_types/has_one.py +0 -60
- clearskies/column_types/integer.py +0 -41
- clearskies/column_types/json.py +0 -25
- clearskies/column_types/many_to_many.py +0 -278
- clearskies/column_types/many_to_many_with_data.py +0 -162
- clearskies/column_types/phone.py +0 -48
- clearskies/column_types/select.py +0 -11
- clearskies/column_types/string.py +0 -24
- clearskies/column_types/timestamp.py +0 -73
- clearskies/column_types/updated.py +0 -26
- clearskies/column_types/updated_micro.py +0 -26
- clearskies/column_types/uuid.py +0 -25
- clearskies/columns.py +0 -123
- clearskies/condition_parser.py +0 -172
- clearskies/contexts/build_context.py +0 -54
- clearskies/contexts/convert_to_application.py +0 -190
- clearskies/contexts/extract_handler.py +0 -37
- clearskies/contexts/test.py +0 -94
- clearskies/decorators/__init__.py +0 -41
- clearskies/decorators/allow_non_json_bodies.py +0 -9
- clearskies/decorators/auth0_jwks.py +0 -22
- clearskies/decorators/authorization.py +0 -10
- clearskies/decorators/binding_classes.py +0 -9
- clearskies/decorators/binding_modules.py +0 -9
- clearskies/decorators/bindings.py +0 -9
- clearskies/decorators/create.py +0 -10
- clearskies/decorators/delete.py +0 -10
- clearskies/decorators/docs.py +0 -14
- clearskies/decorators/get.py +0 -10
- clearskies/decorators/jwks.py +0 -26
- clearskies/decorators/merge.py +0 -124
- clearskies/decorators/patch.py +0 -10
- clearskies/decorators/post.py +0 -10
- clearskies/decorators/public.py +0 -11
- clearskies/decorators/response_headers.py +0 -10
- clearskies/decorators/return_raw_response.py +0 -9
- clearskies/decorators/schema.py +0 -10
- clearskies/decorators/secret_bearer.py +0 -24
- clearskies/decorators/security_headers.py +0 -10
- clearskies/di/standard_dependencies.py +0 -151
- clearskies/handlers/__init__.py +0 -41
- clearskies/handlers/advanced_search.py +0 -271
- clearskies/handlers/base.py +0 -479
- clearskies/handlers/callable.py +0 -192
- clearskies/handlers/create.py +0 -35
- clearskies/handlers/crud_by_method.py +0 -18
- clearskies/handlers/database_connector.py +0 -32
- clearskies/handlers/delete.py +0 -61
- clearskies/handlers/exceptions/__init__.py +0 -5
- clearskies/handlers/exceptions/not_found.py +0 -3
- clearskies/handlers/get.py +0 -156
- clearskies/handlers/health_check.py +0 -59
- clearskies/handlers/input_processing.py +0 -79
- clearskies/handlers/list.py +0 -530
- clearskies/handlers/mygrations.py +0 -82
- clearskies/handlers/request_method_routing.py +0 -47
- clearskies/handlers/restful_api.py +0 -218
- clearskies/handlers/routing.py +0 -62
- clearskies/handlers/schema_helper.py +0 -128
- clearskies/handlers/simple_routing.py +0 -206
- clearskies/handlers/simple_routing_route.py +0 -197
- clearskies/handlers/simple_search.py +0 -136
- clearskies/handlers/update.py +0 -102
- clearskies/handlers/write.py +0 -193
- clearskies/input_requirements/__init__.py +0 -78
- clearskies/input_requirements/after.py +0 -36
- clearskies/input_requirements/before.py +0 -36
- clearskies/input_requirements/in_the_future_at_least.py +0 -19
- clearskies/input_requirements/in_the_future_at_most.py +0 -19
- clearskies/input_requirements/in_the_past_at_least.py +0 -19
- clearskies/input_requirements/in_the_past_at_most.py +0 -19
- clearskies/input_requirements/maximum_length.py +0 -19
- clearskies/input_requirements/maximum_value.py +0 -19
- clearskies/input_requirements/minimum_length.py +0 -22
- clearskies/input_requirements/minimum_value.py +0 -19
- clearskies/input_requirements/required.py +0 -23
- clearskies/input_requirements/requirement.py +0 -25
- clearskies/input_requirements/time_delta.py +0 -38
- clearskies/input_requirements/unique.py +0 -18
- clearskies/mocks/__init__.py +0 -7
- clearskies/mocks/input_output.py +0 -124
- clearskies/mocks/models.py +0 -142
- clearskies/models.py +0 -350
- clearskies/security_headers/base.py +0 -12
- clearskies/tests/simple_api/models/__init__.py +0 -2
- clearskies/tests/simple_api/models/status.py +0 -23
- clearskies/tests/simple_api/models/user.py +0 -21
- clearskies/tests/simple_api/users_api.py +0 -64
- {clear_skies-1.22.31.dist-info → clear_skies-2.0.0.dist-info}/LICENSE +0 -0
- /clearskies/{contexts/bash.py → autodoc/py.typed} +0 -0
- /clearskies/{handlers/exceptions → exceptions}/authentication.py +0 -0
- /clearskies/{handlers/exceptions → exceptions}/authorization.py +0 -0
- /clearskies/{handlers/exceptions → exceptions}/client_error.py +0 -0
- /clearskies/{tests/__init__.py → input_outputs/py.typed} +0 -0
- /clearskies/{tests/simple_api/__init__.py → py.typed} +0 -0
|
@@ -1,76 +1,62 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import clearskies.configs
|
|
2
|
+
import clearskies.parameters_to_properties
|
|
3
|
+
from clearskies.security_header import SecurityHeader
|
|
3
4
|
|
|
4
|
-
numbers = [
|
|
5
|
-
"max_age",
|
|
6
|
-
"stale_if_error",
|
|
7
|
-
"stale_while_revalidate",
|
|
8
|
-
"s_maxage",
|
|
9
|
-
]
|
|
10
|
-
bools = [
|
|
11
|
-
"immutable",
|
|
12
|
-
"must_understand",
|
|
13
|
-
"no_cache",
|
|
14
|
-
"no_store",
|
|
15
|
-
"no_transform",
|
|
16
|
-
"private",
|
|
17
|
-
"public",
|
|
18
|
-
"s_maxage",
|
|
19
|
-
]
|
|
20
5
|
|
|
6
|
+
class CacheControl(SecurityHeader):
|
|
7
|
+
max_age = clearskies.configs.Integer()
|
|
8
|
+
s_maxage = clearskies.configs.Integer()
|
|
9
|
+
stale_while_revalidate = clearskies.configs.Integer()
|
|
10
|
+
stale_if_error = clearskies.configs.Integer()
|
|
11
|
+
immutable = clearskies.configs.Boolean(default=False)
|
|
12
|
+
must_understand = clearskies.configs.Boolean(default=False)
|
|
13
|
+
no_cache = clearskies.configs.Boolean(default=False)
|
|
14
|
+
no_store = clearskies.configs.Boolean(default=False)
|
|
15
|
+
no_transform = clearskies.configs.Boolean(default=False)
|
|
16
|
+
private = clearskies.configs.Boolean(default=False)
|
|
17
|
+
public = clearskies.configs.Boolean(default=False)
|
|
21
18
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
19
|
+
numbers: list[str] = [
|
|
20
|
+
"max_age",
|
|
21
|
+
"stale_if_error",
|
|
22
|
+
"stale_while_revalidate",
|
|
23
|
+
"s_maxage",
|
|
24
|
+
]
|
|
25
|
+
bools: list[str] = [
|
|
26
|
+
"immutable",
|
|
27
|
+
"must_understand",
|
|
28
|
+
"no_cache",
|
|
29
|
+
"no_store",
|
|
30
|
+
"no_transform",
|
|
31
|
+
"private",
|
|
32
|
+
"public",
|
|
33
|
+
]
|
|
34
34
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def configure(
|
|
35
|
+
@clearskies.parameters_to_properties.parameters_to_properties
|
|
36
|
+
def __init__(
|
|
39
37
|
self,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
stale_while_revalidate=None,
|
|
52
|
-
stale_if_error=None,
|
|
38
|
+
max_age: int | None = None,
|
|
39
|
+
s_maxage: int | None = None,
|
|
40
|
+
stale_while_revalidate: int | None = None,
|
|
41
|
+
stale_if_error: int | None = None,
|
|
42
|
+
immutable: bool = False,
|
|
43
|
+
must_understand: bool = False,
|
|
44
|
+
no_cache: bool = False,
|
|
45
|
+
no_store: bool = False,
|
|
46
|
+
no_transform: bool = False,
|
|
47
|
+
private: bool = False,
|
|
48
|
+
public: bool = False,
|
|
53
49
|
):
|
|
54
|
-
self.
|
|
55
|
-
self.no_cache = no_cache
|
|
56
|
-
self.no_store = no_store
|
|
57
|
-
self.no_transform = no_transform
|
|
58
|
-
self.s_maxage = s_maxage
|
|
59
|
-
self.must_understand = must_understand
|
|
60
|
-
self.private = private
|
|
61
|
-
self.public = public
|
|
62
|
-
self.immutable = immutable
|
|
63
|
-
self.stale_while_revalidate = stale_while_revalidate
|
|
64
|
-
self.stale_if_error = stale_if_error
|
|
50
|
+
self.finalize_and_validate_configuration()
|
|
65
51
|
|
|
66
52
|
def set_headers_for_input_output(self, input_output):
|
|
67
53
|
parts = []
|
|
68
|
-
for variable_name in bools:
|
|
54
|
+
for variable_name in self.bools:
|
|
69
55
|
value = getattr(self, variable_name)
|
|
70
56
|
if not value:
|
|
71
57
|
continue
|
|
72
58
|
parts.append(variable_name.replace("_", "-"))
|
|
73
|
-
for variable_name in numbers:
|
|
59
|
+
for variable_name in self.numbers:
|
|
74
60
|
value = getattr(self, variable_name)
|
|
75
61
|
if value is None:
|
|
76
62
|
continue
|
|
@@ -78,53 +64,4 @@ class CacheControl(Base):
|
|
|
78
64
|
parts.append(f"{key_name}={value}")
|
|
79
65
|
if not parts:
|
|
80
66
|
return
|
|
81
|
-
input_output.
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
# Use an explicity param list, even though long, so that Python can provide some input checking directly
|
|
85
|
-
def cache_control(
|
|
86
|
-
self,
|
|
87
|
-
no_cache=None,
|
|
88
|
-
no_store=None,
|
|
89
|
-
no_transform=None,
|
|
90
|
-
max_age=None,
|
|
91
|
-
s_maxage=None,
|
|
92
|
-
must_revalidate=None,
|
|
93
|
-
proxy_revalidate=None,
|
|
94
|
-
must_understand=None,
|
|
95
|
-
private=None,
|
|
96
|
-
public=None,
|
|
97
|
-
immutable=None,
|
|
98
|
-
stale_while_revalidate=None,
|
|
99
|
-
stale_if_error=None,
|
|
100
|
-
):
|
|
101
|
-
for variable_name in numbers:
|
|
102
|
-
value = locals()[variable_name]
|
|
103
|
-
if value is not None and type(value) != int:
|
|
104
|
-
actual_type = type(value)
|
|
105
|
-
raise ValueError(
|
|
106
|
-
f"Invalid configuration value for cache control: {variable_name} should be an integer but instead is '{actual_type}'"
|
|
107
|
-
)
|
|
108
|
-
for variable_name in bools:
|
|
109
|
-
value = locals()[variable_name]
|
|
110
|
-
if value is not None and type(value) != bool:
|
|
111
|
-
actual_type = type(value)
|
|
112
|
-
raise ValueError(
|
|
113
|
-
f"Invalid configuration value for cache control: {variable_name} should be True/False but instead is of type '{actual_type}'"
|
|
114
|
-
)
|
|
115
|
-
return BindingConfig(
|
|
116
|
-
CacheControl,
|
|
117
|
-
no_cache=no_cache,
|
|
118
|
-
no_store=no_store,
|
|
119
|
-
no_transform=no_transform,
|
|
120
|
-
max_age=max_age,
|
|
121
|
-
s_maxage=s_maxage,
|
|
122
|
-
must_revalidate=must_revalidate,
|
|
123
|
-
proxy_revalidate=proxy_revalidate,
|
|
124
|
-
must_understand=must_understand,
|
|
125
|
-
private=private,
|
|
126
|
-
public=public,
|
|
127
|
-
immutable=immutable,
|
|
128
|
-
stale_while_revalidate=stale_while_revalidate,
|
|
129
|
-
stale_if_error=stale_if_error,
|
|
130
|
-
)
|
|
67
|
+
input_output.response_headers.add("cache-control", ", ".join(parts))
|
|
@@ -1,105 +1,50 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
]
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
methods = None
|
|
14
|
-
headers = None
|
|
15
|
-
max_age = None
|
|
16
|
-
credentials = None
|
|
17
|
-
expose_headers = None
|
|
1
|
+
import clearskies.configs
|
|
2
|
+
import clearskies.parameters_to_properties
|
|
3
|
+
from clearskies.security_header import SecurityHeader
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Cors(SecurityHeader):
|
|
7
|
+
origin = clearskies.configs.String()
|
|
8
|
+
methods = clearskies.configs.StringList(default=[])
|
|
9
|
+
headers = clearskies.configs.StringList(default=[])
|
|
10
|
+
max_age = clearskies.configs.Integer(default=5)
|
|
11
|
+
credentials = clearskies.configs.Boolean(default=False)
|
|
12
|
+
expose_headers = clearskies.configs.StringList(default=[])
|
|
18
13
|
is_cors = True
|
|
19
14
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
15
|
+
@clearskies.parameters_to_properties.parameters_to_properties
|
|
16
|
+
def __init__(
|
|
17
|
+
self,
|
|
18
|
+
credentials: bool = False,
|
|
19
|
+
expose_headers: list[str] = [],
|
|
20
|
+
headers: list[str] = [],
|
|
21
|
+
max_age: int = 5,
|
|
22
|
+
methods: list[str] = [],
|
|
23
|
+
origin: str = "",
|
|
24
|
+
):
|
|
25
|
+
self.finalize_and_validate_configuration()
|
|
30
26
|
|
|
31
|
-
def set_headers(self, headers):
|
|
32
|
-
|
|
33
|
-
headers = ", ".join(headers)
|
|
34
|
-
self.headers = headers if headers is not None else ""
|
|
27
|
+
def set_headers(self, headers: list[str]):
|
|
28
|
+
self.headers = headers
|
|
35
29
|
|
|
36
|
-
def add_header(self, header):
|
|
37
|
-
|
|
38
|
-
self.headers = header
|
|
39
|
-
elif header not in self.headers:
|
|
40
|
-
self.headers += ", " + header
|
|
30
|
+
def add_header(self, header: str):
|
|
31
|
+
self.headers = [*self.headers, header]
|
|
41
32
|
|
|
42
|
-
def set_methods(self, methods):
|
|
43
|
-
|
|
44
|
-
methods = ", ".join(methods)
|
|
45
|
-
self.methods = methods if methods is not None else ""
|
|
33
|
+
def set_methods(self, methods: list[str]):
|
|
34
|
+
self.methods = methods
|
|
46
35
|
|
|
47
|
-
def add_method(self, method):
|
|
48
|
-
|
|
49
|
-
self.methods = method
|
|
50
|
-
elif method not in self.methods:
|
|
51
|
-
self.methods += ", " + method
|
|
36
|
+
def add_method(self, method: str):
|
|
37
|
+
self.methods = [*self.methods, method]
|
|
52
38
|
|
|
53
39
|
def set_headers_for_input_output(self, input_output):
|
|
54
|
-
for key in ["
|
|
55
|
-
|
|
40
|
+
for key in ["expose_headers", "methods", "headers"]:
|
|
41
|
+
value = getattr(self, key)
|
|
42
|
+
if not value:
|
|
56
43
|
continue
|
|
57
|
-
input_output.
|
|
44
|
+
input_output.response_headers.add(f"access-control-allow-{key}".replace("_", "-"), ", ".join(value))
|
|
58
45
|
if self.credentials:
|
|
59
|
-
input_output.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
input_output.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
def cors(origin=None, methods=None, headers=None, max_age=None, credentials=None, expose_headers=None):
|
|
67
|
-
# I didn't auto-pull into kwargs so that the allowed values are clearly defined.
|
|
68
|
-
# however, checking and processing will be easier with a dict
|
|
69
|
-
kwargs = {
|
|
70
|
-
"origin": origin,
|
|
71
|
-
"methods": methods,
|
|
72
|
-
"headers": headers,
|
|
73
|
-
"max_age": max_age,
|
|
74
|
-
"credentials": credentials,
|
|
75
|
-
"expose_headers": expose_headers,
|
|
76
|
-
}
|
|
77
|
-
allowed_types = {
|
|
78
|
-
"origin": str,
|
|
79
|
-
"max_age": int,
|
|
80
|
-
"credentials": bool,
|
|
81
|
-
}
|
|
82
|
-
for key in lists:
|
|
83
|
-
value = kwargs[key]
|
|
84
|
-
if value is None:
|
|
85
|
-
continue
|
|
86
|
-
actual_type = type(value)
|
|
87
|
-
if actual_type == list:
|
|
88
|
-
if not all([type(item) == str for item in value]):
|
|
89
|
-
raise ValueError(
|
|
90
|
-
f"Invalid configuration value for CORS: {key} should be a list of strings, but another kind of value was found"
|
|
91
|
-
)
|
|
92
|
-
kwargs[key] = ", ".join(value)
|
|
93
|
-
elif actual_type != str:
|
|
94
|
-
raise ValueError(
|
|
95
|
-
f"Invalid configuration value for CORS: {key} should be a string or list of strings but instead is '{actual_type}'"
|
|
96
|
-
)
|
|
97
|
-
for key, allowed_type in allowed_types.items():
|
|
98
|
-
if kwargs[key] is None:
|
|
99
|
-
continue
|
|
100
|
-
actual_type = type(kwargs[key])
|
|
101
|
-
if actual_type != allowed_type:
|
|
102
|
-
raise ValueError(
|
|
103
|
-
f"Invalid configuration value for CORS: {key} should be a {allowed_type} but instead is '{actual_type}'"
|
|
104
|
-
)
|
|
105
|
-
return BindingConfig(CORS, **kwargs)
|
|
46
|
+
input_output.response_headers.add("access-control-allow-credentials", "true")
|
|
47
|
+
if self.max_age:
|
|
48
|
+
input_output.response_headers.add("access-control-max-age", str(self.max_age))
|
|
49
|
+
if self.origin:
|
|
50
|
+
input_output.response_headers.add("access-control-allow-origin", str(self.origin))
|
|
@@ -1,169 +1,94 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import clearskies.configs
|
|
2
|
+
import clearskies.parameters_to_properties
|
|
3
|
+
from clearskies.security_header import SecurityHeader
|
|
3
4
|
|
|
4
|
-
directives = [
|
|
5
|
-
"default_src",
|
|
6
|
-
"script_src",
|
|
7
|
-
"style_src",
|
|
8
|
-
"img_src",
|
|
9
|
-
"connect_src",
|
|
10
|
-
"font_src",
|
|
11
|
-
"object_src",
|
|
12
|
-
"media_src",
|
|
13
|
-
"frame_src",
|
|
14
|
-
"sandbox",
|
|
15
|
-
"report_uri",
|
|
16
|
-
"child_src",
|
|
17
|
-
"form_action",
|
|
18
|
-
"frame_ancestors",
|
|
19
|
-
"plugin_types",
|
|
20
|
-
"base_uri",
|
|
21
|
-
"report_to",
|
|
22
|
-
"worker_src",
|
|
23
|
-
"manifest_src",
|
|
24
|
-
"prefetch_src",
|
|
25
|
-
"navigate_to",
|
|
26
|
-
]
|
|
27
5
|
|
|
28
|
-
|
|
29
|
-
class CSP(Base):
|
|
6
|
+
class Csp(SecurityHeader):
|
|
30
7
|
header_name = "content-security-policy"
|
|
31
|
-
default_src =
|
|
32
|
-
script_src =
|
|
33
|
-
style_src =
|
|
34
|
-
img_src =
|
|
35
|
-
connect_src =
|
|
36
|
-
font_src =
|
|
37
|
-
object_src =
|
|
38
|
-
media_src =
|
|
39
|
-
frame_src =
|
|
40
|
-
sandbox =
|
|
41
|
-
report_uri =
|
|
42
|
-
child_src =
|
|
43
|
-
form_action =
|
|
44
|
-
frame_ancestors =
|
|
45
|
-
plugin_types =
|
|
46
|
-
base_uri =
|
|
47
|
-
report_to =
|
|
48
|
-
worker_src =
|
|
49
|
-
manifest_src =
|
|
50
|
-
prefetch_src =
|
|
51
|
-
navigate_to =
|
|
8
|
+
default_src = clearskies.configs.String()
|
|
9
|
+
script_src = clearskies.configs.String()
|
|
10
|
+
style_src = clearskies.configs.String()
|
|
11
|
+
img_src = clearskies.configs.String()
|
|
12
|
+
connect_src = clearskies.configs.String()
|
|
13
|
+
font_src = clearskies.configs.String()
|
|
14
|
+
object_src = clearskies.configs.String()
|
|
15
|
+
media_src = clearskies.configs.String()
|
|
16
|
+
frame_src = clearskies.configs.String()
|
|
17
|
+
sandbox = clearskies.configs.String()
|
|
18
|
+
report_uri = clearskies.configs.String()
|
|
19
|
+
child_src = clearskies.configs.String()
|
|
20
|
+
form_action = clearskies.configs.String()
|
|
21
|
+
frame_ancestors = clearskies.configs.String()
|
|
22
|
+
plugin_types = clearskies.configs.String()
|
|
23
|
+
base_uri = clearskies.configs.String()
|
|
24
|
+
report_to = clearskies.configs.String()
|
|
25
|
+
worker_src = clearskies.configs.String()
|
|
26
|
+
manifest_src = clearskies.configs.String()
|
|
27
|
+
prefetch_src = clearskies.configs.String()
|
|
28
|
+
navigate_to = clearskies.configs.String()
|
|
52
29
|
|
|
53
|
-
|
|
54
|
-
|
|
30
|
+
directives = [
|
|
31
|
+
"default_src",
|
|
32
|
+
"script_src",
|
|
33
|
+
"style_src",
|
|
34
|
+
"img_src",
|
|
35
|
+
"connect_src",
|
|
36
|
+
"font_src",
|
|
37
|
+
"object_src",
|
|
38
|
+
"media_src",
|
|
39
|
+
"frame_src",
|
|
40
|
+
"sandbox",
|
|
41
|
+
"report_uri",
|
|
42
|
+
"child_src",
|
|
43
|
+
"form_action",
|
|
44
|
+
"frame_ancestors",
|
|
45
|
+
"plugin_types",
|
|
46
|
+
"base_uri",
|
|
47
|
+
"report_to",
|
|
48
|
+
"worker_src",
|
|
49
|
+
"manifest_src",
|
|
50
|
+
"prefetch_src",
|
|
51
|
+
"navigate_to",
|
|
52
|
+
]
|
|
55
53
|
|
|
56
|
-
|
|
54
|
+
@clearskies.parameters_to_properties.parameters_to_properties
|
|
55
|
+
def __init__(
|
|
57
56
|
self,
|
|
58
|
-
default_src=
|
|
59
|
-
script_src=
|
|
60
|
-
style_src=
|
|
61
|
-
img_src=
|
|
62
|
-
connect_src=
|
|
63
|
-
font_src=
|
|
64
|
-
object_src=
|
|
65
|
-
media_src=
|
|
66
|
-
frame_src=
|
|
67
|
-
sandbox=
|
|
68
|
-
report_uri=
|
|
69
|
-
child_src=
|
|
70
|
-
form_action=
|
|
71
|
-
frame_ancestors=
|
|
72
|
-
plugin_types=
|
|
73
|
-
base_uri=
|
|
74
|
-
report_to=
|
|
75
|
-
worker_src=
|
|
76
|
-
manifest_src=
|
|
77
|
-
prefetch_src=
|
|
78
|
-
navigate_to=
|
|
57
|
+
default_src: str = "",
|
|
58
|
+
script_src: str = "",
|
|
59
|
+
style_src: str = "",
|
|
60
|
+
img_src: str = "",
|
|
61
|
+
connect_src: str = "",
|
|
62
|
+
font_src: str = "",
|
|
63
|
+
object_src: str = "",
|
|
64
|
+
media_src: str = "",
|
|
65
|
+
frame_src: str = "",
|
|
66
|
+
sandbox: str = "",
|
|
67
|
+
report_uri: str = "",
|
|
68
|
+
child_src: str = "",
|
|
69
|
+
form_action: str = "",
|
|
70
|
+
frame_ancestors: str = "",
|
|
71
|
+
plugin_types: str = "",
|
|
72
|
+
base_uri: str = "",
|
|
73
|
+
report_to: str = "",
|
|
74
|
+
worker_src: str = "",
|
|
75
|
+
manifest_src: str = "",
|
|
76
|
+
prefetch_src: str = "",
|
|
77
|
+
navigate_to: str = "",
|
|
79
78
|
):
|
|
80
|
-
self.
|
|
81
|
-
self.script_src = script_src
|
|
82
|
-
self.style_src = style_src
|
|
83
|
-
self.img_src = img_src
|
|
84
|
-
self.connect_src = connect_src
|
|
85
|
-
self.font_src = font_src
|
|
86
|
-
self.object_src = object_src
|
|
87
|
-
self.media_src = media_src
|
|
88
|
-
self.frame_src = frame_src
|
|
89
|
-
self.sandbox = sandbox
|
|
90
|
-
self.report_uri = report_uri
|
|
91
|
-
self.child_src = child_src
|
|
92
|
-
self.form_action = form_action
|
|
93
|
-
self.frame_ancestors = frame_ancestors
|
|
94
|
-
self.plugin_types = plugin_types
|
|
95
|
-
self.base_uri = base_uri
|
|
96
|
-
self.report_to = report_to
|
|
97
|
-
self.worker_src = worker_src
|
|
98
|
-
self.manifest_src = manifest_src
|
|
99
|
-
self.prefetch_src = prefetch_src
|
|
100
|
-
self.navigate_to = navigate_to
|
|
79
|
+
self.finalize_and_validate_configuration()
|
|
101
80
|
|
|
102
81
|
def set_headers_for_input_output(self, input_output):
|
|
103
82
|
parts = []
|
|
104
|
-
for variable_name in directives:
|
|
83
|
+
for variable_name in self.directives:
|
|
105
84
|
value = getattr(self, variable_name)
|
|
106
85
|
if not value:
|
|
107
86
|
continue
|
|
87
|
+
if value.lower().strip() == "self":
|
|
88
|
+
value = "'self'"
|
|
108
89
|
header_key_name = variable_name.replace("_", "-")
|
|
109
90
|
parts.append(f"{header_key_name} {value}")
|
|
110
91
|
if not parts:
|
|
111
92
|
return
|
|
112
93
|
header_value = "; ".join(parts)
|
|
113
|
-
input_output.
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
def csp(
|
|
117
|
-
default_src=None,
|
|
118
|
-
script_src=None,
|
|
119
|
-
style_src=None,
|
|
120
|
-
img_src=None,
|
|
121
|
-
connect_src=None,
|
|
122
|
-
font_src=None,
|
|
123
|
-
object_src=None,
|
|
124
|
-
media_src=None,
|
|
125
|
-
frame_src=None,
|
|
126
|
-
sandbox=None,
|
|
127
|
-
report_uri=None,
|
|
128
|
-
child_src=None,
|
|
129
|
-
form_action=None,
|
|
130
|
-
frame_ancestors=None,
|
|
131
|
-
plugin_types=None,
|
|
132
|
-
base_uri=None,
|
|
133
|
-
report_to=None,
|
|
134
|
-
worker_src=None,
|
|
135
|
-
manifest_src=None,
|
|
136
|
-
prefetch_src=None,
|
|
137
|
-
navigate_to=None,
|
|
138
|
-
):
|
|
139
|
-
for variable_name in directives:
|
|
140
|
-
value = locals()[variable_name]
|
|
141
|
-
if value is not None and type(value) != str:
|
|
142
|
-
actual_type = type(value)
|
|
143
|
-
raise ValueError(
|
|
144
|
-
f"Invalid configuration value for CSP: {variable_name} should be a string but instead is '{actual_type}'"
|
|
145
|
-
)
|
|
146
|
-
return BindingConfig(
|
|
147
|
-
CSP,
|
|
148
|
-
default_src=default_src,
|
|
149
|
-
script_src=script_src,
|
|
150
|
-
style_src=style_src,
|
|
151
|
-
img_src=img_src,
|
|
152
|
-
connect_src=connect_src,
|
|
153
|
-
font_src=font_src,
|
|
154
|
-
object_src=object_src,
|
|
155
|
-
media_src=media_src,
|
|
156
|
-
frame_src=frame_src,
|
|
157
|
-
sandbox=sandbox,
|
|
158
|
-
report_uri=report_uri,
|
|
159
|
-
child_src=child_src,
|
|
160
|
-
form_action=form_action,
|
|
161
|
-
frame_ancestors=frame_ancestors,
|
|
162
|
-
plugin_types=plugin_types,
|
|
163
|
-
base_uri=base_uri,
|
|
164
|
-
report_to=report_to,
|
|
165
|
-
worker_src=worker_src,
|
|
166
|
-
manifest_src=manifest_src,
|
|
167
|
-
prefetch_src=prefetch_src,
|
|
168
|
-
navigate_to=navigate_to,
|
|
169
|
-
)
|
|
94
|
+
input_output.response_headers.add(self.header_name, header_value)
|
|
@@ -1,24 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import clearskies.configs
|
|
2
|
+
import clearskies.parameters_to_properties
|
|
3
|
+
from clearskies.security_header import SecurityHeader
|
|
3
4
|
|
|
4
5
|
|
|
5
|
-
class
|
|
6
|
-
max_age =
|
|
7
|
-
include_sub_domains =
|
|
6
|
+
class Hsts(SecurityHeader):
|
|
7
|
+
max_age = clearskies.configs.Integer(default=31536000)
|
|
8
|
+
include_sub_domains = clearskies.configs.Boolean()
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
@clearskies.parameters_to_properties.parameters_to_properties
|
|
11
|
+
def __init__(
|
|
12
|
+
self,
|
|
13
|
+
max_age: int = 31536000,
|
|
14
|
+
include_sub_domains: bool = False,
|
|
15
|
+
):
|
|
16
|
+
self.finalize_and_validate_configuration()
|
|
15
17
|
|
|
16
18
|
def set_headers_for_input_output(self, input_output):
|
|
17
19
|
value = f"max-age={self.max_age} ;"
|
|
18
20
|
if self.include_sub_domains:
|
|
19
21
|
value += " includeSubDomains"
|
|
20
|
-
input_output.
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def hsts(max_age=31536000, include_sub_domains=False):
|
|
24
|
-
return BindingConfig(HSTS, max_age=max_age, include_sub_domains=include_sub_domains)
|
|
22
|
+
input_output.response_headers.add("strict-transport-security", value)
|
clearskies/test_base.py
ADDED
clearskies/typing.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
from typing import Any, Callable
|
|
2
|
+
|
|
3
|
+
from clearskies.action import Action
|
|
4
|
+
from clearskies.query.condition import Condition
|
|
5
|
+
from clearskies.validator import Validator
|
|
6
|
+
|
|
7
|
+
action = Callable[..., dict[str, Any]] | Action
|
|
8
|
+
condition = str | Callable | Condition
|
|
9
|
+
join = str | Callable[..., str]
|
|
10
|
+
validator = Callable[..., str] | Validator
|
|
11
|
+
response = str | bytes | dict[str, Any] | list[Any]
|
clearskies/validator.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from typing import TYPE_CHECKING, Any
|
|
5
|
+
|
|
6
|
+
from clearskies import configurable
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
import clearskies.column
|
|
10
|
+
import clearskies.model
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Validator(ABC, configurable.Configurable):
|
|
14
|
+
is_unique = False
|
|
15
|
+
is_required = False
|
|
16
|
+
|
|
17
|
+
def __call__(self, model: clearskies.model.Model, column_name: str, data: dict[str, Any]) -> str:
|
|
18
|
+
return self.check(model, column_name, data)
|
|
19
|
+
|
|
20
|
+
@abstractmethod
|
|
21
|
+
def check(self, model: clearskies.model.Model, column_name: str, data: dict[str, Any]) -> str:
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
def additional_write_columns(self, is_create=False) -> dict[str, clearskies.column.Column]:
|
|
25
|
+
return {}
|