clear-skies 1.22.10__py3-none-any.whl → 2.0.23__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.
- clear_skies-2.0.23.dist-info/METADATA +76 -0
- clear_skies-2.0.23.dist-info/RECORD +265 -0
- {clear_skies-1.22.10.dist-info → clear_skies-2.0.23.dist-info}/WHEEL +1 -1
- clearskies/__init__.py +37 -21
- clearskies/action.py +7 -0
- clearskies/authentication/__init__.py +8 -39
- clearskies/authentication/authentication.py +44 -0
- clearskies/authentication/authorization.py +14 -8
- clearskies/authentication/authorization_pass_through.py +14 -10
- clearskies/authentication/jwks.py +135 -58
- clearskies/authentication/public.py +3 -26
- clearskies/authentication/secret_bearer.py +515 -44
- clearskies/autodoc/formats/oai3_json/__init__.py +2 -2
- clearskies/autodoc/formats/oai3_json/oai3_json.py +11 -9
- 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 +10 -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 +16 -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 +1118 -280
- clearskies/backends/backend.py +54 -85
- clearskies/backends/cursor_backend.py +246 -191
- clearskies/backends/memory_backend.py +514 -208
- clearskies/backends/secrets_backend.py +68 -31
- clearskies/column.py +1221 -0
- clearskies/columns/__init__.py +71 -0
- clearskies/columns/audit.py +306 -0
- clearskies/columns/belongs_to_id.py +478 -0
- clearskies/columns/belongs_to_model.py +129 -0
- clearskies/columns/belongs_to_self.py +109 -0
- clearskies/columns/boolean.py +110 -0
- clearskies/columns/category_tree.py +273 -0
- clearskies/columns/category_tree_ancestors.py +51 -0
- clearskies/columns/category_tree_children.py +126 -0
- clearskies/columns/category_tree_descendants.py +48 -0
- clearskies/columns/created.py +92 -0
- clearskies/columns/created_by_authorization_data.py +114 -0
- clearskies/columns/created_by_header.py +103 -0
- clearskies/columns/created_by_ip.py +90 -0
- clearskies/columns/created_by_routing_data.py +102 -0
- clearskies/columns/created_by_user_agent.py +89 -0
- clearskies/columns/date.py +232 -0
- clearskies/columns/datetime.py +284 -0
- clearskies/columns/email.py +78 -0
- clearskies/columns/float.py +149 -0
- clearskies/columns/has_many.py +529 -0
- clearskies/columns/has_many_self.py +62 -0
- clearskies/columns/has_one.py +21 -0
- clearskies/columns/integer.py +158 -0
- clearskies/columns/json.py +126 -0
- clearskies/columns/many_to_many_ids.py +335 -0
- clearskies/columns/many_to_many_ids_with_data.py +274 -0
- clearskies/columns/many_to_many_models.py +156 -0
- clearskies/columns/many_to_many_pivots.py +132 -0
- clearskies/columns/phone.py +162 -0
- clearskies/columns/select.py +95 -0
- clearskies/columns/string.py +102 -0
- clearskies/columns/timestamp.py +164 -0
- clearskies/columns/updated.py +107 -0
- clearskies/columns/uuid.py +83 -0
- clearskies/configs/README.md +105 -0
- clearskies/configs/__init__.py +170 -0
- clearskies/configs/actions.py +43 -0
- clearskies/configs/any.py +15 -0
- clearskies/configs/any_dict.py +24 -0
- clearskies/configs/any_dict_or_callable.py +25 -0
- clearskies/configs/authentication.py +23 -0
- clearskies/configs/authorization.py +23 -0
- clearskies/configs/boolean.py +18 -0
- clearskies/configs/boolean_or_callable.py +20 -0
- clearskies/configs/callable_config.py +20 -0
- clearskies/configs/columns.py +34 -0
- clearskies/configs/conditions.py +30 -0
- clearskies/configs/config.py +26 -0
- clearskies/configs/datetime.py +20 -0
- clearskies/configs/datetime_or_callable.py +21 -0
- clearskies/configs/email.py +10 -0
- clearskies/configs/email_list.py +17 -0
- clearskies/configs/email_list_or_callable.py +17 -0
- clearskies/configs/email_or_email_list_or_callable.py +59 -0
- clearskies/configs/endpoint.py +23 -0
- clearskies/configs/endpoint_list.py +29 -0
- clearskies/configs/float.py +18 -0
- clearskies/configs/float_or_callable.py +20 -0
- clearskies/configs/headers.py +28 -0
- clearskies/configs/integer.py +18 -0
- clearskies/configs/integer_or_callable.py +20 -0
- clearskies/configs/joins.py +30 -0
- clearskies/configs/list_any_dict.py +32 -0
- clearskies/configs/list_any_dict_or_callable.py +33 -0
- clearskies/configs/model_class.py +35 -0
- clearskies/configs/model_column.py +67 -0
- clearskies/configs/model_columns.py +58 -0
- clearskies/configs/model_destination_name.py +26 -0
- clearskies/configs/model_to_id_column.py +45 -0
- clearskies/configs/readable_model_column.py +11 -0
- clearskies/configs/readable_model_columns.py +11 -0
- clearskies/configs/schema.py +23 -0
- clearskies/configs/searchable_model_columns.py +11 -0
- clearskies/configs/security_headers.py +39 -0
- clearskies/configs/select.py +28 -0
- clearskies/configs/select_list.py +49 -0
- clearskies/configs/string.py +31 -0
- clearskies/configs/string_dict.py +34 -0
- clearskies/configs/string_list.py +47 -0
- clearskies/configs/string_list_or_callable.py +48 -0
- clearskies/configs/string_or_callable.py +18 -0
- clearskies/configs/timedelta.py +20 -0
- clearskies/configs/timezone.py +20 -0
- clearskies/configs/url.py +25 -0
- clearskies/configs/validators.py +45 -0
- clearskies/configs/writeable_model_column.py +11 -0
- clearskies/configs/writeable_model_columns.py +11 -0
- clearskies/configurable.py +78 -0
- clearskies/contexts/__init__.py +8 -8
- clearskies/contexts/cli.py +129 -43
- clearskies/contexts/context.py +93 -56
- clearskies/contexts/wsgi.py +79 -33
- clearskies/contexts/wsgi_ref.py +87 -0
- clearskies/cursors/__init__.py +7 -0
- clearskies/cursors/cursor.py +166 -0
- clearskies/cursors/from_environment/__init__.py +5 -0
- clearskies/cursors/from_environment/mysql.py +51 -0
- clearskies/cursors/from_environment/postgresql.py +49 -0
- clearskies/cursors/from_environment/sqlite.py +35 -0
- clearskies/cursors/mysql.py +61 -0
- clearskies/cursors/postgresql.py +61 -0
- clearskies/cursors/sqlite.py +62 -0
- clearskies/decorators.py +33 -0
- clearskies/decorators.pyi +10 -0
- clearskies/di/__init__.py +11 -7
- clearskies/di/additional_config.py +115 -4
- clearskies/di/additional_config_auto_import.py +12 -0
- clearskies/di/di.py +714 -125
- clearskies/di/inject/__init__.py +23 -0
- clearskies/di/inject/akeyless_sdk.py +16 -0
- clearskies/di/inject/by_class.py +24 -0
- clearskies/di/inject/by_name.py +22 -0
- clearskies/di/inject/di.py +16 -0
- clearskies/di/inject/environment.py +15 -0
- clearskies/di/inject/input_output.py +19 -0
- clearskies/di/inject/now.py +16 -0
- clearskies/di/inject/requests.py +16 -0
- clearskies/di/inject/secrets.py +15 -0
- clearskies/di/inject/utcnow.py +16 -0
- clearskies/di/inject/uuid.py +16 -0
- clearskies/di/injectable.py +32 -0
- clearskies/di/injectable_properties.py +131 -0
- clearskies/end.py +219 -0
- clearskies/endpoint.py +1303 -0
- clearskies/endpoint_group.py +333 -0
- clearskies/endpoints/__init__.py +25 -0
- clearskies/endpoints/advanced_search.py +519 -0
- clearskies/endpoints/callable.py +382 -0
- clearskies/endpoints/create.py +201 -0
- clearskies/endpoints/delete.py +133 -0
- clearskies/endpoints/get.py +267 -0
- clearskies/endpoints/health_check.py +181 -0
- clearskies/endpoints/list.py +567 -0
- clearskies/endpoints/restful_api.py +417 -0
- clearskies/endpoints/schema.py +185 -0
- clearskies/endpoints/simple_search.py +279 -0
- clearskies/endpoints/update.py +188 -0
- clearskies/environment.py +7 -3
- clearskies/exceptions/__init__.py +19 -0
- clearskies/{handlers/exceptions/input_error.py → exceptions/input_errors.py} +1 -1
- clearskies/exceptions/missing_dependency.py +2 -0
- clearskies/exceptions/moved_permanently.py +3 -0
- clearskies/exceptions/moved_temporarily.py +3 -0
- clearskies/functional/__init__.py +2 -2
- clearskies/functional/json.py +47 -0
- 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 +135 -160
- clearskies/input_outputs/exceptions/__init__.py +6 -1
- clearskies/input_outputs/headers.py +54 -0
- clearskies/input_outputs/input_output.py +77 -123
- clearskies/input_outputs/programmatic.py +62 -0
- clearskies/input_outputs/wsgi.py +36 -48
- clearskies/model.py +1874 -193
- clearskies/query/__init__.py +12 -0
- clearskies/query/condition.py +228 -0
- clearskies/query/join.py +136 -0
- clearskies/query/query.py +193 -0
- clearskies/query/sort.py +27 -0
- clearskies/schema.py +82 -0
- clearskies/secrets/__init__.py +4 -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 +421 -155
- clearskies/secrets/exceptions/__init__.py +7 -1
- clearskies/secrets/exceptions/not_found_error.py +2 -0
- clearskies/secrets/exceptions/permissions_error.py +2 -0
- clearskies/secrets/secrets.py +12 -11
- clearskies/security_header.py +17 -0
- clearskies/security_headers/__init__.py +8 -8
- clearskies/security_headers/cache_control.py +47 -109
- clearskies/security_headers/cors.py +38 -92
- clearskies/security_headers/csp.py +76 -150
- clearskies/security_headers/hsts.py +14 -15
- clearskies/typing.py +11 -0
- clearskies/validator.py +36 -0
- clearskies/validators/__init__.py +33 -0
- clearskies/validators/after_column.py +61 -0
- clearskies/validators/before_column.py +15 -0
- clearskies/validators/in_the_future.py +29 -0
- clearskies/validators/in_the_future_at_least.py +13 -0
- clearskies/validators/in_the_future_at_most.py +12 -0
- clearskies/validators/in_the_past.py +29 -0
- clearskies/validators/in_the_past_at_least.py +12 -0
- clearskies/validators/in_the_past_at_most.py +12 -0
- clearskies/validators/maximum_length.py +25 -0
- clearskies/validators/maximum_value.py +28 -0
- clearskies/validators/minimum_length.py +25 -0
- clearskies/validators/minimum_value.py +28 -0
- clearskies/{input_requirements → validators}/required.py +18 -9
- clearskies/validators/timedelta.py +58 -0
- clearskies/validators/unique.py +28 -0
- clear_skies-1.22.10.dist-info/METADATA +0 -47
- clear_skies-1.22.10.dist-info/RECORD +0 -213
- 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 -13
- 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 -58
- 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 -39
- 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/di/test_module/__init__.py +0 -6
- clearskies/di/test_module/another_module/__init__.py +0 -2
- clearskies/di/test_module/module_class.py +0 -5
- clearskies/handlers/__init__.py +0 -41
- clearskies/handlers/advanced_search.py +0 -271
- clearskies/handlers/base.py +0 -479
- clearskies/handlers/callable.py +0 -191
- 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 -192
- clearskies/handlers/simple_search.py +0 -136
- clearskies/handlers/update.py +0 -96
- 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/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.10.dist-info → clear_skies-2.0.23.dist-info/licenses}/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/{secrets/exceptions → exceptions}/not_found.py +0 -0
- /clearskies/{tests/__init__.py → input_outputs/py.typed} +0 -0
- /clearskies/{tests/simple_api/__init__.py → py.typed} +0 -0
clearskies/handlers/create.py
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
from .write import Write
|
|
2
|
-
from .exceptions import InputError
|
|
3
|
-
from collections import OrderedDict
|
|
4
|
-
from ..functional import string
|
|
5
|
-
import json
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class Create(Write):
|
|
9
|
-
_is_create = True
|
|
10
|
-
|
|
11
|
-
def __init__(self, di, logging):
|
|
12
|
-
super().__init__(di)
|
|
13
|
-
self._logging = logging
|
|
14
|
-
|
|
15
|
-
def handle(self, input_output):
|
|
16
|
-
model = self._model.empty_model()
|
|
17
|
-
input_data = self.request_data(input_output)
|
|
18
|
-
self._logging.debug("Incoming request data: " + json.dumps(input_data))
|
|
19
|
-
input_errors = {
|
|
20
|
-
**self._extra_column_errors(input_data),
|
|
21
|
-
**self._find_input_errors(model, input_data, input_output),
|
|
22
|
-
}
|
|
23
|
-
if input_errors:
|
|
24
|
-
self._logging.debug("Request rejected due to input errors: " + json.dumps(input_errors))
|
|
25
|
-
raise InputError(input_errors)
|
|
26
|
-
model.save(input_data, columns=self._columns)
|
|
27
|
-
|
|
28
|
-
return self.success(input_output, self._model_as_json(model, input_output))
|
|
29
|
-
|
|
30
|
-
def documentation(self):
|
|
31
|
-
nice_model = string.camel_case_to_words(self._model.__class__.__name__)
|
|
32
|
-
return self._documentation(
|
|
33
|
-
description=f"Create a new {nice_model}",
|
|
34
|
-
response_description=f"The new {nice_model}",
|
|
35
|
-
)
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
from .request_method_routing import RequestMethodRouting
|
|
2
|
-
from .create import Create
|
|
3
|
-
from .update import Update
|
|
4
|
-
from .delete import Delete
|
|
5
|
-
from .get import Get
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class CRUDByMethod(RequestMethodRouting):
|
|
9
|
-
def __init__(self, di):
|
|
10
|
-
super().__init__(di)
|
|
11
|
-
|
|
12
|
-
def method_handler_map(self):
|
|
13
|
-
return {
|
|
14
|
-
"CREATE": Create,
|
|
15
|
-
"GET": Get,
|
|
16
|
-
"PATCH": Update,
|
|
17
|
-
"DELETE": Delete,
|
|
18
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
from .base import Base
|
|
2
|
-
import os
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class DatabaseConnector(Base):
|
|
6
|
-
_configuration_defaults = {
|
|
7
|
-
"tunnel_only": False,
|
|
8
|
-
"command": "mysql",
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
def __init__(self, di):
|
|
12
|
-
super().__init__(di)
|
|
13
|
-
|
|
14
|
-
def handle(self, input_output):
|
|
15
|
-
connection_details = self._di.build("connection_details")
|
|
16
|
-
request_body = input_output.json_body(required=False)
|
|
17
|
-
if request_body and "tunnel_only" in request_body:
|
|
18
|
-
tunnel_only = request_body["tunnel_only"]
|
|
19
|
-
else:
|
|
20
|
-
tunnel_only = self.configuration("tunnel_only")
|
|
21
|
-
|
|
22
|
-
if tunnel_only:
|
|
23
|
-
return self.success(input_output, {})
|
|
24
|
-
|
|
25
|
-
command = self.configuration("command")
|
|
26
|
-
port = connection_details.get("port", 3306)
|
|
27
|
-
print("connect!")
|
|
28
|
-
print(connection_details["host"])
|
|
29
|
-
os.system(
|
|
30
|
-
f"{command} -h {connection_details['host']} -u '{connection_details['username']}' -p'{connection_details['password']}' --port={port} -D {connection_details['database']}"
|
|
31
|
-
)
|
|
32
|
-
print("done!")
|
clearskies/handlers/delete.py
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
from collections import OrderedDict
|
|
2
|
-
from .base import Base
|
|
3
|
-
from .. import autodoc
|
|
4
|
-
from ..functional import string
|
|
5
|
-
from .get import Get
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class Delete(Get):
|
|
9
|
-
_configuration_defaults = {
|
|
10
|
-
"model": None,
|
|
11
|
-
"model_class": None,
|
|
12
|
-
"readable_columns": None,
|
|
13
|
-
"where": [],
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
def __init__(self, di):
|
|
17
|
-
super().__init__(di)
|
|
18
|
-
|
|
19
|
-
def handle(self, input_output):
|
|
20
|
-
model = self.fetch_model(input_output)
|
|
21
|
-
if type(model) == str:
|
|
22
|
-
return self.error(input_output, model, 404)
|
|
23
|
-
|
|
24
|
-
model.delete()
|
|
25
|
-
return self.success(input_output, {})
|
|
26
|
-
|
|
27
|
-
def documentation(self):
|
|
28
|
-
nice_model = string.camel_case_to_words(self._model.__class__.__name__)
|
|
29
|
-
|
|
30
|
-
authentication = self.configuration("authentication")
|
|
31
|
-
standard_error_responses = []
|
|
32
|
-
if not getattr(authentication, "is_public", False):
|
|
33
|
-
standard_error_responses.append(self.documentation_access_denied_response())
|
|
34
|
-
if getattr(authentication, "can_authorize", False):
|
|
35
|
-
standard_error_responses.append(self.documentation_unauthorized_response())
|
|
36
|
-
|
|
37
|
-
id_label = "id" if self.configuration("id_column_name") else self.id_column_name
|
|
38
|
-
return [
|
|
39
|
-
autodoc.request.Request(
|
|
40
|
-
"Delete the " + nice_model + " with an " + id_label + " of {" + id_label + "}",
|
|
41
|
-
[
|
|
42
|
-
self.documentation_success_response(
|
|
43
|
-
autodoc.schema.Object("data", children=[]),
|
|
44
|
-
description=f"The {nice_model} was deleted",
|
|
45
|
-
),
|
|
46
|
-
*standard_error_responses,
|
|
47
|
-
self.documentation_not_found(),
|
|
48
|
-
],
|
|
49
|
-
relative_path=self.configuration("base_url").rstrip("/") + "/{" + id_label + "}",
|
|
50
|
-
parameters=[
|
|
51
|
-
autodoc.request.URLPath(
|
|
52
|
-
autodoc.schema.Integer(id_label),
|
|
53
|
-
description=f"The {id_label} of the record to delete.",
|
|
54
|
-
required=True,
|
|
55
|
-
)
|
|
56
|
-
],
|
|
57
|
-
root_properties={
|
|
58
|
-
"security": self.documentation_request_security(),
|
|
59
|
-
},
|
|
60
|
-
)
|
|
61
|
-
]
|
clearskies/handlers/get.py
DELETED
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
from .base import Base
|
|
2
|
-
from collections import OrderedDict
|
|
3
|
-
from .. import autodoc
|
|
4
|
-
from .. import condition_parser
|
|
5
|
-
from ..functional import string
|
|
6
|
-
import inspect
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class Get(Base):
|
|
10
|
-
_model = None
|
|
11
|
-
|
|
12
|
-
_configuration_defaults = {
|
|
13
|
-
"model": None,
|
|
14
|
-
"model_class": None,
|
|
15
|
-
"readable_columns": None,
|
|
16
|
-
"where": [],
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
def __init__(self, di):
|
|
20
|
-
super().__init__(di)
|
|
21
|
-
|
|
22
|
-
def handle(self, input_output):
|
|
23
|
-
model = self.fetch_model(input_output)
|
|
24
|
-
if type(model) == str:
|
|
25
|
-
return self.error(input_output, model, 404)
|
|
26
|
-
return self.success(input_output, self._model_as_json(model, input_output))
|
|
27
|
-
|
|
28
|
-
def get_model_id(self, input_output):
|
|
29
|
-
routing_data = input_output.routing_data()
|
|
30
|
-
if self.id_column_name in routing_data:
|
|
31
|
-
return routing_data[self.id_column_name]
|
|
32
|
-
if "id" in routing_data:
|
|
33
|
-
return routing_data["id"]
|
|
34
|
-
raise ValueError("I didn't receive the ID in my routing data. I am probably misconfigured.")
|
|
35
|
-
|
|
36
|
-
def fetch_model(self, input_output):
|
|
37
|
-
id = self.get_model_id(input_output)
|
|
38
|
-
models = self._model.where(f"{self.id_column_name}={id}")
|
|
39
|
-
for where in self.configuration("where"):
|
|
40
|
-
if type(where) == str:
|
|
41
|
-
models = models.where(where)
|
|
42
|
-
else:
|
|
43
|
-
models = self._di.call_function(
|
|
44
|
-
where,
|
|
45
|
-
models=models,
|
|
46
|
-
input_output=input_output,
|
|
47
|
-
routing_data=input_output.routing_data(),
|
|
48
|
-
authorization_data=input_output.get_authorization_data(),
|
|
49
|
-
)
|
|
50
|
-
models = models.where_for_request(
|
|
51
|
-
models,
|
|
52
|
-
input_output.routing_data(),
|
|
53
|
-
input_output.get_authorization_data(),
|
|
54
|
-
input_output,
|
|
55
|
-
)
|
|
56
|
-
authorization = self._configuration.get("authorization", None)
|
|
57
|
-
if authorization and hasattr(authorization, "filter_models"):
|
|
58
|
-
models = authorization.filter_models(models, input_output.get_authorization_data(), input_output)
|
|
59
|
-
model = models.first()
|
|
60
|
-
if not model.exists:
|
|
61
|
-
return "Not Found"
|
|
62
|
-
|
|
63
|
-
return model
|
|
64
|
-
|
|
65
|
-
def _check_configuration(self, configuration):
|
|
66
|
-
super()._check_configuration(configuration)
|
|
67
|
-
error_prefix = "Configuration error for %s:" % (self.__class__.__name__)
|
|
68
|
-
has_model_class = ("model_class" in configuration) and configuration["model_class"] is not None
|
|
69
|
-
has_model = ("model" in configuration) and configuration["model"] is not None
|
|
70
|
-
if not has_model and not has_model_class:
|
|
71
|
-
raise KeyError(f"{error_prefix} you must specify 'model' or 'model_class'")
|
|
72
|
-
if has_model and has_model_class:
|
|
73
|
-
raise KeyError(f"{error_prefix} you specified both 'model' and 'model_class', but can only provide one")
|
|
74
|
-
if has_model and inspect.isclass(configuration["model"]):
|
|
75
|
-
raise ValueError(
|
|
76
|
-
"{error_prefix} you must provide a model instance in the 'model' configuration setting, but a class was provided instead"
|
|
77
|
-
)
|
|
78
|
-
if "where" in configuration:
|
|
79
|
-
if not hasattr(configuration["where"], "__iter__") or type(configuration["where"]) == str:
|
|
80
|
-
raise ValueError(
|
|
81
|
-
f"{error_prefix} 'where' should be an iterable of coditions or callables "
|
|
82
|
-
+ ", not "
|
|
83
|
-
+ str(type(configuration["where"])),
|
|
84
|
-
)
|
|
85
|
-
for index, where in enumerate(configuration["where"]):
|
|
86
|
-
if type(where) != str and not callable(where):
|
|
87
|
-
raise ValueError(
|
|
88
|
-
f"{error_prefix} 'where' entry should be a string with a condition or a callable that filters models "
|
|
89
|
-
+ f", but entry #{index+1} is neither of these",
|
|
90
|
-
)
|
|
91
|
-
self._model = self._di.build(configuration["model_class"]) if has_model_class else configuration["model"]
|
|
92
|
-
self._columns = self._model.columns(overrides=configuration.get("column_overrides"))
|
|
93
|
-
|
|
94
|
-
def _get_readable_columns(self):
|
|
95
|
-
resolved_columns = OrderedDict()
|
|
96
|
-
for column_name in self.configuration("readable_columns"):
|
|
97
|
-
if column_name not in self._columns:
|
|
98
|
-
class_name = self.__class__.__name__
|
|
99
|
-
model_class = self._model.__class__.__name__
|
|
100
|
-
raise ValueError(
|
|
101
|
-
f"Handler {class_name} was configured with readable column '{column_name}' but this "
|
|
102
|
-
+ f"column doesn't exist for model {model_class}"
|
|
103
|
-
)
|
|
104
|
-
resolved_columns[column_name] = self._columns[column_name]
|
|
105
|
-
return resolved_columns
|
|
106
|
-
|
|
107
|
-
def documentation(self):
|
|
108
|
-
nice_model = string.camel_case_to_words(self._model.__class__.__name__)
|
|
109
|
-
|
|
110
|
-
authentication = self.configuration("authentication")
|
|
111
|
-
standard_error_responses = []
|
|
112
|
-
if not getattr(authentication, "is_public", False):
|
|
113
|
-
standard_error_responses.append(self.documentation_access_denied_response())
|
|
114
|
-
if getattr(authentication, "can_authorize", False):
|
|
115
|
-
standard_error_responses.append(self.documentation_unauthorized_response())
|
|
116
|
-
|
|
117
|
-
id_label = "id" if self.configuration("id_column_name") else self.id_column_name
|
|
118
|
-
|
|
119
|
-
return [
|
|
120
|
-
autodoc.request.Request(
|
|
121
|
-
"Fetch the " + nice_model + " with an " + id_label + " of {" + id_label + "}",
|
|
122
|
-
[
|
|
123
|
-
self.documentation_success_response(
|
|
124
|
-
autodoc.schema.Object(
|
|
125
|
-
"data",
|
|
126
|
-
children=self.documentation_data_schema(),
|
|
127
|
-
model_name=string.camel_case_to_snake_case(self._model.__class__.__name__),
|
|
128
|
-
),
|
|
129
|
-
description=f"The {nice_model} record",
|
|
130
|
-
),
|
|
131
|
-
*standard_error_responses,
|
|
132
|
-
self.documentation_not_found(),
|
|
133
|
-
],
|
|
134
|
-
relative_path=self.configuration("base_url").rstrip("/") + "/{" + id_label + "}",
|
|
135
|
-
parameters=[
|
|
136
|
-
autodoc.request.URLPath(
|
|
137
|
-
autodoc.schema.String(id_label),
|
|
138
|
-
description=f"The {id_label} of the record to get",
|
|
139
|
-
required=True,
|
|
140
|
-
)
|
|
141
|
-
],
|
|
142
|
-
root_properties={
|
|
143
|
-
"security": self.documentation_request_security(),
|
|
144
|
-
},
|
|
145
|
-
)
|
|
146
|
-
]
|
|
147
|
-
|
|
148
|
-
def documentation_models(self):
|
|
149
|
-
schema_model_name = string.camel_case_to_snake_case(self._model.__class__.__name__)
|
|
150
|
-
|
|
151
|
-
return {
|
|
152
|
-
schema_model_name: autodoc.schema.Object(
|
|
153
|
-
"data",
|
|
154
|
-
children=self.documentation_data_schema(),
|
|
155
|
-
),
|
|
156
|
-
}
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
from .base import Base
|
|
2
|
-
from collections import OrderedDict
|
|
3
|
-
from .. import autodoc
|
|
4
|
-
from .. import condition_parser
|
|
5
|
-
from ..functional import string
|
|
6
|
-
import inspect
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
class HealthCheck(Base):
|
|
10
|
-
_configuration_defaults = {
|
|
11
|
-
"services": [],
|
|
12
|
-
"callable": None,
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
def __init__(self, di):
|
|
16
|
-
super().__init__(di)
|
|
17
|
-
|
|
18
|
-
def top_level_authentication_and_authorization(self, input_output, authentication=None):
|
|
19
|
-
pass
|
|
20
|
-
|
|
21
|
-
def handle(self, input_output):
|
|
22
|
-
services = self.configuration("services")
|
|
23
|
-
health_callable = self.configuration("callable")
|
|
24
|
-
try:
|
|
25
|
-
if services:
|
|
26
|
-
for service in services:
|
|
27
|
-
self._di.build(service, cache=True)
|
|
28
|
-
if health_callable and not health_callable():
|
|
29
|
-
return self.respond(input_output, {"status": "failure"}, 500)
|
|
30
|
-
except:
|
|
31
|
-
return self.respond(input_output, {"status": "failure"}, 500)
|
|
32
|
-
|
|
33
|
-
return self.success(input_output, {})
|
|
34
|
-
|
|
35
|
-
def _check_configuration(self, configuration):
|
|
36
|
-
error_prefix = "Configuration error for %s:" % (self.__class__.__name__)
|
|
37
|
-
services = configuration.get("services")
|
|
38
|
-
if services is not None and type(services) != list:
|
|
39
|
-
raise ValueError(
|
|
40
|
-
f'{error_prefix} "services" should be a list of names, with each name corresponding to a dependency to load'
|
|
41
|
-
)
|
|
42
|
-
health_callable = configuration.get("callable")
|
|
43
|
-
if health_callable is not None and not callable(health_callable):
|
|
44
|
-
raise ValueError(
|
|
45
|
-
f'{error_prefix} "callable" should be a callable that returns true/false to denote health status'
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
def documentation(self):
|
|
49
|
-
return [
|
|
50
|
-
autodoc.request.Request(
|
|
51
|
-
"Healthcheck",
|
|
52
|
-
[
|
|
53
|
-
self.documentation_success_response(
|
|
54
|
-
autodoc.schema.Object("data", children=[]),
|
|
55
|
-
),
|
|
56
|
-
],
|
|
57
|
-
relative_path=self.configuration("base_url"),
|
|
58
|
-
)
|
|
59
|
-
]
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
from .exceptions import InputError
|
|
2
|
-
from collections import OrderedDict
|
|
3
|
-
from abc import abstractmethod
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class InputProcessing:
|
|
7
|
-
_is_create = False
|
|
8
|
-
|
|
9
|
-
def _get_writeable_columns(self):
|
|
10
|
-
if self._writeable_columns is None:
|
|
11
|
-
self._writeable_columns = self._get_rw_columns("writeable")
|
|
12
|
-
additional_columns = OrderedDict()
|
|
13
|
-
for column in self._writeable_columns.values():
|
|
14
|
-
more_columns = column.additional_write_columns(is_create=self._is_create)
|
|
15
|
-
for additional_column_name, additional_column in more_columns.items():
|
|
16
|
-
additional_columns[additional_column_name] = additional_column
|
|
17
|
-
for additional_column_name, additional_column in additional_columns.items():
|
|
18
|
-
self._writeable_columns[additional_column_name] = additional_column
|
|
19
|
-
return self._writeable_columns
|
|
20
|
-
|
|
21
|
-
def _extra_column_errors(self, input_data):
|
|
22
|
-
input_errors = {}
|
|
23
|
-
allowed = self._get_writeable_columns()
|
|
24
|
-
for column_name in input_data.keys():
|
|
25
|
-
if column_name not in allowed:
|
|
26
|
-
input_errors[column_name] = f"Input column '{column_name}' is not an allowed column"
|
|
27
|
-
return input_errors
|
|
28
|
-
|
|
29
|
-
def _find_input_errors(self, model, input_data, input_output):
|
|
30
|
-
input_errors = {}
|
|
31
|
-
for column in self._get_writeable_columns().values():
|
|
32
|
-
input_errors = {
|
|
33
|
-
**input_errors,
|
|
34
|
-
**column.input_errors(model, input_data),
|
|
35
|
-
}
|
|
36
|
-
input_error_callable = self.configuration("input_error_callable")
|
|
37
|
-
if input_error_callable:
|
|
38
|
-
more_input_errors = self._di.call_function(
|
|
39
|
-
input_error_callable,
|
|
40
|
-
input_data=input_data,
|
|
41
|
-
request_data=input_data,
|
|
42
|
-
input_output=input_output,
|
|
43
|
-
routing_data=input_output.routing_data(),
|
|
44
|
-
authorization_data=input_output.get_authorization_data(),
|
|
45
|
-
)
|
|
46
|
-
if type(more_input_errors) != dict:
|
|
47
|
-
raise ValueError(
|
|
48
|
-
"The input error callable, '"
|
|
49
|
-
+ str(input_error_callable)
|
|
50
|
-
+ "', did not return a dictionary as required"
|
|
51
|
-
)
|
|
52
|
-
input_errors = {
|
|
53
|
-
**input_errors,
|
|
54
|
-
**more_input_errors,
|
|
55
|
-
}
|
|
56
|
-
return input_errors
|
|
57
|
-
|
|
58
|
-
def request_data(self, input_output, required=True):
|
|
59
|
-
# we have to map from internal names to external names, because case mapping
|
|
60
|
-
# isn't always one-to-one, so we want to do it exactly the same way that the documentation
|
|
61
|
-
# is built.
|
|
62
|
-
key_map = {self.auto_case_column_name(key, True): key for key in self._get_writeable_columns().keys()}
|
|
63
|
-
# in case the id comes up in the request body
|
|
64
|
-
key_map[self.auto_case_internal_column_name("id")] = "id"
|
|
65
|
-
|
|
66
|
-
# and make sure we don't drop any data along the way, because the input validation
|
|
67
|
-
# needs to return an error for unexpected data.
|
|
68
|
-
request_data = {
|
|
69
|
-
key_map.get(key, key): value for (key, value) in input_output.request_data(required=required).items()
|
|
70
|
-
}
|
|
71
|
-
# the parent handler should provide our resource id (we don't do any routing ourselves)
|
|
72
|
-
# However, our update/etc handlers need to find the id easily, so I'm going to be lazy and
|
|
73
|
-
# just dump it into the request. I'll probably regret that.
|
|
74
|
-
routing_data = input_output.routing_data()
|
|
75
|
-
# we don't have to worry about casing on the 'id' in routing_data because it doesn't come in from the
|
|
76
|
-
# route with a name. Rather, it is populated by clearskies, so will always just be 'id'
|
|
77
|
-
if "id" in routing_data:
|
|
78
|
-
request_data["id"] = routing_data["id"]
|
|
79
|
-
return request_data
|