RemoteWebConsole 0.1.3 → 0.1.4

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: 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"