zrb 1.0.0b9__py3-none-any.whl → 1.1.0__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.
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/.coveragerc +11 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/.gitignore +4 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/column/add_column_task.py +99 -55
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/column/add_column_util.py +301 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/config.py +5 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/add_entity_task.py +131 -2
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/add_entity_util.py +128 -5
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/module/gateway/view/content/my-module/my-entity.html +297 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/test/my_module/my_entity/test_create_my_entity.py +53 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/test/my_module/my_entity/test_delete_my_entity.py +62 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/test/my_module/my_entity/test_read_my_entity.py +65 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/app_template/test/my_module/my_entity/test_update_my_entity.py +61 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/gateway_subroute.py +81 -13
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/entity/template/navigation_config_file.py +8 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/add_module_task.py +8 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/add_module_util.py +42 -3
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/app_template/module/gateway/subroute/my_module.py +8 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/module_task_definition.py +10 -6
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/module/template/navigation_config_file.py +6 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/task.py +56 -12
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/_zrb/task_util.py +10 -4
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/base_service.py +136 -52
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/util/parser.py +3 -3
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/common/util/view.py +1 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/config.py +19 -8
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration/versions/3093c7336477_add_auth_tables.py +46 -43
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/migration/versions/8ed025bcc845_create_permissions.py +69 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/repository/user_db_repository.py +5 -2
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/auth/service/user/user_service.py +16 -21
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/config/navigation.py +39 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/route.py +52 -11
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/schema/navigation.py +95 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/subroute/auth.py +277 -44
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/util/auth.py +66 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/util/view.py +33 -8
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/content/auth/permission.html +311 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/content/auth/role.html +0 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/content/auth/user.html +0 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/content/error.html +4 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/content/login.html +67 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/content/logout.html +49 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/common/util.js +160 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/crud/style.css +14 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/crud/util.js +94 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/default/pico-style.css +23 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/default/script.js +44 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/static/default/style.css +102 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/module/gateway/view/template/default.html +73 -18
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/requirements.txt +6 -1
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/permission.py +1 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/schema/user.py +9 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/_util/access_token.py +19 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/auth/permission/test_create_permission.py +59 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/auth/permission/test_delete_permission.py +68 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/auth/permission/test_read_permission.py +71 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/auth/permission/test_update_permission.py +66 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/auth/test_user_session.py +195 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/test_health_and_readiness.py +28 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/test_homepage.py +15 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test/test_not_found_error.py +16 -0
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/test.sh +7 -0
- zrb/runner/web_route/refresh_token_api_route.py +1 -1
- zrb/runner/web_route/static/refresh-token.template.js +9 -0
- zrb/runner/web_route/static/static_route.py +1 -1
- zrb/task/base_task.py +10 -10
- zrb/util/codemod/modification_mode.py +3 -0
- zrb/util/codemod/modify_class.py +58 -0
- zrb/util/codemod/modify_class_parent.py +68 -0
- zrb/util/codemod/modify_class_property.py +128 -0
- zrb/util/codemod/modify_dict.py +75 -0
- zrb/util/codemod/modify_function.py +65 -0
- zrb/util/codemod/modify_function_call.py +68 -0
- zrb/util/codemod/modify_method.py +88 -0
- zrb/util/codemod/{prepend_code_to_module.py → modify_module.py} +2 -3
- zrb/util/file.py +3 -2
- zrb/util/load.py +13 -7
- {zrb-1.0.0b9.dist-info → zrb-1.1.0.dist-info}/METADATA +2 -2
- {zrb-1.0.0b9.dist-info → zrb-1.1.0.dist-info}/RECORD +80 -46
- zrb/builtin/project/add/fastapp/fastapp_template/my_app_name/migrate.py +0 -3
- zrb/util/codemod/append_code_to_class.py +0 -35
- zrb/util/codemod/append_code_to_function.py +0 -38
- zrb/util/codemod/append_code_to_method.py +0 -55
- zrb/util/codemod/append_key_to_dict.py +0 -51
- zrb/util/codemod/append_param_to_function_call.py +0 -39
- zrb/util/codemod/prepend_parent_to_class.py +0 -38
- zrb/util/codemod/prepend_property_to_class.py +0 -55
- {zrb-1.0.0b9.dist-info → zrb-1.1.0.dist-info}/WHEEL +0 -0
- {zrb-1.0.0b9.dist-info → zrb-1.1.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
from fastapi.testclient import TestClient
|
2
|
+
from my_app_name.main import app
|
3
|
+
from my_app_name.test._util.access_token import get_admin_access_token
|
4
|
+
|
5
|
+
|
6
|
+
def test_create_my_entity():
|
7
|
+
client = TestClient(app, base_url="http://localhost")
|
8
|
+
access_token = get_admin_access_token()
|
9
|
+
new_my_entity_data = {
|
10
|
+
"my_column": "new-my-entity",
|
11
|
+
}
|
12
|
+
response = client.post(
|
13
|
+
"/api/v1/my-entities",
|
14
|
+
json=new_my_entity_data,
|
15
|
+
headers={"Authorization": f"Bearer {access_token}"},
|
16
|
+
)
|
17
|
+
assert response.status_code == 200
|
18
|
+
response_data = response.json()
|
19
|
+
assert response_data.get("id") is not None
|
20
|
+
assert response_data.get("id") != ""
|
21
|
+
assert response_data.get("my_column") == "new-my-entity"
|
22
|
+
|
23
|
+
|
24
|
+
def test_create_my_entity_bulk():
|
25
|
+
client = TestClient(app, base_url="http://localhost")
|
26
|
+
access_token = get_admin_access_token()
|
27
|
+
new_first_my_entity_data = {
|
28
|
+
"my_column": "new-my-entity-bulk-1",
|
29
|
+
}
|
30
|
+
new_second_my_entity_data = {
|
31
|
+
"my_column": "new-my-entity-bulk-2",
|
32
|
+
}
|
33
|
+
new_my_entity_data = [new_first_my_entity_data, new_second_my_entity_data]
|
34
|
+
response = client.post(
|
35
|
+
"/api/v1/my-entities/bulk",
|
36
|
+
json=new_my_entity_data,
|
37
|
+
headers={"Authorization": f"Bearer {access_token}"},
|
38
|
+
)
|
39
|
+
assert response.status_code == 200
|
40
|
+
response_data = response.json()
|
41
|
+
assert len(response_data) == 2
|
42
|
+
# Id should not be empty
|
43
|
+
assert response_data[0] is not None
|
44
|
+
assert response_data[0] != ""
|
45
|
+
assert response_data[1] is not None
|
46
|
+
assert response_data[1] != ""
|
47
|
+
# Data should match
|
48
|
+
assert new_first_my_entity_data["my_column"] in [
|
49
|
+
row["my_column"] for row in response_data
|
50
|
+
]
|
51
|
+
assert new_second_my_entity_data["my_column"] in [
|
52
|
+
row["my_column"] for row in response_data
|
53
|
+
]
|
@@ -0,0 +1,62 @@
|
|
1
|
+
from fastapi.testclient import TestClient
|
2
|
+
from my_app_name.main import app
|
3
|
+
from my_app_name.test._util.access_token import get_admin_access_token
|
4
|
+
|
5
|
+
|
6
|
+
def test_delete_my_entity():
|
7
|
+
client = TestClient(app, base_url="http://localhost")
|
8
|
+
access_token = get_admin_access_token()
|
9
|
+
new_my_entity_data = {
|
10
|
+
"my_column": "to-be-deleted-my-entity",
|
11
|
+
}
|
12
|
+
insert_response = client.post(
|
13
|
+
"/api/v1/my-entities",
|
14
|
+
json=new_my_entity_data,
|
15
|
+
headers={"Authorization": f"Bearer {access_token}"},
|
16
|
+
)
|
17
|
+
assert insert_response.status_code == 200
|
18
|
+
id = insert_response.json().get("id")
|
19
|
+
# deleting
|
20
|
+
response = client.delete(
|
21
|
+
f"/api/v1/my-entities/{id}", headers={"Authorization": f"Bearer {access_token}"}
|
22
|
+
)
|
23
|
+
assert response.status_code == 200
|
24
|
+
response_data = response.json()
|
25
|
+
assert response_data.get("id") == id
|
26
|
+
assert response_data.get("my_column") == "to-be-deleted-my-entity"
|
27
|
+
|
28
|
+
|
29
|
+
def test_delete_my_entity_bulk():
|
30
|
+
client = TestClient(app, base_url="http://localhost")
|
31
|
+
access_token = get_admin_access_token()
|
32
|
+
new_first_my_entity_data = {
|
33
|
+
"my_column": "to-be-deleted-my-entity-bulk-1",
|
34
|
+
}
|
35
|
+
new_second_my_entity_data = {
|
36
|
+
"my_column": "to-be-deleted-my-entity-bulk-2",
|
37
|
+
}
|
38
|
+
new_my_entity_data = [new_first_my_entity_data, new_second_my_entity_data]
|
39
|
+
insert_response = client.post(
|
40
|
+
"/api/v1/my-entities/bulk",
|
41
|
+
json=new_my_entity_data,
|
42
|
+
headers={"Authorization": f"Bearer {access_token}"},
|
43
|
+
)
|
44
|
+
assert insert_response.status_code == 200
|
45
|
+
ids = [row["id"] for row in insert_response.json()]
|
46
|
+
# deleting (use client.request since client.delete doesn't support json param)
|
47
|
+
response = client.request(
|
48
|
+
"DELETE",
|
49
|
+
f"/api/v1/my-entities/bulk",
|
50
|
+
json=ids,
|
51
|
+
headers={"Authorization": f"Bearer {access_token}"},
|
52
|
+
)
|
53
|
+
assert response.status_code == 200
|
54
|
+
response_data = response.json()
|
55
|
+
# Data should match
|
56
|
+
assert len([row["id"] for row in response_data if row["id"] in ids]) == 2
|
57
|
+
assert new_first_my_entity_data["my_column"] in [
|
58
|
+
row["my_column"] for row in response_data
|
59
|
+
]
|
60
|
+
assert new_second_my_entity_data["my_column"] in [
|
61
|
+
row["my_column"] for row in response_data
|
62
|
+
]
|
@@ -0,0 +1,65 @@
|
|
1
|
+
from fastapi.testclient import TestClient
|
2
|
+
from my_app_name.main import app
|
3
|
+
from my_app_name.test._util.access_token import get_admin_access_token
|
4
|
+
|
5
|
+
|
6
|
+
def test_read_my_entity_by_id():
|
7
|
+
client = TestClient(app, base_url="http://localhost")
|
8
|
+
access_token = get_admin_access_token()
|
9
|
+
new_my_entity_data = {
|
10
|
+
"my_column": "to-be-read-my-entity",
|
11
|
+
}
|
12
|
+
insert_response = client.post(
|
13
|
+
"/api/v1/my-entities",
|
14
|
+
json=new_my_entity_data,
|
15
|
+
headers={"Authorization": f"Bearer {access_token}"},
|
16
|
+
)
|
17
|
+
assert insert_response.status_code == 200
|
18
|
+
id = insert_response.json().get("id")
|
19
|
+
# fetching
|
20
|
+
response = client.get(
|
21
|
+
f"/api/v1/my-entities/{id}", headers={"Authorization": f"Bearer {access_token}"}
|
22
|
+
)
|
23
|
+
assert response.status_code == 200
|
24
|
+
response_data = response.json()
|
25
|
+
assert response_data.get("id") == id
|
26
|
+
assert response_data.get("my_column") == "to-be-read-my-entity"
|
27
|
+
|
28
|
+
|
29
|
+
def test_read_my_entity_bulk():
|
30
|
+
client = TestClient(app, base_url="http://localhost")
|
31
|
+
access_token = get_admin_access_token()
|
32
|
+
new_first_my_entity_data = {
|
33
|
+
"my_column": "to-be-read-my-entity-bulk-1",
|
34
|
+
}
|
35
|
+
new_second_my_entity_data = {
|
36
|
+
"my_column": "to-be-read-my-entity-bulk-2",
|
37
|
+
}
|
38
|
+
new_my_entity_data = [new_first_my_entity_data, new_second_my_entity_data]
|
39
|
+
insert_response = client.post(
|
40
|
+
"/api/v1/my-entities/bulk",
|
41
|
+
json=new_my_entity_data,
|
42
|
+
headers={"Authorization": f"Bearer {access_token}"},
|
43
|
+
)
|
44
|
+
assert insert_response.status_code == 200
|
45
|
+
ids = [row["id"] for row in insert_response.json()]
|
46
|
+
# fetching
|
47
|
+
response = client.get(
|
48
|
+
f"/api/v1/my-entities",
|
49
|
+
params={
|
50
|
+
"filter": "my_column:like:to-be-read-my-entity-bulk-%",
|
51
|
+
},
|
52
|
+
headers={"Authorization": f"Bearer {access_token}"},
|
53
|
+
)
|
54
|
+
assert response.status_code == 200
|
55
|
+
response_data_count = response.json()["count"]
|
56
|
+
assert response_data_count == 2
|
57
|
+
response_data = response.json()["data"]
|
58
|
+
# Data should match
|
59
|
+
assert len([row["id"] for row in response_data if row["id"] in ids]) == 2
|
60
|
+
assert new_first_my_entity_data["my_column"] in [
|
61
|
+
row["my_column"] for row in response_data
|
62
|
+
]
|
63
|
+
assert new_second_my_entity_data["my_column"] in [
|
64
|
+
row["my_column"] for row in response_data
|
65
|
+
]
|
@@ -0,0 +1,61 @@
|
|
1
|
+
from fastapi.testclient import TestClient
|
2
|
+
from my_app_name.main import app
|
3
|
+
from my_app_name.test._util.access_token import get_admin_access_token
|
4
|
+
|
5
|
+
|
6
|
+
def test_update_my_entity():
|
7
|
+
client = TestClient(app, base_url="http://localhost")
|
8
|
+
access_token = get_admin_access_token()
|
9
|
+
new_my_entity_data = {
|
10
|
+
"my_column": "to-be-updated-my-entity",
|
11
|
+
}
|
12
|
+
insert_response = client.post(
|
13
|
+
"/api/v1/my-entities",
|
14
|
+
json=new_my_entity_data,
|
15
|
+
headers={"Authorization": f"Bearer {access_token}"},
|
16
|
+
)
|
17
|
+
assert insert_response.status_code == 200
|
18
|
+
id = insert_response.json().get("id")
|
19
|
+
# updating
|
20
|
+
updated_my_entity_data = {
|
21
|
+
"my_column": "updated-my-entity",
|
22
|
+
}
|
23
|
+
response = client.put(
|
24
|
+
f"/api/v1/my-entities/{id}",
|
25
|
+
json=updated_my_entity_data,
|
26
|
+
headers={"Authorization": f"Bearer {access_token}"},
|
27
|
+
)
|
28
|
+
assert response.status_code == 200
|
29
|
+
response_data = response.json()
|
30
|
+
assert response_data.get("id") == id
|
31
|
+
assert response_data.get("my_column") == "updated-my-entity"
|
32
|
+
|
33
|
+
|
34
|
+
def test_update_my_entity_bulk():
|
35
|
+
client = TestClient(app, base_url="http://localhost")
|
36
|
+
access_token = get_admin_access_token()
|
37
|
+
new_first_my_entity_data = {
|
38
|
+
"my_column": "to-be-updated-my-entity-bulk-1",
|
39
|
+
}
|
40
|
+
insert_response = client.post(
|
41
|
+
"/api/v1/my-entities/bulk",
|
42
|
+
json=[new_first_my_entity_data],
|
43
|
+
headers={"Authorization": f"Bearer {access_token}"},
|
44
|
+
)
|
45
|
+
assert insert_response.status_code == 200
|
46
|
+
ids = [row["id"] for row in insert_response.json()]
|
47
|
+
# updating (we only test with one data)
|
48
|
+
updated_my_entity_data = {"my_column": "updated-my-entity-bulk-1"}
|
49
|
+
response = client.put(
|
50
|
+
f"/api/v1/my-entities/bulk",
|
51
|
+
json={
|
52
|
+
"my_entity_ids": ids,
|
53
|
+
"data": updated_my_entity_data,
|
54
|
+
},
|
55
|
+
headers={"Authorization": f"Bearer {access_token}"},
|
56
|
+
)
|
57
|
+
assert response.status_code == 200
|
58
|
+
response_data = response.json()
|
59
|
+
assert len(response_data) == 1
|
60
|
+
response_data[0].get("id") == ids[0]
|
61
|
+
response_data[0].get("my_column") == updated_my_entity_data["my_column"]
|
@@ -1,20 +1,52 @@
|
|
1
1
|
# MyEntity routes
|
2
2
|
|
3
3
|
|
4
|
+
@app.get("/my-module/my-entities", include_in_schema=False)
|
5
|
+
def my_entities_crud_ui(
|
6
|
+
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
7
|
+
page: int = 1,
|
8
|
+
page_size: int = 10,
|
9
|
+
sort: str | None = None,
|
10
|
+
filter: str | None = None,
|
11
|
+
):
|
12
|
+
if not current_user.has_permission("my-entity:read"):
|
13
|
+
return render_error(error_message="Access denied", status_code=403)
|
14
|
+
return render_content(
|
15
|
+
view_path=os.path.join("my-module", "my-entity.html"),
|
16
|
+
current_user=current_user,
|
17
|
+
page_name="my-module.my-entity",
|
18
|
+
page=page,
|
19
|
+
page_size=page_size,
|
20
|
+
sort=sort,
|
21
|
+
filter=filter,
|
22
|
+
allow_create=current_user.has_permission("my-entity:create"),
|
23
|
+
allow_update=current_user.has_permission("my-entity:update"),
|
24
|
+
allow_delete=current_user.has_permission("my-entity:delete"),
|
25
|
+
)
|
26
|
+
|
27
|
+
|
4
28
|
@app.get("/api/v1/my-entities", response_model=MultipleMyEntityResponse)
|
5
29
|
async def get_my_entities(
|
30
|
+
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
6
31
|
page: int = 1,
|
7
32
|
page_size: int = 10,
|
8
33
|
sort: str | None = None,
|
9
34
|
filter: str | None = None,
|
10
35
|
) -> MultipleMyEntityResponse:
|
36
|
+
if not current_user.has_permission("my-entity:read"):
|
37
|
+
raise ForbiddenError("Access denied")
|
11
38
|
return await my_module_client.get_my_entities(
|
12
39
|
page=page, page_size=page_size, sort=sort, filter=filter
|
13
40
|
)
|
14
41
|
|
15
42
|
|
16
43
|
@app.get("/api/v1/my-entities/{my_entity_id}", response_model=MyEntityResponse)
|
17
|
-
async def get_my_entity_by_id(
|
44
|
+
async def get_my_entity_by_id(
|
45
|
+
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
46
|
+
my_entity_id: str,
|
47
|
+
) -> MyEntityResponse:
|
48
|
+
if not current_user.has_permission("my-entity:read"):
|
49
|
+
raise ForbiddenError("Access denied")
|
18
50
|
return await my_module_client.get_my_entity_by_id(my_entity_id)
|
19
51
|
|
20
52
|
|
@@ -22,9 +54,14 @@ async def get_my_entity_by_id(my_entity_id: str) -> MyEntityResponse:
|
|
22
54
|
"/api/v1/my-entities/bulk",
|
23
55
|
response_model=list[MyEntityResponse],
|
24
56
|
)
|
25
|
-
async def create_my_entity_bulk(
|
57
|
+
async def create_my_entity_bulk(
|
58
|
+
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
59
|
+
data: list[MyEntityCreate],
|
60
|
+
) -> list[MyEntityResponse]:
|
61
|
+
if not current_user.has_permission("my-entity:create"):
|
62
|
+
raise ForbiddenError("Access denied")
|
26
63
|
return await my_module_client.create_my_entity_bulk(
|
27
|
-
[row.with_audit(created_by=
|
64
|
+
[row.with_audit(created_by=current_user.id) for row in data]
|
28
65
|
)
|
29
66
|
|
30
67
|
|
@@ -32,17 +69,30 @@ async def create_my_entity_bulk(data: list[MyEntityCreate]):
|
|
32
69
|
"/api/v1/my-entities",
|
33
70
|
response_model=MyEntityResponse,
|
34
71
|
)
|
35
|
-
async def create_my_entity(
|
36
|
-
|
72
|
+
async def create_my_entity(
|
73
|
+
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
74
|
+
data: MyEntityCreate,
|
75
|
+
) -> MyEntityResponse:
|
76
|
+
if not current_user.has_permission("my-entity:create"):
|
77
|
+
raise ForbiddenError("Access denied")
|
78
|
+
return await my_module_client.create_my_entity(
|
79
|
+
data.with_audit(created_by=current_user.id)
|
80
|
+
)
|
37
81
|
|
38
82
|
|
39
83
|
@app.put(
|
40
84
|
"/api/v1/my-entities/bulk",
|
41
85
|
response_model=list[MyEntityResponse],
|
42
86
|
)
|
43
|
-
async def update_my_entity_bulk(
|
87
|
+
async def update_my_entity_bulk(
|
88
|
+
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
89
|
+
my_entity_ids: list[str],
|
90
|
+
data: MyEntityUpdate,
|
91
|
+
) -> list[MyEntityResponse]:
|
92
|
+
if not current_user.has_permission("my-entity:update"):
|
93
|
+
raise ForbiddenError("Access denied")
|
44
94
|
return await my_module_client.update_my_entity_bulk(
|
45
|
-
my_entity_ids, data.with_audit(updated_by=
|
95
|
+
my_entity_ids, data.with_audit(updated_by=current_user.id)
|
46
96
|
)
|
47
97
|
|
48
98
|
|
@@ -50,9 +100,15 @@ async def update_my_entity_bulk(my_entity_ids: list[str], data: MyEntityUpdate):
|
|
50
100
|
"/api/v1/my-entities/{my_entity_id}",
|
51
101
|
response_model=MyEntityResponse,
|
52
102
|
)
|
53
|
-
async def update_my_entity(
|
103
|
+
async def update_my_entity(
|
104
|
+
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
105
|
+
my_entity_id: str,
|
106
|
+
data: MyEntityUpdate,
|
107
|
+
) -> MyEntityResponse:
|
108
|
+
if not current_user.has_permission("my-entity:update"):
|
109
|
+
raise ForbiddenError("Access denied")
|
54
110
|
return await my_module_client.update_my_entity(
|
55
|
-
my_entity_id, data.with_audit(updated_by=
|
111
|
+
my_entity_id, data.with_audit(updated_by=current_user.id)
|
56
112
|
)
|
57
113
|
|
58
114
|
|
@@ -60,9 +116,14 @@ async def update_my_entity(my_entity_id: str, data: MyEntityUpdate):
|
|
60
116
|
"/api/v1/my-entities/bulk",
|
61
117
|
response_model=list[MyEntityResponse],
|
62
118
|
)
|
63
|
-
async def delete_my_entity_bulk(
|
119
|
+
async def delete_my_entity_bulk(
|
120
|
+
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
121
|
+
my_entity_ids: list[str],
|
122
|
+
) -> list[MyEntityResponse]:
|
123
|
+
if not current_user.has_permission("my-entity:delete"):
|
124
|
+
raise ForbiddenError("Access denied")
|
64
125
|
return await my_module_client.delete_my_entity_bulk(
|
65
|
-
my_entity_ids, deleted_by=
|
126
|
+
my_entity_ids, deleted_by=current_user.id
|
66
127
|
)
|
67
128
|
|
68
129
|
|
@@ -70,5 +131,12 @@ async def delete_my_entity_bulk(my_entity_ids: list[str]):
|
|
70
131
|
"/api/v1/my-entities/{my_entity_id}",
|
71
132
|
response_model=MyEntityResponse,
|
72
133
|
)
|
73
|
-
async def delete_my_entity(
|
74
|
-
|
134
|
+
async def delete_my_entity(
|
135
|
+
current_user: Annotated[AuthUserResponse, Depends(get_current_user)],
|
136
|
+
my_entity_id: str,
|
137
|
+
) -> MyEntityResponse:
|
138
|
+
if not current_user.has_permission("my-entity:delete"):
|
139
|
+
raise ForbiddenError("Access denied")
|
140
|
+
return await my_module_client.delete_my_entity(
|
141
|
+
my_entity_id, deleted_by=current_user.id
|
142
|
+
)
|
@@ -10,12 +10,14 @@ from my_app_name._zrb.module.add_module_util import (
|
|
10
10
|
is_app_zrb_config_file,
|
11
11
|
is_app_zrb_task_file,
|
12
12
|
is_gateway_module_subroute_file,
|
13
|
+
is_gateway_navigation_config_file,
|
13
14
|
is_gateway_route_file,
|
14
15
|
is_in_module_dir,
|
15
16
|
update_app_config_file,
|
16
17
|
update_app_main_file,
|
17
18
|
update_app_zrb_config_file,
|
18
19
|
update_app_zrb_task_file,
|
20
|
+
update_gateway_navigation_config_file,
|
19
21
|
update_gateway_route_file,
|
20
22
|
)
|
21
23
|
from my_app_name._zrb.util import get_existing_module_names
|
@@ -91,6 +93,12 @@ scaffold_my_app_name_module = Scaffolder(
|
|
91
93
|
match=is_gateway_route_file,
|
92
94
|
transform=update_gateway_route_file,
|
93
95
|
),
|
96
|
+
# Register module's page to my_app_name/gateway/config/navigation.py
|
97
|
+
ContentTransformer(
|
98
|
+
name="transform-gateway-navigation-config",
|
99
|
+
match=is_gateway_navigation_config_file,
|
100
|
+
transform=update_gateway_navigation_config_file,
|
101
|
+
),
|
94
102
|
],
|
95
103
|
retries=0,
|
96
104
|
upstream=validate_add_my_app_name_module,
|
@@ -4,10 +4,15 @@ from my_app_name._zrb.config import APP_DIR
|
|
4
4
|
from my_app_name._zrb.util import get_existing_module_names
|
5
5
|
|
6
6
|
from zrb.context.any_context import AnyContext
|
7
|
-
from zrb.util.codemod.
|
8
|
-
from zrb.util.codemod.
|
7
|
+
from zrb.util.codemod.modify_dict import append_key_to_dict
|
8
|
+
from zrb.util.codemod.modify_function import append_code_to_function
|
9
9
|
from zrb.util.file import read_file, write_file
|
10
|
-
from zrb.util.string.conversion import
|
10
|
+
from zrb.util.string.conversion import (
|
11
|
+
to_human_case,
|
12
|
+
to_kebab_case,
|
13
|
+
to_pascal_case,
|
14
|
+
to_snake_case,
|
15
|
+
)
|
11
16
|
|
12
17
|
|
13
18
|
def is_app_config_file(ctx: AnyContext, file_path: str) -> bool:
|
@@ -22,6 +27,12 @@ def is_gateway_route_file(ctx: AnyContext, file_path: str) -> bool:
|
|
22
27
|
return file_path == os.path.join(APP_DIR, "module", "gateway", "route.py")
|
23
28
|
|
24
29
|
|
30
|
+
def is_gateway_navigation_config_file(ctx: AnyContext, file_path: str) -> bool:
|
31
|
+
return file_path == os.path.join(
|
32
|
+
APP_DIR, "module", "gateway", "config", "navigation.py"
|
33
|
+
)
|
34
|
+
|
35
|
+
|
25
36
|
def is_app_zrb_task_file(ctx: AnyContext, file_path: str) -> bool:
|
26
37
|
return file_path == os.path.join(APP_DIR, "_zrb", "task.py")
|
27
38
|
|
@@ -194,3 +205,31 @@ def _get_module_subroute_import(existing_code: str, module_name: str) -> str | N
|
|
194
205
|
if import_code in existing_code:
|
195
206
|
return None
|
196
207
|
return import_code
|
208
|
+
|
209
|
+
|
210
|
+
def update_gateway_navigation_config_file(
|
211
|
+
ctx: AnyContext, gateway_navigation_config_file_path: str
|
212
|
+
):
|
213
|
+
existing_gateway_navigation_config_code = read_file(
|
214
|
+
gateway_navigation_config_file_path
|
215
|
+
)
|
216
|
+
snake_module_name = to_snake_case(ctx.input.module)
|
217
|
+
kebab_module_name = to_kebab_case(ctx.input.module)
|
218
|
+
human_module_name = to_human_case(ctx.input.module)
|
219
|
+
new_navigation_config_code = read_file(
|
220
|
+
file_path=os.path.join(
|
221
|
+
os.path.dirname(__file__), "template", "navigation_config_file.py"
|
222
|
+
),
|
223
|
+
replace_map={
|
224
|
+
"my_module": snake_module_name,
|
225
|
+
"my-module": kebab_module_name,
|
226
|
+
"My Module": human_module_name.title(),
|
227
|
+
},
|
228
|
+
).strip()
|
229
|
+
write_file(
|
230
|
+
file_path=gateway_navigation_config_file_path,
|
231
|
+
content=[
|
232
|
+
existing_gateway_navigation_config_code,
|
233
|
+
new_navigation_config_code,
|
234
|
+
],
|
235
|
+
)
|
@@ -1,4 +1,11 @@
|
|
1
|
-
|
1
|
+
import os
|
2
|
+
from typing import Annotated
|
3
|
+
|
4
|
+
from fastapi import Depends, FastAPI
|
5
|
+
from my_app_name.common.error import ForbiddenError
|
6
|
+
from my_app_name.module.gateway.util.auth import get_current_user
|
7
|
+
from my_app_name.module.gateway.util.view import render_content, render_error
|
8
|
+
from my_app_name.schema.user import AuthUserResponse
|
2
9
|
|
3
10
|
|
4
11
|
def serve_my_module_route(app: FastAPI):
|
@@ -1,26 +1,30 @@
|
|
1
1
|
# 🔐 Run/Migrate My Module ==========================================================
|
2
2
|
|
3
3
|
run_my_module = app_run_group.add_task(
|
4
|
-
run_microservice("
|
4
|
+
run_microservice("my_module", 3000), alias="svc-my-module"
|
5
5
|
)
|
6
6
|
prepare_venv >> run_my_module >> run_microservices
|
7
7
|
|
8
8
|
create_my_module_migration = app_create_migration_group.add_task(
|
9
|
-
create_migration("
|
9
|
+
create_migration("my_module"), alias="my_module"
|
10
10
|
)
|
11
11
|
prepare_venv >> create_my_module_migration >> create_all_migration
|
12
12
|
|
13
|
-
migrate_monolith_my_module = migrate_module(
|
14
|
-
"my_module", "my_module", as_microservices=False
|
15
|
-
)
|
13
|
+
migrate_monolith_my_module = migrate_module("my_module", as_microservices=False)
|
16
14
|
prepare_venv >> migrate_monolith_my_module >> [migrate_monolith, run_monolith]
|
17
15
|
|
18
16
|
migrate_microservices_my_module = app_migrate_group.add_task(
|
19
|
-
migrate_module("
|
17
|
+
migrate_module("my_module", as_microservices=True),
|
20
18
|
alias="svc-my-module",
|
21
19
|
)
|
20
|
+
|
22
21
|
(
|
23
22
|
prepare_venv
|
24
23
|
>> migrate_microservices_my_module
|
25
24
|
>> [migrate_microservices, run_my_module]
|
26
25
|
)
|
26
|
+
|
27
|
+
migrate_test_my_module = migrate_module(
|
28
|
+
"my_module", as_microservices=False, additional_env_vars=TEST_ENV_VARS
|
29
|
+
)
|
30
|
+
prepare_venv >> migrate_test_my_module >> migrate_test
|