nsj-rest-lib2 0.0.33__py3-none-any.whl → 0.0.34__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.
@@ -33,6 +33,7 @@ from nsj_rest_lib2.compiler.util.relation_ref import RelationRefParser
33
33
  from nsj_rest_lib2.compiler.edl_model.entity_model import EntityModel
34
34
 
35
35
  from nsj_rest_lib2.settings import get_logger
36
+ from nsj_rest_lib2.dto.escopo_dto import EscopoDTO
36
37
 
37
38
 
38
39
  class EDLCompiler:
@@ -44,13 +45,24 @@ class EDLCompiler:
44
45
  self._function_get_delete_compiler = FunctionGetDeleteCompiler()
45
46
 
46
47
  def compile_models(
47
- self, entity_models: dict[str, EntityModel]
48
+ self,
49
+ entity_models: dict[str, EntityModel],
50
+ escopos: dict[str, EscopoDTO],
48
51
  ) -> list[CompilerResult]:
49
52
 
50
53
  compiler_results = []
51
54
  for entity_model_id in entity_models:
52
55
  entity_model = entity_models[entity_model_id]
53
- compiler_result = self._compile_model(entity_model, entity_models)
56
+ escopo_dto = escopos.get(entity_model.escopo)
57
+ if escopo_dto is None:
58
+ raise Exception(
59
+ f"EscopoDTO não informado para o escopo: {entity_model.escopo}."
60
+ )
61
+ compiler_result = self._compile_model(
62
+ entity_model,
63
+ entity_models,
64
+ escopo=escopo_dto,
65
+ )
54
66
  if compiler_result:
55
67
  compiler_results.append(compiler_result)
56
68
 
@@ -60,6 +72,7 @@ class EDLCompiler:
60
72
  self,
61
73
  edl_json: dict[str, Any],
62
74
  dependencies_edls: list[dict[str, Any]],
75
+ escopo: EscopoDTO,
63
76
  ) -> CompilerResult | None:
64
77
  entity_model = EntityModel(**edl_json)
65
78
 
@@ -71,35 +84,36 @@ class EDLCompiler:
71
84
  dependency_entity_model = EntityModel(**dependency_edl)
72
85
  entity_models.append(dependency_entity_model)
73
86
 
74
- return self.compile_model(entity_model, entity_models)
87
+ return self.compile_model(entity_model, entity_models, escopo=escopo)
75
88
 
76
89
  def compile_model(
77
90
  self,
78
91
  entity_model: EntityModelBase,
79
92
  dependencies_models: list[tuple[str, EntityModelBase]],
93
+ escopo: EscopoDTO,
80
94
  ) -> CompilerResult | None:
81
95
  entity_models = {}
82
96
  for dependency_entity_model in dependencies_models:
83
97
  complete_entity_id = dependency_entity_model[0]
84
98
  entity_models[complete_entity_id] = dependency_entity_model[1]
85
99
 
86
- return self._compile_model(entity_model, entity_models)
100
+ return self._compile_model(entity_model, entity_models, escopo=escopo)
87
101
 
88
102
  def _compile_model(
89
103
  self,
90
104
  entity_model: EntityModelBase,
91
105
  entity_models: dict[str, EntityModel],
92
- escopo: str | None = None,
106
+ escopo: EscopoDTO | None,
93
107
  prefx_class_name: str = "",
94
108
  ) -> CompilerResult | None:
95
109
  if entity_model.mixin:
96
110
  return None
97
111
 
98
- if escopo is None and (isinstance(entity_model, EntityModel)):
99
- escopo = entity_model.escopo
100
-
101
- if not escopo:
102
- raise Exception(f"Escopo não definido para a entidade: {entity_model.id}.")
112
+ if escopo is None:
113
+ raise Exception(
114
+ f"EscopoDTO não informado para a entidade: {getattr(entity_model, 'id', '<unknown>')}."
115
+ )
116
+ escopo_codigo = escopo.codigo
103
117
 
104
118
  # Tratando dos dados base para a extensão parcial
105
119
  partial_metadata: dict[str, str] | None = None
@@ -250,7 +264,7 @@ class EDLCompiler:
250
264
  ) = self._properties_compiler.compile(
251
265
  properties_structure,
252
266
  map_unique_by_property,
253
- escopo,
267
+ escopo_codigo,
254
268
  entity_model,
255
269
  entity_models,
256
270
  prefx_class_name,
@@ -371,9 +385,7 @@ class EDLCompiler:
371
385
  compiler_result.list_function_type_class_name = list_function_type_class
372
386
  compiler_result.delete_function_type_class_name = delete_function_type_class
373
387
  compiler_result.source_get_function_type = get_function_code.strip() or None
374
- compiler_result.source_list_function_type = (
375
- list_function_code.strip() or None
376
- )
388
+ compiler_result.source_list_function_type = list_function_code.strip() or None
377
389
  compiler_result.source_delete_function_type = (
378
390
  delete_function_code.strip() or None
379
391
  )
@@ -392,6 +404,7 @@ class EDLCompiler:
392
404
  compiler_result.api_expose = entity_model.api.expose
393
405
  compiler_result.api_resource = entity_model.api.resource
394
406
  compiler_result.api_verbs = entity_model.api.verbs
407
+ compiler_result.service_account = escopo.service_account
395
408
 
396
409
  get_logger().debug(f"código gerado para a entidade: {entity_model.id}")
397
410
  get_logger().debug("DTO Code:")
@@ -848,7 +861,14 @@ if __name__ == "__main__":
848
861
  entities[complete_entity_id] = entity_model
849
862
 
850
863
  compiler = EDLCompiler()
851
- compiler_results = compiler.compile_models(entities)
864
+ escopos = {}
865
+ for entity_model in entities.values():
866
+ if entity_model.escopo not in escopos:
867
+ escopos[entity_model.escopo] = EscopoDTO(
868
+ codigo=entity_model.escopo,
869
+ service_account=None,
870
+ )
871
+ compiler_results = compiler.compile_models(entities, escopos)
852
872
 
853
873
  with open("output_compilacao_local.py", "w") as f:
854
874
  for compiler_result in compiler_results:
@@ -42,6 +42,7 @@ class CompilerResult:
42
42
  self.api_expose: bool | None = None
43
43
  self.api_resource: str | None = None
44
44
  self.api_verbs: list[str] | None = None
45
+ self.service_account: str | None = None
45
46
  self.relations_dependencies: list[RelationDependency] | None = None
46
47
  self.insert_function_class_name: str | None = None
47
48
  self.insert_function_name: str | None = None
@@ -1,6 +1,6 @@
1
1
  import json
2
2
 
3
- from typing import Any
3
+ from typing import Any, Callable
4
4
 
5
5
  from flask import Flask, request
6
6
 
@@ -68,426 +68,311 @@ def setup_dynamic_routes(
68
68
  f"/{APP_NAME}/{dynamic_root_path}/<entity_escopo>/<entity_resource>/<id>"
69
69
  )
70
70
 
71
- def list_dynamic_wrapper(injector_factory: Any, *args: Any, **kwargs: Any) -> Any:
72
-
73
- def list_dynamic(*args: Any, **kwargs: Any):
74
- # Recuperando o identificador da entidade
71
+ def _dynamic_route_wrapper(
72
+ route_builder: Callable[[tuple[Any, ...]], Callable[..., Any]],
73
+ endpoint_suffix: str | None = None,
74
+ ) -> Callable[..., Any]:
75
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
75
76
  if "entity_resource" not in kwargs:
76
77
  msg = "Faltando parâmetro identificador da entidade na URL."
77
78
  return (format_json_error(msg), 400, {**DEFAULT_RESP_HEADERS})
78
79
  entity_resource = kwargs.pop("entity_resource")
79
80
 
80
- # Verificando se o identificador do escopo foi passado na URL
81
- entity_escopo = ""
82
- if "entity_escopo" in kwargs:
83
- entity_escopo = kwargs.pop("entity_escopo")
81
+ entity_escopo = kwargs.pop("entity_escopo", "")
84
82
 
85
- # Lendo tenant e grupo_empresarial
86
83
  tenant, grupo_empresarial, force_reload = _get_query_args()
87
84
 
88
85
  try:
89
- # Recuperando o código do DTO e Entity correspondente
90
86
  entity_loader = EntityLoader()
91
- (
92
- dto_class_name,
93
- entity_class_name,
94
- etities_dict,
95
- api_expose,
96
- api_verbs,
97
- _insert_function_class_name,
98
- _update_function_class_name,
99
- _insert_function_name,
100
- _update_function_name,
101
- _get_function_name,
102
- list_function_name,
103
- _delete_function_name,
104
- _get_function_type_class_name,
105
- list_function_type_class_name,
106
- _delete_function_type_class_name,
107
- ) = entity_loader.load_entity_source(
87
+ entity_config = entity_loader.load_entity_source(
108
88
  entity_resource,
109
89
  tenant,
110
90
  grupo_empresarial,
111
91
  escopo=entity_escopo,
112
92
  force_reload=force_reload,
113
93
  )
114
-
115
- # Verificando se essa API deve ser exposta
116
- if not api_expose or "GET" not in api_verbs:
117
- return ("", 405, {})
118
-
119
- # Executando o list pelo RestLib
120
- route = ListRoute(
121
- url=COLLECTION_DYNAMIC_ROUTE,
122
- http_method="GET",
123
- dto_class=etities_dict[dto_class_name],
124
- entity_class=etities_dict[entity_class_name],
125
- injector_factory=injector_factory,
126
- list_function_name=list_function_name,
127
- list_function_type_class=etities_dict.get(
128
- list_function_type_class_name
129
- ),
130
- )
131
-
132
- return route.handle_request(*args, **kwargs)
133
94
  except MissingEntityConfigException:
134
95
  msg = f"Entity configuration for {entity_resource} not found."
135
96
  return (format_json_error(msg), 412, {**DEFAULT_RESP_HEADERS})
136
97
 
137
- return list_dynamic
98
+ (
99
+ _,
100
+ _,
101
+ _,
102
+ _,
103
+ _,
104
+ service_account,
105
+ *rest,
106
+ ) = entity_config
107
+
108
+ route_handler = route_builder(entity_config)
109
+
110
+ if multidb:
111
+ route_handler = multi_database(service_account)(route_handler)
112
+
113
+ return route_handler(*args, **kwargs)
114
+
115
+ wrapper.__name__ = endpoint_suffix or f"{route_builder.__name__}_wrapper"
116
+ return wrapper
117
+
118
+ def list_dynamic_builder(entity_config: tuple[Any, ...]) -> Callable[..., Any]:
119
+ (
120
+ dto_class_name,
121
+ entity_class_name,
122
+ etities_dict,
123
+ api_expose,
124
+ api_verbs,
125
+ _service_account,
126
+ _insert_function_class_name,
127
+ _update_function_class_name,
128
+ _insert_function_name,
129
+ _update_function_name,
130
+ _get_function_name,
131
+ list_function_name,
132
+ _delete_function_name,
133
+ _get_function_type_class_name,
134
+ list_function_type_class_name,
135
+ _delete_function_type_class_name,
136
+ ) = entity_config
137
+
138
+ def list_dynamic(*args: Any, **kwargs: Any) -> Any:
139
+ if not api_expose or "GET" not in api_verbs:
140
+ return ("", 405, {})
141
+
142
+ route = ListRoute(
143
+ url=COLLECTION_DYNAMIC_ROUTE,
144
+ http_method="GET",
145
+ dto_class=etities_dict[dto_class_name],
146
+ entity_class=etities_dict[entity_class_name],
147
+ injector_factory=injector_factory,
148
+ list_function_name=list_function_name,
149
+ list_function_type_class=etities_dict.get(
150
+ list_function_type_class_name
151
+ ),
152
+ )
153
+
154
+ return route.handle_request(*args, **kwargs)
138
155
 
139
- def get_dynamic_wrapper(injector_factory: Any, *args: Any, **kwargs: Any) -> Any:
140
-
141
- def get_dynamic(*args: Any, **kwargs: Any):
142
- # Recuperando o identificador da entidade
143
- if "entity_resource" not in kwargs:
144
- msg = "Faltando parâmetro identificador da entidade na URL."
145
- return (format_json_error(msg), 400, {**DEFAULT_RESP_HEADERS})
146
- entity_resource = kwargs.pop("entity_resource")
147
-
148
- # Verificando se o identificador do escopo foi passado na URL
149
- entity_escopo = ""
150
- if "entity_escopo" in kwargs:
151
- entity_escopo = kwargs.pop("entity_escopo")
152
-
153
- # Lendo tenant e grupo_empresarial
154
- tenant, grupo_empresarial, force_reload = _get_query_args()
155
-
156
- try:
157
- # Recuperando o código do DTO e Entity correspondente
158
- entity_loader = EntityLoader()
159
- (
160
- dto_class_name,
161
- entity_class_name,
162
- etities_dict,
163
- api_expose,
164
- api_verbs,
165
- _insert_function_class_name,
166
- _update_function_class_name,
167
- _insert_function_name,
168
- _update_function_name,
169
- get_function_name,
170
- _list_function_name,
171
- _delete_function_name,
172
- get_function_type_class_name,
173
- _list_function_type_class_name,
174
- _delete_function_type_class_name,
175
- ) = entity_loader.load_entity_source(
176
- entity_resource,
177
- tenant,
178
- grupo_empresarial,
179
- escopo=entity_escopo,
180
- force_reload=force_reload,
181
- )
182
-
183
- # Verificando se essa API deve ser exposta
184
- if not api_expose or "GET" not in api_verbs:
185
- return ("", 405, {})
186
-
187
- # Executando o list pelo RestLib
188
- route = GetRoute(
189
- url=ONE_DYNAMIC_ROUTE,
190
- http_method="GET",
191
- dto_class=etities_dict[dto_class_name],
192
- entity_class=etities_dict[entity_class_name],
193
- injector_factory=injector_factory,
194
- get_function_name=get_function_name,
195
- get_function_type_class=etities_dict.get(
196
- get_function_type_class_name
197
- ),
198
- )
156
+ return list_dynamic
199
157
 
200
- return route.handle_request(*args, **kwargs)
201
- except MissingEntityConfigException:
202
- msg = f"Entity configuration for {entity_resource} not found."
203
- return (format_json_error(msg), 412, {**DEFAULT_RESP_HEADERS})
158
+ def get_dynamic_builder(entity_config: tuple[Any, ...]) -> Callable[..., Any]:
159
+ (
160
+ dto_class_name,
161
+ entity_class_name,
162
+ etities_dict,
163
+ api_expose,
164
+ api_verbs,
165
+ _service_account,
166
+ _insert_function_class_name,
167
+ _update_function_class_name,
168
+ _insert_function_name,
169
+ _update_function_name,
170
+ get_function_name,
171
+ _list_function_name,
172
+ _delete_function_name,
173
+ get_function_type_class_name,
174
+ _list_function_type_class_name,
175
+ _delete_function_type_class_name,
176
+ ) = entity_config
177
+
178
+ def get_dynamic(*args: Any, **kwargs: Any) -> Any:
179
+ if not api_expose or "GET" not in api_verbs:
180
+ return ("", 405, {})
181
+
182
+ route = GetRoute(
183
+ url=ONE_DYNAMIC_ROUTE,
184
+ http_method="GET",
185
+ dto_class=etities_dict[dto_class_name],
186
+ entity_class=etities_dict[entity_class_name],
187
+ injector_factory=injector_factory,
188
+ get_function_name=get_function_name,
189
+ get_function_type_class=etities_dict.get(get_function_type_class_name),
190
+ )
191
+
192
+ return route.handle_request(*args, **kwargs)
204
193
 
205
194
  return get_dynamic
206
195
 
207
- def post_dynamic_wrapper(injector_factory: Any, *args: Any, **kwargs: Any) -> Any:
208
- def post_dynamic(*args: Any, **kwargs: Any):
209
- # Recuperando o identificador da entidade
210
- if "entity_resource" not in kwargs:
211
- msg = "Faltando parâmetro identificador da entidade na URL."
212
- return (format_json_error(msg), 400, {**DEFAULT_RESP_HEADERS})
213
- entity_resource = kwargs.pop("entity_resource")
214
-
215
- # Verificando se o identificador do escopo foi passado na URL
216
- entity_escopo = ""
217
- if "entity_escopo" in kwargs:
218
- entity_escopo = kwargs.pop("entity_escopo")
219
-
220
- # Lendo tenant e grupo_empresarial
221
- tenant, grupo_empresarial, force_reload = _get_query_args()
222
-
223
- try:
224
- # Recuperando o código do DTO e Entity correspondente
225
- entity_loader = EntityLoader()
226
- (
227
- dto_class_name,
228
- entity_class_name,
229
- etities_dict,
230
- api_expose,
231
- api_verbs,
232
- insert_function_class_name,
233
- _update_function_class_name,
234
- insert_function_name,
235
- _update_function_name,
236
- _get_function_name,
237
- _list_function_name,
238
- _delete_function_name,
239
- _get_function_type_class_name,
240
- _list_function_type_class_name,
241
- _delete_function_type_class_name,
242
- ) = entity_loader.load_entity_source(
243
- entity_resource,
244
- tenant,
245
- grupo_empresarial,
246
- escopo=entity_escopo,
247
- force_reload=force_reload,
248
- )
249
-
250
- # Verificando se essa API deve ser exposta
251
- if not api_expose or "POST" not in api_verbs:
252
- return ("", 405, {})
253
-
254
- # Executando o list pelo RestLib
255
- insert_function_type_class = (
256
- etities_dict.get(insert_function_class_name)
257
- if insert_function_class_name
258
- else None
259
- )
260
-
261
- route = PostRoute(
262
- url=COLLECTION_DYNAMIC_ROUTE,
263
- http_method="POST",
264
- dto_class=etities_dict[dto_class_name],
265
- entity_class=etities_dict[entity_class_name],
266
- injector_factory=injector_factory,
267
- insert_function_type_class=insert_function_type_class,
268
- insert_function_name=insert_function_name,
269
- )
270
-
271
- return route.handle_request(*args, **kwargs)
272
- except MissingEntityConfigException:
273
- msg = f"Entity configuration for {entity_resource} not found."
274
- return (format_json_error(msg), 412, {**DEFAULT_RESP_HEADERS})
196
+ def post_dynamic_builder(entity_config: tuple[Any, ...]) -> Callable[..., Any]:
197
+ (
198
+ dto_class_name,
199
+ entity_class_name,
200
+ etities_dict,
201
+ api_expose,
202
+ api_verbs,
203
+ _service_account,
204
+ insert_function_class_name,
205
+ _update_function_class_name,
206
+ insert_function_name,
207
+ _update_function_name,
208
+ _get_function_name,
209
+ _list_function_name,
210
+ _delete_function_name,
211
+ _get_function_type_class_name,
212
+ _list_function_type_class_name,
213
+ _delete_function_type_class_name,
214
+ ) = entity_config
215
+
216
+ def post_dynamic(*args: Any, **kwargs: Any) -> Any:
217
+ if not api_expose or "POST" not in api_verbs:
218
+ return ("", 405, {})
219
+
220
+ insert_function_type_class = (
221
+ etities_dict.get(insert_function_class_name)
222
+ if insert_function_class_name
223
+ else None
224
+ )
225
+
226
+ route = PostRoute(
227
+ url=COLLECTION_DYNAMIC_ROUTE,
228
+ http_method="POST",
229
+ dto_class=etities_dict[dto_class_name],
230
+ entity_class=etities_dict[entity_class_name],
231
+ injector_factory=injector_factory,
232
+ insert_function_type_class=insert_function_type_class,
233
+ insert_function_name=insert_function_name,
234
+ )
235
+
236
+ return route.handle_request(*args, **kwargs)
275
237
 
276
238
  return post_dynamic
277
239
 
278
- def put_dynamic_wrapper(injector_factory: Any, *args: Any, **kwargs: Any) -> Any:
279
- def put_dynamic(*args: Any, **kwargs: Any):
280
- # Recuperando o identificador da entidade
281
- if "entity_resource" not in kwargs:
282
- msg = "Faltando parâmetro identificador da entidade na URL."
283
- return (format_json_error(msg), 400, {**DEFAULT_RESP_HEADERS})
284
- entity_resource = kwargs.pop("entity_resource")
285
-
286
- # Verificando se o identificador do escopo foi passado na URL
287
- entity_escopo = ""
288
- if "entity_escopo" in kwargs:
289
- entity_escopo = kwargs.pop("entity_escopo")
290
-
291
- # Lendo tenant e grupo_empresarial
292
- tenant, grupo_empresarial, force_reload = _get_query_args()
293
-
294
- try:
295
- # Recuperando o código do DTO e Entity correspondente
296
- entity_loader = EntityLoader()
297
- (
298
- dto_class_name,
299
- entity_class_name,
300
- etities_dict,
301
- api_expose,
302
- api_verbs,
303
- _insert_function_class_name,
304
- update_function_class_name,
305
- _insert_function_name,
306
- update_function_name,
307
- _get_function_name,
308
- _list_function_name,
309
- _delete_function_name,
310
- _get_function_type_class_name,
311
- _list_function_type_class_name,
312
- _delete_function_type_class_name,
313
- ) = entity_loader.load_entity_source(
314
- entity_resource,
315
- tenant,
316
- grupo_empresarial,
317
- escopo=entity_escopo,
318
- force_reload=force_reload,
319
- )
320
-
321
- # Verificando se essa API deve ser exposta
322
- if not api_expose or "PUT" not in api_verbs:
323
- return ("", 405, {})
324
-
325
- # Executando o list pelo RestLib
326
- update_function_type_class = (
327
- etities_dict.get(update_function_class_name)
328
- if update_function_class_name
329
- else None
330
- )
331
-
332
- route = PutRoute(
333
- url=ONE_DYNAMIC_ROUTE,
334
- http_method="PUT",
335
- dto_class=etities_dict[dto_class_name],
336
- entity_class=etities_dict[entity_class_name],
337
- injector_factory=injector_factory,
338
- update_function_type_class=update_function_type_class,
339
- update_function_name=update_function_name,
340
- )
341
-
342
- return route.handle_request(*args, **kwargs)
343
- except MissingEntityConfigException:
344
- msg = f"Entity configuration for {entity_resource} not found."
345
- return (format_json_error(msg), 412, {**DEFAULT_RESP_HEADERS})
240
+ def put_dynamic_builder(entity_config: tuple[Any, ...]) -> Callable[..., Any]:
241
+ (
242
+ dto_class_name,
243
+ entity_class_name,
244
+ etities_dict,
245
+ api_expose,
246
+ api_verbs,
247
+ _service_account,
248
+ _insert_function_class_name,
249
+ update_function_class_name,
250
+ _insert_function_name,
251
+ update_function_name,
252
+ _get_function_name,
253
+ _list_function_name,
254
+ _delete_function_name,
255
+ _get_function_type_class_name,
256
+ _list_function_type_class_name,
257
+ _delete_function_type_class_name,
258
+ ) = entity_config
259
+
260
+ def put_dynamic(*args: Any, **kwargs: Any) -> Any:
261
+ if not api_expose or "PUT" not in api_verbs:
262
+ return ("", 405, {})
263
+
264
+ update_function_type_class = (
265
+ etities_dict.get(update_function_class_name)
266
+ if update_function_class_name
267
+ else None
268
+ )
269
+
270
+ route = PutRoute(
271
+ url=ONE_DYNAMIC_ROUTE,
272
+ http_method="PUT",
273
+ dto_class=etities_dict[dto_class_name],
274
+ entity_class=etities_dict[entity_class_name],
275
+ injector_factory=injector_factory,
276
+ update_function_type_class=update_function_type_class,
277
+ update_function_name=update_function_name,
278
+ )
279
+
280
+ return route.handle_request(*args, **kwargs)
346
281
 
347
282
  return put_dynamic
348
283
 
349
- def patch_dynamic_wrapper(injector_factory: Any, *args: Any, **kwargs: Any) -> Any:
350
- def patch_dynamic(*args: Any, **kwargs: Any):
351
- # Recuperando o identificador da entidade
352
- if "entity_resource" not in kwargs:
353
- msg = "Faltando parâmetro identificador da entidade na URL."
354
- return (format_json_error(msg), 400, {**DEFAULT_RESP_HEADERS})
355
- entity_resource = kwargs.pop("entity_resource")
356
-
357
- # Verificando se o identificador do escopo foi passado na URL
358
- entity_escopo = ""
359
- if "entity_escopo" in kwargs:
360
- entity_escopo = kwargs.pop("entity_escopo")
361
-
362
- # Lendo tenant e grupo_empresarial
363
- tenant, grupo_empresarial, force_reload = _get_query_args()
364
-
365
- try:
366
- # Recuperando o código do DTO e Entity correspondente
367
- entity_loader = EntityLoader()
368
- (
369
- dto_class_name,
370
- entity_class_name,
371
- etities_dict,
372
- api_expose,
373
- api_verbs,
374
- _insert_function_class_name,
375
- _update_function_class_name,
376
- _insert_function_name,
377
- _update_function_name,
378
- _get_function_name,
379
- _list_function_name,
380
- _delete_function_name,
381
- ) = entity_loader.load_entity_source(
382
- entity_resource,
383
- tenant,
384
- grupo_empresarial,
385
- escopo=entity_escopo,
386
- force_reload=force_reload,
387
- )
388
-
389
- # Verificando se essa API deve ser exposta
390
- if not api_expose or "PATCH" not in api_verbs:
391
- return ("", 405, {})
392
-
393
- # Executando o list pelo RestLib
394
- route = PatchRoute(
395
- url=ONE_DYNAMIC_ROUTE,
396
- http_method="PATCH",
397
- dto_class=etities_dict[dto_class_name],
398
- entity_class=etities_dict[entity_class_name],
399
- injector_factory=injector_factory,
400
- )
401
-
402
- return route.handle_request(*args, **kwargs)
403
- except MissingEntityConfigException:
404
- msg = f"Entity configuration for {entity_resource} not found."
405
- return (format_json_error(msg), 412, {**DEFAULT_RESP_HEADERS})
284
+ def patch_dynamic_builder(entity_config: tuple[Any, ...]) -> Callable[..., Any]:
285
+ (
286
+ dto_class_name,
287
+ entity_class_name,
288
+ etities_dict,
289
+ api_expose,
290
+ api_verbs,
291
+ _service_account,
292
+ _insert_function_class_name,
293
+ _update_function_class_name,
294
+ _insert_function_name,
295
+ _update_function_name,
296
+ _get_function_name,
297
+ _list_function_name,
298
+ _delete_function_name,
299
+ *_,
300
+ ) = entity_config
301
+
302
+ def patch_dynamic(*args: Any, **kwargs: Any) -> Any:
303
+ if not api_expose or "PATCH" not in api_verbs:
304
+ return ("", 405, {})
305
+
306
+ route = PatchRoute(
307
+ url=ONE_DYNAMIC_ROUTE,
308
+ http_method="PATCH",
309
+ dto_class=etities_dict[dto_class_name],
310
+ entity_class=etities_dict[entity_class_name],
311
+ injector_factory=injector_factory,
312
+ )
313
+
314
+ return route.handle_request(*args, **kwargs)
406
315
 
407
316
  return patch_dynamic
408
317
 
409
- def delete_dynamic_wrapper(injector_factory: Any, *args: Any, **kwargs: Any) -> Any:
410
- def delete_dynamic(*args: Any, **kwargs: Any):
411
- # Recuperando o identificador da entidade
412
- if "entity_resource" not in kwargs:
413
- msg = "Faltando parâmetro identificador da entidade na URL."
414
- return (format_json_error(msg), 400, {**DEFAULT_RESP_HEADERS})
415
- entity_resource = kwargs.pop("entity_resource")
416
-
417
- # Verificando se o identificador do escopo foi passado na URL
418
- entity_escopo = ""
419
- if "entity_escopo" in kwargs:
420
- entity_escopo = kwargs.pop("entity_escopo")
421
-
422
- # Lendo tenant e grupo_empresarial
423
- tenant, grupo_empresarial, force_reload = _get_query_args()
424
-
425
- try:
426
- # Recuperando o código do DTO e Entity correspondente
427
- entity_loader = EntityLoader()
428
- (
429
- dto_class_name,
430
- entity_class_name,
431
- etities_dict,
432
- api_expose,
433
- api_verbs,
434
- _insert_function_class_name,
435
- _update_function_class_name,
436
- _insert_function_name,
437
- _update_function_name,
438
- _get_function_name,
439
- _list_function_name,
440
- delete_function_name,
441
- _get_function_type_class_name,
442
- _list_function_type_class_name,
443
- delete_function_type_class_name,
444
- ) = entity_loader.load_entity_source(
445
- entity_resource,
446
- tenant,
447
- grupo_empresarial,
448
- escopo=entity_escopo,
449
- force_reload=force_reload,
450
- )
451
-
452
- # Verificando se essa API deve ser exposta
453
- if not api_expose or "DELETE" not in api_verbs:
454
- return ("", 405, {})
455
-
456
- # Executando o list pelo RestLib
457
- route = DeleteRoute(
458
- url=ONE_DYNAMIC_ROUTE,
459
- http_method="DELETE",
460
- dto_class=etities_dict[dto_class_name],
461
- entity_class=etities_dict[entity_class_name],
462
- injector_factory=injector_factory,
463
- delete_function_name=delete_function_name,
464
- delete_function_type_class=etities_dict.get(
465
- delete_function_type_class_name
466
- ),
467
- )
468
-
469
- return route.handle_request(*args, **kwargs)
470
- except MissingEntityConfigException:
471
- msg = f"Entity configuration for {entity_resource} not found."
472
- return (format_json_error(msg), 412, {**DEFAULT_RESP_HEADERS})
318
+ def delete_dynamic_builder(entity_config: tuple[Any, ...]) -> Callable[..., Any]:
319
+ (
320
+ dto_class_name,
321
+ entity_class_name,
322
+ etities_dict,
323
+ api_expose,
324
+ api_verbs,
325
+ _service_account,
326
+ _insert_function_class_name,
327
+ _update_function_class_name,
328
+ _insert_function_name,
329
+ _update_function_name,
330
+ _get_function_name,
331
+ _list_function_name,
332
+ delete_function_name,
333
+ _get_function_type_class_name,
334
+ _list_function_type_class_name,
335
+ delete_function_type_class_name,
336
+ ) = entity_config
337
+
338
+ def delete_dynamic(*args: Any, **kwargs: Any) -> Any:
339
+ if not api_expose or "DELETE" not in api_verbs:
340
+ return ("", 405, {})
341
+
342
+ route = DeleteRoute(
343
+ url=ONE_DYNAMIC_ROUTE,
344
+ http_method="DELETE",
345
+ dto_class=etities_dict[dto_class_name],
346
+ entity_class=etities_dict[entity_class_name],
347
+ injector_factory=injector_factory,
348
+ delete_function_name=delete_function_name,
349
+ delete_function_type_class=etities_dict.get(
350
+ delete_function_type_class_name
351
+ ),
352
+ )
353
+
354
+ return route.handle_request(*args, **kwargs)
473
355
 
474
356
  return delete_dynamic
475
357
 
476
- # Ajustando para o padrão com multi database (se necessário)
477
- if multidb:
478
- list_dynamic = multi_database()(list_dynamic_wrapper(injector_factory))
479
- get_dynamic = multi_database()(get_dynamic_wrapper(injector_factory))
480
- post_dynamic = multi_database()(post_dynamic_wrapper(injector_factory))
481
- put_dynamic = multi_database()(put_dynamic_wrapper(injector_factory))
482
- patch_dynamic = multi_database()(patch_dynamic_wrapper(injector_factory))
483
- delete_dynamic = multi_database()(delete_dynamic_wrapper(injector_factory))
484
- else:
485
- list_dynamic = list_dynamic_wrapper(injector_factory)
486
- get_dynamic = get_dynamic_wrapper(injector_factory)
487
- post_dynamic = post_dynamic_wrapper(injector_factory)
488
- put_dynamic = put_dynamic_wrapper(injector_factory)
489
- patch_dynamic = patch_dynamic_wrapper(injector_factory)
490
- delete_dynamic = delete_dynamic_wrapper(injector_factory)
358
+ list_dynamic = _dynamic_route_wrapper(
359
+ list_dynamic_builder, endpoint_suffix="list_dynamic"
360
+ )
361
+ get_dynamic = _dynamic_route_wrapper(
362
+ get_dynamic_builder, endpoint_suffix="get_dynamic"
363
+ )
364
+ post_dynamic = _dynamic_route_wrapper(
365
+ post_dynamic_builder, endpoint_suffix="post_dynamic"
366
+ )
367
+ put_dynamic = _dynamic_route_wrapper(
368
+ put_dynamic_builder, endpoint_suffix="put_dynamic"
369
+ )
370
+ patch_dynamic = _dynamic_route_wrapper(
371
+ patch_dynamic_builder, endpoint_suffix="patch_dynamic"
372
+ )
373
+ delete_dynamic = _dynamic_route_wrapper(
374
+ delete_dynamic_builder, endpoint_suffix="delete_dynamic"
375
+ )
491
376
 
492
377
  # Registrando as rotas no flask
493
378
  flask_app.add_url_rule(
@@ -0,0 +1 @@
1
+ #
@@ -0,0 +1,39 @@
1
+ import uuid
2
+
3
+ from nsj_rest_lib.decorator.dto import DTO
4
+ from nsj_rest_lib.descriptor.dto_field import DTOField
5
+ from nsj_rest_lib.descriptor.dto_field_validators import DTOFieldValidators
6
+ from nsj_rest_lib.dto.dto_base import DTOBase
7
+
8
+
9
+ @DTO()
10
+ class EscopoDTO(DTOBase):
11
+
12
+ id: uuid.UUID = DTOField(
13
+ pk=True,
14
+ resume=True,
15
+ not_null=True,
16
+ default_value=uuid.uuid4,
17
+ strip=True,
18
+ min=36,
19
+ max=36,
20
+ validator=DTOFieldValidators().validate_uuid,
21
+ )
22
+
23
+ codigo: str = DTOField(
24
+ resume=True,
25
+ not_null=True,
26
+ strip=True,
27
+ min=1,
28
+ max=100,
29
+ unique="escopo_codigo",
30
+ candidate_key=True,
31
+ )
32
+
33
+ service_account: str = DTOField(
34
+ resume=True,
35
+ strip=True,
36
+ min=5,
37
+ max=320,
38
+ validator=DTOFieldValidators().validate_email,
39
+ )
File without changes
@@ -0,0 +1,15 @@
1
+ import uuid
2
+
3
+ from nsj_rest_lib.entity.entity_base import EntityBase
4
+ from nsj_rest_lib.decorator.entity import Entity
5
+
6
+
7
+ @Entity(
8
+ table_name="restlib2.escopo",
9
+ pk_field="id",
10
+ default_order_fields=["codigo", "id"],
11
+ )
12
+ class EscopoEntity(EntityBase):
13
+ id: uuid.UUID = None
14
+ codigo: str = None
15
+ service_account: str = None
@@ -70,6 +70,7 @@ class EntityConfigWriter:
70
70
  return {
71
71
  "dto_class_name": compiler_result.dto_class_name,
72
72
  "entity_class_name": compiler_result.entity_class_name,
73
+ "service_account": compiler_result.service_account,
73
74
  "insert_function_class_name": compiler_result.insert_function_class_name,
74
75
  "insert_function_name": compiler_result.insert_function_name,
75
76
  "source_insert_function": compiler_result.source_insert_function,
@@ -141,6 +142,7 @@ class EntityConfigWriter:
141
142
  compiler_result.source_get_function_type,
142
143
  compiler_result.source_list_function_type,
143
144
  compiler_result.source_delete_function_type,
145
+ compiler_result.service_account,
144
146
  ):
145
147
  hasher.update(content)
146
148
 
@@ -24,6 +24,7 @@ class LoadedEntity:
24
24
  self.api_expose: bool = False
25
25
  self.api_verbs: list[str] = []
26
26
  self.relations_dependencies: list[RelationDependency] = []
27
+ self.service_account: str | None = None
27
28
  self.insert_function_class_name: str | None = None
28
29
  self.update_function_class_name: str | None = None
29
30
  self.insert_function_name: str | None = None
@@ -102,6 +103,7 @@ class EntityLoader:
102
103
  entities_dict = namespace.entities_dict
103
104
  api_expose = loaded_entity.api_expose
104
105
  api_verbs = loaded_entity.api_verbs
106
+ service_account = loaded_entity.service_account
105
107
  relations_dependencies = loaded_entity.relations_dependencies
106
108
  insert_function_class_name = loaded_entity.insert_function_class_name
107
109
  update_function_class_name = loaded_entity.update_function_class_name
@@ -164,6 +166,7 @@ class EntityLoader:
164
166
  entities_dict,
165
167
  api_expose,
166
168
  api_verbs,
169
+ service_account,
167
170
  insert_function_class_name,
168
171
  update_function_class_name,
169
172
  insert_function_name,
@@ -195,6 +198,7 @@ class EntityLoader:
195
198
  entities_dict,
196
199
  api_expose,
197
200
  api_verbs,
201
+ service_account,
198
202
  insert_function_class_name,
199
203
  update_function_class_name,
200
204
  insert_function_name,
@@ -213,6 +217,7 @@ class EntityLoader:
213
217
  namespace,
214
218
  api_expose,
215
219
  api_verbs,
220
+ service_account,
216
221
  insert_function_class_name,
217
222
  update_function_class_name,
218
223
  insert_function_name,
@@ -230,6 +235,7 @@ class EntityLoader:
230
235
  namespace.entities_dict,
231
236
  api_expose,
232
237
  api_verbs,
238
+ service_account,
233
239
  insert_function_class_name,
234
240
  update_function_class_name,
235
241
  insert_function_name,
@@ -249,6 +255,7 @@ class EntityLoader:
249
255
  entities_dict,
250
256
  api_expose,
251
257
  api_verbs,
258
+ service_account,
252
259
  insert_function_class_name,
253
260
  update_function_class_name,
254
261
  insert_function_name,
@@ -293,6 +300,7 @@ class EntityLoader:
293
300
  namespace,
294
301
  api_expose,
295
302
  api_verbs,
303
+ service_account,
296
304
  insert_function_class_name,
297
305
  update_function_class_name,
298
306
  insert_function_name,
@@ -311,6 +319,7 @@ class EntityLoader:
311
319
  namespace.entities_dict,
312
320
  api_expose,
313
321
  api_verbs,
322
+ service_account,
314
323
  insert_function_class_name,
315
324
  update_function_class_name,
316
325
  insert_function_name,
@@ -367,6 +376,7 @@ class EntityLoader:
367
376
  str | None,
368
377
  str | None,
369
378
  str | None,
379
+ str | None,
370
380
  ] | None:
371
381
  # Interpretando o json de configuração da entidade
372
382
  try:
@@ -381,6 +391,7 @@ class EntityLoader:
381
391
  api_expose = entity_config["api_expose"]
382
392
  # api_resource = entity_config["api_resource"]
383
393
  api_verbs = entity_config["api_verbs"]
394
+ service_account = entity_config.get("service_account")
384
395
  insert_function_class_name = entity_config.get(
385
396
  "insert_function_class_name"
386
397
  )
@@ -533,6 +544,7 @@ class EntityLoader:
533
544
  loaded_entity.entity_hash = entity_hash
534
545
  loaded_entity.api_expose = api_expose
535
546
  loaded_entity.api_verbs = api_verbs
547
+ loaded_entity.service_account = service_account
536
548
  loaded_entity.relations_dependencies = relations_dependencies
537
549
  loaded_entity.insert_function_class_name = insert_function_class_name
538
550
  loaded_entity.update_function_class_name = update_function_class_name
@@ -559,6 +571,7 @@ class EntityLoader:
559
571
  namespace,
560
572
  api_expose,
561
573
  api_verbs,
574
+ service_account,
562
575
  insert_function_class_name,
563
576
  update_function_class_name,
564
577
  insert_function_name,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nsj_rest_lib2
3
- Version: 0.0.33
3
+ Version: 0.0.34
4
4
  Summary: Biblioteca para permitir a distribuição de rotas dinâmicas numa API, configuradas por meio de EDLs declarativos (em formato JSON).
5
5
  Home-page: https://github.com/Nasajon/nsj_rest_lib2
6
6
  Author: Nasajon Sistemas
@@ -3,7 +3,7 @@ nsj_rest_lib2/exception.py,sha256=E9uMUdoCCQOVQfc8f6gD9b5Pxurf3Q4SytDCcqSlkZ8,56
3
3
  nsj_rest_lib2/redis_config.py,sha256=4KLcvYS3nJO7PMQgF6F9_j6r-TyqcS7TBbd3LEQuKDU,629
4
4
  nsj_rest_lib2/settings.py,sha256=Hn_o1HZmievnYb8D1kNT2Nq-OEjxbyNjOiOpbnFsMwE,367
5
5
  nsj_rest_lib2/compiler/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- nsj_rest_lib2/compiler/compiler.py,sha256=f62qzh3R9oC9JJ0pkaHJwVyhM0MEwhZDs_q7MzdDlxw,34467
6
+ nsj_rest_lib2/compiler/compiler.py,sha256=a-lfAEgj2O6mmYKoA3q2x_tVhjBD-y7C6LHixStgqaU,35263
7
7
  nsj_rest_lib2/compiler/compiler_structures.py,sha256=stspjqJGXU7Vz3BqQ-ZF5ZmumFm3R4jpkWgVVsXW5d0,1488
8
8
  nsj_rest_lib2/compiler/dto_compiler.py,sha256=Fs6VysuAjBgct7_Wc0sugvx7z9tfnlZcSrBu0l0Pyp0,7019
9
9
  nsj_rest_lib2/compiler/entity_compiler.py,sha256=LeGEBxsjAmZZog2gh4vjUX1aFp9JSVgHHOdTkY0aH-s,6733
@@ -14,7 +14,7 @@ nsj_rest_lib2/compiler/migration_compiler.py,sha256=vlG54XmYRqzIo0Iey-4HbSRzPg3Y
14
14
  nsj_rest_lib2/compiler/migration_compiler_alter_table.py,sha256=awtqVrKox86rmlQV7K17JzZJZqz9cF7McshLBlLx65s,7969
15
15
  nsj_rest_lib2/compiler/migration_compiler_create_table.py,sha256=h22cU53EFnuB5t28fMZ_r7MM-14Vqqu3emebBUJN2LY,2606
16
16
  nsj_rest_lib2/compiler/migration_compiler_util.py,sha256=WB_GRX78nTRKlZkgL-4yowwlQoAe81llZ-E2AYfIbh4,5168
17
- nsj_rest_lib2/compiler/model.py,sha256=hmL9ItHGTX4sNZbAYCzVdZnX8JYb_MjG1PtuaQQ2hsA,2310
17
+ nsj_rest_lib2/compiler/model.py,sha256=ow9dQve7npl4OZU2GyS0HMZ2OXvBSebWTQCXFm6iMxM,2358
18
18
  nsj_rest_lib2/compiler/property_compiler.py,sha256=hMQX5vrLqjOEM_wdzuerxuARMq5JhZQ_R8cUVoLHNNM,47631
19
19
  nsj_rest_lib2/compiler/edl_model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
20
  nsj_rest_lib2/compiler/edl_model/ai_entity_edl.py,sha256=664QBDcOgVnyfwtUOXO1W7AKaZhueBG335x5DuogruY,7644
@@ -34,11 +34,15 @@ nsj_rest_lib2/compiler/util/str_util.py,sha256=0ReIQ2Vy4zAmVMvGv0FcUehRQw15hlz0e
34
34
  nsj_rest_lib2/compiler/util/type_naming_util.py,sha256=jYUnr3eC6ewwhIAFHF89OOLoSH9aO_syHMF66AsWX3s,2355
35
35
  nsj_rest_lib2/compiler/util/type_util.py,sha256=HTKOH4uRTOY0YgoM8oUv_6cEcReE_bgKYXFBsQCb-3A,357
36
36
  nsj_rest_lib2/controller/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
- nsj_rest_lib2/controller/dynamic_controller.py,sha256=y9bSGJdQ-mIIkDneY0nRFfmivPOzDbeGFxFU9J3pQTk,21642
37
+ nsj_rest_lib2/controller/dynamic_controller.py,sha256=8kvN75-E4mA1nApNJMMQstKv036z8tDPV5YtLCokNQU,14132
38
+ nsj_rest_lib2/dto/__init__.py,sha256=MsSFjiLMLJZ7QhUPpVBWKiyDnCzryquRyr329NoCACI,2
39
+ nsj_rest_lib2/dto/escopo_dto.py,sha256=RSAPVTgckH57qd9y_dVHYG0NcAKg7B2UFZUyQRok28M,869
40
+ nsj_rest_lib2/entity/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
41
+ nsj_rest_lib2/entity/escopo_entity.py,sha256=T4bxFDzHJvIj-nZ_6d0Xh2oQg21HgoRjp19nt6clY18,338
38
42
  nsj_rest_lib2/service/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
39
- nsj_rest_lib2/service/entity_config_writer.py,sha256=4pLNqyw2asTiiuxNwYnH69eLLABa9GfrgD_GxS6vJ18,5991
40
- nsj_rest_lib2/service/entity_loader.py,sha256=65qa_45tPAQWU6G_vsG9Gy4d9OksYT2yyyr137zrWb0,24812
41
- nsj_rest_lib2-0.0.33.dist-info/METADATA,sha256=7IMSPUzmXYlgr-_SCRfFTo7ekSbk8y-x3LtY6cVuhyA,1094
42
- nsj_rest_lib2-0.0.33.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
43
- nsj_rest_lib2-0.0.33.dist-info/top_level.txt,sha256=L6zh0EfH8_rur7OJ8_V-El-XEMf4qg3bkF8ADgqLVIA,14
44
- nsj_rest_lib2-0.0.33.dist-info/RECORD,,
43
+ nsj_rest_lib2/service/entity_config_writer.py,sha256=bLXWrncm_OOjkvF_wcEAJ1NVjhcrV-zt41gDNtPDh68,6100
44
+ nsj_rest_lib2/service/entity_loader.py,sha256=FPHdJs6qA_-bjtHMsJ7OAe0RxVv0vfOMX5lN51ZB_JA,25355
45
+ nsj_rest_lib2-0.0.34.dist-info/METADATA,sha256=WfkNgNrmcbNCbwJIvWqv8DqqcBSSBNgNl1YZHi54dfE,1094
46
+ nsj_rest_lib2-0.0.34.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
47
+ nsj_rest_lib2-0.0.34.dist-info/top_level.txt,sha256=L6zh0EfH8_rur7OJ8_V-El-XEMf4qg3bkF8ADgqLVIA,14
48
+ nsj_rest_lib2-0.0.34.dist-info/RECORD,,