cmdbox 0.5.1.2__py3-none-any.whl → 0.5.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of cmdbox might be problematic. Click here for more details.

Files changed (143) hide show
  1. cmdbox/app/app.py +4 -2
  2. cmdbox/app/auth/signin.py +634 -631
  3. cmdbox/app/client.py +10 -10
  4. cmdbox/app/common.py +50 -6
  5. cmdbox/app/commons/convert.py +9 -0
  6. cmdbox/app/commons/module.py +113 -113
  7. cmdbox/app/commons/redis_client.py +40 -29
  8. cmdbox/app/edge.py +4 -4
  9. cmdbox/app/features/cli/audit_base.py +138 -0
  10. cmdbox/app/features/cli/cmdbox_audit_createdb.py +224 -0
  11. cmdbox/app/features/cli/cmdbox_audit_delete.py +308 -0
  12. cmdbox/app/features/cli/cmdbox_audit_search.py +416 -0
  13. cmdbox/app/features/cli/cmdbox_audit_write.py +247 -0
  14. cmdbox/app/features/cli/cmdbox_client_file_copy.py +207 -207
  15. cmdbox/app/features/cli/cmdbox_client_file_download.py +207 -207
  16. cmdbox/app/features/cli/cmdbox_client_file_list.py +193 -193
  17. cmdbox/app/features/cli/cmdbox_client_file_mkdir.py +191 -191
  18. cmdbox/app/features/cli/cmdbox_client_file_move.py +199 -199
  19. cmdbox/app/features/cli/cmdbox_client_file_remove.py +190 -190
  20. cmdbox/app/features/cli/cmdbox_client_file_rmdir.py +190 -190
  21. cmdbox/app/features/cli/cmdbox_client_file_upload.py +212 -212
  22. cmdbox/app/features/cli/cmdbox_client_server_info.py +166 -166
  23. cmdbox/app/features/cli/cmdbox_server_list.py +88 -88
  24. cmdbox/app/features/cli/cmdbox_server_stop.py +138 -138
  25. cmdbox/app/features/web/cmdbox_web_audit.py +81 -0
  26. cmdbox/app/features/web/cmdbox_web_audit_metrics.py +72 -0
  27. cmdbox/app/features/web/cmdbox_web_del_cmd.py +2 -0
  28. cmdbox/app/features/web/cmdbox_web_del_pipe.py +1 -0
  29. cmdbox/app/features/web/cmdbox_web_do_signin.py +12 -2
  30. cmdbox/app/features/web/cmdbox_web_do_signout.py +1 -0
  31. cmdbox/app/features/web/cmdbox_web_exec_cmd.py +31 -2
  32. cmdbox/app/features/web/cmdbox_web_exec_pipe.py +1 -0
  33. cmdbox/app/features/web/cmdbox_web_filer download.py +43 -42
  34. cmdbox/app/features/web/cmdbox_web_filer.py +1 -0
  35. cmdbox/app/features/web/cmdbox_web_filer_upload.py +65 -64
  36. cmdbox/app/features/web/cmdbox_web_gui.py +166 -165
  37. cmdbox/app/features/web/cmdbox_web_load_pin.py +43 -43
  38. cmdbox/app/features/web/cmdbox_web_raw_pipe.py +87 -87
  39. cmdbox/app/features/web/cmdbox_web_save_cmd.py +1 -0
  40. cmdbox/app/features/web/cmdbox_web_save_pin.py +42 -42
  41. cmdbox/app/features/web/cmdbox_web_save_pipe.py +1 -0
  42. cmdbox/app/features/web/cmdbox_web_user_data.py +58 -0
  43. cmdbox/app/features/web/cmdbox_web_users.py +12 -0
  44. cmdbox/app/options.py +788 -601
  45. cmdbox/app/web.py +7 -1
  46. cmdbox/extensions/features.yml +23 -0
  47. cmdbox/extensions/sample_project/sample/app/features/cli/sample_client_time.py +82 -82
  48. cmdbox/extensions/sample_project/sample/app/features/cli/sample_server_time.py +145 -145
  49. cmdbox/extensions/user_list.yml +5 -0
  50. cmdbox/licenses/{LICENSE.Sphinx.8.1.3(BSD License).txt → LICENSE.Sphinx.8.2.3(UNKNOWN).txt} +1 -1
  51. cmdbox/licenses/LICENSE.argcomplete.3.6.2(Apache Software License).txt +177 -0
  52. cmdbox/licenses/{LICENSE.babel.2.16.0(BSD License).txt → LICENSE.babel.2.17.0(BSD License).txt } +1 -1
  53. cmdbox/licenses/{LICENSE.pkginfo.1.10.0(MIT License).txt → LICENSE.charset-normalizer.3.4.1(MIT License).txt } +1 -1
  54. cmdbox/licenses/LICENSE.gevent.25.4.1(MIT).txt +25 -0
  55. cmdbox/licenses/LICENSE.greenlet.3.2.0(MIT AND Python-2.0).txt +30 -0
  56. cmdbox/licenses/LICENSE.gunicorn.23.0.0(MIT License).txt +23 -0
  57. cmdbox/licenses/LICENSE.importlib_metadata.8.6.1(Apache Software License).txt +202 -0
  58. cmdbox/licenses/LICENSE.nh3.0.2.21(MIT).txt +21 -0
  59. cmdbox/licenses/{LICENSE.pillow.11.0.0(CMU License (MIT-CMU)).txt → LICENSE.pillow.11.1.0(CMU License (MIT-CMU)).txt } +27 -40
  60. cmdbox/licenses/LICENSE.pillow.11.2.1(UNKNOWN).txt +1200 -0
  61. cmdbox/licenses/LICENSE.plyer.2.1.0(MIT License).txt +19 -0
  62. cmdbox/licenses/LICENSE.prompt_toolkit.3.0.50(BSD License).txt +27 -0
  63. cmdbox/licenses/LICENSE.prompt_toolkit.3.0.51(BSD License).txt +27 -0
  64. cmdbox/licenses/LICENSE.psycopg-binary.3.2.6(GNU Lesser General Public License v3 (LGPLv3)).txt +165 -0
  65. cmdbox/licenses/LICENSE.psycopg-pool.3.2.6(GNU Lesser General Public License v3 (LGPLv3)).txt +165 -0
  66. cmdbox/licenses/LICENSE.psycopg.3.2.6(GNU Lesser General Public License v3 (LGPLv3)).txt +165 -0
  67. cmdbox/licenses/LICENSE.pycryptodome.3.22.0(BSD License; Public Domain).txt +61 -0
  68. cmdbox/licenses/LICENSE.pydantic.2.11.3(MIT License).txt +21 -0
  69. cmdbox/licenses/LICENSE.pydantic_core.2.33.1(MIT License).txt +21 -0
  70. cmdbox/licenses/LICENSE.pystray.0.19.5(GNU Lesser General Public License v3 (LGPLv3)).txt +674 -0
  71. cmdbox/licenses/LICENSE.questionary.2.1.0(MIT License).txt +19 -0
  72. cmdbox/licenses/LICENSE.roman-numerals-py.3.1.0(CC0 1.0 Universal (CC0 1.0) Public Domain Dedication; Zero-Clause BSD (0BSD)).txt +146 -0
  73. cmdbox/licenses/{LICENSE.six.1.16.0(MIT License).txt → LICENSE.six.1.17.0(MIT License).txt } +1 -1
  74. cmdbox/licenses/LICENSE.starlette.0.46.2(BSD License).txt +27 -0
  75. cmdbox/licenses/{LICENSE.charset-normalizer.3.4.0(MIT License).txt → LICENSE.typing-inspection.0.4.0(MIT License).txt } +2 -2
  76. cmdbox/licenses/LICENSE.typing_extensions.4.13.2(UNKNOWN).txt +279 -0
  77. cmdbox/licenses/LICENSE.tzdata.2025.2(Apache Software License).txt +15 -0
  78. cmdbox/licenses/LICENSE.urllib3.2.4.0(UNKNOWN).txt +21 -0
  79. cmdbox/licenses/LICENSE.uvicorn.0.34.1(BSD License).txt +27 -0
  80. cmdbox/licenses/LICENSE.watchfiles.1.0.5(MIT License).txt +21 -0
  81. cmdbox/licenses/files.txt +49 -38
  82. cmdbox/logconf_audit.yml +30 -0
  83. cmdbox/logconf_cmdbox.yml +30 -0
  84. cmdbox/version.py +2 -2
  85. cmdbox/web/assets/apexcharts/apexcharts.css +679 -0
  86. cmdbox/web/assets/apexcharts/apexcharts.min.js +38 -0
  87. cmdbox/web/assets/cmdbox/audit.js +340 -0
  88. cmdbox/web/assets/cmdbox/color_mode.css +520 -0
  89. cmdbox/web/assets/cmdbox/common.js +416 -24
  90. cmdbox/web/assets/cmdbox/filer_modal.js +1 -1
  91. cmdbox/web/assets/cmdbox/list_cmd.js +10 -275
  92. cmdbox/web/assets/cmdbox/list_pipe.js +3 -3
  93. cmdbox/web/assets/cmdbox/main.js +2 -2
  94. cmdbox/web/assets/cmdbox/result.js +2 -2
  95. cmdbox/web/assets/cmdbox/signin.js +2 -2
  96. cmdbox/web/assets/cmdbox/users.js +19 -20
  97. cmdbox/web/assets/cmdbox/view_raw.js +1 -1
  98. cmdbox/web/assets/cmdbox/view_result.js +11 -13
  99. cmdbox/web/assets/filer/filer.js +2 -2
  100. cmdbox/web/assets/filer/main.js +2 -2
  101. cmdbox/web/assets_license_list.txt +4 -1
  102. cmdbox/web/audit.html +268 -0
  103. cmdbox/web/filer.html +37 -12
  104. cmdbox/web/gui.html +36 -53
  105. cmdbox/web/result.html +24 -3
  106. cmdbox/web/signin.html +35 -14
  107. cmdbox/web/users.html +21 -3
  108. {cmdbox-0.5.1.2.dist-info → cmdbox-0.5.3.dist-info}/METADATA +28 -5
  109. {cmdbox-0.5.1.2.dist-info → cmdbox-0.5.3.dist-info}/RECORD +142 -103
  110. {cmdbox-0.5.1.2.dist-info → cmdbox-0.5.3.dist-info}/entry_points.txt +0 -1
  111. cmdbox/licenses/LICENSE.nh3.0.2.18(MIT).txt +0 -1
  112. /cmdbox/licenses/{LICENSE.Jinja2.3.1.4(BSD License).txt → LICENSE.Jinja2.3.1.6(BSD License).txt} +0 -0
  113. /cmdbox/licenses/{LICENSE.Pygments.2.18.0(BSD License).txt → LICENSE.Pygments.2.19.1(BSD License).txt} +0 -0
  114. /cmdbox/licenses/{LICENSE.anyio.4.6.2.post1(MIT License).txt → LICENSE.anyio.4.9.0(MIT License).txt} +0 -0
  115. /cmdbox/licenses/{LICENSE.argcomplete.3.5.1(Apache Software License).txt → LICENSE.argcomplete.3.6.1(Apache Software License).txt} +0 -0
  116. /cmdbox/licenses/{LICENSE.certifi.2024.8.30(Mozilla Public License 2.0 (MPL 2.0)).txt → LICENSE.certifi.2025.1.31(Mozilla Public License 2.0 (MPL 2.0)).txt} +0 -0
  117. /cmdbox/licenses/{LICENSE.click.8.1.7(BSD License).txt → LICENSE.click.8.1.8(BSD License).txt} +0 -0
  118. /cmdbox/licenses/{LICENSE.cryptography.43.0.3(Apache Software License; BSD License).txt → LICENSE.cryptography.44.0.2(Apache Software License; BSD License).txt} +0 -0
  119. /cmdbox/licenses/{LICENSE.fastapi.0.115.5(MIT License).txt → LICENSE.fastapi.0.115.12(MIT License).txt} +0 -0
  120. /cmdbox/licenses/{LICENSE.importlib_metadata.8.5.0(Apache Software License).txt → LICENSE.id.1.5.0(Apache Software License).txt} +0 -0
  121. /cmdbox/licenses/{LICENSE.keyring.25.5.0(MIT License).txt → LICENSE.keyring.25.6.0(MIT License).txt} +0 -0
  122. /cmdbox/licenses/{LICENSE.more-itertools.10.5.0(MIT License).txt → LICENSE.more-itertools.10.6.0(MIT License).txt} +0 -0
  123. /cmdbox/licenses/{LICENSE.numpy.2.1.3(BSD License).txt → LICENSE.numpy.2.2.4(BSD License).txt} +0 -0
  124. /cmdbox/licenses/{LICENSE.prettytable.3.12.0(BSD License).txt → LICENSE.prettytable.3.16.0(UNKNOWN).txt} +0 -0
  125. /cmdbox/licenses/{LICENSE.pydantic.2.10.2(MIT License).txt → LICENSE.pydantic.2.11.1(MIT License).txt} +0 -0
  126. /cmdbox/licenses/{LICENSE.pydantic_core.2.27.1(MIT License).txt → LICENSE.pydantic_core.2.33.0(MIT License).txt} +0 -0
  127. /cmdbox/licenses/{LICENSE.python-dotenv.1.0.1(BSD License).txt → LICENSE.python-dotenv.1.1.0(BSD License).txt} +0 -0
  128. /cmdbox/licenses/{LICENSE.python-multipart.0.0.17(Apache Software License).txt → LICENSE.python-multipart.0.0.20(Apache Software License).txt} +0 -0
  129. /cmdbox/licenses/{LICENSE.redis.5.2.0(MIT License).txt → LICENSE.redis.5.2.1(MIT License).txt} +0 -0
  130. /cmdbox/licenses/{LICENSE.rich.13.9.4(MIT License).txt → LICENSE.rich.14.0.0(MIT License).txt} +0 -0
  131. /cmdbox/licenses/{LICENSE.sphinx-intl.2.3.0(BSD License).txt → LICENSE.sphinx-intl.2.3.1(BSD License).txt} +0 -0
  132. /cmdbox/licenses/{LICENSE.starlette.0.41.3(BSD License).txt → LICENSE.starlette.0.46.1(BSD License).txt} +0 -0
  133. /cmdbox/licenses/{LICENSE.tomli.2.1.0(MIT License).txt → LICENSE.tomli.2.2.1(MIT License).txt} +0 -0
  134. /cmdbox/licenses/{LICENSE.twine.5.1.1(Apache Software License).txt → LICENSE.twine.6.1.0(Apache Software License).txt} +0 -0
  135. /cmdbox/licenses/{LICENSE.typing_extensions.4.12.2(Python Software Foundation License).txt → LICENSE.typing_extensions.4.13.0(UNKNOWN).txt} +0 -0
  136. /cmdbox/licenses/{LICENSE.urllib3.2.2.3(MIT License).txt → LICENSE.urllib3.2.3.0(MIT License).txt} +0 -0
  137. /cmdbox/licenses/{LICENSE.uvicorn.0.32.1(BSD License).txt → LICENSE.uvicorn.0.34.0(BSD License).txt} +0 -0
  138. /cmdbox/licenses/{LICENSE.watchfiles.1.0.0(MIT License).txt → LICENSE.watchfiles.1.0.4(MIT License).txt} +0 -0
  139. /cmdbox/licenses/{LICENSE.websockets.14.1(BSD License).txt → LICENSE.websockets.15.0.1(BSD License).txt} +0 -0
  140. /cmdbox/licenses/{LICENSE.zope.interface.7.1.1(Zope Public License).txt → LICENSE.zope.interface.7.2(Zope Public License).txt} +0 -0
  141. {cmdbox-0.5.1.2.dist-info → cmdbox-0.5.3.dist-info}/LICENSE +0 -0
  142. {cmdbox-0.5.1.2.dist-info → cmdbox-0.5.3.dist-info}/WHEEL +0 -0
  143. {cmdbox-0.5.1.2.dist-info → cmdbox-0.5.3.dist-info}/top_level.txt +0 -0
@@ -1,43 +1,43 @@
1
- from cmdbox.app import feature
2
- from cmdbox.app.web import Web
3
- from fastapi import FastAPI, Request, Response, HTTPException
4
-
5
-
6
- class LoadPin(feature.WebFeature):
7
- def route(self, web:Web, app:FastAPI) -> None:
8
- """
9
- webモードのルーティングを設定します
10
-
11
- Args:
12
- web (Web): Webオブジェクト
13
- app (FastAPI): FastAPIオブジェクト
14
- """
15
- @app.post('/gui/load_cmd_pin')
16
- async def load_cmd_pin(req:Request, res:Response):
17
- signin = web.signin.check_signin(req, res)
18
- if signin is not None:
19
- raise HTTPException(status_code=401, detail=self.DEFAULT_401_MESSAGE)
20
- if 'signin' not in req.session or req.session['signin'] is None:
21
- return dict(warn='Please sign in.')
22
- form = await req.form()
23
- title = form.get('title')
24
- sess = req.session['signin']
25
- data = web.user_data(req, sess['uid'], sess['name'], 'cmdpins', title)
26
- if data is None:
27
- return dict(success='off')
28
- return dict(success=data)
29
-
30
- @app.post('/gui/load_pipe_pin')
31
- async def load_pipe_pin(req:Request, res:Response):
32
- signin = web.signin.check_signin(req, res)
33
- if signin is not None:
34
- raise HTTPException(status_code=401, detail=self.DEFAULT_401_MESSAGE)
35
- if 'signin' not in req.session or req.session['signin'] is None:
36
- return dict(warn='Please sign in.')
37
- form = await req.form()
38
- title = form.get('title')
39
- sess = req.session['signin']
40
- data = web.user_data(req, sess['uid'], sess['name'], 'pipepins', title)
41
- if data is None:
42
- return dict(success='off')
43
- return dict(success=data)
1
+ from cmdbox.app import feature
2
+ from cmdbox.app.web import Web
3
+ from fastapi import FastAPI, Request, Response, HTTPException
4
+
5
+
6
+ class LoadPin(feature.WebFeature):
7
+ def route(self, web:Web, app:FastAPI) -> None:
8
+ """
9
+ webモードのルーティングを設定します
10
+
11
+ Args:
12
+ web (Web): Webオブジェクト
13
+ app (FastAPI): FastAPIオブジェクト
14
+ """
15
+ @app.post('/gui/load_cmd_pin')
16
+ async def load_cmd_pin(req:Request, res:Response):
17
+ signin = web.signin.check_signin(req, res)
18
+ if signin is not None:
19
+ raise HTTPException(status_code=401, detail=self.DEFAULT_401_MESSAGE)
20
+ if 'signin' not in req.session or req.session['signin'] is None:
21
+ return dict(warn='Please sign in.')
22
+ form = await req.form()
23
+ title = form.get('title')
24
+ sess = req.session['signin']
25
+ data = web.user_data(req, sess['uid'], sess['name'], 'cmdpins', title)
26
+ if data is None:
27
+ return dict(success='off')
28
+ return dict(success=data)
29
+
30
+ @app.post('/gui/load_pipe_pin')
31
+ async def load_pipe_pin(req:Request, res:Response):
32
+ signin = web.signin.check_signin(req, res)
33
+ if signin is not None:
34
+ raise HTTPException(status_code=401, detail=self.DEFAULT_401_MESSAGE)
35
+ if 'signin' not in req.session or req.session['signin'] is None:
36
+ return dict(warn='Please sign in.')
37
+ form = await req.form()
38
+ title = form.get('title')
39
+ sess = req.session['signin']
40
+ data = web.user_data(req, sess['uid'], sess['name'], 'pipepins', title)
41
+ if data is None:
42
+ return dict(success='off')
43
+ return dict(success=data)
@@ -1,87 +1,87 @@
1
- from cmdbox.app import common
2
- from cmdbox.app.features.web import cmdbox_web_raw_cmd, cmdbox_web_load_cmd
3
- from cmdbox.app.web import Web
4
- from fastapi import FastAPI, Request, Response, HTTPException
5
- from typing import Dict, Any, List
6
- import logging
7
- import json
8
-
9
-
10
- class RawPipe(cmdbox_web_raw_cmd.RawCmd, cmdbox_web_load_cmd.LoadCmd):
11
- def route(self, web:Web, app:FastAPI) -> None:
12
- """
13
- webモードのルーティングを設定します
14
-
15
- Args:
16
- web (Web): Webオブジェクト
17
- app (FastAPI): FastAPIオブジェクト
18
- """
19
- @app.post('/gui/raw_pipe')
20
- async def raw_pipe(req:Request, res:Response):
21
- signin = web.signin.check_signin(req, res)
22
- if signin is not None:
23
- raise HTTPException(status_code=401, detail=self.DEFAULT_401_MESSAGE)
24
- form = await req.form()
25
- title = form.get('title')
26
- opt = form.get('opt')
27
- ret = self.raw_pipe(web, title, json.loads(opt))
28
- return ret
29
-
30
- def raw_pipe(self, web:Web, title:str, opt:Dict[str, Any], setredis:bool=False) -> List[Dict[str, Any]]:
31
- """
32
- パイプラインのコマンドライン文字列、curlコマンド文字列を作成する
33
-
34
- Args:
35
- web (Web): Webオブジェクト
36
- title (str): タイトル
37
- opt (dict): オプション
38
- setredis (bool): Webインスタンスのredis接続情報をオプションにセットするかどうか
39
-
40
- Returns:
41
- list[Dict[str, Any]]: コマンドライン文字列、curlコマンド文字列
42
- """
43
- if web.logger.level == logging.DEBUG:
44
- web.logger.debug(f"web.raw_pipe: title={title}, opt={opt}")
45
- cmdlines = []
46
- errormsg = []
47
- curl_cmd_file = ""
48
- for i, cmd_title in enumerate(opt['pipe_cmd']):
49
- if cmd_title == '':
50
- continue
51
- cmd_opt = self.load_cmd(web, cmd_title)
52
- cmd_ref = web.options.get_cmd_choices(cmd_opt['mode'], cmd_opt['cmd'], True)
53
- chk_stdin = len([ref for ref in cmd_ref if ref['opt'] == 'stdin']) > 0
54
-
55
- if 'debug' in cmd_opt and cmd_opt['debug']:
56
- errormsg.append(f'The "debug" option is not supported with the debug option "true". ({cmd_title})')
57
- if 'output_csv' in cmd_opt and cmd_opt['output_csv'] != '':
58
- errormsg.append(f'The "output_csv" option is not supported in pipe. ({cmd_title})')
59
- if i>0:
60
- if chk_stdin and ('stdin' not in cmd_opt or not cmd_opt['stdin']):
61
- errormsg.append(f'The "stdin" option should be specified for the second and subsequent commands. ({cmd_title})')
62
- if chk_stdin and 'pred_input_type' in cmd_opt and cmd_opt['pred_input_type'] not in ['capture']:
63
- errormsg.append(f'When using the "stdin" option, "pred_input_type" cannot be other than "capture". ({cmd_title})')
64
- for ref in cmd_ref:
65
- if 'fileio' in ref and ref['fileio'] == 'in' and ref['opt'] in cmd_opt and cmd_opt[ref['opt']] != '' and len([v for v in cmd_opt[ref['opt']] if v != '']) > 0:
66
- errormsg.append(f'The "{ref["opt"]}" option should not be specified in a second or subsequent command. ({cmd_title})')
67
- if i==0:
68
- if 'request_files' in opt and len(opt['request_files']) > 0:
69
- for fn in opt['request_files']:
70
- if fn in cmd_opt:
71
- cmd_opt[fn] = opt['request_files'][fn]
72
- curl_cmd_file = self.mk_curl_fileup(web, cmd_opt)
73
-
74
- if setredis:
75
- if 'host' in cmd_opt: cmd_opt['host'] = web.redis_host
76
- if 'port' in cmd_opt: cmd_opt['port'] = web.redis_port
77
- if 'password' in cmd_opt: cmd_opt['password'] = web.redis_password
78
- if 'svname' in cmd_opt: cmd_opt['svname'] = web.svname
79
- cmd_output = self.raw_cmd(web, cmd_title, cmd_opt)
80
- cmdlines.append(cmd_output[0]["raw"])
81
-
82
- curl_opt = json.dumps(opt, default=common.default_json_enc)
83
- curl_opt = curl_opt.replace('"', '\\"')
84
- ret = [dict(type='cmdline', raw=' | '.join(cmdlines)),
85
- dict(type='curlcmd', raw=f'curl {curl_cmd_file} http://localhost:{web.listen_port}/exec_pipe/{title}')]
86
- ret += [dict(type='warn', raw=em) for em in errormsg]
87
- return ret
1
+ from cmdbox.app import common
2
+ from cmdbox.app.features.web import cmdbox_web_raw_cmd, cmdbox_web_load_cmd
3
+ from cmdbox.app.web import Web
4
+ from fastapi import FastAPI, Request, Response, HTTPException
5
+ from typing import Dict, Any, List
6
+ import logging
7
+ import json
8
+
9
+
10
+ class RawPipe(cmdbox_web_raw_cmd.RawCmd, cmdbox_web_load_cmd.LoadCmd):
11
+ def route(self, web:Web, app:FastAPI) -> None:
12
+ """
13
+ webモードのルーティングを設定します
14
+
15
+ Args:
16
+ web (Web): Webオブジェクト
17
+ app (FastAPI): FastAPIオブジェクト
18
+ """
19
+ @app.post('/gui/raw_pipe')
20
+ async def raw_pipe(req:Request, res:Response):
21
+ signin = web.signin.check_signin(req, res)
22
+ if signin is not None:
23
+ raise HTTPException(status_code=401, detail=self.DEFAULT_401_MESSAGE)
24
+ form = await req.form()
25
+ title = form.get('title')
26
+ opt = form.get('opt')
27
+ ret = self.raw_pipe(web, title, json.loads(opt))
28
+ return ret
29
+
30
+ def raw_pipe(self, web:Web, title:str, opt:Dict[str, Any], setredis:bool=False) -> List[Dict[str, Any]]:
31
+ """
32
+ パイプラインのコマンドライン文字列、curlコマンド文字列を作成する
33
+
34
+ Args:
35
+ web (Web): Webオブジェクト
36
+ title (str): タイトル
37
+ opt (dict): オプション
38
+ setredis (bool): Webインスタンスのredis接続情報をオプションにセットするかどうか
39
+
40
+ Returns:
41
+ list[Dict[str, Any]]: コマンドライン文字列、curlコマンド文字列
42
+ """
43
+ if web.logger.level == logging.DEBUG:
44
+ web.logger.debug(f"web.raw_pipe: title={title}, opt={opt}")
45
+ cmdlines = []
46
+ errormsg = []
47
+ curl_cmd_file = ""
48
+ for i, cmd_title in enumerate(opt['pipe_cmd']):
49
+ if cmd_title == '':
50
+ continue
51
+ cmd_opt = self.load_cmd(web, cmd_title)
52
+ cmd_ref = web.options.get_cmd_choices(cmd_opt['mode'], cmd_opt['cmd'], True)
53
+ chk_stdin = len([ref for ref in cmd_ref if ref['opt'] == 'stdin']) > 0
54
+
55
+ if 'debug' in cmd_opt and cmd_opt['debug']:
56
+ errormsg.append(f'The "debug" option is not supported with the debug option "true". ({cmd_title})')
57
+ if 'output_csv' in cmd_opt and cmd_opt['output_csv'] != '':
58
+ errormsg.append(f'The "output_csv" option is not supported in pipe. ({cmd_title})')
59
+ if i>0:
60
+ if chk_stdin and ('stdin' not in cmd_opt or not cmd_opt['stdin']):
61
+ errormsg.append(f'The "stdin" option should be specified for the second and subsequent commands. ({cmd_title})')
62
+ if chk_stdin and 'pred_input_type' in cmd_opt and cmd_opt['pred_input_type'] not in ['capture']:
63
+ errormsg.append(f'When using the "stdin" option, "pred_input_type" cannot be other than "capture". ({cmd_title})')
64
+ for ref in cmd_ref:
65
+ if 'fileio' in ref and ref['fileio'] == 'in' and ref['opt'] in cmd_opt and cmd_opt[ref['opt']] != '' and len([v for v in cmd_opt[ref['opt']] if v != '']) > 0:
66
+ errormsg.append(f'The "{ref["opt"]}" option should not be specified in a second or subsequent command. ({cmd_title})')
67
+ if i==0:
68
+ if 'request_files' in opt and len(opt['request_files']) > 0:
69
+ for fn in opt['request_files']:
70
+ if fn in cmd_opt:
71
+ cmd_opt[fn] = opt['request_files'][fn]
72
+ curl_cmd_file = self.mk_curl_fileup(web, cmd_opt)
73
+
74
+ if setredis:
75
+ if 'host' in cmd_opt: cmd_opt['host'] = web.redis_host
76
+ if 'port' in cmd_opt: cmd_opt['port'] = web.redis_port
77
+ if 'password' in cmd_opt: cmd_opt['password'] = web.redis_password
78
+ if 'svname' in cmd_opt: cmd_opt['svname'] = web.svname
79
+ cmd_output = self.raw_cmd(web, cmd_title, cmd_opt)
80
+ cmdlines.append(cmd_output[0]["raw"])
81
+
82
+ curl_opt = json.dumps(opt, default=common.default_json_enc)
83
+ curl_opt = curl_opt.replace('"', '\\"')
84
+ ret = [dict(type='cmdline', raw=' | '.join(cmdlines)),
85
+ dict(type='curlcmd', raw=f'curl {curl_cmd_file} http://localhost:{web.listen_port}/exec_pipe/{title}')]
86
+ ret += [dict(type='warn', raw=em) for em in errormsg]
87
+ return ret
@@ -23,6 +23,7 @@ class SaveCmd(feature.WebFeature):
23
23
  title = form.get('title')
24
24
  opt = form.get('opt')
25
25
  ret = self.save_cmd(web, title, json.loads(opt))
26
+ web.options.audit_exec(req, res, web)
26
27
  return ret
27
28
 
28
29
  def save_cmd(self, web:Web, title:str, opt:Dict[str, Any]) -> Dict[str, str]:
@@ -1,42 +1,42 @@
1
- from cmdbox.app import common, feature
2
- from cmdbox.app.web import Web
3
- from fastapi import FastAPI, Request, Response, HTTPException
4
- from typing import Dict, Any
5
-
6
-
7
- class SavePin(feature.WebFeature):
8
- def route(self, web:Web, app:FastAPI) -> None:
9
- """
10
- webモードのルーティングを設定します
11
-
12
- Args:
13
- web (Web): Webオブジェクト
14
- app (FastAPI): FastAPIオブジェクト
15
- """
16
- @app.post('/gui/save_cmd_pin')
17
- async def save_cmd_pin(req:Request, res:Response):
18
- signin = web.signin.check_signin(req, res)
19
- if signin is not None:
20
- raise HTTPException(status_code=401, detail=self.DEFAULT_401_MESSAGE)
21
- if 'signin' not in req.session or req.session['signin'] is None:
22
- return dict(warn='Please sign in.')
23
- form = await req.form()
24
- title = form.get('title')
25
- pin = form.get('pin')
26
- sess = req.session['signin']
27
- web.user_data(req, sess['uid'], sess['name'], 'cmdpins', title, pin)
28
- return dict(success=f'Command pin "{title}:{pin}" saved.')
29
-
30
- @app.post('/gui/save_pipe_pin')
31
- async def save_pipe_pin(req:Request, res:Response):
32
- signin = web.signin.check_signin(req, res)
33
- if signin is not None:
34
- raise HTTPException(status_code=401, detail=self.DEFAULT_401_MESSAGE)
35
- if 'signin' not in req.session or req.session['signin'] is None:
36
- return dict(warn='Please sign in.')
37
- form = await req.form()
38
- title = form.get('title')
39
- pin = form.get('pin')
40
- sess = req.session['signin']
41
- web.user_data(req, sess['uid'], sess['name'], 'pipepins', title, pin)
42
- return dict(success=f'Pipe pin "{title}:{pin}" saved.')
1
+ from cmdbox.app import common, feature
2
+ from cmdbox.app.web import Web
3
+ from fastapi import FastAPI, Request, Response, HTTPException
4
+ from typing import Dict, Any
5
+
6
+
7
+ class SavePin(feature.WebFeature):
8
+ def route(self, web:Web, app:FastAPI) -> None:
9
+ """
10
+ webモードのルーティングを設定します
11
+
12
+ Args:
13
+ web (Web): Webオブジェクト
14
+ app (FastAPI): FastAPIオブジェクト
15
+ """
16
+ @app.post('/gui/save_cmd_pin')
17
+ async def save_cmd_pin(req:Request, res:Response):
18
+ signin = web.signin.check_signin(req, res)
19
+ if signin is not None:
20
+ raise HTTPException(status_code=401, detail=self.DEFAULT_401_MESSAGE)
21
+ if 'signin' not in req.session or req.session['signin'] is None:
22
+ return dict(warn='Please sign in.')
23
+ form = await req.form()
24
+ title = form.get('title')
25
+ pin = form.get('pin')
26
+ sess = req.session['signin']
27
+ web.user_data(req, sess['uid'], sess['name'], 'cmdpins', title, pin)
28
+ return dict(success=f'Command pin "{title}:{pin}" saved.')
29
+
30
+ @app.post('/gui/save_pipe_pin')
31
+ async def save_pipe_pin(req:Request, res:Response):
32
+ signin = web.signin.check_signin(req, res)
33
+ if signin is not None:
34
+ raise HTTPException(status_code=401, detail=self.DEFAULT_401_MESSAGE)
35
+ if 'signin' not in req.session or req.session['signin'] is None:
36
+ return dict(warn='Please sign in.')
37
+ form = await req.form()
38
+ title = form.get('title')
39
+ pin = form.get('pin')
40
+ sess = req.session['signin']
41
+ web.user_data(req, sess['uid'], sess['name'], 'pipepins', title, pin)
42
+ return dict(success=f'Pipe pin "{title}:{pin}" saved.')
@@ -23,6 +23,7 @@ class SavePipe(feature.WebFeature):
23
23
  title = form.get('title')
24
24
  opt = form.get('opt')
25
25
  ret = self.save_pipe(web, title, json.loads(opt))
26
+ web.options.audit_exec(req, res, web)
26
27
  return ret
27
28
 
28
29
  def save_pipe(self, web:Web, title:str, opt:Dict[str, Any]) -> Dict[str, str]:
@@ -0,0 +1,58 @@
1
+ from cmdbox.app import common, feature
2
+ from cmdbox.app.web import Web
3
+ from fastapi import FastAPI, Request, Response, HTTPException
4
+ from typing import Dict, Any
5
+
6
+
7
+ class UserData(feature.WebFeature):
8
+ def route(self, web:Web, app:FastAPI) -> None:
9
+ """
10
+ webモードのルーティングを設定します
11
+
12
+ Args:
13
+ web (Web): Webオブジェクト
14
+ app (FastAPI): FastAPIオブジェクト
15
+ """
16
+ @app.post('/gui/user_data/load')
17
+ async def load(req:Request, res:Response):
18
+ signin = web.signin.check_signin(req, res)
19
+ if signin is not None:
20
+ raise HTTPException(status_code=401, detail=self.DEFAULT_401_MESSAGE)
21
+ if 'signin' not in req.session or req.session['signin'] is None:
22
+ return dict(warn='Please sign in.')
23
+ form = await req.form()
24
+ categoly = form.get('categoly')
25
+ key = form.get('key')
26
+ sess = req.session['signin']
27
+ ret = web.user_data(req, sess['uid'], sess['name'], categoly, key)
28
+ return dict(success=ret)
29
+
30
+ @app.post('/gui/user_data/save')
31
+ async def save(req:Request, res:Response):
32
+ signin = web.signin.check_signin(req, res)
33
+ if signin is not None:
34
+ raise HTTPException(status_code=401, detail=self.DEFAULT_401_MESSAGE)
35
+ if 'signin' not in req.session or req.session['signin'] is None:
36
+ return dict(warn='Please sign in.')
37
+ form = await req.form()
38
+ categoly = form.get('categoly')
39
+ key = form.get('key')
40
+ val = form.get('val')
41
+ sess = req.session['signin']
42
+ web.user_data(req, sess['uid'], sess['name'], categoly, key, val)
43
+ return dict(success=f'user_data "{categoly}:{key}:val" saved.')
44
+
45
+ @app.post('/gui/user_data/delete')
46
+ async def delete(req:Request, res:Response):
47
+ signin = web.signin.check_signin(req, res)
48
+ if signin is not None:
49
+ raise HTTPException(status_code=401, detail=self.DEFAULT_401_MESSAGE)
50
+ if 'signin' not in req.session or req.session['signin'] is None:
51
+ return dict(warn='Please sign in.')
52
+ form = await req.form()
53
+ categoly = form.get('categoly')
54
+ key = form.get('key')
55
+ val = form.get('val')
56
+ sess = req.session['signin']
57
+ web.user_data(req, sess['uid'], sess['name'], categoly, key, delkey=True)
58
+ return dict(success=f'user_data "{categoly}:{key}:val" deleted.')
@@ -28,6 +28,7 @@ class Users(feature.WebFeature):
28
28
  if signin is not None:
29
29
  return signin
30
30
  res.headers['Access-Control-Allow-Origin'] = '*'
31
+ web.options.audit_exec(req, res, web)
31
32
  return web.users_html_data
32
33
 
33
34
  @app.get('/users/list')
@@ -37,6 +38,7 @@ class Users(feature.WebFeature):
37
38
  return signin
38
39
  if web.signin.get_data() is None:
39
40
  return dict(error='signin_file_data is None.')
41
+ web.options.audit_exec(req, res, web)
40
42
  return web.user_list(None)
41
43
 
42
44
  @app.post('/users/add')
@@ -49,6 +51,7 @@ class Users(feature.WebFeature):
49
51
  form = await req.json()
50
52
  try:
51
53
  web.user_add(form)
54
+ web.options.audit_exec(req, res, web)
52
55
  return dict(success='add user')
53
56
  except Exception as e:
54
57
  return dict(error=str(e))
@@ -63,6 +66,7 @@ class Users(feature.WebFeature):
63
66
  form = await req.json()
64
67
  try:
65
68
  web.user_edit(form)
69
+ web.options.audit_exec(req, res, web)
66
70
  return dict(success='edit user')
67
71
  except Exception as e:
68
72
  return dict(error=str(e))
@@ -79,6 +83,7 @@ class Users(feature.WebFeature):
79
83
  if req.session['signin']['uid'] == form.get('uid', None):
80
84
  raise ValueError('You cannot delete yourself.')
81
85
  web.user_del(form.get('uid', None))
86
+ web.options.audit_exec(req, res, web)
82
87
  return dict(success='delete user')
83
88
  except Exception as e:
84
89
  return dict(error=str(e))
@@ -93,6 +98,7 @@ class Users(feature.WebFeature):
93
98
  form = await req.json()
94
99
  try:
95
100
  apikey = web.apikey_add(form)
101
+ web.options.audit_exec(req, res, web)
96
102
  return dict(success=apikey)
97
103
  except Exception as e:
98
104
  return dict(error=str(e))
@@ -107,6 +113,7 @@ class Users(feature.WebFeature):
107
113
  form = await req.json()
108
114
  try:
109
115
  apikey = web.apikey_del(form)
116
+ web.options.audit_exec(req, res, web)
110
117
  return dict(success=apikey)
111
118
  except Exception as e:
112
119
  return dict(error=str(e))
@@ -119,6 +126,7 @@ class Users(feature.WebFeature):
119
126
  if web.signin.get_data() is None:
120
127
  return dict(error='signin_file_data is None.')
121
128
  try:
129
+ web.options.audit_exec(req, res, web)
122
130
  return web.group_list(None)
123
131
  except Exception as e:
124
132
  return dict(error=str(e))
@@ -133,6 +141,7 @@ class Users(feature.WebFeature):
133
141
  form = await req.json()
134
142
  try:
135
143
  web.group_add(form)
144
+ web.options.audit_exec(req, res, web)
136
145
  return dict(success='add group')
137
146
  except Exception as e:
138
147
  return dict(error=str(e))
@@ -147,6 +156,7 @@ class Users(feature.WebFeature):
147
156
  form = await req.json()
148
157
  try:
149
158
  web.group_edit(form)
159
+ web.options.audit_exec(req, res, web)
150
160
  return dict(success='edit group')
151
161
  except Exception as e:
152
162
  return dict(error=str(e))
@@ -163,6 +173,7 @@ class Users(feature.WebFeature):
163
173
  if form.get('gid', None) in req.session['signin']['gids']:
164
174
  raise ValueError('You cannot delete yourself group.')
165
175
  web.group_del(form.get('gid', None))
176
+ web.options.audit_exec(req, res, web)
166
177
  return dict(success='delete group')
167
178
  except Exception as e:
168
179
  return dict(error=str(e))
@@ -214,6 +225,7 @@ class Users(feature.WebFeature):
214
225
  try:
215
226
  ret = web.change_password(form.get('user_name', None), form.get('password', None),
216
227
  form.get('new_password', None), form.get('confirm_password', None))
228
+ web.options.audit_exec(req, res, web)
217
229
  return ret
218
230
  except Exception as e:
219
231
  return dict(error=str(e))