web_sandbox_console 0.1.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 +4 -4
- data/README.md +143 -6
- data/app/assets/images/web_sandbox_console/logo-icon.png +0 -0
- data/app/assets/javascripts/web_sandbox_console/application.js +0 -1
- data/app/assets/javascripts/web_sandbox_console/code_editor.js +0 -0
- data/app/assets/javascripts/web_sandbox_console/codemirror.js +9778 -0
- data/app/assets/javascripts/web_sandbox_console/matchbrackets.js +158 -0
- data/app/assets/javascripts/web_sandbox_console/ruby.js +298 -0
- data/app/assets/stylesheets/web_sandbox_console/application.css +85 -14
- data/app/assets/stylesheets/web_sandbox_console/codemirror.css +349 -0
- data/app/assets/stylesheets/web_sandbox_console/common.css +231 -0
- data/app/assets/stylesheets/web_sandbox_console/docs.css +274 -0
- data/app/assets/stylesheets/web_sandbox_console/home.css +47 -0
- data/app/assets/stylesheets/web_sandbox_console/lucario.css +45 -0
- data/app/controllers/web_sandbox_console/application_controller.rb +4 -0
- data/app/controllers/web_sandbox_console/authorization_controller.rb +82 -0
- data/app/controllers/web_sandbox_console/home_controller.rb +44 -4
- data/app/views/layouts/web_sandbox_console/application.html.erb +82 -11
- data/app/views/web_sandbox_console/authorization/auth_page.html.erb +33 -0
- data/app/views/web_sandbox_console/home/do_view_file.js.erb +14 -0
- data/app/views/web_sandbox_console/home/download_page.html.erb +22 -0
- data/app/views/web_sandbox_console/home/eval_code.js.erb +1 -1
- data/app/views/web_sandbox_console/home/index.html.erb +34 -7
- data/app/views/web_sandbox_console/home/view_file.html.erb +39 -0
- data/config/routes.rb +12 -0
- data/lib/generators/web_sandbox_console/templates/web_sandbox_console.rb +20 -3
- data/lib/generators/web_sandbox_console/templates/web_sandbox_console.yml +5 -0
- data/lib/generators/web_sandbox_console/web_sandbox_console_generator.rb +5 -0
- data/lib/web_sandbox_console.rb +4 -0
- data/lib/web_sandbox_console/common.rb +29 -8
- data/lib/web_sandbox_console/configuration.rb +9 -1
- data/lib/web_sandbox_console/safe_ruby.rb +116 -16
- data/lib/web_sandbox_console/sandbox.rb +119 -20
- data/lib/web_sandbox_console/sandbox_error.rb +4 -0
- data/lib/web_sandbox_console/version.rb +1 -1
- data/lib/web_sandbox_console/view_file.rb +257 -0
- data/lib/web_sandbox_console/view_file_error.rb +4 -0
- metadata +28 -6
- data/app/jobs/web_sandbox_console/application_job.rb +0 -4
@@ -0,0 +1,257 @@
|
|
1
|
+
module WebSandboxConsole
|
2
|
+
class ViewFile
|
3
|
+
attr_accessor :file_or_dir # 文件或目录
|
4
|
+
attr_accessor :start_line_num # 起始行数
|
5
|
+
attr_accessor :end_line_num # 结束行数
|
6
|
+
attr_accessor :sed_start_time # 开始时间
|
7
|
+
attr_accessor :sed_end_time # 结束时间
|
8
|
+
attr_accessor :grep_content # 过滤内容
|
9
|
+
attr_accessor :touch_grep_protect # 是否触发过滤保护
|
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
|
19
|
+
|
20
|
+
def initialize(opts = {})
|
21
|
+
@file_or_dir = opts[:file_or_dir]
|
22
|
+
@start_line_num = (opts[:start_line_num].presence || 1).to_i
|
23
|
+
@end_line_num = (opts[:end_line_num].presence || 100).to_i
|
24
|
+
@sed_start_time = opts[:sed_start_time]
|
25
|
+
@sed_end_time = opts[:sed_end_time]
|
26
|
+
@grep_content = opts[:grep_content]
|
27
|
+
@touch_grep_protect = false
|
28
|
+
@content_is_trimed = false
|
29
|
+
@is_big_file_return = false
|
30
|
+
@special_line_return = false
|
31
|
+
end
|
32
|
+
|
33
|
+
def view
|
34
|
+
begin
|
35
|
+
check_param
|
36
|
+
correction_line_num
|
37
|
+
file_or_dir_exists
|
38
|
+
check_blacklist
|
39
|
+
check_only_view_log
|
40
|
+
view_file
|
41
|
+
rescue ViewFileError => e
|
42
|
+
{lines: [e.message]}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# 检查参数
|
47
|
+
def check_param
|
48
|
+
raise ViewFileError, '文件或目录参数不能为空' if file_or_dir.blank?
|
49
|
+
raise ViewFileError, "过滤内容中不能出现单引号" if grep_content.to_s.include?("'")
|
50
|
+
end
|
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
|
+
|
59
|
+
# 转换成项目路径
|
60
|
+
def project_path(path)
|
61
|
+
"#{Rails.root}/#{path}"
|
62
|
+
end
|
63
|
+
|
64
|
+
# 绝对路径
|
65
|
+
def file_or_dir_path
|
66
|
+
"#{Rails.root}/#{file_or_dir}"
|
67
|
+
end
|
68
|
+
|
69
|
+
# 是否存在
|
70
|
+
def file_or_dir_exists
|
71
|
+
raise ViewFileError, '文件或目录不存在' unless File.exists?(file_or_dir_path)
|
72
|
+
end
|
73
|
+
|
74
|
+
# 是目录?
|
75
|
+
def is_directory?(path)
|
76
|
+
File.directory?(path)
|
77
|
+
end
|
78
|
+
|
79
|
+
# 目录下所有子文件 目录
|
80
|
+
def dir_all_sub_file_or_dir(current_dir)
|
81
|
+
Dir["#{current_dir}**/*"]
|
82
|
+
end
|
83
|
+
|
84
|
+
# 黑名单 包含自身 及其 子目录/文件
|
85
|
+
def blacklist_all_file_dir_arr
|
86
|
+
black_lists = WebSandboxConsole.view_file_blacklist
|
87
|
+
return [] if black_lists.blank?
|
88
|
+
|
89
|
+
result_arr = black_lists.inject([]) do |result_arr, black_item_path|
|
90
|
+
current_path = project_path(black_item_path)
|
91
|
+
|
92
|
+
if is_directory?(current_path)
|
93
|
+
result_arr.concat(dir_all_sub_file_or_dir(current_path))
|
94
|
+
else
|
95
|
+
result_arr
|
96
|
+
end
|
97
|
+
end
|
98
|
+
black_lists.map{|i| project_path(i)}.concat(result_arr)
|
99
|
+
end
|
100
|
+
|
101
|
+
# 检查是否为黑名单 文件 / 目录
|
102
|
+
def check_blacklist
|
103
|
+
black_lists = blacklist_all_file_dir_arr
|
104
|
+
raise ViewFileError, '文件或目录无权限查看' if black_lists.include?(file_or_dir_path) || black_lists.include?(file_or_dir_path + '/')
|
105
|
+
end
|
106
|
+
|
107
|
+
# 检查 仅能查看日志
|
108
|
+
def check_only_view_log
|
109
|
+
if WebSandboxConsole.only_view_log_file
|
110
|
+
raise ViewFileError, '仅可查看日志目录/文件' unless file_or_dir.split("/")[0] == 'log'
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# 目录下文件
|
115
|
+
def files_in_dir
|
116
|
+
lines = Dir["#{file_or_dir_path}/*"].map do |path|
|
117
|
+
path += is_directory?(path) ? '(目录)' : '(文件)'
|
118
|
+
path[file_or_dir_path.length..-1]
|
119
|
+
end
|
120
|
+
{lines: lines}
|
121
|
+
end
|
122
|
+
|
123
|
+
# 是否为大文件
|
124
|
+
def is_big_file?
|
125
|
+
File.new(file_or_dir_path).size > 10.megabytes
|
126
|
+
end
|
127
|
+
|
128
|
+
# 是否需要过滤
|
129
|
+
def need_grep?
|
130
|
+
@sed_start_time || @grep_content.present?
|
131
|
+
end
|
132
|
+
|
133
|
+
# 查看文件/目录
|
134
|
+
def view_file
|
135
|
+
if is_directory?(file_or_dir_path)
|
136
|
+
files_in_dir
|
137
|
+
else # 文件
|
138
|
+
parse_start_and_end_time
|
139
|
+
lines = if need_grep?
|
140
|
+
grep_file_content
|
141
|
+
elsif is_big_file?
|
142
|
+
@is_big_file_return = true
|
143
|
+
tail_any_line(1000)
|
144
|
+
else
|
145
|
+
@special_line_return = true
|
146
|
+
special_line_content
|
147
|
+
end
|
148
|
+
# 修剪行数
|
149
|
+
lines = content_trim(lines)
|
150
|
+
|
151
|
+
{
|
152
|
+
lines: add_line_num(lines),
|
153
|
+
total_line_num: cal_file_total_line_num,
|
154
|
+
touch_grep_protect: @touch_grep_protect,
|
155
|
+
content_is_trimed: @content_is_trimed,
|
156
|
+
is_big_file_return: @is_big_file_return,
|
157
|
+
special_line_return: @special_line_return
|
158
|
+
}
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# 计算文件总行数
|
163
|
+
def cal_file_total_line_num
|
164
|
+
`wc -l < #{file_or_dir_path}`.to_i
|
165
|
+
end
|
166
|
+
|
167
|
+
# 最后 xx 行
|
168
|
+
def tail_any_line(num)
|
169
|
+
tail_any_line_content(num).split("\n")
|
170
|
+
end
|
171
|
+
|
172
|
+
# 最后多少行内容
|
173
|
+
def tail_any_line_content(num)
|
174
|
+
`tail -n #{num} #{file_or_dir_path}`
|
175
|
+
end
|
176
|
+
|
177
|
+
# 按指定行返回
|
178
|
+
def special_line_content
|
179
|
+
File.readlines(file_or_dir_path)[(start_line_num - 1)..(end_line_num - 1)]
|
180
|
+
end
|
181
|
+
|
182
|
+
# 过滤超时保护
|
183
|
+
def grep_timeout_protect
|
184
|
+
begin
|
185
|
+
Timeout::timeout(8) {yield}
|
186
|
+
rescue Timeout::Error => e
|
187
|
+
# 触发过滤保护
|
188
|
+
@touch_grep_protect = true
|
189
|
+
tail_any_line_content(1000)
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
# 过滤文件
|
194
|
+
def grep_file_content
|
195
|
+
content = if @sed_start_time && @grep_content.present?
|
196
|
+
grep_timeout_protect {`sed -n '/#{@sed_start_time}/,/#{@sed_end_time}/p' #{file_or_dir_path} | fgrep '#{@grep_content}'`}
|
197
|
+
elsif @sed_start_time
|
198
|
+
grep_timeout_protect {`sed -n '/#{@sed_start_time}/,/#{@sed_end_time}/p' #{file_or_dir_path}`}
|
199
|
+
else
|
200
|
+
grep_timeout_protect {`fgrep '#{@grep_content}' #{file_or_dir_path}`}
|
201
|
+
end
|
202
|
+
content.split("\n")
|
203
|
+
end
|
204
|
+
|
205
|
+
# 修剪过滤内容
|
206
|
+
def content_trim(lines)
|
207
|
+
if lines.length > 1000
|
208
|
+
@content_is_trimed = true
|
209
|
+
# 内容太多时 只返回前1000行
|
210
|
+
lines.first(1000)
|
211
|
+
else
|
212
|
+
lines
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
# 添加行号
|
217
|
+
def add_line_num(lines)
|
218
|
+
start_num = is_big_file? ? 1 : start_line_num
|
219
|
+
lines.each_with_index.map do |line, index|
|
220
|
+
line = "#{index + start_num}: #{line}"
|
221
|
+
hightlight_grep_content(line)
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
# 高亮内容
|
226
|
+
def hightlight_grep_content(content)
|
227
|
+
if @grep_content.present?
|
228
|
+
content.gsub(@grep_content.to_s, "<span style='color: #E35520;'> #{@grep_content}</span>").html_safe
|
229
|
+
else
|
230
|
+
content
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
private
|
235
|
+
# 解析时间
|
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"
|
253
|
+
end
|
254
|
+
|
255
|
+
|
256
|
+
end
|
257
|
+
end
|
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.
|
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-
|
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:
|
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: []
|
@@ -50,23 +55,37 @@ files:
|
|
50
55
|
- README.md
|
51
56
|
- Rakefile
|
52
57
|
- app/assets/config/web_sandbox_console_manifest.js
|
58
|
+
- app/assets/images/web_sandbox_console/logo-icon.png
|
53
59
|
- app/assets/javascripts/web_sandbox_console/application.js
|
60
|
+
- app/assets/javascripts/web_sandbox_console/code_editor.js
|
61
|
+
- app/assets/javascripts/web_sandbox_console/codemirror.js
|
54
62
|
- app/assets/javascripts/web_sandbox_console/home.js
|
63
|
+
- app/assets/javascripts/web_sandbox_console/matchbrackets.js
|
64
|
+
- app/assets/javascripts/web_sandbox_console/ruby.js
|
55
65
|
- app/assets/stylesheets/web_sandbox_console/application.css
|
66
|
+
- app/assets/stylesheets/web_sandbox_console/codemirror.css
|
67
|
+
- app/assets/stylesheets/web_sandbox_console/common.css
|
68
|
+
- app/assets/stylesheets/web_sandbox_console/docs.css
|
56
69
|
- app/assets/stylesheets/web_sandbox_console/home.css
|
70
|
+
- app/assets/stylesheets/web_sandbox_console/lucario.css
|
57
71
|
- app/controllers/web_sandbox_console/application_controller.rb
|
72
|
+
- app/controllers/web_sandbox_console/authorization_controller.rb
|
58
73
|
- app/controllers/web_sandbox_console/home_controller.rb
|
59
74
|
- app/helpers/web_sandbox_console/application_helper.rb
|
60
75
|
- app/helpers/web_sandbox_console/home_helper.rb
|
61
|
-
- app/jobs/web_sandbox_console/application_job.rb
|
62
76
|
- app/mailers/web_sandbox_console/application_mailer.rb
|
63
77
|
- app/models/web_sandbox_console/application_record.rb
|
64
78
|
- app/views/layouts/web_sandbox_console/application.html.erb
|
79
|
+
- app/views/web_sandbox_console/authorization/auth_page.html.erb
|
80
|
+
- app/views/web_sandbox_console/home/do_view_file.js.erb
|
81
|
+
- app/views/web_sandbox_console/home/download_page.html.erb
|
65
82
|
- app/views/web_sandbox_console/home/eval_code.js.erb
|
66
83
|
- app/views/web_sandbox_console/home/index.html.erb
|
84
|
+
- app/views/web_sandbox_console/home/view_file.html.erb
|
67
85
|
- config/routes.rb
|
68
86
|
- lib/generators/web_sandbox_console/USAGE
|
69
87
|
- lib/generators/web_sandbox_console/templates/web_sandbox_console.rb
|
88
|
+
- lib/generators/web_sandbox_console/templates/web_sandbox_console.yml
|
70
89
|
- lib/generators/web_sandbox_console/web_sandbox_console_generator.rb
|
71
90
|
- lib/tasks/web_sandbox_console_tasks.rake
|
72
91
|
- lib/web_sandbox_console.rb
|
@@ -75,7 +94,10 @@ files:
|
|
75
94
|
- lib/web_sandbox_console/engine.rb
|
76
95
|
- lib/web_sandbox_console/safe_ruby.rb
|
77
96
|
- lib/web_sandbox_console/sandbox.rb
|
97
|
+
- lib/web_sandbox_console/sandbox_error.rb
|
78
98
|
- lib/web_sandbox_console/version.rb
|
99
|
+
- lib/web_sandbox_console/view_file.rb
|
100
|
+
- lib/web_sandbox_console/view_file_error.rb
|
79
101
|
homepage: https://github.com/dongmy54/web_sandbox_console
|
80
102
|
licenses:
|
81
103
|
- MIT
|
@@ -98,5 +120,5 @@ requirements: []
|
|
98
120
|
rubygems_version: 3.0.8
|
99
121
|
signing_key:
|
100
122
|
specification_version: 4
|
101
|
-
summary:
|
123
|
+
summary: A secure, convenient web console
|
102
124
|
test_files: []
|