jaaql-middleware-python 4.33.8__tar.gz → 4.33.10__tar.gz
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.
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/PKG-INFO +1 -1
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/constants.py +1 -1
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/db/db_utils.py +4 -1
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/documentation/documentation_internal.py +89 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/documentation/documentation_public.py +0 -234
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/exceptions/http_status_exception.py +3 -1
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/generated_constants.py +1 -1
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/interpreter/interpret_jaaql.py +0 -2
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/mvc/controller.py +30 -27
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/mvc/exception_queries.py +5 -55
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/mvc/generated_queries.py +71 -146
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/mvc/model.py +365 -436
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/scripts/01.install_domains.generated.sql +2 -5
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/scripts/04.install_jaaql_data_structures.generated.sql +6 -23
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/scripts/05.install_static_data.generated.sql +6 -2
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/scripts/ZZZZ.generated_functions_views_and_permissions.sql +419 -965
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/scripts/ZZZZ.reset_references.sql +101 -120
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql_middleware_python.egg-info/PKG-INFO +1 -1
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/LICENSE.txt +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/README.md +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/__init__.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/config/__init__.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/config/config-docker.ini +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/config/config-test.ini +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/config/config.ini +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/config_constants.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/db/__init__.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/db/db_interface.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/db/db_pg_interface.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/db/db_utils_no_circ.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/documentation/__init__.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/documentation/documentation_shared.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/email/__init__.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/email/email_manager.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/email/email_manager_service.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/email/patch_ems.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/exceptions/__init__.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/exceptions/custom_http_status.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/exceptions/jaaql_interpretable_handled_errors.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/exceptions/not_yet_implement_exception.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/interpreter/__init__.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/jaaql.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/migrations/__init__.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/migrations/migrations.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/mvc/__init__.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/mvc/base_controller.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/mvc/base_model.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/mvc/controller_interface.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/mvc/handmade_queries.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/mvc/model_interface.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/mvc/response.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/openapi/__init__.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/openapi/swagger_documentation.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/patch.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/scripts/02.install_super_user.exceptions.sql +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/scripts/03.install_super_user.handwritten.sql +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/scripts/06.install_jaaql.exceptions.sql +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/scripts/swagger_template.html +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/services/__init__.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/services/cached_canned_query_service.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/services/migrations_manager_service.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/services/patch_mms.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/services/patch_shared_var_service.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/services/shared_var_service.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/utilities/__init__.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/utilities/cron.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/utilities/crypt_utils.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/utilities/options.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/utilities/utils.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/utilities/utils_no_project_imports.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/utilities/vault.py +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql_middleware_python.egg-info/SOURCES.txt +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql_middleware_python.egg-info/dependency_links.txt +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql_middleware_python.egg-info/requires.txt +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql_middleware_python.egg-info/top_level.txt +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/setup.cfg +0 -0
- {jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jaaql-middleware-python
|
|
3
|
-
Version: 4.33.
|
|
3
|
+
Version: 4.33.10
|
|
4
4
|
Summary: The jaaql package, allowing for rapid development and deployment of RESTful HTTP applications
|
|
5
5
|
Home-page: https://github.com/JAAQL/JAAQL-middleware-python
|
|
6
6
|
Author: Software Quality Measurement and Improvement bv
|
|
@@ -116,11 +116,14 @@ def execute_supplied_statement(db_interface, query: str, parameters: dict = None
|
|
|
116
116
|
|
|
117
117
|
def force_singleton(data, as_objects: bool = False, singleton_code: int = None, singleton_message: str = None):
|
|
118
118
|
was_no_singleton = False
|
|
119
|
+
original_count = 1
|
|
119
120
|
if as_objects:
|
|
120
121
|
if len(data) != 1:
|
|
122
|
+
original_count = len(data)
|
|
121
123
|
was_no_singleton = True
|
|
122
124
|
else:
|
|
123
125
|
if len(data["rows"]) != 1:
|
|
126
|
+
original_count = len(data["rows"])
|
|
124
127
|
was_no_singleton = True
|
|
125
128
|
if len(data["rows"]) != 0:
|
|
126
129
|
data["rows"] = data["rows"][0]
|
|
@@ -129,7 +132,7 @@ def force_singleton(data, as_objects: bool = False, singleton_code: int = None,
|
|
|
129
132
|
err = ERR__expected_single_row % len(data)
|
|
130
133
|
if singleton_message is not None:
|
|
131
134
|
err = singleton_message
|
|
132
|
-
raise HttpSingletonStatusException(err, singleton_code)
|
|
135
|
+
raise HttpSingletonStatusException(err, singleton_code, original_count)
|
|
133
136
|
|
|
134
137
|
return data[0] if as_objects else data
|
|
135
138
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from jaaql.documentation.documentation_public import ARG_RES__query
|
|
1
2
|
from jaaql.openapi.swagger_documentation import *
|
|
2
3
|
from jaaql.constants import *
|
|
3
4
|
from jaaql.mvc.generated_queries import *
|
|
@@ -478,4 +479,92 @@ DOCUMENTATION__procedures = SwaggerDocumentation(
|
|
|
478
479
|
)
|
|
479
480
|
]
|
|
480
481
|
)
|
|
482
|
+
)
|
|
483
|
+
|
|
484
|
+
ARG_RES__id_token_hint = SwaggerArgumentResponse(
|
|
485
|
+
name="id_token_hint",
|
|
486
|
+
description="Optional ID Token previously issued to the user; recommended for OIDC RP-initiated logout.",
|
|
487
|
+
arg_type=str,
|
|
488
|
+
required=False,
|
|
489
|
+
condition="Recommended",
|
|
490
|
+
example=["eyJ..."]
|
|
491
|
+
)
|
|
492
|
+
|
|
493
|
+
DOCUMENTATION__oidc_begin_logout = SwaggerDocumentation(
|
|
494
|
+
tags="oidc",
|
|
495
|
+
security=False,
|
|
496
|
+
methods=SwaggerMethod(
|
|
497
|
+
name="Begin OIDC logout",
|
|
498
|
+
description="Clears the app session, sets a logout state cookie, and redirects the browser to the OP end-session endpoint. After logout, the OP redirects to /api/oidc/post-logout.",
|
|
499
|
+
method=REST__GET,
|
|
500
|
+
arguments=[
|
|
501
|
+
ARG_RES__tenant,
|
|
502
|
+
ARG_RES__provider,
|
|
503
|
+
ARG_RES__application,
|
|
504
|
+
ARG_RES__schema,
|
|
505
|
+
ARG_RES__redirect_uri,
|
|
506
|
+
ARG_RES__id_token_hint
|
|
507
|
+
],
|
|
508
|
+
response=SwaggerFlatResponse(
|
|
509
|
+
description="Redirect",
|
|
510
|
+
code=HTTPStatus.FOUND,
|
|
511
|
+
body="You are being redirected to the identity server for logout..."
|
|
512
|
+
)
|
|
513
|
+
)
|
|
514
|
+
)
|
|
515
|
+
|
|
516
|
+
DOCUMENTATION__oidc_post_logout = SwaggerDocumentation(
|
|
517
|
+
tags="oidc",
|
|
518
|
+
security=False,
|
|
519
|
+
methods=SwaggerMethod(
|
|
520
|
+
name="OIDC post-logout redirect",
|
|
521
|
+
description="Receives the OP redirect after logout, validates state, clears the cookie, and redirects to the final app URL.",
|
|
522
|
+
method=REST__GET,
|
|
523
|
+
arguments=SwaggerArgumentResponse(
|
|
524
|
+
name="state",
|
|
525
|
+
description="Opaque state returned by the OP; must match the value set at logout start.",
|
|
526
|
+
arg_type=str,
|
|
527
|
+
example=["y3nvJ..."]
|
|
528
|
+
),
|
|
529
|
+
response=SwaggerFlatResponse(
|
|
530
|
+
description="Redirect",
|
|
531
|
+
code=HTTPStatus.FOUND,
|
|
532
|
+
body="You are being redirected back to your place in the app..."
|
|
533
|
+
)
|
|
534
|
+
)
|
|
535
|
+
)
|
|
536
|
+
|
|
537
|
+
DOCUMENTATION__security_event = SwaggerDocumentation(
|
|
538
|
+
tags="security",
|
|
539
|
+
methods=SwaggerMethod(
|
|
540
|
+
name="Action security event",
|
|
541
|
+
description="Executes a security event",
|
|
542
|
+
method=REST__POST,
|
|
543
|
+
body=[
|
|
544
|
+
ARG_RES__application,
|
|
545
|
+
SwaggerArgumentResponse(
|
|
546
|
+
name=KG__security_event__name,
|
|
547
|
+
description="The name of the security event",
|
|
548
|
+
arg_type=str,
|
|
549
|
+
example=["add-user"]
|
|
550
|
+
),
|
|
551
|
+
SwaggerArgumentResponse(
|
|
552
|
+
name=KG__security_event__type,
|
|
553
|
+
description="The name of the security event",
|
|
554
|
+
arg_type=str,
|
|
555
|
+
example=["add-user"]
|
|
556
|
+
),
|
|
557
|
+
SwaggerArgumentResponse(
|
|
558
|
+
name=KEY__parameters,
|
|
559
|
+
description="Any parameters to pass to the underlying function",
|
|
560
|
+
arg_type=ARG_RESP__allow_all
|
|
561
|
+
),
|
|
562
|
+
SwaggerArgumentResponse(
|
|
563
|
+
name="explicit_types",
|
|
564
|
+
description="Explicit types for parameters",
|
|
565
|
+
arg_type=ARG_RESP__allow_all
|
|
566
|
+
)
|
|
567
|
+
],
|
|
568
|
+
response=RES__allow_all
|
|
569
|
+
)
|
|
481
570
|
)
|
|
@@ -76,20 +76,6 @@ DOCUMENTATION__create_account_batch = SwaggerDocumentation(
|
|
|
76
76
|
)
|
|
77
77
|
)
|
|
78
78
|
|
|
79
|
-
DOCUMENTATION__password = SwaggerDocumentation(
|
|
80
|
-
tags="Account",
|
|
81
|
-
methods=SwaggerMethod(
|
|
82
|
-
method=REST__POST,
|
|
83
|
-
name="Change password",
|
|
84
|
-
description="Will change the logged in users password to the new one",
|
|
85
|
-
body=[
|
|
86
|
-
rename_arg(ARG_RES__password, KEY__old_password, "The old password for the user"),
|
|
87
|
-
ARG_RES__password
|
|
88
|
-
],
|
|
89
|
-
response=RES__oauth_token
|
|
90
|
-
)
|
|
91
|
-
)
|
|
92
|
-
|
|
93
79
|
ARG_RES__event_application = SwaggerArgumentResponse(
|
|
94
80
|
name=KG__security_event__application,
|
|
95
81
|
description="The application of the dispatcher",
|
|
@@ -112,31 +98,6 @@ ARG_RES__query = SwaggerArgumentResponse(
|
|
|
112
98
|
required=True
|
|
113
99
|
)
|
|
114
100
|
|
|
115
|
-
ARG_RES__event_lock = SwaggerArgumentResponse(
|
|
116
|
-
name=KG__security_event__event_lock,
|
|
117
|
-
description="A key that is used to reference a security event",
|
|
118
|
-
arg_type=str,
|
|
119
|
-
example="0aff271e-bf0a-463b-b234-f558abd70edd"
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
ARG_RES__security_event_unlock_key = SwaggerArgumentResponse(
|
|
123
|
-
name=KG__security_event__unlock_key,
|
|
124
|
-
description="The unlock key",
|
|
125
|
-
required=False,
|
|
126
|
-
condition="Are you using a key to unlock or a code",
|
|
127
|
-
arg_type=str,
|
|
128
|
-
example="c9a941d5-2aea-4b96-967b-32a01e889d03"
|
|
129
|
-
)
|
|
130
|
-
|
|
131
|
-
ARG_RES__security_event_unlock_code = SwaggerArgumentResponse(
|
|
132
|
-
name=KG__security_event__unlock_code,
|
|
133
|
-
description="The unlock code",
|
|
134
|
-
required=False,
|
|
135
|
-
condition="Are you using a key to unlock or a code",
|
|
136
|
-
arg_type=str,
|
|
137
|
-
example="ABC123"
|
|
138
|
-
)
|
|
139
|
-
|
|
140
101
|
ARG_RES__oauth_token = SwaggerArgumentResponse(
|
|
141
102
|
name=KEY__oauth_token,
|
|
142
103
|
description="An auth token",
|
|
@@ -144,51 +105,6 @@ ARG_RES__oauth_token = SwaggerArgumentResponse(
|
|
|
144
105
|
example=EXAMPLE__jwt
|
|
145
106
|
)
|
|
146
107
|
|
|
147
|
-
DOCUMENTATION__reset_password = SwaggerDocumentation(
|
|
148
|
-
tags="Reset Password",
|
|
149
|
-
security=False,
|
|
150
|
-
methods=[
|
|
151
|
-
SwaggerMethod(
|
|
152
|
-
name="Request an password reset",
|
|
153
|
-
description="Requests a password reset, sending an email to the user (or if the email template does not contain "
|
|
154
|
-
"the reset code, they will then need to be approved by an admin).",
|
|
155
|
-
method=REST__POST,
|
|
156
|
-
body=[
|
|
157
|
-
ARG_RES__username,
|
|
158
|
-
ARG_RES__parameters,
|
|
159
|
-
ARG_RES__event_application,
|
|
160
|
-
SwaggerArgumentResponse(
|
|
161
|
-
name=KEY__reset_password_template,
|
|
162
|
-
description="The template to send if the user is already signed up",
|
|
163
|
-
required=False,
|
|
164
|
-
condition="Should an email be sent or the default be used",
|
|
165
|
-
arg_type=str,
|
|
166
|
-
example=KG__application__default_r_et
|
|
167
|
-
),
|
|
168
|
-
SwaggerArgumentResponse(
|
|
169
|
-
name=KEY__unregistered_user_reset_password_template,
|
|
170
|
-
description="The template to send if the user hasn't signed up",
|
|
171
|
-
required=False,
|
|
172
|
-
condition="Should an email be sent or the default be used",
|
|
173
|
-
arg_type=str,
|
|
174
|
-
example=KG__application__default_u_et
|
|
175
|
-
)
|
|
176
|
-
],
|
|
177
|
-
response=[
|
|
178
|
-
SwaggerResponse(
|
|
179
|
-
description="Reset password response",
|
|
180
|
-
response=ARG_RES__event_lock
|
|
181
|
-
),
|
|
182
|
-
SwaggerFlatResponse(
|
|
183
|
-
description=ERR__too_many_reset_requests,
|
|
184
|
-
code=HTTPStatus.TOO_MANY_REQUESTS,
|
|
185
|
-
body=ERR__too_many_reset_requests
|
|
186
|
-
)
|
|
187
|
-
]
|
|
188
|
-
)
|
|
189
|
-
]
|
|
190
|
-
)
|
|
191
|
-
|
|
192
108
|
DOCUMENTATION__emails = SwaggerDocumentation(
|
|
193
109
|
tags="Emails",
|
|
194
110
|
security=True,
|
|
@@ -209,156 +125,6 @@ DOCUMENTATION__emails = SwaggerDocumentation(
|
|
|
209
125
|
)
|
|
210
126
|
)
|
|
211
127
|
|
|
212
|
-
DOCUMENTATION__sign_up = SwaggerDocumentation(
|
|
213
|
-
tags="sign_up",
|
|
214
|
-
# Explicitly set sign up to true to enforce design decision. We use the attempted insert of the current user (which can be the public user) as security
|
|
215
|
-
# If the insert fails then the user cannot sign up
|
|
216
|
-
security=False,
|
|
217
|
-
methods=[
|
|
218
|
-
SwaggerMethod(
|
|
219
|
-
name="Signs up to the Platform",
|
|
220
|
-
description="Requests an invitation, sending an email to the user.",
|
|
221
|
-
method=REST__POST,
|
|
222
|
-
body=[
|
|
223
|
-
ARG_RES__username,
|
|
224
|
-
set_nullable(ARG_RES__password, "Is the user going through an unconfirmed signup"),
|
|
225
|
-
ARG_RES__parameters,
|
|
226
|
-
ARG_RES__remember_me,
|
|
227
|
-
ARG_RES__query,
|
|
228
|
-
ARG_RES__event_application,
|
|
229
|
-
SwaggerArgumentResponse(
|
|
230
|
-
name=KEY__sign_up_template,
|
|
231
|
-
description="The template to send if the user hasn't signed up",
|
|
232
|
-
required=False,
|
|
233
|
-
condition="Should an email be sent or the default be used",
|
|
234
|
-
arg_type=str,
|
|
235
|
-
example=KG__application__default_s_et
|
|
236
|
-
),
|
|
237
|
-
SwaggerArgumentResponse(
|
|
238
|
-
name=KEY__already_signed_up_template,
|
|
239
|
-
description="The template to send if the user is already signed up",
|
|
240
|
-
required=False,
|
|
241
|
-
condition="Should an email be sent or the default be used",
|
|
242
|
-
arg_type=str,
|
|
243
|
-
example=KG__application__default_a_et
|
|
244
|
-
)
|
|
245
|
-
],
|
|
246
|
-
response=RES__allow_all
|
|
247
|
-
)
|
|
248
|
-
]
|
|
249
|
-
)
|
|
250
|
-
|
|
251
|
-
DOCUMENTATION__resend_sign_up = SwaggerDocumentation(
|
|
252
|
-
tags="sign_up",
|
|
253
|
-
security=True,
|
|
254
|
-
methods=[
|
|
255
|
-
SwaggerMethod(
|
|
256
|
-
name="Resend sign up email",
|
|
257
|
-
description="Allows an unconfirmed user to resend themselves a signup email when they are logged in.",
|
|
258
|
-
method=REST__POST,
|
|
259
|
-
body=[
|
|
260
|
-
ARG_RES__event_application,
|
|
261
|
-
SwaggerArgumentResponse(
|
|
262
|
-
name=KEY__sign_up_template,
|
|
263
|
-
description="The template to send if the user hasn't signed up",
|
|
264
|
-
required=False,
|
|
265
|
-
condition="Should an email be sent or the default be used",
|
|
266
|
-
arg_type=str,
|
|
267
|
-
example=KG__application__default_s_et
|
|
268
|
-
),
|
|
269
|
-
SwaggerArgumentResponse(
|
|
270
|
-
name=KEY__already_signed_up_template,
|
|
271
|
-
description="The template to send if the user is already signed up",
|
|
272
|
-
required=False,
|
|
273
|
-
condition="Should an email be sent or the default be used",
|
|
274
|
-
arg_type=str,
|
|
275
|
-
example=KG__application__default_a_et
|
|
276
|
-
)
|
|
277
|
-
],
|
|
278
|
-
response=RES__allow_all
|
|
279
|
-
)
|
|
280
|
-
]
|
|
281
|
-
)
|
|
282
|
-
|
|
283
|
-
DOCUMENTATION__invite = SwaggerDocumentation(
|
|
284
|
-
tags="invite",
|
|
285
|
-
# Explicitly set sign up to true to enforce design decision. We use the attempted insert of the current user (which can be the public user) as security
|
|
286
|
-
# If the insert fails then the user cannot sign up
|
|
287
|
-
security=True,
|
|
288
|
-
methods=[
|
|
289
|
-
SwaggerMethod(
|
|
290
|
-
name="Request an invitation",
|
|
291
|
-
description="Requests an invitation, sending an email to the user (or if the email template does not contain "
|
|
292
|
-
"the unlock code, they will then need to be approved by an admin).",
|
|
293
|
-
method=REST__POST,
|
|
294
|
-
body=[
|
|
295
|
-
set_nullable(ARG_RES__username, "Potentially if the user is not known"),
|
|
296
|
-
ARG_RES__parameters,
|
|
297
|
-
ARG_RES__event_application,
|
|
298
|
-
SwaggerArgumentResponse(
|
|
299
|
-
name=KEY__sign_up_template,
|
|
300
|
-
description="The template to send if the user hasn't signed up",
|
|
301
|
-
required=False,
|
|
302
|
-
condition="Should an email be sent or the default be used",
|
|
303
|
-
arg_type=str,
|
|
304
|
-
example=KG__application__default_s_et
|
|
305
|
-
),
|
|
306
|
-
SwaggerArgumentResponse(
|
|
307
|
-
name=KEY__already_signed_up_template,
|
|
308
|
-
description="The template to send if the user is already signed up",
|
|
309
|
-
required=False,
|
|
310
|
-
condition="Should an email be sent or the default be used",
|
|
311
|
-
arg_type=str,
|
|
312
|
-
example=KG__application__default_a_et
|
|
313
|
-
)
|
|
314
|
-
],
|
|
315
|
-
response=RES__allow_all
|
|
316
|
-
)
|
|
317
|
-
]
|
|
318
|
-
)
|
|
319
|
-
|
|
320
|
-
from jaaql.mvc.handmade_queries import EMAIL_TYPE__signup
|
|
321
|
-
|
|
322
|
-
DOCUMENTATION__security_event = SwaggerDocumentation(
|
|
323
|
-
tags="Security Event",
|
|
324
|
-
security=False,
|
|
325
|
-
methods=[
|
|
326
|
-
SwaggerMethod(
|
|
327
|
-
name="Check Event and Key",
|
|
328
|
-
description="Checks a security event is unused and that the key is valid",
|
|
329
|
-
method=REST__POST,
|
|
330
|
-
body=[
|
|
331
|
-
set_nullable(ARG_RES__event_lock, "Just the unlock key can be provided"),
|
|
332
|
-
ARG_RES__security_event_unlock_key,
|
|
333
|
-
ARG_RES__security_event_unlock_code
|
|
334
|
-
],
|
|
335
|
-
response=SwaggerFlatResponse(
|
|
336
|
-
description="Will receive the type of the description if unlock code is correct",
|
|
337
|
-
body=EMAIL_TYPE__signup
|
|
338
|
-
)
|
|
339
|
-
),
|
|
340
|
-
SwaggerMethod(
|
|
341
|
-
name="Finish Security Event",
|
|
342
|
-
description="Finishes the security event, supplying a password which can either be a new password or your login password, if using the "
|
|
343
|
-
"already signed up flow",
|
|
344
|
-
method=REST__PUT,
|
|
345
|
-
body=[
|
|
346
|
-
set_nullable(ARG_RES__event_lock, "Just the unlock key can be provided"),
|
|
347
|
-
ARG_RES__security_event_unlock_key,
|
|
348
|
-
ARG_RES__security_event_unlock_code,
|
|
349
|
-
set_nullable(ARG_RES__password, "only if it's required")
|
|
350
|
-
],
|
|
351
|
-
response=SwaggerResponse(
|
|
352
|
-
description="Signup parameters",
|
|
353
|
-
response=[
|
|
354
|
-
ARG_RES__parameters,
|
|
355
|
-
ARG_RES__username
|
|
356
|
-
]
|
|
357
|
-
)
|
|
358
|
-
)
|
|
359
|
-
]
|
|
360
|
-
)
|
|
361
|
-
|
|
362
128
|
ARG_RES__proc = [
|
|
363
129
|
SwaggerArgumentResponse(
|
|
364
130
|
name=KG__remote_procedure__application,
|
|
@@ -28,9 +28,11 @@ class HttpStatusException(Exception):
|
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
class HttpSingletonStatusException(HttpStatusException):
|
|
31
|
-
def __init__(self, message: str, response_code: int = HTTPStatus.UNPROCESSABLE_ENTITY):
|
|
31
|
+
def __init__(self, message: str, response_code: int = HTTPStatus.UNPROCESSABLE_ENTITY, actual_count: int = 1):
|
|
32
32
|
super().__init__(message, response_code)
|
|
33
33
|
|
|
34
|
+
self.actual_count = actual_count
|
|
35
|
+
|
|
34
36
|
|
|
35
37
|
class JaaqlInterpretableHandledError(Exception):
|
|
36
38
|
def __init__(self, error_code: int, http_response_code: int,
|
{jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/generated_constants.py
RENAMED
|
@@ -268,7 +268,7 @@ class Constraints(Enum):
|
|
|
268
268
|
DatabaseUserRegistryProviderTenantDatabaseKey = "database_user_registry_provider_tenant_database_key"
|
|
269
269
|
AccountIdKey = "account_id_key"
|
|
270
270
|
ValidatedIpAddressUuidKey = "validated_ip_address_uuid_key"
|
|
271
|
-
|
|
271
|
+
SecurityEventApplicationNameTypeKey = "security_event_application_name_type_key"
|
|
272
272
|
HandledErrorCodeKey = "handled_error_code_key"
|
|
273
273
|
PgBaseExceptionNameKey = "pg_base_exception_name_key"
|
|
274
274
|
PgErrorClassCodeKey = "pg_error_class_code_key"
|
|
@@ -612,8 +612,6 @@ GROUP BY CH.column_name, CH.data_type, CH.udt_name, CH.domain_name;"""
|
|
|
612
612
|
return PYFORMAT_str
|
|
613
613
|
elif isinstance(value, list):
|
|
614
614
|
return PYFORMAT_str
|
|
615
|
-
elif isinstance(value, list):
|
|
616
|
-
return PYFORMAT_str
|
|
617
615
|
elif type(value).__name__ == "date":
|
|
618
616
|
return PYFORMAT_str
|
|
619
617
|
elif isinstance(value, Decimal):
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from jaaql.mvc.exception_queries import SECURITY_EVENT_TYPE__create, SECURITY_EVENT_TYPE__delete, \
|
|
2
|
+
SECURITY_EVENT_TYPE__reset
|
|
1
3
|
from jaaql.mvc.model import JAAQLModel
|
|
2
4
|
from jaaql.mvc.base_controller import BaseJAAQLController
|
|
3
5
|
from jaaql.documentation.documentation_internal import *
|
|
@@ -93,10 +95,6 @@ class JAAQLController(BaseJAAQLController):
|
|
|
93
95
|
def prepare(http_inputs: dict, account_id: str):
|
|
94
96
|
return self.model.fetch_domains(http_inputs, account_id)
|
|
95
97
|
|
|
96
|
-
@self.publish_route('/account/password', DOCUMENTATION__password)
|
|
97
|
-
def password(account_id: str, username: str, ip_address: str, is_the_anonymous_user: bool, http_inputs: dict):
|
|
98
|
-
return self.model.add_my_account_password(account_id, username, ip_address, is_the_anonymous_user, **http_inputs)
|
|
99
|
-
|
|
100
98
|
@self.publish_route('/submit', DOCUMENTATION__submit)
|
|
101
99
|
def submit(http_inputs: dict, account_id: str, verification_hook: queue.Queue, ip_address: str):
|
|
102
100
|
return self.model.submit(http_inputs, account_id, verification_hook=verification_hook, ip_address=ip_address)
|
|
@@ -113,37 +111,29 @@ class JAAQLController(BaseJAAQLController):
|
|
|
113
111
|
def clean(connection: DBInterface):
|
|
114
112
|
self.model.clean(connection)
|
|
115
113
|
|
|
114
|
+
@self.publish_route('/security-event', DOCUMENTATION__security_event)
|
|
115
|
+
def security_event(http_inputs: dict, account_id: str):
|
|
116
|
+
security_event = security_event__select(self.model.jaaql_lookup_connection, http_inputs[KEY__application],
|
|
117
|
+
name=http_inputs[KG__security_event__name],
|
|
118
|
+
type=http_inputs[KG__security_event__type])
|
|
119
|
+
http_inputs["email"] = http_inputs[KEY__parameters]["email"]
|
|
120
|
+
if security_event[KG__security_event__type] == SECURITY_EVENT_TYPE__create:
|
|
121
|
+
return self.model.security_event__create_user(http_inputs, account_id, security_event)
|
|
122
|
+
elif security_event[KG__security_event__type] == SECURITY_EVENT_TYPE__delete:
|
|
123
|
+
return self.model.security_event__delete_user(http_inputs, account_id, security_event)
|
|
124
|
+
elif security_event[KG__security_event__type] == SECURITY_EVENT_TYPE__reset:
|
|
125
|
+
return self.model.security_event__reset_user_password(http_inputs, account_id, security_event)
|
|
126
|
+
else:
|
|
127
|
+
raise HttpStatusException("Invalid security event type")
|
|
128
|
+
|
|
116
129
|
@self.publish_route('/internal/dispatchers', DOCUMENTATION__dispatchers)
|
|
117
130
|
def dispatchers(connection: DBInterface, http_inputs: dict):
|
|
118
131
|
self.model.attach_dispatcher_credentials(connection, http_inputs)
|
|
119
132
|
|
|
120
|
-
@self.publish_route('/invite', DOCUMENTATION__invite)
|
|
121
|
-
def invite(http_inputs: dict, account_id: str, is_the_anonymous_user: bool):
|
|
122
|
-
return self.model.invite(http_inputs, account_id, is_the_anonymous_user)
|
|
123
|
-
|
|
124
|
-
@self.publish_route('/sign-up', DOCUMENTATION__sign_up)
|
|
125
|
-
def sign_up(http_inputs: dict, ip_address: str, response: JAAQLResponse):
|
|
126
|
-
return self.model.sign_up(http_inputs, ip_address, response)
|
|
127
|
-
|
|
128
|
-
@self.publish_route('/sign-up-resend', DOCUMENTATION__resend_sign_up)
|
|
129
|
-
def sign_up_resend(http_inputs: dict, account_id: str, username: str):
|
|
130
|
-
return self.model.resend_signup_email(http_inputs, account_id, username)
|
|
131
|
-
|
|
132
133
|
@self.publish_route('/email', DOCUMENTATION__emails)
|
|
133
134
|
def send_email(is_the_anonymous_user: bool, account_id: str, http_inputs: dict, username: str, auth_token: str):
|
|
134
135
|
return self.model.send_email(is_the_anonymous_user, account_id, http_inputs, username, auth_token)
|
|
135
136
|
|
|
136
|
-
@self.publish_route('/account/reset-password', DOCUMENTATION__reset_password)
|
|
137
|
-
def reset_password(http_inputs: dict):
|
|
138
|
-
return self.model.reset_password(http_inputs)
|
|
139
|
-
|
|
140
|
-
@self.publish_route('/security-event', DOCUMENTATION__security_event)
|
|
141
|
-
def security_event(http_inputs: dict):
|
|
142
|
-
if self.is_post():
|
|
143
|
-
return self.model.check_security_event_key_and_security_event_is_unlocked(http_inputs)
|
|
144
|
-
else:
|
|
145
|
-
return self.model.finish_security_event(http_inputs)
|
|
146
|
-
|
|
147
137
|
@self.publish_route('/cron', DOCUMENTATION__cron)
|
|
148
138
|
def cron(ip_address: str):
|
|
149
139
|
self.model.execute_cron_jobs(ip_address)
|
|
@@ -201,3 +191,16 @@ class JAAQLController(BaseJAAQLController):
|
|
|
201
191
|
@self.publish_route('/rendered_documents', DOCUMENTATION__rendered_document)
|
|
202
192
|
def documents(http_inputs: dict):
|
|
203
193
|
return self.model.fetch_document_stream(http_inputs)
|
|
194
|
+
|
|
195
|
+
@self.publish_route('/oidc/logout', DOCUMENTATION__oidc_begin_logout)
|
|
196
|
+
def begin_oidc_logout(http_inputs: dict, response: JAAQLResponse):
|
|
197
|
+
# inputs: application, tenant, provider, optional schema, redirect_uri, optional id_token_hint
|
|
198
|
+
self.model.begin_oidc_logout(http_inputs, response)
|
|
199
|
+
|
|
200
|
+
@self.publish_route('/oidc/post-logout', DOCUMENTATION__oidc_post_logout)
|
|
201
|
+
def finish_oidc_logout(http_inputs: dict, response: JAAQLResponse):
|
|
202
|
+
# KC returns ?state=... here; validate against cookie and bounce to final app URL
|
|
203
|
+
self.model.finish_oidc_logout(
|
|
204
|
+
{"state": http_inputs["state"], "oidc_cookie": request.cookies.get(COOKIE_OIDC)},
|
|
205
|
+
response
|
|
206
|
+
)
|
{jaaql_middleware_python-4.33.8 → jaaql_middleware_python-4.33.10}/jaaql/mvc/exception_queries.py
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
This script was generated from jaaql.exceptions.fxli at 2025-05
|
|
2
|
+
This script was generated from jaaql.exceptions.fxli at 2025-11-05, 14:24:08
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
from jaaql.utilities.crypt_utils import get_repeatable_salt
|
|
@@ -190,69 +190,19 @@ QUERY___add_or_update_validated_ip_address = "INSERT INTO validated_ip_address (
|
|
|
190
190
|
QUERY__fetch_application_schemas = "SELECT S.name, S.database, (A.default_schema = S.name) as is_default, A.is_live FROM application_schema S INNER JOIN application A ON A.name = S.application WHERE S.application = :application"
|
|
191
191
|
KEY__is_default = "is_default"
|
|
192
192
|
|
|
193
|
-
QUERY__count_security_events_of_type_in_24hr_window = """
|
|
194
|
-
SELECT
|
|
195
|
-
COUNT(*) as count
|
|
196
|
-
FROM security_event S
|
|
197
|
-
INNER JOIN email_template E ON E.name = S.email_template AND E.application = S.application
|
|
198
|
-
WHERE E.type IN (:type_one, :type_two) AND ((:account::postgres_role is not null AND account = :account) OR (:fake_account::encrypted__jaaql_username is not null AND fake_account = :fake_account)) AND (creation_timestamp + interval '24 hour') > current_timestamp
|
|
199
|
-
"""
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
def count_for_security_event(
|
|
203
|
-
connection: DBInterface, encryption_key: bytes, vault_repeatable_salt: str,
|
|
204
|
-
type_one: str, type_two: str,
|
|
205
|
-
account, fake_account=None
|
|
206
|
-
):
|
|
207
|
-
return execute_supplied_statement_singleton(
|
|
208
|
-
connection, QUERY__count_security_events_of_type_in_24hr_window, {
|
|
209
|
-
"type_one": type_one, "type_two": type_two,
|
|
210
|
-
KG__security_event__account: account,
|
|
211
|
-
KG__security_event__fake_account: fake_account
|
|
212
|
-
}, as_objects=True, encryption_key=encryption_key, encrypt_parameters=[KG__security_event__fake_account],
|
|
213
|
-
encryption_salts={KG__security_event__fake_account: get_repeatable_salt(vault_repeatable_salt, fake_account)}
|
|
214
|
-
)[KEY__count]
|
|
215
|
-
|
|
216
193
|
|
|
217
194
|
RPC_ACCESS__private = "P"
|
|
218
195
|
RPC_ACCESS__public = "U"
|
|
219
196
|
RPC_ACCESS__webhook = "W"
|
|
220
197
|
|
|
198
|
+
SECURITY_EVENT_TYPE__create = "C"
|
|
199
|
+
SECURITY_EVENT_TYPE__delete = "D"
|
|
200
|
+
SECURITY_EVENT_TYPE__reset = "R"
|
|
201
|
+
|
|
221
202
|
KEY__type_one = "type_one"
|
|
222
203
|
KEY__type_two = "type_two"
|
|
223
204
|
|
|
224
|
-
EMAIL_TYPE__signup = "S"
|
|
225
|
-
EMAIL_TYPE__already_signed_up = "A"
|
|
226
|
-
EMAIL_TYPE__reset_password = "R"
|
|
227
|
-
EMAIL_TYPE__unregistered_password_reset = "U"
|
|
228
|
-
EMAIL_TYPE__general = "G"
|
|
229
|
-
|
|
230
|
-
KEY__key_fits = "key_fits"
|
|
231
|
-
QUERY__check_security_event_unlock = """
|
|
232
|
-
UPDATE
|
|
233
|
-
security_event S
|
|
234
|
-
SET
|
|
235
|
-
wrong_key_attempt_count = S.wrong_key_attempt_count + (case when (S.unlock_code = :unlock_code OR S.unlock_key = :unlock_key OR S.wrong_key_attempt_count >= 3) then 0 else 1 end)
|
|
236
|
-
FROM application A
|
|
237
|
-
WHERE
|
|
238
|
-
S.application = A.name AND
|
|
239
|
-
(S.event_lock = :event_lock OR S.unlock_key = :unlock_key) AND S.finish_timestamp is null AND
|
|
240
|
-
S.creation_timestamp + (A.unlock_key_validity_period || ' seconds')::interval > current_timestamp
|
|
241
|
-
RETURNING S.*, A.unlock_code_validity_period, (S.unlock_code = :unlock_code OR S.unlock_key = :unlock_key) as key_fits
|
|
242
|
-
"""
|
|
243
|
-
|
|
244
205
|
|
|
245
|
-
def check_security_event_unlock(
|
|
246
|
-
connection: DBInterface, event_lock, unlock_code,
|
|
247
|
-
unlock_key, singleton_code: int = None, singleton_message: str = None
|
|
248
|
-
):
|
|
249
|
-
return execute_supplied_statement_singleton(
|
|
250
|
-
connection, QUERY__check_security_event_unlock, {
|
|
251
|
-
KG__security_event__event_lock: event_lock,
|
|
252
|
-
KG__security_event__unlock_code: unlock_code,
|
|
253
|
-
KG__security_event__unlock_key: unlock_key
|
|
254
|
-
}, as_objects=True, singleton_code=singleton_code, singleton_message=singleton_message
|
|
255
|
-
)
|
|
256
206
|
|
|
257
207
|
|
|
258
208
|
QUERY__fetch_document_templates_for_email_template = """
|