RemoteWebConsole 0.1.3 → 0.1.4

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: 94896087ba07c17255f8644f93552895742f3f1e37dbb28218739abd2c038054
4
- data.tar.gz: ff9a6eb87e0cefee1271814f96f7d73761f11321f62c2167d6398a29110d5229
3
+ metadata.gz: 130aeeb342a0d697598d2beffa62a8e41912b5847d0212796d37ea47e062bd7e
4
+ data.tar.gz: 9fef7199fafeb3e8b4b6d306c0ed8dec8380fcfe4b61c8d904d052d86e371c0f
5
5
  SHA512:
6
- metadata.gz: 98a7c597250b695b0cca7d8c5e6870b35813ff213eb61e62ac0b14ef2157df2d3c842ca85a2251e9f1ab568c445c53d656d12f5a03c8fdc0575423d97eb76d2c
7
- data.tar.gz: f888291e31bab5f9bbbb95acf9baf35072951fd7c3d210ec48194423e2e922a35f7e48d5ef64bcf458818bf965b613b6a441ae340576a7743e3fb442861de2d2
6
+ metadata.gz: 2fffa6d8986a335d44d9066613922a301fc5c6bdd3325408638abfe1eb0ea3f987cdc21629625ec11bfe1cbb390d118c93964d320e9a077cb1182655a537ee87
7
+ data.tar.gz: 795a316ef71700c8cd893ac8a4e359239d598ca31f38986b4110e2886073ccafff46bcaade7104483ec7cbdea7654836b340d02e556aad5c8bc069fc51f6d34c
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2022 Cynicallity
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # Webconsole
2
+ Short description and motivation.
3
+
4
+ ## Usage
5
+ How to use my plugin.
6
+
7
+ ## Installation
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'webconsole'
12
+ ```
13
+
14
+ And then execute:
15
+ ```bash
16
+ $ bundle
17
+ ```
18
+
19
+ Or install it yourself as:
20
+ ```bash
21
+ $ gem install webconsole
22
+ ```
23
+
24
+ ## Contributing
25
+ Contribution directions go here.
26
+
27
+ ## License
28
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ require "bundler/setup"
2
+
3
+ APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
4
+ load "rails/tasks/engine.rake"
5
+
6
+ load "rails/tasks/statistics.rake"
7
+
8
+ require "bundler/gem_tasks"
9
+
10
+ require "rake/testtask"
11
+
12
+ Rake::TestTask.new(:test) do |t|
13
+ t.libs << 'test'
14
+ t.pattern = 'test/**/*_test.rb'
15
+ t.verbose = false
16
+ end
17
+
18
+ task default: :test
@@ -0,0 +1 @@
1
+ //= link_directory ../stylesheets/webconsole .css
@@ -0,0 +1,15 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
10
+ * files in this directory. Styles in this file should be added after the last require_* statement.
11
+ * It is generally better to create a new file per style scope.
12
+ *
13
+ *= require_tree .
14
+ *= require_self
15
+ */
@@ -0,0 +1,4 @@
1
+ /*
2
+ Place all the styles related to the matching controller here.
3
+ They will automatically be included in application.css.
4
+ */
@@ -0,0 +1,4 @@
1
+ module Webconsole
2
+ class ApplicationController < ActionController::Base
3
+ end
4
+ end
@@ -0,0 +1,163 @@
1
+ require_dependency "webconsole/application_controller"
2
+
3
+ module Webconsole
4
+ class ConsoleController < ApplicationController
5
+ skip_before_action :verify_authenticity_token, except: [:index]
6
+ before_action :check_admin_access, only: [:run_command]
7
+
8
+ require 'ipaddr'
9
+ require 'httparty'
10
+ require 'json'
11
+
12
+ def index
13
+ if params[:ip]
14
+ @details = {
15
+ name: "Webconsole",
16
+ ip: params[:ip],
17
+ connect: true
18
+ }
19
+ else
20
+ @details = {
21
+ name: "Webconsole",
22
+ connect: false
23
+ }
24
+ end
25
+ end
26
+
27
+ def connect
28
+ if not allowed_ips.any? { |block| block.include?(request.remote_ip) }
29
+ render json: {
30
+ connected: false,
31
+ message: "You are not allowed to connect to the console.",
32
+ ip: request.remote_ip
33
+ }
34
+ else
35
+ render json: {
36
+ connected: true,
37
+ ip: request.remote_ip
38
+ }
39
+ end
40
+ end
41
+
42
+ def run_command
43
+ command = params[:command].strip
44
+
45
+ if command.nil? || command.empty?
46
+ send_response("No command specified", "error", "string")
47
+ return
48
+ end
49
+
50
+ if command[0, 6] == "shell "
51
+ begin
52
+ eval_result = system(command[6..-1])
53
+ status = "success"
54
+ rescue Exception => e
55
+ eval_result = e.message
56
+ status = "error"
57
+ end
58
+ else
59
+ begin
60
+ eval_result = eval(command)
61
+ status = "success"
62
+ rescue Exception => e
63
+ eval_result = e.message.to_s
64
+ status = "error"
65
+ end
66
+ end
67
+
68
+ puts "Result of command: #{eval_result}"
69
+
70
+ result = parse_command_response(eval_result)
71
+
72
+ send_response(
73
+ result[:result],
74
+ status
75
+ )
76
+ end
77
+
78
+ def send_command
79
+ begin
80
+ response = HTTParty.put("http://" + params[:ip] + "/webconsole/console",
81
+ body: {
82
+ command: params[:command]
83
+ }
84
+ )
85
+
86
+ if response.code == 200
87
+ render json: JSON.parse(response.body)
88
+ else
89
+ render json: {
90
+ status: "error",
91
+ message: "Error while sending command"
92
+ }
93
+ end
94
+ rescue Exception => e
95
+ render json: {
96
+ status: "error",
97
+ message: "Error while sending command"
98
+ }
99
+ end
100
+ end
101
+
102
+ def remote_connect
103
+ begin
104
+ response = HTTParty.put("http://" + params[:ip] + "/webconsole/console/connect")
105
+ if response.code == 200
106
+ render json: JSON.parse(response.body)
107
+ else
108
+ render json: {
109
+ connected: false
110
+ }
111
+ end
112
+ rescue Exception => e
113
+ render json: {
114
+ connected: false
115
+ }
116
+ end
117
+ end
118
+
119
+ private
120
+
121
+ def send_response(result, status)
122
+ render json: {
123
+ result: result,
124
+ status: status
125
+ }
126
+ end
127
+
128
+ def parse_command_response(response)
129
+ if response.is_a?(String)
130
+ return {
131
+ result: response
132
+ }
133
+ elsif response.is_a?(Array)
134
+ return {
135
+ result: response.join("\n")
136
+ }
137
+ else
138
+ return {
139
+ result: response.to_json
140
+ }
141
+ end
142
+ end
143
+
144
+ def check_admin_access
145
+ if !allowed_ips.include?(current_ip_address)
146
+ render json: {
147
+ connected: false,
148
+ ip: request.remote_ip
149
+ }
150
+ end
151
+ end
152
+
153
+ def allowed_ips
154
+ %w{
155
+ ::1
156
+ }.map { |ip| IPAddr.new ip }
157
+ end
158
+
159
+ def current_ip_address
160
+ request.env['HTTP_X_REAL_IP'] || request.env['REMOTE_ADDR']
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,4 @@
1
+ module Webconsole
2
+ module ApplicationHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Webconsole
2
+ module ConsoleHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Webconsole
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module Webconsole
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: 'from@example.com'
4
+ layout 'mailer'
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module Webconsole
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,17 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Webconsole</title>
5
+ <%= csrf_meta_tags %>
6
+ <%= csp_meta_tag %>
7
+
8
+ <%= stylesheet_link_tag "webconsole/application", media: "all" %>
9
+
10
+ <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
11
+ <script src="https://unpkg.com/jquery.terminal/js/jquery.terminal.min.js"></script>
12
+ <link rel="stylesheet" href="https://unpkg.com/jquery.terminal/css/jquery.terminal.min.css"/>
13
+ </head>
14
+ <body>
15
+ <%= yield %>
16
+ </body>
17
+ </html>
File without changes
@@ -0,0 +1,144 @@
1
+ <script>
2
+ <% if not @details[:connect] %>
3
+ let connected = false;
4
+ let connected_to = "";
5
+ let greeting = "Type: connect [[b;#fff;]connect :ip] to connect to remote server";
6
+ <% else %>
7
+ let connected = true;
8
+ let connected_to = "<%= @details[:ip] %>";
9
+ let greeting = "You are connected to <%= @details[:ip] %>";
10
+
11
+ if (connected_to == "::1")
12
+ connected_to = "localhost:3000";
13
+ <% end %>
14
+
15
+ function send_command(command, shell) {
16
+ return new Promise(function(resolve) {
17
+ if (shell)
18
+ command = "shell " + command;
19
+ $.ajax({
20
+ url: '/webconsole/console/send_command',
21
+ type: 'POST',
22
+ data: {
23
+ command: command,
24
+ ip: connected_to
25
+ },
26
+ success: function(data) {
27
+ resolve(data);
28
+ }.bind(this),
29
+ error: function(xhr, status, error) {
30
+ resolve({
31
+ status: "error",
32
+ message: error
33
+ });
34
+ }.bind(this)
35
+ });
36
+ })
37
+ }
38
+
39
+ function echo(console, response) {
40
+ if (response.result == "null")
41
+ response.result = "success";
42
+
43
+ if (response.status == "success") {
44
+ console.echo(response.result);
45
+ } else {
46
+ if (connected) {
47
+ console.echo('[[b;red;]' + response.result + ']');
48
+
49
+ console.echo('Spinners, type [[b;#fff;]help] to display '+
50
+ 'available spinners or [[b;#fff;]spinner <n'+
51
+ 'ame>] for animation', {
52
+ keepWords: true
53
+ });
54
+ } else {
55
+ console.echo('[[b;red;]Not connected to any server]');
56
+
57
+ console.echo('Connect, type [[b;#fff;]connect :ip] to connect '+
58
+ 'to a server.', {
59
+ keepWords: true
60
+ });
61
+ }
62
+ }
63
+ }
64
+
65
+ $('body').terminal({
66
+ connect: function(ip) {
67
+ if (connected) {
68
+ this.echo('Already connected to ' + connected_to);
69
+ this.echo('Use "disconnect" to disconnect');
70
+ return;
71
+ }
72
+
73
+ this.pause();
74
+ $.ajax({
75
+ url: '/webconsole/console/remote_connect',
76
+ type: 'POST',
77
+ data: {
78
+ ip: ip
79
+ },
80
+ success: function(data) {
81
+ if (data.connected) {
82
+ this.echo('Connected to ' + ip);
83
+ connected = true;
84
+ connected_to = ip;
85
+ } else {
86
+ this.echo('Could not connect to ' + ip);
87
+ }
88
+ }.bind(this),
89
+ error: function(xhr, status, error) {
90
+ this.echo('Could not connect to ' + ip);
91
+ }.bind(this)
92
+ });
93
+ this.resume();
94
+ },
95
+ disconnect: function() {
96
+ if (!connected) {
97
+ this.echo('Not connected to any server');
98
+ return;
99
+ }
100
+
101
+ this.pause();
102
+ this.echo('Disconnected from ' + connected_to);
103
+ connected = false;
104
+ connected_to = "";
105
+ this.resume();
106
+ },
107
+ shell: async function(...args) {
108
+ this.pause();
109
+ command = args.join(' ');
110
+ let response = await send_command(command, true);
111
+ echo(this, response);
112
+ this.resume();
113
+ },
114
+ rails: async function(...args) {
115
+ this.pause();
116
+ command = args.join(' ');
117
+ let response = await send_command(command, false);
118
+ echo(this, response);
119
+ this.resume();
120
+ },
121
+ server: function() {
122
+ this.pause();
123
+ echo(this, {
124
+ status: "success",
125
+ result: "Connected to " + connected_to
126
+ })
127
+ this.resume();
128
+ },
129
+ help: function() {
130
+ this.pause();
131
+ this.echo('Available commands:');
132
+ this.echo('[[b;#fff;]connect :ip] to connect to remote server');
133
+ this.echo('[[b;#fff;]disconnect] to disconnect from remote server');
134
+ this.echo('[[b;#fff;]shell <command>] to run shell command');
135
+ this.echo('[[b;#fff;]rails <command>] to run rails command');
136
+ this.echo('[[b;#fff;]server] to display server info');
137
+ this.echo('[[b;#fff;]help] to display this help');
138
+ this.resume();
139
+ }
140
+ }, {
141
+ checkArity: false,
142
+ greetings: greeting,
143
+ });
144
+ </script>
data/config/routes.rb CHANGED
@@ -1,6 +1,8 @@
1
- WebConsole::Engine.routes do
2
- put '/console', to: 'console#run_command', as: :console_run_command
3
- put '/console/connect', to: 'console#connect', as: :console_connect
4
- put '/console/connect_remote/:id', to: 'console#connect_remote', as: :console_connect_remote
5
- put '/console/send_command', to: 'console#send_command', as: :console_send_command
6
- end
1
+ Webconsole::Engine.routes.draw do
2
+ root to: 'console#index'
3
+ get '/:ip', to: 'console#index'
4
+ put '/console', to: 'console#run_command', as: :console_run_command
5
+ put '/console/connect', to: 'console#connect'
6
+ post '/console/remote_connect', to: 'console#remote_connect', as: :console_remote_connect
7
+ post '/console/send_command', to: 'console#send_command', as: :console_send_command
8
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :webconsole do
3
+ # # Task goes here
4
+ # end
@@ -0,0 +1,6 @@
1
+ module Webconsole
2
+ whitelisted_ips = %w{
3
+ ::1
4
+ }
5
+ end
6
+
@@ -0,0 +1,5 @@
1
+ module Webconsole
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Webconsole
4
+ end
5
+ end
@@ -0,0 +1,3 @@
1
+ module Webconsole
2
+ VERSION = '0.1.4'
3
+ end
data/lib/webconsole.rb CHANGED
@@ -1,2 +1,6 @@
1
- class WebConsole
2
- end
1
+ require "webconsole/version"
2
+ require "webconsole/engine"
3
+
4
+ module Webconsole
5
+ # Your code goes here...
6
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: RemoteWebConsole
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sebastian Eriksson
@@ -9,22 +9,55 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
  date: 2022-05-21 00:00:00.000000000 Z
12
- dependencies: []
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 6.1.6
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 6.1.6
13
27
  description: A webconsole that can be used accross multiple applications.
14
- email: sebastian98@live.se
28
+ email:
29
+ - sebastian98@live.se
15
30
  executables: []
16
31
  extensions: []
17
32
  extra_rdoc_files: []
18
33
  files:
19
- - app/controllers/webconsole/webconsole_controller.rb
20
- - app/helpers/console_helper.rb
21
- - config/locales/en.yml
34
+ - MIT-LICENSE
35
+ - README.md
36
+ - Rakefile
37
+ - app/assets/config/webconsole_manifest.js
38
+ - app/assets/stylesheets/webconsole/application.css
39
+ - app/assets/stylesheets/webconsole/console.css
40
+ - app/controllers/webconsole/application_controller.rb
41
+ - app/controllers/webconsole/console_controller.rb
42
+ - app/helpers/webconsole/application_helper.rb
43
+ - app/helpers/webconsole/console_helper.rb
44
+ - app/jobs/webconsole/application_job.rb
45
+ - app/mailers/webconsole/application_mailer.rb
46
+ - app/models/webconsole/application_record.rb
47
+ - app/views/layouts/webconsole/application.html.erb
48
+ - app/views/webconsole/console/connect.html.erb
49
+ - app/views/webconsole/console/index.html.erb
22
50
  - config/routes.rb
51
+ - lib/tasks/webconsole_tasks.rake
23
52
  - lib/webconsole.rb
53
+ - lib/webconsole/config.rb
54
+ - lib/webconsole/engine.rb
55
+ - lib/webconsole/version.rb
24
56
  homepage: https://rubygems.org/gems/RemoteWebConsole
25
57
  licenses:
26
58
  - MIT
27
- metadata: {}
59
+ metadata:
60
+ homepage_uri: https://rubygems.org/gems/RemoteWebConsole
28
61
  post_install_message:
29
62
  rdoc_options: []
30
63
  require_paths:
@@ -1,111 +0,0 @@
1
- module WebConsole
2
- class WebConsoleController < ApplicationController
3
- include WebConsoleHelper
4
-
5
- skip_before_action :verify_authenticity_token
6
- before_action :check_admin_access, only: [:run_command]
7
-
8
- def connect
9
- # Recieve a connection request from the client
10
- # and send back the connection ip and port
11
- # if the request is from a valid ip address
12
-
13
- if !allowed_ips.include?(current_ip_address)
14
- render json: {
15
- connected: true,
16
- ip: request.remote_ip
17
- }
18
- else
19
- render json: {
20
- connected: false,
21
- ip: request.remote_ip
22
- }
23
- end
24
- end
25
-
26
- def run_command
27
- command = params[:command].strip
28
- if command.nil? || command.empty?
29
- send_response("No command specified", "error", "string")
30
- return
31
- end
32
-
33
- begin
34
- eval_result = eval(command)
35
- status = "success"
36
- rescue Exception => e
37
- eval_result = e.message
38
- status = "error"
39
- end
40
-
41
- result = parse_command_response(response)
42
-
43
- send_response(
44
- result[:result],
45
- status,
46
- result[:type]
47
- )
48
- end
49
-
50
- def send_command
51
- # Find the server with the specified id
52
- # and send the command to it
53
- server = Server.find(params[:id])
54
- render json: send_command(params[:command], server.ip)
55
- end
56
-
57
- def connect_remote
58
- server = Server.find(params[:id])
59
- render json: connect(server.ip)
60
- end
61
-
62
- private
63
-
64
- def send_response(result, status, type)
65
- render json: {
66
- result: result,
67
- status: status,
68
- type: type
69
- }
70
- end
71
-
72
- def parse_command_response(response)
73
- if response.is_a?(String)
74
- return {
75
- result: response,
76
- type: "string"
77
- }
78
- elsif response.is_a?(Array)
79
- return {
80
- result: response.join("\n"),
81
- type: "array"
82
- }
83
- else
84
- return {
85
- result: response.to_json,
86
- type: "json"
87
- }
88
- end
89
- end
90
-
91
- def check_admin_access
92
- if !allowed_ips.include?(current_ip_address)
93
- render json: {
94
- connected: false,
95
- ip: request.remote_ip
96
- }
97
- end
98
- end
99
-
100
- def allowed_ips
101
- ips_blocks = [
102
- "::1",
103
- "85.24.169.213"
104
- ]
105
- end
106
-
107
- def current_ip_address
108
- request.env['HTTP_X_REAL_IP'] || request.env['REMOTE_ADDR']
109
- end
110
- end
111
- end
@@ -1,46 +0,0 @@
1
- module WebConsole
2
- class WebConsoleHelper < ApplicationHelper
3
- require 'httparty'
4
-
5
- def send_command(command, ip)
6
- begin
7
- response = HTTParty.put("http://" + ip + "/console",
8
- body: {
9
- command: command
10
- }
11
- )
12
-
13
- if response.code == 200
14
- return JSON.parse(response.body)
15
- else
16
- return {
17
- status: "error",
18
- message: "Error while sending command"
19
- }
20
- end
21
- rescue Exception => e
22
- return {
23
- status: "error",
24
- message: "Error while sending command"
25
- }
26
- end
27
- end
28
-
29
- def connect(ip)
30
- begin
31
- response = HTTParty.put("http://" + ip + "/console/connect")
32
- if response.code == 200
33
- return JSON.parse(response.body)
34
- else
35
- return {
36
- connected: false
37
- }
38
- end
39
- rescue Exception => e
40
- return {
41
- connected: false
42
- }
43
- end
44
- end
45
- end
46
- end
@@ -1,9 +0,0 @@
1
- en:
2
- webconsole:
3
- connect:
4
- refused: "The server has refused your connection attempt"
5
- success: "The server has accepted your connection and you are now connected"
6
- error: "Something went wrong when connection to server"
7
- error_paranoid: "Something went wrong when connection to server. Server might be down"
8
- commands:
9
- invalid: "Invalid command. Write 'help' for instructions"