dmart 0.1.10__py3-none-any.whl → 1.4.1__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.
- api/managed/utils.py +32 -30
- bundler.py +12 -4
- data_adapters/sql/adapter.py +3 -3
- {dmart-0.1.10.dist-info → dmart-1.4.1.dist-info}/METADATA +2 -3
- {dmart-0.1.10.dist-info → dmart-1.4.1.dist-info}/RECORD +14 -14
- dmart.py +70 -8
- languages/loader.py +0 -1
- main.py +48 -2
- plugins/system_notification_sender/plugin.py +1 -1
- utils/generate_email.py +0 -1
- utils/settings.py +2 -2
- {dmart-0.1.10.dist-info → dmart-1.4.1.dist-info}/WHEEL +0 -0
- {dmart-0.1.10.dist-info → dmart-1.4.1.dist-info}/entry_points.txt +0 -0
- {dmart-0.1.10.dist-info → dmart-1.4.1.dist-info}/top_level.txt +0 -0
api/managed/utils.py
CHANGED
|
@@ -469,22 +469,23 @@ async def serve_request_update(request, owner_shortname: str):
|
|
|
469
469
|
schema_shortname=record_schema_shortname,
|
|
470
470
|
)
|
|
471
471
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
if latest_history and latest_history.last_checksum_history != requested_checksum:
|
|
480
|
-
raise api.Exception(
|
|
481
|
-
status.HTTP_409_CONFLICT,
|
|
482
|
-
api.Error(
|
|
483
|
-
type="request",
|
|
484
|
-
code=InternalErrorCode.CONFLICT,
|
|
485
|
-
message="Resource has been updated by another request!",
|
|
486
|
-
),
|
|
472
|
+
if settings.is_sha_required:
|
|
473
|
+
requested_checksum = record.attributes.get("last_checksum_history")
|
|
474
|
+
if requested_checksum:
|
|
475
|
+
latest_history = await db.get_latest_history(
|
|
476
|
+
space_name=request.space_name,
|
|
477
|
+
subpath=record.subpath,
|
|
478
|
+
shortname=record.shortname,
|
|
487
479
|
)
|
|
480
|
+
if latest_history and latest_history.last_checksum_history != requested_checksum:
|
|
481
|
+
raise api.Exception(
|
|
482
|
+
status.HTTP_409_CONFLICT,
|
|
483
|
+
api.Error(
|
|
484
|
+
type="request",
|
|
485
|
+
code=InternalErrorCode.CONFLICT,
|
|
486
|
+
message="Resource has been updated by another request!",
|
|
487
|
+
),
|
|
488
|
+
)
|
|
488
489
|
|
|
489
490
|
# CHECK PERMISSION
|
|
490
491
|
if not await access_control.check_access(
|
|
@@ -1534,22 +1535,23 @@ async def serve_space_update(request, record, owner_shortname: str, is_replace:
|
|
|
1534
1535
|
user_shortname=owner_shortname,
|
|
1535
1536
|
)
|
|
1536
1537
|
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
if latest_history and latest_history.last_checksum_history != requested_checksum:
|
|
1545
|
-
raise api.Exception(
|
|
1546
|
-
status.HTTP_409_CONFLICT,
|
|
1547
|
-
api.Error(
|
|
1548
|
-
type="request",
|
|
1549
|
-
code=InternalErrorCode.CONFLICT,
|
|
1550
|
-
message="Resource has been updated by another request. Please refresh and try again.",
|
|
1551
|
-
),
|
|
1538
|
+
if settings.is_sha_required:
|
|
1539
|
+
requested_checksum = record.attributes.get("last_checksum_history")
|
|
1540
|
+
if requested_checksum:
|
|
1541
|
+
latest_history = await db.get_latest_history(
|
|
1542
|
+
space_name=space.shortname,
|
|
1543
|
+
subpath=record.subpath,
|
|
1544
|
+
shortname=space.shortname,
|
|
1552
1545
|
)
|
|
1546
|
+
if latest_history and latest_history.last_checksum_history != requested_checksum:
|
|
1547
|
+
raise api.Exception(
|
|
1548
|
+
status.HTTP_409_CONFLICT,
|
|
1549
|
+
api.Error(
|
|
1550
|
+
type="request",
|
|
1551
|
+
code=InternalErrorCode.CONFLICT,
|
|
1552
|
+
message="Resource has been updated by another request. Please refresh and try again.",
|
|
1553
|
+
),
|
|
1554
|
+
)
|
|
1553
1555
|
|
|
1554
1556
|
old_flat = flatten_dict(old_space.model_dump())
|
|
1555
1557
|
new_flat = flatten_dict(space.model_dump())
|
bundler.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import json
|
|
3
3
|
import subprocess
|
|
4
4
|
import PyInstaller.__main__
|
|
5
|
-
|
|
5
|
+
import os
|
|
6
6
|
|
|
7
7
|
branch_cmd = "git rev-parse --abbrev-ref HEAD"
|
|
8
8
|
result, _ = subprocess.Popen(branch_cmd.split(" "), stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
|
|
@@ -29,8 +29,7 @@ info = {
|
|
|
29
29
|
|
|
30
30
|
json.dump(info, open('info.json', 'w'))
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
PyInstaller.__main__.run([
|
|
32
|
+
args = [
|
|
34
33
|
'dmart.py',
|
|
35
34
|
'--name=dmart',
|
|
36
35
|
'--onefile',
|
|
@@ -41,4 +40,13 @@ PyInstaller.__main__.run([
|
|
|
41
40
|
'--collect-submodules=concurrent_log_handler',
|
|
42
41
|
'--collect-submodules=pythonjsonlogger',
|
|
43
42
|
'--clean',
|
|
44
|
-
]
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
cxb_path = 'cxb'
|
|
46
|
+
if not os.path.isdir(cxb_path):
|
|
47
|
+
cxb_path = '../cxb/dist/client'
|
|
48
|
+
|
|
49
|
+
if os.path.isdir(cxb_path):
|
|
50
|
+
args.append(f'--add-data={cxb_path}:cxb')
|
|
51
|
+
|
|
52
|
+
PyInstaller.__main__.run(args)
|
data_adapters/sql/adapter.py
CHANGED
|
@@ -1379,7 +1379,7 @@ class SQLAdapter(BaseDataAdapter):
|
|
|
1379
1379
|
ffv_resource_type.append(perm_key_splited[2])
|
|
1380
1380
|
|
|
1381
1381
|
if len(ffv_spaces):
|
|
1382
|
-
perm_key_splited_query = f'@space_name:{
|
|
1382
|
+
perm_key_splited_query = f'@space_name:{"|".join(ffv_spaces)} @subpath:/{"|/".join(ffv_subpath)} @resource_type:{"|".join(ffv_resource_type)} {" ".join(ffv_query)}'
|
|
1383
1383
|
if query.search:
|
|
1384
1384
|
query.search += f' {perm_key_splited_query}'
|
|
1385
1385
|
else:
|
|
@@ -2146,7 +2146,7 @@ class SQLAdapter(BaseDataAdapter):
|
|
|
2146
2146
|
|
|
2147
2147
|
return history_diff
|
|
2148
2148
|
except Exception as e:
|
|
2149
|
-
print("[!store_entry_diff]", e)
|
|
2149
|
+
print("[!store_entry_diff]", e, old_version_flattend, new_version_flattend)
|
|
2150
2150
|
logger.error(f"Failed parsing an entry. Error: {e}")
|
|
2151
2151
|
return {}
|
|
2152
2152
|
|
|
@@ -2466,7 +2466,7 @@ class SQLAdapter(BaseDataAdapter):
|
|
|
2466
2466
|
try:
|
|
2467
2467
|
return await self.load(space_name, "/", space_name, core.Space)
|
|
2468
2468
|
except Exception as e:
|
|
2469
|
-
print("[!fetch_space]", e)
|
|
2469
|
+
print("[!fetch_space]", e, space_name)
|
|
2470
2470
|
return None
|
|
2471
2471
|
|
|
2472
2472
|
async def set_user_session(self, user_shortname: str, token: str) -> bool:
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dmart
|
|
3
|
-
Version:
|
|
4
|
-
Requires-Python: >=3.
|
|
3
|
+
Version: 1.4.1
|
|
4
|
+
Requires-Python: >=3.11
|
|
5
5
|
Requires-Dist: fastapi
|
|
6
6
|
Requires-Dist: pydantic
|
|
7
7
|
Requires-Dist: pydantic[email]
|
|
@@ -19,7 +19,6 @@ Requires-Dist: pydantic-settings
|
|
|
19
19
|
Requires-Dist: fastapi-sso
|
|
20
20
|
Requires-Dist: sqlmodel
|
|
21
21
|
Requires-Dist: psycopg[binary]
|
|
22
|
-
Requires-Dist: asyncpg
|
|
23
22
|
Requires-Dist: greenlet
|
|
24
23
|
Requires-Dist: alembic
|
|
25
24
|
Requires-Dist: jinja2
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
bundler.py,sha256=
|
|
1
|
+
bundler.py,sha256=so8ZJResb1PcOH5vboa_mpFAdYr_T8u8DbbFXd570Lg,1704
|
|
2
2
|
data_generator.py,sha256=CnE-VHEeX7-lAXtqCgbRqR9WHjTuOgeiZcviYrHAmho,2287
|
|
3
|
-
dmart.py,sha256=
|
|
3
|
+
dmart.py,sha256=QZQvR0q3CGOJy8KzXh7m8wW51JqILw--xvC0N4akjnY,21683
|
|
4
4
|
get_settings.py,sha256=Sbe2WCoiK398E7HY4SNLfDN_GmE8knR4M-YJWF31jcg,153
|
|
5
|
-
main.py,sha256=
|
|
5
|
+
main.py,sha256=0jguG9WZMYJgYAR_JO95GrSFM8Hu5qbInABMxWvoY3I,19526
|
|
6
6
|
migrate.py,sha256=hn1MZoVby_Jjqhc7y3CrLcGD619QmVZv3PONNvO7VKQ,665
|
|
7
7
|
password_gen.py,sha256=xjx8wi105ZYvhLBBQj7_rugACpxifGXHse6f7YlGXWQ,196
|
|
8
8
|
run_notification_campaign.py,sha256=ZCvHfaimK4W6q4XuHs2r6wavMGipYYw4aUkNlxmGUd8,2652
|
|
@@ -40,7 +40,7 @@ api/info/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
40
40
|
api/info/router.py,sha256=sQZZor7A-uDzsJX39aqEA7bMZOJ-WTitYeFvVNWfaHw,3938
|
|
41
41
|
api/managed/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
42
42
|
api/managed/router.py,sha256=0xfJ3NXV3XHyG8yWLEECBJt-XppymOxYuMDvQJdO1MI,50865
|
|
43
|
-
api/managed/utils.py,sha256=
|
|
43
|
+
api/managed/utils.py,sha256=KyDqnGK_ndX2Uy47FmrPHmu6PpZ35IhgjGjA816x-uY,72841
|
|
44
44
|
api/public/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
45
45
|
api/public/router.py,sha256=TrraWs2LGL_c_JRDbvS8OHm3fJ-ZKF7o4El7wvjV4Mk,24753
|
|
46
46
|
api/qr/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -70,7 +70,7 @@ data_adapters/file/drop_index.py,sha256=OK3wXwaO9tUcHcJjqyLeBnkElzK35MZMi8YLGWdr
|
|
|
70
70
|
data_adapters/file/health_check.py,sha256=cMvwsXhjEykjrTyB3HtUn8QqKdtB_h5w8mGOEYPepzU,24221
|
|
71
71
|
data_adapters/file/redis_services.py,sha256=83STcca5fYFaEVLRYAxfUQXeUQZqJOT8XH-GBSbkR-E,39914
|
|
72
72
|
data_adapters/sql/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
73
|
-
data_adapters/sql/adapter.py,sha256=
|
|
73
|
+
data_adapters/sql/adapter.py,sha256=MlNRWjUigjjS2SRzDYNaUOsGwTFPHZQn-o0DXxKKHl8,154565
|
|
74
74
|
data_adapters/sql/adapter_helpers.py,sha256=Eu22NElz2fMu6zyOsGsGrnAZcyWhHz9I__RJ9z6cwK0,15076
|
|
75
75
|
data_adapters/sql/create_tables.py,sha256=KqaXHTDOD8YaqGNc_e0iHHotd0WE3Kad_tBevtoGA20,17427
|
|
76
76
|
data_adapters/sql/create_users_folders.py,sha256=fm3P-CMcPX4b4DqXHKWMOtfX4RHdaev2nCDhYrS5cIs,1911
|
|
@@ -82,7 +82,7 @@ languages/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
82
82
|
languages/arabic.json,sha256=UL61rP9_M42CGfU94G5-1bXVUVnsJWXzoqhaXTXTJuM,910
|
|
83
83
|
languages/english.json,sha256=Y7eZ2X8c427_97qYrHOeGb2d725T-YlNNFVSi8FB7Kw,649
|
|
84
84
|
languages/kurdish.json,sha256=GgPLkVKyhIQjT7h3cPfDh0oyzg26znvBUe5X_Zz2TWI,864
|
|
85
|
-
languages/loader.py,sha256=
|
|
85
|
+
languages/loader.py,sha256=3gf2WmfSQ-AVIpyLAm_5J5NcQlWqBxQHMjcUd04Pijs,381
|
|
86
86
|
models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
87
87
|
models/api.py,sha256=f5X56dudyEysPmDuI5grM2RRCXuIQoehaAB6wMAGG28,6473
|
|
88
88
|
models/core.py,sha256=tEb7cbnC71yE9SDluynj7dE3U8Ed-EbF3uRJizy-uuU,16880
|
|
@@ -103,7 +103,7 @@ plugins/redis_db_update/plugin.py,sha256=z05k1zNJgBnKPj-jrtMUeI9br75ZPlifbzL0Hxp
|
|
|
103
103
|
plugins/resource_folders_creation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
104
104
|
plugins/resource_folders_creation/plugin.py,sha256=OwYPtRjMt2esAAEdv1FjdZgjEz01yt2xOZQi3nB0kEQ,3327
|
|
105
105
|
plugins/system_notification_sender/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
106
|
-
plugins/system_notification_sender/plugin.py,sha256=
|
|
106
|
+
plugins/system_notification_sender/plugin.py,sha256=MUOujwyRJ3yQrXwZ-X4qSdx0ZNU2c-sYy0d0-U8twoA,8253
|
|
107
107
|
plugins/update_access_controls/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
108
108
|
plugins/update_access_controls/plugin.py,sha256=43UV4vg-zxBF_7Bv0AZH6gU0Bgy2ybapNK21wJTF05k,301
|
|
109
109
|
pytests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -121,7 +121,7 @@ utils/access_control.py,sha256=8cCKr-6bL-Shl8j8xtfjEykMPGy6wkbNz-NRwLCdx-Y,11757
|
|
|
121
121
|
utils/async_request.py,sha256=Lm2xGXLeph7P1_fLhhNJDhPubKT2ncFn_Ueft4JVoeI,255
|
|
122
122
|
utils/exporter.py,sha256=HjcZCzcuH6N6f7Gn2hkTEeEFyo-MfrsiZUYAE-9kkVQ,9718
|
|
123
123
|
utils/firebase_notifier.py,sha256=nAeCUo5Mtwxygwj8ONlw8ZAtL_ekdJBabvU0z2dZ3NY,2391
|
|
124
|
-
utils/generate_email.py,sha256=
|
|
124
|
+
utils/generate_email.py,sha256=25i1iNVDfyRDq7vvZVFkaTYfMZFkAg1ZVQO2GdK7yRQ,1122
|
|
125
125
|
utils/helpers.py,sha256=gNxLg09cclRWrKNBy2pwGZsxGA0iFS5iZ_nyra3SmnI,9928
|
|
126
126
|
utils/hypercorn_config.py,sha256=q28HGRLWo9wjOVF183WwFPs3HQo4Nexc7q_7dmSVHRI,311
|
|
127
127
|
utils/internal_error_code.py,sha256=KGlXPC5YruPmb0ORVY7U3EEVpBgSLuU4lHdXgwUVN2M,1637
|
|
@@ -135,15 +135,15 @@ utils/query_policies_helper.py,sha256=jBcNI_15P6LqVeWz6w9UMreLuNIc50GxqAf17KzxE8
|
|
|
135
135
|
utils/regex.py,sha256=cv9b_l_e8tz42mKckeeyDgypKqh2e71E28co2iuEVxA,2286
|
|
136
136
|
utils/repository.py,sha256=9L-IvQ0Js0SQ5OR-Rh0i2Wdu4H9H06r8eE84hfBIu7Q,18313
|
|
137
137
|
utils/router_helper.py,sha256=Tgoq3oakejdEeyeVieTNk38JsPZ8x5RuR0kw2THc1mI,604
|
|
138
|
-
utils/settings.py,sha256=
|
|
138
|
+
utils/settings.py,sha256=SIunwTJF0Ac9fUWRt3sUsgWzMkWk0RUryEANYuOJQ9k,5660
|
|
139
139
|
utils/sms_notifier.py,sha256=04D6D_ldk3S9SojI7_381pqLc8v9lligeNHAysohz7w,550
|
|
140
140
|
utils/social_sso.py,sha256=Dm1W6U9OwKbAeUwM-kwJBHFEoreeoN-s-RHdOZ1-cNg,2216
|
|
141
141
|
utils/ticket_sys_utils.py,sha256=9QAlW2iiy8KyxQRBDj_WmzS5kKb0aYJmGwd4qzmGVqo,7005
|
|
142
142
|
utils/web_notifier.py,sha256=QM87VVid2grC5lK3NdS1yzz0z1wXljr4GChJOeK86W4,843
|
|
143
143
|
utils/templates/activation.html.j2,sha256=XAMKCdoqONoc4ZQucD0yV-Pg5DlHHASZrTVItNS-iBE,640
|
|
144
144
|
utils/templates/reminder.html.j2,sha256=aoS8bTs56q4hjAZKsb0jV9c-PIURBELuBOpT_qPZNVU,639
|
|
145
|
-
dmart-
|
|
146
|
-
dmart-
|
|
147
|
-
dmart-
|
|
148
|
-
dmart-
|
|
149
|
-
dmart-
|
|
145
|
+
dmart-1.4.1.dist-info/METADATA,sha256=Xx4kYj7woXX61a2PqjZnthP2Ud5fVUpbly5mCg6xWCk,2068
|
|
146
|
+
dmart-1.4.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
147
|
+
dmart-1.4.1.dist-info/entry_points.txt,sha256=GjfoGh1bpxuU9HHGJzbtCFPNptHv9TryxHMN3uBSKpg,37
|
|
148
|
+
dmart-1.4.1.dist-info/top_level.txt,sha256=JTypu1r5v9v7ru-60JSSbnSMEESHFRMacpcz-rPJx_U,262
|
|
149
|
+
dmart-1.4.1.dist-info/RECORD,,
|
dmart.py
CHANGED
|
@@ -11,6 +11,7 @@ import subprocess
|
|
|
11
11
|
import sys
|
|
12
12
|
import time
|
|
13
13
|
import warnings
|
|
14
|
+
import webbrowser
|
|
14
15
|
from multiprocessing import freeze_support
|
|
15
16
|
from pathlib import Path
|
|
16
17
|
|
|
@@ -29,6 +30,7 @@ from utils.settings import settings
|
|
|
29
30
|
freeze_support()
|
|
30
31
|
|
|
31
32
|
commands = """ server
|
|
33
|
+
serve
|
|
32
34
|
hyper
|
|
33
35
|
health-check
|
|
34
36
|
create-index
|
|
@@ -49,7 +51,10 @@ sentinel = object()
|
|
|
49
51
|
def hypercorn_main() -> int:
|
|
50
52
|
parser = argparse.ArgumentParser()
|
|
51
53
|
parser.add_argument(
|
|
52
|
-
"application",
|
|
54
|
+
"application",
|
|
55
|
+
help="The application to dispatch to as path.to.module:instance.path",
|
|
56
|
+
nargs="?",
|
|
57
|
+
default="main:app"
|
|
53
58
|
)
|
|
54
59
|
parser.add_argument("--access-log", help="Deprecated, see access-logfile", default=sentinel)
|
|
55
60
|
parser.add_argument(
|
|
@@ -83,7 +88,7 @@ def hypercorn_main() -> int:
|
|
|
83
88
|
"-c",
|
|
84
89
|
"--config",
|
|
85
90
|
help="Location of a TOML config file, or when prefixed with `file:` a Python file, or when prefixed with `python:` a Python module.", # noqa: E501
|
|
86
|
-
default=
|
|
91
|
+
default="hypercorn_config.toml",
|
|
87
92
|
)
|
|
88
93
|
parser.add_argument(
|
|
89
94
|
"--debug",
|
|
@@ -210,6 +215,17 @@ def hypercorn_main() -> int:
|
|
|
210
215
|
parser.add_argument(
|
|
211
216
|
"-u", "--user", help="User to own any unix sockets.", default=sentinel, type=int
|
|
212
217
|
)
|
|
218
|
+
parser.add_argument(
|
|
219
|
+
"--open-cxb",
|
|
220
|
+
help="Open CXB page in browser after server starts",
|
|
221
|
+
action="store_true",
|
|
222
|
+
default=False,
|
|
223
|
+
)
|
|
224
|
+
parser.add_argument(
|
|
225
|
+
"--cxb-config",
|
|
226
|
+
help="Path to CXB config.json",
|
|
227
|
+
default=sentinel,
|
|
228
|
+
)
|
|
213
229
|
|
|
214
230
|
def _convert_verify_mode(value: str) -> ssl.VerifyMode:
|
|
215
231
|
try:
|
|
@@ -314,6 +330,9 @@ def hypercorn_main() -> int:
|
|
|
314
330
|
config.websocket_ping_interval = args.websocket_ping_interval
|
|
315
331
|
if args.workers is not sentinel:
|
|
316
332
|
config.workers = args.workers
|
|
333
|
+
|
|
334
|
+
if args.cxb_config is not sentinel:
|
|
335
|
+
os.environ["DMART_CXB_CONFIG"] = args.cxb_config
|
|
317
336
|
|
|
318
337
|
if len(args.binds) > 0:
|
|
319
338
|
config.bind = args.binds
|
|
@@ -323,6 +342,32 @@ def hypercorn_main() -> int:
|
|
|
323
342
|
config.quic_bind = args.quic_binds
|
|
324
343
|
if len(args.server_names) > 0:
|
|
325
344
|
config.server_names = args.server_names
|
|
345
|
+
|
|
346
|
+
if args.open_cxb:
|
|
347
|
+
# Assuming default port 8282 if not specified in binds
|
|
348
|
+
port = 8282
|
|
349
|
+
host = "127.0.0.1"
|
|
350
|
+
|
|
351
|
+
# Try to parse bind address if available
|
|
352
|
+
if len(args.binds) > 0:
|
|
353
|
+
try:
|
|
354
|
+
bind_parts = args.binds[0].split(":")
|
|
355
|
+
if len(bind_parts) == 2:
|
|
356
|
+
host = bind_parts[0]
|
|
357
|
+
port = int(bind_parts[1])
|
|
358
|
+
elif len(bind_parts) == 1:
|
|
359
|
+
host = bind_parts[0]
|
|
360
|
+
except:
|
|
361
|
+
pass
|
|
362
|
+
|
|
363
|
+
url = f"http://{host}:{port}/cxb/"
|
|
364
|
+
|
|
365
|
+
def open_browser():
|
|
366
|
+
time.sleep(2) # Give server a moment to start
|
|
367
|
+
webbrowser.open(url)
|
|
368
|
+
|
|
369
|
+
import threading
|
|
370
|
+
threading.Thread(target=open_browser, daemon=True).start()
|
|
326
371
|
|
|
327
372
|
return run(config)
|
|
328
373
|
|
|
@@ -336,13 +381,30 @@ def main():
|
|
|
336
381
|
|
|
337
382
|
match sys.argv[0]:
|
|
338
383
|
case "hyper":
|
|
339
|
-
if len(sys.argv) == 1:
|
|
340
|
-
print("Running Hypercorn with default settings")
|
|
341
|
-
default_params = "main:app --config hypercorn_config.toml"
|
|
342
|
-
print(f">{default_params}")
|
|
343
|
-
sys.argv = ["hyper"] + default_params.split(" ")
|
|
344
384
|
hypercorn_main()
|
|
345
|
-
case "server":
|
|
385
|
+
case "server" | "serve":
|
|
386
|
+
# Check for --open-cxb flag in server command arguments
|
|
387
|
+
open_cxb = False
|
|
388
|
+
if "--open-cxb" in sys.argv:
|
|
389
|
+
open_cxb = True
|
|
390
|
+
sys.argv.remove("--open-cxb")
|
|
391
|
+
|
|
392
|
+
if "--cxb-config" in sys.argv:
|
|
393
|
+
idx = sys.argv.index("--cxb-config")
|
|
394
|
+
if idx + 1 < len(sys.argv):
|
|
395
|
+
os.environ["DMART_CXB_CONFIG"] = sys.argv[idx + 1]
|
|
396
|
+
sys.argv.pop(idx + 1)
|
|
397
|
+
sys.argv.pop(idx)
|
|
398
|
+
|
|
399
|
+
if open_cxb:
|
|
400
|
+
url = f"http://{settings.listening_host}:{settings.listening_port}/cxb/"
|
|
401
|
+
def open_browser():
|
|
402
|
+
time.sleep(2) # Give server a moment to start
|
|
403
|
+
webbrowser.open(url)
|
|
404
|
+
|
|
405
|
+
import threading
|
|
406
|
+
threading.Thread(target=open_browser, daemon=True).start()
|
|
407
|
+
|
|
346
408
|
asyncio.run(server())
|
|
347
409
|
case "health-check":
|
|
348
410
|
parser = argparse.ArgumentParser(
|
languages/loader.py
CHANGED
main.py
CHANGED
|
@@ -5,6 +5,7 @@ from starlette.datastructures import UploadFile
|
|
|
5
5
|
from contextlib import asynccontextmanager
|
|
6
6
|
import asyncio
|
|
7
7
|
import json
|
|
8
|
+
import os
|
|
8
9
|
from os import getpid
|
|
9
10
|
import sys
|
|
10
11
|
import time
|
|
@@ -24,11 +25,12 @@ from fastapi.logger import logger
|
|
|
24
25
|
from fastapi.encoders import jsonable_encoder
|
|
25
26
|
from fastapi.exceptions import RequestValidationError
|
|
26
27
|
from utils.access_control import access_control
|
|
27
|
-
from fastapi.responses import ORJSONResponse
|
|
28
|
+
from fastapi.responses import ORJSONResponse, FileResponse
|
|
28
29
|
from hypercorn.asyncio import serve
|
|
29
30
|
from hypercorn.config import Config
|
|
30
31
|
from starlette.concurrency import iterate_in_threadpool
|
|
31
32
|
from starlette.exceptions import HTTPException as StarletteHTTPException
|
|
33
|
+
from starlette.staticfiles import StaticFiles
|
|
32
34
|
import models.api as api
|
|
33
35
|
from utils.settings import settings
|
|
34
36
|
from asgi_correlation_id import CorrelationIdMiddleware
|
|
@@ -462,6 +464,51 @@ app.include_router(
|
|
|
462
464
|
# load plugins
|
|
463
465
|
asyncio.run(plugin_manager.load_plugins(app, capture_body))
|
|
464
466
|
|
|
467
|
+
# Serve CXB
|
|
468
|
+
cxb_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), "cxb")
|
|
469
|
+
if not os.path.exists(cxb_path):
|
|
470
|
+
# Try relative to project root (development mode)
|
|
471
|
+
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
472
|
+
cxb_dist_path = os.path.join(project_root, "cxb", "dist", "client")
|
|
473
|
+
if os.path.isdir(cxb_dist_path):
|
|
474
|
+
cxb_path = cxb_dist_path
|
|
475
|
+
|
|
476
|
+
if os.path.isdir(cxb_path):
|
|
477
|
+
@app.get("/cxb/config.json", include_in_schema=False)
|
|
478
|
+
async def get_cxb_config():
|
|
479
|
+
# Priority 0: Explicit path from flag
|
|
480
|
+
cxb_config = os.getenv("DMART_CXB_CONFIG")
|
|
481
|
+
if cxb_config and os.path.exists(cxb_config):
|
|
482
|
+
return FileResponse(cxb_config)
|
|
483
|
+
|
|
484
|
+
# Priority 1: Check in current directory (where dmart is run)
|
|
485
|
+
if os.path.exists("config.json"):
|
|
486
|
+
return FileResponse("config.json")
|
|
487
|
+
|
|
488
|
+
# Priority 2: Check in spaces folder (user directory)
|
|
489
|
+
user_config = settings.spaces_folder / "config.json"
|
|
490
|
+
if user_config.exists():
|
|
491
|
+
return FileResponse(user_config)
|
|
492
|
+
|
|
493
|
+
# Priority 3: Check in bundled CXB directory
|
|
494
|
+
bundled_config = os.path.join(cxb_path, "config.json")
|
|
495
|
+
if os.path.exists(bundled_config):
|
|
496
|
+
return FileResponse(bundled_config)
|
|
497
|
+
|
|
498
|
+
# Fallback to defaults generated from settings
|
|
499
|
+
return {
|
|
500
|
+
"title": "DMART Unified Data Platform",
|
|
501
|
+
"footer": "dmart.cc unified data platform",
|
|
502
|
+
"short_name": "dmart",
|
|
503
|
+
"display_name": "dmart",
|
|
504
|
+
"description": "dmart unified data platform",
|
|
505
|
+
"default_language": "en",
|
|
506
|
+
"languages": { "ar": "العربية", "en": "English" },
|
|
507
|
+
"backend": f"{settings.app_url}" if settings.app_url else f"http://{settings.listening_host}:{settings.listening_port}",
|
|
508
|
+
"websocket": settings.websocket_url if settings.websocket_url else f"ws://{settings.listening_host}:{settings.websocket_port}/ws"
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
app.mount("/cxb", StaticFiles(directory=cxb_path, html=True), name="cxb")
|
|
465
512
|
|
|
466
513
|
@app.options("/{x:path}", include_in_schema=False)
|
|
467
514
|
async def myoptions():
|
|
@@ -503,4 +550,3 @@ if __name__ == "__main__":
|
|
|
503
550
|
asyncio.run(main())
|
|
504
551
|
except Exception as e:
|
|
505
552
|
print("[!1server]", e)
|
|
506
|
-
|
|
@@ -69,7 +69,7 @@ class Plugin(PluginBase):
|
|
|
69
69
|
retrieve_json_payload=True,
|
|
70
70
|
space_name="management",
|
|
71
71
|
subpath="notifications/system",
|
|
72
|
-
search=f"@payload.body.on_space:{data.space_name} @payload.body.on_subpath:{data.subpath.lstrip(
|
|
72
|
+
search=f"@payload.body.on_space:{data.space_name} @payload.body.on_subpath:{data.subpath.lstrip('/')} @payload.body.on_action:{data.action_type}",
|
|
73
73
|
limit=30,
|
|
74
74
|
offset=0
|
|
75
75
|
), "dmart")
|
utils/generate_email.py
CHANGED
utils/settings.py
CHANGED
|
@@ -5,7 +5,6 @@ import os
|
|
|
5
5
|
import re
|
|
6
6
|
import string
|
|
7
7
|
import random
|
|
8
|
-
import sys
|
|
9
8
|
from venv import logger
|
|
10
9
|
|
|
11
10
|
from pydantic import Field
|
|
@@ -78,6 +77,7 @@ class Settings(BaseSettings):
|
|
|
78
77
|
session_inactivity_ttl: int = 0 # Set initially to 0 to disable session timeout. Possible value : 60 * 60 * 24 * 7 # 7 days
|
|
79
78
|
request_timeout: int = 35 # In seconds the time of dmart requests.
|
|
80
79
|
jq_timeout: int = 2 # secs
|
|
80
|
+
is_sha_required: bool = False
|
|
81
81
|
|
|
82
82
|
url_shorter_expires: int = 60 * 60 * 48 # 48 hours
|
|
83
83
|
|
|
@@ -157,7 +157,7 @@ try:
|
|
|
157
157
|
Settings()
|
|
158
158
|
)
|
|
159
159
|
except Exception as e:
|
|
160
|
-
|
|
160
|
+
logger.error(f"Failed to load settings.\nError: {e}")
|
|
161
161
|
# sys.exit(1)
|
|
162
162
|
pass
|
|
163
163
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|