clear-skies 2.0.4__py3-none-any.whl → 2.0.5__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-2.0.5.dist-info/METADATA +74 -0
- clear_skies-2.0.5.dist-info/RECORD +4 -0
- {clear_skies-2.0.4.dist-info → clear_skies-2.0.5.dist-info}/WHEEL +1 -1
- clear_skies-2.0.4.dist-info/METADATA +0 -36
- clear_skies-2.0.4.dist-info/RECORD +0 -251
- clearskies/__init__.py +0 -61
- clearskies/action.py +0 -7
- clearskies/authentication/__init__.py +0 -15
- clearskies/authentication/authentication.py +0 -46
- clearskies/authentication/authorization.py +0 -16
- clearskies/authentication/authorization_pass_through.py +0 -20
- clearskies/authentication/jwks.py +0 -163
- clearskies/authentication/public.py +0 -5
- clearskies/authentication/secret_bearer.py +0 -553
- clearskies/autodoc/__init__.py +0 -8
- clearskies/autodoc/formats/__init__.py +0 -5
- clearskies/autodoc/formats/oai3_json/__init__.py +0 -7
- clearskies/autodoc/formats/oai3_json/oai3_json.py +0 -87
- clearskies/autodoc/formats/oai3_json/oai3_schema_resolver.py +0 -15
- clearskies/autodoc/formats/oai3_json/parameter.py +0 -35
- clearskies/autodoc/formats/oai3_json/request.py +0 -68
- clearskies/autodoc/formats/oai3_json/response.py +0 -28
- clearskies/autodoc/formats/oai3_json/schema/__init__.py +0 -11
- clearskies/autodoc/formats/oai3_json/schema/array.py +0 -9
- clearskies/autodoc/formats/oai3_json/schema/default.py +0 -13
- clearskies/autodoc/formats/oai3_json/schema/enum.py +0 -7
- clearskies/autodoc/formats/oai3_json/schema/object.py +0 -35
- clearskies/autodoc/formats/oai3_json/test.json +0 -1985
- clearskies/autodoc/py.typed +0 -0
- clearskies/autodoc/request/__init__.py +0 -15
- clearskies/autodoc/request/header.py +0 -6
- clearskies/autodoc/request/json_body.py +0 -6
- clearskies/autodoc/request/parameter.py +0 -8
- clearskies/autodoc/request/request.py +0 -47
- clearskies/autodoc/request/url_parameter.py +0 -6
- clearskies/autodoc/request/url_path.py +0 -6
- clearskies/autodoc/response/__init__.py +0 -5
- clearskies/autodoc/response/response.py +0 -9
- clearskies/autodoc/schema/__init__.py +0 -31
- clearskies/autodoc/schema/array.py +0 -10
- clearskies/autodoc/schema/base64.py +0 -8
- clearskies/autodoc/schema/boolean.py +0 -5
- clearskies/autodoc/schema/date.py +0 -5
- clearskies/autodoc/schema/datetime.py +0 -5
- clearskies/autodoc/schema/double.py +0 -5
- clearskies/autodoc/schema/enum.py +0 -17
- clearskies/autodoc/schema/integer.py +0 -6
- clearskies/autodoc/schema/long.py +0 -5
- clearskies/autodoc/schema/number.py +0 -6
- clearskies/autodoc/schema/object.py +0 -13
- clearskies/autodoc/schema/password.py +0 -5
- clearskies/autodoc/schema/schema.py +0 -11
- clearskies/autodoc/schema/string.py +0 -5
- clearskies/backends/__init__.py +0 -65
- clearskies/backends/api_backend.py +0 -1178
- clearskies/backends/backend.py +0 -136
- clearskies/backends/cursor_backend.py +0 -335
- clearskies/backends/memory_backend.py +0 -797
- clearskies/backends/secrets_backend.py +0 -106
- clearskies/column.py +0 -1233
- clearskies/columns/__init__.py +0 -71
- clearskies/columns/audit.py +0 -206
- clearskies/columns/belongs_to_id.py +0 -483
- clearskies/columns/belongs_to_model.py +0 -132
- clearskies/columns/belongs_to_self.py +0 -105
- clearskies/columns/boolean.py +0 -113
- clearskies/columns/category_tree.py +0 -275
- clearskies/columns/category_tree_ancestors.py +0 -51
- clearskies/columns/category_tree_children.py +0 -127
- clearskies/columns/category_tree_descendants.py +0 -48
- clearskies/columns/created.py +0 -95
- clearskies/columns/created_by_authorization_data.py +0 -116
- clearskies/columns/created_by_header.py +0 -99
- clearskies/columns/created_by_ip.py +0 -92
- clearskies/columns/created_by_routing_data.py +0 -97
- clearskies/columns/created_by_user_agent.py +0 -92
- clearskies/columns/date.py +0 -234
- clearskies/columns/datetime.py +0 -282
- clearskies/columns/email.py +0 -76
- clearskies/columns/float.py +0 -153
- clearskies/columns/has_many.py +0 -505
- clearskies/columns/has_many_self.py +0 -56
- clearskies/columns/has_one.py +0 -14
- clearskies/columns/integer.py +0 -160
- clearskies/columns/json.py +0 -126
- clearskies/columns/many_to_many_ids.py +0 -337
- clearskies/columns/many_to_many_ids_with_data.py +0 -274
- clearskies/columns/many_to_many_models.py +0 -158
- clearskies/columns/many_to_many_pivots.py +0 -134
- clearskies/columns/phone.py +0 -159
- clearskies/columns/select.py +0 -92
- clearskies/columns/string.py +0 -102
- clearskies/columns/timestamp.py +0 -164
- clearskies/columns/updated.py +0 -110
- clearskies/columns/uuid.py +0 -86
- clearskies/configs/README.md +0 -105
- clearskies/configs/__init__.py +0 -162
- clearskies/configs/actions.py +0 -43
- clearskies/configs/any.py +0 -13
- clearskies/configs/any_dict.py +0 -22
- clearskies/configs/any_dict_or_callable.py +0 -23
- clearskies/configs/authentication.py +0 -23
- clearskies/configs/authorization.py +0 -23
- clearskies/configs/boolean.py +0 -16
- clearskies/configs/boolean_or_callable.py +0 -18
- clearskies/configs/callable_config.py +0 -18
- clearskies/configs/columns.py +0 -34
- clearskies/configs/conditions.py +0 -30
- clearskies/configs/config.py +0 -24
- clearskies/configs/datetime.py +0 -18
- clearskies/configs/datetime_or_callable.py +0 -19
- clearskies/configs/endpoint.py +0 -23
- clearskies/configs/endpoint_list.py +0 -28
- clearskies/configs/float.py +0 -16
- clearskies/configs/float_or_callable.py +0 -18
- clearskies/configs/integer.py +0 -16
- clearskies/configs/integer_or_callable.py +0 -18
- clearskies/configs/joins.py +0 -30
- clearskies/configs/list_any_dict.py +0 -30
- clearskies/configs/list_any_dict_or_callable.py +0 -31
- clearskies/configs/model_class.py +0 -35
- clearskies/configs/model_column.py +0 -65
- clearskies/configs/model_columns.py +0 -56
- clearskies/configs/model_destination_name.py +0 -25
- clearskies/configs/model_to_id_column.py +0 -43
- clearskies/configs/readable_model_column.py +0 -9
- clearskies/configs/readable_model_columns.py +0 -9
- clearskies/configs/schema.py +0 -23
- clearskies/configs/searchable_model_columns.py +0 -9
- clearskies/configs/security_headers.py +0 -39
- clearskies/configs/select.py +0 -26
- clearskies/configs/select_list.py +0 -47
- clearskies/configs/string.py +0 -29
- clearskies/configs/string_dict.py +0 -32
- clearskies/configs/string_list.py +0 -32
- clearskies/configs/string_list_or_callable.py +0 -35
- clearskies/configs/string_or_callable.py +0 -18
- clearskies/configs/timedelta.py +0 -18
- clearskies/configs/timezone.py +0 -18
- clearskies/configs/url.py +0 -23
- clearskies/configs/validators.py +0 -45
- clearskies/configs/writeable_model_column.py +0 -9
- clearskies/configs/writeable_model_columns.py +0 -9
- clearskies/configurable.py +0 -76
- clearskies/contexts/__init__.py +0 -11
- clearskies/contexts/cli.py +0 -117
- clearskies/contexts/context.py +0 -98
- clearskies/contexts/wsgi.py +0 -76
- clearskies/contexts/wsgi_ref.py +0 -82
- clearskies/decorators.py +0 -33
- clearskies/di/__init__.py +0 -14
- clearskies/di/additional_config.py +0 -130
- clearskies/di/additional_config_auto_import.py +0 -17
- clearskies/di/di.py +0 -973
- clearskies/di/inject/__init__.py +0 -23
- clearskies/di/inject/by_class.py +0 -21
- clearskies/di/inject/by_name.py +0 -18
- clearskies/di/inject/di.py +0 -13
- clearskies/di/inject/environment.py +0 -14
- clearskies/di/inject/input_output.py +0 -20
- clearskies/di/inject/now.py +0 -13
- clearskies/di/inject/requests.py +0 -13
- clearskies/di/inject/secrets.py +0 -14
- clearskies/di/inject/utcnow.py +0 -13
- clearskies/di/inject/uuid.py +0 -15
- clearskies/di/injectable.py +0 -29
- clearskies/di/injectable_properties.py +0 -131
- 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/end.py +0 -183
- clearskies/endpoint.py +0 -1314
- clearskies/endpoint_group.py +0 -338
- clearskies/endpoints/__init__.py +0 -25
- clearskies/endpoints/advanced_search.py +0 -526
- clearskies/endpoints/callable.py +0 -388
- clearskies/endpoints/create.py +0 -205
- clearskies/endpoints/delete.py +0 -139
- clearskies/endpoints/get.py +0 -271
- clearskies/endpoints/health_check.py +0 -183
- clearskies/endpoints/list.py +0 -574
- clearskies/endpoints/restful_api.py +0 -427
- clearskies/endpoints/schema.py +0 -189
- clearskies/endpoints/simple_search.py +0 -286
- clearskies/endpoints/update.py +0 -193
- clearskies/environment.py +0 -104
- clearskies/exceptions/__init__.py +0 -19
- clearskies/exceptions/authentication.py +0 -2
- clearskies/exceptions/authorization.py +0 -2
- clearskies/exceptions/client_error.py +0 -2
- clearskies/exceptions/input_errors.py +0 -4
- clearskies/exceptions/missing_dependency.py +0 -2
- clearskies/exceptions/moved_permanently.py +0 -3
- clearskies/exceptions/moved_temporarily.py +0 -3
- clearskies/exceptions/not_found.py +0 -2
- clearskies/functional/__init__.py +0 -7
- clearskies/functional/routing.py +0 -92
- clearskies/functional/string.py +0 -112
- clearskies/functional/validations.py +0 -76
- clearskies/input_outputs/__init__.py +0 -13
- clearskies/input_outputs/cli.py +0 -171
- clearskies/input_outputs/exceptions/__init__.py +0 -2
- clearskies/input_outputs/exceptions/cli_input_error.py +0 -2
- clearskies/input_outputs/exceptions/cli_not_found.py +0 -2
- clearskies/input_outputs/headers.py +0 -45
- clearskies/input_outputs/input_output.py +0 -138
- clearskies/input_outputs/programmatic.py +0 -69
- clearskies/input_outputs/py.typed +0 -0
- clearskies/input_outputs/wsgi.py +0 -77
- clearskies/model.py +0 -1922
- clearskies/py.typed +0 -0
- clearskies/query/__init__.py +0 -12
- clearskies/query/condition.py +0 -223
- clearskies/query/join.py +0 -136
- clearskies/query/query.py +0 -196
- clearskies/query/sort.py +0 -27
- clearskies/schema.py +0 -82
- clearskies/secrets/__init__.py +0 -6
- clearskies/secrets/additional_configs/__init__.py +0 -32
- clearskies/secrets/additional_configs/mysql_connection_dynamic_producer.py +0 -61
- clearskies/secrets/additional_configs/mysql_connection_dynamic_producer_via_ssh_cert_bastion.py +0 -160
- clearskies/secrets/akeyless.py +0 -182
- clearskies/secrets/exceptions/__init__.py +0 -1
- clearskies/secrets/exceptions/not_found.py +0 -2
- clearskies/secrets/secrets.py +0 -38
- clearskies/security_header.py +0 -15
- clearskies/security_headers/__init__.py +0 -11
- clearskies/security_headers/cache_control.py +0 -67
- clearskies/security_headers/cors.py +0 -50
- clearskies/security_headers/csp.py +0 -94
- clearskies/security_headers/hsts.py +0 -22
- clearskies/security_headers/x_content_type_options.py +0 -0
- clearskies/security_headers/x_frame_options.py +0 -0
- clearskies/test_base.py +0 -8
- clearskies/typing.py +0 -11
- clearskies/validator.py +0 -37
- clearskies/validators/__init__.py +0 -33
- clearskies/validators/after_column.py +0 -62
- clearskies/validators/before_column.py +0 -13
- clearskies/validators/in_the_future.py +0 -32
- clearskies/validators/in_the_future_at_least.py +0 -11
- clearskies/validators/in_the_future_at_most.py +0 -10
- clearskies/validators/in_the_past.py +0 -32
- clearskies/validators/in_the_past_at_least.py +0 -10
- clearskies/validators/in_the_past_at_most.py +0 -10
- clearskies/validators/maximum_length.py +0 -26
- clearskies/validators/maximum_value.py +0 -29
- clearskies/validators/minimum_length.py +0 -26
- clearskies/validators/minimum_value.py +0 -29
- clearskies/validators/required.py +0 -34
- clearskies/validators/timedelta.py +0 -59
- clearskies/validators/unique.py +0 -30
- {clear_skies-2.0.4.dist-info → clear_skies-2.0.5.dist-info/licenses}/LICENSE +0 -0
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import TYPE_CHECKING, Self, Type, overload
|
|
4
|
-
|
|
5
|
-
from clearskies.columns import CategoryTreeChildren
|
|
6
|
-
|
|
7
|
-
if TYPE_CHECKING:
|
|
8
|
-
from clearskies import Model
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class CategoryTreeDescendants(CategoryTreeChildren):
|
|
12
|
-
"""
|
|
13
|
-
Return all descendants from a category tree column.
|
|
14
|
-
|
|
15
|
-
See the CategoryTree column for usage examples.
|
|
16
|
-
|
|
17
|
-
The descendants are the recursive children of a given category. So, given the following tree:
|
|
18
|
-
|
|
19
|
-
```
|
|
20
|
-
Root/
|
|
21
|
-
├─ Sub/
|
|
22
|
-
│ ├─ Sub Sub/
|
|
23
|
-
│ │ ├─ Sub Sub Sub/
|
|
24
|
-
├─ Another Child/
|
|
25
|
-
|
|
26
|
-
The descendants of `Root` are `["Sub", "Sub Sub", "Sub Sub Sub", "Another Child"]`.
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
|
-
_descriptor_config_map = None
|
|
30
|
-
|
|
31
|
-
@overload
|
|
32
|
-
def __get__(self, instance: None, cls: type[Model]) -> Self:
|
|
33
|
-
pass
|
|
34
|
-
|
|
35
|
-
@overload
|
|
36
|
-
def __get__(self, instance: Model, cls: type[Model]) -> Model:
|
|
37
|
-
pass
|
|
38
|
-
|
|
39
|
-
def __get__(self, model, cls):
|
|
40
|
-
if model is None:
|
|
41
|
-
self.model_class = cls
|
|
42
|
-
return self # type: ignore
|
|
43
|
-
|
|
44
|
-
# this makes sure we're initialized
|
|
45
|
-
if "name" not in self._config: # type: ignore
|
|
46
|
-
model.get_columns()
|
|
47
|
-
|
|
48
|
-
return self.relatives(model, include_all=True)
|
clearskies/columns/created.py
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import datetime
|
|
4
|
-
from typing import TYPE_CHECKING, Any
|
|
5
|
-
|
|
6
|
-
import clearskies.decorators
|
|
7
|
-
import clearskies.di
|
|
8
|
-
import clearskies.typing
|
|
9
|
-
from clearskies import configs
|
|
10
|
-
from clearskies.columns.datetime import Datetime
|
|
11
|
-
|
|
12
|
-
if TYPE_CHECKING:
|
|
13
|
-
from clearskies import Model
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class Created(Datetime):
|
|
17
|
-
"""
|
|
18
|
-
The created column records the time that a record is created.
|
|
19
|
-
|
|
20
|
-
This will always populate the column when the model is first created. If you attempt to set a value
|
|
21
|
-
to this column on create then it will be overwritten.
|
|
22
|
-
|
|
23
|
-
```python
|
|
24
|
-
import clearskies
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class MyModel(clearskies.Model):
|
|
28
|
-
backend = clearskies.backends.MemoryBackend()
|
|
29
|
-
id_column_name = "id"
|
|
30
|
-
id = clearskies.columns.Uuid()
|
|
31
|
-
name = clearskies.columns.String()
|
|
32
|
-
created = clearskies.columns.Created()
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
cli = clearskies.contexts.Cli(
|
|
36
|
-
clearskies.endpoints.Callable(
|
|
37
|
-
lambda my_models: my_models.create({"name": "An Example"}),
|
|
38
|
-
model_class=MyModel,
|
|
39
|
-
readable_column_names=["id", "name", "created"],
|
|
40
|
-
),
|
|
41
|
-
classes=[MyModel],
|
|
42
|
-
)
|
|
43
|
-
cli()
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
And if you execute this you'll see that the `created` column was automatically populated:
|
|
47
|
-
|
|
48
|
-
```json
|
|
49
|
-
{
|
|
50
|
-
"status": "success",
|
|
51
|
-
"error": "",
|
|
52
|
-
"data": {
|
|
53
|
-
"id": "c54d74ac-5282-439e-af4f-23efb9ba96d4",
|
|
54
|
-
"name": "An Example",
|
|
55
|
-
"created": "2025-05-09T19:58:43+00:00",
|
|
56
|
-
},
|
|
57
|
-
"pagination": {},
|
|
58
|
-
"input_errors": {},
|
|
59
|
-
}
|
|
60
|
-
```
|
|
61
|
-
"""
|
|
62
|
-
|
|
63
|
-
"""
|
|
64
|
-
Created fields are never writeable because they always set the created time automatically.
|
|
65
|
-
"""
|
|
66
|
-
is_writeable = configs.Boolean(default=False)
|
|
67
|
-
_descriptor_config_map = None
|
|
68
|
-
|
|
69
|
-
now = clearskies.di.inject.Now()
|
|
70
|
-
|
|
71
|
-
@clearskies.decorators.parameters_to_properties
|
|
72
|
-
def __init__(
|
|
73
|
-
self,
|
|
74
|
-
date_format: str = "%Y-%m-%d %H:%M:%S",
|
|
75
|
-
in_utc: bool = True,
|
|
76
|
-
backend_default: str = "0000-00-00 00:00:00",
|
|
77
|
-
is_readable: bool = True,
|
|
78
|
-
is_searchable: bool = True,
|
|
79
|
-
is_temporary: bool = False,
|
|
80
|
-
on_change_pre_save: clearskies.typing.action | list[clearskies.typing.action] = [],
|
|
81
|
-
on_change_post_save: clearskies.typing.action | list[clearskies.typing.action] = [],
|
|
82
|
-
on_change_save_finished: clearskies.typing.action | list[clearskies.typing.action] = [],
|
|
83
|
-
):
|
|
84
|
-
pass
|
|
85
|
-
|
|
86
|
-
def pre_save(self, data: dict[str, Any], model: Model) -> dict[str, Any]:
|
|
87
|
-
if model:
|
|
88
|
-
return data
|
|
89
|
-
now = self.now
|
|
90
|
-
if self.timezone_aware:
|
|
91
|
-
now = now.astimezone(self.timezone)
|
|
92
|
-
data = {**data, self.name: now}
|
|
93
|
-
if self.on_change_pre_save:
|
|
94
|
-
data = self.execute_actions_with_data(self.on_change_pre_save, model, data)
|
|
95
|
-
return data
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import TYPE_CHECKING, Any
|
|
4
|
-
|
|
5
|
-
import clearskies.decorators
|
|
6
|
-
import clearskies.typing
|
|
7
|
-
from clearskies import configs
|
|
8
|
-
from clearskies.columns.string import String
|
|
9
|
-
|
|
10
|
-
if TYPE_CHECKING:
|
|
11
|
-
from clearskies import Model
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class CreatedByAuthorizationData(String):
|
|
15
|
-
"""
|
|
16
|
-
This column will automatically take data from the authorization data attached to a request and store it in the model upon creation.
|
|
17
|
-
|
|
18
|
-
If authorization data isn't available from the context being executed, then you may end up with an error
|
|
19
|
-
(depending on the context). This is a good thing if you are trying to consistely provide audit information,
|
|
20
|
-
but may be a problem if your model creation needs to happen more flexibly. Obviously, a pre-requisite for using this
|
|
21
|
-
class is to have an authentication class attached to your endpoint which populates the authorization data.
|
|
22
|
-
|
|
23
|
-
NOTE: columns generally also have the `created_by_source_type` and `created_by_source_key` properties that perform
|
|
24
|
-
this exact same function. Why do we have those properties and this column? This column works well if we have
|
|
25
|
-
some simple string values that we want to always pull from the authorization data (email, for instance). The
|
|
26
|
-
properties work better if you need to pull authorization data but it's not just a string type. An example might
|
|
27
|
-
be if you wanted to pull the user id out of the authorziation data to populate a `BelongsToId` column. You wouldn't
|
|
28
|
-
use this column because it can't provide all the functionality related to `BelongsToId`, so instead you would
|
|
29
|
-
use the `BelongsToId` column and set `created_by_source_type` to `authorization_data` and `created_by_source_key` to `user_id`.
|
|
30
|
-
Example usage:
|
|
31
|
-
|
|
32
|
-
```python
|
|
33
|
-
class MyModel(clearskies.Model):
|
|
34
|
-
backend = clearskies.backends.MemoryBackend()
|
|
35
|
-
id_column_name = "id"
|
|
36
|
-
|
|
37
|
-
id = clearskies.columns.Uuid()
|
|
38
|
-
name = clearskies.columns.String()
|
|
39
|
-
organization_id = clearskies.columns.CreatedByAuthorizationData("organization_id")
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
class MyAuthentication(clearskies.authentication.Authentication):
|
|
43
|
-
def authenticate(self, input_output) -> bool:
|
|
44
|
-
# Authenticate the user!
|
|
45
|
-
#
|
|
46
|
-
# This is where you would normally authenticate the user and provide any data about them to the
|
|
47
|
-
# authorization system. This might mean validating a JWT and then providing the claims as authorization data,
|
|
48
|
-
# or looking up a session id and providing the session data to the authorization system. In this case,
|
|
49
|
-
# we're just going to return a fixed id for our organization.
|
|
50
|
-
input_output.authorization_data = {
|
|
51
|
-
"organization_id": "my-super-awesome-organization",
|
|
52
|
-
}
|
|
53
|
-
return True
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
cli = clearskies.contexts.Cli(
|
|
57
|
-
clearskies.endpoints.Create(
|
|
58
|
-
MyModel,
|
|
59
|
-
writeable_column_names=["name"],
|
|
60
|
-
readable_column_names=["id", "name", "organization_id"],
|
|
61
|
-
authentication=MyAuthentication(),
|
|
62
|
-
),
|
|
63
|
-
classes=[MyModel],
|
|
64
|
-
)
|
|
65
|
-
cli()
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
And running this will give you something like:
|
|
69
|
-
|
|
70
|
-
```json
|
|
71
|
-
{
|
|
72
|
-
"status": "success",
|
|
73
|
-
"error": "",
|
|
74
|
-
"data": {
|
|
75
|
-
"id": "49816ea4-0956-461e-abd4-03dbde845ba9",
|
|
76
|
-
"name": "Bob",
|
|
77
|
-
"organization_id": "my-super-awesome-organization",
|
|
78
|
-
},
|
|
79
|
-
"pagination": {},
|
|
80
|
-
"input_errors": {},
|
|
81
|
-
}
|
|
82
|
-
```
|
|
83
|
-
"""
|
|
84
|
-
|
|
85
|
-
"""
|
|
86
|
-
The key inside the authorization data that should be pulled into the column value when the record is created
|
|
87
|
-
"""
|
|
88
|
-
authorization_data_key_name = configs.String(required=True)
|
|
89
|
-
|
|
90
|
-
"""
|
|
91
|
-
Whether or not to throw an error if the key is not present in the authorization data.
|
|
92
|
-
"""
|
|
93
|
-
strict = configs.Boolean(default=True)
|
|
94
|
-
|
|
95
|
-
"""
|
|
96
|
-
Since this column is always populated automatically, it is never directly writeable.
|
|
97
|
-
"""
|
|
98
|
-
is_writeable = configs.Boolean(default=False)
|
|
99
|
-
_descriptor_config_map = None
|
|
100
|
-
|
|
101
|
-
_allowed_search_operators = ["=", "in", "is not null", "is null", "like"]
|
|
102
|
-
|
|
103
|
-
@clearskies.decorators.parameters_to_properties
|
|
104
|
-
def __init__(
|
|
105
|
-
self,
|
|
106
|
-
authorization_data_key_name: str,
|
|
107
|
-
strict: bool = True,
|
|
108
|
-
is_readable: bool = True,
|
|
109
|
-
is_searchable: bool = True,
|
|
110
|
-
is_temporary: bool = False,
|
|
111
|
-
on_change_pre_save: clearskies.typing.action | list[clearskies.typing.action] = [],
|
|
112
|
-
on_change_post_save: clearskies.typing.action | list[clearskies.typing.action] = [],
|
|
113
|
-
on_change_save_finished: clearskies.typing.action | list[clearskies.typing.action] = [],
|
|
114
|
-
):
|
|
115
|
-
self.created_by_source_key = authorization_data_key_name
|
|
116
|
-
self.created_by_source_type = "authorization_data"
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import clearskies.decorators
|
|
2
|
-
import clearskies.typing
|
|
3
|
-
from clearskies import configs
|
|
4
|
-
from clearskies.columns.string import String
|
|
5
|
-
from clearskies.query import Condition
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class CreatedByHeader(String):
|
|
9
|
-
"""
|
|
10
|
-
This column will automatically take data from the header attached to a request and store it in the model upon creation.
|
|
11
|
-
|
|
12
|
-
If header data isn't available from the context being executed, then you may end up with an error
|
|
13
|
-
(depending on the context). This is a good thing if you are trying to consistely provide audit information,
|
|
14
|
-
but may be a problem if your model creation needs to happen more flexibly.
|
|
15
|
-
|
|
16
|
-
NOTE: columns generally also have the `created_by_source_type` and `created_by_source_key` properties that perform
|
|
17
|
-
this exact same function. Why do we have those properties and this column? This column works well if we have
|
|
18
|
-
some simple string values that we want to always pull from the header data. The properties work better if you need to
|
|
19
|
-
pull header data but it's not just a string type. An example might be if you wanted to pull the user id out of the
|
|
20
|
-
header data to populate a `BelongsToId` column. You wouldn't use this column because it can't provide all the functionality
|
|
21
|
-
related to `BelongsToId`, so instead you would use the `BelongsToId` column and set `created_by_source_type` to `http_header` and
|
|
22
|
-
`created_by_source_key` to `user_id`. Example usage:
|
|
23
|
-
|
|
24
|
-
```python
|
|
25
|
-
import clearskies
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
class MyModel(clearskies.Model):
|
|
29
|
-
backend = clearskies.backends.MemoryBackend()
|
|
30
|
-
id_column_name = "id"
|
|
31
|
-
|
|
32
|
-
id = clearskies.columns.Uuid()
|
|
33
|
-
name = clearskies.columns.String()
|
|
34
|
-
custom_header = clearskies.columns.CreatedByHeader("my_custom_header")
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
wsgi = clearskies.contexts.WsgiRef(
|
|
38
|
-
clearskies.endpoints.Create(
|
|
39
|
-
MyModel,
|
|
40
|
-
writeable_column_names=["name"],
|
|
41
|
-
readable_column_names=["id", "name", "custom_header"],
|
|
42
|
-
),
|
|
43
|
-
classes=[MyModel],
|
|
44
|
-
)
|
|
45
|
-
wsgi()
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
If you invoked this:
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
$ curl 'http://localhost:8080' -d '{"name":"Bob"}' -H 'my_custom_header: some header value' | jq
|
|
52
|
-
|
|
53
|
-
{
|
|
54
|
-
"status": "success",
|
|
55
|
-
"error": "",
|
|
56
|
-
"data": {
|
|
57
|
-
"id": "10459ee4-a75e-4fd1-9993-2feeea629144",
|
|
58
|
-
"name": "Bob",
|
|
59
|
-
"custom_header": "some header value"
|
|
60
|
-
},
|
|
61
|
-
"pagination": {},
|
|
62
|
-
"input_errors": {}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
```
|
|
66
|
-
"""
|
|
67
|
-
|
|
68
|
-
"""
|
|
69
|
-
The name of the header that this column should be populated from.
|
|
70
|
-
"""
|
|
71
|
-
header_name = configs.String(required=True)
|
|
72
|
-
|
|
73
|
-
"""
|
|
74
|
-
Whether or not to throw an error if the key is not present in the header data.
|
|
75
|
-
"""
|
|
76
|
-
strict = configs.Boolean(default=True)
|
|
77
|
-
|
|
78
|
-
"""
|
|
79
|
-
Since this column is always populated automatically, it is never directly writeable.
|
|
80
|
-
"""
|
|
81
|
-
is_writeable = configs.Boolean(default=False)
|
|
82
|
-
_descriptor_config_map = None
|
|
83
|
-
|
|
84
|
-
_allowed_search_operators = ["=", "in", "is not null", "is null", "like"]
|
|
85
|
-
|
|
86
|
-
@clearskies.decorators.parameters_to_properties
|
|
87
|
-
def __init__(
|
|
88
|
-
self,
|
|
89
|
-
header_name: str,
|
|
90
|
-
strict: bool = True,
|
|
91
|
-
is_readable: bool = True,
|
|
92
|
-
is_searchable: bool = True,
|
|
93
|
-
is_temporary: bool = False,
|
|
94
|
-
on_change_pre_save: clearskies.typing.action | list[clearskies.typing.action] = [],
|
|
95
|
-
on_change_post_save: clearskies.typing.action | list[clearskies.typing.action] = [],
|
|
96
|
-
on_change_save_finished: clearskies.typing.action | list[clearskies.typing.action] = [],
|
|
97
|
-
):
|
|
98
|
-
self.created_by_source_key = header_name
|
|
99
|
-
self.created_by_source_type = "http_header"
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from typing import TYPE_CHECKING, Any
|
|
4
|
-
|
|
5
|
-
import clearskies.decorators
|
|
6
|
-
import clearskies.typing
|
|
7
|
-
from clearskies import configs
|
|
8
|
-
from clearskies.columns.string import String
|
|
9
|
-
|
|
10
|
-
if TYPE_CHECKING:
|
|
11
|
-
from clearskies import Model
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class CreatedByIp(String):
|
|
15
|
-
"""
|
|
16
|
-
Return the ip address of the client when the record is created.
|
|
17
|
-
|
|
18
|
-
If the ip address isn't available from the context being executed, then you may end up with an error
|
|
19
|
-
(depending on the context). This is a good thing if you are trying to consistely provide audit information,
|
|
20
|
-
but may be a problem if your model creation needs to happen more flexibly. Example:
|
|
21
|
-
|
|
22
|
-
```python
|
|
23
|
-
import clearskies
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
class MyModel(clearskies.Model):
|
|
27
|
-
backend = clearskies.backends.MemoryBackend()
|
|
28
|
-
id_column_name = "id"
|
|
29
|
-
|
|
30
|
-
id = clearskies.columns.Uuid()
|
|
31
|
-
name = clearskies.columns.String()
|
|
32
|
-
ip_address = clearskies.columns.CreatedByIp()
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
wsgi = clearskies.contexts.WsgiRef(
|
|
36
|
-
clearskies.endpoints.Create(
|
|
37
|
-
MyModel,
|
|
38
|
-
writeable_column_names=["name"],
|
|
39
|
-
readable_column_names=["id", "name", "ip_address"],
|
|
40
|
-
),
|
|
41
|
-
classes=[MyModel],
|
|
42
|
-
)
|
|
43
|
-
wsgi()
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
And if you invoked this:
|
|
47
|
-
|
|
48
|
-
```bash
|
|
49
|
-
$ curl 'http://localhost:8080' -d '{"name":"Bob"}' | jq
|
|
50
|
-
{
|
|
51
|
-
"status": "success",
|
|
52
|
-
"error": "",
|
|
53
|
-
"data": {
|
|
54
|
-
"id": "62e457fe-1680-4fa1-b4e3-0329f304fedb",
|
|
55
|
-
"name": "Bob",
|
|
56
|
-
"ip_address": "127.0.0.1"
|
|
57
|
-
},
|
|
58
|
-
"pagination": {},
|
|
59
|
-
"input_errors": {}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
```
|
|
63
|
-
"""
|
|
64
|
-
|
|
65
|
-
"""
|
|
66
|
-
Since this column is always populated automatically, it is never directly writeable.
|
|
67
|
-
"""
|
|
68
|
-
is_writeable = configs.Boolean(default=False)
|
|
69
|
-
_descriptor_config_map = None
|
|
70
|
-
|
|
71
|
-
_allowed_search_operators = ["=", "in", "is not null", "is null", "like"]
|
|
72
|
-
|
|
73
|
-
@clearskies.decorators.parameters_to_properties
|
|
74
|
-
def __init__(
|
|
75
|
-
self,
|
|
76
|
-
is_readable: bool = True,
|
|
77
|
-
is_searchable: bool = True,
|
|
78
|
-
is_temporary: bool = False,
|
|
79
|
-
on_change_pre_save: clearskies.typing.action | list[clearskies.typing.action] = [],
|
|
80
|
-
on_change_post_save: clearskies.typing.action | list[clearskies.typing.action] = [],
|
|
81
|
-
on_change_save_finished: clearskies.typing.action | list[clearskies.typing.action] = [],
|
|
82
|
-
):
|
|
83
|
-
pass
|
|
84
|
-
|
|
85
|
-
def pre_save(self, data: dict[str, Any], model: Model) -> dict[str, Any]:
|
|
86
|
-
if model:
|
|
87
|
-
return data
|
|
88
|
-
input_output = self.di.build("input_output", cache=True)
|
|
89
|
-
data = {**data, self.name: input_output.get_client_ip()}
|
|
90
|
-
if self.on_change_pre_save:
|
|
91
|
-
data = self.execute_actions_with_data(self.on_change_pre_save, model, data)
|
|
92
|
-
return data
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import clearskies.decorators
|
|
2
|
-
import clearskies.typing
|
|
3
|
-
from clearskies import configs
|
|
4
|
-
from clearskies.columns.string import String
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
class CreatedByRoutingData(String):
|
|
8
|
-
"""
|
|
9
|
-
This column will automatically take data from the route path in the request and store it in the model upon creation.
|
|
10
|
-
|
|
11
|
-
If routing data isn't available from the context being executed, then you may end up with an error
|
|
12
|
-
(depending on the context). This is a good thing if you are trying to consistely provide audit information,
|
|
13
|
-
but may be a problem if your model creation needs to happen more flexibly.
|
|
14
|
-
|
|
15
|
-
NOTE: columns generally also have the `created_by_source_type` and `created_by_source_key` properties that perform
|
|
16
|
-
this exact same function. Why do we have those properties and this column? This column works well if we have
|
|
17
|
-
some simple string values that we want to always pull from the route path. The properties work better if you need to
|
|
18
|
-
pull route data but it's not just a string type. An example might be if you wanted to pull the user id out of the
|
|
19
|
-
route data to populate a `BelongsToId` column. You wouldn't use this column because it can't provide all the functionality
|
|
20
|
-
related to `BelongsToId`, so instead you would use the `BelongsToId` column and set `created_by_source_type` to `routing_data` and
|
|
21
|
-
`created_by_source_key` to `user_id`. Example usage:
|
|
22
|
-
|
|
23
|
-
```python
|
|
24
|
-
import clearskies
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class MyModel(clearskies.Model):
|
|
28
|
-
backend = clearskies.backends.MemoryBackend()
|
|
29
|
-
id_column_name = "id"
|
|
30
|
-
|
|
31
|
-
id = clearskies.columns.Uuid()
|
|
32
|
-
name = clearskies.columns.String()
|
|
33
|
-
organization_id = clearskies.columns.CreatedByRoutingData("organization_id")
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
wsgi = clearskies.contexts.WsgiRef(
|
|
37
|
-
clearskies.endpoints.Create(
|
|
38
|
-
MyModel,
|
|
39
|
-
url="/{organization_id}",
|
|
40
|
-
writeable_column_names=["name"],
|
|
41
|
-
readable_column_names=["id", "name", "organization_id"],
|
|
42
|
-
),
|
|
43
|
-
classes=[MyModel],
|
|
44
|
-
)
|
|
45
|
-
wsgi()
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
And if you invoked this:
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
$ curl 'http://localhost:8080/my-org-id' -d '{"name":"Bob"}' | jq
|
|
52
|
-
{
|
|
53
|
-
"status": "success",
|
|
54
|
-
"error": "",
|
|
55
|
-
"data": {
|
|
56
|
-
"id": "3643db8c-c9d4-47ee-a747-8922c59d9e7e",
|
|
57
|
-
"name": "Bob",
|
|
58
|
-
"organization_id": "my-org-id"
|
|
59
|
-
},
|
|
60
|
-
"pagination": {},
|
|
61
|
-
"input_errors": {}
|
|
62
|
-
}
|
|
63
|
-
```
|
|
64
|
-
"""
|
|
65
|
-
|
|
66
|
-
"""
|
|
67
|
-
The name of the route path to populate the column with.
|
|
68
|
-
"""
|
|
69
|
-
routing_path_name = configs.String(required=True)
|
|
70
|
-
|
|
71
|
-
"""
|
|
72
|
-
Whether or not to throw an error if the key is not present in the header data.
|
|
73
|
-
"""
|
|
74
|
-
strict = configs.Boolean(default=True)
|
|
75
|
-
|
|
76
|
-
"""
|
|
77
|
-
Since this column is always populated automatically, it is never directly writeable.
|
|
78
|
-
"""
|
|
79
|
-
is_writeable = configs.Boolean(default=False)
|
|
80
|
-
_descriptor_config_map = None
|
|
81
|
-
|
|
82
|
-
_allowed_search_operators = ["=", "in", "is not null", "is null", "like"]
|
|
83
|
-
|
|
84
|
-
@clearskies.decorators.parameters_to_properties
|
|
85
|
-
def __init__(
|
|
86
|
-
self,
|
|
87
|
-
routing_path_name: str,
|
|
88
|
-
strict: bool = True,
|
|
89
|
-
is_readable: bool = True,
|
|
90
|
-
is_searchable: bool = True,
|
|
91
|
-
is_temporary: bool = False,
|
|
92
|
-
on_change_pre_save: clearskies.typing.action | list[clearskies.typing.action] = [],
|
|
93
|
-
on_change_post_save: clearskies.typing.action | list[clearskies.typing.action] = [],
|
|
94
|
-
on_change_save_finished: clearskies.typing.action | list[clearskies.typing.action] = [],
|
|
95
|
-
):
|
|
96
|
-
self.created_by_source_key = routing_path_name
|
|
97
|
-
self.created_by_source_type = "routing_data"
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import datetime
|
|
4
|
-
from typing import TYPE_CHECKING, Any
|
|
5
|
-
|
|
6
|
-
import clearskies.decorators
|
|
7
|
-
import clearskies.typing
|
|
8
|
-
from clearskies import configs
|
|
9
|
-
from clearskies.columns.string import String
|
|
10
|
-
|
|
11
|
-
if TYPE_CHECKING:
|
|
12
|
-
from clearskies import Model
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class CreatedByUserAgent(String):
|
|
16
|
-
"""
|
|
17
|
-
This column will automatically take the user agent from the client and store it in the model upon creation.
|
|
18
|
-
|
|
19
|
-
If the user agent isn't available from the context being executed, then you may end up with an error
|
|
20
|
-
(depending on the context). This is a good thing if you are trying to consistely provide audit information,
|
|
21
|
-
but may be a problem if your model creation needs to happen more flexibly. Example:
|
|
22
|
-
|
|
23
|
-
```python
|
|
24
|
-
import clearskies
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class MyModel(clearskies.Model):
|
|
28
|
-
backend = clearskies.backends.MemoryBackend()
|
|
29
|
-
id_column_name = "id"
|
|
30
|
-
|
|
31
|
-
id = clearskies.columns.Uuid()
|
|
32
|
-
name = clearskies.columns.String()
|
|
33
|
-
user_agent = clearskies.columns.CreatedByUserAgent()
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
wsgi = clearskies.contexts.WsgiRef(
|
|
37
|
-
clearskies.endpoints.Create(
|
|
38
|
-
MyModel,
|
|
39
|
-
writeable_column_names=["name"],
|
|
40
|
-
readable_column_names=["id", "name", "user_agent"],
|
|
41
|
-
),
|
|
42
|
-
classes=[MyModel],
|
|
43
|
-
)
|
|
44
|
-
wsgi()
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
And if you invoked this:
|
|
48
|
-
|
|
49
|
-
```bash
|
|
50
|
-
$ curl 'http://localhost:8080' -d '{"name":"Bob"}' | jq
|
|
51
|
-
{
|
|
52
|
-
"status": "success",
|
|
53
|
-
"error": "",
|
|
54
|
-
"data": {
|
|
55
|
-
"id": "a66e5fa9-6377-4d3b-9d50-fc7feaed6d1a",
|
|
56
|
-
"name": "Bob",
|
|
57
|
-
"user_agent": "curl/8.5.0"
|
|
58
|
-
},
|
|
59
|
-
"pagination": {},
|
|
60
|
-
"input_errors": {}
|
|
61
|
-
}
|
|
62
|
-
```
|
|
63
|
-
"""
|
|
64
|
-
|
|
65
|
-
"""
|
|
66
|
-
Since this column is always populated automatically, it is never directly writeable.
|
|
67
|
-
"""
|
|
68
|
-
is_writeable = configs.Boolean(default=False)
|
|
69
|
-
_descriptor_config_map = None
|
|
70
|
-
|
|
71
|
-
_allowed_search_operators = ["=", "in", "is not null", "is null", "like"]
|
|
72
|
-
|
|
73
|
-
@clearskies.decorators.parameters_to_properties
|
|
74
|
-
def __init__(
|
|
75
|
-
self,
|
|
76
|
-
is_readable: bool = True,
|
|
77
|
-
is_searchable: bool = True,
|
|
78
|
-
is_temporary: bool = False,
|
|
79
|
-
on_change_pre_save: clearskies.typing.action | list[clearskies.typing.action] = [],
|
|
80
|
-
on_change_post_save: clearskies.typing.action | list[clearskies.typing.action] = [],
|
|
81
|
-
on_change_save_finished: clearskies.typing.action | list[clearskies.typing.action] = [],
|
|
82
|
-
):
|
|
83
|
-
pass
|
|
84
|
-
|
|
85
|
-
def pre_save(self, data: dict[str, Any], model: Model) -> dict[str, Any]:
|
|
86
|
-
if model:
|
|
87
|
-
return data
|
|
88
|
-
input_output = self.di.build("input_output", cache=True)
|
|
89
|
-
data = {**data, self.name: input_output.request_headers.user_agent}
|
|
90
|
-
if self.on_change_pre_save:
|
|
91
|
-
data = self.execute_actions_with_data(self.on_change_pre_save, model, data)
|
|
92
|
-
return data
|