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.

Files changed (114) hide show
  1. cmdbox/app/auth/signin.py +1 -0
  2. cmdbox/app/feature.py +2 -0
  3. cmdbox/app/features/cli/audit_base.py +5 -2
  4. cmdbox/app/features/cli/cmdbox_audit_createdb.py +1 -1
  5. cmdbox/app/features/cli/cmdbox_audit_delete.py +27 -18
  6. cmdbox/app/features/cli/cmdbox_audit_search.py +128 -62
  7. cmdbox/app/features/cli/cmdbox_audit_write.py +31 -20
  8. cmdbox/app/features/cli/cmdbox_client_file_copy.py +1 -1
  9. cmdbox/app/features/cli/cmdbox_client_file_download.py +1 -1
  10. cmdbox/app/features/cli/cmdbox_client_file_list.py +1 -1
  11. cmdbox/app/features/cli/cmdbox_client_file_mkdir.py +1 -1
  12. cmdbox/app/features/cli/cmdbox_client_file_move.py +1 -1
  13. cmdbox/app/features/cli/cmdbox_client_file_remove.py +1 -1
  14. cmdbox/app/features/cli/cmdbox_client_file_rmdir.py +1 -1
  15. cmdbox/app/features/cli/cmdbox_client_file_upload.py +1 -1
  16. cmdbox/app/features/cli/cmdbox_client_server_info.py +1 -1
  17. cmdbox/app/features/cli/cmdbox_gui_start.py +1 -1
  18. cmdbox/app/features/cli/cmdbox_server_start.py +1 -1
  19. cmdbox/app/features/cli/cmdbox_server_stop.py +1 -1
  20. cmdbox/app/features/cli/cmdbox_web_apikey_add.py +1 -1
  21. cmdbox/app/features/cli/cmdbox_web_apikey_del.py +1 -1
  22. cmdbox/app/features/cli/cmdbox_web_group_add.py +1 -1
  23. cmdbox/app/features/cli/cmdbox_web_group_del.py +1 -1
  24. cmdbox/app/features/cli/cmdbox_web_group_edit.py +1 -1
  25. cmdbox/app/features/cli/cmdbox_web_group_list.py +1 -1
  26. cmdbox/app/features/cli/cmdbox_web_start.py +1 -1
  27. cmdbox/app/features/cli/cmdbox_web_user_add.py +1 -1
  28. cmdbox/app/features/cli/cmdbox_web_user_del.py +1 -1
  29. cmdbox/app/features/cli/cmdbox_web_user_edit.py +1 -1
  30. cmdbox/app/features/cli/cmdbox_web_user_list.py +1 -1
  31. cmdbox/app/features/web/cmdbox_web_audit.py +87 -0
  32. cmdbox/app/features/web/cmdbox_web_audit_metrics.py +72 -0
  33. cmdbox/app/features/web/cmdbox_web_exec_cmd.py +10 -5
  34. cmdbox/app/features/web/cmdbox_web_user_data.py +58 -0
  35. cmdbox/app/options.py +49 -19
  36. cmdbox/app/server.py +15 -3
  37. cmdbox/app/web.py +7 -1
  38. cmdbox/extensions/features.yml +11 -8
  39. cmdbox/extensions/sample_project/sample/app/features/cli/sample_server_time.py +1 -1
  40. cmdbox/extensions/user_list.yml +5 -0
  41. cmdbox/licenses/LICENSE.Jinja2.3.1.4(BSD License).txt +28 -0
  42. cmdbox/licenses/LICENSE.Pygments.2.18.0(BSD License).txt +25 -0
  43. cmdbox/licenses/LICENSE.Sphinx.8.1.3(BSD License).txt +31 -0
  44. cmdbox/licenses/LICENSE.anyio.4.6.2.post1(MIT License).txt +20 -0
  45. cmdbox/licenses/LICENSE.argcomplete.3.5.1(Apache Software License).txt +177 -0
  46. cmdbox/licenses/LICENSE.argcomplete.3.6.2(Apache Software License).txt +177 -0
  47. cmdbox/licenses/LICENSE.babel.2.16.0(BSD License).txt +27 -0
  48. cmdbox/licenses/LICENSE.certifi.2024.8.30(Mozilla Public License 2.0 (MPL 2.0)).txt +20 -0
  49. cmdbox/licenses/LICENSE.charset-normalizer.3.4.0(MIT License).txt +21 -0
  50. cmdbox/licenses/LICENSE.click.8.1.7(BSD License).txt +28 -0
  51. cmdbox/licenses/LICENSE.cryptography.43.0.3(Apache Software License; BSD License).txt +3 -0
  52. cmdbox/licenses/LICENSE.fastapi.0.115.5(MIT License).txt +21 -0
  53. cmdbox/licenses/LICENSE.gevent.25.4.1(MIT).txt +25 -0
  54. cmdbox/licenses/LICENSE.greenlet.3.2.0(MIT AND Python-2.0).txt +30 -0
  55. cmdbox/licenses/LICENSE.importlib_metadata.8.5.0(Apache Software License).txt +202 -0
  56. cmdbox/licenses/LICENSE.keyring.25.5.0(MIT License).txt +17 -0
  57. cmdbox/licenses/LICENSE.more-itertools.10.5.0(MIT License).txt +19 -0
  58. cmdbox/licenses/LICENSE.nh3.0.2.18(MIT).txt +1 -0
  59. cmdbox/licenses/LICENSE.numpy.2.1.3(BSD License).txt +950 -0
  60. cmdbox/licenses/LICENSE.pillow.11.0.0(CMU License (MIT-CMU)).txt +1226 -0
  61. cmdbox/licenses/LICENSE.pillow.11.2.1(UNKNOWN).txt +1200 -0
  62. cmdbox/licenses/LICENSE.pkginfo.1.10.0(MIT License).txt +21 -0
  63. cmdbox/licenses/LICENSE.prettytable.3.12.0(BSD License).txt +30 -0
  64. cmdbox/licenses/LICENSE.prompt_toolkit.3.0.51(BSD License).txt +27 -0
  65. cmdbox/licenses/LICENSE.pydantic.2.10.2(MIT License).txt +21 -0
  66. cmdbox/licenses/LICENSE.pydantic.2.11.3(MIT License).txt +21 -0
  67. cmdbox/licenses/LICENSE.pydantic_core.2.27.1(MIT License).txt +21 -0
  68. cmdbox/licenses/LICENSE.pydantic_core.2.33.1(MIT License).txt +21 -0
  69. cmdbox/licenses/LICENSE.python-dotenv.1.0.1(BSD License).txt +27 -0
  70. cmdbox/licenses/LICENSE.python-multipart.0.0.17(Apache Software License).txt +14 -0
  71. cmdbox/licenses/LICENSE.redis.5.2.0(MIT License).txt +21 -0
  72. cmdbox/licenses/LICENSE.rich.13.9.4(MIT License).txt +19 -0
  73. cmdbox/licenses/LICENSE.six.1.16.0(MIT License).txt +18 -0
  74. cmdbox/licenses/LICENSE.sphinx-intl.2.3.0(BSD License).txt +25 -0
  75. cmdbox/licenses/LICENSE.starlette.0.41.3(BSD License).txt +27 -0
  76. cmdbox/licenses/LICENSE.starlette.0.46.2(BSD License).txt +27 -0
  77. cmdbox/licenses/LICENSE.tomli.2.1.0(MIT License).txt +21 -0
  78. cmdbox/licenses/LICENSE.twine.5.1.1(Apache Software License).txt +174 -0
  79. cmdbox/licenses/LICENSE.typing_extensions.4.12.2(Python Software Foundation License).txt +279 -0
  80. cmdbox/licenses/LICENSE.typing_extensions.4.13.2(UNKNOWN).txt +279 -0
  81. cmdbox/licenses/LICENSE.urllib3.2.2.3(MIT License).txt +21 -0
  82. cmdbox/licenses/LICENSE.urllib3.2.4.0(UNKNOWN).txt +21 -0
  83. cmdbox/licenses/LICENSE.uvicorn.0.32.1(BSD License).txt +27 -0
  84. cmdbox/licenses/LICENSE.uvicorn.0.34.1(BSD License).txt +27 -0
  85. cmdbox/licenses/LICENSE.watchfiles.1.0.0(MIT License).txt +21 -0
  86. cmdbox/licenses/LICENSE.watchfiles.1.0.5(MIT License).txt +21 -0
  87. cmdbox/licenses/LICENSE.websockets.14.1(BSD License).txt +24 -0
  88. cmdbox/licenses/LICENSE.zope.interface.7.1.1(Zope Public License).txt +44 -0
  89. cmdbox/licenses/files.txt +12 -13
  90. cmdbox/version.py +2 -2
  91. cmdbox/web/assets/apexcharts/apexcharts.css +679 -0
  92. cmdbox/web/assets/apexcharts/apexcharts.min.js +38 -0
  93. cmdbox/web/assets/cmdbox/audit.js +404 -0
  94. cmdbox/web/assets/cmdbox/color_mode.css +4 -0
  95. cmdbox/web/assets/cmdbox/common.js +397 -24
  96. cmdbox/web/assets/cmdbox/filer_modal.js +1 -1
  97. cmdbox/web/assets/cmdbox/list_cmd.js +7 -271
  98. cmdbox/web/assets/cmdbox/list_pipe.js +3 -3
  99. cmdbox/web/assets/cmdbox/users.js +17 -17
  100. cmdbox/web/assets/cmdbox/view_raw.js +1 -1
  101. cmdbox/web/assets/cmdbox/view_result.js +11 -13
  102. cmdbox/web/assets/filer/filer.js +2 -2
  103. cmdbox/web/assets_license_list.txt +4 -1
  104. cmdbox/web/audit.html +293 -0
  105. cmdbox/web/filer.html +21 -10
  106. cmdbox/web/gui.html +21 -52
  107. cmdbox/web/result.html +9 -2
  108. cmdbox/web/users.html +7 -3
  109. {cmdbox-0.5.2.dist-info → cmdbox-0.5.3.1.dist-info}/METADATA +13 -10
  110. {cmdbox-0.5.2.dist-info → cmdbox-0.5.3.1.dist-info}/RECORD +114 -59
  111. {cmdbox-0.5.2.dist-info → cmdbox-0.5.3.1.dist-info}/LICENSE +0 -0
  112. {cmdbox-0.5.2.dist-info → cmdbox-0.5.3.1.dist-info}/WHEEL +0 -0
  113. {cmdbox-0.5.2.dist-info → cmdbox-0.5.3.1.dist-info}/entry_points.txt +0 -0
  114. {cmdbox-0.5.2.dist-info → cmdbox-0.5.3.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,404 @@
1
+ const audit = {};
2
+ // 監査ログ一覧
3
+ audit.rawlog = async () => {
4
+ const modal = $('#search_modal');
5
+ const rawlog_area = $('#rawlog_area').html('');
6
+ const [title, opt] = cmdbox.get_param(modal);
7
+ cmdbox.show_loading();
8
+ const data = await audit.query(opt);
9
+ if (!data) {
10
+ cmdbox.hide_loading();
11
+ modal.modal('hide');
12
+ return;
13
+ }
14
+ audit.tracelog(JSON.parse(JSON.stringify(data)));
15
+ data.forEach((row) => {
16
+ if (row['clmsg_id']) {
17
+ row['clmsg_id'] = `<a href="#" data-id="${row['clmsg_id']}" onclick="audit.clmsg_id_click_func(this);">${row['clmsg_id']}</a>`;
18
+ }
19
+ });
20
+ render_result_func(rawlog_area, data, 110);
21
+ await audit.metrics();
22
+ modal.modal('hide');
23
+ cmdbox.hide_loading();
24
+ };
25
+ // 監査ログのclmsg_idをクリックしたときの処理
26
+ audit.clmsg_id_click_func = (elem) => {
27
+ const clmsg_id = $(elem).attr('data-id');
28
+ const area = $(`#trace_area`);
29
+ const trace_tab = document.querySelector('#main_tabs #trace-tab')
30
+ bootstrap.Tab.getOrCreateInstance(trace_tab).show()
31
+ area.animate({scrollTop: $(`#${clmsg_id}`).offset().top - area.offset().top + area.scrollTop()}, 500);
32
+ };
33
+ // 監査ログのトレース
34
+ audit.tracelog = async (data) => {
35
+ const rawlog_area = $('#trace_area').html('');
36
+ const table = $('<table class="table table-bordered table-hover table-sm"></table>').appendTo(rawlog_area);
37
+ const table_head = $('<thead><tr></tr></thead>').appendTo(table).find('tr');
38
+ const table_body = $('<tbody></tbody>').appendTo(table);
39
+ table_head.append($('<th class="th" scope="col">clmsg_user</th>'));
40
+ table_head.append($('<th class="th" scope="col">trace log</th>'));
41
+ const row_dict = {};
42
+ for (const row of data) {
43
+ const clmsg_id = row['clmsg_id'];
44
+ if (clmsg_id == null || clmsg_id == '') continue;
45
+ if (!row_dict[clmsg_id]) {
46
+ row_dict[clmsg_id] = {clmsg_id:clmsg_id, clmsg_user:row['clmsg_user'], clmsg_date:row['clmsg_date'], row:[]};
47
+ }
48
+ if (!row_dict[clmsg_id]['clmsg_date']) {
49
+ row_dict[clmsg_id]['clmsg_date'] = row['clmsg_date'];
50
+ }
51
+ if (!row_dict[clmsg_id]['clmsg_user']) {
52
+ row_dict[clmsg_id]['clmsg_user'] = row['clmsg_user'];
53
+ }
54
+ delete row['clmsg_id'];
55
+ delete row['clmsg_user'];
56
+ row_dict[clmsg_id]['row'].push(row);
57
+ }
58
+ Object.values(row_dict).sort((a,b) => {
59
+ a['clmsg_date'] > b['clmsg_date'] ? 1 : -1;
60
+ }).forEach((attr, i) => {
61
+ const tr = $('<tr></tr>').appendTo(table_body);
62
+ $(`<td>${attr['clmsg_user']}</td>`).appendTo(tr);
63
+ const div = $(`<td><span id="${attr['clmsg_id']}">clmsg_id : ${attr['clmsg_id']}</span><div/></td>`).appendTo(tr).find('div');
64
+ render_result_func(div, attr['row'], 100);
65
+ });
66
+ };
67
+ // 検索
68
+ audit.query = async (opt) => {
69
+ const res = await fetch(`audit/rawlog`,
70
+ {method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(opt)});
71
+ if (res.status != 200) {
72
+ cmdbox.message(`${res.status}: ${res.statusText}`);
73
+ return;
74
+ }
75
+ try {
76
+ const content = JSON.parse(await res.text());
77
+ if (!content['success']) {
78
+ cmdbox.message(content);
79
+ return;
80
+ }
81
+ return content['success']['data'];
82
+ } catch (e) {
83
+ cmdbox.message({'error': e.message});
84
+ return;
85
+ }
86
+ };
87
+ // メトリクスの表示
88
+ audit.metrics = async () => {
89
+ const metrics_area = $('#metrics_area');
90
+ metrics_area.html('');
91
+ audit.list_audit_metrics().then((res) => {
92
+ if (!res['success']) return;
93
+ res['success'].forEach(async (row) => {
94
+ const modal = $('#search_modal');
95
+ const [_, opt] = cmdbox.get_param(modal);
96
+ opt['select'] = row['vertical'];
97
+ opt['select'][row['horizontal']] = '-';
98
+ opt['select_date_format'] = row['horizontal_date_format'];
99
+ opt['groupby'] = [row['horizontal']];
100
+ opt['groupby_date_format'] = row['horizontal_date_format'];
101
+ opt['sort'][row['horizontal']] = 'DESC';
102
+ Object.keys(row).forEach((key) => {
103
+ if (!key.startsWith('filter_')) return;
104
+ opt[key] = row[key];
105
+ });
106
+ let data = await audit.query(opt);
107
+ if (!data) data = [];
108
+ data = data.reverse();
109
+ // 時系列グラフの追加
110
+ const card = $(`<div class="col-${row['col_size']} p-1"><div class="card card-hover"><div class="card-body"></div></div></div>`).appendTo(metrics_area);
111
+ const card_body = card.find('.card-body');
112
+ const title = $(`<div class="d-flex">`
113
+ + `<button id="edit_metrics" type="button" class="btn p-0 me-3">`
114
+ + `<svg width="32" height="32" fill="currentColor" class="bi bi-plus-lg"><use href="#svg_edit_btn"></use></svg></button>`
115
+ + `<h5 class="d-inline-block m-0">${row['title']}</h5></div>`).appendTo(card_body);
116
+ const edit_btn = card_body.find('#edit_metrics');
117
+ const graph = $(`<div class="chart"></div>`).appendTo(card_body);
118
+ const series = [];
119
+ for (const vk of Object.keys(row['vertical'])) {
120
+ if (vk == row['horizontal']) continue;
121
+ const sel = {name:vk, data:[...data.map(d => d[vk])]};
122
+ series.push(sel);
123
+ }
124
+ const categories = [...data.map(d => d[row['horizontal']])];
125
+ const chart_opt = {
126
+ chart: {
127
+ type: row['chart_type'],
128
+ stacked: row['chart_stacked'],
129
+ },
130
+ stroke: {
131
+ show: true,
132
+ curve: row['stroke_curve'],
133
+ width: row['stroke_width'],
134
+ },
135
+ series: series,
136
+ tooltip: {
137
+ theme: false
138
+ },
139
+ xaxis: {
140
+ categories: categories
141
+ }
142
+ }
143
+ const chart = new ApexCharts(graph.get(0), chart_opt);
144
+ chart.render();
145
+ graph.find('.apexcharts-toolbar').on('click', (e) => {
146
+ e.stopPropagation();
147
+ e.preventDefault();
148
+ });
149
+ edit_btn.off('click').on('click', (e) => {
150
+ const title = row['title'];
151
+ audit.metrics_modal_func(title);
152
+ e.stopPropagation();
153
+ });
154
+ });
155
+ });
156
+ };
157
+ // メトリクスのモーダルダイアログを表示
158
+ audit.metrics_modal_func = (title) => {
159
+ const modal = $('#metrics_modal');
160
+ modal.find('.modal-title').text(title ? `Edit Metrics : ${title}` : 'New Metrics');
161
+ const row_content = modal.find('.row_content');
162
+ row_content.empty();
163
+ audit.load_audit_metrics(title?title:null).then(async (res) => {
164
+ const axis = ['','audit_type', 'clmsg_id', 'clmsg_date', 'clmsg_src', 'clmsg_title', 'clmsg_user', 'clmsg_body', 'clmsg_tag', 'svmsg_id', 'svmsg_date'];
165
+ const chart_type = ['','line', 'area', 'bar'];
166
+ const stroke_curve = ['','smooth', 'straight', 'stepline'];
167
+ const data = res['success']?res['success']:{};
168
+ const rows = [
169
+ {opt:'title', type:'str', default:title?title:'', required:true, multi:false, hide:false, choice:null},
170
+ {opt:'chart_type', type:'str', default:data['chart_type']?data['chart_type']:'line', required:true, multi:false, hide:false, choice:chart_type,
171
+ discription_en: 'Specifies the type of graph.',
172
+ discription_ja: 'グラフのタイプを指定します。',
173
+ choice_show: {
174
+ 'line':['stroke_curve','stroke_width'],
175
+ 'area':['stroke_curve','chart_stacked','stroke_width'],
176
+ 'bar':['chart_stacked']}},
177
+ {opt:'stroke_curve', type:'str', default:data['stroke_curve']?data['stroke_curve']:'straight', required:false, multi:false, hide:false, choice:stroke_curve,
178
+ discription_en: 'Specifies the type of line.',
179
+ discription_ja: '線のタイプを指定します。'},
180
+ {opt:'chart_stacked', type:'bool', default:data['chart_stacked']?data['chart_stacked']:false, required:false, multi:false, hide:false, choice:[false, true],
181
+ discription_en: 'Specifies whether to stack the graph.',
182
+ discription_ja: 'グラフを積み上げるかどうかを指定します。'},
183
+ {opt:'stroke_width', type:'int', default:data['stroke_width']?data['stroke_width']:2, required:false, multi:false, hide:false, choice:[...Array(5).keys()].map(i => i+1),
184
+ discription_en: 'Specifies the width of the line.',
185
+ discription_ja: '線の幅を指定します。'},
186
+ {opt:'col_size', type:'int', default:data['col_size']?data['col_size']:6, required:true, multi:false, hide:false, choice:[...Array(12).keys()].map(i => i+1),
187
+ discription_en: 'Specifies the size of the graph display width.',
188
+ discription_ja: 'グラフの表示幅のサイズを指定します。'},
189
+ {opt:'horizontal', type:'str', default:data['horizontal']?data['horizontal']:'clmsg_date', required:true, multi:false, hide:false, choice:axis,
190
+ discription_en: 'Specify the items to be displayed on the horizontal axis.',
191
+ discription_ja: '横軸の表示項目を指定します。',
192
+ choice_show: {
193
+ 'clmsg_date':['horizontal_date_format'],
194
+ 'svmsg_date':['horizontal_date_format']}},
195
+ {opt:'horizontal_date_format', type:'str', default:data['horizontal_date_format']?data['horizontal_date_format']:'%Y/%m/%d',
196
+ required:false, multi:false, hide:false, choice:['','%Y/%m/%d %H:%M', '%Y/%m/%d %H', '%Y/%m/%d', '%Y/%m', '%Y', '%m', '%w'],
197
+ discription_en: 'Specify the date format to be displayed on the horizontal axis.',
198
+ discription_ja: '横軸の表示日付フォーマットを指定します。'},
199
+ ];
200
+ data['vertical'] = data['vertical'] || {'clmsg_id':'count'};
201
+ Object.keys(data['vertical']).forEach((key) => {
202
+ const def = {};
203
+ def[key] = data['vertical'][key];
204
+ rows.push({opt:'vertical', type:'dict', default:def, required:true, multi:true, hide:false,
205
+ choice:{key:axis, val:['-','count','sum','avg','min','max']}});
206
+ });
207
+ const base_rows = await cmdbox.get_cmd_choices('audit', 'search');
208
+ base_rows.filter(row => row['opt'].startsWith('filter')).forEach((row) => {
209
+ row['hide'] = true;
210
+ if (data[row['opt']]) {
211
+ const val = data[row['opt']];
212
+ if (Array.isArray(val) && val.length > 0) {
213
+ val.forEach((v) => {
214
+ if (!v || v=='') return;
215
+ r = {...row};
216
+ r['default'] = v;
217
+ rows.push(r);
218
+ });
219
+ }
220
+ else if (typeof val=='object') {
221
+ Object.keys(val).forEach((k) => {
222
+ if (!k || k=='') return;
223
+ if (!val[k] || val[k]=='') return;
224
+ r = {...row};
225
+ r['default'][k] = val[k];
226
+ rows.push(r);
227
+ });
228
+ }
229
+ else {
230
+ row['default'] = val;
231
+ }
232
+ }
233
+ rows.push(row);
234
+ });
235
+ rows.forEach((row, i) => cmdbox.add_form_func(i, modal, row_content, row, null, 12, 6));
236
+ title && modal.find('[name="title"]').prop('readonly', true);
237
+ modal.find('.choice_show').change();
238
+ });
239
+ // 保存実行
240
+ modal.find('#metrics_save').off('click').on('click', async () => {
241
+ const [title, opt] = cmdbox.get_param(modal);
242
+ if (!title || title == '') {
243
+ cmdbox.message({'warn': 'Title is required'});
244
+ return;
245
+ }
246
+ if (!opt['chart_type'] || opt['chart_type'] == '') {
247
+ cmdbox.message({'warn': 'chart_type is required'});
248
+ return;
249
+ }
250
+ if (!opt['col_size'] || opt['col_size'] == '') {
251
+ cmdbox.message({'warn': 'col_size is required'});
252
+ return;
253
+ }
254
+ if (!opt['horizontal'] || opt['horizontal'] == '') {
255
+ cmdbox.message({'warn': 'horizontal is required'});
256
+ return;
257
+ }
258
+ if (!opt['vertical'] || opt['vertical'] == '') {
259
+ cmdbox.message({'warn': 'vertical is required'});
260
+ return;
261
+ }
262
+ if (!window.confirm('Do you want to save?')) return;
263
+ await audit.save_audit_metrics(title, opt);
264
+ await audit.metrics();
265
+ modal.modal('hide');
266
+ });
267
+ // 削除実行
268
+ modal.find('#metrics_del').off('click').on('click', async () => {
269
+ if (!window.confirm('Do you want to delete?')) return;
270
+ await audit.del_audit_metrics(title);
271
+ await audit.metrics();
272
+ modal.modal('hide');
273
+ });
274
+ if (!title) modal.find('#metrics_del').hide();
275
+ else modal.find('#metrics_del').show();
276
+ modal.modal('show');
277
+ };
278
+ // 監査ログのフィルターフォームの初期化
279
+ audit.init_form = async () => {
280
+ // フォームの初期化
281
+ const modal = $('#search_modal');
282
+ const row_content = modal.find('.row_content');
283
+ const res = await fetch('audit/mode_cmd', {method: 'GET'});
284
+ if (res.status != 200) cmdbox.message(`${res.status}: ${res.statusText}`);
285
+ const msg = await res.json();
286
+ if (!msg['success']) {
287
+ cmdbox.message(msg);
288
+ return;
289
+ }
290
+ const args = msg['success'];
291
+ const py_get_cmd_choices = await cmdbox.get_cmd_choices(args['mode'], args['cmd']);
292
+ row_content.html('');
293
+ // 検索ボタンを表示
294
+ $('#do_search').off('click').on('click', async (e) => {
295
+ await audit.rawlog();
296
+ const condition = {};
297
+ row_content.find(':input').each((i, el) => {
298
+ const elem = $(el);
299
+ const id = elem.attr('id');
300
+ const val = elem.val();
301
+ if (!id || id == '') return;
302
+ if (!val || val == '') return;
303
+ condition[id] = {'name': elem.attr('name'), 'value': val,
304
+ 'param_data_index': elem.attr('param_data_index'),
305
+ 'param_data_type': elem.attr('param_data_type'),
306
+ 'param_data_multi': elem.attr('param_data_multi')};
307
+ });
308
+ cmdbox.save_user_data('audit', 'condition', JSON.stringify(condition));
309
+ });
310
+ // 主なフィルター条件のフォームを表示
311
+ const nml_conditions = ['filter_audit_type', 'filter_clmsg_id', 'filter_clmsg_src', 'filter_clmsg_title', 'filter_clmsg_title', 'filter_clmsg_user',
312
+ 'filter_clmsg_tag', 'filter_svmsg_sdate', 'filter_svmsg_edate']
313
+ py_get_cmd_choices.filter(row => nml_conditions.includes(row.opt)).forEach((row, i) => cmdbox.add_form_func(i, modal, row_content, row, null, 12, 6));
314
+ const adv_link = $('<div class="text-center card-hover col-12 mb-3"><a href="#">[ advanced options ]</a></div>').appendTo(row_content);
315
+ adv_link.off('click').on('click', (e) => {row_content.find('.adv').toggle();});
316
+ // 高度なフィルター条件のフォームを表示
317
+ const adv_conditions = ['filter_clmsg_body', 'filter_clmsg_sdate', 'filter_svmsg_edate',
318
+ 'filter_svmsg_id', 'sort', 'offset', 'limit'];
319
+ const adv_row_content = $('<div class="row_content"></div>').appendTo(row_content);
320
+ py_get_cmd_choices.filter(row => adv_conditions.includes(row.opt)).forEach((row, i) => cmdbox.add_form_func(i, modal, adv_row_content, row, null, 12, 12));
321
+ adv_row_content.children().each((i, elem) => {$(elem).addClass('adv').hide();}).appendTo(row_content);
322
+ adv_row_content.remove();
323
+ let condition = await cmdbox.load_user_data('audit', 'condition');
324
+ condition = condition && condition['success'] ? JSON.parse(condition['success']) : {};
325
+ Object.keys(condition).forEach((id) => {
326
+ const data = condition[id];
327
+ if (!data) return;
328
+ let elem = row_content.find(`#${id}`);
329
+ if (elem.length > 0) {
330
+ elem.val(data['value']);
331
+ return;
332
+ }
333
+ const last_elem = row_content.find(`[name="${data['name']}"]:last`);
334
+ const add_btn = last_elem.next('.add_buton');
335
+ if (add_btn.length <= 0) return;
336
+ add_btn.click();
337
+ elem = row_content.find(`[name="${data['name']}"]:last`);
338
+ elem.val(val);
339
+ });
340
+ row_content.find(':input').each((i, elem) => {
341
+ const id = $(elem).attr('id');
342
+ if (!id || id == '') return;
343
+ const val = localStorage.getItem(id);
344
+ if (!val || val == '') return
345
+ $(elem).val(val);
346
+ });
347
+ $('#search_rawlog').off('click').on('click', (e) => {
348
+ modal.modal('show');
349
+ });
350
+ $('#search_trace').off('click').on('click', (e) => {
351
+ modal.modal('show');
352
+ });
353
+ };
354
+ audit.list_audit_metrics = async () => {
355
+ const formData = new FormData();
356
+ const res = await fetch('audit/metrics/list', {method: 'POST', body: formData});
357
+ if (res.status != 200) cmdbox.message({'error':`${res.status}: ${res.statusText}`});
358
+ return await res.json();
359
+ }
360
+ audit.load_audit_metrics = async (title) => {
361
+ const formData = new FormData();
362
+ formData.append('title', title);
363
+ const res = await fetch('audit/metrics/load', {method: 'POST', body: formData});
364
+ if (res.status != 200) cmdbox.message({'error':`${res.status}: ${res.statusText}`});
365
+ return await res.json();
366
+ }
367
+ audit.save_audit_metrics = async (title, opt) => {
368
+ const formData = new FormData();
369
+ formData.append('title', title);
370
+ formData.append('opt', JSON.stringify(opt));
371
+ const res = await fetch('audit/metrics/save', {method: 'POST', body: formData});
372
+ if (res.status != 200) cmdbox.message({'error':`${res.status}: ${res.statusText}`});
373
+ return await res.json();
374
+ };
375
+ audit.del_audit_metrics = async (title) => {
376
+ const formData = new FormData();
377
+ formData.append('title', title);
378
+ const res = await fetch('audit/metrics/delete', {method: 'POST', body: formData});
379
+ if (res.status != 200) cmdbox.message({'error':`${res.status}: ${res.statusText}`});
380
+ return await res.json();
381
+ }
382
+ $(() => {
383
+ // カラーモード対応
384
+ cmdbox.change_color_mode();
385
+ // アイコンを表示
386
+ cmdbox.set_logoicon('.navbar-brand');
387
+ // copyright表示
388
+ cmdbox.copyright();
389
+ // バージョン情報モーダル初期化
390
+ cmdbox.init_version_modal();
391
+ // モーダルボタン初期化
392
+ cmdbox.init_modal_button();
393
+ // コマンド実行用のオプション取得
394
+ cmdbox.get_server_opt(true, $('.filer_form')).then(async (opt) => {
395
+ // フィルターフォーム初期化
396
+ await audit.init_form();
397
+ // 監査ログ一覧表示
398
+ await audit.rawlog();
399
+ // メトリクス表示
400
+ $('#add_metrics').off('click').on('click', (e) => {
401
+ audit.metrics_modal_func();
402
+ });
403
+ });
404
+ });
@@ -1,3 +1,7 @@
1
+ .th {
2
+ background-color: var(--bs-tertiary-bg) !important;
3
+ word-break:normal;
4
+ }
1
5
  /* ライトモード (基本) - 必要に応じて調整 */
2
6
  [data-bs-theme="light"] {
3
7
  --bs-body-bg: #fff;