cmdbox 0.6.2.2__py3-none-any.whl → 0.6.2.4__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.
- cmdbox/app/auth/signin.py +6 -5
- cmdbox/app/common.py +21 -15
- cmdbox/app/feature.py +5 -1
- cmdbox/app/features/cli/agent_base.py +1 -1
- cmdbox/app/features/cli/cmdbox_audit_search.py +23 -1
- cmdbox/app/features/cli/cmdbox_audit_write.py +260 -260
- cmdbox/app/features/cli/cmdbox_cmd_list.py +2 -2
- cmdbox/app/features/cli/cmdbox_cmd_load.py +2 -2
- cmdbox/app/features/cli/cmdbox_edge_config.py +2 -2
- cmdbox/app/features/cli/cmdbox_edge_start.py +1 -1
- cmdbox/app/features/cli/cmdbox_mcp_client.py +174 -0
- cmdbox/app/features/cli/cmdbox_mcp_proxy.py +2 -2
- cmdbox/app/features/cli/cmdbox_server_start.py +1 -1
- cmdbox/app/features/cli/cmdbox_web_apikey_add.py +2 -2
- cmdbox/app/features/cli/cmdbox_web_apikey_del.py +2 -2
- cmdbox/app/features/cli/cmdbox_web_gencert.py +3 -3
- cmdbox/app/features/cli/cmdbox_web_group_add.py +2 -2
- cmdbox/app/features/cli/cmdbox_web_group_del.py +2 -2
- cmdbox/app/features/cli/cmdbox_web_group_edit.py +2 -2
- cmdbox/app/features/cli/cmdbox_web_group_list.py +2 -2
- cmdbox/app/features/cli/cmdbox_web_start.py +12 -12
- cmdbox/app/features/cli/cmdbox_web_stop.py +1 -1
- cmdbox/app/features/cli/cmdbox_web_user_add.py +2 -2
- cmdbox/app/features/cli/cmdbox_web_user_del.py +2 -2
- cmdbox/app/features/cli/cmdbox_web_user_edit.py +2 -2
- cmdbox/app/features/cli/cmdbox_web_user_list.py +2 -2
- cmdbox/app/mcp.py +82 -86
- cmdbox/app/options.py +2 -3
- cmdbox/app/web.py +15 -0
- cmdbox/extensions/features.yml +2 -14
- cmdbox/extensions/sample_project/sample/extensions/user_list.yml +25 -1
- cmdbox/version.py +4 -3
- cmdbox/web/assets/cmdbox/agent.js +1 -0
- cmdbox/web/assets/cmdbox/common.js +2 -0
- cmdbox/web/assets/cmdbox/filer_modal.js +4 -2
- {cmdbox-0.6.2.2.dist-info → cmdbox-0.6.2.4.dist-info}/METADATA +1 -1
- {cmdbox-0.6.2.2.dist-info → cmdbox-0.6.2.4.dist-info}/RECORD +41 -40
- {cmdbox-0.6.2.2.dist-info → cmdbox-0.6.2.4.dist-info}/LICENSE +0 -0
- {cmdbox-0.6.2.2.dist-info → cmdbox-0.6.2.4.dist-info}/WHEEL +0 -0
- {cmdbox-0.6.2.2.dist-info → cmdbox-0.6.2.4.dist-info}/entry_points.txt +0 -0
- {cmdbox-0.6.2.2.dist-info → cmdbox-0.6.2.4.dist-info}/top_level.txt +0 -0
cmdbox/app/auth/signin.py
CHANGED
|
@@ -217,7 +217,7 @@ class Signin(object):
|
|
|
217
217
|
continue
|
|
218
218
|
jadge = rule['rule']
|
|
219
219
|
if logger.level == logging.DEBUG:
|
|
220
|
-
logger.debug(f"rule: {req.url.path}: {jadge}")
|
|
220
|
+
logger.debug(f"path rule: {req.url.path}: {jadge}")
|
|
221
221
|
if jadge == 'allow':
|
|
222
222
|
res.headers['signin'] = 'success'
|
|
223
223
|
return None
|
|
@@ -663,7 +663,7 @@ class Signin(object):
|
|
|
663
663
|
continue
|
|
664
664
|
jadge = rule['rule']
|
|
665
665
|
if logger.level == logging.DEBUG:
|
|
666
|
-
logger.debug(f"rule: {path}: {jadge}")
|
|
666
|
+
logger.debug(f"path rule: {path}: {jadge}")
|
|
667
667
|
if jadge == 'allow':
|
|
668
668
|
return None
|
|
669
669
|
else:
|
|
@@ -747,7 +747,7 @@ class Signin(object):
|
|
|
747
747
|
continue
|
|
748
748
|
jadge = rule['rule']
|
|
749
749
|
if logger.level == logging.DEBUG:
|
|
750
|
-
logger.debug(f"rule: mode={mode}, cmd={cmd}: {jadge}")
|
|
750
|
+
logger.debug(f"cmd rule: mode={mode}, cmd={cmd}: {jadge}")
|
|
751
751
|
return jadge == 'allow'
|
|
752
752
|
|
|
753
753
|
def get_enable_modes(self, req:Request, res:Response) -> List[str]:
|
|
@@ -931,7 +931,8 @@ async def create_request_scope(req:Request=None, res:Response=None, websocket:We
|
|
|
931
931
|
sess = None
|
|
932
932
|
if req is not None:
|
|
933
933
|
sess = req.session if hasattr(req, 'session') else None
|
|
934
|
-
|
|
934
|
+
from cmdbox.app.web import Web
|
|
935
|
+
request_scope.set(dict(req=req, res=res, websocket=websocket, web=Web.getInstance()))
|
|
935
936
|
try:
|
|
936
937
|
yield # リクエストの処理
|
|
937
938
|
finally:
|
|
@@ -954,4 +955,4 @@ def get_request_scope() -> Dict[str, Any]:
|
|
|
954
955
|
Returns:
|
|
955
956
|
Dict[str, Any]: リクエストとレスポンスとWebSocket接続
|
|
956
957
|
"""
|
|
957
|
-
return request_scope.get() if request_scope.get() is not None else dict(req=None, res=None, session=None, websocket=None)
|
|
958
|
+
return request_scope.get() if request_scope.get() is not None else dict(req=None, res=None, session=None, websocket=None, web=None)
|
cmdbox/app/common.py
CHANGED
|
@@ -8,6 +8,7 @@ from rich.logging import RichHandler
|
|
|
8
8
|
from rich.console import Console
|
|
9
9
|
from tabulate import tabulate
|
|
10
10
|
from typing import List, Tuple, Dict, Any
|
|
11
|
+
import argparse
|
|
11
12
|
import asyncio
|
|
12
13
|
import datetime
|
|
13
14
|
import logging
|
|
@@ -27,6 +28,7 @@ import tempfile
|
|
|
27
28
|
import time
|
|
28
29
|
import yaml
|
|
29
30
|
import sys
|
|
31
|
+
import threading
|
|
30
32
|
|
|
31
33
|
|
|
32
34
|
HOME_DIR = Path(os.path.expanduser("~"))
|
|
@@ -439,7 +441,7 @@ def check_fname(fname:str) -> bool:
|
|
|
439
441
|
Returns:
|
|
440
442
|
bool: Trueの場合は使えない文字が含まれている
|
|
441
443
|
"""
|
|
442
|
-
return re.search('[\s
|
|
444
|
+
return re.search('[\s:;\\\\/,\.\?\#\$\%\^\&\!\@\*\~\|\<\>\(\)\{\}\[\]\'\"\`]',str(fname)) is not None
|
|
443
445
|
|
|
444
446
|
def mkdirs(dir_path:Path):
|
|
445
447
|
"""
|
|
@@ -696,28 +698,32 @@ def is_event_loop_running() -> bool:
|
|
|
696
698
|
except RuntimeError:
|
|
697
699
|
return False
|
|
698
700
|
|
|
699
|
-
def exec_sync(
|
|
701
|
+
def exec_sync(apprun, logger:logging.Logger, args:argparse.Namespace, tm:float, pf:List[Dict[str, float]]) -> Tuple[int, Dict[str, Any], Any]:
|
|
700
702
|
""""
|
|
701
703
|
指定された関数が非同期関数であっても同期的に実行します。
|
|
702
704
|
|
|
703
705
|
Args:
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
706
|
+
apprun (function): 関数
|
|
707
|
+
logger (logging.Logger): ロガー
|
|
708
|
+
args (argparse.Namespace): コマンドライン引数
|
|
709
|
+
tm (float): 処理時間
|
|
710
|
+
pf (List[Dict[str, float]]): パフォーマンス情報
|
|
707
711
|
|
|
708
712
|
Returns:
|
|
709
|
-
Any:
|
|
713
|
+
Tuple[int, Dict[str, Any], Any]: 戻り値のタプル。0は成功、1は失敗、2はキャンセル
|
|
710
714
|
"""
|
|
711
|
-
if inspect.iscoroutinefunction(
|
|
715
|
+
if inspect.iscoroutinefunction(apprun):
|
|
712
716
|
if is_event_loop_running():
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
717
|
+
def _run(apprun, ctx, logger, args, tm, pf):
|
|
718
|
+
ctx.append(asyncio.run(apprun(logger, args, tm, pf)))
|
|
719
|
+
ctx = []
|
|
720
|
+
th = threading.Thread(target=_run, args=(apprun, ctx, logger, args, tm, pf))
|
|
721
|
+
th.start()
|
|
722
|
+
th.join()
|
|
723
|
+
result = ctx[0] if ctx else None
|
|
724
|
+
return 0, result, None
|
|
725
|
+
return asyncio.run(apprun(logger, args, tm, pf))
|
|
726
|
+
return apprun(logger, args, tm, pf)
|
|
721
727
|
|
|
722
728
|
def get_tzoffset_str() -> str:
|
|
723
729
|
"""
|
cmdbox/app/feature.py
CHANGED
|
@@ -123,13 +123,17 @@ class Feature(object):
|
|
|
123
123
|
status, res = tool.exec_cmd(opt, logger, timeout, prevres)
|
|
124
124
|
yield status, res
|
|
125
125
|
|
|
126
|
-
def audited_by(self) -> bool:
|
|
126
|
+
def audited_by(self, logger:logging.Logger, args:argparse.Namespace) -> bool:
|
|
127
127
|
"""
|
|
128
128
|
この機能が監査ログを記録する対象かどうかを返します
|
|
129
129
|
|
|
130
130
|
Returns:
|
|
131
|
+
logger (logging.Logger): ロガー
|
|
132
|
+
args (argparse.Namespace): 引数
|
|
131
133
|
bool: 監査ログを記録する場合はTrue
|
|
132
134
|
"""
|
|
135
|
+
if hasattr(self, 'client_only') and self.client_only:
|
|
136
|
+
return False
|
|
133
137
|
return True
|
|
134
138
|
|
|
135
139
|
class OneshotEdgeFeature(Feature):
|
|
@@ -60,7 +60,7 @@ class AgentBase(feature.ResultEdgeFeature):
|
|
|
60
60
|
dict(opt="llmprojectid", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=None,
|
|
61
61
|
description_ja="llmのプロバイダ接続のためのプロジェクトIDを指定します。",
|
|
62
62
|
description_en="Specify the project ID for llm's provider connection."),
|
|
63
|
-
dict(opt="llmsvaccountfile", type=Options.T_FILE, default=None, required=False, multi=False, hide=False, choice=None,
|
|
63
|
+
dict(opt="llmsvaccountfile", type=Options.T_FILE, default=None, required=False, multi=False, hide=False, choice=None, fileio="in",
|
|
64
64
|
description_ja="llmのプロバイダ接続のためのサービスアカウントファイルを指定します。",
|
|
65
65
|
description_en="Specifies the service account file for llm's provider connection."),
|
|
66
66
|
dict(opt="llmlocation", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=None,
|
|
@@ -103,7 +103,22 @@ class AuditSearch(audit_base.AuditBase):
|
|
|
103
103
|
description_en="Specifies the number of rows to retrieve."),
|
|
104
104
|
dict(opt="csv", type=Options.T_BOOL, default=False, required=False, multi=False, hide=False, choice=[False, True],
|
|
105
105
|
description_ja="検索結果をcsvで出力します。",
|
|
106
|
-
description_en="Output search results in csv.")
|
|
106
|
+
description_en="Output search results in csv."),
|
|
107
|
+
dict(opt="output_json", short="o", type=Options.T_FILE, default=None, required=False, multi=False, hide=True, choice=None, fileio="out",
|
|
108
|
+
description_ja="処理結果jsonの保存先ファイルを指定。",
|
|
109
|
+
description_en="Specify the destination file for saving the processing result json."),
|
|
110
|
+
dict(opt="output_json_append", short="a", type=Options.T_BOOL, default=False, required=False, multi=False, hide=True, choice=[True, False],
|
|
111
|
+
description_ja="処理結果jsonファイルを追記保存します。",
|
|
112
|
+
description_en="Save the processing result json file by appending."),
|
|
113
|
+
dict(opt="stdout_log", type=Options.T_BOOL, default=True, required=False, multi=False, hide=True, choice=[True, False],
|
|
114
|
+
description_ja="GUIモードでのみ使用可能です。コマンド実行時の標準出力をConsole logに出力します。",
|
|
115
|
+
description_en="Available only in GUI mode. Outputs standard output during command execution to Console log."),
|
|
116
|
+
dict(opt="capture_stdout", type=Options.T_BOOL, default=True, required=False, multi=False, hide=True, choice=[True, False],
|
|
117
|
+
description_ja="GUIモードでのみ使用可能です。コマンド実行時の標準出力をキャプチャーし、実行結果画面に表示します。",
|
|
118
|
+
description_en="Available only in GUI mode. Captures standard output during command execution and displays it on the execution result screen."),
|
|
119
|
+
dict(opt="capture_maxsize", type=Options.T_INT, default=self.DEFAULT_CAPTURE_MAXSIZE, required=False, multi=False, hide=True, choice=None,
|
|
120
|
+
description_ja="GUIモードでのみ使用可能です。コマンド実行時の標準出力の最大キャプチャーサイズを指定します。",
|
|
121
|
+
description_en="Available only in GUI mode. Specifies the maximum capture size of standard output when executing commands."),
|
|
107
122
|
]
|
|
108
123
|
return opt
|
|
109
124
|
|
|
@@ -129,6 +144,12 @@ class AuditSearch(audit_base.AuditBase):
|
|
|
129
144
|
Returns:
|
|
130
145
|
Tuple[int, Dict[str, Any], Any]: 終了コード, 結果, オブジェクト
|
|
131
146
|
"""
|
|
147
|
+
if not hasattr(args, 'format') or not args.format:
|
|
148
|
+
args.format = False
|
|
149
|
+
if not hasattr(args, 'output_json') or not args.output_json:
|
|
150
|
+
args.output_json = None
|
|
151
|
+
if not hasattr(args, 'output_json_append') or not args.output_json_append:
|
|
152
|
+
args.output_json_append = False
|
|
132
153
|
if args.svname is None:
|
|
133
154
|
msg = dict(warn=f"Please specify the --svname option.")
|
|
134
155
|
common.print_format(msg, args.format, tm, None, False, pf=pf)
|
|
@@ -210,6 +231,7 @@ class AuditSearch(audit_base.AuditBase):
|
|
|
210
231
|
ret = buf.getvalue()
|
|
211
232
|
ret = ret.replace('\r\n', '\n') if ret is not None else ''
|
|
212
233
|
|
|
234
|
+
common.print_format(ret, args.format, tm, args.output_json, args.output_json_append, pf=pf)
|
|
213
235
|
return 0, ret, cl
|
|
214
236
|
|
|
215
237
|
def is_cluster_redirect(self):
|