clear-skies 1.22.0__py3-none-any.whl → 1.22.2__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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: clear-skies
3
- Version: 1.22.0
3
+ Version: 1.22.2
4
4
  Summary: A framework for building backends in the cloud
5
5
  Home-page: https://github.com/cmancone/clearskies
6
6
  License: MIT
@@ -1,9 +1,10 @@
1
1
  clearskies/__init__.py,sha256=Iz_VxSgiqM6VtGXoUsB_yVKFy_uWvcf071w803wJ8EE,832
2
2
  clearskies/application.py,sha256=_gYGIUGdVE5fAS9dwxRZ1gDpDjqGo7-twVt_VxI6XVE,966
3
- clearskies/authentication/__init__.py,sha256=pHKJOfujgvNAbgzQpKVzEhWORwjAZTE4jKhJ50M7zts,900
3
+ clearskies/authentication/__init__.py,sha256=e8hJ_gKdKn7dIzHe4Hg3jdUYIzGGSr5aJKnQa3zh-MU,997
4
4
  clearskies/authentication/auth0_jwks.py,sha256=bzqNaEoG_iPndwttRXuaKpgkDtgOCLAooyifl0I0ACI,4447
5
5
  clearskies/authentication/auth_exception.py,sha256=8Tay3Sim2K8vAZ6ldisSJyRyN0cwX7iyGHwfglSKW_A,41
6
6
  clearskies/authentication/authorization.py,sha256=eLzBrXMNr1gYoIBZTd8I6uH3R0CfMMjhvimkJt4Amrs,601
7
+ clearskies/authentication/authorization_pass_through.py,sha256=wrRSY0RyRFifeyRgNn9D-3ptCXjPSbytHB8xAyyFSWE,737
7
8
  clearskies/authentication/jwks.py,sha256=AOrCkL7pVznTM6mbrQ3RVHCccws0b_yEtqEOe6NRw5k,3368
8
9
  clearskies/authentication/jwks_jwcrypto.py,sha256=PqyQNJZY7P98qgdxNltwCWoPxsaWLDqPuMknB4u2mDc,1732
9
10
  clearskies/authentication/public.py,sha256=zNpglAILTU7koz22YaGpMOAtTn_dG8dAP4Q9REdbaOk,630
@@ -57,7 +58,7 @@ clearskies/backends/secrets_backend.py,sha256=4lzrgdL_O_pgCT5HknV2gotFgp9GzjQ5_2
57
58
  clearskies/binding_config.py,sha256=bF8LBNEgJacwKCqToAtDqN9hv5omzU7zt_4qB9KPtE0,457
58
59
  clearskies/column_types/__init__.py,sha256=wofhLfyW00I6tb6o9DMsMx7j9hlbbqefhDzWfw0Row0,4731
59
60
  clearskies/column_types/audit.py,sha256=2YcrZVVElpOUdmxYTQ_6CshL1HVou6fz65dOOs_b8Gw,9659
60
- clearskies/column_types/belongs_to.py,sha256=tH1tbTOfjifSNuVjO-KbMF7GiUIoLfcDItrrS3TGGM8,11044
61
+ clearskies/column_types/belongs_to.py,sha256=E7Wi84vr2PnNw7TBCoZa8jkpwiJhO-iQmZ_ekq26kTs,12206
61
62
  clearskies/column_types/boolean.py,sha256=1yyM1CUfgD84pPE65c1OP1Qjf_J0Z45hjPrDR51AUkQ,1878
62
63
  clearskies/column_types/category_tree.py,sha256=kPx0fNTJxHaaEI_-0JxQ7NBcV2bYgUDGmtf1wmTqoEg,13172
63
64
  clearskies/column_types/column.py,sha256=ftuDFswjk-KE9Frxo1rhgkjr4sjSjnUc5ZtfNrnGLIc,15530
@@ -72,7 +73,7 @@ clearskies/column_types/datetime.py,sha256=xtuZpUC9fA16i1oO80kPIx--8RDPuei9RdsDD
72
73
  clearskies/column_types/datetime_micro.py,sha256=ewQSniCc2MmNIyX2XNuNcCIwh5Fpf1HcvpLfzB8lz8g,382
73
74
  clearskies/column_types/email.py,sha256=qq0Yo_C3KxUqT68q2HWXocBBR4xwMqjxcIdgZRv218U,584
74
75
  clearskies/column_types/float.py,sha256=j8jJeBueSOusPtAFCWgLHYBncfLnqT1U7bh1zcAkYiA,1332
75
- clearskies/column_types/has_many.py,sha256=Z4oM1g2dQx6H9171c52FLC41nLryCOKmh51I75mYmmY,5895
76
+ clearskies/column_types/has_many.py,sha256=090CNJOrpLTgfB8MHEenjGtkeGVUvXWq0wC-bowSF9g,7200
76
77
  clearskies/column_types/has_one.py,sha256=uphIPUuHLwwmhljLMaKKPujR6TYTT7onn-hHUF6S_IY,2230
77
78
  clearskies/column_types/integer.py,sha256=dGIluusPmhLRNg7PplOJLbQI2AXojqRBUHt8ekYWNVI,1386
78
79
  clearskies/column_types/json.py,sha256=TbZkdwCoZYhbALUxof2jENGfaq2i5TlcyBcmo7XzDGQ,652
@@ -205,7 +206,7 @@ clearskies/tests/simple_api/models/__init__.py,sha256=nUA0W6fgXw_Bxa9CudkaDkC80t
205
206
  clearskies/tests/simple_api/models/status.py,sha256=PEhPbaQh5qdUNHp8O0gz91LOLENAEBtqSaHxUPXchaM,699
206
207
  clearskies/tests/simple_api/models/user.py,sha256=5_P4Tp1tTdX7PkMJ__epPM5MA7JAeVYGas69vcWloLc,819
207
208
  clearskies/tests/simple_api/users_api.py,sha256=KYXCgEofDxHeRdQK67txN5oYUPvxxmB8JTku7L-apk4,2344
208
- clear_skies-1.22.0.dist-info/LICENSE,sha256=3Ehd0g3YOpCj8sqj0Xjq5qbOtjjgk9qzhhD9YjRQgOA,1053
209
- clear_skies-1.22.0.dist-info/METADATA,sha256=a0Q4D5KWAlqhWVBabYpHGsj6ZNUClL8Ce1eBaXFE03g,1817
210
- clear_skies-1.22.0.dist-info/WHEEL,sha256=d2fvjOD7sXsVzChCqf0Ty0JbHKBaLYwDbGQDwQTnJ50,88
211
- clear_skies-1.22.0.dist-info/RECORD,,
209
+ clear_skies-1.22.2.dist-info/LICENSE,sha256=3Ehd0g3YOpCj8sqj0Xjq5qbOtjjgk9qzhhD9YjRQgOA,1053
210
+ clear_skies-1.22.2.dist-info/METADATA,sha256=VK-epQE4gX0HBLswlPrBOSyKYKegicpH7hW5ZfYLSrE,1817
211
+ clear_skies-1.22.2.dist-info/WHEEL,sha256=d2fvjOD7sXsVzChCqf0Ty0JbHKBaLYwDbGQDwQTnJ50,88
212
+ clear_skies-1.22.2.dist-info/RECORD,,
@@ -5,6 +5,7 @@ from .auth0_jwks import Auth0JWKS
5
5
  from .authorization import Authorization
6
6
  from .jwks import JWKS
7
7
  from .jwks_jwcrypto import JWKSJwCrypto
8
+ from .authorization_pass_through import AuthorizationPassThrough
8
9
 
9
10
 
10
11
  def public():
@@ -29,6 +30,7 @@ def jwks_jwcrypto(jwks_url, **kwargs):
29
30
 
30
31
  __all__ = [
31
32
  "Authorization",
33
+ "AuthorizationPassThrough",
32
34
  "BindingConfig",
33
35
  "public",
34
36
  "Public",
@@ -0,0 +1,18 @@
1
+ from clearskies.authentication import JWKSJwCrypto
2
+
3
+
4
+ class AuthorizationPassThrough(JWKSJwCrypto):
5
+ """
6
+ This authentication class takes the authentication header from the incoming request and reflects
7
+ it on outgoing requests.
8
+ """
9
+
10
+ def __init__(self, environment, requests, di):
11
+ super().__init__(environment, requests)
12
+ # we need the dependency injection container so we can grab the input output and,
13
+ # with that, the request headers (which contain the JWT we'll pass through).
14
+ self.di = di
15
+
16
+ def headers(self, retry_auth=False):
17
+ input_output = self.di.build("input_output", cache=True)
18
+ return {"Authorization": input_output.get_request_header("authorization", True)}
@@ -34,6 +34,7 @@ class BelongsTo(String):
34
34
  "model_column_name",
35
35
  "readable_parent_columns",
36
36
  "join_type",
37
+ "where",
37
38
  ]
38
39
 
39
40
  def __init__(self, di):
@@ -43,6 +44,7 @@ class BelongsTo(String):
43
44
  super()._check_configuration(configuration)
44
45
  self.validate_models_class(configuration["parent_models_class"])
45
46
 
47
+ error_prefix = f"Configuration error for '{self.name}' in '{self.model_class.__name__}':"
46
48
  if not configuration.get("model_column_name") and self.name[-3:] != "_id":
47
49
  raise ValueError(
48
50
  f"Invalid name for column '{self.name}' in '{self.model_class.__name__}' - "
@@ -50,19 +52,14 @@ class BelongsTo(String):
50
52
  + "that the parent model can be fetched from."
51
53
  )
52
54
  if configuration.get("model_column_name") and type(configuration.get("model_column_name")) != str:
53
- raise ValueError(
54
- f"Configuration error for '{self.name}' in '{self.model_class.__name__}': 'model_column_name' must be a string."
55
- )
55
+ raise ValueError(f"{error_prefix} 'model_column_name' must be a string.")
56
56
 
57
57
  join_type = configuration.get("join_type")
58
58
  if join_type and join_type.upper() not in ["LEFT", "INNER"]:
59
- raise ValueError(
60
- f"Configuration error for '{self.name}' in '{self.model_class.__name__}': join_type must be INNER or LEFT"
61
- )
59
+ raise ValueError(f"{error_prefix} join_type must be INNER or LEFT")
62
60
 
63
61
  if configuration.get("readable_parent_columns"):
64
62
  parent_columns = self.di.build(configuration["parent_models_class"], cache=True).raw_columns_configuration()
65
- error_prefix = f"Configuration error for '{self.name}' in '{self.model_class.__name__}':"
66
63
  readable_parent_columns = configuration["readable_parent_columns"]
67
64
  if not hasattr(readable_parent_columns, "__iter__"):
68
65
  raise ValueError(
@@ -81,6 +78,19 @@ class BelongsTo(String):
81
78
  + "column does not exist in the model class."
82
79
  )
83
80
 
81
+ wheres = configuration.get("where")
82
+ if wheres:
83
+ if not isinstance(wheres, list):
84
+ raise ValueError(
85
+ f"{error_prefix} 'where' must be a list of where conditions or callables that return where conditions"
86
+ )
87
+ for index, where in enumerate(wheres):
88
+ if callable(where) or isinstance(where, str):
89
+ continue
90
+ raise ValueError(
91
+ f"{error_prefix} 'where' must be a list of where conditions or callables that return where conditions, but the item in entry #${index+1} was neither a string nor a callable"
92
+ )
93
+
84
94
  def _finalize_configuration(self, configuration):
85
95
  return {
86
96
  **super()._finalize_configuration(configuration),
@@ -89,6 +99,7 @@ class BelongsTo(String):
89
99
  if configuration.get("model_column_name")
90
100
  else self.name[:-3],
91
101
  "join_type": configuration.get("join_type", "INNER").upper(),
102
+ "where": configuration.get("where", []),
92
103
  },
93
104
  }
94
105
 
@@ -149,7 +160,17 @@ class BelongsTo(String):
149
160
 
150
161
  @property
151
162
  def parent_models(self):
152
- return self.di.build(self.config("parent_models_class"), cache=True)
163
+ parents = self.di.build(self.config("parent_models_class"), cache=True)
164
+ for where in self.config("where"):
165
+ if callable(where):
166
+ parents = self.di.call_function(where, model=parents)
167
+ if not parents:
168
+ raise ValueError(
169
+ f"Configuration error for column '{self.name}' in model '{self.model_class.__name__}': when 'where' is a callable, it must return a models class, but when the callable in where entry #{index+1} was called, it did not return the models class"
170
+ )
171
+ else:
172
+ parents = parents.where(where)
173
+ return parents
153
174
 
154
175
  @property
155
176
  def parent_columns(self):
@@ -27,6 +27,7 @@ class HasMany(Column):
27
27
  "is_readable",
28
28
  "readable_child_columns",
29
29
  "parent_id_column_name",
30
+ "where",
30
31
  ]
31
32
 
32
33
  def __init__(self, di):
@@ -63,9 +64,10 @@ class HasMany(Column):
63
64
 
64
65
  def _check_configuration(self, configuration):
65
66
  super()._check_configuration(configuration)
67
+ error_prefix = f"Configuration error for '{self.name}' in '{self.model_class.__name__}':"
68
+
66
69
  if configuration.get("is_readable"):
67
70
  child_columns = self.di.build(configuration["child_models_class"], cache=True).raw_columns_configuration()
68
- error_prefix = f"Configuration error for '{self.name}' in '{self.model_class.__name__}':"
69
71
  if not "readable_child_columns" in configuration:
70
72
  raise ValueError(f"{error_prefix} must provide 'readable_child_columns' if is_readable is set")
71
73
  readable_child_columns = configuration["readable_child_columns"]
@@ -86,6 +88,19 @@ class HasMany(Column):
86
88
  + "column does not exist in the model class."
87
89
  )
88
90
 
91
+ wheres = configuration.get("where")
92
+ if wheres:
93
+ if not isinstance(wheres, list):
94
+ raise ValueError(
95
+ f"{error_prefix} 'where' must be a list of where conditions or callables that return where conditions"
96
+ )
97
+ for index, where in enumerate(wheres):
98
+ if callable(where) or isinstance(where, str):
99
+ continue
100
+ raise ValueError(
101
+ f"{error_prefix} 'where' must be a list of where conditions or callables that return where conditions, but the item in entry #${index+1} was neither a string nor a callable"
102
+ )
103
+
89
104
  def get_child_columns(self):
90
105
  if "child_columns" not in self.configuration:
91
106
  self.configuration["child_columns"] = self.child_models.columns()
@@ -119,7 +134,17 @@ class HasMany(Column):
119
134
 
120
135
  @property
121
136
  def child_models(self):
122
- return self.di.build(self.config("child_models_class"), cache=True)
137
+ children = self.di.build(self.config("child_models_class"), cache=True)
138
+ for index, where in enumerate(self.config("where")):
139
+ if callable(where):
140
+ children = self.di.call_function(where, model=children)
141
+ if not children:
142
+ raise ValueError(
143
+ f"Configuration error for column '{self.name}' in model '{self.model_class.__name__}': when 'where' is a callable, it must return a models class, but when the callable in where entry #{index+1} was called, it did not return the models class"
144
+ )
145
+ else:
146
+ children = children.where(where)
147
+ return children
123
148
 
124
149
  def documentation(self, name=None, example=None, value=None):
125
150
  columns = self.get_child_columns()