Compare commits

..

124 Commits

Author SHA1 Message Date
Arslan, Erdem
102e38988c enable debug mode for release pipeline 2024-01-30 12:48:57 +01:00
Arslan, Erdem
4e7c44eeb5 update tags for release pipeline 2024-01-30 12:42:27 +01:00
Arslan, Erdem
3238cdf36d update release pipeline 2024-01-30 12:23:14 +01:00
Arslan, Erdem
1abbc383ec create .gitlab-ci.yml for a release pipeline 2024-01-30 12:22:54 +01:00
5a09cc8e31 update ui-assets.nix
All checks were successful
checks-impure / test (push) Has been skipped
checks / test (push) Has been skipped
assets1 / test (push) Has been skipped
2024-01-29 20:02:50 +00:00
Sara Pervana
c6e1b8a21d Merge pull request 'added dark mode switch for icon buttons' (#77) from dark-mode-buttons into main
Some checks failed
checks-impure / test (push) Successful in 26s
checks / test (push) Successful in 1m13s
assets1 / test (push) Has been cancelled
Reviewed-on: #77
2024-01-29 21:00:33 +01:00
sara-pervana
afe291c54c added dark mode switch for icon buttons
All checks were successful
checks-impure / test (pull_request) Successful in 28s
checks / test (pull_request) Successful in 3m47s
2024-01-29 20:53:16 +01:00
6024090f69 update ui-assets.nix
All checks were successful
checks-impure / test (push) Has been skipped
checks / test (push) Has been skipped
assets1 / test (push) Has been skipped
2024-01-29 18:40:49 +00:00
Sara Pervana
596e87c31b Merge pull request 'Adding Consume Functionality' (#74) from consume-functionality into main
Some checks failed
checks-impure / test (push) Successful in 26s
checks / test (push) Successful in 1m10s
assets1 / test (push) Has been cancelled
Reviewed-on: #74
2024-01-29 19:38:27 +01:00
sara-pervana
06c55f151b fixed invalid tailwind classes 2024-01-29 19:38:27 +01:00
sara-pervana
04675f5e9e added a bit of time delay for register/deregister and also a confirm button for delete 2024-01-29 19:38:27 +01:00
sara-pervana
b5008306cb added consume view and loaders on the buttons when clicked 2024-01-29 19:38:27 +01:00
sara-pervana
1b549549c0 added headers for axios requests 2024-01-29 19:38:27 +01:00
sara-pervana
29aa17ca7c added consume and register deregister as simple fetch 2024-01-29 19:38:27 +01:00
sara-pervana
e06afab048 minimum progress 2024-01-29 19:38:27 +01:00
sara-pervana
697d2685f3 small formatting fixes 2024-01-29 19:38:27 +01:00
Georg-Stahn
2f6ad476b3 Merge pull request 'added middleware for emulation' (#76) from georgdeamon into main
All checks were successful
checks-impure / test (push) Successful in 25s
checks / test (push) Successful in 1m24s
assets1 / test (push) Successful in 23s
Reviewed-on: #76
2024-01-28 19:37:23 +01:00
Georg-Stahn
dc04001dca emulate nix fmt changes
All checks were successful
checks-impure / test (pull_request) Successful in 26s
checks / test (pull_request) Successful in 3m35s
2024-01-28 18:26:00 +01:00
Georg-Stahn
3828402865 added middleware for emulation
Some checks failed
checks-impure / test (pull_request) Successful in 26s
checks / test (pull_request) Failing after 3m38s
2024-01-28 18:22:32 +01:00
Georg-Stahn
5b64eb4c3f Merge pull request 'georgdeamon' (#75) from georgdeamon into main
All checks were successful
checks-impure / test (push) Successful in 25s
checks / test (push) Successful in 1m12s
assets1 / test (push) Successful in 21s
Reviewed-on: #75
2024-01-26 11:47:50 +01:00
Georg-Stahn
eebc7eee20 filter out ap dlg in entity view
All checks were successful
checks-impure / test (pull_request) Successful in 26s
checks / test (pull_request) Successful in 3m19s
2024-01-26 09:18:04 +01:00
Georg-Stahn
2e787aa386 change deamon0 8000 to deamon1 8001 as emulation 2024-01-26 08:43:43 +01:00
Georg-Stahn
90c6df93f4 change deamon0 8000 to deamon1 8001 as emulation 2024-01-26 08:38:45 +01:00
374fdfdaea update ui-assets.nix
All checks were successful
checks-impure / test (push) Has been skipped
checks / test (push) Has been skipped
assets1 / test (push) Has been skipped
2024-01-26 00:28:17 +00:00
Sara Pervana
a240cfd340 Merge pull request 'Added a lot of fixes' (#73) from more-fixes into main
Some checks failed
checks-impure / test (push) Successful in 26s
checks / test (push) Successful in 1m14s
assets1 / test (push) Has been cancelled
Reviewed-on: #73
2024-01-26 01:25:58 +01:00
sara-pervana
eaec0feb96 warning fix
All checks were successful
checks-impure / test (pull_request) Successful in 26s
checks / test (pull_request) Successful in 3m3s
2024-01-26 01:19:32 +01:00
sara-pervana
f3ab6e1b45 removed warnings
Some checks failed
checks-impure / test (pull_request) Successful in 26s
checks / test (pull_request) Failing after 1m48s
2024-01-26 01:11:55 +01:00
sara-pervana
2c79dabce0 added a lot of stuff
Some checks failed
checks-impure / test (pull_request) Successful in 33s
checks / test (pull_request) Failing after 2m47s
2024-01-26 00:44:53 +01:00
sara-pervana
fd09d73edd small formatting fixes 2024-01-25 22:31:25 +01:00
sara-pervana
2000c1444a fix the issue of mermaid chart not rendering when changing routes 2024-01-25 21:56:18 +01:00
sara-pervana
b98c6090af remove fake data in the header of dlg and ap views 2024-01-25 20:51:45 +01:00
42a25a2eda update ui-assets.nix
All checks were successful
checks-impure / test (push) Has been skipped
checks / test (push) Has been skipped
assets1 / test (push) Has been skipped
2024-01-25 14:08:59 +00:00
b6b2bfbee5 Merge pull request 'Fixed sidebar and did problem' (#72) from Qubasa-main into main
Some checks failed
checks-impure / test (push) Successful in 26s
checks / test (push) Successful in 1m14s
assets1 / test (push) Has been cancelled
Reviewed-on: #72
2024-01-25 15:06:37 +01:00
09f80b1f42 Fixed sidebar and did problem
All checks were successful
checks-impure / test (pull_request) Successful in 26s
checks / test (pull_request) Successful in 1m13s
2024-01-25 14:47:52 +01:00
170ada9382 Fixed sidebar and did problem 2024-01-25 14:47:37 +01:00
a8b472e84d update ui-assets.nix
All checks were successful
checks-impure / test (push) Has been skipped
checks / test (push) Has been skipped
assets1 / test (push) Has been skipped
2024-01-25 13:39:23 +00:00
Erdem-Arslan
cf3fc347de Merge pull request 'dynamic-routing-sidebar' (#71) from dynamic-routing-sidebar into main
Some checks failed
checks-impure / test (push) Successful in 26s
checks / test (push) Successful in 1m12s
assets1 / test (push) Has been cancelled
Reviewed-on: #71
2024-01-25 14:37:03 +01:00
Arslan, Erdem
1d39ebcddc fix formatting
All checks were successful
checks-impure / test (pull_request) Successful in 29s
checks / test (pull_request) Successful in 3m47s
2024-01-25 14:32:11 +01:00
Arslan, Erdem
d978e413d5 filter out AP and DLG entities 2024-01-25 14:08:52 +01:00
8d72268922 update ui-assets.nix
All checks were successful
checks-impure / test (push) Has been skipped
checks / test (push) Has been skipped
assets1 / test (push) Has been skipped
2024-01-25 01:03:29 +00:00
Sara Pervana
840b3b6972 Merge pull request 'A lot of Diagram Fixes as well as other code changes' (#70) from diagram-fixes into main
Some checks failed
checks-impure / test (push) Successful in 25s
checks / test (push) Successful in 1m11s
assets1 / test (push) Has been cancelled
Reviewed-on: #70
2024-01-25 02:01:10 +01:00
sara-pervana
db1591a76e final final tailwind fixes 2024-01-25 02:01:10 +01:00
sara-pervana
1d6ea0ef0c afain fixed tailwind classes 2024-01-25 02:01:10 +01:00
sara-pervana
711ade4866 fixing some failuers on build 2024-01-25 02:01:10 +01:00
sara-pervana
7779441c87 final fixes for the diagram 2024-01-25 02:01:10 +01:00
sara-pervana
8e92415c34 small change to readme 2024-01-25 02:01:10 +01:00
sara-pervana
68e2f6d683 removed warnings 2024-01-25 02:01:10 +01:00
sara-pervana
c03da10e98 current progress with diagram and project fixes 2024-01-25 02:01:10 +01:00
60205b3c22 Merge pull request 'fix src_name and des_name being NULL' (#69) from Qubasa-main into main
All checks were successful
checks-impure / test (push) Successful in 28s
checks / test (push) Successful in 3m50s
assets1 / test (push) Successful in 22s
Reviewed-on: #69
2024-01-24 23:50:25 +01:00
da99e71b54 fix src_name and des_name being NULL 2024-01-24 23:50:25 +01:00
b978aabdd6 update ui-assets.nix
All checks were successful
checks-impure / test (push) Has been skipped
checks / test (push) Has been skipped
assets1 / test (push) Has been skipped
2024-01-24 22:42:32 +00:00
357568ebcb Merge pull request 'Fixed upload script' (#68) from Qubasa-main into main
Some checks failed
checks-impure / test (push) Successful in 26s
checks / test (push) Successful in 1m18s
assets1 / test (push) Has been cancelled
Reviewed-on: #68
2024-01-24 23:40:08 +01:00
ea2be8b7c7 nix fmt
All checks were successful
checks-impure / test (pull_request) Successful in 29s
checks / test (pull_request) Successful in 3m53s
2024-01-24 23:33:28 +01:00
672c8364bc Fixed upload script 2024-01-24 23:33:02 +01:00
2b8a9d9316 Merge pull request 'Fixed wrong ordering of eventmessages' (#66) from Qubasa-main into main
All checks were successful
checks-impure / test (push) Successful in 26s
checks / test (push) Successful in 1m12s
assets1 / test (push) Successful in 22s
Reviewed-on: #66
2024-01-24 22:47:06 +01:00
9b6fc699f2 Added push_docker script
All checks were successful
checks-impure / test (pull_request) Successful in 28s
checks / test (pull_request) Successful in 3m47s
2024-01-24 22:41:29 +01:00
d232510c0e Added build_docker.sh script 2024-01-24 22:41:29 +01:00
dcaecba393 Fixed incorrect grouping, in eventmessages 2024-01-24 22:41:03 +01:00
7901712c4c update ui-assets.nix
All checks were successful
checks-impure / test (push) Has been skipped
checks / test (push) Has been skipped
assets1 / test (push) Has been skipped
2024-01-24 21:26:10 +00:00
Erdem-Arslan
48df7352da Merge pull request 'dynamic-routing-sidebar' (#67) from dynamic-routing-sidebar into main
Some checks failed
checks-impure / test (push) Successful in 26s
checks / test (push) Successful in 1m14s
assets1 / test (push) Has been cancelled
Reviewed-on: #67
2024-01-24 22:23:50 +01:00
Arslan, Erdem
c5c4ab7178 remove variable index within mapping
All checks were successful
checks-impure / test (pull_request) Successful in 26s
checks / test (pull_request) Successful in 3m10s
2024-01-24 22:19:46 +01:00
Arslan, Erdem
22bcbf6819 fix formatting
Some checks failed
checks-impure / test (pull_request) Successful in 27s
checks / test (pull_request) Failing after 1m51s
2024-01-24 22:14:19 +01:00
Arslan, Erdem
2ab2282116 implement dynamic routing within the sidebar 2024-01-24 22:12:00 +01:00
1c6e33e74f Merge pull request 'Fixed wrong ordering of eventmessages' (#65) from Qubasa-main into main
All checks were successful
checks-impure / test (push) Successful in 26s
checks / test (push) Successful in 1m13s
assets1 / test (push) Successful in 22s
Reviewed-on: #65
2024-01-24 18:51:56 +01:00
1757bf1952 Fixed wrong ordering of eventmessages 2024-01-24 18:51:56 +01:00
c726e4bb41 Merge pull request 'Improved links to API doc in README' (#64) from Qubasa-main into main
All checks were successful
checks-impure / test (push) Successful in 26s
checks / test (push) Successful in 1m14s
assets1 / test (push) Successful in 22s
Reviewed-on: #64
2024-01-24 18:04:07 +01:00
8a5232255f Improved links to API doc in README
All checks were successful
checks-impure / test (pull_request) Successful in 26s
checks / test (pull_request) Successful in 1m12s
2024-01-24 18:03:15 +01:00
674168160e Merge pull request 'Finished README for backend' (#63) from Qubasa-main into main
Some checks failed
checks-impure / test (push) Successful in 26s
checks / test (push) Successful in 1m11s
assets1 / test (push) Has been cancelled
Reviewed-on: #63
2024-01-24 18:02:20 +01:00
fba6dcb70a Finished README for backend
All checks were successful
checks-impure / test (pull_request) Successful in 25s
checks / test (pull_request) Successful in 1m16s
2024-01-24 17:53:46 +01:00
3c6cbe01e8 Merge pull request 'Fixed eventmessage formatting problem' (#62) from Qubasa-main into main
All checks were successful
checks-impure / test (push) Successful in 26s
checks / test (push) Successful in 1m13s
assets1 / test (push) Successful in 22s
Reviewed-on: #62
2024-01-24 16:52:16 +01:00
5aff0ec6f0 nix fmt
All checks were successful
checks-impure / test (pull_request) Successful in 26s
checks / test (pull_request) Successful in 3m41s
2024-01-24 16:32:02 +01:00
03f6318651 Fixed failing tests 2024-01-24 16:31:39 +01:00
11f4651814 nix fmt
Some checks failed
checks-impure / test (pull_request) Successful in 26s
checks / test (pull_request) Failing after 1m14s
2024-01-24 16:22:11 +01:00
1b433ea314 Fixed eventmessage formatting problem 2024-01-24 16:19:36 +01:00
894081a5c8 update ui-assets.nix
All checks were successful
checks-impure / test (push) Has been skipped
checks / test (push) Has been skipped
assets1 / test (push) Has been skipped
2024-01-23 11:23:55 +00:00
1f09701795 Merge pull request 'Made client/[name] generate static pages' (#61) from Qubasa-main into main
Some checks failed
checks-impure / test (push) Successful in 26s
checks / test (push) Successful in 1m12s
assets1 / test (push) Has been cancelled
2024-01-23 12:21:36 +01:00
2fb2a1d22a Fixed ui openapi.json bug. Reverted buildDir settings
All checks were successful
checks-impure / test (pull_request) Successful in 27s
checks / test (pull_request) Successful in 3m18s
2024-01-23 12:17:29 +01:00
6f4bab98c1 Made client/[name] generate static pages
All checks were successful
checks-impure / test (pull_request) Successful in 26s
checks / test (pull_request) Successful in 1m19s
2024-01-23 00:17:24 +01:00
Arslan, Erdem
ea0148fdaf formatting index.tsx 2024-01-21 21:56:03 +01:00
Arslan, Erdem
7ae1d5f768 create loading spinner for the consumer button 2024-01-21 21:34:53 +01:00
Arslan, Erdem
ec67dd1bac updating fetch request 2024-01-21 21:24:17 +01:00
Arslan, Erdem
522d7eb69a fetch the consume and register/deregister endpoints and add error handling 2024-01-21 21:15:51 +01:00
Arslan, Erdem
07a5a2fc24 Merge branch 'main' into register-deregister-actions
# Conflicts:
#	pkgs/ui/src/components/sequence_diagram/index.tsx
2024-01-21 20:45:24 +01:00
d54206f43c update ui-assets.nix
All checks were successful
checks-impure / test (push) Has been skipped
checks / test (push) Has been skipped
assets1 / test (push) Has been skipped
2024-01-21 18:40:02 +00:00
29ca34aaed Merge pull request 'Added docker file. Improved Documentation' (#60) from Qubasa-main into main
Some checks failed
checks-impure / test (push) Successful in 25s
checks / test (push) Successful in 1m21s
assets1 / test (push) Has been cancelled
2024-01-21 19:37:34 +01:00
79dbefcfe6 Added docker file. Improved Documentation
All checks were successful
checks-impure / test (pull_request) Successful in 26s
checks / test (pull_request) Successful in 1m23s
2024-01-21 19:30:48 +01:00
sara-pervana
59e33f3ead add register, deregister actions 2024-01-21 16:49:34 +01:00
a21d9c1bae Merge pull request 'Added nested create_eventmessages' (#59) from Qubasa-main into main
Some checks failed
checks-impure / test (push) Successful in 26s
checks / test (push) Failing after 2m44s
assets1 / test (push) Successful in 24s
2024-01-18 18:16:16 +01:00
17df0a6ac1 Added nested create_eventmessages
All checks were successful
checks-impure / test (pull_request) Successful in 26s
checks / test (pull_request) Successful in 1m15s
2024-01-18 18:10:22 +01:00
Georg-Stahn
047bee93c4 Merge pull request 'readmes added comments and some links to the openapi docs mds :)' (#58) from georgsdocs into main
All checks were successful
checks-impure / test (push) Successful in 27s
checks / test (push) Successful in 1m14s
assets1 / test (push) Successful in 22s
Reviewed-on: #58
2024-01-16 22:32:19 +01:00
Georg-Stahn
3052015a51 readmes added comments and some links to the openapi docs mds :)
All checks were successful
checks-impure / test (pull_request) Successful in 29s
checks / test (pull_request) Successful in 3m29s
2024-01-16 22:25:05 +01:00
01e98d363b update ui-assets.nix
All checks were successful
checks-impure / test (push) Has been skipped
checks / test (push) Has been skipped
assets1 / test (push) Has been skipped
2024-01-16 21:17:07 +00:00
Sara Pervana
407f569837 Merge pull request 'Added Sequence Diagram with Mermaid' (#51) from mermaid into main
Some checks failed
checks-impure / test (push) Successful in 26s
checks / test (push) Successful in 1m13s
assets1 / test (push) Has been cancelled
Reviewed-on: #51
2024-01-16 22:14:46 +01:00
sara-pervana
51859b148b final changes and fixes added 2024-01-16 22:14:46 +01:00
sara-pervana
13de134bb0 fixed height issue, fixed code for grouping in diagram 2024-01-16 22:14:46 +01:00
sara-pervana
9f03c187f3 some changes for the tailwind classes and turned the rule for custom classes off 2024-01-16 22:14:46 +01:00
sara-pervana
1db032e932 removed unnecessary style file and ran nix fmt 2024-01-16 22:14:46 +01:00
sara-pervana
7b2b675c2c added mermaid diagram 2024-01-16 22:14:46 +01:00
Onur Arslan
47700b7bd0 - installed dependencies for mermaid 2024-01-16 22:14:46 +01:00
e3813555cc Merge pull request 'Fix repository endpoint' (#57) from Qubasa-main into main
All checks were successful
checks-impure / test (push) Successful in 26s
checks / test (push) Successful in 1m12s
assets1 / test (push) Successful in 20s
2024-01-16 21:20:11 +01:00
36004c6151 Fix repository endpoint
All checks were successful
checks-impure / test (pull_request) Successful in 25s
checks / test (pull_request) Successful in 1m11s
2024-01-16 21:14:15 +01:00
957f99a906 update ui-assets.nix
All checks were successful
checks-impure / test (push) Has been skipped
checks / test (push) Has been skipped
assets1 / test (push) Has been skipped
2024-01-16 15:25:34 +00:00
f957e55aeb Merge pull request 'UI: Fixed exception in service view rendering' (#56) from Qubasa-main into main
Some checks failed
checks-impure / test (push) Successful in 26s
checks / test (push) Successful in 1m16s
assets1 / test (push) Has been cancelled
2024-01-16 16:23:14 +01:00
92e584cc5c Fixed unused var error
All checks were successful
checks-impure / test (pull_request) Successful in 26s
checks / test (pull_request) Successful in 2m55s
2024-01-16 16:19:44 +01:00
93084c360b UI: Fixed missing types
Some checks failed
checks-impure / test (pull_request) Successful in 25s
checks / test (pull_request) Failing after 2m2s
2024-01-15 19:56:24 +01:00
4918f84e85 UI: Fixed exception in service view rendering
Some checks failed
checks-impure / test (pull_request) Successful in 25s
checks / test (pull_request) Failing after 1m26s
2024-01-15 19:42:01 +01:00
422a3f4da1 update ui-assets.nix
All checks were successful
checks-impure / test (push) Has been skipped
checks / test (push) Has been skipped
assets1 / test (push) Has been skipped
2024-01-15 17:16:30 +00:00
1980204e82 Merge pull request 'Backend: Added action field' (#55) from Qubasa-main into main
Some checks failed
checks-impure / test (push) Successful in 25s
checks / test (push) Successful in 1m11s
assets1 / test (push) Has been cancelled
2024-01-15 18:14:12 +01:00
f46ed02435 Services and entites now have correct url to emulated servers
All checks were successful
checks-impure / test (pull_request) Successful in 26s
checks / test (pull_request) Successful in 1m11s
2024-01-15 18:08:31 +01:00
cb31fd79c8 Merge pull request 'Backend: Added action field' (#54) from Qubasa-main into main
All checks were successful
checks-impure / test (push) Successful in 26s
checks / test (push) Successful in 1m13s
assets1 / test (push) Successful in 20s
2024-01-15 17:23:01 +01:00
eb5eb1613f Added put service endpoint 2024-01-15 17:17:53 +01:00
d2af394fc7 Prettier ignores openapi markdown files now 2024-01-15 17:17:53 +01:00
26e594f94b Backend: Added action field 2024-01-15 17:17:53 +01:00
dfd7979baf Added put service endpoint
All checks were successful
checks-impure / test (pull_request) Successful in 27s
checks / test (pull_request) Successful in 1m11s
2024-01-15 17:17:17 +01:00
a8557ee039 Prettier ignores openapi markdown files now 2024-01-15 17:03:21 +01:00
eca63cb824 Backend: Added action field 2024-01-15 16:56:38 +01:00
2864ec20cc Merge pull request 'Added usage field to service' (#53) from Qubasa-main into main
All checks were successful
checks-impure / test (push) Successful in 26s
checks / test (push) Successful in 1m12s
assets1 / test (push) Successful in 22s
2024-01-15 16:11:04 +01:00
390ded6dff Fixed missing entity_did in ServiceBase
All checks were successful
checks-impure / test (pull_request) Successful in 2m28s
checks / test (pull_request) Successful in 10m45s
2024-01-15 15:57:31 +01:00
e47b0b4911 Added usage field to service
Some checks failed
checks-impure / test (pull_request) Successful in 25s
checks / test (pull_request) Failing after 1m56s
2024-01-14 17:01:14 +01:00
b8da1db58c Merge pull request 'Added AP get repository' (#52) from Qubasa-main into main
All checks were successful
checks-impure / test (push) Successful in 25s
checks / test (push) Successful in 1m23s
assets1 / test (push) Successful in 21s
2024-01-14 16:01:37 +01:00
7045f945c8 Fixed bug in validate schema
All checks were successful
checks-impure / test (pull_request) Successful in 26s
checks / test (pull_request) Successful in 3m17s
2024-01-14 15:57:30 +01:00
44797a0bc3 Get entity by did or name 2024-01-14 15:28:46 +01:00
52987625c8 Added AP get repository 2024-01-14 15:28:46 +01:00
8a3a593cc0 Merge pull request 'backend: Fully working roles field. Added get_entity_by_roles' (#50) from Qubasa-main into main
All checks were successful
checks-impure / test (push) Successful in 25s
checks / test (push) Successful in 1m18s
assets1 / test (push) Successful in 21s
2024-01-14 13:57:43 +01:00
106 changed files with 8165 additions and 1419 deletions

View File

@@ -58,7 +58,8 @@ jobs:
git commit -am "update ui-assets.nix"
echo "Current branch: $GITHUB_REF_NAME"
git push origin HEAD:$GITHUB_REF_NAME
git push origin HEAD:"$GITHUB_REF_NAME"
echo "Done uploading"
fi
else
echo "No UI files changed. Skipping asset build and push"

2
.gitignore vendored
View File

@@ -23,3 +23,5 @@ htmlcov
# georgs
pkgs/.vs/
pkgs/clan-cli/.hypothesis/
ui-assets.tar.gz
ui-release

12
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,12 @@
stages:
- release
release:
stage: release
script:
- set -x
- ./service-aware-network-front-end/pkgs/clan-cli/push_docker.sh
only:
- dev
tags:
- ea

146
README.md
View File

@@ -21,7 +21,7 @@ Let's get your development environment up and running:
1. **Install Nix Package Manager**:
- You can install the Nix package manager by either [downloading the Nix installer](https://github.com/DeterminateSystems/nix-installer/releases) or running this command:
- You can install the Nix package manager by running this command:
```bash
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install
```
@@ -34,7 +34,7 @@ sudo echo "experimental-features = nix-command flakes" > '/etc/nix/nix.conf'
2. **Install direnv**:
- Download the direnv package from [here](https://direnv.net/docs/installation.html) or run the following command:
- Install the direnv package by running the following command:
```bash
curl -sfL https://direnv.net/install.sh | bash
```
@@ -75,11 +75,20 @@ sudo echo "experimental-features = nix-command flakes" > '/etc/nix/nix.conf'
```bash
clan webui --reload --no-open --log-level debug --populate --emulate
```
- The server will automatically restart if any Python files change.
- The server will automatically restart if any Python files change. Emulated services however will not.
- The `--populate` flag will automatically populate the database with dummy data
- To look into the endpoints open up a swagger instance by visiting: http://localhost:2979/docs
- The `--emulate` flag will automatically run servers the database with dummy data for the fronted to communicate with (ap, dlg, c1 and c2)
- To look into the emulated endpoints go to http://localhost:2979/emulate
8. **Build the Frontend**:
8. **Detailed Backend Documentation**
- For detailed backend documentation go to [pkgs/clan-cli/README.md](pkgs/clan-cli/README.md)
- We explain:
- How to build and run a docker image
- Internal workings of the App
9. **Build the Frontend**:
- In a different shell, navigate to the `pkgs/ui` directory and execute:
```bash
@@ -87,31 +96,20 @@ sudo echo "experimental-features = nix-command flakes" > '/etc/nix/nix.conf'
```
- Wait for the frontend to build.
9. **Start the Frontend**:
- To start the frontend, execute:
```bash
npm run dev
```
- Access the website by going to [http://localhost:3000](http://localhost:3000).
10. **Start the Frontend**:
- To start the frontend, execute:
```bash
npm run dev
```
- Access the website by going to [http://localhost:3000](http://localhost:3000).
11. **Detailed Frontend Documentation**
- For detailed frontend documentation go to [pkgs/ui/README.md](pkgs/ui/README.md)
# Setting Up Your Git Workflow
Let's set up your Git workflow to collaborate effectively:
1. **Register Your Gitea Account Locally**:
- Execute the following command to add your Gitea account locally:
```bash
tea login add
```
- Go to https://gitea.gchq.icu/user/settings/applications and create token with all privileges
- Fill out the prompt as follows:
- URL of Gitea instance: `https://gitea.gchq.icu`
- Name of new Login [gitea.gchq.icu]: `gitea.gchq.icu:7171`
- Do you have an access token? Yes
- Token: \***\*\*\*\***
- Set Optional settings: No
2. **Git Workflow**:
1. Add your changes to Git using `git add <file1> <file2>`.
@@ -124,99 +122,3 @@ Let's set up your Git workflow to collaborate effectively:
5. Use `git status` to check for merge conflicts.
6. If conflicts exist, resolve them. Here's a tutorial for resolving conflicts in [VSCode](https://code.visualstudio.com/docs/sourcecontrol/overview#_merge-conflicts).
7. After resolving conflicts, execute `git merge --continue` and repeat step 5 until there are no conflicts.
3. **Create a Pull Request**:
- To automatically open a pull request that gets merged if all tests pass, execute:
```bash
merge-after-ci
```
- If it fails and says something along the lines off `[ERROR] fail-on-change` then the formatter complained.
Execute `nix fmt` from the project root by hand and then make a new git commit. Afterwards redo step 3 and it should work.
4. **Review Your Pull Request**:
- Visit https://gitea.gchq.icu and go to the project page. Check under "Pull Requests" for any issues with your pull request.
5. **Push Your Changes**:
- If there are issues, fix them and redo step 2. Afterward, execute:
```bash
git push origin HEAD:YourUsername-main
```
- This will directly push to your open pull request.
# Debugging
When working on the backend of your project, debugging is an essential part of the development process. Here are some methods for debugging and testing the backend of your application:
## Test Backend Locally in Devshell with Breakpoints
To test the backend locally in a development environment and set breakpoints for debugging, follow these steps:
1. Run the following command to execute your tests and allow for debugging with breakpoints:
```bash
pytest -n0 -s --maxfail=1
```
You can place `breakpoint()` in your Python code where you want to trigger a breakpoint for debugging.
## Test Backend Locally in a Nix Sandbox
To run your backend tests in a Nix sandbox, you have two options depending on whether your test functions have been marked as impure or not:
### Running Tests Marked as Impure
If your test functions need to execute `nix build` and have been marked as impure because you can't execute `nix build` inside a Nix sandbox, use the following command:
```bash
nix run .#impure-checks
```
This command will run the impure test functions.
### Running Pure Tests
For test functions that have not been marked as impure and don't require executing `nix build`, you can use the following command:
```bash
nix build .#checks.x86_64-linux.clan-pytest --rebuild
```
This command will run all pure test functions.
### Inspecting the Nix Sandbox
If you need to inspect the Nix sandbox while running tests, follow these steps:
1. Insert an endless sleep into your test code where you want to pause the execution. For example:
```python
import time
time.sleep(3600) # Sleep for one hour
```
2. Use `cntr` and `psgrep` to attach to the Nix sandbox. This allows you to interactively debug your code while it's paused. For example:
```bash
psgrep -a -x your_python_process_name
cntr attach <pid>
```
These debugging and testing methods will help you identify and fix issues in your backend code efficiently, ensuring the reliability and robustness of your application.
# Using this Template
To make the most of this template:
1. Set up a new Gitea account named `ui-asset-bot`. Generate an access token with all access permissions and set it under `settings/actions/secrets` as a secret called `BOT_ACCESS_TOKEN`.
- Also, edit the file `.gitea/workflows/ui_assets.yaml` and change the `BOT_EMAIL` variable to match the email you set for that account. Gitea matches commits to accounts by their email address, so this step is essential.
2. Create a second Gitea account named `merge-bot`. Edit the file `pkgs/merge-after-ci/default.nix` if the name should be different. Under "Branches," set the main branch to be protected and add `merge-bot` to the whitelisted users for pushing. Set the unprotected file pattern to `**/ui-assets.nix`.
- Enable the status check for "build / test (pull_request)."
3. Add both `merge-bot` and `ui-asset-bot` as collaborators.
- Set the option to "Delete pull request branch after merge by default."
- Also, set the default merge style to "Rebase then create merge commit."
With this template, you're well-equipped to build and collaborate on high-quality websites efficiently. Happy coding!.

View File

@@ -18,6 +18,8 @@
treefmt.settings.formatter.prettier.excludes = [
"secrets.yaml"
"key.json"
"keyfile.json"
"**/pkgs/clan-cli/tests/openapi_client/**"
];
treefmt.programs.mypy.enable = true;

View File

@@ -1,34 +1,333 @@
# clan-cli
# Starting The Backend
The clan-cli contains the command line interface as well as the graphical webui through the `clan webui` command.
## Hacking on the cli
Start the web ui with
We recommend setting up [direnv](https://direnv.net/) to load the developement with nix.
If you do not have it set up you can also use `nix develop` directly like this:
```
use flake .#clan-cli --builders ''
```bash
clan webui --reload --no-open --log-level debug --populate --emulate
```
After you can use the local bin wrapper to test things in the cli:
- The `--populate` flag will automatically populate the database with dummy data
- To look into the endpoints open up a swagger instance by visiting: http://localhost:2979/docs
- The `--emulate` flag will automatically run servers the database with dummy data for the fronted to communicate with (ap, dlg, c1 and c2)
- To look into the emulated endpoints go to http://localhost:2979/emulate
```
./bin/clan
# Using the Uploaded Docker Image
Pull the image
```bash
docker pull git.tu-berlin.de:5000/internet-of-services-lab/service-aware-network-front-end:latest
```
## Hacking on the webui
Run the image
By default the webui is build from a tarball available https://git.clan.lol/clan/-/packages/generic/ui/.
To start a local developement environment instead, use the `--dev` flag:
```
./bin/clan webui --dev
```bash
docker run -p 127.0.0.1:2979:2979 git.tu-berlin.de:5000/internet-of-services-lab/service-aware-network-front-end:latest
```
This will spawn two webserver, a python one to for the api and a nodejs one that rebuilds the ui on the fly.
# API Documentation
## Run webui directly
Api documentation can be found in the folder `pkgs/clan-cli/tests/openapi_client/docs/`
For Entity object go to
- [tests/openapi_client/docs/EntitiesApi.md](tests/openapi_client/docs/EntitiesApi.md)
- [tests/openapi_client/docs/EventmessagesApi.md](tests/openapi_client/docs/EventmessagesApi.md)
- [tests/openapi_client/docs/ServicesApi.md](tests/openapi_client/docs/ServicesApi.md)
- [tests/openapi_client/docs/ResolutionApi.md](tests/openapi_client/docs/ResolutionApi.md)
- [tests/openapi_client/docs/RepositoriesApi.md](tests/openapi_client/docs/RepositoriesApi.md)
# Building a Docker Image if the Frontend Changed
To build a new docker image when the frontend code and/or backend code changed you first need
to get the `GITLAB_TOKEN` go to [repo access tokens](https://git.tu-berlin.de/internet-of-services-lab/service-aware-network-front-end/-/settings/access_tokens) and generate one.
- Make sure the Gitlab token has access to package registry.
Then execute
```bash
export GITLAB_TOKEN="<your-access-token>"
```
Afterwards you can execute:
```bash
./build_docker.sh
```
This will create a symlink directory called `result` to a tar.gz docker file. Import it by executing:
```bash
docker load < result
```
And then run the docker file by executing:
```bash
docker run -p 127.0.0.1:2979:2979 clan-docker:latest
```
# Uploading a Docker Image
You can use the script:
```bash
./push_docker.sh
```
### The Script Explained
Login to the tu docker image server
```bash
docker login git.tu-berlin.de:5000
```
Tag the imported image
```bash
docker image tag clan-docker:latest git.tu-berlin.de:5000/internet-of-services-lab/service-aware-network-front-end:latest
```
Push the image to the git registry
```bash
docker image push git.tu-berlin.de:5000/internet-of-services-lab/service-aware-network-front-end:latest
```
# Upload UI assets as a package
To upload the release build UI assets to gitlab as a package
first get the `GITLAB_TOKEN`. Go to [repo access tokens](https://git.tu-berlin.de/internet-of-services-lab/service-aware-network-front-end/-/settings/access_tokens) and generate one.
- Make sure the Gitlab token has access to package registry.
To upload the UI assets as a package then execute:
```bash
./upload_ui_assets.sh
```
Please commit the changes to ui-assets.nix and push them to the repository.
If you want clan webui to use the new ui assets.
```bash
$ git commit -m "Update ui-assets.nix" "$PROJECT_DIR/pkgs/ui/nix/ui-assets.nix"
$ git push
```
If you execute `clan webui` the page you will see is a precompiled release version of the UI. This above script will update said precompiled release version. The `./build_docker.sh` script execute this to make sure that the included UI in the docker is up to date.
### The Script Explained
If changes to the UI have been made, and you want them to propagate to the docker container and the `clan webui` command edit the file: [../ui/nix/ui-assets.nix](../ui/nix/ui-assets.nix).
This is where a release version of the frontend is downloaded and integrated into the cli and the docker build. To do this first execute
```bash
nix build .#ui --out-link ui-release
```
Make a tarball out of it called `ui-assets.tar.gz`
```bash
tar --transform 's,^\.,assets,' -czvf "ui-assets.tar.gz" -C ui-release/result/lib/node_modules/*/out .
```
Upload ui-assets.tar.gz to gitlab.
```bash
curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
--upload-file ./ui-assets.tar.gz \
"https://git.tu-berlin.de/api/v4/projects/internet-of-services-lab%2Fservice-aware-network-front-end/packages/generic/ui-assets/1.0.0/ui-assets.tar.gz"
```
You can find your uploaded package at the [package registry](https://git.tu-berlin.de/internet-of-services-lab/service-aware-network-front-end/-/packages)
And export the download url into a variable:
```
export url="https://git.tu-berlin.de/api/v4/projects/internet-of-services-lab%2Fservice-aware-network-front-end/packages/generic/ui-assets/1.0.0/ui-assets.tar.gz"
```
Now execute the command:
```bash
cat > "../ui/nix/ui-assets.nix" <<EOF
{ fetchzip }:
fetchzip {
url = "$url";
sha256 = "$(nix-prefetch-url --unpack $url)";
}
EOF
```
And now build the docker image:
```bash
nix build .#clan-docker
```
# Building a Docker Image if only the Backend Changed
To build a new docker image only when the backend code changed execute:
```bash
nix build .#clan-docker
```
This is much faster then the `./build_docker.sh` script as it needs not to build the frontend and again.
This will create a symlink directory called `result` to a tar.gz docker file. Import it by executing:
```bash
docker load < result
```
And then run the docker file by executing:
```bash
docker run -p 127.0.0.1:2979:2979 clan-docker:latest
```
- To change parameters in the generated docker image edit the file :
[flake-module.nix at line 22](flake-module.nix)
- Documentation on `dockerTools.buildImage` you can find here: https://nix.dev/tutorials/nixos/building-and-running-docker-images.html
# Auto Generating a Python Client
For the tests we automatically generate a python client for the API endpoints. To do this execute while inside the `pkgs/clan-cli` folder:
```bash
./bin/gen-python-client
```
This will replace the folder
`tests/openapi_client`.
# Adding dependencies
**Dependency Management**: We use the [Nix package manager](https://nixos.org/) to manage dependencies and ensure reproducibility, making your development process more robust.
To add dependencies edit the file [default.nix](default.nix)
To search for a python dependency named "request" execute:
```bash
nix search nixpkgs#pythonPackages request
```
Add the depdendency at the top of the file
```nix
{
, mydep # <--- Add here
, websockets
, broadcaster
, aenum
, dateutil
, urllib3
}:
let
[...]
```
Add them into this array if they are a python dependency
```nix
dependencies = [
argcomplete
fastapi
uvicorn
sqlalchemy
websockets
broadcaster
mydep # <--- Add here
];
```
To search for a binary dependency named "firefox" execute:
```bash
nix search nixpkgs firefox
```
Runtime dependency add them into this array:
```nix
runtimeDependencies = [
bash
nix
fakeroot
zbar
git
mypy
];
```
# Development environment
The development environment created by `nix develop` or automatically by `direnv` is located at [shell.nix](shell.nix). The `shellHook` variable execute bash code.
# Debugging
When working on the backend of your project, debugging is an essential part of the development process. Here are some methods for debugging and testing the backend of your application:
## Test Backend Locally in Devshell with Breakpoints
To test the backend locally in a development environment and set breakpoints for debugging, follow these steps:
1. Run the following command to execute your tests and allow for debugging with breakpoints:
```bash
rm -f sql_app.db && pytest -s
```
You can place `breakpoint()` in your Python code where you want to trigger a breakpoint for debugging.
## Test Backend Locally in a Nix Sandbox
To run your backend tests in a Nix sandbox, you have two options depending on whether your test functions have been marked as impure or not:
### Running Tests Marked as Impure
If your test functions need to execute `nix build` and have been marked as impure because you can't execute `nix build` inside a Nix sandbox, use the following command:
```bash
nix run .#impure-checks
```
This command will run the impure test functions.
### Running Pure Tests
For test functions that have not been marked as impure and don't require executing `nix build`, you can use the following command:
```bash
nix build .#checks.x86_64-linux.clan-pytest --rebuild
```
This command will run all pure test functions.
### Inspecting the Nix Sandbox
If you need to inspect the Nix sandbox while running tests, follow these steps:
1. Insert an endless sleep into your test code where you want to pause the execution. For example:
```python
import time
time.sleep(3600) # Sleep for one hour
```
2. Use `cntr` and `psgrep` to attach to the Nix sandbox. This allows you to interactively debug your code while it's paused. For example:
```bash
psgrep -a -x your_python_process_name
cntr attach <pid>
```
These debugging and testing methods will help you identify and fix issues in your backend code efficiently, ensuring the reliability and robustness of your application.
## Run Web UI in VSCode
Useful for vscode run and debug option
@@ -53,18 +352,3 @@ Add this `launch.json` to your .vscode directory to have working breakpoints in
]
}
```
## Run locally single-threaded for debugging
By default tests run in parallel using pytest-xdist.
pytest-xdist however breaks `breakpoint()`. To disable it, use this:
```console
pytest -n0 -s
```
You can also run a single test like this:
```console
pytest -n0 -s tests/test_secrets_cli.py::test_users
```

16
pkgs/clan-cli/build_docker.sh Executable file
View File

@@ -0,0 +1,16 @@
#!/usr/bin/env bash
set -euo pipefail
PROJECT_DIR=$(git rev-parse --show-toplevel)
"$PROJECT_DIR"/pkgs/clan-cli/upload_ui_assets.sh
nix build .#clan-docker
cat <<EOF
==============================
Please commit the changes to ui-assets.nix and push them to the repository.
If you want clan webui to use the new ui assets.
$ git commit -m "Update ui-assets.nix" "$PROJECT_DIR/pkgs/ui/nix/ui-assets.nix"
$ git push
EOF

View File

@@ -0,0 +1,37 @@
**init\_**.py:
```bash
usage: clan webui [-h] [--port PORT] [--host HOST] [--populate] [--emulate] [--no-open] [--dev]
[--dev-port DEV_PORT] [--dev-host DEV_HOST] [--reload]
[--log-level {critical,error,warning,info,debug,trace}]
[sub_url]
positional arguments:
sub_url Sub URL to open in the browser
options:
-h, --help show this help message and exit
--port PORT Port to listen on
--host HOST Host to listen on
--populate Populate the database with dummy data
--emulate Emulate two entities c1 and c2 + dlg and ap
--no-open Don't open the browser
--dev Run in development mode
--dev-port DEV_PORT Port to listen on for the dev server
--dev-host DEV_HOST Host to listen on
--reload Don't reload on changes
--log-level {critical,error,warning,info,debug,trace}
Log level
```
In this folder are some basic files:
- config.py
- to configer basic value for the server and the emulation
- ip/host
- ports
- emuplate_fast.py
- some api call that emulate the behavoir
- extra servers with api calls are emulated here
In the subfolder <webui> is the backend impplemented.

View File

@@ -1,14 +1,18 @@
# Imports
import argparse
import logging
import sys
from types import ModuleType
from typing import Optional
# Custom imports
from . import webui
from .custom_logger import setup_logging
# Setting up the logger
log = logging.getLogger(__name__)
# Trying to import argcomplete module, if not present, set it to None
argcomplete: Optional[ModuleType] = None
try:
import argcomplete # type: ignore[no-redef]
@@ -16,44 +20,59 @@ except ImportError:
pass
# Function to create the main argument parser
def create_parser(prog: Optional[str] = None) -> argparse.ArgumentParser:
# Creating the main argument parser with a description
parser = argparse.ArgumentParser(prog=prog, description="cLAN tool")
# Adding a debug argument to enable debug logging
parser.add_argument(
"--debug",
help="Enable debug logging",
action="store_true",
)
# Adding subparsers for different commands
subparsers = parser.add_subparsers()
# Adding a subparser for the "webui" command
parser_webui = subparsers.add_parser("webui", help="start webui")
# Registering additional arguments for the "webui" command
webui.register_parser(parser_webui)
# Using argcomplete for shell autocompletion if available
if argcomplete:
argcomplete.autocomplete(parser)
# If no command-line arguments provided, print the help message
if len(sys.argv) == 1:
parser.print_help()
return parser
# this will be the entrypoint under /bin/clan (see pyproject.toml config)
### Main entry point function
def main() -> None:
# Creating the main argument parser
parser = create_parser()
# Parsing command-line arguments
args = parser.parse_args()
# Setting up logging based on the debug flag
if args.debug:
setup_logging(logging.DEBUG)
log.debug("Debug log activated")
else:
setup_logging(logging.INFO)
# If the parsed arguments do not have the "func" attribute, exit
if not hasattr(args, "func"):
return
# Calling the function associated with the specified command
args.func(args)
# Entry point for script execution
if __name__ == "__main__":
main()

View File

@@ -1,8 +1,88 @@
# CORS configuration
cors_url = [
"http://localhost",
"http://127.0.0.1",
"http://0.0.0.0",
"http://[::]",
]
cors_ports = ["*", 3000, 2979, 8001, 8002]
cors_whitelist = []
for u in cors_url:
for p in cors_ports:
cors_whitelist.append(f"{u}:{p}")
# host for the server, frontend, backend and emulators
host = "127.0.0.1"
# Used for eventmessage number to name mapping
group_type_to_label = {
1: {
"name": "Attachement",
1: "Request Send",
2: "Request Received",
3: "Response Send",
4: "Response Received",
},
2: {
"name": "Connection Setup",
1: "Request Send",
2: "Request Received",
3: "Response Send",
4: "Response Received",
},
3: {
"name": "Presentation",
1: "Request Send",
2: "Request Received",
3: "Respone Send",
4: "Respone Received",
5: "Respone Ack",
},
4: {
"name": "DID Resolution",
1: "Request Send",
2: "Request Received",
3: "Response Send",
4: "Response Received",
},
5: {
"name": "Service De-registration",
1: "Send",
2: "Received",
3: "Success Send",
4: "Success Received",
},
6: {
"name": "Service Registration",
1: "Send",
2: "Received",
3: "Success Send",
4: "Success Received",
},
7: {
"name": "Service Discovery",
1: "Discovery Send",
2: "Discovery Received",
3: "Result Send",
4: "Result Received",
},
8: {
"name": "Service Operation",
1: "Request Send",
2: "Request Received",
3: "Response Send",
4: "Response Received",
},
}
# Used for emulation and population for testing
port_dlg = 7000
port_ap = 7500
port_client_base = 8000
_port_client_base = 8000
c1_port = _port_client_base + 1
c2_port = _port_client_base + 2
dlg_url = f"http://{host}:{port_dlg}/docs"
ap_url = f"http://{host}:{port_ap}/docs"
c1_url = f"http://{host}:{port_client_base}/docs"
c2_url = f"http://{host}:{port_client_base + 1}/docs"
c1_url = f"http://{host}:{c1_port}/docs"
c2_url = f"http://{host}:{c2_port}/docs"

View File

@@ -1,28 +1,42 @@
# Importing necessary modules and packages
import sys
import time
import urllib
from datetime import datetime
# Importing FastAPI and related components
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import HTMLResponse, JSONResponse
# Importing configuration and schemas from the clan_cli package
import clan_cli.config as config
from clan_cli.webui.schemas import Resolution
# Creating FastAPI instances for different applications
app_dlg = FastAPI(swagger_ui_parameters={"tryItOutEnabled": True})
app_ap = FastAPI(swagger_ui_parameters={"tryItOutEnabled": True})
app_c1 = FastAPI(swagger_ui_parameters={"tryItOutEnabled": True})
app_c2 = FastAPI(swagger_ui_parameters={"tryItOutEnabled": True})
# List of FastAPI instances and their associated ports
apps = [
(app_dlg, config.port_dlg),
(app_ap, config.port_ap),
(app_c1, config.port_client_base),
(app_c2, config.port_client_base + 1),
(app_c1, config.c1_port),
(app_c2, config.c2_port),
]
for app, port in apps:
app.add_middleware(
CORSMiddleware,
allow_origins=config.cors_whitelist,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
#### HEALTHCHECK
# Healthcheck endpoints for different applications
@app_c1.get("/")
async def root_c1() -> str:
return "C1 is alive"
@@ -63,6 +77,7 @@ async def healthcheck_ap() -> str:
return "200 OK"
# Function for performing health checks on a given URL with retries
def get_health(*, url: str, max_retries: int = 20, delay: float = 0.2) -> str | None:
for attempt in range(max_retries):
try:
@@ -74,13 +89,10 @@ def get_health(*, url: str, max_retries: int = 20, delay: float = 0.2) -> str |
return None
#### CONSUME SERVICE
# TODO send_msg???
@app_c1.get("/consume_service_from_other_entity", response_class=HTMLResponse)
# Service consumption emulation for c1 which returns a gif1
@app_c1.get("/v1/print_daemon1", response_class=HTMLResponse)
async def consume_service_from_other_entity_c1() -> HTMLResponse:
# HTML content for the response
html_content = """
<html>
<body>
@@ -92,8 +104,21 @@ async def consume_service_from_other_entity_c1() -> HTMLResponse:
return HTMLResponse(content=html_content, status_code=200)
@app_c2.get("/consume_service_from_other_entity", response_class=HTMLResponse)
@app_c1.get("/v1/print_daemon1/register", response_class=JSONResponse)
async def register_c1() -> JSONResponse:
time.sleep(2)
return JSONResponse(content={"status": "registered"}, status_code=200)
@app_c1.get("/v1/print_daemon1/deregister", response_class=JSONResponse)
async def deregister_c1() -> JSONResponse:
time.sleep(2)
return JSONResponse(content={"status": "deregistered"}, status_code=200)
@app_c2.get("/v1/print_daemon2", response_class=HTMLResponse)
async def consume_service_from_other_entity_c2() -> HTMLResponse:
# Similar HTML content for the response
html_content = """
<html>
<body>
@@ -105,51 +130,113 @@ async def consume_service_from_other_entity_c2() -> HTMLResponse:
return HTMLResponse(content=html_content, status_code=200)
@app_c2.get("/v1/print_daemon2/register", response_class=JSONResponse)
async def register_c2() -> JSONResponse:
time.sleep(2)
return JSONResponse(content={"status": "registered"}, status_code=200)
@app_c2.get("/v1/print_daemon2/deregister", response_class=JSONResponse)
async def deregister_c2() -> JSONResponse:
time.sleep(2)
return JSONResponse(content={"status": "deregistered"}, status_code=200)
@app_ap.get("/ap_list_of_services", response_class=JSONResponse)
async def ap_list_of_services() -> JSONResponse:
# Sample list of services as a JSON response
res = [
# Service 1
{
"uuid": "98ae4334-6c12-ace8-ae34-0454cac5b68c",
"service_name": "Carlos Printing46",
"uuid": "bdd640fb-0667-1ad1-1c80-317fa3b1799d",
"service_name": "Carlos Printing0",
"service_type": "3D Printing",
"endpoint_url": "127.0.0.1:6600/v1/print_daemon46",
"status": "unknown",
"other": {"action": ["register", "deregister", "delete", "create"]},
"entity_did": "did:sov:test:6600",
"entity": {
"did": "did:sov:test:6600",
"name": "AP",
"ip": "127.0.0.1:6600",
"network": "255.255.0.0",
"visible": True,
"other": {},
"attached": False,
"stop_health_task": False,
"roles": ["AP"],
"endpoint_url": "http://127.0.0.1:8001/v1/print_daemon1",
"other": {},
"entity_did": "did:sov:test:120",
"status": {"data": ["draft", "registered"]},
"action": {
"data": [
{
"name": "register",
"endpoint": "http://127.0.0.1:8001/v1/print_daemon1/register",
},
{
"name": "deregister",
"endpoint": "http://127.0.0.1:8001/v1/print_daemon1/deregister",
},
]
},
"usage": [{"times_consumed": 2, "consumer_entity_did": "did:sov:test:120"}],
},
# Service 2 (similar structure)
{
"uuid": "23b8c1e9-3924-56de-3eb1-3b9046685257",
"service_name": "Carlos Printing1",
"service_type": "3D Printing",
"endpoint_url": "http://127.0.0.1:8002/v1/print_daemon2",
"other": {},
"entity_did": "did:sov:test:121",
"status": {"data": ["draft", "registered"]},
"action": {
"data": [
{
"name": "register",
"endpoint": "http://127.0.0.1:8002/v1/print_daemon2/register",
},
{
"name": "deregister",
"endpoint": "http://127.0.0.1:8002/v1/print_daemon2/deregister",
},
]
},
"usage": [{"times_consumed": 2, "consumer_entity_did": "did:sov:test:120"}],
},
{
"uuid": "988c24c9-61b1-cd22-6280-1c4510435a10",
"service_name": "Carlos Printing47",
"uuid": "bd9c66b3-ad3c-2d6d-1a3d-1fa7bc8960a9",
"service_name": "Carlos Printing2",
"service_type": "3D Printing",
"endpoint_url": "127.0.0.1:6600/v1/print_daemon47",
"status": "unknown",
"other": {"action": ["register", "deregister", "delete", "create"]},
"entity_did": "did:sov:test:6600",
"entity": {
"did": "did:sov:test:6600",
"name": "AP",
"ip": "127.0.0.1:6600",
"network": "255.255.0.0",
"visible": True,
"other": {},
"attached": False,
"stop_health_task": False,
"roles": ["AP"],
"endpoint_url": "http://127.0.0.1:8003/v1/print_daemon3",
"other": {},
"entity_did": "did:sov:test:122",
"status": {"data": ["draft", "registered"]},
"action": {
"data": [
{
"name": "register",
"endpoint": "http://127.0.0.1:8003/v1/print_daemon3/register",
},
{
"name": "deregister",
"endpoint": "http://127.0.0.1:8003/v1/print_daemon3/deregister",
},
]
},
"usage": [{"times_consumed": 2, "consumer_entity_did": "did:sov:test:120"}],
},
{
"uuid": "972a8469-1641-9f82-8b9d-2434e465e150",
"service_name": "Carlos Printing3",
"service_type": "3D Printing",
"endpoint_url": "http://127.0.0.1:8004/v1/print_daemon4",
"other": {},
"entity_did": "did:sov:test:123",
"status": {"data": ["draft", "registered"]},
"action": {
"data": [
{
"name": "register",
"endpoint": "http://127.0.0.1:8004/v1/print_daemon4/register",
},
{
"name": "deregister",
"endpoint": "http://127.0.0.1:8004/v1/print_daemon4/deregister",
},
]
},
"usage": [{"times_consumed": 2, "consumer_entity_did": "did:sov:test:120"}],
},
]
# resp = json.dumps(obj=res)
return JSONResponse(content=res, status_code=200)

View File

@@ -0,0 +1,6 @@
Here are the files found for the backend of the service.
- the backed is using a sql light db with sqlachremy
- this is done in
- sql\_\*.py, schema.py, tags.py
- subfolder: routers which also contains the apicall defenitions

View File

@@ -2,25 +2,55 @@ import argparse
import logging
from typing import Callable, NoReturn, Optional
# Get the logger for this module
log = logging.getLogger(__name__)
# Initialize variables for server startup and potential ImportError
start_server: Optional[Callable] = None
ServerImportError: Optional[ImportError] = None
# Try importing the start_server function from the server module
try:
from .server import start_server
except ImportError as e:
# If ImportError occurs, log the exception and store it in ServerImportError
log.exception(e)
ServerImportError = e
# Function to be called when FastAPI is not installed
##########################################################################################
# usage: clan webui [-h] [--port PORT] [--host HOST] [--populate] [--emulate] [--no-open] [--dev]
# [--dev-port DEV_PORT] [--dev-host DEV_HOST] [--reload]
# [--log-level {critical,error,warning,info,debug,trace}]
# [sub_url]
#
# positional arguments:
# sub_url Sub URL to open in the browser
#
# options:
# -h, --help show this help message and exit
# --port PORT Port to listen on
# --host HOST Host to listen on
# --populate Populate the database with dummy data
# --emulate Emulate two entities c1 and c2 + dlg and ap
# --no-open Don't open the browser
# --dev Run in development mode
# --dev-port DEV_PORT Port to listen on for the dev server
# --dev-host DEV_HOST Host to listen on
# --reload Don't reload on changes
# --log-level {critical,error,warning,info,debug,trace}
# Log level
##########################################################################################
def fastapi_is_not_installed(_: argparse.Namespace) -> NoReturn:
assert ServerImportError is not None
print(
f"Dependencies for the webserver is not installed. The webui command has been disabled ({ServerImportError})"
f"Dependencies for the webserver are not installed. The webui command has been disabled ({ServerImportError})"
)
exit(1)
# Function to register command-line arguments for the webserver
def register_parser(parser: argparse.ArgumentParser) -> None:
parser.add_argument("--port", type=int, default=2979, help="Port to listen on")
parser.add_argument(
@@ -69,10 +99,10 @@ def register_parser(parser: argparse.ArgumentParser) -> None:
type=str,
default="/",
nargs="?",
help="Sub url to open in the browser",
help="Sub URL to open in the browser",
)
# Set the args.func variable in args
# Set the args.func variable in args based on whether FastAPI is installed
if start_server is None:
parser.set_defaults(func=fastapi_is_not_installed)
else:

View File

@@ -1,55 +1,46 @@
# Imports
import logging
from contextlib import asynccontextmanager
from typing import Any
# import for sql
# Import FastAPI components and SQLAlchemy related modules
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.routing import APIRoute
from fastapi.staticfiles import StaticFiles
from sqlalchemy.exc import SQLAlchemyError
# Import configs
from ..config import cors_ports, cors_url
# Import custom modules and classes
from ..errors import ClanError
from . import sql_models
from .assets import asset_path
from .error_handlers import clan_error_handler, sql_error_handler
from .routers import endpoints, health, root, socket_manager2 # sql router hinzufügen
from .routers import endpoints, health, root
from .sql_db import engine
from .tags import tags_metadata
cors_url = [
"http://localhost",
"http://127.0.0.1",
"http://0.0.0.0",
"http://[::]",
]
cors_ports = [2979, 3000]
cors_whitelist = []
for u in cors_url:
for p in cors_ports:
cors_whitelist.append(f"{u}:{p}")
# Logging setup
log = logging.getLogger(__name__)
@asynccontextmanager
async def lifespan(app: FastAPI) -> Any:
await socket_manager2.brd.connect()
yield
await socket_manager2.brd.disconnect()
# Function to set up and configure the FastAPI application
def setup_app() -> FastAPI:
# bind sql engine
# TODO comment aut and add flag to run with pupulated data rm *.sql run pytest with marked then start clan webui
# https://docs.pytest.org/en/7.1.x/example/markers.html
# Uncomment the following line to drop existing tables during startup (if needed)
# sql_models.Base.metadata.drop_all(engine)
# Create tables in the database using SQLAlchemy
sql_models.Base.metadata.create_all(bind=engine)
app = FastAPI(lifespan=lifespan, swagger_ui_parameters={"tryItOutEnabled": True})
# Initialize FastAPI application with lifespan management
app = FastAPI(swagger_ui_parameters={"tryItOutEnabled": True})
# Configure CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=cors_whitelist,
@@ -58,31 +49,35 @@ def setup_app() -> FastAPI:
allow_headers=["*"],
)
# Include routers for various endpoints and components
app.include_router(health.router)
# sql methodes
app.include_router(endpoints.router)
app.include_router(socket_manager2.router)
# Needs to be last in register. Because of wildcard route
# Needs to be last in registration due to wildcard route
app.include_router(root.router)
# Add custom exception handlers
app.add_exception_handler(ClanError, clan_error_handler) # type: ignore
app.add_exception_handler(SQLAlchemyError, sql_error_handler) # type: ignore
# Mount the "static" route for serving static files
app.mount("/static", StaticFiles(directory=asset_path()), name="static")
# Add tag descriptions to the OpenAPI schema
app.openapi_tags = tags_metadata
# Assign operation IDs to API routes
for route in app.routes:
if isinstance(route, APIRoute):
route.operation_id = route.name # in this case, 'read_items'
log.debug(f"Registered route: {route}")
# Log registered exception handlers
for i in app.exception_handlers.items():
log.debug(f"Registered exception handler: {i}")
return app
# Create an instance of the FastAPI application
app = setup_app()

View File

@@ -0,0 +1,13 @@
from enum import Enum
class Status(Enum):
ONLINE = "online"
OFFLINE = "offline"
UNKNOWN = "unknown"
class Role(Enum):
PROSUMER = "service_prosumer"
AP = "AP"
DLG = "DLG"

View File

@@ -0,0 +1 @@
In the <endpoints.py> are the api endpoints implemented which could be used of the user/s.

View File

@@ -1,12 +1,17 @@
import json
import logging
import time
import typing
from collections import OrderedDict
from typing import Any, List, Optional
import httpx
from fastapi import APIRouter, BackgroundTasks, Depends, Query
from fastapi.responses import HTMLResponse
from fastapi.responses import HTMLResponse, PlainTextResponse
from sqlalchemy.orm import Session
from clan_cli.config import ap_url, c1_url, c2_url, dlg_url, group_type_to_label
from ...errors import ClanError
from .. import sql_crud, sql_db, sql_models
from ..schemas import (
@@ -18,6 +23,7 @@ from ..schemas import (
Role,
Service,
ServiceCreate,
ServiceUsageCreate,
)
from ..tags import Tags
@@ -26,17 +32,58 @@ router = APIRouter()
log = logging.getLogger(__name__)
# API Endpoints for all tables
# see the default api documentation under:
### pkgs/clan-cli/tests/openapi_client/docs/DefaultApi.md
#########################
# #
# Service #
# #
#########################
# see the corresponding documentation under:
### pkgs/clan-cli/tests/openapi_client/docs/Service.md
### pkgs/clan-cli/tests/openapi_client/docs/ServiceCreate.md
### pkgs/clan-cli/tests/openapi_client/docs/ServiceUsageCreate.md
### pkgs/clan-cli/tests/openapi_client/docs/ServicesApi.md
@router.post("/api/v1/service", response_model=Service, tags=[Tags.services])
def create_service(
service: ServiceCreate, db: Session = Depends(sql_db.get_db)
) -> Service:
# todo checken ob schon da ...
return sql_crud.create_service(db=db, service=service)
services = sql_crud.create_service(db=db, service=service)
return services
@router.post("/api/v1/service_usage", response_model=Service, tags=[Tags.services])
def add_service_usage(
usage: ServiceUsageCreate,
service_uuid: str = "bdd640fb-0667-1ad1-1c80-317fa3b1799d",
db: Session = Depends(sql_db.get_db),
) -> Service:
service = sql_crud.add_service_usage(db, service_uuid, usage)
return service
@router.put("/api/v1/inc_service_usage", response_model=Service, tags=[Tags.services])
def inc_service_usage(
usage: ServiceUsageCreate,
consumer_entity_did: str = "did:sov:test:120",
service_uuid: str = "bdd640fb-0667-1ad1-1c80-317fa3b1799d",
db: Session = Depends(sql_db.get_db),
) -> Service:
service = sql_crud.increment_service_usage(db, service_uuid, consumer_entity_did)
return service
@router.put("/api/v1/service", response_model=Service, tags=[Tags.services])
def update_service(
service: ServiceCreate,
uuid: str = "bdd640fb-0667-1ad1-1c80-317fa3b1799d",
db: Session = Depends(sql_db.get_db),
) -> Service:
service = sql_crud.set_service(db, uuid, service)
return service
@router.get("/api/v1/services", response_model=List[Service], tags=[Tags.services])
@@ -47,7 +94,9 @@ def get_all_services(
return services
@router.get("/api/v1/service", response_model=List[Service], tags=[Tags.services])
@router.get(
"/api/v1/service_by_did", response_model=List[Service], tags=[Tags.services]
)
def get_service_by_did(
entity_did: str = "did:sov:test:120",
skip: int = 0,
@@ -58,6 +107,17 @@ def get_service_by_did(
return service
@router.get("/api/v1/service", response_model=Service, tags=[Tags.services])
def get_service_by_uuid(
uuid: str = "bdd640fb-0667-1ad1-1c80-317fa3b1799d",
skip: int = 0,
limit: int = 100,
db: Session = Depends(sql_db.get_db),
) -> Optional[sql_models.Service]:
service = sql_crud.get_service_by_uuid(db, uuid=uuid)
return service
@router.get(
"/api/v1/services_without_entity",
response_model=List[Service],
@@ -87,6 +147,10 @@ def delete_service(
# Entity #
# #
#########################
# see the corresponding documentation under:
### pkgs/clan-cli/tests/openapi_client/docs/Entity.md
### pkgs/clan-cli/tests/openapi_client/docs/EntityCreate.md
### pkgs/clan-cli/tests/openapi_client/docs/EntitiesApi.md
@router.post("/api/v1/entity", response_model=Entity, tags=[Tags.entities])
def create_entity(
entity: EntityCreate, db: Session = Depends(sql_db.get_db)
@@ -104,6 +168,14 @@ def get_entity_by_roles(
return entity
@router.get("/api/v1/entity_by_role", response_model=List[Entity], tags=[Tags.entities])
def get_entity_by_role(
role: Role, db: Session = Depends(sql_db.get_db)
) -> List[sql_models.Entity]:
entity = sql_crud.get_entity_by_role(db, roles=[role])
return entity
@router.get("/api/v1/entities", response_model=List[Entity], tags=[Tags.entities])
def get_all_entities(
skip: int = 0, limit: int = 100, db: Session = Depends(sql_db.get_db)
@@ -112,7 +184,7 @@ def get_all_entities(
return entities
@router.get("/api/v1/entity", response_model=Optional[Entity], tags=[Tags.entities])
@router.get("/api/v1/entity", response_model=Entity, tags=[Tags.entities])
def get_entity_by_did(
entity_did: str = "did:sov:test:120",
db: Session = Depends(sql_db.get_db),
@@ -141,9 +213,6 @@ def detach_entity(
limit: int = 100,
db: Session = Depends(sql_db.get_db),
) -> dict[str, str]:
entity = sql_crud.get_entity_by_did(db, did=entity_did)
if entity is None:
raise ClanError(f"Entity with did '{entity_did}' not found")
sql_crud.set_stop_health_task(db, entity_did, True)
return {"message": f"Detached {entity_did} successfully"}
@@ -231,6 +300,8 @@ def get_rpc_by_role(db: Session, role: Role, path: str) -> Any:
raise ClanError(f"No {role} found")
if len(matching_entities) > 1:
raise ClanError(f"More than one {role} found")
if len(matching_entities) == 0:
raise ClanError(f"No {role} found")
dlg = matching_entities[0]
url = f"http://{dlg.ip}/{path}"
@@ -250,6 +321,9 @@ def get_rpc_by_role(db: Session, role: Role, path: str) -> Any:
# Resolution #
# #
#########################
# see the corresponding documentation under:
### pkgs/clan-cli/tests/openapi_client/docs/Resolution.md
### pkgs/clan-cli/tests/openapi_client/docs/ResolutionApi.md
@router.get(
"/api/v1/resolutions", response_model=List[Resolution], tags=[Tags.resolutions]
)
@@ -264,6 +338,8 @@ def get_all_resolutions(
# Repository #
# #
#########################
# see the corresponding documentation under:
### pkgs/clan-cli/tests/openapi_client/docs/RepositoriesApi.md
@router.get(
"/api/v1/repositories", tags=[Tags.repositories], response_model=List[Service]
)
@@ -278,6 +354,10 @@ def get_all_repositories(
# Eventmessage #
# #
#########################
# see the corresponding documentation under:
### pkgs/clan-cli/tests/openapi_client/docs/Eventmessage.md
### pkgs/clan-cli/tests/openapi_client/docs/EventmessageCreate.md
### pkgs/clan-cli/tests/openapi_client/docs/EventmessageApi.md
@router.post(
"/api/v1/event_message", response_model=Eventmessage, tags=[Tags.eventmessages]
)
@@ -287,16 +367,75 @@ def create_eventmessage(
return sql_crud.create_eventmessage(db, eventmsg)
@typing.no_type_check
@router.get(
"/api/v1/event_messages",
response_model=List[Eventmessage],
response_class=PlainTextResponse,
tags=[Tags.eventmessages],
)
def get_all_eventmessages(
skip: int = 0, limit: int = 100, db: Session = Depends(sql_db.get_db)
) -> List[sql_models.Eventmessage]:
) -> PlainTextResponse:
# SQL sorts eventmessages by timestamp, so we don't need to sort them here
eventmessages = sql_crud.get_eventmessages(db, skip=skip, limit=limit)
return eventmessages
cresult: List[OrderedDict[int, OrderedDict[int, List[Eventmessage]]]] = []
cresult_idx = 0
cresult.append(OrderedDict())
for idx, msg in enumerate(eventmessages):
# Use the group_type_to_label from config.py to get the group name and msg_type name
group = group_type_to_label.get(msg.group, None)
group_name = (
str(group.get("name", None)) if group is not None else str(msg.group)
)
msg_type_name = (
group.get(msg.msg_type, None) if group is not None else str(msg.msg_type)
)
# Get the name of the src and des entity from the database
src_name = sql_crud.get_entity_by_did(db, msg.src_did)
src_name = msg.src_did if src_name is None else src_name.name
des_name = sql_crud.get_entity_by_did(db, msg.des_did)
des_name = msg.des_did if des_name is None else des_name.name
result = cresult[cresult_idx]
if result.get("group_name") is None:
# Initialize the result array and dictionary
result["group_name"] = group_name
elif result["group_name"] != group_name:
# If the group name changed, create a new result array and dictionary
cresult_idx += 1
cresult.append(OrderedDict())
result = cresult[cresult_idx]
result["group_name"] = group_name
if result.get("groups") is None:
result["groups"] = OrderedDict()
if result["groups"].get(msg.group_id) is None:
result["groups"][msg.group_id] = []
# Append the eventmessage to the result array
result_arr = result["groups"][msg.group_id]
result_arr.append(
Eventmessage(
id=msg.id,
timestamp=msg.timestamp,
group=msg.group,
group_name=group_name,
group_id=msg.group_id,
msg_type=msg.msg_type,
msg_type_name=msg_type_name,
src_did=msg.src_did,
src_name=src_name,
des_did=msg.des_did,
des_name=des_name,
msg=msg.msg,
).dict()
)
return PlainTextResponse(content=json.dumps(cresult, indent=4), status_code=200)
##############################
@@ -305,10 +444,7 @@ def get_all_eventmessages(
# #
##############################
@router.get("/emulate", response_class=HTMLResponse)
@router.get("/emu", response_class=HTMLResponse)
def get_emulated_enpoints() -> HTMLResponse:
from clan_cli.config import ap_url, c1_url, c2_url, dlg_url
html_content = f"""
<html>
<head>

View File

@@ -1,52 +0,0 @@
# Requires: `starlette`, `uvicorn`, `jinja2`
# Run with `uvicorn example:app`
import logging
import os
import anyio
from broadcaster import Broadcast
from fastapi import APIRouter, WebSocket
from fastapi.responses import HTMLResponse
log = logging.getLogger(__name__)
router = APIRouter()
brd = Broadcast("memory://")
@router.get("/ws2_example")
async def get() -> HTMLResponse:
html = open(f"{os.getcwd()}/webui/routers/messenger.html").read()
return HTMLResponse(html)
@router.websocket("/ws2")
async def chatroom_ws(websocket: WebSocket) -> None:
await websocket.accept()
async with anyio.create_task_group() as task_group:
# run until first is complete
async def run_chatroom_ws_receiver() -> None:
await chatroom_ws_receiver(websocket=websocket)
task_group.cancel_scope.cancel()
task_group.start_soon(run_chatroom_ws_receiver)
log.warning("Started chatroom_ws_sender")
await chatroom_ws_sender(websocket)
async def chatroom_ws_receiver(websocket: WebSocket) -> None:
async for message in websocket.iter_text():
log.warning(f"Received message: {message}")
await brd.publish(channel="chatroom", message=message)
async def chatroom_ws_sender(websocket: WebSocket) -> None:
async with brd.subscribe(channel="chatroom") as subscriber:
if subscriber is None:
log.error("Subscriber is None")
return
async for event in subscriber: # type: ignore
await websocket.send_text(event.message)

View File

@@ -1,30 +1,30 @@
# Imports
import logging
from datetime import datetime
from enum import Enum
from typing import List
from typing import List, Optional
from pydantic import BaseModel, Field, validator
from . import sql_models
from .db_types import Role, Status
# Set logger
log = logging.getLogger(__name__)
class Status(Enum):
ONLINE = "online"
OFFLINE = "offline"
UNKNOWN = "unknown"
class Role(Enum):
PROSUMER = "service_prosumer"
AP = "AP"
DLG = "DLG"
# create basemodel
class Machine(BaseModel):
name: str
status: Status
### Create database schema for sql
# each section will represent an own table
# Entity, Service, Resolution, Eventmessages
# The relation between them is as follows:
# one Entity can have many Services
#########################
# #
# Entity #
@@ -72,8 +72,12 @@ class Entity(EntityBase):
# define a custom getter function for roles
@validator("roles", pre=True)
def get_roles(cls, v: List[EntityRoles | Role]) -> List[Role]:
if isinstance(v, list) and len(v) > 0 and isinstance(v[0], EntityRoles):
def get_roles(cls, v: List[sql_models.EntityRoles | Role]) -> List[Role]:
if (
isinstance(v, list)
and len(v) > 0
and isinstance(v[0], sql_models.EntityRoles)
):
return [x.role for x in v] # type: ignore
else:
return v # type: ignore
@@ -84,30 +88,50 @@ class Entity(EntityBase):
# Service #
# #
#########################
class ServiceUsageBase(BaseModel):
times_consumed: int = Field(..., example=2)
class ServiceUsageCreate(ServiceUsageBase):
consumer_entity_did: str = Field(..., example="did:sov:test:120")
class ServiceUsage(ServiceUsageCreate):
class Config:
orm_mode = True
class ServiceBase(BaseModel):
uuid: str = Field(..., example="8e285c0c-4e40-430a-a477-26b3b81e30df")
uuid: str = Field(..., example="bdd640fb-0667-1ad1-1c80-317fa3b1799d")
service_name: str = Field(..., example="Carlos Printing")
service_type: str = Field(..., example="3D Printing")
endpoint_url: str = Field(..., example="http://127.0.0.1:8000")
status: str = Field(..., example="unknown")
other: dict = Field(
..., example={"action": ["register", "deregister", "delete", "create"]}
other: dict = Field(..., example={"test": "test"})
entity_did: str = Field(..., example="did:sov:test:120")
status: dict = Field(..., example={"data": ["draft", "registered"]})
action: dict = Field(
...,
example={
"data": [
{"name": "register", "path": "/register"},
{"name": "deregister", "path": "/deregister"},
]
},
)
class ServiceCreate(ServiceBase):
entity_did: str = Field(..., example="did:sov:test:120")
usage: List[ServiceUsageCreate]
class Service(ServiceCreate):
entity: Entity
class Service(ServiceBase):
usage: List[ServiceUsage]
class Config:
orm_mode = True
class ServicesByName(BaseModel):
entity: Entity
services: List[Service]
class Config:
@@ -149,7 +173,7 @@ class EventmessageBase(BaseModel):
..., example=12345
) # specific to one group needed to enable visually nested groups
msg_type: int = Field(..., example=1) # message type for the label
src_did: str = Field(..., example="did:sov:test:2234")
src_did: str = Field(..., example="did:sov:test:121")
des_did: str = Field(..., example="did:sov:test:120")
@@ -159,6 +183,10 @@ class EventmessageCreate(EventmessageBase):
class Eventmessage(EventmessageCreate):
id: int = Field(...)
des_name: Optional[str] = Field(default=None, example="C2")
src_name: Optional[str] = Field(default=None, example="C1")
msg_type_name: Optional[str] = Field(default=None, example="Request Send")
group_name: Optional[str] = Field(default=None, example="Presentation")
class Config:
orm_mode = True

View File

@@ -1,3 +1,4 @@
# Imports
import argparse
import logging
import multiprocessing as mp
@@ -10,7 +11,6 @@ from pathlib import Path
from threading import Thread
from typing import Iterator
# XXX: can we dynamically load this using nix develop?
import uvicorn
from pydantic import AnyUrl, IPvAnyAddress
from pydantic.tools import parse_obj_as
@@ -19,9 +19,11 @@ import clan_cli.config as config
from clan_cli.emulate_fastapi import apps, get_health
from clan_cli.errors import ClanError
# Setting up logging
log = logging.getLogger(__name__)
# Function to open the browser for a specified URL
def open_browser(base_url: AnyUrl, sub_url: str) -> None:
for i in range(5):
try:
@@ -33,6 +35,7 @@ def open_browser(base_url: AnyUrl, sub_url: str) -> None:
_open_browser(url)
# Helper function to open a web browser for a given URL using available browsers
def _open_browser(url: AnyUrl) -> subprocess.Popen:
for browser in ("firefox", "iceweasel", "iceape", "seamonkey"):
if shutil.which(browser):
@@ -52,6 +55,7 @@ def _open_browser(url: AnyUrl) -> subprocess.Popen:
raise ClanError("No browser found")
# Context manager to spawn the Node.js development server
@contextmanager
def spawn_node_dev_server(host: IPvAnyAddress, port: int) -> Iterator[None]:
log.info("Starting node dev server...")
@@ -78,6 +82,7 @@ def spawn_node_dev_server(host: IPvAnyAddress, port: int) -> Iterator[None]:
proc.terminate()
# Main function to start the server
def start_server(args: argparse.Namespace) -> None:
with ExitStack() as stack:
headers: list[tuple[str, str]] = []
@@ -115,6 +120,7 @@ def start_server(args: argparse.Namespace) -> None:
sql_models.Base.metadata.drop_all(engine)
if args.populate:
# pre populate the server with some test data
test_dir = Path(__file__).parent.parent.parent / "tests"
if not test_dir.is_dir():

View File

@@ -1,27 +1,130 @@
# Imports
from typing import List, Optional
from sqlalchemy import func
from sqlalchemy import asc, func
from sqlalchemy.orm import Session
from sqlalchemy.sql.expression import true
from ..errors import ClanError
from . import schemas, sql_models
# Functions to manipulate the tables of the database
#########################
# #
# service #
# #
#########################
def create_service(db: Session, service: schemas.ServiceCreate) -> sql_models.Service:
db_service = sql_models.Service(**service.dict())
if get_entity_by_did(db, service.entity_did) is None:
raise ClanError(f"Entity with did '{service.entity_did}' not found")
if get_service_by_uuid(db, service.uuid) is not None:
raise ClanError(f"Service with uuid '{service.uuid}' already exists")
db_service = sql_models.Service(
uuid=service.uuid,
service_name=service.service_name,
service_type=service.service_type,
endpoint_url=service.endpoint_url,
status=service.status,
other=service.other,
entity_did=service.entity_did,
action=service.action,
)
db_usage = []
for usage in service.usage:
db_usage.append(
sql_models.ServiceUsage(
times_consumed=usage.times_consumed,
consumer_entity_did=usage.consumer_entity_did,
)
)
db_service.usage = db_usage
db.add(db_service)
db.commit()
db.refresh(db_service)
return db_service
def set_service_usage(
db: Session, service_uuid: str, usages: List[schemas.ServiceUsageCreate]
) -> sql_models.Service:
db_service = get_service_by_uuid(db, service_uuid)
if db_service is None:
raise ClanError(f"Service with uuid '{service_uuid}' not found")
db_usage = []
for usage in usages:
db_usage.append(
sql_models.ServiceUsage(
times_consumed=usage.times_consumed,
consumer_entity_did=usage.consumer_entity_did,
)
)
db_service.usage = db_usage
db.add(db_service)
db.commit()
db.refresh(db_service)
return db_service
def set_service(
db: Session, service_uuid: str, service: schemas.ServiceCreate
) -> sql_models.Service:
db_service = get_service_by_uuid(db, service_uuid)
if db_service is None:
raise ClanError(f"Service with uuid '{service_uuid}' not found")
db_service.service_name = service.service_name # type: ignore
db_service.service_type = service.service_type # type: ignore
db_service.endpoint_url = service.endpoint_url # type: ignore
db_service.status = service.status # type: ignore
db_service.other = service.other # type: ignore
db_service.entity_did = service.entity_did # type: ignore
db_service.action = service.action # type: ignore
db.add(db_service)
db.commit()
db.refresh(db_service)
return db_service
def add_service_usage(
db: Session, service_uuid: str, usage: schemas.ServiceUsageCreate
) -> sql_models.Service:
db_service = get_service_by_uuid(db, service_uuid)
if db_service is None:
raise ClanError(f"Service with uuid '{service_uuid}' not found")
db_service.usage.append(
sql_models.ServiceUsage(
times_consumed=usage.times_consumed,
consumer_entity_did=usage.consumer_entity_did,
)
)
db.add(db_service)
db.commit()
db.refresh(db_service)
return db_service
def increment_service_usage(
db: Session, service_uuid: str, consumer_entity_did: str
) -> sql_models.ServiceUsage:
db_service = get_service_by_uuid(db, service_uuid)
if db_service is None:
raise ClanError(f"Service with uuid '{service_uuid}' not found")
# TODO: Make a query for this
for usage in db_service.usage:
if usage.consumer_entity_did == consumer_entity_did:
usage.times_consumed += 1
break
db.add(db_service)
db.commit()
db.refresh(db_service)
return db_service
def get_service_by_uuid(db: Session, uuid: str) -> Optional[sql_models.Service]:
return db.query(sql_models.Service).filter(sql_models.Service.uuid == uuid).first()
def get_services(
db: Session, skip: int = 0, limit: int = 100
) -> List[sql_models.Service]:
@@ -65,6 +168,10 @@ def get_services_without_entity_id(
# #
#########################
def create_entity(db: Session, entity: schemas.EntityCreate) -> sql_models.Entity:
if get_entity_by_did(db, entity.did) is not None:
raise ClanError(f"Entity with did '{entity.did}' already exists")
if get_entity_by_name_or_did(db, entity.name) is not None:
raise ClanError(f"Entity with name '{entity.name}' already exists")
db_entity = sql_models.Entity(
did=entity.did,
name=entity.name,
@@ -142,7 +249,9 @@ def get_attached_entities(
# Returns same entity if setting didnt changed something
def set_stop_health_task(db: Session, entity_did: str, value: bool) -> None:
def set_stop_health_task(
db: Session, entity_did: str, value: bool
) -> sql_models.Entity:
db_entity = get_entity_by_did(db, entity_did)
if db_entity is None:
raise ClanError(f"Entity with did '{entity_did}' not found")
@@ -152,9 +261,13 @@ def set_stop_health_task(db: Session, entity_did: str, value: bool) -> None:
# save changes in db
db.add(db_entity)
db.commit()
db.refresh(db_entity)
return db_entity
def set_attached_by_entity_did(db: Session, entity_did: str, attached: bool) -> None:
def set_attached_by_entity_did(
db: Session, entity_did: str, attached: bool
) -> sql_models.Entity:
db_entity = get_entity_by_did(db, entity_did)
if db_entity is None:
raise ClanError(f"Entity with did '{entity_did}' not found")
@@ -164,6 +277,8 @@ def set_attached_by_entity_did(db: Session, entity_did: str, attached: bool) ->
# save changes in db
db.add(db_entity)
db.commit()
db.refresh(db_entity)
return db_entity
def delete_entity_by_did(db: Session, did: str) -> None:
@@ -204,4 +319,11 @@ def create_eventmessage(
def get_eventmessages(
db: Session, skip: int = 0, limit: int = 100
) -> List[sql_models.Eventmessage]:
return db.query(sql_models.Eventmessage).offset(skip).limit(limit).all()
# Use order_by and desc to sort by timestamp
return (
db.query(sql_models.Eventmessage)
.order_by(asc(sql_models.Eventmessage.timestamp))
.offset(skip)
.limit(limit)
.all()
)

View File

@@ -1,3 +1,4 @@
# Imports
from typing import Generator
from sqlalchemy import create_engine
@@ -7,6 +8,8 @@ from sqlalchemy.orm import Session, declarative_base, sessionmaker
URL = "sqlite:///./sql_app.db"
# Create db engine
engine = create_engine(URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

View File

@@ -1,18 +1,18 @@
from sqlalchemy import JSON, Boolean, Column, Enum, ForeignKey, Integer, String, Text
from sqlalchemy.orm import relationship
from .schemas import Role
from .db_types import Role
from .sql_db import Base
# Relationsship example
# https://dev.to/freddiemazzilli/flask-sqlalchemy-relationships-exploring-relationship-associations-igo
# SQLAlchemy model for the "entities" table
class Entity(Base):
__tablename__ = "entities"
## Queryable body ##
# Primary Key
did = Column(String, primary_key=True, index=True)
# Indexed Columns
name = Column(String, index=True, unique=True)
ip = Column(String, index=True)
network = Column(String, index=True)
@@ -21,56 +21,87 @@ class Entity(Base):
stop_health_task = Column(Boolean)
## Non queryable body ##
# In here we deposit: Not yet defined stuff
# JSON field for additional non-queryable data
other = Column(JSON)
## Relations ##
# One-to-Many relationship with "services" table
services = relationship("Service", back_populates="entity")
# One-to-Many relationship with "entity_roles" table
roles = relationship("EntityRoles", back_populates="entity")
# One-to-Many relationship with "service_usage" table
consumes = relationship("ServiceUsage", back_populates="consumer_entity")
# SQLAlchemy model for the "entity_roles" table
class EntityRoles(Base):
__tablename__ = "entity_roles"
## Queryable body ##
# Primary Key
id = Column(Integer, primary_key=True, autoincrement=True)
# Foreign Key
entity_did = Column(String, ForeignKey("entities.did"))
# Enum field for role
role = Column(Enum(Role), index=True, nullable=False) # type: ignore
## Relations ##
# Many-to-One relationship with "entities" table
entity = relationship("Entity", back_populates="roles")
class ServiceAbstract(Base):
__abstract__ = True
# SQLAlchemy model for the "service_usage" table
class ServiceUsage(Base):
__tablename__ = "service_usage"
## Queryable body ##
# Primary Key
id = Column(Integer, primary_key=True, autoincrement=True)
# Foreign Key
consumer_entity_did = Column(String, ForeignKey("entities.did"))
# Many-to-One relationship with "entities" table
consumer_entity = relationship("Entity", back_populates="consumes")
times_consumed = Column(Integer, index=True, nullable=False)
service_uuid = Column(String, ForeignKey("services.uuid"))
# Many-to-One relationship with "services" table
service = relationship("Service", back_populates="usage")
# SQLAlchemy model for the "services" table
class Service(Base):
__tablename__ = "services"
# Queryable body
# Primary Key
uuid = Column(Text(length=36), primary_key=True, index=True)
service_name = Column(String, index=True)
service_type = Column(String, index=True)
endpoint_url = Column(String, index=True)
status = Column(String, index=True)
## Non queryable body ##
# In here we deposit: Action
# JSON fields for additional non-queryable data
other = Column(JSON)
class Service(ServiceAbstract):
__tablename__ = "services"
status = Column(JSON, index=True)
action = Column(JSON, index=True)
## Relations ##
# One entity can have many services
# One-to-Many relationship with "entities" table
entity = relationship("Entity", back_populates="services")
entity_did = Column(String, ForeignKey("entities.did"))
# One-to-Many relationship with "service_usage" table
usage = relationship("ServiceUsage", back_populates="service")
# SQLAlchemy model for the "eventmessages" table
class Eventmessage(Base):
__tablename__ = "eventmessages"
## Queryable body ##
# Primary Key
id = Column(Integer, primary_key=True, autoincrement=True)
timestamp = Column(Integer, unique=True, index=True)
timestamp = Column(Integer, index=True)
group = Column(Integer, index=True)
group_id = Column(Integer, index=True)
msg_type = Column(Integer, index=True) # message type for the label
@@ -78,8 +109,10 @@ class Eventmessage(Base):
des_did = Column(String, index=True)
## Non queryable body ##
# In here we deposit: Network, Roles, Visible, etc.
# JSON field for additional non-queryable data
msg = Column(JSON)
## Relations ##
# One-to-Many relationship with "entities" table
# One entity can send many messages
# (Note: The comment is incomplete and can be extended based on the relationship)

View File

@@ -1,5 +1,4 @@
{ age
, lib
{ lib
, argcomplete
, fastapi
, uvicorn
@@ -15,23 +14,17 @@
, python3
, runCommand
, setuptools
, sops
, stdenv
, wheel
, fakeroot
, rsync
, ui-assets
, bash
, sshpass
, zbar
, tor
, git
, nixpkgs
, makeDesktopItem
, copyDesktopItems
, qemu
, gnupg
, e2fsprogs
, mypy
, sqlalchemy
, websockets
@@ -73,17 +66,9 @@ let
bash
nix
fakeroot
openssh
sshpass
zbar
tor
age
rsync
sops
git
mypy
qemu
e2fsprogs
];
runtimeDependenciesAsSet = builtins.listToAttrs (builtins.map (p: lib.nameValuePair (lib.getName p.name) p) runtimeDependencies);

View File

@@ -12,6 +12,19 @@
};
inherit (self'.packages.clan-cli) clan-openapi;
default = self'.packages.clan-cli;
clan-docker = pkgs.dockerTools.buildImage {
name = "clan-docker";
tag = "latest";
created = "now";
config = {
Cmd = [ "${self'.packages.clan-cli}/bin/clan" "webui" "--no-open" "--host" "0.0.0.0" ];
ExposedPorts = {
"2979/tcp" = { };
};
};
};
};
checks = self'.packages.clan-cli.tests;

9
pkgs/clan-cli/push_docker.sh Executable file
View File

@@ -0,0 +1,9 @@
#!/usr/bin/env bash
# shellcheck shell=bash
set -euo pipefail
docker login git.tu-berlin.de:5000
docker load < result
docker image tag clan-docker:latest git.tu-berlin.de:5000/internet-of-services-lab/service-aware-network-front-end:latest
docker image push git.tu-berlin.de:5000/internet-of-services-lab/service-aware-network-front-end:latest

View File

@@ -20,6 +20,7 @@ __version__ = "1.0.0"
from openapi_client.api.default_api import DefaultApi
from openapi_client.api.entities_api import EntitiesApi
from openapi_client.api.eventmessages_api import EventmessagesApi
from openapi_client.api.repositories_api import RepositoriesApi
from openapi_client.api.resolution_api import ResolutionApi
from openapi_client.api.services_api import ServicesApi
@@ -45,6 +46,8 @@ from openapi_client.models.resolution import Resolution
from openapi_client.models.role import Role
from openapi_client.models.service import Service
from openapi_client.models.service_create import ServiceCreate
from openapi_client.models.service_usage import ServiceUsage
from openapi_client.models.service_usage_create import ServiceUsageCreate
from openapi_client.models.status import Status
from openapi_client.models.validation_error import ValidationError
from openapi_client.models.validation_error_loc_inner import ValidationErrorLocInner

View File

@@ -4,6 +4,7 @@
from openapi_client.api.default_api import DefaultApi
from openapi_client.api.entities_api import EntitiesApi
from openapi_client.api.eventmessages_api import EventmessagesApi
from openapi_client.api.repositories_api import RepositoriesApi
from openapi_client.api.resolution_api import ResolutionApi
from openapi_client.api.services_api import ServicesApi

View File

@@ -43,13 +43,13 @@ class DefaultApi:
self.api_client = api_client
@validate_arguments
def get(self, **kwargs) -> None: # noqa: E501
"""Get # noqa: E501
def get_emulated_enpoints(self, **kwargs) -> str: # noqa: E501
"""Get Emulated Enpoints # noqa: E501
This method makes a synchronous HTTP request by default. To make an
asynchronous HTTP request, please pass async_req=True
>>> thread = api.get(async_req=True)
>>> thread = api.get_emulated_enpoints(async_req=True)
>>> result = thread.get()
:param async_req: Whether to execute the request asynchronously.
@@ -61,22 +61,22 @@ class DefaultApi:
:return: Returns the result object.
If the method is called asynchronously,
returns the request thread.
:rtype: None
:rtype: str
"""
kwargs['_return_http_data_only'] = True
if '_preload_content' in kwargs:
message = "Error! Please call the get_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data" # noqa: E501
message = "Error! Please call the get_emulated_enpoints_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data" # noqa: E501
raise ValueError(message)
return self.get_with_http_info(**kwargs) # noqa: E501
return self.get_emulated_enpoints_with_http_info(**kwargs) # noqa: E501
@validate_arguments
def get_with_http_info(self, **kwargs) -> ApiResponse: # noqa: E501
"""Get # noqa: E501
def get_emulated_enpoints_with_http_info(self, **kwargs) -> ApiResponse: # noqa: E501
"""Get Emulated Enpoints # noqa: E501
This method makes a synchronous HTTP request by default. To make an
asynchronous HTTP request, please pass async_req=True
>>> thread = api.get_with_http_info(async_req=True)
>>> thread = api.get_emulated_enpoints_with_http_info(async_req=True)
>>> result = thread.get()
:param async_req: Whether to execute the request asynchronously.
@@ -101,7 +101,7 @@ class DefaultApi:
:return: Returns the result object.
If the method is called asynchronously,
returns the request thread.
:rtype: None
:rtype: tuple(str, status_code(int), headers(HTTPHeaderDict))
"""
_params = locals()
@@ -125,7 +125,7 @@ class DefaultApi:
if _key not in _all_params:
raise ApiTypeError(
"Got an unexpected keyword argument '%s'"
" to method get" % _key
" to method get_emulated_enpoints" % _key
)
_params[_key] = _val
del _params['kwargs']
@@ -146,15 +146,17 @@ class DefaultApi:
_body_params = None
# set the HTTP header `Accept`
_header_params['Accept'] = self.api_client.select_header_accept(
['application/json']) # noqa: E501
['text/html']) # noqa: E501
# authentication setting
_auth_settings = [] # noqa: E501
_response_types_map = {}
_response_types_map = {
'200': "str",
}
return self.api_client.call_api(
'/ws2_example', 'GET',
'/emulate', 'GET',
_path_params,
_query_params,
_header_params,

View File

@@ -1074,145 +1074,6 @@ class EntitiesApi:
collection_formats=_collection_formats,
_request_auth=_params.get('_request_auth'))
@validate_arguments
def get_entity_by_name_or_did(self, entity_name_or_did : Optional[StrictStr] = None, **kwargs) -> Entity: # noqa: E501
"""Get Entity By Name Or Did # noqa: E501
This method makes a synchronous HTTP request by default. To make an
asynchronous HTTP request, please pass async_req=True
>>> thread = api.get_entity_by_name_or_did(entity_name_or_did, async_req=True)
>>> result = thread.get()
:param entity_name_or_did:
:type entity_name_or_did: str
:param async_req: Whether to execute the request asynchronously.
:type async_req: bool, optional
:param _request_timeout: timeout setting for this request.
If one number provided, it will be total request
timeout. It can also be a pair (tuple) of
(connection, read) timeouts.
:return: Returns the result object.
If the method is called asynchronously,
returns the request thread.
:rtype: Entity
"""
kwargs['_return_http_data_only'] = True
if '_preload_content' in kwargs:
message = "Error! Please call the get_entity_by_name_or_did_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data" # noqa: E501
raise ValueError(message)
return self.get_entity_by_name_or_did_with_http_info(entity_name_or_did, **kwargs) # noqa: E501
@validate_arguments
def get_entity_by_name_or_did_with_http_info(self, entity_name_or_did : Optional[StrictStr] = None, **kwargs) -> ApiResponse: # noqa: E501
"""Get Entity By Name Or Did # noqa: E501
This method makes a synchronous HTTP request by default. To make an
asynchronous HTTP request, please pass async_req=True
>>> thread = api.get_entity_by_name_or_did_with_http_info(entity_name_or_did, async_req=True)
>>> result = thread.get()
:param entity_name_or_did:
:type entity_name_or_did: str
:param async_req: Whether to execute the request asynchronously.
:type async_req: bool, optional
:param _preload_content: if False, the ApiResponse.data will
be set to none and raw_data will store the
HTTP response body without reading/decoding.
Default is True.
:type _preload_content: bool, optional
:param _return_http_data_only: response data instead of ApiResponse
object with status code, headers, etc
:type _return_http_data_only: bool, optional
:param _request_timeout: timeout setting for this request. If one
number provided, it will be total request
timeout. It can also be a pair (tuple) of
(connection, read) timeouts.
:param _request_auth: set to override the auth_settings for an a single
request; this effectively ignores the authentication
in the spec for a single request.
:type _request_auth: dict, optional
:type _content_type: string, optional: force content-type for the request
:return: Returns the result object.
If the method is called asynchronously,
returns the request thread.
:rtype: tuple(Entity, status_code(int), headers(HTTPHeaderDict))
"""
_params = locals()
_all_params = [
'entity_name_or_did'
]
_all_params.extend(
[
'async_req',
'_return_http_data_only',
'_preload_content',
'_request_timeout',
'_request_auth',
'_content_type',
'_headers'
]
)
# validate the arguments
for _key, _val in _params['kwargs'].items():
if _key not in _all_params:
raise ApiTypeError(
"Got an unexpected keyword argument '%s'"
" to method get_entity_by_name_or_did" % _key
)
_params[_key] = _val
del _params['kwargs']
_collection_formats = {}
# process the path parameters
_path_params = {}
# process the query parameters
_query_params = []
if _params.get('entity_name_or_did') is not None: # noqa: E501
_query_params.append(('entity_name_or_did', _params['entity_name_or_did']))
# process the header parameters
_header_params = dict(_params.get('_headers', {}))
# process the form parameters
_form_params = []
_files = {}
# process the body parameter
_body_params = None
# set the HTTP header `Accept`
_header_params['Accept'] = self.api_client.select_header_accept(
['application/json']) # noqa: E501
# authentication setting
_auth_settings = [] # noqa: E501
_response_types_map = {
'200': "Entity",
'422': "HTTPValidationError",
}
return self.api_client.call_api(
'/api/v1/entity_by_name_or_did', 'GET',
_path_params,
_query_params,
_header_params,
body=_body_params,
post_params=_form_params,
files=_files,
response_types_map=_response_types_map,
auth_settings=_auth_settings,
async_req=_params.get('async_req'),
_return_http_data_only=_params.get('_return_http_data_only'), # noqa: E501
_preload_content=_params.get('_preload_content', True),
_request_timeout=_params.get('_request_timeout'),
collection_formats=_collection_formats,
_request_auth=_params.get('_request_auth'))
@validate_arguments
def get_entity_by_roles(self, roles : conlist(Role), **kwargs) -> List[Entity]: # noqa: E501
"""Get Entity By Roles # noqa: E501

View File

@@ -20,7 +20,7 @@ from pydantic import validate_arguments, ValidationError
from pydantic import StrictInt
from typing import List, Optional
from typing import Optional
from openapi_client.models.eventmessage import Eventmessage
from openapi_client.models.eventmessage_create import EventmessageCreate
@@ -192,7 +192,7 @@ class EventmessagesApi:
_request_auth=_params.get('_request_auth'))
@validate_arguments
def get_all_eventmessages(self, skip : Optional[StrictInt] = None, limit : Optional[StrictInt] = None, **kwargs) -> List[Eventmessage]: # noqa: E501
def get_all_eventmessages(self, skip : Optional[StrictInt] = None, limit : Optional[StrictInt] = None, **kwargs) -> None: # noqa: E501
"""Get All Eventmessages # noqa: E501
This method makes a synchronous HTTP request by default. To make an
@@ -214,7 +214,7 @@ class EventmessagesApi:
:return: Returns the result object.
If the method is called asynchronously,
returns the request thread.
:rtype: List[Eventmessage]
:rtype: None
"""
kwargs['_return_http_data_only'] = True
if '_preload_content' in kwargs:
@@ -258,7 +258,7 @@ class EventmessagesApi:
:return: Returns the result object.
If the method is called asynchronously,
returns the request thread.
:rtype: tuple(List[Eventmessage], status_code(int), headers(HTTPHeaderDict))
:rtype: None
"""
_params = locals()
@@ -316,10 +316,7 @@ class EventmessagesApi:
# authentication setting
_auth_settings = [] # noqa: E501
_response_types_map = {
'200': "List[Eventmessage]",
'422': "HTTPValidationError",
}
_response_types_map = {}
return self.api_client.call_api(
'/api/v1/event_messages', 'GET',

View File

@@ -0,0 +1,192 @@
# coding: utf-8
"""
FastAPI
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.1.0
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
import re # noqa: F401
import io
import warnings
from pydantic import validate_arguments, ValidationError
from pydantic import StrictInt
from typing import List, Optional
from openapi_client.models.service import Service
from openapi_client.api_client import ApiClient
from openapi_client.api_response import ApiResponse
from openapi_client.exceptions import ( # noqa: F401
ApiTypeError,
ApiValueError
)
class RepositoriesApi:
"""NOTE: This class is auto generated by OpenAPI Generator
Ref: https://openapi-generator.tech
Do not edit the class manually.
"""
def __init__(self, api_client=None) -> None:
if api_client is None:
api_client = ApiClient.get_default()
self.api_client = api_client
@validate_arguments
def get_all_repositories(self, skip : Optional[StrictInt] = None, limit : Optional[StrictInt] = None, **kwargs) -> List[Service]: # noqa: E501
"""Get All Repositories # noqa: E501
This method makes a synchronous HTTP request by default. To make an
asynchronous HTTP request, please pass async_req=True
>>> thread = api.get_all_repositories(skip, limit, async_req=True)
>>> result = thread.get()
:param skip:
:type skip: int
:param limit:
:type limit: int
:param async_req: Whether to execute the request asynchronously.
:type async_req: bool, optional
:param _request_timeout: timeout setting for this request.
If one number provided, it will be total request
timeout. It can also be a pair (tuple) of
(connection, read) timeouts.
:return: Returns the result object.
If the method is called asynchronously,
returns the request thread.
:rtype: List[Service]
"""
kwargs['_return_http_data_only'] = True
if '_preload_content' in kwargs:
message = "Error! Please call the get_all_repositories_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data" # noqa: E501
raise ValueError(message)
return self.get_all_repositories_with_http_info(skip, limit, **kwargs) # noqa: E501
@validate_arguments
def get_all_repositories_with_http_info(self, skip : Optional[StrictInt] = None, limit : Optional[StrictInt] = None, **kwargs) -> ApiResponse: # noqa: E501
"""Get All Repositories # noqa: E501
This method makes a synchronous HTTP request by default. To make an
asynchronous HTTP request, please pass async_req=True
>>> thread = api.get_all_repositories_with_http_info(skip, limit, async_req=True)
>>> result = thread.get()
:param skip:
:type skip: int
:param limit:
:type limit: int
:param async_req: Whether to execute the request asynchronously.
:type async_req: bool, optional
:param _preload_content: if False, the ApiResponse.data will
be set to none and raw_data will store the
HTTP response body without reading/decoding.
Default is True.
:type _preload_content: bool, optional
:param _return_http_data_only: response data instead of ApiResponse
object with status code, headers, etc
:type _return_http_data_only: bool, optional
:param _request_timeout: timeout setting for this request. If one
number provided, it will be total request
timeout. It can also be a pair (tuple) of
(connection, read) timeouts.
:param _request_auth: set to override the auth_settings for an a single
request; this effectively ignores the authentication
in the spec for a single request.
:type _request_auth: dict, optional
:type _content_type: string, optional: force content-type for the request
:return: Returns the result object.
If the method is called asynchronously,
returns the request thread.
:rtype: tuple(List[Service], status_code(int), headers(HTTPHeaderDict))
"""
_params = locals()
_all_params = [
'skip',
'limit'
]
_all_params.extend(
[
'async_req',
'_return_http_data_only',
'_preload_content',
'_request_timeout',
'_request_auth',
'_content_type',
'_headers'
]
)
# validate the arguments
for _key, _val in _params['kwargs'].items():
if _key not in _all_params:
raise ApiTypeError(
"Got an unexpected keyword argument '%s'"
" to method get_all_repositories" % _key
)
_params[_key] = _val
del _params['kwargs']
_collection_formats = {}
# process the path parameters
_path_params = {}
# process the query parameters
_query_params = []
if _params.get('skip') is not None: # noqa: E501
_query_params.append(('skip', _params['skip']))
if _params.get('limit') is not None: # noqa: E501
_query_params.append(('limit', _params['limit']))
# process the header parameters
_header_params = dict(_params.get('_headers', {}))
# process the form parameters
_form_params = []
_files = {}
# process the body parameter
_body_params = None
# set the HTTP header `Accept`
_header_params['Accept'] = self.api_client.select_header_accept(
['application/json']) # noqa: E501
# authentication setting
_auth_settings = [] # noqa: E501
_response_types_map = {
'200': "List[Service]",
'422': "HTTPValidationError",
}
return self.api_client.call_api(
'/api/v1/repositories', 'GET',
_path_params,
_query_params,
_header_params,
body=_body_params,
post_params=_form_params,
files=_files,
response_types_map=_response_types_map,
auth_settings=_auth_settings,
async_req=_params.get('async_req'),
_return_http_data_only=_params.get('_return_http_data_only'), # noqa: E501
_preload_content=_params.get('_preload_content', True),
_request_timeout=_params.get('_request_timeout'),
collection_formats=_collection_formats,
_request_auth=_params.get('_request_auth'))

View File

@@ -24,6 +24,7 @@ from typing import Any, List, Optional, Dict
from openapi_client.models.service import Service
from openapi_client.models.service_create import ServiceCreate
from openapi_client.models.service_usage_create import ServiceUsageCreate
from openapi_client.api_client import ApiClient
from openapi_client.api_response import ApiResponse
@@ -45,6 +46,160 @@ class ServicesApi:
api_client = ApiClient.get_default()
self.api_client = api_client
@validate_arguments
def add_service_usage(self, service_usage_create : ServiceUsageCreate, service_uuid : Optional[StrictStr] = None, **kwargs) -> Service: # noqa: E501
"""Add Service Usage # noqa: E501
This method makes a synchronous HTTP request by default. To make an
asynchronous HTTP request, please pass async_req=True
>>> thread = api.add_service_usage(service_usage_create, service_uuid, async_req=True)
>>> result = thread.get()
:param service_usage_create: (required)
:type service_usage_create: ServiceUsageCreate
:param service_uuid:
:type service_uuid: str
:param async_req: Whether to execute the request asynchronously.
:type async_req: bool, optional
:param _request_timeout: timeout setting for this request.
If one number provided, it will be total request
timeout. It can also be a pair (tuple) of
(connection, read) timeouts.
:return: Returns the result object.
If the method is called asynchronously,
returns the request thread.
:rtype: Service
"""
kwargs['_return_http_data_only'] = True
if '_preload_content' in kwargs:
message = "Error! Please call the add_service_usage_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data" # noqa: E501
raise ValueError(message)
return self.add_service_usage_with_http_info(service_usage_create, service_uuid, **kwargs) # noqa: E501
@validate_arguments
def add_service_usage_with_http_info(self, service_usage_create : ServiceUsageCreate, service_uuid : Optional[StrictStr] = None, **kwargs) -> ApiResponse: # noqa: E501
"""Add Service Usage # noqa: E501
This method makes a synchronous HTTP request by default. To make an
asynchronous HTTP request, please pass async_req=True
>>> thread = api.add_service_usage_with_http_info(service_usage_create, service_uuid, async_req=True)
>>> result = thread.get()
:param service_usage_create: (required)
:type service_usage_create: ServiceUsageCreate
:param service_uuid:
:type service_uuid: str
:param async_req: Whether to execute the request asynchronously.
:type async_req: bool, optional
:param _preload_content: if False, the ApiResponse.data will
be set to none and raw_data will store the
HTTP response body without reading/decoding.
Default is True.
:type _preload_content: bool, optional
:param _return_http_data_only: response data instead of ApiResponse
object with status code, headers, etc
:type _return_http_data_only: bool, optional
:param _request_timeout: timeout setting for this request. If one
number provided, it will be total request
timeout. It can also be a pair (tuple) of
(connection, read) timeouts.
:param _request_auth: set to override the auth_settings for an a single
request; this effectively ignores the authentication
in the spec for a single request.
:type _request_auth: dict, optional
:type _content_type: string, optional: force content-type for the request
:return: Returns the result object.
If the method is called asynchronously,
returns the request thread.
:rtype: tuple(Service, status_code(int), headers(HTTPHeaderDict))
"""
_params = locals()
_all_params = [
'service_usage_create',
'service_uuid'
]
_all_params.extend(
[
'async_req',
'_return_http_data_only',
'_preload_content',
'_request_timeout',
'_request_auth',
'_content_type',
'_headers'
]
)
# validate the arguments
for _key, _val in _params['kwargs'].items():
if _key not in _all_params:
raise ApiTypeError(
"Got an unexpected keyword argument '%s'"
" to method add_service_usage" % _key
)
_params[_key] = _val
del _params['kwargs']
_collection_formats = {}
# process the path parameters
_path_params = {}
# process the query parameters
_query_params = []
if _params.get('service_uuid') is not None: # noqa: E501
_query_params.append(('service_uuid', _params['service_uuid']))
# process the header parameters
_header_params = dict(_params.get('_headers', {}))
# process the form parameters
_form_params = []
_files = {}
# process the body parameter
_body_params = None
if _params['service_usage_create'] is not None:
_body_params = _params['service_usage_create']
# set the HTTP header `Accept`
_header_params['Accept'] = self.api_client.select_header_accept(
['application/json']) # noqa: E501
# set the HTTP header `Content-Type`
_content_types_list = _params.get('_content_type',
self.api_client.select_header_content_type(
['application/json']))
if _content_types_list:
_header_params['Content-Type'] = _content_types_list
# authentication setting
_auth_settings = [] # noqa: E501
_response_types_map = {
'200': "Service",
'422': "HTTPValidationError",
}
return self.api_client.call_api(
'/api/v1/service_usage', 'POST',
_path_params,
_query_params,
_header_params,
body=_body_params,
post_params=_form_params,
files=_files,
response_types_map=_response_types_map,
auth_settings=_auth_settings,
async_req=_params.get('async_req'),
_return_http_data_only=_params.get('_return_http_data_only'), # noqa: E501
_preload_content=_params.get('_preload_content', True),
_request_timeout=_params.get('_request_timeout'),
collection_formats=_collection_formats,
_request_auth=_params.get('_request_auth'))
@validate_arguments
def create_service(self, service_create : ServiceCreate, **kwargs) -> Service: # noqa: E501
"""Create Service # noqa: E501
@@ -615,6 +770,161 @@ class ServicesApi:
'422': "HTTPValidationError",
}
return self.api_client.call_api(
'/api/v1/service_by_did', 'GET',
_path_params,
_query_params,
_header_params,
body=_body_params,
post_params=_form_params,
files=_files,
response_types_map=_response_types_map,
auth_settings=_auth_settings,
async_req=_params.get('async_req'),
_return_http_data_only=_params.get('_return_http_data_only'), # noqa: E501
_preload_content=_params.get('_preload_content', True),
_request_timeout=_params.get('_request_timeout'),
collection_formats=_collection_formats,
_request_auth=_params.get('_request_auth'))
@validate_arguments
def get_service_by_uuid(self, uuid : Optional[StrictStr] = None, skip : Optional[StrictInt] = None, limit : Optional[StrictInt] = None, **kwargs) -> Service: # noqa: E501
"""Get Service By Uuid # noqa: E501
This method makes a synchronous HTTP request by default. To make an
asynchronous HTTP request, please pass async_req=True
>>> thread = api.get_service_by_uuid(uuid, skip, limit, async_req=True)
>>> result = thread.get()
:param uuid:
:type uuid: str
:param skip:
:type skip: int
:param limit:
:type limit: int
:param async_req: Whether to execute the request asynchronously.
:type async_req: bool, optional
:param _request_timeout: timeout setting for this request.
If one number provided, it will be total request
timeout. It can also be a pair (tuple) of
(connection, read) timeouts.
:return: Returns the result object.
If the method is called asynchronously,
returns the request thread.
:rtype: Service
"""
kwargs['_return_http_data_only'] = True
if '_preload_content' in kwargs:
message = "Error! Please call the get_service_by_uuid_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data" # noqa: E501
raise ValueError(message)
return self.get_service_by_uuid_with_http_info(uuid, skip, limit, **kwargs) # noqa: E501
@validate_arguments
def get_service_by_uuid_with_http_info(self, uuid : Optional[StrictStr] = None, skip : Optional[StrictInt] = None, limit : Optional[StrictInt] = None, **kwargs) -> ApiResponse: # noqa: E501
"""Get Service By Uuid # noqa: E501
This method makes a synchronous HTTP request by default. To make an
asynchronous HTTP request, please pass async_req=True
>>> thread = api.get_service_by_uuid_with_http_info(uuid, skip, limit, async_req=True)
>>> result = thread.get()
:param uuid:
:type uuid: str
:param skip:
:type skip: int
:param limit:
:type limit: int
:param async_req: Whether to execute the request asynchronously.
:type async_req: bool, optional
:param _preload_content: if False, the ApiResponse.data will
be set to none and raw_data will store the
HTTP response body without reading/decoding.
Default is True.
:type _preload_content: bool, optional
:param _return_http_data_only: response data instead of ApiResponse
object with status code, headers, etc
:type _return_http_data_only: bool, optional
:param _request_timeout: timeout setting for this request. If one
number provided, it will be total request
timeout. It can also be a pair (tuple) of
(connection, read) timeouts.
:param _request_auth: set to override the auth_settings for an a single
request; this effectively ignores the authentication
in the spec for a single request.
:type _request_auth: dict, optional
:type _content_type: string, optional: force content-type for the request
:return: Returns the result object.
If the method is called asynchronously,
returns the request thread.
:rtype: tuple(Service, status_code(int), headers(HTTPHeaderDict))
"""
_params = locals()
_all_params = [
'uuid',
'skip',
'limit'
]
_all_params.extend(
[
'async_req',
'_return_http_data_only',
'_preload_content',
'_request_timeout',
'_request_auth',
'_content_type',
'_headers'
]
)
# validate the arguments
for _key, _val in _params['kwargs'].items():
if _key not in _all_params:
raise ApiTypeError(
"Got an unexpected keyword argument '%s'"
" to method get_service_by_uuid" % _key
)
_params[_key] = _val
del _params['kwargs']
_collection_formats = {}
# process the path parameters
_path_params = {}
# process the query parameters
_query_params = []
if _params.get('uuid') is not None: # noqa: E501
_query_params.append(('uuid', _params['uuid']))
if _params.get('skip') is not None: # noqa: E501
_query_params.append(('skip', _params['skip']))
if _params.get('limit') is not None: # noqa: E501
_query_params.append(('limit', _params['limit']))
# process the header parameters
_header_params = dict(_params.get('_headers', {}))
# process the form parameters
_form_params = []
_files = {}
# process the body parameter
_body_params = None
# set the HTTP header `Accept`
_header_params['Accept'] = self.api_client.select_header_accept(
['application/json']) # noqa: E501
# authentication setting
_auth_settings = [] # noqa: E501
_response_types_map = {
'200': "Service",
'422': "HTTPValidationError",
}
return self.api_client.call_api(
'/api/v1/service', 'GET',
_path_params,
@@ -786,3 +1096,319 @@ class ServicesApi:
_request_timeout=_params.get('_request_timeout'),
collection_formats=_collection_formats,
_request_auth=_params.get('_request_auth'))
@validate_arguments
def inc_service_usage(self, service_usage_create : ServiceUsageCreate, consumer_entity_did : Optional[StrictStr] = None, service_uuid : Optional[StrictStr] = None, **kwargs) -> Service: # noqa: E501
"""Inc Service Usage # noqa: E501
This method makes a synchronous HTTP request by default. To make an
asynchronous HTTP request, please pass async_req=True
>>> thread = api.inc_service_usage(service_usage_create, consumer_entity_did, service_uuid, async_req=True)
>>> result = thread.get()
:param service_usage_create: (required)
:type service_usage_create: ServiceUsageCreate
:param consumer_entity_did:
:type consumer_entity_did: str
:param service_uuid:
:type service_uuid: str
:param async_req: Whether to execute the request asynchronously.
:type async_req: bool, optional
:param _request_timeout: timeout setting for this request.
If one number provided, it will be total request
timeout. It can also be a pair (tuple) of
(connection, read) timeouts.
:return: Returns the result object.
If the method is called asynchronously,
returns the request thread.
:rtype: Service
"""
kwargs['_return_http_data_only'] = True
if '_preload_content' in kwargs:
message = "Error! Please call the inc_service_usage_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data" # noqa: E501
raise ValueError(message)
return self.inc_service_usage_with_http_info(service_usage_create, consumer_entity_did, service_uuid, **kwargs) # noqa: E501
@validate_arguments
def inc_service_usage_with_http_info(self, service_usage_create : ServiceUsageCreate, consumer_entity_did : Optional[StrictStr] = None, service_uuid : Optional[StrictStr] = None, **kwargs) -> ApiResponse: # noqa: E501
"""Inc Service Usage # noqa: E501
This method makes a synchronous HTTP request by default. To make an
asynchronous HTTP request, please pass async_req=True
>>> thread = api.inc_service_usage_with_http_info(service_usage_create, consumer_entity_did, service_uuid, async_req=True)
>>> result = thread.get()
:param service_usage_create: (required)
:type service_usage_create: ServiceUsageCreate
:param consumer_entity_did:
:type consumer_entity_did: str
:param service_uuid:
:type service_uuid: str
:param async_req: Whether to execute the request asynchronously.
:type async_req: bool, optional
:param _preload_content: if False, the ApiResponse.data will
be set to none and raw_data will store the
HTTP response body without reading/decoding.
Default is True.
:type _preload_content: bool, optional
:param _return_http_data_only: response data instead of ApiResponse
object with status code, headers, etc
:type _return_http_data_only: bool, optional
:param _request_timeout: timeout setting for this request. If one
number provided, it will be total request
timeout. It can also be a pair (tuple) of
(connection, read) timeouts.
:param _request_auth: set to override the auth_settings for an a single
request; this effectively ignores the authentication
in the spec for a single request.
:type _request_auth: dict, optional
:type _content_type: string, optional: force content-type for the request
:return: Returns the result object.
If the method is called asynchronously,
returns the request thread.
:rtype: tuple(Service, status_code(int), headers(HTTPHeaderDict))
"""
_params = locals()
_all_params = [
'service_usage_create',
'consumer_entity_did',
'service_uuid'
]
_all_params.extend(
[
'async_req',
'_return_http_data_only',
'_preload_content',
'_request_timeout',
'_request_auth',
'_content_type',
'_headers'
]
)
# validate the arguments
for _key, _val in _params['kwargs'].items():
if _key not in _all_params:
raise ApiTypeError(
"Got an unexpected keyword argument '%s'"
" to method inc_service_usage" % _key
)
_params[_key] = _val
del _params['kwargs']
_collection_formats = {}
# process the path parameters
_path_params = {}
# process the query parameters
_query_params = []
if _params.get('consumer_entity_did') is not None: # noqa: E501
_query_params.append(('consumer_entity_did', _params['consumer_entity_did']))
if _params.get('service_uuid') is not None: # noqa: E501
_query_params.append(('service_uuid', _params['service_uuid']))
# process the header parameters
_header_params = dict(_params.get('_headers', {}))
# process the form parameters
_form_params = []
_files = {}
# process the body parameter
_body_params = None
if _params['service_usage_create'] is not None:
_body_params = _params['service_usage_create']
# set the HTTP header `Accept`
_header_params['Accept'] = self.api_client.select_header_accept(
['application/json']) # noqa: E501
# set the HTTP header `Content-Type`
_content_types_list = _params.get('_content_type',
self.api_client.select_header_content_type(
['application/json']))
if _content_types_list:
_header_params['Content-Type'] = _content_types_list
# authentication setting
_auth_settings = [] # noqa: E501
_response_types_map = {
'200': "Service",
'422': "HTTPValidationError",
}
return self.api_client.call_api(
'/api/v1/inc_service_usage', 'PUT',
_path_params,
_query_params,
_header_params,
body=_body_params,
post_params=_form_params,
files=_files,
response_types_map=_response_types_map,
auth_settings=_auth_settings,
async_req=_params.get('async_req'),
_return_http_data_only=_params.get('_return_http_data_only'), # noqa: E501
_preload_content=_params.get('_preload_content', True),
_request_timeout=_params.get('_request_timeout'),
collection_formats=_collection_formats,
_request_auth=_params.get('_request_auth'))
@validate_arguments
def update_service(self, service_create : ServiceCreate, uuid : Optional[StrictStr] = None, **kwargs) -> Service: # noqa: E501
"""Update Service # noqa: E501
This method makes a synchronous HTTP request by default. To make an
asynchronous HTTP request, please pass async_req=True
>>> thread = api.update_service(service_create, uuid, async_req=True)
>>> result = thread.get()
:param service_create: (required)
:type service_create: ServiceCreate
:param uuid:
:type uuid: str
:param async_req: Whether to execute the request asynchronously.
:type async_req: bool, optional
:param _request_timeout: timeout setting for this request.
If one number provided, it will be total request
timeout. It can also be a pair (tuple) of
(connection, read) timeouts.
:return: Returns the result object.
If the method is called asynchronously,
returns the request thread.
:rtype: Service
"""
kwargs['_return_http_data_only'] = True
if '_preload_content' in kwargs:
message = "Error! Please call the update_service_with_http_info method with `_preload_content` instead and obtain raw data from ApiResponse.raw_data" # noqa: E501
raise ValueError(message)
return self.update_service_with_http_info(service_create, uuid, **kwargs) # noqa: E501
@validate_arguments
def update_service_with_http_info(self, service_create : ServiceCreate, uuid : Optional[StrictStr] = None, **kwargs) -> ApiResponse: # noqa: E501
"""Update Service # noqa: E501
This method makes a synchronous HTTP request by default. To make an
asynchronous HTTP request, please pass async_req=True
>>> thread = api.update_service_with_http_info(service_create, uuid, async_req=True)
>>> result = thread.get()
:param service_create: (required)
:type service_create: ServiceCreate
:param uuid:
:type uuid: str
:param async_req: Whether to execute the request asynchronously.
:type async_req: bool, optional
:param _preload_content: if False, the ApiResponse.data will
be set to none and raw_data will store the
HTTP response body without reading/decoding.
Default is True.
:type _preload_content: bool, optional
:param _return_http_data_only: response data instead of ApiResponse
object with status code, headers, etc
:type _return_http_data_only: bool, optional
:param _request_timeout: timeout setting for this request. If one
number provided, it will be total request
timeout. It can also be a pair (tuple) of
(connection, read) timeouts.
:param _request_auth: set to override the auth_settings for an a single
request; this effectively ignores the authentication
in the spec for a single request.
:type _request_auth: dict, optional
:type _content_type: string, optional: force content-type for the request
:return: Returns the result object.
If the method is called asynchronously,
returns the request thread.
:rtype: tuple(Service, status_code(int), headers(HTTPHeaderDict))
"""
_params = locals()
_all_params = [
'service_create',
'uuid'
]
_all_params.extend(
[
'async_req',
'_return_http_data_only',
'_preload_content',
'_request_timeout',
'_request_auth',
'_content_type',
'_headers'
]
)
# validate the arguments
for _key, _val in _params['kwargs'].items():
if _key not in _all_params:
raise ApiTypeError(
"Got an unexpected keyword argument '%s'"
" to method update_service" % _key
)
_params[_key] = _val
del _params['kwargs']
_collection_formats = {}
# process the path parameters
_path_params = {}
# process the query parameters
_query_params = []
if _params.get('uuid') is not None: # noqa: E501
_query_params.append(('uuid', _params['uuid']))
# process the header parameters
_header_params = dict(_params.get('_headers', {}))
# process the form parameters
_form_params = []
_files = {}
# process the body parameter
_body_params = None
if _params['service_create'] is not None:
_body_params = _params['service_create']
# set the HTTP header `Accept`
_header_params['Accept'] = self.api_client.select_header_accept(
['application/json']) # noqa: E501
# set the HTTP header `Content-Type`
_content_types_list = _params.get('_content_type',
self.api_client.select_header_content_type(
['application/json']))
if _content_types_list:
_header_params['Content-Type'] = _content_types_list
# authentication setting
_auth_settings = [] # noqa: E501
_response_types_map = {
'200': "Service",
'422': "HTTPValidationError",
}
return self.api_client.call_api(
'/api/v1/service', 'PUT',
_path_params,
_query_params,
_header_params,
body=_body_params,
post_params=_form_params,
files=_files,
response_types_map=_response_types_map,
auth_settings=_auth_settings,
async_req=_params.get('async_req'),
_return_http_data_only=_params.get('_return_http_data_only'), # noqa: E501
_preload_content=_params.get('_preload_content', True),
_request_timeout=_params.get('_request_timeout'),
collection_formats=_collection_formats,
_request_auth=_params.get('_request_auth'))

View File

@@ -1,18 +1,18 @@
# openapi_client.DefaultApi
All URIs are relative to _http://localhost_
All URIs are relative to *http://localhost*
| Method | HTTP request | Description |
| ---------------------------------- | -------------------- | ----------- |
| [**get**](DefaultApi.md#get) | **GET** /ws2_example | Get |
| [**health**](DefaultApi.md#health) | **GET** /health | Health |
| [**root**](DefaultApi.md#root) | **GET** /{path_name} | Root |
Method | HTTP request | Description
------------- | ------------- | -------------
[**get_emulated_enpoints**](DefaultApi.md#get_emulated_enpoints) | **GET** /emulate | Get Emulated Enpoints
[**health**](DefaultApi.md#health) | **GET** /health | Health
[**root**](DefaultApi.md#root) | **GET** /{path_name} | Root
# **get**
> get()
# **get_emulated_enpoints**
> str get_emulated_enpoints()
Get
Get Emulated Enpoints
### Example
@@ -36,19 +36,22 @@ with openapi_client.ApiClient(configuration) as api_client:
api_instance = openapi_client.DefaultApi(api_client)
try:
# Get
api_instance.get()
# Get Emulated Enpoints
api_response = api_instance.get_emulated_enpoints()
print("The response of DefaultApi->get_emulated_enpoints:\n")
pprint(api_response)
except Exception as e:
print("Exception when calling DefaultApi->get: %s\n" % e)
print("Exception when calling DefaultApi->get_emulated_enpoints: %s\n" % e)
```
### Parameters
### Parameters
This endpoint does not need any parameter.
### Return type
void (empty response body)
**str**
### Authorization
@@ -56,19 +59,17 @@ No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
- **Content-Type**: Not defined
- **Accept**: text/html
### HTTP response details
| Status code | Description | Response headers |
| ----------- | ------------------- | ---------------- |
| **200** | Successful Response | - |
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | Successful Response | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **health**
> Machine health()
Health
@@ -104,8 +105,9 @@ with openapi_client.ApiClient(configuration) as api_client:
print("Exception when calling DefaultApi->health: %s\n" % e)
```
### Parameters
### Parameters
This endpoint does not need any parameter.
### Return type
@@ -118,19 +120,17 @@ No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
| ----------- | ------------------- | ---------------- |
| **200** | Successful Response | - |
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | Successful Response | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **root**
> root(path_name)
Root
@@ -155,7 +155,7 @@ configuration = openapi_client.Configuration(
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.DefaultApi(api_client)
path_name = 'path_name_example' # str |
path_name = 'path_name_example' # str |
try:
# Root
@@ -164,11 +164,13 @@ with openapi_client.ApiClient(configuration) as api_client:
print("Exception when calling DefaultApi->root: %s\n" % e)
```
### Parameters
| Name | Type | Description | Notes |
| ------------- | ------- | ----------- | ----- |
| **path_name** | **str** | |
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**path_name** | **str**| |
### Return type
@@ -180,14 +182,14 @@ No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
| ----------- | ------------------- | ---------------- |
| **200** | Successful Response | - |
| **422** | Validation Error | - |
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | Successful Response | - |
**422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)

View File

@@ -1,22 +1,21 @@
# openapi_client.EntitiesApi
All URIs are relative to _http://localhost_
All URIs are relative to *http://localhost*
Method | HTTP request | Description
------------- | ------------- | -------------
[**attach_entity**](EntitiesApi.md#attach_entity) | **PUT** /api/v1/attach | Attach Entity
[**create_entity**](EntitiesApi.md#create_entity) | **POST** /api/v1/entity | Create Entity
[**delete_entity**](EntitiesApi.md#delete_entity) | **DELETE** /api/v1/entity | Delete Entity
[**detach_entity**](EntitiesApi.md#detach_entity) | **PUT** /api/v1/detach | Detach Entity
[**get_all_entities**](EntitiesApi.md#get_all_entities) | **GET** /api/v1/entities | Get All Entities
[**get_attached_entities**](EntitiesApi.md#get_attached_entities) | **GET** /api/v1/attached_entities | Get Attached Entities
[**get_entity_by_did**](EntitiesApi.md#get_entity_by_did) | **GET** /api/v1/entity | Get Entity By Did
[**get_entity_by_roles**](EntitiesApi.md#get_entity_by_roles) | **GET** /api/v1/entity_by_roles | Get Entity By Roles
[**is_attached**](EntitiesApi.md#is_attached) | **GET** /api/v1/is_attached | Is Attached
| Method | HTTP request | Description |
| ------------------------------------------------------------------------- | ------------------------------------- | ------------------------- |
| [**attach_entity**](EntitiesApi.md#attach_entity) | **PUT** /api/v1/attach | Attach Entity |
| [**create_entity**](EntitiesApi.md#create_entity) | **POST** /api/v1/entity | Create Entity |
| [**delete_entity**](EntitiesApi.md#delete_entity) | **DELETE** /api/v1/entity | Delete Entity |
| [**detach_entity**](EntitiesApi.md#detach_entity) | **PUT** /api/v1/detach | Detach Entity |
| [**get_all_entities**](EntitiesApi.md#get_all_entities) | **GET** /api/v1/entities | Get All Entities |
| [**get_attached_entities**](EntitiesApi.md#get_attached_entities) | **GET** /api/v1/attached_entities | Get Attached Entities |
| [**get_entity_by_did**](EntitiesApi.md#get_entity_by_did) | **GET** /api/v1/entity | Get Entity By Did |
| [**get_entity_by_name_or_did**](EntitiesApi.md#get_entity_by_name_or_did) | **GET** /api/v1/entity_by_name_or_did | Get Entity By Name Or Did |
| [**get_entity_by_roles**](EntitiesApi.md#get_entity_by_roles) | **GET** /api/v1/entity_by_roles | Get Entity By Roles |
| [**is_attached**](EntitiesApi.md#is_attached) | **GET** /api/v1/is_attached | Is Attached |
# **attach_entity**
> Dict[str, str] attach_entity(entity_did=entity_did, skip=skip, limit=limit)
Attach Entity
@@ -41,7 +40,7 @@ configuration = openapi_client.Configuration(
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.EntitiesApi(api_client)
entity_did = 'did:sov:test:1234' # str | (optional) (default to 'did:sov:test:1234')
entity_did = 'did:sov:test:120' # str | (optional) (default to 'did:sov:test:120')
skip = 0 # int | (optional) (default to 0)
limit = 100 # int | (optional) (default to 100)
@@ -54,13 +53,15 @@ with openapi_client.ApiClient(configuration) as api_client:
print("Exception when calling EntitiesApi->attach_entity: %s\n" % e)
```
### Parameters
| Name | Type | Description | Notes |
| -------------- | ------- | ----------- | --------------------------------------------------- |
| **entity_did** | **str** | | [optional] [default to &#39;did:sov:test:1234&#39;] |
| **skip** | **int** | | [optional] [default to 0] |
| **limit** | **int** | | [optional] [default to 100] |
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**entity_did** | **str**| | [optional] [default to &#39;did:sov:test:120&#39;]
**skip** | **int**| | [optional] [default to 0]
**limit** | **int**| | [optional] [default to 100]
### Return type
@@ -72,20 +73,18 @@ No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
| ----------- | ------------------- | ---------------- |
| **200** | Successful Response | - |
| **422** | Validation Error | - |
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | Successful Response | - |
**422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **create_entity**
> Entity create_entity(entity_create)
Create Entity
@@ -112,7 +111,7 @@ configuration = openapi_client.Configuration(
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.EntitiesApi(api_client)
entity_create = openapi_client.EntityCreate() # EntityCreate |
entity_create = openapi_client.EntityCreate() # EntityCreate |
try:
# Create Entity
@@ -123,11 +122,13 @@ with openapi_client.ApiClient(configuration) as api_client:
print("Exception when calling EntitiesApi->create_entity: %s\n" % e)
```
### Parameters
| Name | Type | Description | Notes |
| ----------------- | ----------------------------------- | ----------- | ----- |
| **entity_create** | [**EntityCreate**](EntityCreate.md) | |
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**entity_create** | [**EntityCreate**](EntityCreate.md)| |
### Return type
@@ -139,20 +140,18 @@ No authorization required
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: application/json
- **Content-Type**: application/json
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
| ----------- | ------------------- | ---------------- |
| **200** | Successful Response | - |
| **422** | Validation Error | - |
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | Successful Response | - |
**422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **delete_entity**
> Dict[str, str] delete_entity(entity_did=entity_did)
Delete Entity
@@ -177,7 +176,7 @@ configuration = openapi_client.Configuration(
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.EntitiesApi(api_client)
entity_did = 'did:sov:test:1234' # str | (optional) (default to 'did:sov:test:1234')
entity_did = 'did:sov:test:120' # str | (optional) (default to 'did:sov:test:120')
try:
# Delete Entity
@@ -188,11 +187,13 @@ with openapi_client.ApiClient(configuration) as api_client:
print("Exception when calling EntitiesApi->delete_entity: %s\n" % e)
```
### Parameters
| Name | Type | Description | Notes |
| -------------- | ------- | ----------- | --------------------------------------------------- |
| **entity_did** | **str** | | [optional] [default to &#39;did:sov:test:1234&#39;] |
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**entity_did** | **str**| | [optional] [default to &#39;did:sov:test:120&#39;]
### Return type
@@ -204,20 +205,18 @@ No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
| ----------- | ------------------- | ---------------- |
| **200** | Successful Response | - |
| **422** | Validation Error | - |
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | Successful Response | - |
**422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **detach_entity**
> Dict[str, str] detach_entity(entity_did=entity_did, skip=skip, limit=limit)
Detach Entity
@@ -242,7 +241,7 @@ configuration = openapi_client.Configuration(
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.EntitiesApi(api_client)
entity_did = 'did:sov:test:1234' # str | (optional) (default to 'did:sov:test:1234')
entity_did = 'did:sov:test:120' # str | (optional) (default to 'did:sov:test:120')
skip = 0 # int | (optional) (default to 0)
limit = 100 # int | (optional) (default to 100)
@@ -255,13 +254,15 @@ with openapi_client.ApiClient(configuration) as api_client:
print("Exception when calling EntitiesApi->detach_entity: %s\n" % e)
```
### Parameters
| Name | Type | Description | Notes |
| -------------- | ------- | ----------- | --------------------------------------------------- |
| **entity_did** | **str** | | [optional] [default to &#39;did:sov:test:1234&#39;] |
| **skip** | **int** | | [optional] [default to 0] |
| **limit** | **int** | | [optional] [default to 100] |
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**entity_did** | **str**| | [optional] [default to &#39;did:sov:test:120&#39;]
**skip** | **int**| | [optional] [default to 0]
**limit** | **int**| | [optional] [default to 100]
### Return type
@@ -273,20 +274,18 @@ No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
| ----------- | ------------------- | ---------------- |
| **200** | Successful Response | - |
| **422** | Validation Error | - |
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | Successful Response | - |
**422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **get_all_entities**
> List[Entity] get_all_entities(skip=skip, limit=limit)
Get All Entities
@@ -324,12 +323,14 @@ with openapi_client.ApiClient(configuration) as api_client:
print("Exception when calling EntitiesApi->get_all_entities: %s\n" % e)
```
### Parameters
| Name | Type | Description | Notes |
| --------- | ------- | ----------- | --------------------------- |
| **skip** | **int** | | [optional] [default to 0] |
| **limit** | **int** | | [optional] [default to 100] |
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**skip** | **int**| | [optional] [default to 0]
**limit** | **int**| | [optional] [default to 100]
### Return type
@@ -341,20 +342,18 @@ No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
| ----------- | ------------------- | ---------------- |
| **200** | Successful Response | - |
| **422** | Validation Error | - |
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | Successful Response | - |
**422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **get_attached_entities**
> List[Entity] get_attached_entities(skip=skip, limit=limit)
Get Attached Entities
@@ -392,12 +391,14 @@ with openapi_client.ApiClient(configuration) as api_client:
print("Exception when calling EntitiesApi->get_attached_entities: %s\n" % e)
```
### Parameters
| Name | Type | Description | Notes |
| --------- | ------- | ----------- | --------------------------- |
| **skip** | **int** | | [optional] [default to 0] |
| **limit** | **int** | | [optional] [default to 100] |
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**skip** | **int**| | [optional] [default to 0]
**limit** | **int**| | [optional] [default to 100]
### Return type
@@ -409,20 +410,18 @@ No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
| ----------- | ------------------- | ---------------- |
| **200** | Successful Response | - |
| **422** | Validation Error | - |
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | Successful Response | - |
**422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **get_entity_by_did**
> Entity get_entity_by_did(entity_did=entity_did)
Get Entity By Did
@@ -448,7 +447,7 @@ configuration = openapi_client.Configuration(
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.EntitiesApi(api_client)
entity_did = 'did:sov:test:1234' # str | (optional) (default to 'did:sov:test:1234')
entity_did = 'did:sov:test:120' # str | (optional) (default to 'did:sov:test:120')
try:
# Get Entity By Did
@@ -459,11 +458,13 @@ with openapi_client.ApiClient(configuration) as api_client:
print("Exception when calling EntitiesApi->get_entity_by_did: %s\n" % e)
```
### Parameters
| Name | Type | Description | Notes |
| -------------- | ------- | ----------- | --------------------------------------------------- |
| **entity_did** | **str** | | [optional] [default to &#39;did:sov:test:1234&#39;] |
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**entity_did** | **str**| | [optional] [default to &#39;did:sov:test:120&#39;]
### Return type
@@ -475,86 +476,18 @@ No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
| ----------- | ------------------- | ---------------- |
| **200** | Successful Response | - |
| **422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **get_entity_by_name_or_did**
> Entity get_entity_by_name_or_did(entity_name_or_did=entity_name_or_did)
Get Entity By Name Or Did
### Example
```python
import time
import os
import openapi_client
from openapi_client.models.entity import Entity
from openapi_client.rest import ApiException
from pprint import pprint
# Defining the host is optional and defaults to http://localhost
# See configuration.py for a list of all supported configuration parameters.
configuration = openapi_client.Configuration(
host = "http://localhost"
)
# Enter a context with an instance of the API client
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.EntitiesApi(api_client)
entity_name_or_did = 'C1' # str | (optional) (default to 'C1')
try:
# Get Entity By Name Or Did
api_response = api_instance.get_entity_by_name_or_did(entity_name_or_did=entity_name_or_did)
print("The response of EntitiesApi->get_entity_by_name_or_did:\n")
pprint(api_response)
except Exception as e:
print("Exception when calling EntitiesApi->get_entity_by_name_or_did: %s\n" % e)
```
### Parameters
| Name | Type | Description | Notes |
| ---------------------- | ------- | ----------- | ------------------------------------ |
| **entity_name_or_did** | **str** | | [optional] [default to &#39;C1&#39;] |
### Return type
[**Entity**](Entity.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
| ----------- | ------------------- | ---------------- |
| **200** | Successful Response | - |
| **422** | Validation Error | - |
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | Successful Response | - |
**422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **get_entity_by_roles**
> List[Entity] get_entity_by_roles(roles)
Get Entity By Roles
@@ -581,7 +514,7 @@ configuration = openapi_client.Configuration(
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.EntitiesApi(api_client)
roles = [openapi_client.Role()] # List[Role] |
roles = [openapi_client.Role()] # List[Role] |
try:
# Get Entity By Roles
@@ -592,11 +525,13 @@ with openapi_client.ApiClient(configuration) as api_client:
print("Exception when calling EntitiesApi->get_entity_by_roles: %s\n" % e)
```
### Parameters
| Name | Type | Description | Notes |
| --------- | ------------------------- | ----------- | ----- |
| **roles** | [**List[Role]**](Role.md) | |
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**roles** | [**List[Role]**](Role.md)| |
### Return type
@@ -608,20 +543,18 @@ No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
| ----------- | ------------------- | ---------------- |
| **200** | Successful Response | - |
| **422** | Validation Error | - |
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | Successful Response | - |
**422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **is_attached**
> Dict[str, str] is_attached(entity_did=entity_did)
Is Attached
@@ -646,7 +579,7 @@ configuration = openapi_client.Configuration(
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.EntitiesApi(api_client)
entity_did = 'did:sov:test:1234' # str | (optional) (default to 'did:sov:test:1234')
entity_did = 'did:sov:test:120' # str | (optional) (default to 'did:sov:test:120')
try:
# Is Attached
@@ -657,11 +590,13 @@ with openapi_client.ApiClient(configuration) as api_client:
print("Exception when calling EntitiesApi->is_attached: %s\n" % e)
```
### Parameters
| Name | Type | Description | Notes |
| -------------- | ------- | ----------- | --------------------------------------------------- |
| **entity_did** | **str** | | [optional] [default to &#39;did:sov:test:1234&#39;] |
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**entity_did** | **str**| | [optional] [default to &#39;did:sov:test:120&#39;]
### Return type
@@ -673,14 +608,14 @@ No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
| ----------- | ------------------- | ---------------- |
| **200** | Successful Response | - |
| **422** | Validation Error | - |
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | Successful Response | - |
**422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)

View File

@@ -1,18 +1,18 @@
# Entity
## Properties
| Name | Type | Description | Notes |
| -------------------- | ------------------------- | ----------- | ----- |
| **did** | **str** | |
| **name** | **str** | |
| **ip** | **str** | |
| **network** | **str** | |
| **visible** | **bool** | |
| **other** | **object** | |
| **attached** | **bool** | |
| **stop_health_task** | **bool** | |
| **roles** | [**List[Role]**](Role.md) | |
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**did** | **str** | |
**name** | **str** | |
**ip** | **str** | |
**network** | **str** | |
**visible** | **bool** | |
**other** | **object** | |
**attached** | **bool** | |
**stop_health_task** | **bool** | |
**roles** | [**List[Role]**](Role.md) | |
## Example
@@ -31,5 +31,6 @@ entity_dict = entity_instance.to_dict()
# create an instance of Entity from a dict
entity_form_dict = entity.from_dict(entity_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -1,16 +1,16 @@
# EntityCreate
## Properties
| Name | Type | Description | Notes |
| ----------- | ------------------------- | ----------- | ----- |
| **did** | **str** | |
| **name** | **str** | |
| **ip** | **str** | |
| **network** | **str** | |
| **visible** | **bool** | |
| **other** | **object** | |
| **roles** | [**List[Role]**](Role.md) | |
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**did** | **str** | |
**name** | **str** | |
**ip** | **str** | |
**network** | **str** | |
**visible** | **bool** | |
**other** | **object** | |
**roles** | [**List[Role]**](Role.md) | |
## Example
@@ -29,5 +29,6 @@ entity_create_dict = entity_create_instance.to_dict()
# create an instance of EntityCreate from a dict
entity_create_form_dict = entity_create.from_dict(entity_create_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -1,17 +1,21 @@
# Eventmessage
## Properties
| Name | Type | Description | Notes |
| ------------- | ---------- | ----------- | ----- |
| **timestamp** | **int** | |
| **group** | **int** | |
| **group_id** | **int** | |
| **msg_type** | **int** | |
| **src_did** | **str** | |
| **des_did** | **str** | |
| **msg** | **object** | |
| **id** | **int** | |
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**timestamp** | **int** | |
**group** | **int** | |
**group_id** | **int** | |
**msg_type** | **int** | |
**src_did** | **str** | |
**des_did** | **str** | |
**msg** | **object** | |
**id** | **int** | |
**des_name** | **str** | | [optional]
**src_name** | **str** | | [optional]
**msg_type_name** | **str** | | [optional]
**group_name** | **str** | | [optional]
## Example
@@ -30,5 +34,6 @@ eventmessage_dict = eventmessage_instance.to_dict()
# create an instance of Eventmessage from a dict
eventmessage_form_dict = eventmessage.from_dict(eventmessage_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -1,16 +1,16 @@
# EventmessageCreate
## Properties
| Name | Type | Description | Notes |
| ------------- | ---------- | ----------- | ----- |
| **timestamp** | **int** | |
| **group** | **int** | |
| **group_id** | **int** | |
| **msg_type** | **int** | |
| **src_did** | **str** | |
| **des_did** | **str** | |
| **msg** | **object** | |
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**timestamp** | **int** | |
**group** | **int** | |
**group_id** | **int** | |
**msg_type** | **int** | |
**src_did** | **str** | |
**des_did** | **str** | |
**msg** | **object** | |
## Example
@@ -29,5 +29,6 @@ eventmessage_create_dict = eventmessage_create_instance.to_dict()
# create an instance of EventmessageCreate from a dict
eventmessage_create_form_dict = eventmessage_create.from_dict(eventmessage_create_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -1,14 +1,14 @@
# openapi_client.EventmessagesApi
All URIs are relative to _http://localhost_
All URIs are relative to *http://localhost*
Method | HTTP request | Description
------------- | ------------- | -------------
[**create_eventmessage**](EventmessagesApi.md#create_eventmessage) | **POST** /api/v1/event_message | Create Eventmessage
[**get_all_eventmessages**](EventmessagesApi.md#get_all_eventmessages) | **GET** /api/v1/event_messages | Get All Eventmessages
| Method | HTTP request | Description |
| ---------------------------------------------------------------------- | ------------------------------ | --------------------- |
| [**create_eventmessage**](EventmessagesApi.md#create_eventmessage) | **POST** /api/v1/event_message | Create Eventmessage |
| [**get_all_eventmessages**](EventmessagesApi.md#get_all_eventmessages) | **GET** /api/v1/event_messages | Get All Eventmessages |
# **create_eventmessage**
> Eventmessage create_eventmessage(eventmessage_create)
Create Eventmessage
@@ -35,7 +35,7 @@ configuration = openapi_client.Configuration(
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.EventmessagesApi(api_client)
eventmessage_create = openapi_client.EventmessageCreate() # EventmessageCreate |
eventmessage_create = openapi_client.EventmessageCreate() # EventmessageCreate |
try:
# Create Eventmessage
@@ -46,11 +46,13 @@ with openapi_client.ApiClient(configuration) as api_client:
print("Exception when calling EventmessagesApi->create_eventmessage: %s\n" % e)
```
### Parameters
| Name | Type | Description | Notes |
| ----------------------- | ----------------------------------------------- | ----------- | ----- |
| **eventmessage_create** | [**EventmessageCreate**](EventmessageCreate.md) | |
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**eventmessage_create** | [**EventmessageCreate**](EventmessageCreate.md)| |
### Return type
@@ -62,21 +64,19 @@ No authorization required
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: application/json
- **Content-Type**: application/json
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
| ----------- | ------------------- | ---------------- |
| **200** | Successful Response | - |
| **422** | Validation Error | - |
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | Successful Response | - |
**422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **get_all_eventmessages**
> List[Eventmessage] get_all_eventmessages(skip=skip, limit=limit)
> get_all_eventmessages(skip=skip, limit=limit)
Get All Eventmessages
@@ -86,7 +86,6 @@ Get All Eventmessages
import time
import os
import openapi_client
from openapi_client.models.eventmessage import Eventmessage
from openapi_client.rest import ApiException
from pprint import pprint
@@ -106,23 +105,23 @@ with openapi_client.ApiClient(configuration) as api_client:
try:
# Get All Eventmessages
api_response = api_instance.get_all_eventmessages(skip=skip, limit=limit)
print("The response of EventmessagesApi->get_all_eventmessages:\n")
pprint(api_response)
api_instance.get_all_eventmessages(skip=skip, limit=limit)
except Exception as e:
print("Exception when calling EventmessagesApi->get_all_eventmessages: %s\n" % e)
```
### Parameters
| Name | Type | Description | Notes |
| --------- | ------- | ----------- | --------------------------- |
| **skip** | **int** | | [optional] [default to 0] |
| **limit** | **int** | | [optional] [default to 100] |
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**skip** | **int**| | [optional] [default to 0]
**limit** | **int**| | [optional] [default to 100]
### Return type
[**List[Eventmessage]**](Eventmessage.md)
void (empty response body)
### Authorization
@@ -130,14 +129,14 @@ No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
| ----------- | ------------------- | ---------------- |
| **200** | Successful Response | - |
| **422** | Validation Error | - |
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | Successful Response | - |
**422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)

View File

@@ -1,10 +1,10 @@
# HTTPValidationError
## Properties
| Name | Type | Description | Notes |
| ---------- | ----------------------------------------------- | ----------- | ---------- |
| **detail** | [**List[ValidationError]**](ValidationError.md) | | [optional] |
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**detail** | [**List[ValidationError]**](ValidationError.md) | | [optional]
## Example
@@ -23,5 +23,6 @@ http_validation_error_dict = http_validation_error_instance.to_dict()
# create an instance of HTTPValidationError from a dict
http_validation_error_form_dict = http_validation_error.from_dict(http_validation_error_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -1,11 +1,11 @@
# Machine
## Properties
| Name | Type | Description | Notes |
| ---------- | ----------------------- | ----------- | ----- |
| **name** | **str** | |
| **status** | [**Status**](Status.md) | |
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**name** | **str** | |
**status** | [**Status**](Status.md) | |
## Example
@@ -24,5 +24,6 @@ machine_dict = machine_instance.to_dict()
# create an instance of Machine from a dict
machine_form_dict = machine.from_dict(machine_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -0,0 +1,77 @@
# openapi_client.RepositoriesApi
All URIs are relative to *http://localhost*
Method | HTTP request | Description
------------- | ------------- | -------------
[**get_all_repositories**](RepositoriesApi.md#get_all_repositories) | **GET** /api/v1/repositories | Get All Repositories
# **get_all_repositories**
> List[Service] get_all_repositories(skip=skip, limit=limit)
Get All Repositories
### Example
```python
import time
import os
import openapi_client
from openapi_client.models.service import Service
from openapi_client.rest import ApiException
from pprint import pprint
# Defining the host is optional and defaults to http://localhost
# See configuration.py for a list of all supported configuration parameters.
configuration = openapi_client.Configuration(
host = "http://localhost"
)
# Enter a context with an instance of the API client
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.RepositoriesApi(api_client)
skip = 0 # int | (optional) (default to 0)
limit = 100 # int | (optional) (default to 100)
try:
# Get All Repositories
api_response = api_instance.get_all_repositories(skip=skip, limit=limit)
print("The response of RepositoriesApi->get_all_repositories:\n")
pprint(api_response)
except Exception as e:
print("Exception when calling RepositoriesApi->get_all_repositories: %s\n" % e)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**skip** | **int**| | [optional] [default to 0]
**limit** | **int**| | [optional] [default to 100]
### Return type
[**List[Service]**](Service.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | Successful Response | - |
**422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)

View File

@@ -1,15 +1,14 @@
# Resolution
## Properties
| Name | Type | Description | Notes |
| ------------------ | ------------ | ----------- | ----- |
| **requester_name** | **str** | |
| **requester_did** | **str** | |
| **resolved_did** | **str** | |
| **other** | **object** | |
| **timestamp** | **datetime** | |
| **id** | **int** | |
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**requester_name** | **str** | |
**requester_did** | **str** | |
**resolved_did** | **str** | |
**other** | **object** | |
**timestamp** | **datetime** | |
## Example
@@ -28,5 +27,6 @@ resolution_dict = resolution_instance.to_dict()
# create an instance of Resolution from a dict
resolution_form_dict = resolution.from_dict(resolution_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -1,13 +1,13 @@
# openapi_client.ResolutionApi
All URIs are relative to _http://localhost_
All URIs are relative to *http://localhost*
Method | HTTP request | Description
------------- | ------------- | -------------
[**get_all_resolutions**](ResolutionApi.md#get_all_resolutions) | **GET** /api/v1/resolutions | Get All Resolutions
| Method | HTTP request | Description |
| --------------------------------------------------------------- | --------------------------- | ------------------- |
| [**get_all_resolutions**](ResolutionApi.md#get_all_resolutions) | **GET** /api/v1/resolutions | Get All Resolutions |
# **get_all_resolutions**
> List[Resolution] get_all_resolutions(skip=skip, limit=limit)
Get All Resolutions
@@ -45,12 +45,14 @@ with openapi_client.ApiClient(configuration) as api_client:
print("Exception when calling ResolutionApi->get_all_resolutions: %s\n" % e)
```
### Parameters
| Name | Type | Description | Notes |
| --------- | ------- | ----------- | --------------------------- |
| **skip** | **int** | | [optional] [default to 0] |
| **limit** | **int** | | [optional] [default to 100] |
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**skip** | **int**| | [optional] [default to 0]
**limit** | **int**| | [optional] [default to 100]
### Return type
@@ -62,14 +64,14 @@ No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
| ----------- | ------------------- | ---------------- |
| **200** | Successful Response | - |
| **422** | Validation Error | - |
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | Successful Response | - |
**422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)

View File

@@ -3,8 +3,9 @@
An enumeration.
## Properties
| Name | Type | Description | Notes |
| ---- | ---- | ----------- | ----- |
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -1,17 +1,18 @@
# Service
## Properties
| Name | Type | Description | Notes |
| ---------------- | ----------------------- | ----------- | ----- |
| **uuid** | **str** | |
| **service_name** | **str** | |
| **service_type** | **str** | |
| **endpoint_url** | **str** | |
| **status** | **str** | |
| **other** | **object** | |
| **entity_did** | **str** | |
| **entity** | [**Entity**](Entity.md) | |
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**uuid** | **str** | |
**service_name** | **str** | |
**service_type** | **str** | |
**endpoint_url** | **str** | |
**other** | **object** | |
**entity_did** | **str** | |
**status** | **object** | |
**action** | **object** | |
**usage** | [**List[ServiceUsage]**](ServiceUsage.md) | |
## Example
@@ -30,5 +31,6 @@ service_dict = service_instance.to_dict()
# create an instance of Service from a dict
service_form_dict = service.from_dict(service_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -1,16 +1,18 @@
# ServiceCreate
## Properties
| Name | Type | Description | Notes |
| ---------------- | ---------- | ----------- | ----- |
| **uuid** | **str** | |
| **service_name** | **str** | |
| **service_type** | **str** | |
| **endpoint_url** | **str** | |
| **status** | **str** | |
| **other** | **object** | |
| **entity_did** | **str** | |
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**uuid** | **str** | |
**service_name** | **str** | |
**service_type** | **str** | |
**endpoint_url** | **str** | |
**other** | **object** | |
**entity_did** | **str** | |
**status** | **object** | |
**action** | **object** | |
**usage** | [**List[ServiceUsageCreate]**](ServiceUsageCreate.md) | |
## Example
@@ -29,5 +31,6 @@ service_create_dict = service_create_instance.to_dict()
# create an instance of ServiceCreate from a dict
service_create_form_dict = service_create.from_dict(service_create_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -0,0 +1,29 @@
# ServiceUsage
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**times_consumed** | **int** | |
**consumer_entity_did** | **str** | |
## Example
```python
from openapi_client.models.service_usage import ServiceUsage
# TODO update the JSON string below
json = "{}"
# create an instance of ServiceUsage from a JSON string
service_usage_instance = ServiceUsage.from_json(json)
# print the JSON string representation of the object
print ServiceUsage.to_json()
# convert the object into a dict
service_usage_dict = service_usage_instance.to_dict()
# create an instance of ServiceUsage from a dict
service_usage_form_dict = service_usage.from_dict(service_usage_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -0,0 +1,29 @@
# ServiceUsageCreate
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**times_consumed** | **int** | |
**consumer_entity_did** | **str** | |
## Example
```python
from openapi_client.models.service_usage_create import ServiceUsageCreate
# TODO update the JSON string below
json = "{}"
# create an instance of ServiceUsageCreate from a JSON string
service_usage_create_instance = ServiceUsageCreate.from_json(json)
# print the JSON string representation of the object
print ServiceUsageCreate.to_json()
# convert the object into a dict
service_usage_create_dict = service_usage_create_instance.to_dict()
# create an instance of ServiceUsageCreate from a dict
service_usage_create_form_dict = service_usage_create.from_dict(service_usage_create_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -1,17 +1,90 @@
# openapi_client.ServicesApi
All URIs are relative to _http://localhost_
All URIs are relative to *http://localhost*
| Method | HTTP request | Description |
| ----------------------------------------------------------------------------- | --------------------------------------- | --------------------------- |
| [**create_service**](ServicesApi.md#create_service) | **POST** /api/v1/service | Create Service |
| [**delete_service**](ServicesApi.md#delete_service) | **DELETE** /api/v1/service | Delete Service |
| [**get_all_services**](ServicesApi.md#get_all_services) | **GET** /api/v1/services | Get All Services |
| [**get_service_by_did**](ServicesApi.md#get_service_by_did) | **GET** /api/v1/service | Get Service By Did |
| [**get_services_without_entity**](ServicesApi.md#get_services_without_entity) | **GET** /api/v1/services_without_entity | Get Services Without Entity |
Method | HTTP request | Description
------------- | ------------- | -------------
[**add_service_usage**](ServicesApi.md#add_service_usage) | **POST** /api/v1/service_usage | Add Service Usage
[**create_service**](ServicesApi.md#create_service) | **POST** /api/v1/service | Create Service
[**delete_service**](ServicesApi.md#delete_service) | **DELETE** /api/v1/service | Delete Service
[**get_all_services**](ServicesApi.md#get_all_services) | **GET** /api/v1/services | Get All Services
[**get_service_by_did**](ServicesApi.md#get_service_by_did) | **GET** /api/v1/service_by_did | Get Service By Did
[**get_service_by_uuid**](ServicesApi.md#get_service_by_uuid) | **GET** /api/v1/service | Get Service By Uuid
[**get_services_without_entity**](ServicesApi.md#get_services_without_entity) | **GET** /api/v1/services_without_entity | Get Services Without Entity
[**inc_service_usage**](ServicesApi.md#inc_service_usage) | **PUT** /api/v1/inc_service_usage | Inc Service Usage
[**update_service**](ServicesApi.md#update_service) | **PUT** /api/v1/service | Update Service
# **add_service_usage**
> Service add_service_usage(service_usage_create, service_uuid=service_uuid)
Add Service Usage
### Example
```python
import time
import os
import openapi_client
from openapi_client.models.service import Service
from openapi_client.models.service_usage_create import ServiceUsageCreate
from openapi_client.rest import ApiException
from pprint import pprint
# Defining the host is optional and defaults to http://localhost
# See configuration.py for a list of all supported configuration parameters.
configuration = openapi_client.Configuration(
host = "http://localhost"
)
# Enter a context with an instance of the API client
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.ServicesApi(api_client)
service_usage_create = openapi_client.ServiceUsageCreate() # ServiceUsageCreate |
service_uuid = 'bdd640fb-0667-1ad1-1c80-317fa3b1799d' # str | (optional) (default to 'bdd640fb-0667-1ad1-1c80-317fa3b1799d')
try:
# Add Service Usage
api_response = api_instance.add_service_usage(service_usage_create, service_uuid=service_uuid)
print("The response of ServicesApi->add_service_usage:\n")
pprint(api_response)
except Exception as e:
print("Exception when calling ServicesApi->add_service_usage: %s\n" % e)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**service_usage_create** | [**ServiceUsageCreate**](ServiceUsageCreate.md)| |
**service_uuid** | **str**| | [optional] [default to &#39;bdd640fb-0667-1ad1-1c80-317fa3b1799d&#39;]
### Return type
[**Service**](Service.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | Successful Response | - |
**422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **create_service**
> Service create_service(service_create)
Create Service
@@ -38,7 +111,7 @@ configuration = openapi_client.Configuration(
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.ServicesApi(api_client)
service_create = openapi_client.ServiceCreate() # ServiceCreate |
service_create = openapi_client.ServiceCreate() # ServiceCreate |
try:
# Create Service
@@ -49,11 +122,13 @@ with openapi_client.ApiClient(configuration) as api_client:
print("Exception when calling ServicesApi->create_service: %s\n" % e)
```
### Parameters
| Name | Type | Description | Notes |
| ------------------ | ------------------------------------- | ----------- | ----- |
| **service_create** | [**ServiceCreate**](ServiceCreate.md) | |
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**service_create** | [**ServiceCreate**](ServiceCreate.md)| |
### Return type
@@ -65,20 +140,18 @@ No authorization required
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: application/json
- **Content-Type**: application/json
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
| ----------- | ------------------- | ---------------- |
| **200** | Successful Response | - |
| **422** | Validation Error | - |
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | Successful Response | - |
**422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **delete_service**
> Dict[str, str] delete_service(entity_did=entity_did)
Delete Service
@@ -103,7 +176,7 @@ configuration = openapi_client.Configuration(
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.ServicesApi(api_client)
entity_did = 'did:sov:test:1234' # str | (optional) (default to 'did:sov:test:1234')
entity_did = 'did:sov:test:120' # str | (optional) (default to 'did:sov:test:120')
try:
# Delete Service
@@ -114,11 +187,13 @@ with openapi_client.ApiClient(configuration) as api_client:
print("Exception when calling ServicesApi->delete_service: %s\n" % e)
```
### Parameters
| Name | Type | Description | Notes |
| -------------- | ------- | ----------- | --------------------------------------------------- |
| **entity_did** | **str** | | [optional] [default to &#39;did:sov:test:1234&#39;] |
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**entity_did** | **str**| | [optional] [default to &#39;did:sov:test:120&#39;]
### Return type
@@ -130,20 +205,18 @@ No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
| ----------- | ------------------- | ---------------- |
| **200** | Successful Response | - |
| **422** | Validation Error | - |
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | Successful Response | - |
**422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **get_all_services**
> List[Service] get_all_services(skip=skip, limit=limit)
Get All Services
@@ -181,12 +254,14 @@ with openapi_client.ApiClient(configuration) as api_client:
print("Exception when calling ServicesApi->get_all_services: %s\n" % e)
```
### Parameters
| Name | Type | Description | Notes |
| --------- | ------- | ----------- | --------------------------- |
| **skip** | **int** | | [optional] [default to 0] |
| **limit** | **int** | | [optional] [default to 100] |
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**skip** | **int**| | [optional] [default to 0]
**limit** | **int**| | [optional] [default to 100]
### Return type
@@ -198,20 +273,18 @@ No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
| ----------- | ------------------- | ---------------- |
| **200** | Successful Response | - |
| **422** | Validation Error | - |
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | Successful Response | - |
**422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **get_service_by_did**
> List[Service] get_service_by_did(entity_did=entity_did, skip=skip, limit=limit)
Get Service By Did
@@ -237,7 +310,7 @@ configuration = openapi_client.Configuration(
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.ServicesApi(api_client)
entity_did = 'did:sov:test:1234' # str | (optional) (default to 'did:sov:test:1234')
entity_did = 'did:sov:test:120' # str | (optional) (default to 'did:sov:test:120')
skip = 0 # int | (optional) (default to 0)
limit = 100 # int | (optional) (default to 100)
@@ -250,13 +323,15 @@ with openapi_client.ApiClient(configuration) as api_client:
print("Exception when calling ServicesApi->get_service_by_did: %s\n" % e)
```
### Parameters
| Name | Type | Description | Notes |
| -------------- | ------- | ----------- | --------------------------------------------------- |
| **entity_did** | **str** | | [optional] [default to &#39;did:sov:test:1234&#39;] |
| **skip** | **int** | | [optional] [default to 0] |
| **limit** | **int** | | [optional] [default to 100] |
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**entity_did** | **str**| | [optional] [default to &#39;did:sov:test:120&#39;]
**skip** | **int**| | [optional] [default to 0]
**limit** | **int**| | [optional] [default to 100]
### Return type
@@ -268,20 +343,88 @@ No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | Successful Response | - |
**422** | Validation Error | - |
| Status code | Description | Response headers |
| ----------- | ------------------- | ---------------- |
| **200** | Successful Response | - |
| **422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **get_service_by_uuid**
> Service get_service_by_uuid(uuid=uuid, skip=skip, limit=limit)
Get Service By Uuid
### Example
```python
import time
import os
import openapi_client
from openapi_client.models.service import Service
from openapi_client.rest import ApiException
from pprint import pprint
# Defining the host is optional and defaults to http://localhost
# See configuration.py for a list of all supported configuration parameters.
configuration = openapi_client.Configuration(
host = "http://localhost"
)
# Enter a context with an instance of the API client
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.ServicesApi(api_client)
uuid = 'bdd640fb-0667-1ad1-1c80-317fa3b1799d' # str | (optional) (default to 'bdd640fb-0667-1ad1-1c80-317fa3b1799d')
skip = 0 # int | (optional) (default to 0)
limit = 100 # int | (optional) (default to 100)
try:
# Get Service By Uuid
api_response = api_instance.get_service_by_uuid(uuid=uuid, skip=skip, limit=limit)
print("The response of ServicesApi->get_service_by_uuid:\n")
pprint(api_response)
except Exception as e:
print("Exception when calling ServicesApi->get_service_by_uuid: %s\n" % e)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**uuid** | **str**| | [optional] [default to &#39;bdd640fb-0667-1ad1-1c80-317fa3b1799d&#39;]
**skip** | **int**| | [optional] [default to 0]
**limit** | **int**| | [optional] [default to 100]
### Return type
[**Service**](Service.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | Successful Response | - |
**422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **get_services_without_entity**
> List[Service] get_services_without_entity(entity_did=entity_did, skip=skip, limit=limit)
Get Services Without Entity
@@ -307,7 +450,7 @@ configuration = openapi_client.Configuration(
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.ServicesApi(api_client)
entity_did = 'did:sov:test:1234' # str | (optional) (default to 'did:sov:test:1234')
entity_did = 'did:sov:test:120' # str | (optional) (default to 'did:sov:test:120')
skip = 0 # int | (optional) (default to 0)
limit = 100 # int | (optional) (default to 100)
@@ -320,13 +463,15 @@ with openapi_client.ApiClient(configuration) as api_client:
print("Exception when calling ServicesApi->get_services_without_entity: %s\n" % e)
```
### Parameters
| Name | Type | Description | Notes |
| -------------- | ------- | ----------- | --------------------------------------------------- |
| **entity_did** | **str** | | [optional] [default to &#39;did:sov:test:1234&#39;] |
| **skip** | **int** | | [optional] [default to 0] |
| **limit** | **int** | | [optional] [default to 100] |
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**entity_did** | **str**| | [optional] [default to &#39;did:sov:test:120&#39;]
**skip** | **int**| | [optional] [default to 0]
**limit** | **int**| | [optional] [default to 100]
### Return type
@@ -338,14 +483,154 @@ No authorization required
### HTTP request headers
- **Content-Type**: Not defined
- **Accept**: application/json
- **Content-Type**: Not defined
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
| ----------- | ------------------- | ---------------- |
| **200** | Successful Response | - |
| **422** | Validation Error | - |
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | Successful Response | - |
**422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **inc_service_usage**
> Service inc_service_usage(service_usage_create, consumer_entity_did=consumer_entity_did, service_uuid=service_uuid)
Inc Service Usage
### Example
```python
import time
import os
import openapi_client
from openapi_client.models.service import Service
from openapi_client.models.service_usage_create import ServiceUsageCreate
from openapi_client.rest import ApiException
from pprint import pprint
# Defining the host is optional and defaults to http://localhost
# See configuration.py for a list of all supported configuration parameters.
configuration = openapi_client.Configuration(
host = "http://localhost"
)
# Enter a context with an instance of the API client
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.ServicesApi(api_client)
service_usage_create = openapi_client.ServiceUsageCreate() # ServiceUsageCreate |
consumer_entity_did = 'did:sov:test:120' # str | (optional) (default to 'did:sov:test:120')
service_uuid = 'bdd640fb-0667-1ad1-1c80-317fa3b1799d' # str | (optional) (default to 'bdd640fb-0667-1ad1-1c80-317fa3b1799d')
try:
# Inc Service Usage
api_response = api_instance.inc_service_usage(service_usage_create, consumer_entity_did=consumer_entity_did, service_uuid=service_uuid)
print("The response of ServicesApi->inc_service_usage:\n")
pprint(api_response)
except Exception as e:
print("Exception when calling ServicesApi->inc_service_usage: %s\n" % e)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**service_usage_create** | [**ServiceUsageCreate**](ServiceUsageCreate.md)| |
**consumer_entity_did** | **str**| | [optional] [default to &#39;did:sov:test:120&#39;]
**service_uuid** | **str**| | [optional] [default to &#39;bdd640fb-0667-1ad1-1c80-317fa3b1799d&#39;]
### Return type
[**Service**](Service.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | Successful Response | - |
**422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **update_service**
> Service update_service(service_create, uuid=uuid)
Update Service
### Example
```python
import time
import os
import openapi_client
from openapi_client.models.service import Service
from openapi_client.models.service_create import ServiceCreate
from openapi_client.rest import ApiException
from pprint import pprint
# Defining the host is optional and defaults to http://localhost
# See configuration.py for a list of all supported configuration parameters.
configuration = openapi_client.Configuration(
host = "http://localhost"
)
# Enter a context with an instance of the API client
with openapi_client.ApiClient(configuration) as api_client:
# Create an instance of the API class
api_instance = openapi_client.ServicesApi(api_client)
service_create = openapi_client.ServiceCreate() # ServiceCreate |
uuid = 'bdd640fb-0667-1ad1-1c80-317fa3b1799d' # str | (optional) (default to 'bdd640fb-0667-1ad1-1c80-317fa3b1799d')
try:
# Update Service
api_response = api_instance.update_service(service_create, uuid=uuid)
print("The response of ServicesApi->update_service:\n")
pprint(api_response)
except Exception as e:
print("Exception when calling ServicesApi->update_service: %s\n" % e)
```
### Parameters
Name | Type | Description | Notes
------------- | ------------- | ------------- | -------------
**service_create** | [**ServiceCreate**](ServiceCreate.md)| |
**uuid** | **str**| | [optional] [default to &#39;bdd640fb-0667-1ad1-1c80-317fa3b1799d&#39;]
### Return type
[**Service**](Service.md)
### Authorization
No authorization required
### HTTP request headers
- **Content-Type**: application/json
- **Accept**: application/json
### HTTP response details
| Status code | Description | Response headers |
|-------------|-------------|------------------|
**200** | Successful Response | - |
**422** | Validation Error | - |
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)

View File

@@ -3,8 +3,9 @@
An enumeration.
## Properties
| Name | Type | Description | Notes |
| ---- | ---- | ----------- | ----- |
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -1,12 +1,12 @@
# ValidationError
## Properties
| Name | Type | Description | Notes |
| -------- | --------------------------------------------------------------- | ----------- | ----- |
| **loc** | [**List[ValidationErrorLocInner]**](ValidationErrorLocInner.md) | |
| **msg** | **str** | |
| **type** | **str** | |
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**loc** | [**List[ValidationErrorLocInner]**](ValidationErrorLocInner.md) | |
**msg** | **str** | |
**type** | **str** | |
## Example
@@ -25,5 +25,6 @@ validation_error_dict = validation_error_instance.to_dict()
# create an instance of ValidationError from a dict
validation_error_form_dict = validation_error.from_dict(validation_error_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -1,9 +1,9 @@
# ValidationErrorLocInner
## Properties
| Name | Type | Description | Notes |
| ---- | ---- | ----------- | ----- |
## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
## Example
@@ -22,5 +22,6 @@ validation_error_loc_inner_dict = validation_error_loc_inner_instance.to_dict()
# create an instance of ValidationErrorLocInner from a dict
validation_error_loc_inner_form_dict = validation_error_loc_inner.from_dict(validation_error_loc_inner_dict)
```
[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)

View File

@@ -24,6 +24,8 @@ from openapi_client.models.resolution import Resolution
from openapi_client.models.role import Role
from openapi_client.models.service import Service
from openapi_client.models.service_create import ServiceCreate
from openapi_client.models.service_usage import ServiceUsage
from openapi_client.models.service_usage_create import ServiceUsageCreate
from openapi_client.models.status import Status
from openapi_client.models.validation_error import ValidationError
from openapi_client.models.validation_error_loc_inner import ValidationErrorLocInner

View File

@@ -18,7 +18,7 @@ import re # noqa: F401
import json
from typing import Any, Dict
from typing import Any, Dict, Optional
from pydantic import BaseModel, Field, StrictInt, StrictStr
class Eventmessage(BaseModel):
@@ -33,7 +33,11 @@ class Eventmessage(BaseModel):
des_did: StrictStr = Field(...)
msg: Dict[str, Any] = Field(...)
id: StrictInt = Field(...)
__properties = ["timestamp", "group", "group_id", "msg_type", "src_did", "des_did", "msg", "id"]
des_name: Optional[StrictStr] = None
src_name: Optional[StrictStr] = None
msg_type_name: Optional[StrictStr] = None
group_name: Optional[StrictStr] = None
__properties = ["timestamp", "group", "group_id", "msg_type", "src_did", "des_did", "msg", "id", "des_name", "src_name", "msg_type_name", "group_name"]
class Config:
"""Pydantic configuration"""
@@ -78,7 +82,11 @@ class Eventmessage(BaseModel):
"src_did": obj.get("src_did"),
"des_did": obj.get("des_did"),
"msg": obj.get("msg"),
"id": obj.get("id")
"id": obj.get("id"),
"des_name": obj.get("des_name"),
"src_name": obj.get("src_name"),
"msg_type_name": obj.get("msg_type_name"),
"group_name": obj.get("group_name")
})
return _obj

View File

@@ -19,7 +19,7 @@ import json
from datetime import datetime
from typing import Any, Dict
from pydantic import BaseModel, Field, StrictInt, StrictStr
from pydantic import BaseModel, Field, StrictStr
class Resolution(BaseModel):
"""
@@ -30,8 +30,7 @@ class Resolution(BaseModel):
resolved_did: StrictStr = Field(...)
other: Dict[str, Any] = Field(...)
timestamp: datetime = Field(...)
id: StrictInt = Field(...)
__properties = ["requester_name", "requester_did", "resolved_did", "other", "timestamp", "id"]
__properties = ["requester_name", "requester_did", "resolved_did", "other", "timestamp"]
class Config:
"""Pydantic configuration"""
@@ -73,8 +72,7 @@ class Resolution(BaseModel):
"requester_did": obj.get("requester_did"),
"resolved_did": obj.get("resolved_did"),
"other": obj.get("other"),
"timestamp": obj.get("timestamp"),
"id": obj.get("id")
"timestamp": obj.get("timestamp")
})
return _obj

View File

@@ -18,9 +18,9 @@ import re # noqa: F401
import json
from typing import Any, Dict
from pydantic import BaseModel, Field, StrictStr
from openapi_client.models.entity import Entity
from typing import Any, Dict, List
from pydantic import BaseModel, Field, StrictStr, conlist
from openapi_client.models.service_usage import ServiceUsage
class Service(BaseModel):
"""
@@ -30,11 +30,12 @@ class Service(BaseModel):
service_name: StrictStr = Field(...)
service_type: StrictStr = Field(...)
endpoint_url: StrictStr = Field(...)
status: StrictStr = Field(...)
other: Dict[str, Any] = Field(...)
entity_did: StrictStr = Field(...)
entity: Entity = Field(...)
__properties = ["uuid", "service_name", "service_type", "endpoint_url", "status", "other", "entity_did", "entity"]
status: Dict[str, Any] = Field(...)
action: Dict[str, Any] = Field(...)
usage: conlist(ServiceUsage) = Field(...)
__properties = ["uuid", "service_name", "service_type", "endpoint_url", "other", "entity_did", "status", "action", "usage"]
class Config:
"""Pydantic configuration"""
@@ -60,9 +61,13 @@ class Service(BaseModel):
exclude={
},
exclude_none=True)
# override the default output from pydantic by calling `to_dict()` of entity
if self.entity:
_dict['entity'] = self.entity.to_dict()
# override the default output from pydantic by calling `to_dict()` of each item in usage (list)
_items = []
if self.usage:
for _item in self.usage:
if _item:
_items.append(_item.to_dict())
_dict['usage'] = _items
return _dict
@classmethod
@@ -79,10 +84,11 @@ class Service(BaseModel):
"service_name": obj.get("service_name"),
"service_type": obj.get("service_type"),
"endpoint_url": obj.get("endpoint_url"),
"status": obj.get("status"),
"other": obj.get("other"),
"entity_did": obj.get("entity_did"),
"entity": Entity.from_dict(obj.get("entity")) if obj.get("entity") is not None else None
"status": obj.get("status"),
"action": obj.get("action"),
"usage": [ServiceUsage.from_dict(_item) for _item in obj.get("usage")] if obj.get("usage") is not None else None
})
return _obj

View File

@@ -18,8 +18,9 @@ import re # noqa: F401
import json
from typing import Any, Dict
from pydantic import BaseModel, Field, StrictStr
from typing import Any, Dict, List
from pydantic import BaseModel, Field, StrictStr, conlist
from openapi_client.models.service_usage_create import ServiceUsageCreate
class ServiceCreate(BaseModel):
"""
@@ -29,10 +30,12 @@ class ServiceCreate(BaseModel):
service_name: StrictStr = Field(...)
service_type: StrictStr = Field(...)
endpoint_url: StrictStr = Field(...)
status: StrictStr = Field(...)
other: Dict[str, Any] = Field(...)
entity_did: StrictStr = Field(...)
__properties = ["uuid", "service_name", "service_type", "endpoint_url", "status", "other", "entity_did"]
status: Dict[str, Any] = Field(...)
action: Dict[str, Any] = Field(...)
usage: conlist(ServiceUsageCreate) = Field(...)
__properties = ["uuid", "service_name", "service_type", "endpoint_url", "other", "entity_did", "status", "action", "usage"]
class Config:
"""Pydantic configuration"""
@@ -58,6 +61,13 @@ class ServiceCreate(BaseModel):
exclude={
},
exclude_none=True)
# override the default output from pydantic by calling `to_dict()` of each item in usage (list)
_items = []
if self.usage:
for _item in self.usage:
if _item:
_items.append(_item.to_dict())
_dict['usage'] = _items
return _dict
@classmethod
@@ -74,9 +84,11 @@ class ServiceCreate(BaseModel):
"service_name": obj.get("service_name"),
"service_type": obj.get("service_type"),
"endpoint_url": obj.get("endpoint_url"),
"status": obj.get("status"),
"other": obj.get("other"),
"entity_did": obj.get("entity_did")
"entity_did": obj.get("entity_did"),
"status": obj.get("status"),
"action": obj.get("action"),
"usage": [ServiceUsageCreate.from_dict(_item) for _item in obj.get("usage")] if obj.get("usage") is not None else None
})
return _obj

View File

@@ -0,0 +1,73 @@
# coding: utf-8
"""
FastAPI
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.1.0
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
from __future__ import annotations
import pprint
import re # noqa: F401
import json
from pydantic import BaseModel, Field, StrictInt, StrictStr
class ServiceUsage(BaseModel):
"""
ServiceUsage
"""
times_consumed: StrictInt = Field(...)
consumer_entity_did: StrictStr = Field(...)
__properties = ["times_consumed", "consumer_entity_did"]
class Config:
"""Pydantic configuration"""
allow_population_by_field_name = True
validate_assignment = True
def to_str(self) -> str:
"""Returns the string representation of the model using alias"""
return pprint.pformat(self.dict(by_alias=True))
def to_json(self) -> str:
"""Returns the JSON representation of the model using alias"""
return json.dumps(self.to_dict())
@classmethod
def from_json(cls, json_str: str) -> ServiceUsage:
"""Create an instance of ServiceUsage from a JSON string"""
return cls.from_dict(json.loads(json_str))
def to_dict(self):
"""Returns the dictionary representation of the model using alias"""
_dict = self.dict(by_alias=True,
exclude={
},
exclude_none=True)
return _dict
@classmethod
def from_dict(cls, obj: dict) -> ServiceUsage:
"""Create an instance of ServiceUsage from a dict"""
if obj is None:
return None
if not isinstance(obj, dict):
return ServiceUsage.parse_obj(obj)
_obj = ServiceUsage.parse_obj({
"times_consumed": obj.get("times_consumed"),
"consumer_entity_did": obj.get("consumer_entity_did")
})
return _obj

View File

@@ -0,0 +1,73 @@
# coding: utf-8
"""
FastAPI
No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
The version of the OpenAPI document: 0.1.0
Generated by OpenAPI Generator (https://openapi-generator.tech)
Do not edit the class manually.
""" # noqa: E501
from __future__ import annotations
import pprint
import re # noqa: F401
import json
from pydantic import BaseModel, Field, StrictInt, StrictStr
class ServiceUsageCreate(BaseModel):
"""
ServiceUsageCreate
"""
times_consumed: StrictInt = Field(...)
consumer_entity_did: StrictStr = Field(...)
__properties = ["times_consumed", "consumer_entity_did"]
class Config:
"""Pydantic configuration"""
allow_population_by_field_name = True
validate_assignment = True
def to_str(self) -> str:
"""Returns the string representation of the model using alias"""
return pprint.pformat(self.dict(by_alias=True))
def to_json(self) -> str:
"""Returns the JSON representation of the model using alias"""
return json.dumps(self.to_dict())
@classmethod
def from_json(cls, json_str: str) -> ServiceUsageCreate:
"""Create an instance of ServiceUsageCreate from a JSON string"""
return cls.from_dict(json.loads(json_str))
def to_dict(self):
"""Returns the dictionary representation of the model using alias"""
_dict = self.dict(by_alias=True,
exclude={
},
exclude_none=True)
return _dict
@classmethod
def from_dict(cls, obj: dict) -> ServiceUsageCreate:
"""Create an instance of ServiceUsageCreate from a dict"""
if obj is None:
return None
if not isinstance(obj, dict):
return ServiceUsageCreate.parse_obj(obj)
_obj = ServiceUsageCreate.parse_obj({
"times_consumed": obj.get("times_consumed"),
"consumer_entity_did": obj.get("consumer_entity_did")
})
return _obj

View File

@@ -26,7 +26,7 @@ random.seed(42)
host = config.host
port_dlg = config.port_dlg
port_ap = config.port_ap
port_client_base = config.port_client_base
port_client_base = config._port_client_base
num_uuids = 100
uuids = [str(uuid.UUID(int=random.getrandbits(128))) for i in range(num_uuids)]
@@ -38,9 +38,9 @@ def test_health(api_client: ApiClient) -> None:
assert res.status == Status.ONLINE
def create_entities(num: int = 10, role: str = "entity") -> list[EntityCreate]:
def create_entities(num: int = 5, role: str = "entity") -> list[EntityCreate]:
res = []
for i in range(num):
for i in range(1, num + 1):
en = EntityCreate(
did=f"did:sov:test:12{i}",
name=f"C{i}",
@@ -75,14 +75,28 @@ def create_entities(num: int = 10, role: str = "entity") -> list[EntityCreate]:
def create_service(idx: int, entity: Entity) -> ServiceCreate:
idx += 1
se = ServiceCreate(
uuid=uuids[idx],
service_name=f"Carlos Printing{idx}",
service_type="3D Printing",
endpoint_url=f"{entity.ip}/v1/print_daemon{idx}",
status="unknown",
other={"action": ["register", "deregister", "delete", "create"]},
endpoint_url=f"http://{entity.ip}/v1/print_daemon{idx}",
status={"data": ["draft", "registered"]},
other={},
action={
"data": [
{
"name": "register",
"endpoint": f"http://{entity.ip}/v1/print_daemon{idx}/register",
},
{
"name": "deregister",
"endpoint": f"http://{entity.ip}/v1/print_daemon{idx}/deregister",
},
]
},
entity_did=entity.did,
usage=[{"times_consumed": 2, "consumer_entity_did": "did:sov:test:120"}],
)
return se
@@ -100,59 +114,58 @@ def test_create_entities(api_client: ApiClient) -> None:
def test_create_services(api_client: ApiClient) -> None:
sapi = ServicesApi(api_client=api_client)
eapi = EntitiesApi(api_client=api_client)
for midx, entity in enumerate(eapi.get_all_entities()):
for idx in range(4):
service_obj = create_service(idx + 4 * midx, entity)
service = sapi.create_service(service_obj)
assert service.uuid == service_obj.uuid
for midx, entity in enumerate(eapi.get_entity_by_roles([Role("service_prosumer")])):
service_obj = create_service(midx, entity)
service = sapi.create_service(service_obj)
assert service.uuid == service_obj.uuid
random.seed(77)
def create_eventmessages(num: int = 2) -> list[EventmessageCreate]:
def create_eventmessages(num: int = 4) -> list[EventmessageCreate]:
res = []
starttime = int(time.time())
for i in range(num):
group_id = i % 5 + random.getrandbits(6)
for i2 in range(1, num + 1):
group_id = i2 % 5 + random.getrandbits(6) + 1
em_req_send = EventmessageCreate(
timestamp=starttime + i * 10,
group=i % 5,
timestamp=starttime + i2 * 10,
group=i2 % 5,
group_id=group_id,
msg_type=1,
src_did=f"did:sov:test:12{i}",
des_did=f"did:sov:test:12{i+1}",
src_did=f"did:sov:test:12{i2}",
des_did=f"did:sov:test:12{i2+1}",
msg={},
)
res.append(em_req_send)
em_req_rec = EventmessageCreate(
timestamp=starttime + (i * 10) + 2,
group=i % 5,
timestamp=starttime + (i2 * 10) + 2,
group=i2 % 5,
group_id=group_id,
msg_type=2,
src_did=f"did:sov:test:12{i}",
des_did=f"did:sov:test:12{i+1}",
src_did=f"did:sov:test:12{i2}",
des_did=f"did:sov:test:12{i2+1}",
msg={},
)
res.append(em_req_rec)
group_id = i % 5 + random.getrandbits(6)
group_id = i2 % 5 + random.getrandbits(6)
em_res_send = EventmessageCreate(
timestamp=starttime + i * 10 + 4,
group=i % 5,
timestamp=starttime + i2 * 10 + 4,
group=i2 % 5,
group_id=group_id,
msg_type=3,
src_did=f"did:sov:test:12{i+1}",
des_did=f"did:sov:test:12{i}",
src_did=f"did:sov:test:12{i2+1}",
des_did=f"did:sov:test:12{i2}",
msg={},
)
res.append(em_res_send)
em_res_rec = EventmessageCreate(
timestamp=starttime + (i * 10) + 8,
group=i % 5,
timestamp=starttime + (i2 * 10) + 8,
group=i2 % 5,
group_id=group_id,
msg_type=4,
src_did=f"did:sov:test:12{i+1}",
des_did=f"did:sov:test:12{i}",
src_did=f"did:sov:test:12{i2+1}",
des_did=f"did:sov:test:12{i2}",
msg={},
)
res.append(em_res_rec)
@@ -161,11 +174,12 @@ def create_eventmessages(num: int = 2) -> list[EventmessageCreate]:
def test_create_eventmessages(api_client: ApiClient) -> None:
api = EventmessagesApi(api_client=api_client)
assert [] == api.get_all_eventmessages()
assert api.get_all_eventmessages() is None
for idx, own_eventmsg in enumerate(create_eventmessages()):
res: Eventmessage = api.create_eventmessage(own_eventmsg)
assert res.msg == own_eventmsg.msg
assert res.src_did == own_eventmsg.src_did
assert res.des_did == own_eventmsg.des_did
assert [] != api.get_all_eventmessages()
assert {} != api.get_all_eventmessages()

View File

@@ -0,0 +1,48 @@
#!/usr/bin/env bash
# shellcheck shell=bash
set -euo pipefail
# GITLAB_TOKEN
if [[ -z "${GITLAB_TOKEN:-}" ]]; then
cat <<EOF
GITLAB_TOKEN environment var is not set. Please generate a new token under
https://git.tu-berlin.de/internet-of-services-lab/service-aware-network-front-end/-/settings/access_tokens
EOF
exit 1
fi
tmpdir=$(mktemp -d)
cleanup() { rm -rf "$tmpdir"; }
trap cleanup EXIT
# Create a new ui build
nix build '.#ui' --out-link "$tmpdir/result"
tar --transform 's,^\.,assets,' -czvf "$tmpdir/assets.tar.gz" -C "$tmpdir"/result/lib/node_modules/*/out .
# upload ui assets to gitlab
gitlab_base="https://git.tu-berlin.de/api/v4/projects/internet-of-services-lab%2Fservice-aware-network-front-end"
curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
--upload-file "$tmpdir/assets.tar.gz" \
"$gitlab_base/packages/generic/ui-assets/1.0.0/ui-assets.tar.gz"
# write url and hash to ui-assets.nix
url="$gitlab_base/packages/generic/ui-assets/1.0.0/ui-assets.tar.gz"
PROJECT_DIR=$(git rev-parse --show-toplevel)
cat > "$PROJECT_DIR/pkgs/ui/nix/ui-assets.nix" <<EOF
{ fetchzip }:
fetchzip {
url = "$url";
sha256 = "$(nix-prefetch-url --unpack $url)";
}
EOF
cat <<EOF
Please commit the changes to ui-assets.nix and push them to the repository.
If you want clan webui to use the new ui assets.
$ git commit -m "Update ui-assets.nix" "$PROJECT_DIR/pkgs/ui/nix/ui-assets.nix"
$ git push
EOF

View File

@@ -1,10 +1,19 @@
{
"root": true,
"extends": ["next/core-web-vitals", "plugin:tailwindcss/recommended", "plugin:@typescript-eslint/recommended"],
"extends": [
"next/core-web-vitals",
"plugin:tailwindcss/recommended",
"plugin:@typescript-eslint/recommended"
],
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"ignorePatterns": ["**/src/api/*"],
"plugins": [
"@typescript-eslint"
],
"ignorePatterns": [
"**/src/api/*"
],
"rules": {
"@typescript-eslint/no-explicit-any": "off"
"@typescript-eslint/no-explicit-any": "off",
"tailwindcss/no-custom-classname": "off"
}
}
}

View File

@@ -1,4 +1,40 @@
# cLan - awesome UI
# Web UI
**Dependency Management**: We use the [Nix package manager](https://nixos.org/) to manage dependencies and ensure reproducibility, making your development process more robust.
The files in `src/api` are autogenerated from the openapi.json. The openapi.json comes from the backend, from fastapi which autogenerates the openapi.json file from the python code.
We then use orval to generate typescript files to `src/api`
## Build Development Web UI
To build the dev web ui with hotreloading
```bash
npm run dev
```
## Build release Web UI
To build the release version execute
```bash
nix build .#ui
```
you can find the output in your current working directory at a symlink called `result`
The actual web files served by the web server are located in
`result/lib/node_modules/clan-ui/out`
You can also build it directly in you dev environment. Notice however that this will clutter your directory. The out directory is directly in you working dir.
```bash
npm run build
```
## Development environment
The development environment created by `nix develop` or automatically by `direnv` is located at [shell.nix](shell.nix). The `shellHook` variable executes bash code.
## Updating dependencies
@@ -15,15 +51,3 @@ The prettier tailwind class sorting is not yet working properly with our devShel
To sort classnames manually:
`cd /clan-core/pkgs/ui/`
## Upload ui to gitea
Create a gitea token here: https://git.clan.lol/user/settings/applications
Than run this command:
```
GITEA_TOKEN=<YOUR_TOKEN> nix run .#update-ui-assets
```
.

1
pkgs/ui/_document.js Normal file
View File

@@ -0,0 +1 @@
<script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>;

View File

@@ -5,6 +5,12 @@ const nextConfig = {
eslint: {
dirs: ["src"],
},
generateBuildId: async () => {
// This could be anything, using the latest git hash
return process.env.NEXT_BUILD_ID;
},
outputFileTracing: true,
reactStrictMode: true,
};
module.exports = nextConfig;

View File

@@ -70,6 +70,7 @@ in
# nextjs chaches some stuff in $HOME
built.override.preBuild = ''
export HOME=./home
export NEXT_BUILD_ID=$(git log -1 --pretty=format:"%H")
echo "----------- GENERATE API TS ------------"

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
{ fetchzip }:
fetchzip {
url = "https://gitea.gchq.icu/api/packages/IoSL/generic/IoSL-service-aware-frontend/04h6w20fgq1zd4qzqm1rqkyk1s3mxnra1088icdrshsdm29x81xa/assets.tar.gz";
sha256 = "04h6w20fgq1zd4qzqm1rqkyk1s3mxnra1088icdrshsdm29x81xa";
url = "https://gitea.gchq.icu/api/packages/IoSL/generic/IoSL-service-aware-frontend/15svaig548jz1l8qsiqcycmw3hkb4805rb08mwlv2isxxshrj9ij/assets.tar.gz";
sha256 = "15svaig548jz1l8qsiqcycmw3hkb4805rb08mwlv2isxxshrj9ij";
}

1067
pkgs/ui/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -25,6 +25,7 @@
"axios": "^1.4.0",
"classnames": "^2.3.2",
"hex-rgb": "^5.0.0",
"mermaid": "^10.6.1",
"next": "13.4.12",
"postcss": "8.4.27",
"pretty-bytes": "^6.1.1",

View File

@@ -8,7 +8,7 @@ pkgs.mkShell {
fmod.config.floco.settings.nodePackage
];
shellHook = ''
ID=${pkg.built.tree}
export ID=${pkg.built.tree}
currID=$(cat .floco/.node_modules_id 2> /dev/null)
mkdir -p .floco
@@ -22,10 +22,11 @@ pkgs.mkShell {
ln -sf ${pkgs.roboto}/share/fonts ./src
export PATH="$PATH:$(realpath ./node_modules)/.bin"
export NEXT_BUILD_ID=$(git log -1 --pretty=format:"%H")
# re-generate the api code
rm -rf src/api openapi.json
rm -f --interactive=never openapi.json
rm -rf src/api
cp ${clanPkgs.clan-openapi}/openapi.json .
orval
'';

View File

@@ -6,13 +6,15 @@ import { useGetAllRepositories } from "@/api/repositories/repositories";
import SummaryDetails from "@/components/summary_card";
import CustomTable from "@/components/table";
import {
APSummaryDetails,
APAttachmentsTableConfig,
APServiceRepositoryTableConfig,
} from "@/config/access_point";
import { useEffect } from "react";
import useGetEntityByNameOrDid from "@/components/hooks/useGetEntityByNameOrDid";
import { projectConfig } from "@/config/config";
export default function AccessPoint() {
const { entity } = useGetEntityByNameOrDid("AP");
const {
data: APAttachementData,
isLoading: loadingAttachements,
@@ -45,7 +47,7 @@ export default function AccessPoint() {
useEffect(() => {
const interval = setInterval(() => {
onRefresh();
}, 5000);
}, projectConfig.REFRESH_FREQUENCY);
return () => clearInterval(interval);
// eslint-disable-next-line react-hooks/exhaustive-deps
@@ -54,10 +56,25 @@ export default function AccessPoint() {
return (
<div className="m-10">
<SummaryDetails
fake
hasRefreshButton
onRefresh={onRefresh}
entity={{ name: "Access Point", details: APSummaryDetails }}
entity={{
name: "Access Point",
details: [
{
label: "DID",
value: entity?.did,
},
{
label: "IP",
value: entity?.ip,
},
{
label: "Network",
value: entity?.network,
},
],
}}
/>
<div>
<h4>Attachment View</h4>

View File

@@ -1,19 +1,14 @@
"use client";
import { useEffect, useMemo, useRef, useState } from "react";
import { useEffect, useMemo, useState } from "react";
import { ClientTableConfig, ServiceTableConfig } from "@/config/client_1";
import CustomTable from "@/components/table";
import {
Alert,
Button,
Card,
CardContent,
CardHeader,
Snackbar,
Typography,
CircularProgress,
IconButton,
} from "@mui/material";
import CopyToClipboard from "@/components/copy_to_clipboard";
import {
attachEntity,
detachEntity,
@@ -26,6 +21,10 @@ import useGetEntityByNameOrDid from "@/components/hooks/useGetEntityByNameOrDid"
import { useGetAllServices } from "@/api/services/services";
import axios from "axios";
import CloseIcon from "@mui/icons-material/Close";
import { useSearchParams } from "next/navigation";
import SummaryDetails from "@/components/summary_card";
import { projectConfig } from "@/config/config";
import ConsumeDisplayComponent from "@/components/consume_content";
interface SnackMessage {
message: string;
@@ -105,14 +104,16 @@ const AttachButton = ({
);
};
export default function Client({
params,
}: {
params: { client_name: string };
}) {
const { client_name } = params;
export default function Client() {
const searchParams = useSearchParams();
const name = searchParams.get("name") ?? "";
const [consumeContent, setConsumeContent] = useState(null);
const [snackbarOpen, setSnackbarOpen] = useState(false);
const [snackbarMessage, setSnackbarMessage] = useState<
SnackMessage | undefined
>(undefined);
const { entity: entity } = useGetEntityByNameOrDid(client_name);
const { entity: entity } = useGetEntityByNameOrDid(name);
const {
data: services,
isLoading: services_loading,
@@ -137,23 +138,22 @@ export default function Client({
useEffect(() => {
const interval = setInterval(() => {
onRefresh();
}, 5000);
}, projectConfig.REFRESH_FREQUENCY);
return () => clearInterval(interval);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const cardContentRef = useRef(null);
const [snackbarOpen, setSnackbarOpen] = useState(false);
const [snackbarMessage, setSnackbarMessage] = useState<
SnackMessage | undefined
>(undefined);
const closeSnackBar = () => {
setSnackbarMessage(undefined);
setSnackbarOpen(false);
};
// Consume
const handleConsumeContent = (content: any) => {
setConsumeContent(content);
};
if (services_loading) return <Skeleton height={500} />;
if (!services) return <Alert severity="error">Client not found</Alert>;
@@ -180,34 +180,43 @@ export default function Client({
</div>
</div>
<Card variant="outlined">
<CardHeader
subheader="Summary"
action={<CopyToClipboard contentRef={cardContentRef} />}
/>
<CardContent ref={cardContentRef}>
<Typography color="text.primary" gutterBottom>
DID: <code>{entity?.did}</code>
</Typography>
<Typography color="text.primary" gutterBottom>
IP: <code>{entity?.ip}</code>
</Typography>
<Typography color="text.primary" gutterBottom>
Network: <code>{entity?.other?.network}</code>
</Typography>
</CardContent>
</Card>
<div>
<h4>Client View</h4>
<CustomTable
loading={services_loading}
data={clients}
configuration={ClientTableConfig}
tkey="client-table"
/>
<SummaryDetails
entity={{
name: "",
details: [
{ label: "DID", value: entity?.did },
{ label: "IP", value: entity?.ip },
{ label: "Network", value: entity?.network },
],
}}
/>
<div
style={{
display: "flex",
justifyContent: "space-between",
flexWrap: "nowrap",
alignItems: "center",
}}
>
<div style={{ width: consumeContent ? "55%" : "100%" }}>
<h4>Service Consumer View</h4>
<CustomTable
loading={services_loading}
data={clients}
onConsumeAction={handleConsumeContent}
configuration={ClientTableConfig}
tkey="client-table"
/>
</div>
{consumeContent && (
<div style={{ width: "40%" }}>
<h4>Service Output</h4>
<ConsumeDisplayComponent htmlContent={consumeContent} />
</div>
)}
</div>
<div>
<h4>Service View</h4>
<h4>Service Producer View</h4>
<CustomTable
loading={services_loading}
data={services?.data}

View File

@@ -0,0 +1,5 @@
import Client from "@/app/client/client";
export default function Page() {
return <Client />;
}

View File

@@ -1,26 +1,37 @@
"use client";
import { DLGResolutionTableConfig, DLGSummaryDetails } from "@/config/dlg";
import { DLGResolutionTableConfig } from "@/config/dlg";
import CustomTable from "@/components/table";
import SummaryDetails from "@/components/summary_card";
import useFetch from "@/components/hooks/useFetch";
import { useEffect } from "react";
import { useGetAllResolutions } from "@/api/resolution/resolution";
import { mutate } from "swr";
import useGetEntityByNameOrDid from "@/components/hooks/useGetEntityByNameOrDid";
import { projectConfig } from "@/config/config";
export default function DLG() {
const { entity } = useGetEntityByNameOrDid("DLG");
const {
data: resolutionData,
loading: loadingResolutions,
fetch,
} = useFetch("/get_resolutions");
isLoading: loadingResolutions,
swrKey: resolutionsKeyFunc,
} = useGetAllResolutions();
const onRefresh = () => {
fetch();
const resolutionsKey =
typeof resolutionsKeyFunc === "function"
? resolutionsKeyFunc()
: resolutionsKeyFunc;
if (resolutionsKey) {
mutate(resolutionsKey);
}
};
useEffect(() => {
const interval = setInterval(() => {
onRefresh();
}, 5000);
}, projectConfig.REFRESH_FREQUENCY);
return () => clearInterval(interval);
// eslint-disable-next-line react-hooks/exhaustive-deps
@@ -29,19 +40,31 @@ export default function DLG() {
return (
<div className="m-10">
<SummaryDetails
fake
hasRefreshButton
onRefresh={onRefresh}
entity={{
name: "Distributed Ledger Gateway",
details: DLGSummaryDetails,
details: [
{
label: "DID",
value: entity?.did,
},
{
label: "IP",
value: entity?.ip,
},
{
label: "Network",
value: entity?.network,
},
],
}}
/>
<div>
<h4>DID Resolution View</h4>
<CustomTable
loading={loadingResolutions}
data={resolutionData}
data={resolutionData?.data}
configuration={DLGResolutionTableConfig}
tkey="resolution_table"
/>

View File

@@ -1,12 +1,19 @@
"use client";
import { useAppState } from "@/components/hooks/useAppContext";
import { NoDataOverlay } from "@/components/noDataOverlay";
import SummaryDetails from "@/components/summary_card";
import CustomTable from "@/components/table";
import { HomeTableConfig } from "@/config/home";
import dynamic from "next/dynamic";
import { useEffect } from "react";
import { mutate } from "swr";
import ErrorBoundary from "@/components/error_boundary";
import { projectConfig } from "@/config/config";
const NoSSRSequenceDiagram = dynamic(
() => import("../../components/sequence_diagram"),
{ ssr: false },
);
export default function Home() {
const { data } = useAppState();
@@ -24,7 +31,7 @@ export default function Home() {
useEffect(() => {
const interval = setInterval(() => {
onRefresh();
}, 5000);
}, projectConfig.REFRESH_FREQUENCY);
return () => clearInterval(interval);
// eslint-disable-next-line react-hooks/exhaustive-deps
@@ -36,7 +43,6 @@ export default function Home() {
entity={{ name: "Home", details: [] }}
hasRefreshButton={true}
onRefresh={onRefresh}
hasAttachDetach={false}
/>
<div>
@@ -51,7 +57,9 @@ export default function Home() {
<div>
<h4>Sequence Diagram</h4>
<NoDataOverlay label="No Activity yet" />
<ErrorBoundary>
<NoSSRSequenceDiagram />
</ErrorBoundary>
</div>
</div>
);

View File

@@ -6,6 +6,7 @@ import {
CssBaseline,
IconButton,
ThemeProvider,
Tooltip,
useMediaQuery,
} from "@mui/material";
import { StyledEngineProvider } from "@mui/material/styles";
@@ -50,6 +51,12 @@ export default function RootLayout({
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Service Aware Networks" />
<link rel="icon" href="tub-favicon.ico" sizes="any" />
<script
// eslint-disable-next-line react/no-danger
dangerouslySetInnerHTML={{
__html: `mermaid.initialize({startOnLoad: true});`,
}}
/>
</head>
<StyledEngineProvider injectFirst>
<ThemeProvider theme={userPrefersDarkmode ? darkTheme : lightTheme}>
@@ -77,13 +84,15 @@ export default function RootLayout({
>
<div className="grid grid-cols-3">
<div className="col-span-1">
<IconButton
style={{ padding: "12px" }}
hidden={true}
onClick={() => setShowSidebar((c) => !c)}
>
{!showSidebar && <MenuIcon />}
</IconButton>
<Tooltip placement="right" title="Expand Sidebar">
<IconButton
style={{ padding: "12px" }}
hidden={true}
onClick={() => setShowSidebar((c) => !c)}
>
{!showSidebar && <MenuIcon />}
</IconButton>
</Tooltip>
</div>
</div>

View File

@@ -0,0 +1,73 @@
import { Button, CircularProgress, Snackbar } from "@mui/material";
import { useState } from "react";
import axios from "axios";
const ConsumeAction = ({
endpoint,
onConsume,
}: {
endpoint: string;
rowData?: any;
onConsume?: any;
}) => {
const [error, setError] = useState(null);
const [loading, setLoading] = useState(false);
if (error) console.error("Error in state", error);
const handleConsume = () => {
if (loading) return;
setLoading(true);
const axiosConfig = {
url: endpoint,
method: "GET",
data: null,
withCredentials: true,
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
};
axios(axiosConfig)
.then((response) => {
if (onConsume) {
onConsume(response.data);
console.log("I got the data from consume: ", response.data);
}
})
.catch((error) => {
if (onConsume) onConsume(null);
console.error("Error happened during consume: ", error);
setError(error);
})
.finally(() => {
setLoading(false);
});
};
const handleCloseSnackbar = () => {
setError(null);
};
return (
<>
<Button disabled={loading} onClick={handleConsume} variant="contained">
{loading ? <CircularProgress size={24} /> : `Consume`}
</Button>
{error && (
<Snackbar
anchorOrigin={{ vertical: "top", horizontal: "center" }}
open={error}
autoHideDuration={2000}
message={`Something happened during consume: ${error}`}
onClose={handleCloseSnackbar}
/>
)}
</>
);
};
export default ConsumeAction;

View File

@@ -0,0 +1,9 @@
const ConsumeDisplayComponent = ({ htmlContent }: { htmlContent: any }) => {
return (
<div>
<div dangerouslySetInnerHTML={{ __html: htmlContent }} />
</div>
);
};
export default ConsumeDisplayComponent;

View File

@@ -1,26 +1,50 @@
import { useState } from "react";
import { Button, Snackbar } from "@mui/material";
import { useState, RefObject } from "react";
import { Tooltip, Snackbar } from "@mui/material";
import ContentCopyIcon from "@mui/icons-material/ContentCopy";
const CopyToClipboard = ({ contentRef }: { contentRef: any }) => {
const CopyToClipboard = ({
contentRef,
textToCopy,
}: {
contentRef?: RefObject<HTMLDivElement>;
textToCopy?: string;
}) => {
const [open, setOpen] = useState(false);
const handleClick = () => {
if (contentRef.current) {
const text = contentRef.current.textContent;
navigator.clipboard.writeText(text);
setOpen(true);
// Prioritize direct text copy if 'textToCopy' is provided
const text = textToCopy || contentRef?.current?.textContent || "";
const copiedText = textToCopy ? JSON.stringify(text, null, 2) : text;
if (text) {
navigator.clipboard.writeText(copiedText).then(
() => {
setOpen(true);
},
(err) => {
console.error("Could not copy text: ", err);
},
);
}
};
return (
<>
<Button onClick={handleClick}>Copy</Button>
<Tooltip placement="left" title="Copy to Clipboard">
<ContentCopyIcon onClick={handleClick} className="cursor-pointer" />
</Tooltip>
<Snackbar
open={open}
onClose={() => setOpen(false)}
autoHideDuration={2000}
message="Copied to clipboard"
message="Copied to clipboard!"
anchorOrigin={{
vertical: "bottom",
horizontal: "left",
}}
/>
</>
);
};
export default CopyToClipboard;

View File

@@ -0,0 +1,73 @@
# CopyToClipboard Component
## Overview
The `CopyToClipboard` component is a versatile UI component designed to facilitate copying text to the user's clipboard. It can copy text from two sources: directly from a passed text string prop (`textToCopy`) or from the text content of a referenced div element (`contentRef`). The component includes a clickable icon and displays a confirmation snackbar notification once the copy action is successful.
## Props
The component accepts the following props:
1. `textToCopy` (optional): A string representing the direct text you want to copy. If provided, this text is copied to the clipboard when the icon is clicked.
2. `contentRef` (optional): A `RefObject<HTMLDivElement>` that references a div element. The text content of this div is copied to the clipboard if `textToCopy` is not provided.
## Behavior
- Copy Action: When the copy icon is clicked, the component:
- Prioritizes copying the text from the `textToCopy` prop if it's provided and not an empty string.
- If `textToCopy` is not provided or is empty, it then attempts to copy the text content of the element referenced by contentRef.
- Uses the Clipboard API (`navigator.clipboard.writeText`) to copy the text to the user's clipboard.
- Displays a snackbar notification confirming the copy action if successful.
- Snackbar Notification: A temporary notification that:
- Appears after the text is successfully copied.
- Displays the message "Copied to clipboard!".
- Disappears automatically after 2000 milliseconds and is positioned at the bottom left of the screen.
## How to Use
1. Import the `CopyToClipboard` component.
2. Use the component in one of the following ways:
3. Pass a `textToCopy` prop with the text you want to copy, OR
4. Pass a `contentRef` prop pointing to a div element containing the text you want to copy.
5. Render the `CopyToClipboard` component where you want the copy icon to appear.
## Example
Using `textToCopy` prop:
```javascript
import CopyToClipboard from "./CopyToClipboard";
const SomeComponent = () => {
return (
<div>
<CopyToClipboard textToCopy="Text to be copied" />
</div>
);
};
export default SomeComponent;
```
Using `contentRef` prop:
```javascript
import React, { useRef } from "react";
import CopyToClipboard from "./CopyToClipboard";
const SomeComponent = () => {
const textRef = useRef(null);
return (
<div>
<div ref={textRef}>Text to copy from ref</div>
<CopyToClipboard contentRef={textRef} />
</div>
);
};
export default SomeComponent;
```

View File

@@ -0,0 +1,231 @@
import { IEntityActions } from "@/types";
import {
Button,
Snackbar,
Alert,
AlertColor,
CircularProgress,
Dialog,
DialogTitle,
DialogContent,
DialogContentText,
DialogActions,
} from "@mui/material";
import { useState } from "react";
import { deleteEntity } from "@/api/entities/entities";
import axios from "axios";
interface Props {
endpointData: IEntityActions[];
rowData?: any;
}
const SNACKBAR_DEFAULT = {
open: false,
message: "",
severity: "info" as AlertColor,
};
const EntityActions = ({ endpointData, rowData }: Props) => {
const [snackbar, setSnackbar] = useState<{
open: boolean;
message: string;
severity: AlertColor;
}>(SNACKBAR_DEFAULT);
const [registerData, setRegisterData] = useState(null);
const [registerError, setRegisterError] = useState(null);
const [loadingRegister, setLoadingRegister] = useState(false);
const [DeregisterData, setDeRegisterData] = useState(null);
const [DeregisterError, setDeRegisterError] = useState(null);
const [loadingDeRegister, setLoadingDeRegister] = useState(false);
const [loadingDelete, setLoadingDelete] = useState(false);
const [confirmDelete, setConfirmDelete] = useState(false);
if (registerData) console.log("Register Data in state", registerData);
if (registerError) console.error("Register Error in state", registerError);
if (DeregisterData) console.log("Register Data in state", DeregisterData);
if (DeregisterError)
console.error("Register Error in state", DeregisterError);
const onDeleteEntity = async () => {
setLoadingDelete(true);
if (rowData)
try {
const response = await deleteEntity({
entity_did: rowData?.entity_did,
});
setSnackbar({
open: true,
message: response.data.message,
severity: "success",
});
} catch (error) {
console.error("Error deleting entity: ", error);
setSnackbar({
open: true,
message: "Failed to delete entity.",
severity: "error",
});
} finally {
setLoadingDelete(false);
closeDeleteConfirmation();
}
};
const onRegisterEntity = (endpoint: string) => {
if (loadingRegister) return;
setLoadingRegister(true);
const axiosConfig = {
url: endpoint,
method: "GET",
data: null,
withCredentials: true,
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
};
axios(axiosConfig)
.then((response) => {
setRegisterData(response.data);
console.log("I got the data from register: ", response.data);
setSnackbar({
open: true,
message: "Registered successfully!",
severity: "success",
});
})
.catch((error) => {
console.error("Error happened during register: ", error);
setRegisterError(error);
setSnackbar({
open: true,
message: error,
severity: "error",
});
})
.finally(() => {
setLoadingRegister(false);
});
};
const onDeregisterEntity = (endpoint: string) => {
if (loadingDeRegister) return;
setLoadingDeRegister(true);
const axiosConfig = {
url: endpoint,
method: "GET",
data: null,
};
axios(axiosConfig)
.then((response) => {
setDeRegisterData(response.data);
console.log("I got the data from deregister: ", response.data);
setSnackbar({
open: true,
message: "De-Registered successfully!",
severity: "success",
});
})
.catch((error) => {
console.error("Error happened during deregister: ", error);
setDeRegisterError(error);
setSnackbar({
open: true,
message: error,
severity: "error",
});
})
.finally(() => {
setLoadingDeRegister(false);
});
};
const handleCloseSnackbar = () => {
setSnackbar(SNACKBAR_DEFAULT);
};
const openDeleteConfirmation = () => {
setConfirmDelete(true);
};
const closeDeleteConfirmation = () => {
setConfirmDelete(false);
};
return (
<>
<div className="flex justify-between">
{endpointData.map(
({ name, endpoint }: IEntityActions, index: number) => {
const isRegister = name && name.toLocaleLowerCase() === "register";
// const isDeRegister = name && name.toLocaleLowerCase() === "deregister";
return (
<Button
disabled={loadingRegister || loadingDeRegister}
key={index}
onClick={() =>
isRegister
? onRegisterEntity(endpoint)
: onDeregisterEntity(endpoint)
}
variant="contained"
size="small"
>
{name}
</Button>
);
},
)}
<Button
disabled={loadingDelete}
onClick={openDeleteConfirmation}
size="small"
variant="contained"
>
Delete
</Button>
</div>
<Dialog open={confirmDelete} onClose={closeDeleteConfirmation}>
<DialogTitle>Delete Entity Confirmation</DialogTitle>
<DialogContent>
<DialogContentText>
Are you sure you want to delete this entity?
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={closeDeleteConfirmation}>Cancel</Button>
<Button variant="contained" onClick={onDeleteEntity}>
{loadingDelete ? <CircularProgress size={24} /> : `Confirm`}
</Button>
</DialogActions>
</Dialog>
<Snackbar
anchorOrigin={{ vertical: "top", horizontal: "center" }}
open={snackbar.open}
autoHideDuration={5000}
onClose={handleCloseSnackbar}
>
<Alert
onClose={handleCloseSnackbar}
severity={snackbar?.severity}
sx={{ width: "100%" }}
>
{snackbar.message}
</Alert>
</Snackbar>
</>
);
};
export default EntityActions;

View File

@@ -0,0 +1,49 @@
import React from "react";
interface Props {
children: React.ReactNode;
}
interface State {
hasError: boolean;
}
class ErrorBoundary extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
// Define a state variable to track whether is an error or not
this.state = { hasError: false };
}
static getDerivedStateFromError(error: Error): State {
console.error(error);
// Update state so the next render will show the fallback UI
return { hasError: true };
}
componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {
// You can use your own error logging service here
console.log({ error, errorInfo });
}
render(): React.ReactNode {
// Check if the error is thrown
if (this.state.hasError) {
// You can render any custom fallback UI
return (
<div>
<h2>Oops, there is an error!</h2>
<button
type="button"
onClick={() => this.setState({ hasError: false })}
>
Try again?
</button>
</div>
);
}
// Return children components in case of no error
return this.props.children;
}
}
export default ErrorBoundary;

View File

@@ -0,0 +1,49 @@
import { useState, useEffect } from "react";
import axios from "axios";
import { projectConfig } from "@/config/config";
const useAxios = (
url: string,
method = "GET",
payload = null,
isFullUrl = false,
shouldFetch = false,
) => {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const fetch = () => {
setLoading(true);
setError(null);
const finalUrl = isFullUrl ? url : projectConfig.BASE_URL + url;
const axiosConfig = {
url: finalUrl,
method,
data: payload,
};
axios(axiosConfig)
.then((response) => {
setData(response.data);
})
.catch((error) => {
setError(error);
})
.finally(() => {
setLoading(false);
});
};
useEffect(() => {
if (shouldFetch) {
fetch();
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [url, method, JSON.stringify(payload), shouldFetch]);
return { data, loading, error, refetch: fetch };
};
export default useAxios;

View File

@@ -1,33 +0,0 @@
import { useState, useEffect } from "react";
import axios from "axios";
import { BASE_URL } from "@/constants";
const useFetch = (url: string) => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const fetch = () => {
setLoading(true);
axios
.get(BASE_URL + url)
.then((response) => {
setData(response.data);
})
.catch((error) => {
setError(error);
})
.finally(() => {
setLoading(false);
});
};
useEffect(() => {
fetch();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [url]);
return { data, loading, error, fetch };
};
export default useFetch;

View File

@@ -0,0 +1,93 @@
import { getGroupColor, sanitizeDID } from "@/utils/helpers";
export const generateMermaidString = (data: any) => {
if (!data || !data.length) return "";
let mermaidString = "sequenceDiagram\n";
const participantDetails = new Map();
// Collect all unique participants along with their sanitized DIDs
data.forEach((item: any) => {
Object.values(item.groups).forEach((group: any) => {
group.forEach((msg: any) => {
// Apply sanitization to src_name and des_name if they are in DID format
const sanitizedSrcName = msg.src_name.includes(":")
? sanitizeDID(msg.src_name)
: msg.src_name;
const sanitizedDesName = msg.des_name.includes(":")
? sanitizeDID(msg.des_name)
: msg.des_name;
participantDetails.set(sanitizedSrcName, sanitizeDID(msg.src_did));
participantDetails.set(sanitizedDesName, sanitizeDID(msg.des_did));
});
});
});
// Add participants to the mermaid string with names and sanitized DIDs
participantDetails.forEach((sanitizedDID, name) => {
mermaidString += ` participant ${name} as ${name} <br/>${sanitizedDID}\n`;
});
// Iterate through each group
data.forEach((item: any) => {
let groupParticipants: any = new Set(); // This will collect participants for the current group
// Collect participants involved in each specific group
Object.values(item.groups).forEach((group: any) => {
group.forEach((msg: any) => {
const sanitizedSrcName = msg.src_name.includes(":")
? sanitizeDID(msg.src_name)
: msg.src_name;
const sanitizedDesName = msg.des_name.includes(":")
? sanitizeDID(msg.des_name)
: msg.des_name;
groupParticipants.add(sanitizedSrcName);
groupParticipants.add(sanitizedDesName);
});
});
// Convert the set of participants to a sorted array and then to a string
groupParticipants = Array.from(groupParticipants).sort().join(",");
// Get the group color from the config
const groupColor = getGroupColor(item.group_name);
// Add group note with only involved participants
mermaidString += `\n rect ${groupColor}\n Note over ${groupParticipants}: ${item.group_name}\n`;
Object.entries(item.groups).forEach(([groupId, messages]: any) => {
mermaidString += ` alt Group Id ${groupId}\n`;
messages.forEach((msg: any) => {
const sanitizedSrcName = msg.src_name.includes(":")
? sanitizeDID(msg.src_name)
: msg.src_name;
const sanitizedDesName = msg.des_name.includes(":")
? sanitizeDID(msg.des_name)
: msg.des_name;
const arrow = sanitizedSrcName > sanitizedDesName ? "-->>" : "->>";
mermaidString += ` ${sanitizedSrcName}${arrow}${sanitizedDesName}: [${msg.msg_type_name}]: Event Message ${msg.id}\n`;
});
mermaidString += " end\n";
});
mermaidString += " end\n";
});
return mermaidString;
};
export function extractAllEventMessages(data: any) {
const allMessagesArray: any = [];
if (!data || data.length === 0) return allMessagesArray;
else
data.forEach((groupData: any) => {
Object.values(groupData.groups).forEach((messages: any) => {
messages.forEach((message: any) => {
allMessagesArray.push(message);
});
});
});
return allMessagesArray;
}

View File

@@ -0,0 +1,359 @@
"use client";
import { useRef, useEffect, useState } from "react";
import mermaid from "mermaid";
import {
Button,
Card,
Chip,
Dialog,
DialogActions,
Tooltip,
DialogContent,
DialogContentText,
DialogTitle,
IconButton,
List,
TextField,
useMediaQuery,
} from "@mui/material";
//Icons
import RefreshIcon from "@mui/icons-material/Refresh";
import ZoomInIcon from "@mui/icons-material/ZoomIn";
import ZoomOutIcon from "@mui/icons-material/ZoomOut";
import FullscreenIcon from "@mui/icons-material/Fullscreen";
import DownloadIcon from "@mui/icons-material/Download";
import ResetIcon from "@mui/icons-material/Autorenew";
import FilterAltIcon from "@mui/icons-material/FilterAlt";
// Custom Components
import { NoDataOverlay } from "../noDataOverlay";
import { LoadingOverlay } from "../join/loadingOverlay";
import { useGetAllEventmessages } from "@/api/eventmessages/eventmessages";
import { mutate } from "swr";
import { extractAllEventMessages, generateMermaidString } from "./helpers";
import CopyToClipboard from "../copy_to_clipboard";
import { formatDateTime, getGroupById } from "@/utils/helpers";
const SequenceDiagram = () => {
const {
data: eventMessagesData,
isLoading: loadingEventMessages,
swrKey: eventMessagesKeyFunc,
} = useGetAllEventmessages();
const [scale, setScale] = useState(1);
const [openFilters, setOpenFilters] = useState(false);
const [sequenceNr, setSequenceNr] = useState("");
const mermaidRef: any = useRef(null);
const hasData = eventMessagesData?.data && eventMessagesData?.data.length > 0;
const mermaidString = generateMermaidString(eventMessagesData?.data);
const allEventMessages = extractAllEventMessages(eventMessagesData?.data);
const dataDependency = JSON.stringify(hasData ? eventMessagesData?.data : "");
const userPrefersDarkmode = useMediaQuery("(prefers-color-scheme: dark)");
const iconButtonColor = userPrefersDarkmode ? "default" : "primary";
useEffect(() => {
const currentMermaidRef = mermaidRef?.current;
if (!loadingEventMessages && hasData) {
if (
currentMermaidRef &&
!currentMermaidRef.getAttribute("data-processed")
) {
mermaid.initialize({
startOnLoad: false,
securityLevel: "loose",
sequence: {
mirrorActors: true,
showSequenceNumbers: true,
},
});
}
if (currentMermaidRef) {
currentMermaidRef.innerHTML = mermaidString;
mermaid.init(undefined, currentMermaidRef);
}
}
return () => {
if (currentMermaidRef) {
currentMermaidRef.removeAttribute("data-processed");
currentMermaidRef.innerHTML = "";
}
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [dataDependency]);
useEffect(() => {
if (mermaidRef.current) {
const svg = mermaidRef.current.querySelector("svg");
if (svg) {
svg.style.transform = `scale(${scale})`;
svg.style.transformOrigin = "top left";
mermaidRef.current.style.width = `${
svg.getBoundingClientRect().width * scale
}px`;
mermaidRef.current.style.height = `${
svg.getBoundingClientRect().height * scale
}px`;
}
}
}, [scale]);
const onRefresh = () => {
const eventMessagesKey =
typeof eventMessagesKeyFunc === "function"
? eventMessagesKeyFunc()
: eventMessagesKeyFunc;
if (eventMessagesKey) {
mutate(eventMessagesKey);
}
};
const zoomIn = () => {
setScale((scale) => scale * 1.1);
};
const zoomOut = () => {
setScale((scale) => scale / 1.1);
};
const resetZoom = () => {
setScale(1);
};
const viewInFullScreen = () => {
if (mermaidRef.current) {
const svg = mermaidRef.current.querySelector("svg");
const serializer = new XMLSerializer();
const svgBlob = new Blob([serializer.serializeToString(svg)], {
type: "image/svg+xml",
});
const url = URL.createObjectURL(svgBlob);
window.open(url, "_blank");
}
};
const downloadAsPng = () => {
if (mermaidRef.current) {
const svg = mermaidRef.current.querySelector("svg");
const svgData = new XMLSerializer().serializeToString(svg);
// Create a canvas element to convert SVG to PNG
const canvas = document.createElement("canvas");
const svgSize = svg.getBoundingClientRect();
canvas.width = svgSize.width;
canvas.height = svgSize.height;
const ctx = canvas.getContext("2d");
const img = document.createElement("img");
img.onload = () => {
ctx?.drawImage(img, 0, 0);
const pngData = canvas.toDataURL("image/png");
// Trigger download
const link = document.createElement("a");
link.download = "sequence-diagram.png";
link.href = pngData;
link.click();
};
img.src =
"data:image/svg+xml;base64," +
btoa(unescape(encodeURIComponent(svgData)));
}
};
const toggleFilters = () => {
setOpenFilters((prevState) => !prevState);
};
const onSearchBySeqNumber = (e: any) => {
setSequenceNr(e.target.value);
};
const isFilterMatch = (index: number) => {
if (!sequenceNr) return true;
const filterSeqNrInt = parseInt(sequenceNr, 10);
return index + 1 === filterSeqNrInt;
};
if (loadingEventMessages)
return <LoadingOverlay title="Loading Diagram" subtitle="Please wait..." />;
return (
<>
<div className="flex flex-col items-end">
{hasData ? (
<>
<div className="flex justify-end">
<Tooltip placement="top" title="Filter Messages">
<IconButton color={iconButtonColor} onClick={toggleFilters}>
<FilterAltIcon />
</IconButton>
</Tooltip>
<Tooltip placement="top" title="Refresh Diagram">
<IconButton color={iconButtonColor} onClick={onRefresh}>
<RefreshIcon />
</IconButton>
</Tooltip>
<Tooltip title="Zoom In" placement="top">
<IconButton color={iconButtonColor} onClick={zoomIn}>
<ZoomInIcon />
</IconButton>
</Tooltip>
<Tooltip title="Zoom Out" placement="top">
<IconButton color={iconButtonColor} onClick={zoomOut}>
<ZoomOutIcon />
</IconButton>
</Tooltip>
<Tooltip title="Reset" placement="top">
<IconButton color={iconButtonColor} onClick={resetZoom}>
<ResetIcon />
</IconButton>
</Tooltip>
<Tooltip title="View in Fullscreen" placement="top">
<IconButton color={iconButtonColor} onClick={viewInFullScreen}>
<FullscreenIcon />
</IconButton>
</Tooltip>
<Tooltip title="Download as PNG" placement="top">
<IconButton color={iconButtonColor} onClick={downloadAsPng}>
<DownloadIcon />
</IconButton>
</Tooltip>
</div>
<div className="w-full p-2.5">
<div className="mermaid" ref={mermaidRef}></div>
</div>
</>
) : (
<div className="flex w-full justify-center">
<NoDataOverlay label="No Activity yet" />
</div>
)}
</div>
{openFilters && (
<>
<Dialog
open={openFilters}
keepMounted
fullWidth
maxWidth="lg"
onClose={toggleFilters}
>
<DialogTitle>All Event Messages</DialogTitle>
<DialogContent>
<DialogContentText>
<div className="flex items-center gap-2.5">
<label>Search by Sequence # </label>
<TextField
onChange={onSearchBySeqNumber}
size="small"
variant="outlined"
/>
</div>
<List className="w-full" component="nav">
{allEventMessages
.filter((_: any, index: number) => {
return isFilterMatch(index);
})
.map((message: any, index: number) => {
const {
msg_type_name: msgType,
des_name,
src_name,
group,
group_id,
timestamp,
src_did,
des_did,
// msg, TODO: Need to use the content inside the msg to display in the diagram
} = message;
const formattedTimeStamp = formatDateTime(timestamp);
const { groupIcon: IconComponent, groupName } =
getGroupById(group);
return (
<div
key={index}
style={{ marginBottom: 12 }}
className="flex items-center gap-5"
>
<Chip label={sequenceNr ? sequenceNr : ++index} />
<Card style={{ padding: 10 }} className="w-full">
<div
style={{ marginBottom: 12 }}
className="flex justify-between"
>
<div>
<span
style={{
marginBottom: 12,
fontWeight: "bold",
}}
className="flex items-center gap-2"
>
{IconComponent} {groupName}{" "}
<Chip label={msgType} />
</span>
<span>
Sender: {src_name} <Chip label={src_did} /> |{" "}
</span>
<span>
Receiver: {des_name} <Chip label={des_did} />{" "}
|{" "}
</span>
<span>Group: {group} | </span>
<span>Group ID: {group_id}</span>
</div>
<span>{formattedTimeStamp}</span>
</div>
<span className="font-bold">
Event Message {sequenceNr ? sequenceNr : index++}
</span>
<div
className="mt-4 flex"
style={{
border: "1px solid #f1f1f1",
borderRadius: 5,
}}
>
<pre className="flex-1 p-2">
{JSON.stringify(message, null, 2)}
</pre>
<div className="shrink-0 p-2">
<CopyToClipboard textToCopy={message} />
</div>
</div>
</Card>
</div>
);
})}
</List>
</DialogContentText>
</DialogContent>
<DialogActions className="p-4">
<Button variant="contained" onClick={toggleFilters}>
Close
</Button>
</DialogActions>
</Dialog>
</>
)}
</>
);
};
export default SequenceDiagram;

View File

@@ -6,8 +6,11 @@ import {
ListItemButton,
ListItemIcon,
ListItemText,
Tooltip,
useMediaQuery,
} from "@mui/material";
import { useGetEntityByRole } from "@/api/entities/entities";
import { Role } from "@/api/model/role";
import Image from "next/image";
import React, { ReactNode } from "react";
@@ -32,22 +35,7 @@ type MenuEntry = {
subMenuEntries?: MenuEntry[];
};
const menuEntityEntries: MenuEntry[] = [
{
icon: <PersonIcon />,
label: "C1",
to: "/client/C1",
disabled: false,
},
{
icon: <PersonIcon />,
label: "C2",
to: "/client/C2",
disabled: false,
},
];
const menuEntries: MenuEntry[] = [
export const menuEntries: MenuEntry[] = [
{
icon: <HomeIcon />,
label: "Home",
@@ -83,6 +71,9 @@ interface SidebarProps {
}
export function Sidebar(props: SidebarProps) {
const { data: entityData } = useGetEntityByRole({
role: Role.service_prosumer,
});
const { show, onClose } = props;
const [activeMenuItem, setActiveMenuItem] = React.useState(
typeof window !== "undefined" ? window.location.pathname : "",
@@ -99,13 +90,28 @@ export function Sidebar(props: SidebarProps) {
setCollapseMenuOpen(!collapseMenuOpen);
};
const menuEntityEntries: MenuEntry[] = React.useMemo(() => {
if (entityData) {
return Array.isArray(entityData.data)
? entityData.data.map((entity: any) => ({
icon: <PersonIcon />,
label: entity.name,
to: entity.name,
disabled: false,
}))
: [];
} else {
return [];
}
}, [entityData]);
React.useEffect(() => {
if (isSmallerScreen) {
setCollapseMenuOpen(false);
} else {
setCollapseMenuOpen(true);
}
}, [isSmallerScreen]);
}, [isSmallerScreen, entityData]);
return (
<aside
@@ -125,9 +131,14 @@ export function Sidebar(props: SidebarProps) {
/>
</div>
<div className="lg:absolute lg:right-0 lg:top-0">
<IconButton size="large" className="text-white" onClick={onClose}>
<ChevronLeftIcon fontSize="inherit" />
</IconButton>
<Tooltip
placement="right"
title={collapseMenuOpen ? "Close Sidebar" : "Expand Sidebar"}
>
<IconButton size="large" className="text-white" onClick={onClose}>
<ChevronLeftIcon fontSize="inherit" />
</IconButton>
</Tooltip>
</div>
</div>
<Divider
@@ -195,31 +206,36 @@ export function Sidebar(props: SidebarProps) {
unmountOnExit
>
<List component="div" disablePadding>
{menuEntityEntries.map((menuEntry, idx) => (
<ListItemButton
key={idx}
sx={{ pl: 4 }}
className="lg:justify-normal"
LinkComponent={Link}
href={menuEntry.to}
disabled={menuEntry.disabled}
selected={activeMenuItem === menuEntry.to}
onClick={() => handleMenuItemClick(menuEntry.to)}
{menuEntityEntries?.map((menuEntry, idx) => (
<Link
key={"entity-link-" + idx}
href={`/client?name=${menuEntry.to}`}
style={{ textDecoration: "none", color: "white" }}
>
<ListItemIcon
color="inherit"
className="overflow-hidden text-white lg:justify-normal"
<ListItemButton
key={idx}
sx={{ pl: 4 }}
className="lg:justify-normal"
LinkComponent={Link}
disabled={menuEntry.disabled}
selected={activeMenuItem === menuEntry.to}
onClick={() => handleMenuItemClick(menuEntry.to)}
>
{menuEntry.icon}
</ListItemIcon>
<ListItemText
primary={menuEntry.label}
primaryTypographyProps={{
color: "inherit",
}}
className="hidden lg:block"
/>
</ListItemButton>
<ListItemIcon
color="inherit"
className="overflow-hidden text-white lg:justify-normal"
>
{menuEntry.icon}
</ListItemIcon>
<ListItemText
primary={menuEntry.label}
primaryTypographyProps={{
color: "inherit",
}}
className="hidden lg:block"
/>
</ListItemButton>
</Link>
))}
</List>
</Collapse>

View File

@@ -13,29 +13,17 @@ import { EntityDetails, ISummaryDetails } from "@/types";
const SummaryDetails = ({
entity,
hasRefreshButton,
hasAttachDetach,
fake,
onRefresh,
}: ISummaryDetails) => {
const cardContentRef = useRef(null);
const cardContentRef = useRef<HTMLDivElement>(null);
const hasDetails = entity.details && entity.details.length > 0;
return (
<>
<div
style={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
}}
>
<div className="flex items-center justify-between">
<h2>{entity.name}</h2>
<div>
{hasAttachDetach && (
<Button className="mr-6" variant="contained">
Attach / Detach
</Button>
)}
{hasRefreshButton && (
<Button onClick={onRefresh} variant="contained">
Refresh
@@ -46,7 +34,7 @@ const SummaryDetails = ({
{hasDetails && (
<Card variant="outlined">
<CardHeader
subheader={fake ? "Summary (Fake Data)" : "Summary"}
subheader={`Summary ${fake ? "(Fake Data)" : ""}`}
action={<CopyToClipboard contentRef={cardContentRef} />}
/>
<CardContent ref={cardContentRef}>

View File

@@ -0,0 +1,52 @@
# SummaryDetails Component
## Overview
The `SummaryDetails` component is a flexible UI component designed to display a summary of details related to a specific entity in a card format. It is equipped with optional functionalities such as refreshing the data.
## Props
The component accepts the following props:
1. `entity`: An object representing the entity whose details are to be displayed. It should have a name and details, where details is an array of `EntityDetails` objects.
2. `hasRefreshButton` (optional): A boolean indicating if a Refresh button should be displayed. If true, the button is shown, allowing the user to refresh the entity details.
3. `fake` (optional): A boolean indicating if the displayed data is fake. If true, a label '(Fake Data)' is displayed in the card's header.
4. `onRefresh` (optional): A function to be called when the Refresh button is clicked. It should handle the logic for refreshing the entity details.
## UI Structure
- The component starts with a flex container displaying the entity's name and optional button (Refresh) based on the props.
- If the entity has details (checked by `hasDetails`), it displays a card containing:
- A `CardHeader` with a subheader indicating it's a summary and whether the data is fake.
- A `CopyToClipboard` component attached to the card's action, allowing the user to copy the details.
- A `CardContent` section listing all the details. Each detail is displayed as a `Typography` component, showing the label and value of each `EntityDetails` item.
## How to Use
1. Import the `SummaryDetails` component.
2. Create an entity object with a name and details, where details is an array of objects with label and value.
3. Optionally, decide if you want the Refresh functionality by setting `hasRefreshButton` to `true`.
4. If using the `Refresh` functionality, provide an `onRefresh` function to handle the logic.
5. Render the `SummaryDetails` component with the desired props.
## Example
```javascript
<SummaryDetails
entity={{
name: "Sample Entity",
details: [
{ label: "Detail 1", value: "Value 1" },
{ label: "Detail 2", value: "Value 2" },
// ... more details
],
}}
hasRefreshButton={true}
onRefresh={() => {
// handle refresh button logic/callback
}}
/>
```

View File

@@ -10,8 +10,15 @@ import { NoDataOverlay } from "@/components/noDataOverlay";
import { StyledTableCell, StyledTableRow } from "./style";
import { ICustomTable, CustomTableConfiguration } from "@/types";
import { Checkbox, Skeleton } from "@mui/material";
import ErrorBoundary from "@/components/error_boundary";
const CustomTable = ({ configuration, data, loading, tkey }: ICustomTable) => {
const CustomTable = ({
configuration,
data,
loading,
tkey,
onConsumeAction,
}: ICustomTable) => {
if (loading)
return <Skeleton variant="rectangular" animation="wave" height={200} />;
@@ -22,7 +29,12 @@ const CustomTable = ({ configuration, data, loading, tkey }: ICustomTable) => {
const renderTableCell = (
value: any,
cellKey: string,
render?: (param: any) => void | undefined,
render?: (
param: any,
data?: any,
onFunc?: (param: any) => void,
) => void | undefined,
rowData?: any,
) => {
let renderedValue = value;
@@ -34,18 +46,29 @@ const CustomTable = ({ configuration, data, loading, tkey }: ICustomTable) => {
renderedValue = <Checkbox disabled checked={value} />;
// cover use case if we want to render a component
if (render) renderedValue = render(value);
if (render) renderedValue = render(value, rowData, onConsumeAction);
// catch use case where the value is an object but the render function is not provided in the table config
if (
typeof value === "object" &&
!Array.isArray(value) &&
render === undefined
) {
console.warn("Missing render function for column " + cellKey);
}
return (
<StyledTableCell key={cellKey} align="left">
{renderedValue}
</StyledTableCell>
<ErrorBoundary>
<StyledTableCell key={cellKey} align="left">
{renderedValue}
</StyledTableCell>
</ErrorBoundary>
);
};
return (
<TableContainer component={Paper}>
<Table sx={{ minWidth: 700 }} aria-label="customized table">
<TableContainer component={Paper} style={{ maxHeight: 350 }}>
<Table stickyHeader sx={{ minWidth: 700 }} aria-label="customized table">
<TableHead>
<TableRow>
{configuration.map((header: CustomTableConfiguration) => (
@@ -54,17 +77,18 @@ const CustomTable = ({ configuration, data, loading, tkey }: ICustomTable) => {
</TableRow>
</TableHead>
<TableBody>
{data.map((data: any, rowIndex: number) => (
{data.map((rowData: any, rowIndex: number) => (
<StyledTableRow key={rowIndex}>
{configuration.map(
(column: CustomTableConfiguration, columnIndex: number) => {
const cellValue: any = data[column.key];
const cellValue: any = rowData[column.key];
const cellKey = tkey + ":" + column.key + ":" + rowIndex;
const renderComponent = column?.render;
return renderTableCell(
cellValue,
cellKey + ":" + columnIndex,
renderComponent,
rowData,
);
},
)}

View File

@@ -0,0 +1,75 @@
# CustomTable Component
## Overview
The `CustomTable` component is a dynamic and flexible table designed to display data in a structured tabular format. It is highly customizable, allowing specific rendering for different data types and providing a user-friendly display for loading and empty data states.
## Props
The component accepts the following props:
1. `configuration`: An array of `CustomTableConfiguration` objects defining the structure and customization options for table columns, including:
- `key`: Corresponds to the key in the data objects for the column.
- `label`: Text label for the column header.
- `render` (optional): A function for custom rendering of the cell's content.
- `data`: An array of data objects, each representing a row in the table.
- `loading` (optional): If `true`, displays a loading state (skeleton screen).
- `tkey`: A unique key for the table, used for constructing unique cell keys.
## Behavior
- **Loading State**: Displays a `Skeleton` loader when `loading` is `true`.
- **Empty Data State**: Displays a `NoDataOverlay` component with a message if no data is available.
- **Data Rendering**:
- Dynamically renders cells based on `configuration`.
- Handles different data types:
- Joins array elements with a comma.
- Shows a disabled checkbox for boolean values.
- Uses the provided `render` function for custom rendering.
- Logs a warning if a cell's value is an object (not an array), and no `render` function is provided.
- **Error Handling**: Each cell is wrapped in an `ErrorBoundary` component for graceful error handling.
## How to Use
1. Import the `CustomTable` component.
2. Define the `configuration` for table columns.
3. Provide `data` as an array of objects corresponding to the configuration.
4. Optionally, control the loading state with the `loading` prop.
5. Provide a unique `tkey` for the table.
## Example
```javascript
import CustomTable from "./CustomTable";
const tableConfig = [
{ key: "name", label: "Name" },
{ key: "age", label: "Age" },
{
key: "isActive",
label: "Active",
render: (isActive) => (isActive ? "Yes" : "No"),
},
];
const tableData = [
{ name: "John Doe", age: 30, isActive: true },
{ name: "Jane Smith", age: 25, isActive: false },
];
const SomeComponent = () => {
return (
<div>
<CustomTable
configuration={tableConfig}
data={tableData}
loading={false}
tkey="unique-table-key"
/>
</div>
);
};
export default SomeComponent;
```

View File

@@ -4,7 +4,6 @@ import TableRow from "@mui/material/TableRow";
export const StyledTableCell = styled(TableCell)(({ theme }) => ({
[`&.${tableCellClasses.head}`]: {
// backgroundColor: theme.palette.common.black,
backgroundColor: "#003258",
color: theme.palette.common.white,
},

View File

@@ -1,19 +1,4 @@
// AP - Summary
export const APSummaryDetails = [
{
label: "DID",
value: "did:sov:test:1274",
},
{
label: "IP",
value: "127.0.0.2",
},
{
label: "Network",
value: "Carlo's Home Network",
},
];
// AP - 2 Tables Configurations to display labels
export const APAttachmentsTableConfig = [
{
@@ -59,21 +44,10 @@ export const APServiceRepositoryTableConfig = [
{
key: "status",
label: "Status",
},
{
key: "other",
label: "Type",
render: (value: any) => {
let renderedValue: any = "";
if (typeof value === "object") {
const label = Object.keys(value)[0];
const info = value[label];
renderedValue = (
<code>
{label} {info}
</code>
);
}
if (Array.isArray(value.data)) renderedValue = value.data.join(", ");
else console.error("Status is not an array", value);
return renderedValue;
},
},

View File

@@ -1,4 +1,5 @@
import { Button } from "@mui/material";
import EntityActions from "@/components/entity_actions";
import ConsumeAction from "@/components/consume_action";
export const ClientTableConfig = [
{
@@ -12,11 +13,13 @@ export const ClientTableConfig = [
{
key: "endpoint_url",
label: "End Point",
render: () => {
render: (value: any, rowData: any, onConsume: any) => {
return (
<Button disabled variant="outlined">
Consume
</Button>
<ConsumeAction
rowData={rowData}
onConsume={onConsume}
endpoint={value}
/>
);
},
},
@@ -52,26 +55,43 @@ export const ServiceTableConfig = [
label: "Entity DID",
},
{
key: "status",
label: "Status",
},
{
key: "other",
label: "Action",
key: "usage",
label: "Usage",
render: (value: any) => {
let renderedValue: any = "";
if (typeof value === "object")
renderedValue = (
<>
{value.action.map((actionType: string) => (
<>
<code>{actionType}</code>
<br />
</>
))}
</>
);
let renderedValue = "";
if (value.length > 0) {
renderedValue = value.map((item: any, index: number) => {
return (
<div key={index}>
{item.consumer_entity_did} ({item.times_consumed})
</div>
);
});
}
return renderedValue;
},
},
{
key: "status",
label: "Status",
render: (value: any) => {
let renderedValue: any = "";
if (Array.isArray(value.data)) {
renderedValue = value.data.join(", ");
} else {
console.error("Status is not an array", value);
}
return renderedValue;
},
},
{
key: "action",
label: "Actions",
render: (value: any, rowData?: any) => {
if (value && value?.data.length > 0)
return <EntityActions rowData={rowData} endpointData={value.data} />;
else return "N/A";
},
},
];

View File

@@ -1,77 +0,0 @@
import { Button } from "@mui/material";
export const Client2ConsumerTableConfig = [
{
key: "service_name",
label: "Service name",
},
{
key: "service_type",
label: "Service Type",
},
{
key: "endpoint_url",
label: "End Point",
render: () => {
return (
<Button disabled variant="outlined">
Consume
</Button>
);
},
},
// {
// key: "entity",
// label: "Entity",
// },
{
key: "entity_did",
label: "Entity DID",
},
// {
// key: "network",
// label: "Network",
// },
];
export const Client2ProducerTableConfig = [
{
key: "service_name",
label: "Service name",
},
{
key: "service_type",
label: "Service Type",
},
{
key: "endpoint_url",
label: "End Point",
},
{
key: "entity_did",
label: "Entity DID",
},
{
key: "status",
label: "Status",
},
{
key: "other",
label: "Action",
render: (value: any) => {
let renderedValue: any = "";
if (typeof value === "object")
renderedValue = (
<>
{value.action.map((actionType: string) => (
<>
<code>{actionType}</code>
<br />
</>
))}
</>
);
return renderedValue;
},
},
];

View File

@@ -0,0 +1,112 @@
import AttachmentIcon from "@mui/icons-material/Attachment";
import ArticleIcon from "@mui/icons-material/Article";
import ConstructionIcon from "@mui/icons-material/Construction";
import AssignmentTurnedInIcon from "@mui/icons-material/AssignmentTurnedIn";
import RemoveCircleIcon from "@mui/icons-material/RemoveCircle";
import AddCircleIcon from "@mui/icons-material/AddCircle";
import PageviewIcon from "@mui/icons-material/Pageview";
import BuildIcon from "@mui/icons-material/Build";
export const projectConfig: any = {
BASE_URL: "http://localhost:2979/api/v1",
REFRESH_FREQUENCY: 5000,
GROUPS: [
{
groupName: "Attachement",
groupId: 1,
groupColor: "rgb(230, 230, 250)",
groupIcon: <AttachmentIcon />,
messageTypes: [
{ id: 1, label: "Attachment Request Send" },
{ id: 2, label: "Attachment Request Received" },
{ id: 3, label: "Attachment Response Send" },
{ id: 4, label: "Attachment Response Received" },
],
},
{
groupName: "Connection Setup",
groupId: 2,
groupColor: "rgb(245, 222, 179)",
groupIcon: <ConstructionIcon />,
messageTypes: [
{ id: 1, label: "Connection request send" },
{ id: 2, label: "Connection request received" },
{ id: 3, label: "Connection response send" },
{ id: 4, label: "Connection response received" },
],
},
{
groupName: "Presentation",
groupId: 3,
groupColor: "rgb(255, 209, 220)",
groupIcon: <ArticleIcon />,
messageTypes: [
{ id: 1, label: "Request send" },
{ id: 2, label: "Request received" },
{ id: 3, label: "Presentation send" },
{ id: 4, label: "Presentation received" },
{ id: 5, label: "Presentation acknowledged" },
],
},
{
groupName: "DID Resolution",
groupId: 4,
groupColor: "rgb(189, 255, 243)",
groupIcon: <AssignmentTurnedInIcon />,
messageTypes: [
{ id: 1, label: "DID Resolution Request send" },
{ id: 2, label: "DID Resolution Request received" },
{ id: 3, label: "DID Resolution Response send" },
{ id: 4, label: "DID Resolution Response received" },
],
},
{
groupName: "Service De-registration",
groupId: 5,
groupColor: "rgb(255, 218, 185)",
groupIcon: <RemoveCircleIcon />,
messageTypes: [
{ id: 1, label: "Service De-registration send" },
{ id: 2, label: "Service De-registration received" },
{ id: 3, label: "Service De-registration successful send" },
{ id: 4, label: "Service De-registration successful received" },
],
},
{
groupName: "Service Registration",
groupId: 6,
groupColor: "rgb(200, 162, 200)",
groupIcon: <AddCircleIcon />,
messageTypes: [
{ id: 1, label: "Service Registration send" },
{ id: 2, label: "Service Registration received" },
{ id: 3, label: "Service Registration successful send" },
{ id: 4, label: "Service Registration successful received" },
],
},
{
groupName: "Service Discovery",
groupId: 7,
groupColor: "rgb(255, 250, 205)",
groupIcon: <PageviewIcon />,
messageTypes: [
{ id: 1, label: "Service Discovery send" },
{ id: 2, label: "Service Discovery received" },
{ id: 3, label: "Service Discovery Result send" },
{ id: 4, label: "Service Discovery Result received" },
],
},
{
groupName: "Service Operation",
groupId: 8,
groupColor: "rgb(135, 206, 235)",
groupIcon: <BuildIcon />,
messageTypes: [
{ id: 1, label: "Service Request Send" },
{ id: 2, label: "Service Request Received" },
{ id: 3, label: "Service Response Send" },
{ id: 4, label: "Service Response Received" },
],
},
],
};

View File

@@ -1,19 +1,6 @@
// DLG Summary Details
import { formatDateTime } from "@/utils/helpers";
export const DLGSummaryDetails = [
{
label: "DID",
value: "did:sov:test:1274",
},
{
label: "URL",
value: "dlg.tu-berlin.de",
},
];
// DLG Resolution Table
// DLG - 2 Tables Configurations to display labels
export const DLGResolutionDummyData = [
{

Some files were not shown because too many files have changed in this diff Show More