web_sandbox_console 0.1.0 → 0.2.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: 69751d9ed5eefe3885a9c45e9897858d69546627b6eb9898ab8b77fcea429027
4
- data.tar.gz: 01a2f21f2aee4e4ec9cbdaadf79053b55b51abaeff142064c4e0865331f83d12
3
+ metadata.gz: 59bdbe60c0c4fa3569ef776901c06e5519cdd804fd905fe1c81e15cfd269157c
4
+ data.tar.gz: d71b8d16c04d900fb270f196d1e2bf89b71e77ca2620e48bfdc178158637e5a6
5
5
  SHA512:
6
- metadata.gz: 5f9a54707f95d100575ec671f5c44c331761b98a6f89205cb7fedf0a7762be281d29051f34041f677fa3f4cb859090c9d341d6300f3a081d37d2ba05f4145aab
7
- data.tar.gz: 49a29b84ba6790c2fa91fc6b6759d38b13647002f71247da0b72c5278e1356b925b6a79e824e1aba0094d92bda24e443aba5b8dc838057a131fb140e94c2deb9
6
+ metadata.gz: a8f4487e10e9796fbaefa3ee6d4f8b3112e493adf165d6cacaefa71a6975d436e849ce65ad97af3ba76ad5b3261787bcc15db205576a284120a0fae50f9ce74e
7
+ data.tar.gz: d5395e322921350c55bd3e936782cac340e6f772e075166c81860378c695e79a4711b91016d06590d58384dc812084feef4496a739f64c24acf560b017655343
data/README.md CHANGED
@@ -50,11 +50,22 @@ WebSandboxConsole.setup do |config|
50
50
  # # 配置 黑名单 实例方法
51
51
  # config.instance_method_blacklist = {Kernel: %i(system exec `),File: %i(chmod chown)}
52
52
 
53
+ # 文件黑名单列表 (如果是目录 则目录下所有文件都不用)目录以 / 结尾
54
+ # 默认都是项目路径下的
55
+ # config.view_file_blacklist = %w(config/secrets.yml vendor/)
56
+
53
57
  # # 配置 日志路径 默认路径位于项目下
54
58
  # config.console_log_path = "log/web_sandbox_console.log"
55
59
  end
56
60
  ```
57
61
 
62
+ ## other
63
+ 查看目录或文件路径: `/web_sandbox_console/view_file`
64
+ 除了可以查询一些数据外,还可以查看项目路径下任何文件或目录,如果你输入的是一个目录,那么会查出此目录下的文件/目录;如果你输入的是文件,那么将查出文件的内容,默认查看文件的第一行 到 100行,当然你也可以指定你需要查找的行;
65
+
66
+ 如果一个文件特别大,超过10M,此时将查找文件的最后200行,指定行数将无效;当然也可在配置文件中,配置哪些文件不可查看,哪些目录不可以查看,如果指定的是目录,那么目录下的所有子文件或目录都无权查看.
67
+
68
+ ![Snip20200508_1.png](https://i.loli.net/2020/05/08/3N8Q7pnzroq9Byw.png)
58
69
  ## Contributing
59
70
  Contribution directions go here.
60
71
 
@@ -2,3 +2,22 @@
2
2
  Place all the styles related to the matching controller here.
3
3
  They will automatically be included in application.css.
4
4
  */
5
+
6
+
7
+ .file_or_dir{
8
+ width: 500px;
9
+ height: 30px;
10
+ }
11
+
12
+ .h30{
13
+ height: 30px;
14
+ }
15
+
16
+ .view-file-button{
17
+ background: #272822;
18
+ height: 36px;
19
+ width: 132px;
20
+ font-size: 15px;
21
+ color: white;
22
+ cursor: pointer;
23
+ }
@@ -8,8 +8,17 @@ module WebSandboxConsole
8
8
  def index
9
9
  end
10
10
 
11
+ # 执行代码
11
12
  def eval_code
12
13
  @results = Sandbox.new(params[:code]).evalotor
13
14
  end
15
+
16
+ def view_file
17
+ end
18
+
19
+ # 查看文件
20
+ def do_view_file
21
+ @results = ViewFile.new(params).view
22
+ end
14
23
  end
15
24
  end
@@ -0,0 +1,5 @@
1
+ $(".output-content").empty();
2
+ $(".output-content").append('<p>============ 查找结果如下 ===============</p>');
3
+ <% @results.each do |result| %>
4
+ $(".output-content").append('<pre><%= escape_javascript result %></pre>');
5
+ <% end %>
@@ -1,4 +1,5 @@
1
1
  控制台 index
2
+ <%= link_to '查看文件', web_sandbox_console.view_file_path %>
2
3
 
3
4
  <div class="console">
4
5
  <%= form_tag(web_sandbox_console.eval_code_path, remote: true, class: 'form') do %>
@@ -6,7 +7,7 @@
6
7
  <input type="reset" value="重置" class='reset-button'>
7
8
  <%= submit_tag '提交', data: { disable_with: "已发送,处理中..." }, class: 'send-button' %>
8
9
  <% end %>
9
-
10
+
10
11
  </div>
11
12
 
12
13
  <%= button_tag '清除输出', type: 'button', onclick: "$('.output-content').empty();", class: 'clear-button' %>
@@ -0,0 +1,25 @@
1
+ # view_file
2
+ <%= link_to '控制台', web_sandbox_console.root_path %>
3
+ <div class="view_file">
4
+ <%= form_tag do_view_file_path, method: :post, remote: true do %>
5
+ <table>
6
+ <tr>
7
+ <td>文件/目录路径</td>
8
+ <td>
9
+ <%= text_field_tag :file_or_dir, nil, class: 'file_or_dir', placeholder: '请输入文件路径...'%>
10
+ </td>
11
+ <td>起始行数</td>
12
+ <td><%= text_field_tag :start_line_num, nil, class: 'h30', placeholder: '默认从第1行开始...' %></td>
13
+ <td>结束行数</td>
14
+ <td><%= text_field_tag :end_line_num, nil, class: 'h30', placeholder: '默认从第100行结束...' %></td>
15
+ <td><%= submit_tag '提交', data: { disable_with: "已发送,处理中..." }, class: 'view-file-button' %></td>
16
+ </table>
17
+ <% end %>
18
+ </div>
19
+
20
+ <div class="output-content">
21
+ </div>
22
+
23
+ <style type="text/css">
24
+
25
+ </style>
data/config/routes.rb CHANGED
@@ -2,4 +2,6 @@ WebSandboxConsole::Engine.routes.draw do
2
2
  root "home#index"
3
3
 
4
4
  post :eval_code, to: "home#eval_code"
5
+ get :view_file, to: "home#view_file"
6
+ post :do_view_file, to: "home#do_view_file"
5
7
  end
@@ -16,6 +16,10 @@ WebSandboxConsole.setup do |config|
16
16
  # # 配置 黑名单 实例方法
17
17
  # config.instance_method_blacklist = {Kernel: %i(system exec `),File: %i(chmod chown)}
18
18
 
19
+ # 文件黑名单列表 (如果是目录 则目录下所有文件都不用)目录以 / 结尾
20
+ # 默认都是项目路径下的
21
+ # config.view_file_blacklist = %w(config/secrets.yml vendor/)
22
+
19
23
  # # 配置 日志路径 默认路径位于项目下
20
24
  # config.console_log_path = "log/web_sandbox_console.log"
21
25
  end
@@ -1,8 +1,12 @@
1
+ require 'fileutils'
1
2
  require "web_sandbox_console/engine"
3
+ require "web_sandbox_console/sandbox_error"
2
4
  require "web_sandbox_console/configuration"
3
5
  require "web_sandbox_console/common.rb"
4
6
  require "web_sandbox_console/safe_ruby"
5
7
  require "web_sandbox_console/sandbox"
8
+ require "web_sandbox_console/view_file_error"
9
+ require "web_sandbox_console/view_file"
6
10
 
7
11
 
8
12
  module WebSandboxConsole
@@ -9,6 +9,8 @@ module WebSandboxConsole
9
9
  mattr_accessor :class_method_blacklist
10
10
  # 实例方法 黑名单 hash
11
11
  mattr_accessor :instance_method_blacklist
12
+ # 文件列表 黑名单
13
+ mattr_accessor :view_file_blacklist
12
14
  # 日志路径
13
15
  mattr_accessor :console_log_path
14
16
  # 挂载 引擎路由位置
@@ -16,6 +18,7 @@ module WebSandboxConsole
16
18
 
17
19
  # 默认 引擎路由位置
18
20
  @@mount_engine_route_path = '/web_sandbox_console'
21
+
19
22
 
20
23
  # 内置 实例方法 黑名单
21
24
  INSTANT_METOD_BUILT_IN_BLACKLIST = {
@@ -52,13 +52,13 @@ module WebSandboxConsole
52
52
  # 将两个hash 内部数组也同时合并,并去重
53
53
  def merge_method_hash(hash1, hash2)
54
54
  # 格式统一
55
- hash2.transform_keys!(&:to_sym).transform_values!{|val_arr| val_arr.map{|val| val.to_sym}}
55
+ hash2.transform_keys!(&:to_sym).transform_keys!(&:to_sym).transform_values!{|i| i.map(&:to_sym)}
56
56
  # 共有的key
57
57
  common_keys = hash2.keys & hash1.keys
58
58
  # hash2 特有keys
59
59
  hash2_special_keys = hash2.keys - hash1.keys
60
60
  # 特有keys 直接合到 hash1
61
- hash1.merge!(hash2.slice(hash2_special_keys))
61
+ hash1.merge!(hash2.slice(*hash2_special_keys))
62
62
  # 共用keys 数组去重
63
63
  common_keys.each do |key|
64
64
  hash1[key] = (hash1[key] | hash2[key]).uniq
@@ -1,16 +1,24 @@
1
1
  module WebSandboxConsole
2
2
  class Sandbox
3
- attr_accessor :code
4
- attr_accessor :uuid
3
+ attr_accessor :code # 代码
4
+ attr_accessor :uuid # 唯一标识
5
+ attr_accessor :exe_tmp_file # 执行临时文件(由code 组成的运行代码)
5
6
 
6
7
  def initialize(code = nil)
7
- @code = escape_single_quote_mark(code)
8
- @uuid = SecureRandom.uuid
8
+ @code = code
9
+ @uuid = SecureRandom.uuid
10
+ @exe_tmp_file = "#{Rails.root}/tmp/sandbox/#{uuid}.rb"
9
11
  end
10
12
 
11
13
  def evalotor
12
- `bundle exec rails runner '#{runner_code}'`
13
- get_result
14
+ begin
15
+ check_syntax
16
+ write_exe_tmp_file
17
+ exec_rails_runner
18
+ get_result
19
+ rescue SandboxError => e
20
+ [e.message]
21
+ end
14
22
  end
15
23
 
16
24
  def runner_code
@@ -30,7 +38,54 @@ module WebSandboxConsole
30
38
  WebSandboxConsole.log_p(result, "#{self.uuid}")
31
39
  CODE
32
40
  end
41
+
42
+ # 临时文件目录
43
+ def tmp_file_dir
44
+ File.dirname(self.exe_tmp_file)
45
+ end
46
+
47
+ # 添加临时文件目录
48
+ def add_tmp_file_dir
49
+ FileUtils.mkdir_p(tmp_file_dir) unless File.directory?(tmp_file_dir)
50
+ end
51
+
52
+ # 临时文件 需要清理?
53
+ def tmp_file_need_clean?
54
+ Dir["#{tmp_file_dir}/*"].count > 6
55
+ end
56
+
57
+ # 自动删除临时文件
58
+ def auto_clean_tmp_file
59
+ FileUtils.rm_rf(Dir["#{tmp_file_dir}/*"]) if tmp_file_need_clean?
60
+ end
61
+
62
+ # 写入 执行临时文件
63
+ def write_exe_tmp_file
64
+ add_tmp_file_dir
65
+ auto_clean_tmp_file
66
+ File.open(self.exe_tmp_file, 'w'){|f| f << runner_code}
67
+ end
68
+
69
+ # 准备检查语法
70
+ def prepare_check_syntax
71
+ add_tmp_file_dir
72
+ File.open(self.exe_tmp_file, 'w'){|f| f << self.code}
73
+ end
74
+
75
+ # 检查 语法
76
+ def check_syntax
77
+ prepare_check_syntax
78
+ unless `ruby -c #{self.exe_tmp_file}`.include?('Syntax OK')
79
+ raise SandboxError, "存在语法错误"
80
+ end
81
+ end
82
+
83
+ # 运行rails runner
84
+ def exec_rails_runner
85
+ `bundle exec rails runner #{self.exe_tmp_file}`
86
+ end
33
87
 
88
+ # 获取 执行结果
34
89
  def get_result
35
90
  last_10_lines = `tail -n 10 #{WebSandboxConsole.log_path} | grep #{self.uuid}`
36
91
 
@@ -39,9 +94,5 @@ module WebSandboxConsole
39
94
  end.flatten
40
95
  end
41
96
 
42
- # 转义单引号
43
- def escape_single_quote_mark(code)
44
- code.gsub(/'/,'"')
45
- end
46
97
  end
47
98
  end
@@ -0,0 +1,4 @@
1
+ module WebSandboxConsole
2
+ class SandboxError < StandardError
3
+ end
4
+ end
@@ -1,3 +1,3 @@
1
1
  module WebSandboxConsole
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.0'
3
3
  end
@@ -0,0 +1,117 @@
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
+
7
+ def initialize(opts = {})
8
+ @file_or_dir = opts[:file_or_dir]
9
+ @start_line_num = opts[:start_line_num].present? ? opts[:start_line_num].to_i : 1
10
+ @end_line_num = opts[:end_line_num].present? ? opts[:end_line_num].to_i : 100
11
+ end
12
+
13
+ def view
14
+ begin
15
+ check_param
16
+ file_or_dir_exists
17
+ check_blacklist
18
+ view_file
19
+ rescue ViewFileError => e
20
+ [e.message]
21
+ end
22
+ end
23
+
24
+ # 检查参数
25
+ def check_param
26
+ raise ViewFileError, '文件或目录参数不能为空' if file_or_dir.blank?
27
+ end
28
+
29
+ # 转换成项目路径
30
+ def project_path(path)
31
+ "#{Rails.root}/#{path}"
32
+ end
33
+
34
+ # 绝对路径
35
+ def file_or_dir_path
36
+ "#{Rails.root}/#{file_or_dir}"
37
+ end
38
+
39
+ # 是否存在
40
+ def file_or_dir_exists
41
+ raise ViewFileError, '文件或目录不存在' unless File.exists?(file_or_dir_path)
42
+ end
43
+
44
+ # 是目录?
45
+ def is_directory?(path)
46
+ File.directory?(path)
47
+ end
48
+
49
+ # 目录下所有子文件 目录
50
+ def dir_all_sub_file_or_dir(current_dir)
51
+ Dir["#{current_dir}**/*"]
52
+ end
53
+
54
+ # 黑名单 包含自身 及其 子目录/文件
55
+ def blacklist_all_file_dir_arr
56
+ black_lists = WebSandboxConsole.view_file_blacklist
57
+ return [] if black_lists.blank?
58
+
59
+ result_arr = black_lists.inject([]) do |result_arr, black_item_path|
60
+ current_path = project_path(black_item_path)
61
+
62
+ if is_directory?(current_path)
63
+ result_arr.concat(dir_all_sub_file_or_dir(current_path))
64
+ else
65
+ result_arr
66
+ end
67
+ end
68
+ black_lists.map{|i| project_path(i)}.concat(result_arr)
69
+ end
70
+
71
+ # 检查是否为黑名单 文件 / 目录
72
+ def check_blacklist
73
+ black_lists = blacklist_all_file_dir_arr
74
+ raise ViewFileError, '文件或目录无权限查看' if black_lists.include?(file_or_dir_path) || black_lists.include?(file_or_dir_path + '/')
75
+ end
76
+
77
+ # 目录下文件
78
+ def files_in_dir
79
+ Dir["#{file_or_dir_path}/*"].map do |path|
80
+ path += is_directory?(path) ? '(目录)' : '(文件)'
81
+ path[file_or_dir_path.length..-1]
82
+ end
83
+ end
84
+
85
+ # 是否为大文件
86
+ def is_big_file?
87
+ File.new(file_or_dir_path).size > 10.megabytes
88
+ end
89
+
90
+ # 查看文件/目录
91
+ def view_file
92
+ if is_directory?(file_or_dir_path)
93
+ files_in_dir
94
+ else
95
+ lines = is_big_file? ? tail_200_line : special_line_content
96
+ add_line_num(lines)
97
+ end
98
+ end
99
+
100
+ # 最后 200 行内容
101
+ def tail_200_line
102
+ (`tail -n 200 #{file_or_dir_path}`).split(/[\r,\r\n]/)
103
+ end
104
+
105
+ # 按指定行返回
106
+ def special_line_content
107
+ File.readlines(file_or_dir_path)[(start_line_num - 1)..(end_line_num - 1)]
108
+ end
109
+
110
+ # 添加行号
111
+ def add_line_num(lines)
112
+ start_num = is_big_file? ? 1 : start_line_num
113
+ lines.each_with_index.map{|line, index| "#{index + start_num}: #{line}"}
114
+ end
115
+
116
+ end
117
+ end
@@ -0,0 +1,4 @@
1
+ module WebSandboxConsole
2
+ class ViewFileError < StandardError
3
+ end
4
+ 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.1.0
4
+ version: 0.2.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-04-24 00:00:00.000000000 Z
11
+ date: 2020-05-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -62,8 +62,10 @@ files:
62
62
  - app/mailers/web_sandbox_console/application_mailer.rb
63
63
  - app/models/web_sandbox_console/application_record.rb
64
64
  - app/views/layouts/web_sandbox_console/application.html.erb
65
+ - app/views/web_sandbox_console/home/do_view_file.js.erb
65
66
  - app/views/web_sandbox_console/home/eval_code.js.erb
66
67
  - app/views/web_sandbox_console/home/index.html.erb
68
+ - app/views/web_sandbox_console/home/view_file.html.erb
67
69
  - config/routes.rb
68
70
  - lib/generators/web_sandbox_console/USAGE
69
71
  - lib/generators/web_sandbox_console/templates/web_sandbox_console.rb
@@ -75,7 +77,10 @@ files:
75
77
  - lib/web_sandbox_console/engine.rb
76
78
  - lib/web_sandbox_console/safe_ruby.rb
77
79
  - lib/web_sandbox_console/sandbox.rb
80
+ - lib/web_sandbox_console/sandbox_error.rb
78
81
  - lib/web_sandbox_console/version.rb
82
+ - lib/web_sandbox_console/view_file.rb
83
+ - lib/web_sandbox_console/view_file_error.rb
79
84
  homepage: https://github.com/dongmy54/web_sandbox_console
80
85
  licenses:
81
86
  - MIT