cmdbox 0.5.2__py3-none-any.whl → 0.5.3.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of cmdbox might be problematic. Click here for more details.
- cmdbox/app/auth/signin.py +1 -0
- cmdbox/app/feature.py +2 -0
- cmdbox/app/features/cli/audit_base.py +5 -2
- cmdbox/app/features/cli/cmdbox_audit_createdb.py +1 -1
- cmdbox/app/features/cli/cmdbox_audit_delete.py +27 -18
- cmdbox/app/features/cli/cmdbox_audit_search.py +128 -62
- cmdbox/app/features/cli/cmdbox_audit_write.py +31 -20
- cmdbox/app/features/cli/cmdbox_client_file_copy.py +1 -1
- cmdbox/app/features/cli/cmdbox_client_file_download.py +1 -1
- cmdbox/app/features/cli/cmdbox_client_file_list.py +1 -1
- cmdbox/app/features/cli/cmdbox_client_file_mkdir.py +1 -1
- cmdbox/app/features/cli/cmdbox_client_file_move.py +1 -1
- cmdbox/app/features/cli/cmdbox_client_file_remove.py +1 -1
- cmdbox/app/features/cli/cmdbox_client_file_rmdir.py +1 -1
- cmdbox/app/features/cli/cmdbox_client_file_upload.py +1 -1
- cmdbox/app/features/cli/cmdbox_client_server_info.py +1 -1
- cmdbox/app/features/cli/cmdbox_gui_start.py +1 -1
- cmdbox/app/features/cli/cmdbox_server_start.py +1 -1
- cmdbox/app/features/cli/cmdbox_server_stop.py +1 -1
- cmdbox/app/features/cli/cmdbox_web_apikey_add.py +1 -1
- cmdbox/app/features/cli/cmdbox_web_apikey_del.py +1 -1
- cmdbox/app/features/cli/cmdbox_web_group_add.py +1 -1
- cmdbox/app/features/cli/cmdbox_web_group_del.py +1 -1
- cmdbox/app/features/cli/cmdbox_web_group_edit.py +1 -1
- cmdbox/app/features/cli/cmdbox_web_group_list.py +1 -1
- cmdbox/app/features/cli/cmdbox_web_start.py +1 -1
- cmdbox/app/features/cli/cmdbox_web_user_add.py +1 -1
- cmdbox/app/features/cli/cmdbox_web_user_del.py +1 -1
- cmdbox/app/features/cli/cmdbox_web_user_edit.py +1 -1
- cmdbox/app/features/cli/cmdbox_web_user_list.py +1 -1
- cmdbox/app/features/web/cmdbox_web_audit.py +87 -0
- cmdbox/app/features/web/cmdbox_web_audit_metrics.py +72 -0
- cmdbox/app/features/web/cmdbox_web_exec_cmd.py +10 -5
- cmdbox/app/features/web/cmdbox_web_user_data.py +58 -0
- cmdbox/app/options.py +49 -19
- cmdbox/app/server.py +15 -3
- cmdbox/app/web.py +7 -1
- cmdbox/extensions/features.yml +11 -8
- cmdbox/extensions/sample_project/sample/app/features/cli/sample_server_time.py +1 -1
- cmdbox/extensions/user_list.yml +5 -0
- cmdbox/licenses/LICENSE.Jinja2.3.1.4(BSD License).txt +28 -0
- cmdbox/licenses/LICENSE.Pygments.2.18.0(BSD License).txt +25 -0
- cmdbox/licenses/LICENSE.Sphinx.8.1.3(BSD License).txt +31 -0
- cmdbox/licenses/LICENSE.anyio.4.6.2.post1(MIT License).txt +20 -0
- cmdbox/licenses/LICENSE.argcomplete.3.5.1(Apache Software License).txt +177 -0
- cmdbox/licenses/LICENSE.argcomplete.3.6.2(Apache Software License).txt +177 -0
- cmdbox/licenses/LICENSE.babel.2.16.0(BSD License).txt +27 -0
- cmdbox/licenses/LICENSE.certifi.2024.8.30(Mozilla Public License 2.0 (MPL 2.0)).txt +20 -0
- cmdbox/licenses/LICENSE.charset-normalizer.3.4.0(MIT License).txt +21 -0
- cmdbox/licenses/LICENSE.click.8.1.7(BSD License).txt +28 -0
- cmdbox/licenses/LICENSE.cryptography.43.0.3(Apache Software License; BSD License).txt +3 -0
- cmdbox/licenses/LICENSE.fastapi.0.115.5(MIT License).txt +21 -0
- cmdbox/licenses/LICENSE.gevent.25.4.1(MIT).txt +25 -0
- cmdbox/licenses/LICENSE.greenlet.3.2.0(MIT AND Python-2.0).txt +30 -0
- cmdbox/licenses/LICENSE.importlib_metadata.8.5.0(Apache Software License).txt +202 -0
- cmdbox/licenses/LICENSE.keyring.25.5.0(MIT License).txt +17 -0
- cmdbox/licenses/LICENSE.more-itertools.10.5.0(MIT License).txt +19 -0
- cmdbox/licenses/LICENSE.nh3.0.2.18(MIT).txt +1 -0
- cmdbox/licenses/LICENSE.numpy.2.1.3(BSD License).txt +950 -0
- cmdbox/licenses/LICENSE.pillow.11.0.0(CMU License (MIT-CMU)).txt +1226 -0
- cmdbox/licenses/LICENSE.pillow.11.2.1(UNKNOWN).txt +1200 -0
- cmdbox/licenses/LICENSE.pkginfo.1.10.0(MIT License).txt +21 -0
- cmdbox/licenses/LICENSE.prettytable.3.12.0(BSD License).txt +30 -0
- cmdbox/licenses/LICENSE.prompt_toolkit.3.0.51(BSD License).txt +27 -0
- cmdbox/licenses/LICENSE.pydantic.2.10.2(MIT License).txt +21 -0
- cmdbox/licenses/LICENSE.pydantic.2.11.3(MIT License).txt +21 -0
- cmdbox/licenses/LICENSE.pydantic_core.2.27.1(MIT License).txt +21 -0
- cmdbox/licenses/LICENSE.pydantic_core.2.33.1(MIT License).txt +21 -0
- cmdbox/licenses/LICENSE.python-dotenv.1.0.1(BSD License).txt +27 -0
- cmdbox/licenses/LICENSE.python-multipart.0.0.17(Apache Software License).txt +14 -0
- cmdbox/licenses/LICENSE.redis.5.2.0(MIT License).txt +21 -0
- cmdbox/licenses/LICENSE.rich.13.9.4(MIT License).txt +19 -0
- cmdbox/licenses/LICENSE.six.1.16.0(MIT License).txt +18 -0
- cmdbox/licenses/LICENSE.sphinx-intl.2.3.0(BSD License).txt +25 -0
- cmdbox/licenses/LICENSE.starlette.0.41.3(BSD License).txt +27 -0
- cmdbox/licenses/LICENSE.starlette.0.46.2(BSD License).txt +27 -0
- cmdbox/licenses/LICENSE.tomli.2.1.0(MIT License).txt +21 -0
- cmdbox/licenses/LICENSE.twine.5.1.1(Apache Software License).txt +174 -0
- cmdbox/licenses/LICENSE.typing_extensions.4.12.2(Python Software Foundation License).txt +279 -0
- cmdbox/licenses/LICENSE.typing_extensions.4.13.2(UNKNOWN).txt +279 -0
- cmdbox/licenses/LICENSE.urllib3.2.2.3(MIT License).txt +21 -0
- cmdbox/licenses/LICENSE.urllib3.2.4.0(UNKNOWN).txt +21 -0
- cmdbox/licenses/LICENSE.uvicorn.0.32.1(BSD License).txt +27 -0
- cmdbox/licenses/LICENSE.uvicorn.0.34.1(BSD License).txt +27 -0
- cmdbox/licenses/LICENSE.watchfiles.1.0.0(MIT License).txt +21 -0
- cmdbox/licenses/LICENSE.watchfiles.1.0.5(MIT License).txt +21 -0
- cmdbox/licenses/LICENSE.websockets.14.1(BSD License).txt +24 -0
- cmdbox/licenses/LICENSE.zope.interface.7.1.1(Zope Public License).txt +44 -0
- cmdbox/licenses/files.txt +12 -13
- cmdbox/version.py +2 -2
- cmdbox/web/assets/apexcharts/apexcharts.css +679 -0
- cmdbox/web/assets/apexcharts/apexcharts.min.js +38 -0
- cmdbox/web/assets/cmdbox/audit.js +404 -0
- cmdbox/web/assets/cmdbox/color_mode.css +4 -0
- cmdbox/web/assets/cmdbox/common.js +397 -24
- cmdbox/web/assets/cmdbox/filer_modal.js +1 -1
- cmdbox/web/assets/cmdbox/list_cmd.js +7 -271
- cmdbox/web/assets/cmdbox/list_pipe.js +3 -3
- cmdbox/web/assets/cmdbox/users.js +17 -17
- cmdbox/web/assets/cmdbox/view_raw.js +1 -1
- cmdbox/web/assets/cmdbox/view_result.js +11 -13
- cmdbox/web/assets/filer/filer.js +2 -2
- cmdbox/web/assets_license_list.txt +4 -1
- cmdbox/web/audit.html +293 -0
- cmdbox/web/filer.html +21 -10
- cmdbox/web/gui.html +21 -52
- cmdbox/web/result.html +9 -2
- cmdbox/web/users.html +7 -3
- {cmdbox-0.5.2.dist-info → cmdbox-0.5.3.1.dist-info}/METADATA +13 -10
- {cmdbox-0.5.2.dist-info → cmdbox-0.5.3.1.dist-info}/RECORD +114 -59
- {cmdbox-0.5.2.dist-info → cmdbox-0.5.3.1.dist-info}/LICENSE +0 -0
- {cmdbox-0.5.2.dist-info → cmdbox-0.5.3.1.dist-info}/WHEEL +0 -0
- {cmdbox-0.5.2.dist-info → cmdbox-0.5.3.1.dist-info}/entry_points.txt +0 -0
- {cmdbox-0.5.2.dist-info → cmdbox-0.5.3.1.dist-info}/top_level.txt +0 -0
cmdbox/app/auth/signin.py
CHANGED
cmdbox/app/feature.py
CHANGED
|
@@ -22,10 +22,12 @@ class Feature(object):
|
|
|
22
22
|
default_host:str = os.environ.get('REDIS_HOST', 'localhost')
|
|
23
23
|
default_port:int = int(os.environ.get('REDIS_PORT', '6379'))
|
|
24
24
|
default_pass:str = os.environ.get('REDIS_PASSWORD', 'password')
|
|
25
|
+
default_svname:str = os.environ.get('SVNAME', 'server')
|
|
25
26
|
|
|
26
27
|
def __init__(self, appcls, ver):
|
|
27
28
|
self.ver = ver
|
|
28
29
|
self.appcls = appcls
|
|
30
|
+
self.default_svname:str = ver.__appid__
|
|
29
31
|
|
|
30
32
|
def get_mode(self) -> Union[str, List[str]]:
|
|
31
33
|
"""
|
|
@@ -8,7 +8,8 @@ import sqlite3
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class AuditBase(feature.ResultEdgeFeature):
|
|
11
|
-
|
|
11
|
+
TBL_COLS = ['audit_type', 'clmsg_id', 'clmsg_date', 'clmsg_src', 'clmsg_title', 'clmsg_user', 'clmsg_body', 'clmsg_tag', 'svmsg_id', 'svmsg_date']
|
|
12
|
+
DT_FMT = ['%Y/%m/%d %H:%M', '%Y/%m/%d %H', '%Y/%m/%d', '%Y/%m', '%Y', '%m', '%u']
|
|
12
13
|
def get_option(self):
|
|
13
14
|
"""
|
|
14
15
|
この機能のオプションを返します
|
|
@@ -30,7 +31,7 @@ class AuditBase(feature.ResultEdgeFeature):
|
|
|
30
31
|
dict(opt="password", type=Options.T_STR, default=self.default_pass, required=True, multi=False, hide=True, choice=None, web="mask",
|
|
31
32
|
discription_ja=f"Redisサーバーのアクセスパスワード(任意)を指定します。省略時は `{self.default_pass}` を使用します。",
|
|
32
33
|
discription_en=f"Specify the access password of the Redis server (optional). If omitted, `{self.default_pass}` is used."),
|
|
33
|
-
dict(opt="svname", type=Options.T_STR, default=
|
|
34
|
+
dict(opt="svname", type=Options.T_STR, default=self.default_svname, required=True, multi=False, hide=True, choice=None, web="readonly",
|
|
34
35
|
discription_ja="サーバーのサービス名を指定します。省略時は `server` を使用します。",
|
|
35
36
|
discription_en="Specify the service name of the inference server. If omitted, `server` is used."),
|
|
36
37
|
|
|
@@ -97,6 +98,7 @@ class AuditBase(feature.ResultEdgeFeature):
|
|
|
97
98
|
clmsg_id TEXT,
|
|
98
99
|
clmsg_date TIMESTAMP WITH TIME ZONE,
|
|
99
100
|
clmsg_src TEXT,
|
|
101
|
+
clmsg_title TEXT,
|
|
100
102
|
clmsg_user TEXT,
|
|
101
103
|
clmsg_body JSON,
|
|
102
104
|
clmsg_tag JSON,
|
|
@@ -123,6 +125,7 @@ class AuditBase(feature.ResultEdgeFeature):
|
|
|
123
125
|
clmsg_id TEXT,
|
|
124
126
|
clmsg_date TEXT,
|
|
125
127
|
clmsg_src TEXT,
|
|
128
|
+
clmsg_title TEXT,
|
|
126
129
|
clmsg_user TEXT,
|
|
127
130
|
clmsg_body JSON,
|
|
128
131
|
clmsg_tag JSON,
|
|
@@ -70,7 +70,7 @@ class AuditCreatedb(feature.UnsupportEdgeFeature):
|
|
|
70
70
|
dict(opt="password", type=Options.T_STR, default=self.default_pass, required=True, multi=False, hide=True, choice=None, web="mask",
|
|
71
71
|
discription_ja=f"Redisサーバーのアクセスパスワード(任意)を指定します。省略時は `{self.default_pass}` を使用します。",
|
|
72
72
|
discription_en=f"Specify the access password of the Redis server (optional). If omitted, `{self.default_pass}` is used."),
|
|
73
|
-
dict(opt="svname", type=Options.T_STR, default=
|
|
73
|
+
dict(opt="svname", type=Options.T_STR, default=self.default_svname, required=True, multi=False, hide=True, choice=None, web="readonly",
|
|
74
74
|
discription_ja="サーバーのサービス名を指定します。省略時は `server` を使用します。",
|
|
75
75
|
discription_en="Specify the service name of the inference server. If omitted, `server` is used."),
|
|
76
76
|
dict(opt="retry_count", type=Options.T_INT, default=3, required=False, multi=False, hide=True, choice=None,
|
|
@@ -41,7 +41,7 @@ class AuditDelete(audit_base.AuditBase):
|
|
|
41
41
|
opt['discription_ja'] = "監査ログを削除します。"
|
|
42
42
|
opt['discription_en'] = "Delete the audit log."
|
|
43
43
|
opt['choice'] += [
|
|
44
|
-
dict(opt="delete_audit_type", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=Options.AUDITS,
|
|
44
|
+
dict(opt="delete_audit_type", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=['']+Options.AUDITS,
|
|
45
45
|
discription_ja="削除条件の監査の種類を指定します。",
|
|
46
46
|
discription_en="Specifies the type of audit for the delete condition."),
|
|
47
47
|
dict(opt="delete_clmsg_id", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=None,
|
|
@@ -56,6 +56,9 @@ class AuditDelete(audit_base.AuditBase):
|
|
|
56
56
|
dict(opt="delete_clmsg_src", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=None,
|
|
57
57
|
discription_ja="削除条件のクライアントのメッセージの発生源を指定します。LIKE検索を行います。",
|
|
58
58
|
discription_en="Specifies the source of the message for the client in the delete condition; performs a LIKE search."),
|
|
59
|
+
dict(opt="delete_clmsg_title", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=None,
|
|
60
|
+
discription_ja="削除条件のクライアントのメッセージタイトルを指定します。LIKE検索を行います。",
|
|
61
|
+
discription_en="Specifies the message title of the client for the deletion condition; a LIKE search is performed."),
|
|
59
62
|
dict(opt="delete_clmsg_user", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=None,
|
|
60
63
|
discription_ja="削除条件のクライアントのメッセージの発生させたユーザーを指定します。LIKE検索を行います。",
|
|
61
64
|
discription_en="Specifies the user who generated the message for the client in the delete condition; performs a LIKE search."),
|
|
@@ -111,6 +114,7 @@ class AuditDelete(audit_base.AuditBase):
|
|
|
111
114
|
delete_clmsg_edate = args.delete_clmsg_edate+common.get_tzoffset_str() if args.delete_clmsg_edate else None
|
|
112
115
|
delete_clmsg_edate_b64 = convert.str2b64str(delete_clmsg_edate)
|
|
113
116
|
delete_clmsg_src_b64 = convert.str2b64str(args.delete_clmsg_src)
|
|
117
|
+
delete_clmsg_title_b64 = convert.str2b64str(args.delete_clmsg_title) if args.delete_clmsg_title else None
|
|
114
118
|
delete_clmsg_user_b64 = convert.str2b64str(args.delete_clmsg_user)
|
|
115
119
|
delete_clmsg_body_str = json.dumps(args.delete_clmsg_body, default=common.default_json_enc, ensure_ascii=False) if args.delete_clmsg_body else '{}'
|
|
116
120
|
delete_clmsg_body_b64 = convert.str2b64str(delete_clmsg_body_str)
|
|
@@ -129,8 +133,8 @@ class AuditDelete(audit_base.AuditBase):
|
|
|
129
133
|
cl = client.Client(logger, redis_host=args.host, redis_port=args.port, redis_password=args.password, svname=args.svname)
|
|
130
134
|
ret = cl.redis_cli.send_cmd(self.get_svcmd(),
|
|
131
135
|
[delete_audit_type_b64, delete_clmsg_id_b64, delete_clmsg_sdate_b64, delete_clmsg_edate_b64,
|
|
132
|
-
delete_clmsg_src_b64, delete_clmsg_user_b64, delete_clmsg_body_b64,
|
|
133
|
-
delete_svmsg_id_b64, delete_svmsg_sdate_b64, delete_svmsg_edate_b64,
|
|
136
|
+
delete_clmsg_src_b64, delete_clmsg_title_b64, delete_clmsg_user_b64, delete_clmsg_body_b64,
|
|
137
|
+
delete_clmsg_tag_b64, delete_svmsg_id_b64, delete_svmsg_sdate_b64, delete_svmsg_edate_b64,
|
|
134
138
|
pg_enabled, pg_host_b64, pg_port, pg_user_b64, pg_password_b64, pg_dbname_b64],
|
|
135
139
|
retry_count=args.retry_count, retry_interval=args.retry_interval, timeout=args.timeout)
|
|
136
140
|
common.print_format(ret, args.format, tm, None, False, pf=pf)
|
|
@@ -180,21 +184,22 @@ class AuditDelete(audit_base.AuditBase):
|
|
|
180
184
|
delete_clmsg_sdate = convert.b64str2str(msg[4])
|
|
181
185
|
delete_clmsg_edate = convert.b64str2str(msg[5])
|
|
182
186
|
delete_clmsg_src = convert.b64str2str(msg[6])
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
187
|
+
delete_clmsg_title = convert.b64str2str(msg[7])
|
|
188
|
+
delete_clmsg_user = convert.b64str2str(msg[8])
|
|
189
|
+
body = json.loads(convert.b64str2str(msg[9]))
|
|
190
|
+
tags = json.loads(convert.b64str2str(msg[10]))
|
|
191
|
+
delete_svmsg_id = convert.b64str2str(msg[11])
|
|
192
|
+
delete_svmsg_sdate = convert.b64str2str(msg[12])
|
|
193
|
+
delete_svmsg_edate = convert.b64str2str(msg[13])
|
|
194
|
+
pg_enabled = True if msg[14]=='True' else False
|
|
195
|
+
pg_host = convert.b64str2str(msg[15])
|
|
196
|
+
pg_port = int(msg[16]) if msg[16]!='None' else None
|
|
197
|
+
pg_user = convert.b64str2str(msg[17])
|
|
198
|
+
pg_password = convert.b64str2str(msg[18])
|
|
199
|
+
pg_dbname = convert.b64str2str(msg[19])
|
|
195
200
|
st = self.delete(msg[1],
|
|
196
201
|
delete_audit_type, delete_clmsg_id, delete_clmsg_sdate, delete_clmsg_edate,
|
|
197
|
-
delete_clmsg_src, delete_clmsg_user, body, tags,
|
|
202
|
+
delete_clmsg_src, delete_clmsg_title, delete_clmsg_user, body, tags,
|
|
198
203
|
delete_svmsg_id, delete_svmsg_sdate, delete_svmsg_edate,
|
|
199
204
|
pg_enabled, pg_host, pg_port, pg_user, pg_password, pg_dbname,
|
|
200
205
|
data_dir, logger, redis_cli)
|
|
@@ -202,8 +207,8 @@ class AuditDelete(audit_base.AuditBase):
|
|
|
202
207
|
|
|
203
208
|
def delete(self, reskey:str,
|
|
204
209
|
delete_audit_type:str, delete_clmsg_id:str, delete_clmsg_sdate:str, delete_clmsg_edate:str,
|
|
205
|
-
delete_clmsg_src:str, delete_clmsg_user:str, delete_clmsg_body:Dict[str, Any],
|
|
206
|
-
delete_svmsg_id:str, delete_svmsg_sdate:str, delete_svmsg_edate:str,
|
|
210
|
+
delete_clmsg_src:str, delete_clmsg_title:str, delete_clmsg_user:str, delete_clmsg_body:Dict[str, Any],
|
|
211
|
+
delete_clmsg_tags:List[str], delete_svmsg_id:str, delete_svmsg_sdate:str, delete_svmsg_edate:str,
|
|
207
212
|
pg_enabled:bool, pg_host:str, pg_port:int, pg_user:str, pg_password:str, pg_dbname:str,
|
|
208
213
|
data_dir:Path, logger:logging.Logger, redis_cli:redis_client.RedisClient) -> int:
|
|
209
214
|
"""
|
|
@@ -216,6 +221,7 @@ class AuditDelete(audit_base.AuditBase):
|
|
|
216
221
|
delete_clmsg_sdate (str): クライアントメッセージ発生日時(開始)
|
|
217
222
|
delete_clmsg_edate (str): クライアントメッセージ発生日時(終了)
|
|
218
223
|
delete_clmsg_src (str): クライアントメッセージの発生源
|
|
224
|
+
delete_clmsg_title (str): クライアントメッセージのタイトル
|
|
219
225
|
delete_clmsg_user (str): クライアントメッセージの発生させたユーザー
|
|
220
226
|
delete_clmsg_body (Dict[str, Any]): クライアントメッセージの本文
|
|
221
227
|
delete_clmsg_tags (List[str]): クライアントメッセージのタグ
|
|
@@ -257,6 +263,9 @@ class AuditDelete(audit_base.AuditBase):
|
|
|
257
263
|
if delete_clmsg_src and delete_clmsg_src != 'None':
|
|
258
264
|
where.append(f'clmsg_src LIKE {"%s" if pg_enabled else "?"}')
|
|
259
265
|
params.append(delete_clmsg_src)
|
|
266
|
+
if delete_clmsg_title and delete_clmsg_title != 'None':
|
|
267
|
+
where.append(f'clmsg_title LIKE {"%s" if pg_enabled else "?"}')
|
|
268
|
+
params.append(delete_clmsg_src)
|
|
260
269
|
if delete_clmsg_user and delete_clmsg_user != 'None':
|
|
261
270
|
where.append(f'clmsg_user LIKE {"%s" if pg_enabled else "?"}')
|
|
262
271
|
params.append(delete_clmsg_user)
|
|
@@ -41,11 +41,14 @@ class AuditSearch(audit_base.AuditBase):
|
|
|
41
41
|
opt['discription_ja'] = "監査ログを検索します。"
|
|
42
42
|
opt['discription_en'] = "Search the audit log."
|
|
43
43
|
opt['choice'] += [
|
|
44
|
-
dict(opt="select", type=Options.
|
|
45
|
-
choice=['', '
|
|
44
|
+
dict(opt="select", type=Options.T_DICT, default=None, required=False, multi=True, hide=False,
|
|
45
|
+
choice=dict(key=['']+self.TBL_COLS, val=['-','count','sum','avg','min','max']),
|
|
46
46
|
discription_ja="取得項目を指定します。指定しない場合は全ての項目を取得します。",
|
|
47
47
|
discription_en="Specify the items to be retrieved. If not specified, all items are acquired."),
|
|
48
|
-
dict(opt="
|
|
48
|
+
dict(opt="select_date_format", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=['']+self.DT_FMT,
|
|
49
|
+
discription_ja="取得項目の日時のフォーマットを指定します。",
|
|
50
|
+
discription_en="Specifies the format of the date and time of the acquisition item."),
|
|
51
|
+
dict(opt="filter_audit_type", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=['']+Options.AUDITS,
|
|
49
52
|
discription_ja="フィルタ条件の監査の種類を指定します。",
|
|
50
53
|
discription_en="Specifies the type of audit for the filter condition."),
|
|
51
54
|
dict(opt="filter_clmsg_id", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=None,
|
|
@@ -60,6 +63,9 @@ class AuditSearch(audit_base.AuditBase):
|
|
|
60
63
|
dict(opt="filter_clmsg_src", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=None,
|
|
61
64
|
discription_ja="フィルタ条件のクライアントのメッセージの発生源を指定します。LIKE検索を行います。",
|
|
62
65
|
discription_en="Specifies the source of the message for the client in the filter condition; performs a LIKE search."),
|
|
66
|
+
dict(opt="filter_clmsg_title", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=None,
|
|
67
|
+
discription_ja="フィルタ条件のクライアントのメッセージタイトルを指定します。LIKE検索を行います。",
|
|
68
|
+
discription_en="Specifies the message title of the client for the filter condition; a LIKE search is performed."),
|
|
63
69
|
dict(opt="filter_clmsg_user", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=None,
|
|
64
70
|
discription_ja="フィルタ条件のクライアントのメッセージの発生させたユーザーを指定します。LIKE検索を行います。",
|
|
65
71
|
discription_en="Specifies the user who generated the message for the client in the filter condition; performs a LIKE search."),
|
|
@@ -78,7 +84,13 @@ class AuditSearch(audit_base.AuditBase):
|
|
|
78
84
|
dict(opt="filter_svmsg_edate", type=Options.T_DATETIME, default=None, required=False, multi=False, hide=False, choice=None,
|
|
79
85
|
discription_ja="フィルタ条件のサーバーのメッセージ発生日時(終了)を指定します。",
|
|
80
86
|
discription_en="Specify the date and time (end) when the message occurred for the server in the filter condition."),
|
|
81
|
-
dict(opt="
|
|
87
|
+
dict(opt="groupby", type=Options.T_STR, default=None, required=False, multi=True, hide=False, choice=['']+self.TBL_COLS,
|
|
88
|
+
discription_ja="グループ化項目を指定します。",
|
|
89
|
+
discription_en="Specify grouping items."),
|
|
90
|
+
dict(opt="groupby_date_format", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=['']+self.DT_FMT,
|
|
91
|
+
discription_ja="グループ化項目の日時のフォーマットを指定します。",
|
|
92
|
+
discription_en="Specifies the format of the date and time of the grouping item."),
|
|
93
|
+
dict(opt="sort", type=Options.T_DICT, default=None, required=False, multi=True, hide=False, choice=dict(key=['']+self.TBL_COLS, val=['', 'ASC', 'DESC']),
|
|
82
94
|
discription_ja="ソート項目を指定します。",
|
|
83
95
|
discription_en="Specify the sort item."),
|
|
84
96
|
dict(opt="offset", type=Options.T_INT, default=0, required=False, multi=False, hide=False, choice=None,
|
|
@@ -117,43 +129,51 @@ class AuditSearch(audit_base.AuditBase):
|
|
|
117
129
|
common.print_format(msg, args.format, tm, None, False, pf=pf)
|
|
118
130
|
return 1, msg, None
|
|
119
131
|
|
|
120
|
-
select_str = json.dumps(args.select, default=common.default_json_enc, ensure_ascii=False) if args
|
|
132
|
+
select_str = json.dumps(args.select, default=common.default_json_enc, ensure_ascii=False) if getattr(args, 'select', None) else '{}'
|
|
121
133
|
select_b64 = convert.str2b64str(select_str)
|
|
122
|
-
|
|
134
|
+
select_date_format_b64 = convert.str2b64str(getattr(args, 'select_date_format', None))
|
|
135
|
+
groupby_str = json.dumps(args.groupby, default=common.default_json_enc, ensure_ascii=False) if getattr(args, 'groupby', None) else '[]'
|
|
136
|
+
groupby_b64 = convert.str2b64str(groupby_str)
|
|
137
|
+
groupby_date_format_b64 = convert.str2b64str(getattr(args, 'groupby_date_format', None))
|
|
138
|
+
args.sort = args.sort if getattr(args, 'sort', {}) else {}
|
|
139
|
+
args.sort = args.sort if isinstance(args.sort, dict) else {str(args.sort): 'DESC'}
|
|
140
|
+
sort_str = json.dumps(args.sort, default=common.default_json_enc, ensure_ascii=False)
|
|
123
141
|
sort_b64 = convert.str2b64str(sort_str)
|
|
124
|
-
offset = args
|
|
125
|
-
limit = args
|
|
126
|
-
filter_audit_type_b64 = convert.str2b64str(args
|
|
127
|
-
filter_clmsg_id_b64 = convert.str2b64str(args
|
|
128
|
-
filter_clmsg_sdate = args.filter_clmsg_sdate+common.get_tzoffset_str() if args
|
|
142
|
+
offset = getattr(args, 'offset', None)
|
|
143
|
+
limit = getattr(args, 'limit', None)
|
|
144
|
+
filter_audit_type_b64 = convert.str2b64str(getattr(args, 'filter_audit_type', None))
|
|
145
|
+
filter_clmsg_id_b64 = convert.str2b64str(getattr(args, 'filter_clmsg_id', None))
|
|
146
|
+
filter_clmsg_sdate = args.filter_clmsg_sdate+common.get_tzoffset_str() if getattr(args, 'filter_clmsg_sdate', None) else None
|
|
129
147
|
filter_clmsg_sdate_b64 = convert.str2b64str(filter_clmsg_sdate)
|
|
130
|
-
filter_clmsg_edate = args.filter_clmsg_edate+common.get_tzoffset_str() if args
|
|
148
|
+
filter_clmsg_edate = args.filter_clmsg_edate+common.get_tzoffset_str() if getattr(args, 'filter_clmsg_edate', None) else None
|
|
131
149
|
filter_clmsg_edate_b64 = convert.str2b64str(filter_clmsg_edate)
|
|
132
|
-
filter_clmsg_src_b64 = convert.str2b64str(args
|
|
133
|
-
|
|
134
|
-
|
|
150
|
+
filter_clmsg_src_b64 = convert.str2b64str(getattr(args, 'filter_clmsg_src', None))
|
|
151
|
+
filter_clmsg_title_b64 = convert.str2b64str(getattr(args, 'filter_clmsg_title', None))
|
|
152
|
+
filter_clmsg_user_b64 = convert.str2b64str(getattr(args, 'filter_clmsg_user', None))
|
|
153
|
+
filter_clmsg_body_str = json.dumps(args.filter_clmsg_body, default=common.default_json_enc, ensure_ascii=False) if getattr(args, 'filter_clmsg_body', None) else '{}'
|
|
135
154
|
filter_clmsg_body_b64 = convert.str2b64str(filter_clmsg_body_str)
|
|
136
|
-
filter_clmsg_tag_str = json.dumps(args.filter_clmsg_tag, default=common.default_json_enc, ensure_ascii=False) if args
|
|
155
|
+
filter_clmsg_tag_str = json.dumps(args.filter_clmsg_tag, default=common.default_json_enc, ensure_ascii=False) if getattr(args, 'filter_clmsg_tag', None) else '[]'
|
|
137
156
|
filter_clmsg_tag_b64 = convert.str2b64str(filter_clmsg_tag_str)
|
|
138
|
-
filter_svmsg_id_b64 = convert.str2b64str(args
|
|
139
|
-
filter_svmsg_sdate_b64 = convert.str2b64str(args
|
|
140
|
-
filter_svmsg_edate_b64 = convert.str2b64str(args
|
|
141
|
-
pg_enabled = args.pg_enabled
|
|
142
|
-
pg_host_b64 = convert.str2b64str(args
|
|
143
|
-
pg_port = args.pg_port if isinstance(args.pg_port, int) else None
|
|
144
|
-
pg_user_b64 = convert.str2b64str(args
|
|
145
|
-
pg_password_b64 = convert.str2b64str(args
|
|
146
|
-
pg_dbname_b64 = convert.str2b64str(args
|
|
157
|
+
filter_svmsg_id_b64 = convert.str2b64str(getattr(args, 'filter_svmsg_id', None))
|
|
158
|
+
filter_svmsg_sdate_b64 = convert.str2b64str(getattr(args, 'filter_svmsg_sdate', None))
|
|
159
|
+
filter_svmsg_edate_b64 = convert.str2b64str(getattr(args, 'filter_svmsg_edate', None))
|
|
160
|
+
pg_enabled = args.pg_enabled if getattr(args, 'pg_enabled', False) and isinstance(args.pg_enabled, bool) else False
|
|
161
|
+
pg_host_b64 = convert.str2b64str(getattr(args, 'pg_host', None))
|
|
162
|
+
pg_port = args.pg_port if getattr(args, 'pg_port', 5432) and isinstance(args.pg_port, int) else None
|
|
163
|
+
pg_user_b64 = convert.str2b64str(getattr(args, 'pg_user', None))
|
|
164
|
+
pg_password_b64 = convert.str2b64str(getattr(args, 'pg_password', None))
|
|
165
|
+
pg_dbname_b64 = convert.str2b64str(getattr(args, 'pg_dbname', None))
|
|
147
166
|
|
|
148
167
|
cl = client.Client(logger, redis_host=args.host, redis_port=args.port, redis_password=args.password, svname=args.svname)
|
|
149
168
|
ret = cl.redis_cli.send_cmd(self.get_svcmd(),
|
|
150
|
-
[select_b64,
|
|
169
|
+
[select_b64, select_date_format_b64, groupby_b64, groupby_date_format_b64,
|
|
170
|
+
sort_b64, str(offset), str(limit),
|
|
151
171
|
filter_audit_type_b64, filter_clmsg_id_b64, filter_clmsg_sdate_b64, filter_clmsg_edate_b64,
|
|
152
|
-
filter_clmsg_src_b64, filter_clmsg_user_b64, filter_clmsg_body_b64,
|
|
153
|
-
filter_svmsg_id_b64, filter_svmsg_sdate_b64, filter_svmsg_edate_b64,
|
|
172
|
+
filter_clmsg_src_b64, filter_clmsg_title_b64, filter_clmsg_user_b64, filter_clmsg_body_b64,
|
|
173
|
+
filter_clmsg_tag_b64, filter_svmsg_id_b64, filter_svmsg_sdate_b64, filter_svmsg_edate_b64,
|
|
154
174
|
pg_enabled, pg_host_b64, pg_port, pg_user_b64, pg_password_b64, pg_dbname_b64],
|
|
155
175
|
retry_count=args.retry_count, retry_interval=args.retry_interval, timeout=args.timeout)
|
|
156
|
-
common.print_format(ret, args
|
|
176
|
+
common.print_format(ret, getattr(args, 'format', False), tm, None, False, pf=pf)
|
|
157
177
|
|
|
158
178
|
if 'success' not in ret:
|
|
159
179
|
return 1, ret, cl
|
|
@@ -196,39 +216,44 @@ class AuditSearch(audit_base.AuditBase):
|
|
|
196
216
|
int: 終了コード
|
|
197
217
|
"""
|
|
198
218
|
select = json.loads(convert.b64str2str(msg[2]))
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
219
|
+
select_date_format = convert.b64str2str(msg[3])
|
|
220
|
+
groupby = json.loads(convert.b64str2str(msg[4]))
|
|
221
|
+
groupby_date_format = convert.b64str2str(msg[5])
|
|
222
|
+
sort = json.loads(convert.b64str2str(msg[6]))
|
|
223
|
+
offset = int(msg[7]) if msg[7] else 0
|
|
224
|
+
limit = int(msg[8]) if msg[8] else 100
|
|
202
225
|
|
|
203
|
-
filter_audit_type = convert.b64str2str(msg[
|
|
204
|
-
filter_clmsg_id = convert.b64str2str(msg[
|
|
205
|
-
filter_clmsg_sdate = convert.b64str2str(msg[
|
|
206
|
-
filter_clmsg_edate = convert.b64str2str(msg[
|
|
207
|
-
filter_clmsg_src = convert.b64str2str(msg[
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
226
|
+
filter_audit_type = convert.b64str2str(msg[9])
|
|
227
|
+
filter_clmsg_id = convert.b64str2str(msg[10])
|
|
228
|
+
filter_clmsg_sdate = convert.b64str2str(msg[11])
|
|
229
|
+
filter_clmsg_edate = convert.b64str2str(msg[12])
|
|
230
|
+
filter_clmsg_src = convert.b64str2str(msg[13])
|
|
231
|
+
filter_clmsg_title = convert.b64str2str(msg[14])
|
|
232
|
+
filter_clmsg_user = convert.b64str2str(msg[15])
|
|
233
|
+
body = json.loads(convert.b64str2str(msg[16]))
|
|
234
|
+
tags = json.loads(convert.b64str2str(msg[17]))
|
|
235
|
+
filter_svmsg_id = convert.b64str2str(msg[18])
|
|
236
|
+
filter_svmsg_sdate = convert.b64str2str(msg[19])
|
|
237
|
+
filter_svmsg_edate = convert.b64str2str(msg[20])
|
|
238
|
+
pg_enabled = True if msg[21]=='True' else False
|
|
239
|
+
pg_host = convert.b64str2str(msg[22])
|
|
240
|
+
pg_port = int(msg[23]) if msg[23]!='None' else None
|
|
241
|
+
pg_user = convert.b64str2str(msg[24])
|
|
242
|
+
pg_password = convert.b64str2str(msg[25])
|
|
243
|
+
pg_dbname = convert.b64str2str(msg[26])
|
|
244
|
+
st = self.search(msg[1], select, select_date_format, groupby, groupby_date_format,
|
|
245
|
+
sort, offset, limit,
|
|
221
246
|
filter_audit_type, filter_clmsg_id, filter_clmsg_sdate, filter_clmsg_edate,
|
|
222
|
-
filter_clmsg_src, filter_clmsg_user, body, tags,
|
|
247
|
+
filter_clmsg_src, filter_clmsg_title, filter_clmsg_user, body, tags,
|
|
223
248
|
filter_svmsg_id, filter_svmsg_sdate, filter_svmsg_edate,
|
|
224
249
|
pg_enabled, pg_host, pg_port, pg_user, pg_password, pg_dbname,
|
|
225
250
|
data_dir, logger, redis_cli)
|
|
226
251
|
return st
|
|
227
252
|
|
|
228
|
-
def search(self, reskey:str, select:List[str], sort:Dict[str, str], offset:int, limit:int,
|
|
253
|
+
def search(self, reskey:str, select:Dict[str, str], select_date_format:str, groupby:List[str], groupby_date_format:str, sort:Dict[str, str], offset:int, limit:int,
|
|
229
254
|
filter_audit_type:str, filter_clmsg_id:str, filter_clmsg_sdate:str, filter_clmsg_edate:str,
|
|
230
|
-
filter_clmsg_src:str, filter_clmsg_user:str, filter_clmsg_body:Dict[str, Any],
|
|
231
|
-
filter_svmsg_id:str, filter_svmsg_sdate:str, filter_svmsg_edate:str,
|
|
255
|
+
filter_clmsg_src:str, filter_clmsg_title:str, filter_clmsg_user:str, filter_clmsg_body:Dict[str, Any],
|
|
256
|
+
filter_clmsg_tags:List[str], filter_svmsg_id:str, filter_svmsg_sdate:str, filter_svmsg_edate:str,
|
|
232
257
|
pg_enabled:bool, pg_host:str, pg_port:int, pg_user:str, pg_password:str, pg_dbname:str,
|
|
233
258
|
data_dir:Path, logger:logging.Logger, redis_cli:redis_client.RedisClient) -> int:
|
|
234
259
|
"""
|
|
@@ -236,7 +261,10 @@ class AuditSearch(audit_base.AuditBase):
|
|
|
236
261
|
|
|
237
262
|
Args:
|
|
238
263
|
reskey (str): レスポンスキー
|
|
239
|
-
select (
|
|
264
|
+
select (Dict[str, str]): 取得項目
|
|
265
|
+
select_date_format (str): 取得項目の日時フォーマット
|
|
266
|
+
groupby (List[str]): グループ化項目
|
|
267
|
+
groupby_date_format (str): グループ化項目の日時フォーマット
|
|
240
268
|
sort (Dict[str, str]): ソート条件
|
|
241
269
|
offset (int): 取得する行の開始位置
|
|
242
270
|
limit (int): 取得する行数
|
|
@@ -245,6 +273,7 @@ class AuditSearch(audit_base.AuditBase):
|
|
|
245
273
|
filter_clmsg_sdate (str): クライアントメッセージ発生日時(開始)
|
|
246
274
|
filter_clmsg_edate (str): クライアントメッセージ発生日時(終了)
|
|
247
275
|
filter_clmsg_src (str): クライアントメッセージの発生源
|
|
276
|
+
filter_clmsg_title (str): クライアントメッセージのタイトル
|
|
248
277
|
filter_clmsg_user (str): クライアントメッセージの発生させたユーザー
|
|
249
278
|
filter_clmsg_body (Dict[str, Any]): クライアントメッセージの本文
|
|
250
279
|
filter_clmsg_tags (List[str]): クライアントメッセージのタグ
|
|
@@ -264,6 +293,31 @@ class AuditSearch(audit_base.AuditBase):
|
|
|
264
293
|
Returns:
|
|
265
294
|
int: レスポンスコード
|
|
266
295
|
"""
|
|
296
|
+
def _date_format(pg_enabled, col, date_format):
|
|
297
|
+
if col not in ['clmsg_date', 'svmsg_date']:
|
|
298
|
+
return col
|
|
299
|
+
if pg_enabled:
|
|
300
|
+
if date_format == '%u':
|
|
301
|
+
return f"to_char({col}, 'D')"
|
|
302
|
+
elif date_format == '%m':
|
|
303
|
+
return f"to_char({col}, 'MM')"
|
|
304
|
+
elif date_format == '%Y':
|
|
305
|
+
return f"to_char({col}, 'YYYY')"
|
|
306
|
+
elif date_format == '%Y/%m':
|
|
307
|
+
return f"to_char({col}, 'YYYY/MM')"
|
|
308
|
+
elif date_format == '%Y/%m/%d':
|
|
309
|
+
return f"to_char({col}, 'YYYY/MM/DD')"
|
|
310
|
+
elif date_format == '%Y/%m/%d %H':
|
|
311
|
+
return f"to_char({col}, 'YYYY/MM/DD HH24')"
|
|
312
|
+
elif date_format == '%Y/%m/%d %H:%M':
|
|
313
|
+
return f"to_char({col}, 'YYYY/MM/DD HH24:MI')"
|
|
314
|
+
else:
|
|
315
|
+
return col
|
|
316
|
+
else:
|
|
317
|
+
if date_format is not None and date_format != '':
|
|
318
|
+
return f"strftime('{date_format}', {col})"
|
|
319
|
+
else:
|
|
320
|
+
return col
|
|
267
321
|
try:
|
|
268
322
|
with self.initdb(data_dir, logger, pg_enabled, pg_host, pg_port, pg_user, pg_password, pg_dbname) as conn:
|
|
269
323
|
def dict_factory(cursor, row):
|
|
@@ -271,17 +325,24 @@ class AuditSearch(audit_base.AuditBase):
|
|
|
271
325
|
conn.row_factory = dict_row if pg_enabled else dict_factory
|
|
272
326
|
cursor = conn.cursor()
|
|
273
327
|
try:
|
|
274
|
-
select =
|
|
328
|
+
select = {k:v for k,v in select.items() if k != ''} if select else None
|
|
329
|
+
select = select if select and len(select)>0 else {k:'-' for k in self.TBL_COLS}
|
|
275
330
|
if pg_enabled:
|
|
276
331
|
toz = common.get_tzoffset_str()
|
|
277
|
-
sel =
|
|
278
|
-
for
|
|
279
|
-
if
|
|
280
|
-
sel
|
|
332
|
+
sel = {}
|
|
333
|
+
for k,v in select.items():
|
|
334
|
+
if k in ['clmsg_date', 'svmsg_date']:
|
|
335
|
+
sel[f"{k} AT TIME ZONE INTERVAL '{toz}' as {k}"] = v
|
|
281
336
|
else:
|
|
282
|
-
sel
|
|
337
|
+
sel[k] = v
|
|
283
338
|
select = sel
|
|
284
|
-
sql =
|
|
339
|
+
sql = []
|
|
340
|
+
for k,v in select.items():
|
|
341
|
+
if v in ['count', 'sum', 'avg', 'min', 'max']:
|
|
342
|
+
sql.append(f'{v}({_date_format(pg_enabled, k, select_date_format)}) AS {k}')
|
|
343
|
+
else:
|
|
344
|
+
sql.append(f'{_date_format(pg_enabled, k, select_date_format)} AS {k}')
|
|
345
|
+
sql = f"SELECT {','.join(sql)} FROM audit"
|
|
285
346
|
params = []
|
|
286
347
|
where = []
|
|
287
348
|
if filter_audit_type and filter_audit_type != 'None':
|
|
@@ -299,6 +360,9 @@ class AuditSearch(audit_base.AuditBase):
|
|
|
299
360
|
if filter_clmsg_src and filter_clmsg_src != 'None':
|
|
300
361
|
where.append(f'clmsg_src LIKE {"%s" if pg_enabled else "?"}')
|
|
301
362
|
params.append(filter_clmsg_src)
|
|
363
|
+
if filter_clmsg_title and filter_clmsg_title != 'None':
|
|
364
|
+
where.append(f'clmsg_title LIKE {"%s" if pg_enabled else "?"}')
|
|
365
|
+
params.append(filter_clmsg_title)
|
|
302
366
|
if filter_clmsg_user and filter_clmsg_user != 'None':
|
|
303
367
|
where.append(f'clmsg_user LIKE {"%s" if pg_enabled else "?"}')
|
|
304
368
|
params.append(filter_clmsg_user)
|
|
@@ -322,6 +386,8 @@ class AuditSearch(audit_base.AuditBase):
|
|
|
322
386
|
where.append(f'svmsg_date<={"%s" if pg_enabled else "?"}')
|
|
323
387
|
params.append(filter_svmsg_edate)
|
|
324
388
|
sql += ' WHERE ' + ' AND '.join(where) if len(where)>0 else ''
|
|
389
|
+
if groupby and len(groupby) > 0:
|
|
390
|
+
sql += ' GROUP BY ' + ', '.join([f"{_date_format(pg_enabled, g, groupby_date_format)}" for g in groupby])
|
|
325
391
|
if sort and len(sort) > 0:
|
|
326
392
|
sql += ' ORDER BY ' + ', '.join([f"{k} {v}" for k, v in sort.items()])
|
|
327
393
|
else:
|
|
@@ -53,6 +53,9 @@ class AuditWrite(audit_base.AuditBase):
|
|
|
53
53
|
dict(opt="clmsg_src", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=None,
|
|
54
54
|
discription_ja="クライアントのメッセージの発生源を指定します。通常 `cmdbox.app.feature.Feature` を継承したクラス名を指定します。",
|
|
55
55
|
discription_en="Specifies the source of client messages. Usually specifies the name of a class that extends `cmdbox.app.feature.Feature` ."),
|
|
56
|
+
dict(opt="clmsg_title", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=None,
|
|
57
|
+
discription_ja="クライアントのメッセージタイトルを指定します。通常コマンドタイトルを指定します。",
|
|
58
|
+
discription_en="Specifies the client message title. Usually specifies the command title."),
|
|
56
59
|
dict(opt="clmsg_user", type=Options.T_STR, default=None, required=False, multi=False, hide=False, choice=None,
|
|
57
60
|
discription_ja="クライアントのメッセージを発生させたユーザーを指定します。",
|
|
58
61
|
discription_en="SpecSpecifies the user who generated the client message."),
|
|
@@ -107,6 +110,7 @@ class AuditWrite(audit_base.AuditBase):
|
|
|
107
110
|
clmsg_id_b64 = convert.str2b64str(args.clmsg_id)
|
|
108
111
|
clmsg_date_b64 = convert.str2b64str(args.clmsg_date)
|
|
109
112
|
clmsg_src_b64 = convert.str2b64str(args.clmsg_src) if args.clmsg_src is not None else ''
|
|
113
|
+
clmsg_title_b64 = convert.str2b64str(args.clmsg_title) if args.clmsg_title is not None else ''
|
|
110
114
|
clmsg_user_b64 = convert.str2b64str(args.clmsg_user) if args.clmsg_user is not None else ''
|
|
111
115
|
clmsg_body_str = json.dumps(args.clmsg_body, default=common.default_json_enc, ensure_ascii=False) if args.clmsg_body is not None else '{}'
|
|
112
116
|
clmsg_body_b64 = convert.str2b64str(clmsg_body_str)
|
|
@@ -119,9 +123,11 @@ class AuditWrite(audit_base.AuditBase):
|
|
|
119
123
|
pg_password_b64 = convert.str2b64str(args.pg_password)
|
|
120
124
|
pg_dbname_b64 = convert.str2b64str(args.pg_dbname)
|
|
121
125
|
|
|
126
|
+
if logger.level == logging.DEBUG:
|
|
127
|
+
logger.debug(f"audit write args: {args}")
|
|
122
128
|
cl = client.Client(logger, redis_host=args.host, redis_port=args.port, redis_password=args.password, svname=args.svname)
|
|
123
129
|
cl.redis_cli.send_cmd(self.get_svcmd(),
|
|
124
|
-
[audit_type_b64, clmsg_id_b64, clmsg_date_b64, clmsg_src_b64, clmsg_user_b64, clmsg_body_b64, clmsg_tag_b64,
|
|
130
|
+
[audit_type_b64, clmsg_id_b64, clmsg_date_b64, clmsg_src_b64, clmsg_title_b64, clmsg_user_b64, clmsg_body_b64, clmsg_tag_b64,
|
|
125
131
|
pg_enabled, pg_host_b64, pg_port, pg_user_b64, pg_password_b64, pg_dbname_b64,
|
|
126
132
|
args.retention_period_days],
|
|
127
133
|
retry_count=args.retry_count, retry_interval=args.retry_interval, timeout=args.timeout, nowait=True)
|
|
@@ -153,28 +159,32 @@ class AuditWrite(audit_base.AuditBase):
|
|
|
153
159
|
Returns:
|
|
154
160
|
int: 終了コード
|
|
155
161
|
"""
|
|
162
|
+
if logger.level == logging.DEBUG:
|
|
163
|
+
logger.debug(f"audit write svrun msg: {msg}")
|
|
156
164
|
audit_type = convert.b64str2str(msg[2])
|
|
157
165
|
clmsg_id = convert.b64str2str(msg[3])
|
|
158
166
|
clmsg_date = convert.b64str2str(msg[4])
|
|
159
167
|
clmsg_src = convert.b64str2str(msg[5])
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
168
|
+
clmsg_title = convert.b64str2str(msg[6])
|
|
169
|
+
clmsg_user = convert.b64str2str(msg[7])
|
|
170
|
+
clmsg_body = convert.b64str2str(msg[8])
|
|
171
|
+
clmsg_tags = convert.b64str2str(msg[9])
|
|
172
|
+
pg_enabled = True if msg[10]=='True' else False
|
|
173
|
+
pg_host = convert.b64str2str(msg[11])
|
|
174
|
+
pg_port = int(msg[12]) if msg[12]!='None' else None
|
|
175
|
+
pg_user = convert.b64str2str(msg[13])
|
|
176
|
+
pg_password = convert.b64str2str(msg[14])
|
|
177
|
+
pg_dbname = convert.b64str2str(msg[15])
|
|
178
|
+
retention_period_days = int(msg[16]) if msg[16] != 'None' else None
|
|
170
179
|
svmsg_id = str(uuid.uuid4())
|
|
171
|
-
st = self.write(msg[1], audit_type, clmsg_id, clmsg_date, clmsg_src, clmsg_user, clmsg_body, clmsg_tags, svmsg_id,
|
|
180
|
+
st = self.write(msg[1], audit_type, clmsg_id, clmsg_date, clmsg_src, clmsg_title, clmsg_user, clmsg_body, clmsg_tags, svmsg_id,
|
|
172
181
|
pg_enabled, pg_host, pg_port, pg_user, pg_password, pg_dbname,
|
|
173
182
|
retention_period_days,
|
|
174
183
|
data_dir, logger, redis_cli)
|
|
175
184
|
return st
|
|
176
185
|
|
|
177
|
-
def write(self, reskey:str, audit_type:str, clmsg_id:str, clmsg_date:str, clmsg_src:str,
|
|
186
|
+
def write(self, reskey:str, audit_type:str, clmsg_id:str, clmsg_date:str, clmsg_src:str, clmsg_title:str,
|
|
187
|
+
clmsg_user:str, clmsg_body:str, clmsg_tags:str, svmsg_id:str,
|
|
178
188
|
pg_enabled:bool, pg_host:str, pg_port:int, pg_user:str, pg_password:str, pg_dbname:str,
|
|
179
189
|
retention_period_days:int,
|
|
180
190
|
data_dir:Path, logger:logging.Logger, redis_cli:redis_client.RedisClient) -> int:
|
|
@@ -187,6 +197,7 @@ class AuditWrite(audit_base.AuditBase):
|
|
|
187
197
|
clmsg_id (str): クライアントメッセージID
|
|
188
198
|
clmsg_date (str): クライアントメッセージ発生日時
|
|
189
199
|
clmsg_src (str): クライアントメッセージの発生源
|
|
200
|
+
clmsg_title (str): クライアントメッセージのタイトル
|
|
190
201
|
clmsg_user (str): クライアントメッセージの発生させたユーザー
|
|
191
202
|
clmsg_body (str): クライアントメッセージの本文
|
|
192
203
|
clmsg_tags (str): クライアントメッセージのタグ
|
|
@@ -209,22 +220,22 @@ class AuditWrite(audit_base.AuditBase):
|
|
|
209
220
|
with self.initdb(data_dir, logger, pg_enabled, pg_host, pg_port, pg_user, pg_password, pg_dbname) as conn:
|
|
210
221
|
cursor = conn.cursor()
|
|
211
222
|
try:
|
|
212
|
-
|
|
223
|
+
svmsg_date = datetime.now().strftime('%Y-%m-%d %H:%M:%S') + common.get_tzoffset_str()
|
|
213
224
|
if not pg_enabled:
|
|
214
225
|
cursor.execute('''
|
|
215
|
-
INSERT INTO audit (audit_type, clmsg_id, clmsg_date, clmsg_src, clmsg_user, clmsg_body, clmsg_tag,
|
|
226
|
+
INSERT INTO audit (audit_type, clmsg_id, clmsg_date, clmsg_src, clmsg_title, clmsg_user, clmsg_body, clmsg_tag,
|
|
216
227
|
svmsg_id, svmsg_date)
|
|
217
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?,
|
|
218
|
-
''', (audit_type, clmsg_id, clmsg_date, clmsg_src, clmsg_user, clmsg_body, clmsg_tags, svmsg_id))
|
|
228
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
229
|
+
''', (audit_type, clmsg_id, clmsg_date, clmsg_src, clmsg_title, clmsg_user, clmsg_body, clmsg_tags, svmsg_id, svmsg_date))
|
|
219
230
|
if retention_period_days is not None and retention_period_days > 0:
|
|
220
231
|
cursor.execute('DELETE FROM audit WHERE svmsg_date < datetime(CURRENT_TIMESTAMP, ?)',
|
|
221
232
|
(f'-{retention_period_days} days',))
|
|
222
233
|
else:
|
|
223
234
|
cursor.execute('''
|
|
224
|
-
INSERT INTO audit (audit_type, clmsg_id, clmsg_date, clmsg_src, clmsg_user, clmsg_body, clmsg_tag,
|
|
235
|
+
INSERT INTO audit (audit_type, clmsg_id, clmsg_date, clmsg_src, clmsg_title, clmsg_user, clmsg_body, clmsg_tag,
|
|
225
236
|
svmsg_id, svmsg_date)
|
|
226
|
-
VALUES (%s, %s, %s, %s, %s, %s, %s, %s,
|
|
227
|
-
''', (audit_type, clmsg_id, clmsg_date, clmsg_src, clmsg_user, clmsg_body, clmsg_tags, svmsg_id))
|
|
237
|
+
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
|
238
|
+
''', (audit_type, clmsg_id, clmsg_date, clmsg_src, clmsg_title, clmsg_user, clmsg_body, clmsg_tags, svmsg_id, svmsg_date))
|
|
228
239
|
if retention_period_days is not None and retention_period_days > 0:
|
|
229
240
|
cursor.execute("DELETE FROM audit WHERE svmsg_date < CURRENT_TIMESTAMP + %s ",
|
|
230
241
|
(f'-{retention_period_days} day',))
|
|
@@ -47,7 +47,7 @@ class ClientFileCopy(feature.UnsupportEdgeFeature):
|
|
|
47
47
|
dict(opt="password", type=Options.T_STR, default=self.default_pass, required=True, multi=False, hide=True, choice=None, web="mask",
|
|
48
48
|
discription_ja="Redisサーバーのアクセスパスワード(任意)を指定します。省略時は `password` を使用します。",
|
|
49
49
|
discription_en="Specify the access password of the Redis server (optional). If omitted, `password` is used."),
|
|
50
|
-
dict(opt="svname", type=Options.T_STR, default=
|
|
50
|
+
dict(opt="svname", type=Options.T_STR, default=self.default_svname, required=True, multi=False, hide=True, choice=None, web="readonly",
|
|
51
51
|
discription_ja="サーバーのサービス名を指定します。省略時は `server` を使用します。",
|
|
52
52
|
discription_en="Specify the service name of the inference server. If omitted, `server` is used."),
|
|
53
53
|
dict(opt="from_path", type=Options.T_STR, default=None, required=True, multi=False, hide=False, choice=None,
|
|
@@ -47,7 +47,7 @@ class ClientFileDownload(feature.OneshotEdgeFeature):
|
|
|
47
47
|
dict(opt="password", type=Options.T_STR, default=self.default_pass, required=True, multi=False, hide=True, choice=None, web="mask",
|
|
48
48
|
discription_ja="Redisサーバーのアクセスパスワード(任意)を指定します。省略時は `password` を使用します。",
|
|
49
49
|
discription_en="Specify the access password of the Redis server (optional). If omitted, `password` is used."),
|
|
50
|
-
dict(opt="svname", type=Options.T_STR, default=
|
|
50
|
+
dict(opt="svname", type=Options.T_STR, default=self.default_svname, required=True, multi=False, hide=True, choice=None, web="readonly",
|
|
51
51
|
discription_ja="サーバーのサービス名を指定します。省略時は `server` を使用します。",
|
|
52
52
|
discription_en="Specify the service name of the inference server. If omitted, `server` is used."),
|
|
53
53
|
dict(opt="svpath", type=Options.T_STR, default="/", required=True, multi=False, hide=False, choice=None,
|