web_sandbox_console 0.5.0 → 0.6.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5ad0510372891ece0bb60db8479bf3c59ca712aa010ecda57a321f4d3e92cb0d
4
- data.tar.gz: 878b2f4526a0ee3332c04b48107749115ed7168d5eb043e3c8329848478c78ee
3
+ metadata.gz: '01385f4ee72595defa82f0d4c7141d28281c09e1b34c946177bda7c592043273'
4
+ data.tar.gz: 44a4c34af0ed2b38e018491bcb7711d2b20545b7e6a136851bab564efb341025
5
5
  SHA512:
6
- metadata.gz: a31a83d626eda75091f52acea4c15e1902799c59218f4bf50eec018a999c26068cc5fd5bd9ad2c334658657e4f688f723f2aee0797c5fab9bb4330adae6b32c2
7
- data.tar.gz: 07aecf999a6abb0181d739f6069e8a9bece7a8a6367251991171039c06cd7f2ce14d7a0d803fc23c5584ec25ffb6d4187d3e154af46faed7904cf4a16fed7e76
6
+ metadata.gz: a9118a01bb98153510454b4626f04c732c19a094db040f451d72e475294f5a99aef7b4590de7d1f7241e3410b853108d9cc79d55bb365e715c197051807681fd
7
+ data.tar.gz: 93a338b267b25082cbe0815a3ca695df3702197698ad293beb8b016b4769724d36e0cadcaaf47dc561f9dc6203c3dc75bcd9953b10722de443196aecc2dfd700
data/README.md CHANGED
@@ -3,6 +3,8 @@
3
3
 
4
4
  这个控制台提供一个类似沙盒的安全环境,这里做的所有数据操作,都会回滚(不会真正写入数据库);你可以配置 ip 白名单、基本认证,来增加访问安全性;另外在这个沙盒中,内置禁止了linux命令的执行,所以不用担心,ruby越界去做了linux的相关事情,当然还禁止了文件的新建、删除、目录的新建、删除等一系列方法;如果你需要更强的限制,你还可以去配置你想禁止使用的哪些方法等等,具体看配置文件。
5
5
 
6
+ 此gem基本涵盖了日常使用的常用功能,包括:数据查询、数据修改、数据导出、日志查看、日志时间或内容过滤、文件查看,日志下载等。
7
+
6
8
  ## Usage
7
9
  使用过程相当简单,和一般的gem,安装后你不用特殊去配置任何东西,就可以正常使用。所有的配置选项都是可选的。
8
10
 
@@ -19,22 +21,21 @@ $ bundle
19
21
  ```
20
22
 
21
23
  此时,如果是在本地,你访问 `http://localhost:3000/web_sandbox_console` 就能看到web控制台了,下面这个样子。
24
+
22
25
  PS:代码输入框支持代码高亮,你可以像在代码编辑器一样自由编写代码
23
26
  ![Snip20200710_1.png](https://i.loli.net/2020/07/10/XqolSYAIJGKa5xg.png)
24
27
 
25
28
  ## 配置
26
- ```
27
- 在bundle后,就可以使用一些基础的功能了;
28
- 如果你不满足基础的功能、或者需要更高的安全性,很有必要仔细了解配置选项,总之还是很推荐对项目进行适当配置;
29
- 关于配置的详细介绍,在生成的文件中也有详细的说明,参照说明配置即可;
30
- ```
29
+ 在bundle后,就可以直接使用了,为了安全起见,建议进一步配置基本认证;如果需要数据修改权限,还需要配置公钥;关于配置选项的具体说明,请参阅配置文件注释。
31
30
 
32
31
  在 rails 项目路径下,执行:
33
32
  ```bash
34
33
  $ rails g web_sandbox_console
35
34
  ```
36
35
 
37
- 这会在项目路径下,创建两个配置文件
36
+ 会在项目路径下,创建两个配置文件
37
+ 一、config/initializers/web_sandbox_console.rb文件
38
+
38
39
  ```ruby
39
40
  # config/initializers/web_sandbox_console.rb
40
41
 
@@ -79,7 +80,9 @@ WebSandboxConsole.setup do |config|
79
80
  end
80
81
  ```
81
82
 
82
- 主要用于配置 http_basic_auth 和 public_key,如需使用基本授权、升级授权,参照example文件创建yml文件即可
83
+ 二、config/web_sandbox_console.yml.example 文件
84
+
85
+ 主要用于配置基本授权、升级权限需要用到的公钥,参照example文件创建yml文件即可
83
86
  ```ruby
84
87
  # config/web_sandbox_console.yml.example
85
88
 
@@ -91,29 +94,44 @@ web_sandbox_console:
91
94
 
92
95
  ```
93
96
 
97
+ 关于配置的补充说明:
98
+
99
+ > 建议不要轻易配置黑名单方法,因为禁用某些方法后,可能会导致许多意想不到问题;有可能不小心禁用到rails框架或gem使用的一些方法;
100
+ >
101
+ > 对于此gem内置禁用的方法,gem内部是做了一些兼容性的处理的,因此不会有什么问题
102
+
94
103
  ## 深入了解
104
+
95
105
  主要包含三大功能块:代码执行、文件查看、日志下载,下面分别介绍
96
106
 
97
107
  ### 代码执行
98
108
  1. 提交和异步执行
99
109
 
100
- > 提交后代码会立即执行;如果点击异步执行,则代码会在后台异步执行,这对于需要执行非常耗时的代码,强烈建议异步执行;
110
+ > 提交后代码会立即执行,及时返回执行结果
111
+ >
112
+ > 异步执行,代码会在后台异步执行,这对于执行时间非常长的代码,强烈建议异步执行;比如批量更新数据、导出数据等
101
113
 
102
114
  2. 升级权限
103
- ![Snip20200703_1.png](https://i.loli.net/2020/07/03/26zf5WOBFqmaiHC.png)
115
+ ![Snip20200703_1.png](https://i.loli.net/2020/07/03/26zf5WOBFqmaiHC.png)
116
+
117
+ > 大多数时候,可能用到的操作就是查数据,但是,有时你可能需要修改某条数据,那么功能就不够用了
118
+ >
119
+ > 为了支持数据的修改,同时保证安全性,加入了升级权限这个功能
120
+ >
121
+ > 整个过程相当简单,在yaml文件中配置好公钥 -> 获取token -> 本地加密后回传 -> 授权成功
122
+ >
123
+ > 授权成功后,所有数据操作将不再执行回滚(PS:未升级授权时,做的所有数据操作都会执行回滚,不会真正写入数据库)
104
124
 
105
- ```
106
- 通常你能做的操作就是,查查数据等,数据的所有操作都不会写入到数据库,这样很安全;但是每当你需要修改数据时,还是需要让运维处理;为了满足可以数据写入、和安全性的要求;开发了升级权限这个功能。
107
125
 
108
- 升级权限你需要在配置文件中配置公钥,自己保存私钥;整个过程采用非对称加密的方式,进行授权,还是比较安全的。
109
- 升级授权成功后,代码执行将不再回滚,会直接写入数据库。
110
- ```
111
126
 
112
127
  升级权限流程如下:
113
- > - `config/web_sandbox_console.yml`中配置公钥
114
- > - 进入授权页面,点击获取令牌 `web_sandbox_console/auth_page`
115
- > - 用私钥对令牌加密,然后用base64加密
116
- > - 将加密的打印结果(注意是puts 文本),输入加密密文框,提交
128
+ > 1. config/web_sandbox_console.yml`中配置公钥
129
+ >
130
+ > 2. 进入授权页面,点击获取令牌
131
+ >
132
+ > 3. 用私钥对令牌加密,然后用base64加密
133
+ >
134
+ > 4. 将加密的打印结果(注意是puts 文本),输入加密密文框,提交
117
135
 
118
136
  ```ruby
119
137
  # 本地生成 加密密文代码
@@ -131,35 +149,46 @@ puts encode_text
131
149
  ![Snip20200703_2.png](https://i.loli.net/2020/07/03/zFMjpRSX8fCDQ2i.png)
132
150
  1. 目录和文件
133
151
 
134
- > 你可以查看一个目录下有哪些文件夹或文件,你也可以直接查看文件的内容,默认返回一个文件的前100行
152
+ > 你可以查看一个目录下有哪些文件夹或文件,你也可以直接查看文件的内容,默认返回一个文件的前100行
135
153
 
136
154
  2. 指定行数
137
- ```
138
- 你可以根据文件总行数,指定查看文件的开始行数、结束行数。
139
- PS: a. 在过滤文件(过滤内容/过滤时间)的时候,此时指定行数将被忽略
140
- b. 对于大文件(默认超过10M),处于性能考虑,此时指定行数也会被忽略
141
- ```
142
155
 
143
- 3. 过滤
144
- ```
145
- 需要特别说明的是,过滤时间是针对日志文件写的,因此如果是非日志文件,将不会有任何效果。
146
- 建议:出于性能考虑,过滤时候尽量缩小时间范围
147
- ```
156
+ > 你可以根据文件总行数,指定查看文件的开始行数、结束行数。
157
+ > PS: a. 在过滤文件(过滤内容/过滤时间)的时候,此时指定行数将被忽略
158
+ > b. 对于大文件(默认超过10M),处于性能考虑,此时指定行数也会被忽略
159
+ 3. 过滤内容
160
+
161
+ > 当过滤内容时,仅返回匹配的行,匹配行的上下文是不会返回的
162
+ >
163
+ > 因此如果需要查看匹配行的上下文,需要再次根据匹配行的时间做过滤(PS:此时需清掉内容输入框)
148
164
 
165
+ 4. 过滤时间
166
+
167
+ > 可以只填开始时间,不填结束时间,此时返回该时间的日志
149
168
  4. 权限
150
169
 
151
- > 默认情况,只能查看日志文件或目录,当然你也可以去配置做调整。
170
+ > 默认情况,只能查看日志文件或目录,当然你也可以去配置做调整。
171
+
172
+ 5. 其它
173
+
174
+ > 1. 可以根据返回内容的提示,了解当前查询(文件总行数、当前按照某种方式返回)
175
+ > 2. 查询的逻辑如下:
176
+ > 3. 如果只指定文件名,且文件比较小(小文件),默认返回文件前100行
177
+ > 4. 如果只指定文件名,文件比较大(大文件),默认返回文件最后1000行
178
+ > 5. 如果指定了文件名、过滤内容,则忽略行数查找,直接依据过滤内容匹配行,如果匹配到的行数超过1000行,则返回匹配出的前1000行
179
+ > 6. 如果指定了文件名、过滤内容、过滤时间,则先按照时间匹配出内容,然后根据内容进行匹配
152
180
 
153
181
  ### 日志下载
182
+
154
183
  ![Snip20200703_3.png](https://i.loli.net/2020/07/03/csW5OfEhPVeSbJz.png)
155
184
  你可以直接输入文件名(需要带后缀)下载日志
156
185
 
157
186
  ### 关于数据导出
158
- 在gem 中你可用`CSV.open`的方式导出数据,出于安全考虑,这里open方法是复写之后的,内部没有调用`File.open`方法;
187
+
188
+ 可以先在代码执行页面,用`CSV.open`方式生成 csv文件,然后在日志下载中去下载创建的csv文件
159
189
 
160
190
  有一下几点需注意:
161
- > 1. 你写入你任何路径,最终都只会在log目录下创建csv文件
162
- > 2. 文件名以你路径中(/分隔)的最后一个名称为准
191
+ > 1. 在`CSV.open`中写的任何路径,都不会生效,最终只会在log目录下创建csv文件;比如`CSV.open('#{Rails.root}/hu/bar.txt') 会在log目录下,生成bar.csv文件
163
192
  > 3. csv 文件下载后,会自动删除掉,因此只能下载一次
164
193
 
165
194
 
@@ -167,4 +196,4 @@ PS: a. 在过滤文件(过滤内容/过滤时间)的时候,此时指定行
167
196
  Contribution directions go here.
168
197
 
169
198
  ## License
170
- The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
199
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -186,6 +186,8 @@ img {
186
186
  position: relative;
187
187
  margin-left: 200px;
188
188
  /*padding-top: 70px;*/
189
+ margin-right: 30px;
190
+ min-height: 800px;
189
191
  z-index: 100
190
192
  }
191
193
 
@@ -215,4 +217,15 @@ img {
215
217
 
216
218
  .mr-auto {
217
219
  margin-right: auto!important;
218
- }
220
+ }
221
+
222
+
223
+ pre {
224
+ white-space: pre-wrap; /* Since CSS 2.1 */
225
+ white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
226
+ white-space: -pre-wrap; /* Opera 4-6 */
227
+ white-space: -o-pre-wrap; /* Opera 7 */
228
+ word-wrap: break-word; /* Internet Explorer 5.5+ */
229
+ line-height: 18px;
230
+ margin-top: 0px;
231
+ }
@@ -20,4 +20,32 @@
20
20
  font-size: 15px;
21
21
  color: white;
22
22
  cursor: pointer;
23
+ }
24
+
25
+ /* 执行代码页面样式 */
26
+ .wrapper-console {
27
+ position: relative;
28
+ top: 8px;
29
+ width: 100%;
30
+ height: 300px;
31
+ }
32
+
33
+ .left {
34
+ height: 100%;
35
+ /* 为了不占用绝对定位的宽度 这里计算下宽度*/
36
+ width: calc(100% - 200px);
37
+ }
38
+
39
+ .right {
40
+ position: absolute;
41
+ width: 180px;
42
+ top: 0;
43
+ bottom: 0;
44
+ right: 0;
45
+ padding-left: 15px;
46
+ }
47
+
48
+ /* 选中后code背景色*/
49
+ .CodeMirror-selected {
50
+ background: #20aee3 !important;
23
51
  }
@@ -22,11 +22,8 @@ module WebSandboxConsole
22
22
 
23
23
  # 查看文件
24
24
  def do_view_file
25
- results = ViewFile.new(params).view
26
- @lines = results[:lines]
27
- @total_line_num = results[:total_line_num]
28
- @touch_grep_protect = results[:touch_grep_protect]
29
- @content_is_trimed = results[:content_is_trimed]
25
+ @result_hash = ViewFile.new(params).view
26
+ @tip_hash = WebSandboxConsole::ViewFile::PageTips
30
27
  end
31
28
 
32
29
  # 下载文件页面
@@ -68,7 +68,7 @@
68
68
  </div>
69
69
  </aside>
70
70
 
71
- <div class="page-wrapper" style="min-height: 800px;">
71
+ <div class="page-wrapper">
72
72
  <div class="container-fluid">
73
73
  <%= yield %>
74
74
  </div>
@@ -1,16 +1,14 @@
1
1
  $(".output-content").empty();
2
- <% line_num_show = @total_line_num ? "原始文件总行数:#{@total_line_num}" : "" %>
3
2
 
3
+ <% line_num_show = @result_hash[:total_line_num] ? "原始文件总行数:#{@result_hash[:total_line_num]}" : "" %>
4
4
  $(".output-content").append("<p>============ <%= Time.current %> 查找结果如下 <%= line_num_show %> ===============</p>");
5
5
 
6
- <% if @touch_grep_protect %>
7
- $(".output-content").append("<p>PS: 由于过滤执行时间太长,已触发过滤保护,返回内容为最后1000行</p>");
6
+ <% @tip_hash.each do |key,value| %>
7
+ <% if @result_hash[key.to_sym] %>
8
+ $(".output-content").append("<p>PS: <%= value %></p>");
9
+ <% end %>
8
10
  <% end %>
9
11
 
10
- <% if @content_is_trimed %>
11
- $(".output-content").append("<p>PS: 当前返回内容太多,仅展示满足条件的1000行</p>");
12
- <% end %>
13
-
14
- <% @lines.each do |result| %>
12
+ <% @result_hash[:lines].each do |result| %>
15
13
  $(".output-content").append('<pre><%= escape_javascript result %></pre>');
16
14
  <% end %>
@@ -1,30 +1,5 @@
1
1
  <h3>执行代码</h3>
2
2
 
3
- <style type="text/css">
4
- .wrapper-console {
5
- position: relative;
6
- top: 8px;
7
- width: 100%;
8
- height: 300px;
9
- }
10
-
11
- .left {
12
- height: 100%;
13
- /* 为了不占用绝对定位的宽度 这里计算下宽度*/
14
- width: calc(100% - 200px);
15
- }
16
-
17
- .right {
18
- position: absolute;
19
- width: 180px;
20
- top: 0;
21
- bottom: 0;
22
- right: 0;
23
- padding-left: 15px;
24
- }
25
- </style>
26
-
27
-
28
3
  <div class="wrapper-console">
29
4
  <%= form_tag(web_sandbox_console.eval_code_path, remote: true, class: 'form') do %>
30
5
  <div class= "left">
@@ -60,6 +35,8 @@
60
35
  indentWithTabs: true,
61
36
  theme: 'lucario',
62
37
  tabSize: 2,
63
- lineNumbers: true
38
+ lineNumbers: true,
39
+ lineWrapping: true, /* 自动换行 */
40
+ fixedGutter: false
64
41
  });
65
42
  </script>
@@ -1,17 +1,38 @@
1
1
  module WebSandboxConsole
2
2
  module Common
3
- # uuid 方便取出日志
4
- def log_p(msg_or_exce, uuid = nil)
5
- @logger ||= Logger.new(log_path)
3
+
4
+ def current_uuid(uuid=nil)
5
+ @uuid ||= uuid
6
+ end
7
+
8
+ # logger sql语句
9
+ def logger_sql
10
+ logger = fetch_logger
11
+ logger.level = 0
12
+ logger.formatter = proc {|severity, time, progname, msg| "#{current_uuid}: #{msg}\n"}
13
+ ActiveRecord::Base.logger = logger
14
+ end
6
15
 
7
- if msg_or_exce.respond_to?(:message)
8
- @logger.info "#{uuid}:" + msg_or_exce.message
9
- @logger.info "#{uuid}:" + msg_or_exce.backtrace.join("|||")
10
- else
11
- @logger.info "#{uuid}:" + msg_or_exce.inspect
16
+ # uuid 方便取出日志
17
+ def log_p(msg_or_exce, is_general_text = false)
18
+ uuid = current_uuid
19
+ logger = fetch_logger
20
+
21
+ if msg_or_exce.respond_to?(:message) # 异常
22
+ logger.info "#{uuid}:" + msg_or_exce.message
23
+ logger.info "#{uuid}:" + msg_or_exce.backtrace.join("|||")
24
+ elsif is_general_text # 普通文本
25
+ logger.info "#{uuid}:" + msg_or_exce.inspect
26
+ else # 返回值
27
+ logger.info "#{uuid}: => " + msg_or_exce.inspect
12
28
  end
13
29
  end
14
30
 
31
+ # 获取 logger
32
+ def fetch_logger
33
+ @logger ||= Logger.new(log_path, 'daily')
34
+ end
35
+
15
36
  def log_path
16
37
  "#{Rails.root}/#{self.console_log_path || "log/web_sandbox_console.log"}"
17
38
  end
@@ -7,17 +7,14 @@ module WebSandboxConsole
7
7
  sanitize_class_methods
8
8
  sanitize_logger_new
9
9
  sanitize_csv
10
+ compatible_file_cache
11
+ compatible_i18n_translate
12
+ blacklist_method_remind
10
13
  end
11
14
 
12
15
  # 净化 类方法
13
16
  def sanitize_class_methods
14
- blacklist = if class_method_blacklist
15
- merge_method_hash(CLASS_METHOD_BUILT_IN_BLACKLIST, class_method_blacklist)
16
- else
17
- CLASS_METHOD_BUILT_IN_BLACKLIST
18
- end
19
-
20
- blacklist.each do |klass, methods|
17
+ class_method_blacklists.each do |klass, methods|
21
18
  klass = Object.const_get(klass)
22
19
  methods.each do |method|
23
20
  next if klass.singleton_methods.exclude?(method)
@@ -28,13 +25,7 @@ module WebSandboxConsole
28
25
 
29
26
  # 净化 实例方法
30
27
  def sanitize_instance_methods
31
- blacklist = if instance_method_blacklist
32
- merge_method_hash(INSTANT_METOD_BUILT_IN_BLACKLIST,instance_method_blacklist)
33
- else
34
- INSTANT_METOD_BUILT_IN_BLACKLIST
35
- end
36
-
37
- blacklist.each do |klass, methods|
28
+ instance_method_blacklists.each do |klass, methods|
38
29
  klass = Object.const_get(klass)
39
30
  methods.each do |method|
40
31
  next if (klass != Kernel) && klass.instance_methods.exclude?(method)
@@ -43,6 +34,24 @@ module WebSandboxConsole
43
34
  end
44
35
  end
45
36
 
37
+ # 类方法黑名单列表
38
+ def class_method_blacklists
39
+ blacklist = if class_method_blacklist
40
+ merge_method_hash(CLASS_METHOD_BUILT_IN_BLACKLIST, class_method_blacklist)
41
+ else
42
+ CLASS_METHOD_BUILT_IN_BLACKLIST
43
+ end
44
+ end
45
+
46
+ # 实例方法黑名单列表
47
+ def instance_method_blacklists
48
+ blacklist = if instance_method_blacklist
49
+ merge_method_hash(INSTANT_METOD_BUILT_IN_BLACKLIST,instance_method_blacklist)
50
+ else
51
+ INSTANT_METOD_BUILT_IN_BLACKLIST
52
+ end
53
+ end
54
+
46
55
  # 净化 常量
47
56
  def sanitize_constants
48
57
  return unless constant_blacklist
@@ -105,5 +114,57 @@ module WebSandboxConsole
105
114
  end
106
115
  end
107
116
 
117
+ # 兼容文件缓存
118
+ def compatible_file_cache
119
+ ActiveSupport::Cache::FileStore.class_exec do
120
+ def write_entry(key, entry, options)
121
+ true
122
+ end
123
+
124
+ def delete_entry(key, options)
125
+ true
126
+ end
127
+ end
128
+ end
129
+
130
+ # 兼容翻译
131
+ def compatible_i18n_translate
132
+ I18n.instance_exec do
133
+ def translate(*args)
134
+ "ActiveRecord::RecordInvalid: 校验失败"
135
+ end
136
+ alias :t :translate
137
+ end
138
+ end
139
+
140
+ # 当拦截黑名单方法时提醒
141
+ def blacklist_method_remind
142
+ Kernel.class_exec do
143
+ # 发现此处method_missing Array 没有flatten方法
144
+ def flatten_arr(arr)
145
+ new_arr = []
146
+ arr.each do |e|
147
+ if e.is_a?(Array)
148
+ new_arr.concat(flatten_arr(e))
149
+ else
150
+ new_arr << e
151
+ end
152
+ end
153
+ new_arr
154
+ end
155
+
156
+ def method_missing(name,*params)
157
+ class_methods = WebSandboxConsole.class_method_blacklists.values
158
+ instance_methods = WebSandboxConsole.instance_method_blacklists.values
159
+
160
+ if flatten_arr([class_methods, instance_methods]).include?(name.to_sym)
161
+ msg = "PS:当前代码执行过程中可能调用了黑名单方法,若代码正常返回,请忽略此条提醒"
162
+ WebSandboxConsole.log_p(msg, true)
163
+ end
164
+ super
165
+ end
166
+ end
167
+ end
168
+
108
169
  end
109
170
  end
@@ -43,16 +43,18 @@ module WebSandboxConsole
43
43
 
44
44
  def runner_code
45
45
  str =<<-CODE
46
- WebSandboxConsole.init_safe_env
47
46
  result = nil
48
47
  begin
48
+ WebSandboxConsole.current_uuid("#{self.uuid}")
49
+ WebSandboxConsole.init_safe_env
50
+ WebSandboxConsole.logger_sql
49
51
  #{self.pass_auth ? no_rollback_code : rollback_code}
50
52
  rescue Exception => e
51
- WebSandboxConsole.log_p(e, "#{self.uuid}")
53
+ WebSandboxConsole.log_p(e)
52
54
  rescue SyntaxError => e
53
- WebSandboxConsole.log_p(e, "#{self.uuid}")
55
+ WebSandboxConsole.log_p(e)
54
56
  end
55
- WebSandboxConsole.log_p(result, "#{self.uuid}")
57
+ WebSandboxConsole.log_p(result)
56
58
  CODE
57
59
  end
58
60
 
@@ -121,7 +123,7 @@ module WebSandboxConsole
121
123
 
122
124
  # 返回结果
123
125
  def return_result_arr
124
- last_10_lines = `tail -n 10 #{WebSandboxConsole.log_path} | grep #{self.uuid}`
126
+ last_10_lines = `tail -n 100 #{WebSandboxConsole.log_path} | grep #{self.uuid}`
125
127
 
126
128
  last_10_lines.split("\n").map do |line|
127
129
  line.split("#{self.uuid}:").last.split("|||")
@@ -131,7 +133,8 @@ module WebSandboxConsole
131
133
  # 最终结果
132
134
  def get_result
133
135
  if @stdout.present?
134
- stdout_arr = @stdout.to_s.split("\n")
136
+ stdout_arr = ['------------ 打印值 ----------']
137
+ stdout_arr.concat(@stdout.to_s.split("\n"))
135
138
  stdout_arr << '------------ 返回值 ----------'
136
139
  stdout_arr.concat(return_result_arr)
137
140
  else
@@ -1,3 +1,3 @@
1
1
  module WebSandboxConsole
2
- VERSION = '0.5.0'
2
+ VERSION = '0.6.0'
3
3
  end
@@ -8,21 +8,32 @@ module WebSandboxConsole
8
8
  attr_accessor :grep_content # 过滤内容
9
9
  attr_accessor :touch_grep_protect # 是否触发过滤保护
10
10
  attr_accessor :content_is_trimed # 内容是否有裁剪
11
+
12
+ # 页面相关提示
13
+ PageTips = {
14
+ touch_grep_protect: "由于过滤执行时间太长,已触发过滤保护,返回内容为最后1000行",
15
+ content_is_trimed: "当前返回内容太多,仅展示满足条件的1000行",
16
+ is_big_file_return: "当前文件视为大文件,返回最后1000行",
17
+ special_line_return: "当前按指定行数返回,若未指定行数,则默认返回文件前100行"
18
+ }.freeze
11
19
 
12
20
  def initialize(opts = {})
13
21
  @file_or_dir = opts[:file_or_dir]
14
22
  @start_line_num = (opts[:start_line_num].presence || 1).to_i
15
23
  @end_line_num = (opts[:end_line_num].presence || 100).to_i
16
- @sed_start_time = parse_time(opts[:sed_start_time])
17
- @sed_end_time = parse_time(opts[:sed_end_time])
24
+ @sed_start_time = opts[:sed_start_time]
25
+ @sed_end_time = opts[:sed_end_time]
18
26
  @grep_content = opts[:grep_content]
19
- @touch_grep_protect = false
20
- @content_is_trimed = false
27
+ @touch_grep_protect = false
28
+ @content_is_trimed = false
29
+ @is_big_file_return = false
30
+ @special_line_return = false
21
31
  end
22
32
 
23
33
  def view
24
34
  begin
25
35
  check_param
36
+ correction_line_num
26
37
  file_or_dir_exists
27
38
  check_blacklist
28
39
  check_only_view_log
@@ -38,6 +49,13 @@ module WebSandboxConsole
38
49
  raise ViewFileError, "过滤内容中不能出现单引号" if grep_content.to_s.include?("'")
39
50
  end
40
51
 
52
+ # 纠正起始行数
53
+ def correction_line_num
54
+ if @start_line_num > @end_line_num
55
+ @end_line_num = @start_line_num + 100
56
+ end
57
+ end
58
+
41
59
  # 转换成项目路径
42
60
  def project_path(path)
43
61
  "#{Rails.root}/#{path}"
@@ -117,11 +135,14 @@ module WebSandboxConsole
117
135
  if is_directory?(file_or_dir_path)
118
136
  files_in_dir
119
137
  else # 文件
138
+ parse_start_and_end_time
120
139
  lines = if need_grep?
121
140
  grep_file_content
122
141
  elsif is_big_file?
142
+ @is_big_file_return = true
123
143
  tail_any_line(1000)
124
144
  else
145
+ @special_line_return = true
125
146
  special_line_content
126
147
  end
127
148
  # 修剪行数
@@ -131,7 +152,9 @@ module WebSandboxConsole
131
152
  lines: add_line_num(lines),
132
153
  total_line_num: cal_file_total_line_num,
133
154
  touch_grep_protect: @touch_grep_protect,
134
- content_is_trimed: @content_is_trimed
155
+ content_is_trimed: @content_is_trimed,
156
+ is_big_file_return: @is_big_file_return,
157
+ special_line_return: @special_line_return
135
158
  }
136
159
  end
137
160
  end
@@ -210,8 +233,23 @@ module WebSandboxConsole
210
233
 
211
234
  private
212
235
  # 解析时间
213
- def parse_time(str)
214
- DateTime.parse(str).strftime("%FT%T") rescue nil
236
+ def parse_start_and_end_time
237
+ formatter = datetime_formatter
238
+ @sed_start_time = DateTime.parse(@sed_start_time).strftime(formatter) rescue nil
239
+ @sed_end_time = DateTime.parse(@sed_end_time).strftime(formatter) rescue nil
240
+ end
241
+
242
+ # 日志时间格式是否为标准格式
243
+ def logger_datetime_is_default_formatter
244
+ # 抽取日志的第二行
245
+ logger_line = `head -n 2 #{file_or_dir_path} | tail -n 1`
246
+ datatime_part = logger_line.split(/DEBUG:|INFO:|WARN:|ERROR:|FATAL:|UNKNOWN:/).first.to_s
247
+ datatime_part.include?("T")
248
+ end
249
+
250
+ # 解析日期格式
251
+ def datetime_formatter
252
+ logger_datetime_is_default_formatter ? "%FT%T" : "%F %T"
215
253
  end
216
254
 
217
255
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: web_sandbox_console
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - dongmingyan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-10 00:00:00.000000000 Z
11
+ date: 2020-07-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -38,8 +38,13 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
- description: 工作中许多时候,都需要我们连到服务器进入rails c下查询或一些数据。当运维人员时间比较充足的时候,情况还相对较好;如果一个运维人员,同时负责许多台服务器,让其帮忙负责查询就会浪费很大的一部分时间;为了解决这个问题,我想找到一种即安全、又方便的查询控制台,搜索了一些gem后,发现并没有符合我预期的gem,于是决定写一个相关功能的gem,旨在提供一个安全、方便的web
42
- 控制台.
41
+ description: At work, many times, we need to connect to the server to enter the rails
42
+ c query or some data. When the operator has plenty of time, the situation is relatively
43
+ good; if an operator is responsible for many servers at the same time, it will waste
44
+ a lot of time to help with the query; to solve this problem, I want to find a secure
45
+ and convenient query console, after searching some gem, found and did not meet my
46
+ expectations gem, so decided to write a related function of the console designed
47
+ to provide a safe, convenient web.
43
48
  email:
44
49
  - dongmingyan01@gmail.com
45
50
  executables: []
@@ -115,5 +120,5 @@ requirements: []
115
120
  rubygems_version: 3.0.8
116
121
  signing_key:
117
122
  specification_version: 4
118
- summary: 一个安全、方便的web 控制台
123
+ summary: A secure, convenient web console
119
124
  test_files: []