web_sandbox_console 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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: []