jaaql-middleware-python 4.21.23__tar.gz → 4.21.27__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.21.23/jaaql_middleware_python.egg-info → jaaql-middleware-python-4.21.27}/PKG-INFO +1 -1
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/constants.py +2 -2
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/documentation/documentation_public.py +25 -9
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/email/email_manager_service.py +1 -1
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/mvc/controller.py +8 -4
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/mvc/exception_queries.py +9 -6
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/mvc/generated_queries.py +13 -9
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/mvc/model.py +56 -33
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/openapi/swagger_documentation.py +1 -1
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/scripts/01.install_domains.generated.sql +5 -5
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/scripts/02.install_super_user.exceptions.sql +9 -2
- jaaql-middleware-python-4.21.27/jaaql/scripts/04.install_jaaql_data_structures.generated.sql +4083 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27/jaaql_middleware_python.egg-info}/PKG-INFO +1 -1
- jaaql-middleware-python-4.21.23/jaaql/scripts/04.install_jaaql_data_structures.generated.sql +0 -193
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/LICENSE.txt +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/README.md +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/__init__.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/config/__init__.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/config/config-docker.ini +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/config/config-test.ini +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/config/config.ini +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/config_constants.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/db/__init__.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/db/db_interface.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/db/db_pg_interface.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/db/db_utils.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/db/db_utils_no_circ.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/documentation/__init__.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/documentation/documentation_internal.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/documentation/documentation_shared.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/email/__init__.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/email/email_manager.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/email/patch_ems.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/exceptions/__init__.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/exceptions/custom_http_status.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/exceptions/http_status_exception.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/exceptions/not_yet_implement_exception.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/interpreter/__init__.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/interpreter/interpret_jaaql.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/jaaql.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/migrations/__init__.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/migrations/migration_history.sql +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/migrations/migrations.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/mvc/__init__.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/mvc/base_controller.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/mvc/base_model.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/mvc/controller_interface.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/mvc/handmade_queries.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/mvc/model_interface.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/mvc/response.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/openapi/__init__.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/patch.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/scripts/03.install_super_user.handwritten.sql +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/scripts/05.install_jaaql.exceptions.sql +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/scripts/06.install_jaaql.handwritten.sql +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/scripts/swagger_template.html +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/services/__init__.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/services/cached_canned_query_service.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/services/migrations_manager_service.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/services/patch_mms.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/services/patch_shared_var_service.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/services/shared_var_service.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/utilities/__init__.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/utilities/crypt_utils.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/utilities/options.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/utilities/utils.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/utilities/utils_no_project_imports.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/utilities/vault.py +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql_middleware_python.egg-info/SOURCES.txt +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql_middleware_python.egg-info/dependency_links.txt +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql_middleware_python.egg-info/requires.txt +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql_middleware_python.egg-info/top_level.txt +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/setup.cfg +0 -0
- {jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: jaaql-middleware-python
|
|
3
|
-
Version: 4.21.
|
|
3
|
+
Version: 4.21.27
|
|
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
|
|
@@ -3,7 +3,6 @@ import socket
|
|
|
3
3
|
|
|
4
4
|
KEY__username = "username"
|
|
5
5
|
KEY__password = "password"
|
|
6
|
-
KEY__dbms_user = "dbms_user"
|
|
7
6
|
KEY__remember_me = "remember_me"
|
|
8
7
|
KEY__attach_as = "attach_as"
|
|
9
8
|
KEY__ip_address = "ip_address"
|
|
@@ -38,6 +37,7 @@ KEY__query = "query"
|
|
|
38
37
|
KEY__security_key = "security_key"
|
|
39
38
|
KEY__id = "id"
|
|
40
39
|
KEY__oauth_token = "oauth_token"
|
|
40
|
+
KEY__accounts = "accounts"
|
|
41
41
|
|
|
42
42
|
REGEX__dmbs_object_name = r'^[0-9a-zA-Z_]{1,32}$'
|
|
43
43
|
|
|
@@ -164,5 +164,5 @@ ROLE__postgres = "postgres"
|
|
|
164
164
|
|
|
165
165
|
PROTOCOL__postgres = "postgresql://"
|
|
166
166
|
|
|
167
|
-
VERSION = "4.21.
|
|
167
|
+
VERSION = "4.21.27"
|
|
168
168
|
|
|
@@ -33,6 +33,31 @@ DOCUMENTATION__create_account = SwaggerDocumentation(
|
|
|
33
33
|
)
|
|
34
34
|
)
|
|
35
35
|
|
|
36
|
+
DOCUMENTATION__create_account_batch = SwaggerDocumentation(
|
|
37
|
+
tags="Admin",
|
|
38
|
+
methods=SwaggerMethod(
|
|
39
|
+
method=REST__POST,
|
|
40
|
+
name="Create account batch",
|
|
41
|
+
description="Will create a batch of accounts, if you have privileges to do so",
|
|
42
|
+
body=SwaggerArgumentResponse(
|
|
43
|
+
name=KEY__accounts,
|
|
44
|
+
description="A list of the accounts",
|
|
45
|
+
arg_type=SwaggerList(
|
|
46
|
+
ARG_RES__username,
|
|
47
|
+
set_nullable(ARG_RES__password, "Whether the user is given a password"),
|
|
48
|
+
SwaggerArgumentResponse(
|
|
49
|
+
name=KEY__attach_as,
|
|
50
|
+
description="Whether the user will attach as a role",
|
|
51
|
+
arg_type=str,
|
|
52
|
+
required=False,
|
|
53
|
+
condition="Defaults to false",
|
|
54
|
+
example="my-role"
|
|
55
|
+
)
|
|
56
|
+
)
|
|
57
|
+
)
|
|
58
|
+
)
|
|
59
|
+
)
|
|
60
|
+
|
|
36
61
|
DOCUMENTATION__password = SwaggerDocumentation(
|
|
37
62
|
tags="Account",
|
|
38
63
|
methods=SwaggerMethod(
|
|
@@ -166,15 +191,6 @@ DOCUMENTATION__emails = SwaggerDocumentation(
|
|
|
166
191
|
)
|
|
167
192
|
)
|
|
168
193
|
|
|
169
|
-
ARG_RES__dbms_user = SwaggerArgumentResponse(
|
|
170
|
-
name=KEY__dbms_user,
|
|
171
|
-
description="The id of the dmbs user",
|
|
172
|
-
arg_type=str,
|
|
173
|
-
lower=True,
|
|
174
|
-
strip=True,
|
|
175
|
-
example=[str(uuid.uuid4()), str(uuid.uuid4())]
|
|
176
|
-
)
|
|
177
|
-
|
|
178
194
|
DOCUMENTATION__sign_up = SwaggerDocumentation(
|
|
179
195
|
tags="Signup",
|
|
180
196
|
# 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
|
|
@@ -388,7 +388,7 @@ class EmailManagerService:
|
|
|
388
388
|
if conn is None:
|
|
389
389
|
raise Exception("Could not connect to email dispatcher '%s' with address '%s:%d'" % dispatcher_key, host, port)
|
|
390
390
|
|
|
391
|
-
context = ssl.
|
|
391
|
+
context = ssl.create_default_context()
|
|
392
392
|
|
|
393
393
|
conn.starttls(context=context)
|
|
394
394
|
conn.login(username, password)
|
|
@@ -67,6 +67,10 @@ class JAAQLController(BaseJAAQLController):
|
|
|
67
67
|
def accounts(connection: DBInterface, http_inputs: dict):
|
|
68
68
|
self.model.create_account_with_potential_password(connection, **http_inputs)
|
|
69
69
|
|
|
70
|
+
@self.publish_route('/accounts/batch', DOCUMENTATION__create_account_batch)
|
|
71
|
+
def accounts(connection: DBInterface, http_inputs: dict):
|
|
72
|
+
self.model.create_account_batch_with_potential_password(connection, **http_inputs)
|
|
73
|
+
|
|
70
74
|
@self.publish_route('/prepare', DOCUMENTATION__prepare)
|
|
71
75
|
def prepare(http_inputs: dict, account_id: str):
|
|
72
76
|
return self.model.prepare_queries(http_inputs, account_id)
|
|
@@ -88,16 +92,16 @@ class JAAQLController(BaseJAAQLController):
|
|
|
88
92
|
self.model.attach_dispatcher_credentials(connection, http_inputs)
|
|
89
93
|
|
|
90
94
|
@self.publish_route('/sign-up', DOCUMENTATION__sign_up)
|
|
91
|
-
def sign_up(http_inputs: dict, account_id: str):
|
|
92
|
-
return self.model.sign_up(http_inputs, account_id)
|
|
95
|
+
def sign_up(http_inputs: dict, account_id: str, is_the_anonymous_user: bool):
|
|
96
|
+
return self.model.sign_up(http_inputs, account_id, is_the_anonymous_user)
|
|
93
97
|
|
|
94
98
|
@self.publish_route('/email', DOCUMENTATION__emails)
|
|
95
99
|
def send_email(is_the_anonymous_user: bool, account_id: str, http_inputs: dict, username: str, auth_token: str):
|
|
96
100
|
return self.model.send_email(is_the_anonymous_user, account_id, http_inputs, username, auth_token)
|
|
97
101
|
|
|
98
102
|
@self.publish_route('/account/reset-password', DOCUMENTATION__reset_password)
|
|
99
|
-
def reset_password(http_inputs: dict):
|
|
100
|
-
return self.model.reset_password(http_inputs)
|
|
103
|
+
def reset_password(http_inputs: dict, is_the_anonymous_user: bool):
|
|
104
|
+
return self.model.reset_password(http_inputs, is_the_anonymous_user)
|
|
101
105
|
|
|
102
106
|
@self.publish_route('/security-event', DOCUMENTATION__security_event)
|
|
103
107
|
def security_event(http_inputs: dict):
|
{jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/mvc/exception_queries.py
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
This script was generated from jaaql.exceptions.fxls at
|
|
2
|
+
This script was generated from jaaql.exceptions.fxls at 2024-02-11, 00:36:29
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
from jaaql.utilities.crypt_utils import get_repeatable_salt
|
|
@@ -11,8 +11,8 @@ def add_account_password(
|
|
|
11
11
|
account__id, account_password__hash
|
|
12
12
|
):
|
|
13
13
|
account_password__uuid = account_password__insert(
|
|
14
|
-
connection, encryption_key, account__id,
|
|
15
|
-
account_password__hash,
|
|
14
|
+
connection, encryption_key, account__id,
|
|
15
|
+
account_password__hash,
|
|
16
16
|
encryption_salts={KG__account_password__hash: get_repeatable_salt(vault_repeatable_salt, account__id)}
|
|
17
17
|
)[KG__account_password__uuid]
|
|
18
18
|
|
|
@@ -83,9 +83,10 @@ def fetch_account_from_username(
|
|
|
83
83
|
)
|
|
84
84
|
|
|
85
85
|
|
|
86
|
-
QUERY__create_account = "SELECT create_account(:username, :attach_as, :already_exists, :is_the_anonymous_user) as account_id"
|
|
86
|
+
QUERY__create_account = "SELECT create_account(:username, :attach_as, :already_exists, :is_the_anonymous_user, :allow_already_exists) as account_id"
|
|
87
87
|
KEY__attach_as = "attach_as"
|
|
88
88
|
KEY__already_exists = "already_exists"
|
|
89
|
+
KEY__allow_already_exists = "allow_already_exists"
|
|
89
90
|
KEY__username = "username"
|
|
90
91
|
KEY__is_the_anonymous_user = "is_the_anonymous_user"
|
|
91
92
|
KEY__account_id = "account_id"
|
|
@@ -93,14 +94,16 @@ KEY__account_id = "account_id"
|
|
|
93
94
|
|
|
94
95
|
def create_account(
|
|
95
96
|
connection: DBInterface, encryption_key: bytes, vault_repeatable_salt: str,
|
|
96
|
-
username, attach_as=None, already_exists=False, is_the_anonymous_user=False
|
|
97
|
+
username, attach_as=None, already_exists=False, is_the_anonymous_user=False,
|
|
98
|
+
allow_already_exists=False
|
|
97
99
|
):
|
|
98
100
|
return execute_supplied_statement_singleton(
|
|
99
101
|
connection, QUERY__create_account, {
|
|
100
102
|
KEY__username: username,
|
|
101
103
|
KEY__attach_as: attach_as,
|
|
102
104
|
KEY__already_exists: already_exists,
|
|
103
|
-
KEY__is_the_anonymous_user: is_the_anonymous_user
|
|
105
|
+
KEY__is_the_anonymous_user: is_the_anonymous_user,
|
|
106
|
+
KEY__allow_already_exists: allow_already_exists
|
|
104
107
|
}, encryption_salts={
|
|
105
108
|
KG__account__username: get_repeatable_salt(vault_repeatable_salt)
|
|
106
109
|
}, as_objects=True, encryption_key=encryption_key, encrypt_parameters=[KG__account__username]
|
{jaaql-middleware-python-4.21.23 → jaaql-middleware-python-4.21.27}/jaaql/mvc/generated_queries.py
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"""
|
|
2
|
-
This script was generated from jaaql.fxli at
|
|
2
|
+
This script was generated from jaaql.fxli at 2024-02-11, 00:36:29
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
from jaaql.db.db_interface import DBInterface
|
|
@@ -453,6 +453,7 @@ KG__email_template__name = "name"
|
|
|
453
453
|
KG__email_template__type = "type"
|
|
454
454
|
KG__email_template__content_url = "content_url"
|
|
455
455
|
KG__email_template__validation_schema = "validation_schema"
|
|
456
|
+
KG__email_template__dbms_user_column_name = "dbms_user_column_name"
|
|
456
457
|
KG__email_template__data_validation_table = "data_validation_table"
|
|
457
458
|
KG__email_template__data_validation_view = "data_validation_view"
|
|
458
459
|
KG__email_template__dispatcher_domain_recipient = "dispatcher_domain_recipient"
|
|
@@ -463,12 +464,12 @@ QG__email_template_delete = "DELETE FROM email_template WHERE application = :app
|
|
|
463
464
|
QG__email_template_insert = """
|
|
464
465
|
INSERT INTO email_template (application, dispatcher, name,
|
|
465
466
|
type, content_url, validation_schema,
|
|
466
|
-
data_validation_table, data_validation_view,
|
|
467
|
-
can_be_sent_anonymously)
|
|
467
|
+
dbms_user_column_name, data_validation_table, data_validation_view,
|
|
468
|
+
dispatcher_domain_recipient, can_be_sent_anonymously)
|
|
468
469
|
VALUES (:application, :dispatcher, :name,
|
|
469
470
|
:type, :content_url, :validation_schema,
|
|
470
|
-
:
|
|
471
|
-
:can_be_sent_anonymously)
|
|
471
|
+
:dbms_user_column_name, :data_validation_table, :data_validation_view,
|
|
472
|
+
:dispatcher_domain_recipient, :can_be_sent_anonymously)
|
|
472
473
|
"""
|
|
473
474
|
QG__email_template_select_all = "SELECT * FROM email_template"
|
|
474
475
|
QG__email_template_select = "SELECT * FROM email_template WHERE application = :application AND name = :name"
|
|
@@ -480,6 +481,7 @@ QG__email_template_update = """
|
|
|
480
481
|
type = COALESCE(:type, type),
|
|
481
482
|
content_url = COALESCE(:content_url, content_url),
|
|
482
483
|
validation_schema = COALESCE(:validation_schema, validation_schema),
|
|
484
|
+
dbms_user_column_name = COALESCE(:dbms_user_column_name, dbms_user_column_name),
|
|
483
485
|
data_validation_table = COALESCE(:data_validation_table, data_validation_table),
|
|
484
486
|
data_validation_view = COALESCE(:data_validation_view, data_validation_view),
|
|
485
487
|
dispatcher_domain_recipient = COALESCE(:dispatcher_domain_recipient, dispatcher_domain_recipient),
|
|
@@ -508,8 +510,8 @@ def email_template__update(
|
|
|
508
510
|
connection: DBInterface,
|
|
509
511
|
application, name,
|
|
510
512
|
dispatcher=None, type=None, content_url=None,
|
|
511
|
-
validation_schema=None,
|
|
512
|
-
dispatcher_domain_recipient=None, can_be_sent_anonymously=None
|
|
513
|
+
validation_schema=None, dbms_user_column_name=None, data_validation_table=None,
|
|
514
|
+
data_validation_view=None, dispatcher_domain_recipient=None, can_be_sent_anonymously=None
|
|
513
515
|
):
|
|
514
516
|
execute_supplied_statement(
|
|
515
517
|
connection, QG__email_template_update,
|
|
@@ -523,6 +525,7 @@ def email_template__update(
|
|
|
523
525
|
KG__email_template__type: type,
|
|
524
526
|
KG__email_template__content_url: content_url,
|
|
525
527
|
KG__email_template__validation_schema: validation_schema,
|
|
528
|
+
KG__email_template__dbms_user_column_name: dbms_user_column_name,
|
|
526
529
|
KG__email_template__data_validation_table: data_validation_table,
|
|
527
530
|
KG__email_template__data_validation_view: data_validation_view,
|
|
528
531
|
KG__email_template__dispatcher_domain_recipient: dispatcher_domain_recipient,
|
|
@@ -560,8 +563,8 @@ def email_template__insert(
|
|
|
560
563
|
connection: DBInterface,
|
|
561
564
|
application, dispatcher, name,
|
|
562
565
|
type, content_url,
|
|
563
|
-
validation_schema=None,
|
|
564
|
-
dispatcher_domain_recipient=None, can_be_sent_anonymously=None
|
|
566
|
+
validation_schema=None, dbms_user_column_name=None, data_validation_table=None,
|
|
567
|
+
data_validation_view=None, dispatcher_domain_recipient=None, can_be_sent_anonymously=None
|
|
565
568
|
):
|
|
566
569
|
execute_supplied_statement(
|
|
567
570
|
connection, QG__email_template_insert,
|
|
@@ -572,6 +575,7 @@ def email_template__insert(
|
|
|
572
575
|
KG__email_template__type: type,
|
|
573
576
|
KG__email_template__content_url: content_url,
|
|
574
577
|
KG__email_template__validation_schema: validation_schema,
|
|
578
|
+
KG__email_template__dbms_user_column_name: dbms_user_column_name,
|
|
575
579
|
KG__email_template__data_validation_table: data_validation_table,
|
|
576
580
|
KG__email_template__data_validation_view: data_validation_view,
|
|
577
581
|
KG__email_template__dispatcher_domain_recipient: dispatcher_domain_recipient,
|
|
@@ -93,8 +93,6 @@ SIGNUP__started = 1
|
|
|
93
93
|
SIGNUP__already_registered = 2
|
|
94
94
|
SIGNUP__completed = 3
|
|
95
95
|
|
|
96
|
-
SPECIAL_COLUMN_DBMS_USER = "dbms_user"
|
|
97
|
-
|
|
98
96
|
|
|
99
97
|
class JAAQLModel(BaseJAAQLModel):
|
|
100
98
|
VERIFICATION_QUEUE = None
|
|
@@ -106,16 +104,24 @@ class JAAQLModel(BaseJAAQLModel):
|
|
|
106
104
|
raise HttpStatusException("Not yet implemented", response_code=HTTPStatus.NOT_IMPLEMENTED)
|
|
107
105
|
|
|
108
106
|
def create_account_with_potential_password(self, connection: DBInterface, username: str, attach_as: str = None, password: str = None,
|
|
109
|
-
already_exists: bool = False, is_the_anonymous_user: bool = False):
|
|
107
|
+
already_exists: bool = False, is_the_anonymous_user: bool = False, allow_already_exists: bool = False):
|
|
110
108
|
account_id = create_account(connection, self.get_db_crypt_key(), self.get_vault_repeatable_salt(),
|
|
111
109
|
username, attach_as, already_exists,
|
|
112
|
-
is_the_anonymous_user)
|
|
110
|
+
is_the_anonymous_user, allow_already_exists)
|
|
113
111
|
|
|
114
|
-
if password:
|
|
112
|
+
if password and account_id != "account_already_existed":
|
|
115
113
|
self.add_account_password(account_id, password)
|
|
116
114
|
|
|
115
|
+
if account_id == "account_already_existed":
|
|
116
|
+
account_id = attach_as
|
|
117
|
+
|
|
117
118
|
return account_id
|
|
118
119
|
|
|
120
|
+
def create_account_batch_with_potential_password(self, connection: DBInterface, accounts: list):
|
|
121
|
+
for cur_input in accounts:
|
|
122
|
+
self.create_account_with_potential_password(connection, cur_input[KEY__username], cur_input[KEY__attach_as], cur_input[KEY__password],
|
|
123
|
+
allow_already_exists=True)
|
|
124
|
+
|
|
119
125
|
def validate_query(self, queries: list, query, allow_list=True):
|
|
120
126
|
if isinstance(query, list) and allow_list:
|
|
121
127
|
for sub_query in query:
|
|
@@ -328,15 +334,15 @@ WHERE
|
|
|
328
334
|
if self.is_container:
|
|
329
335
|
if not self.vault.get_obj(VAULT_KEY__allow_jaaql_uninstall):
|
|
330
336
|
raise HttpStatusException("JAAQL not permitted to uninstall itself")
|
|
331
|
-
|
|
337
|
+
DBPGInterface.close_all_pools()
|
|
332
338
|
subprocess.call("./pg_reboot.sh", cwd="/")
|
|
333
339
|
else:
|
|
334
340
|
subprocess.call("docker kill jaaql_pg")
|
|
335
341
|
subprocess.call("docker rm jaaql_pg")
|
|
336
342
|
subprocess.Popen("docker run --name jaaql_pg -p 5434:5432 jaaql/jaaql_pg", start_new_session=True, creationflags=0x00000008)
|
|
337
343
|
time.sleep(7.5)
|
|
344
|
+
DBPGInterface.close_all_pools()
|
|
338
345
|
|
|
339
|
-
DBPGInterface.close_all_pools()
|
|
340
346
|
self.jaaql_lookup_connection = None
|
|
341
347
|
self.install_key = str(uuid.uuid4())
|
|
342
348
|
self.install(
|
|
@@ -637,20 +643,23 @@ WHERE
|
|
|
637
643
|
|
|
638
644
|
self.mark_security_event_unlocked(sec_evt)
|
|
639
645
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
646
|
+
# TODO maybe someday we'll add this back in
|
|
647
|
+
# if template[KG__email_template__type] == EMAIL_TYPE__signup:
|
|
648
|
+
# data_relation = template[KG__email_template__data_validation_view]
|
|
649
|
+
# dbms_user_column_name = template[KG__email_template__dbms_user_column_name]
|
|
650
|
+
# submit_data = {
|
|
651
|
+
# KEY__schema: template[KG__email_template__validation_schema],
|
|
652
|
+
# KEY__application: template[KEY__application],
|
|
653
|
+
# KEY_parameters: {
|
|
654
|
+
# "signed_up_at": datetime.now(),
|
|
655
|
+
# dbms_user_column_name: sec_evt[KG__security_event__account]
|
|
656
|
+
# },
|
|
657
|
+
# KEY_query: f'UPDATE {data_relation} SET signed_up_at = :signed_up_at WHERE {dbms_user_column_name} = :{dbms_user_column_name} AND signed_up_at is null'
|
|
658
|
+
# # Ignore pycharm PEP issue
|
|
659
|
+
# }
|
|
660
|
+
# # We now get the data that can be shown in the email
|
|
661
|
+
# submit(self.vault, self.config, self.get_db_crypt_key(), self.jaaql_lookup_connection, submit_data,
|
|
662
|
+
# self.jaaql_lookup_connection.role, None, self.cached_canned_query_service)
|
|
654
663
|
|
|
655
664
|
return {
|
|
656
665
|
KEY__parameters: parameters,
|
|
@@ -715,7 +724,10 @@ WHERE
|
|
|
715
724
|
attachments=attachments, attachment_access_token=auth_token,
|
|
716
725
|
attachment_base_url=attachment_base_url)
|
|
717
726
|
|
|
718
|
-
def reset_password(self, inputs: dict):
|
|
727
|
+
def reset_password(self, inputs: dict, is_the_anonymous_user: bool):
|
|
728
|
+
if is_the_anonymous_user:
|
|
729
|
+
raise HttpStatusException("Cannot change this user's password")
|
|
730
|
+
|
|
719
731
|
app = application__select(self.jaaql_lookup_connection, inputs[KG__security_event__application])
|
|
720
732
|
if inputs[KEY__reset_password_template] is None:
|
|
721
733
|
inputs[KEY__reset_password_template] = app[KG__application__default_r_et]
|
|
@@ -785,8 +797,9 @@ WHERE
|
|
|
785
797
|
KG__security_event__event_lock: reg_env_ins[KG__security_event__event_lock]
|
|
786
798
|
}
|
|
787
799
|
|
|
788
|
-
def sign_up(self, inputs: dict, account_id: str):
|
|
800
|
+
def sign_up(self, inputs: dict, account_id: str, is_the_anonymous_user: bool):
|
|
789
801
|
app = application__select(self.jaaql_lookup_connection, inputs[KG__security_event__application])
|
|
802
|
+
|
|
790
803
|
if inputs[KEY__sign_up_template] is None:
|
|
791
804
|
inputs[KEY__sign_up_template] = app[KG__application__default_s_et]
|
|
792
805
|
if inputs[KEY__already_signed_up_template] is None:
|
|
@@ -803,11 +816,17 @@ WHERE
|
|
|
803
816
|
if sign_up_template[KG__email_template__type] != EMAIL_TYPE__signup:
|
|
804
817
|
raise HttpStatusException(ERR__template_not_signup)
|
|
805
818
|
|
|
819
|
+
dbms_user_column_name = sign_up_template[KG__email_template__dbms_user_column_name]
|
|
820
|
+
|
|
806
821
|
already_signed_up_template = email_template__select(self.jaaql_lookup_connection, inputs[KG__security_event__application],
|
|
807
822
|
inputs[KEY__already_signed_up_template])
|
|
808
823
|
if already_signed_up_template[KG__email_template__type] != EMAIL_TYPE__already_signed_up:
|
|
809
824
|
raise HttpStatusException(ERR__template_not_already)
|
|
810
825
|
|
|
826
|
+
if is_the_anonymous_user and (not already_signed_up_template[KG__email_template__can_be_sent_anonymously] or
|
|
827
|
+
not sign_up_template[KG__email_template__can_be_sent_anonymously]):
|
|
828
|
+
raise HttpStatusException("Cannot sign up publicly using this route")
|
|
829
|
+
|
|
811
830
|
conn = None
|
|
812
831
|
account_db_interface = None
|
|
813
832
|
|
|
@@ -825,17 +844,16 @@ WHERE
|
|
|
825
844
|
ret = submit(self.vault, self.config, self.get_db_crypt_key(), self.jaaql_lookup_connection, submit_data, account_id, None,
|
|
826
845
|
self.cached_canned_query_service, as_objects=False, singleton=True, keep_alive_conn=True, conn=conn, interface=account_db_interface)
|
|
827
846
|
ret = objectify(ret[list(ret.keys())[-1]], singleton=True)
|
|
828
|
-
|
|
829
847
|
# This is the permissions check. It is an update that returns something that is ignored
|
|
830
848
|
# An exception will be triggered here if the user does not have permissions
|
|
831
849
|
where_clause = " AND ".join(['"' + key + '" = :' + key for key in ret.keys() if re.match(REGEX__dmbs_object_name, key) is not None])
|
|
832
850
|
if len(where_clause) != 0:
|
|
833
851
|
where_clause = " AND " + where_clause
|
|
834
852
|
sign_up_table = sign_up_template[KG__email_template__data_validation_table]
|
|
835
|
-
upt_query = f'UPDATE "{sign_up_table}" SET
|
|
853
|
+
upt_query = f'UPDATE "{sign_up_table}" SET "{dbms_user_column_name}" = :{dbms_user_column_name} WHERE {dbms_user_column_name} is null{where_clause}' # Ignore pycharm pep issue
|
|
836
854
|
submit_data[KEY_query] = upt_query
|
|
837
855
|
submit_data[KEY_parameters] = ret
|
|
838
|
-
submit_data[KEY_parameters][
|
|
856
|
+
submit_data[KEY_parameters][dbms_user_column_name] = None
|
|
839
857
|
submit(self.vault, self.config, self.get_db_crypt_key(), self.jaaql_lookup_connection, submit_data, account_id,
|
|
840
858
|
None, self.cached_canned_query_service, keep_alive_conn=True, conn=conn, interface=account_db_interface)
|
|
841
859
|
|
|
@@ -848,7 +866,7 @@ WHERE
|
|
|
848
866
|
KEY__application: inputs[KG__security_event__application],
|
|
849
867
|
KEY__schema: sign_up_template[KG__email_template__validation_schema],
|
|
850
868
|
KEY_parameters: inputs[KEY__parameters],
|
|
851
|
-
KEY_query: f'SELECT
|
|
869
|
+
KEY_query: f'SELECT {dbms_user_column_name} FROM {data_relation} WHERE {where_clause[5:]}' # Ignore pycharm PEP issue
|
|
852
870
|
}
|
|
853
871
|
|
|
854
872
|
try:
|
|
@@ -856,7 +874,7 @@ WHERE
|
|
|
856
874
|
self.jaaql_lookup_connection, get_user_data,
|
|
857
875
|
self.jaaql_lookup_connection.role, None,
|
|
858
876
|
self.cached_canned_query_service, as_objects=True,
|
|
859
|
-
singleton=True)[
|
|
877
|
+
singleton=True)[dbms_user_column_name]
|
|
860
878
|
|
|
861
879
|
account = account__select(self.jaaql_lookup_connection, self.get_db_crypt_key(), dbms_user)
|
|
862
880
|
inputs[KEY__username] = account[KG__account__username]
|
|
@@ -879,7 +897,7 @@ WHERE
|
|
|
879
897
|
|
|
880
898
|
# We set the dbms user in the application. This can potentially cause an index clash due to a unique index on the dbms_user column
|
|
881
899
|
# This is desirable in many situations but will allow username enumeration
|
|
882
|
-
submit_data[KEY__parameters][
|
|
900
|
+
submit_data[KEY__parameters][dbms_user_column_name] = new_account_id
|
|
883
901
|
submit(self.vault, self.config, self.get_db_crypt_key(), self.jaaql_lookup_connection, submit_data, account_id,
|
|
884
902
|
None, self.cached_canned_query_service, keep_alive_conn=True, conn=conn, interface=account_db_interface)
|
|
885
903
|
|
|
@@ -903,11 +921,16 @@ WHERE
|
|
|
903
921
|
# We will change the model in the future when time allows that we have a single sign up and reset template with alternatives attached
|
|
904
922
|
if re.match(REGEX__dmbs_object_name, data_relation) is None:
|
|
905
923
|
raise HttpStatusException("Unsafe data relation specified for sign up")
|
|
906
|
-
submit_data[KEY_query] = f'SELECT * FROM {data_relation} WHERE
|
|
924
|
+
submit_data[KEY_query] = f'SELECT * FROM {data_relation} WHERE "{dbms_user_column_name}" = :{dbms_user_column_name}{where_clause}' # Ignore pycharm PEP issue
|
|
907
925
|
# We now get the data that can be shown in the email
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
926
|
+
try:
|
|
927
|
+
email_replacement_data = submit(self.vault, self.config, self.get_db_crypt_key(), self.jaaql_lookup_connection, submit_data,
|
|
928
|
+
self.jaaql_lookup_connection.role, None, self.cached_canned_query_service, as_objects=True,
|
|
929
|
+
singleton=True)
|
|
930
|
+
except HttpSingletonStatusException:
|
|
931
|
+
del submit_data[KEY__parameters][dbms_user_column_name]
|
|
932
|
+
raise HttpSingletonStatusException(f'Unable to locate email data. Please check that the data returned from your input query (do _not_ include {
|
|
933
|
+
dbms_user_column_name}) matches an entry in {data_relation}: ' + json.dumps(submit_data, indent=4))
|
|
911
934
|
|
|
912
935
|
template = already_signed_up_template if account_existed else sign_up_template
|
|
913
936
|
unlock_code = self.gen_security_event_unlock_code(CODE__letters, CODE__invite_length)
|
|
@@ -144,7 +144,7 @@ TYPE__exceptions = Optional[Union[List[SwaggerResponseException], SwaggerRespons
|
|
|
144
144
|
class SwaggerSimpleList:
|
|
145
145
|
|
|
146
146
|
def __init__(self, arg_type: type, description: str, example: Optional[TYPE__example] = None,
|
|
147
|
-
required: bool =
|
|
147
|
+
required: bool = True, condition: str = None):
|
|
148
148
|
self.arg_type = arg_type
|
|
149
149
|
self.description = description
|
|
150
150
|
self.example = example
|
|
@@ -11,16 +11,16 @@ CREATE DOMAIN internet_name AS character varying(63) CHECK (VALUE ~* '^[a-z0-9\-
|
|
|
11
11
|
CREATE DOMAIN url AS character varying(256);
|
|
12
12
|
CREATE DOMAIN location AS character varying(256);
|
|
13
13
|
CREATE DOMAIN object_name AS character varying(63) CHECK (VALUE ~* '^[a-z0-9_]*$');
|
|
14
|
-
CREATE DOMAIN validity_period AS integer;
|
|
15
|
-
CREATE DOMAIN short_validity_period AS integer;
|
|
14
|
+
CREATE DOMAIN validity_period AS integer CHECK (VALUE between 15 and 9999999);
|
|
15
|
+
CREATE DOMAIN short_validity_period AS integer CHECK (VALUE between 15 and 86400);
|
|
16
16
|
CREATE DOMAIN person_name AS character varying(64);
|
|
17
17
|
CREATE DOMAIN email_dispatch_protocol AS character varying(8);
|
|
18
|
-
CREATE DOMAIN internet_port AS integer;
|
|
18
|
+
CREATE DOMAIN internet_port AS integer CHECK (VALUE between 1 and 65536);
|
|
19
19
|
CREATE DOMAIN email_server_username AS character varying(255);
|
|
20
20
|
CREATE DOMAIN postgres_role AS character varying(63);
|
|
21
|
-
CREATE DOMAIN attempt_count AS smallint;
|
|
21
|
+
CREATE DOMAIN attempt_count AS smallint CHECK (VALUE between 1 and 3);
|
|
22
22
|
CREATE DOMAIN email_template_type AS character varying(1);
|
|
23
23
|
CREATE DOMAIN safe_path AS character varying(255) CHECK (VALUE ~* '^[a-z$0-9_\-\/]+(\.[a-zA-Z0-9]+)?$');
|
|
24
24
|
CREATE DOMAIN email_account_username AS character varying(64) CHECK (VALUE ~* '^[a-zA-Z0-9_\-\.]+$');
|
|
25
|
-
CREATE DOMAIN current_attempt_count AS smallint;
|
|
25
|
+
CREATE DOMAIN current_attempt_count AS smallint CHECK (VALUE between 0 and 3);
|
|
26
26
|
CREATE DOMAIN unlock_code AS character varying(10);
|
|
@@ -1,11 +1,18 @@
|
|
|
1
|
-
create function create_account(username text, attach_as postgres_role = null, already_exists boolean = false, is_the_anonymous_user boolean = false) returns postgres_role as
|
|
1
|
+
create function create_account(username text, attach_as postgres_role = null, already_exists boolean = false, is_the_anonymous_user boolean = false, allow_already_exists boolean = false) returns postgres_role as
|
|
2
2
|
$$
|
|
3
3
|
DECLARE
|
|
4
4
|
account_id postgres_role;
|
|
5
5
|
BEGIN
|
|
6
6
|
if attach_as is not null then
|
|
7
7
|
if not already_exists then
|
|
8
|
-
|
|
8
|
+
BEGIN
|
|
9
|
+
EXECUTE 'CREATE ROLE ' || quote_ident(attach_as);
|
|
10
|
+
EXCEPTION WHEN duplicate_object THEN
|
|
11
|
+
IF NOT allow_already_exists THEN
|
|
12
|
+
RAISE;
|
|
13
|
+
END IF;
|
|
14
|
+
return 'account_already_existed';
|
|
15
|
+
END;
|
|
9
16
|
end if;
|
|
10
17
|
INSERT INTO account (id, username) VALUES (attach_as, create_account.username) RETURNING id INTO account_id;
|
|
11
18
|
else
|