Detailed Refactoring of Database Interaction

1. **Refactoring of Database Interaction Methods**
   - Refactored the `store_services` method in the `DatabaseManager` class to handle an array of services instead of a hash. This change was made to simplify the interaction with the database and to avoid unnecessary complexity in the data structure.
   - The `store_services` method now iterates over an array of services and inserts each service into the database with a default status of true. This design choice was made to ensure that all services are active by default.

2. **Modification of Database Schema**
   - Modified the `create_services_table` method in the `DatabaseManager` class to create a table with only two columns: `id` and `services`. This change was made to align the database schema with the new data structure used in the `store_services` method.
   - The `status` column was removed from the `services` table because the status of all services is now assumed to be true by default.

3. **Error Handling and Debugging**
   - Encountered a `Sequel::DatabaseError` with the message "Operand should contain 1 column(s)" during the execution of the `store_services` method. This error was caused by an attempt to insert a hash into a single database column.
   - The error was resolved by refactoring the `store_services` method to handle an array of services instead of a hash.

4. **Unorthodox Design Choices**
   - The decision to use an array of services instead of a hash and to assume that the status of all services is true by default may seem unorthodox. However, these design choices were made to simplify the interaction with the database and to avoid unnecessary complexity in the data structure.
   - These design choices also helped to resolve the `Sequel::DatabaseError` that was encountered during the execution of the `store_services` method.

This commit represents a significant refactoring of the database interaction methods in the NETRAVE project. The changes made in this commit have simplified the interaction with the database and have resolved a `Sequel::DatabaseError` that was encountered during the execution of the `store_services` method.
This commit is contained in:
VetheonGames 2023-06-09 19:39:54 -06:00
parent f96cf9e20a
commit 335cd89ebe
13 changed files with 304 additions and 407 deletions

View File

@ -1,14 +1,10 @@
# This is an example Rubocop configuration file with all cops enabled.
# AllCops section defines global settings.
AllCops:
Exclude:
- 'vendor/**/*' # Exclude vendor directory
- 'db/schema.rb' # Exclude database schema file
- 'db/migrate/**/*' # Exclude database migration files
# Enables all cops.
# Set the value to `true` or `false` to enable/disable all cops.
# You can also enable/disable specific cops individually.
# By default, all cops are enabled.
inherit_from: .rubocop_todo.yml
# The behavior of RuboCop can be controlled via the .rubocop.yml
# configuration file. It makes it possible to enable/disable
# certain cops (checks) and to alter their behavior if they accept
# any parameters. The file can be placed either in your home
# directory or in some project directory.
#
# RuboCop will start looking for the configuration file in the directory
# where the inspected file is and continue its way up to the root directory.
#
# See https://docs.rubocop.org/rubocop/configuration

View File

@ -1,217 +0,0 @@
# This configuration was generated by
# `rubocop --auto-gen-config --exclude-limit 1000`
# on 2023-06-07 19:34:17 UTC using RuboCop version 1.52.0.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: TreatCommentsAsGroupSeparators, ConsiderPunctuation, Include.
# Include: **/*.gemfile, **/Gemfile, **/gems.rb
Bundler/OrderedGems:
Exclude:
- 'lib/Gemfile'
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyleAlignWith, Severity.
# SupportedStylesAlignWith: keyword, variable, start_of_line
Layout/EndAlignment:
Exclude:
- 'lib/utils/utilities.rb'
# Offense count: 3
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: Width, AllowedPatterns.
Layout/IndentationWidth:
Exclude:
- 'lib/utils/utilities.rb'
# Offense count: 8
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: final_newline, final_blank_line
Layout/TrailingEmptyLines:
Exclude:
- 'Modules/advanced_logger.rb'
- 'Modules/firewall_manager.rb'
- 'Modules/nftables_interface.rb'
- 'Modules/packet_manager.rb'
- 'Modules/protection_engine.rb'
- 'lib/utils/database_manager.rb'
- 'lib/utils/system_information_gather.rb'
- 'lib/utils/utilities.rb'
# Offense count: 9
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowInHeredoc.
Layout/TrailingWhitespace:
Exclude:
- 'lib/utils/database_manager.rb'
- 'lib/utils/first_run_init.rb'
- 'lib/utils/system_information_gather.rb'
- 'lib/utils/utilities.rb'
# Offense count: 1
# Configuration parameters: AllowComments.
Lint/EmptyFile:
Exclude:
- 'TUI/main_tui.rb'
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
Lint/ScriptPermission:
Exclude:
- 'bin/NETRAVE'
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods.
Lint/UnusedMethodArgument:
Exclude:
- 'lib/utils/system_information_gather.rb'
# Offense count: 5
# Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes.
Metrics/AbcSize:
Max: 20
# Offense count: 8
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
Metrics/MethodLength:
Max: 19
# Offense count: 1
# Configuration parameters: AllowedNames.
# AllowedNames: module_parent
Naming/ClassAndModuleCamelCase:
Exclude:
- 'lib/utils/GUI_launcher.rb'
# Offense count: 1
# Configuration parameters: ExpectMatchingDefinition, CheckDefinitionPathHierarchy, CheckDefinitionPathHierarchyRoots, Regex, IgnoreExecutableScripts, AllowedAcronyms.
# CheckDefinitionPathHierarchyRoots: lib, spec, test, src
# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS
Naming/FileName:
Exclude:
- 'lib/utils/GUI_launcher.rb'
# Offense count: 2
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: always, conditionals
Style/AndOr:
Exclude:
- 'lib/utils/GUI_launcher.rb'
# Offense count: 5
# Configuration parameters: AllowedConstants.
Style/Documentation:
Exclude:
- 'spec/**/*'
- 'test/**/*'
- 'lib/utils/GUI_launcher.rb'
- 'lib/utils/database_manager.rb'
- 'lib/utils/first_run_init.rb'
- 'lib/utils/system_information_gather.rb'
- 'lib/utils/utilities.rb'
# Offense count: 11
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: EnforcedStyle.
# SupportedStyles: always, always_true, never
Style/FrozenStringLiteralComment:
Exclude:
- 'Modules/advanced_logger.rb'
- 'Modules/firewall_manager.rb'
- 'Modules/nftables_interface.rb'
- 'Modules/packet_manager.rb'
- 'Modules/protection_engine.rb'
- 'bin/NETRAVE'
- 'lib/utils/GUI_launcher.rb'
- 'lib/utils/database_manager.rb'
- 'lib/utils/first_run_init.rb'
- 'lib/utils/system_information_gather.rb'
- 'lib/utils/utilities.rb'
# Offense count: 4
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: MinBodyLength, AllowConsecutiveConditionals.
Style/GuardClause:
Exclude:
- 'lib/utils/first_run_init.rb'
- 'lib/utils/system_information_gather.rb'
# Offense count: 4
# This cop supports unsafe autocorrection (--autocorrect-all).
Style/InfiniteLoop:
Exclude:
- 'lib/utils/first_run_init.rb'
- 'lib/utils/system_information_gather.rb'
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
Style/NegatedWhile:
Exclude:
- 'lib/utils/first_run_init.rb'
# Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: EnforcedStyle, AllowedMethods, AllowedPatterns.
# SupportedStyles: predicate, comparison
Style/NumericPredicate:
Exclude:
- 'spec/**/*'
- 'lib/utils/system_information_gather.rb'
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
Style/RedundantBegin:
Exclude:
- 'lib/utils/database_manager.rb'
# Offense count: 9
# This cop supports safe autocorrection (--autocorrect).
Style/RedundantFileExtensionInRequire:
Exclude:
- 'bin/NETRAVE'
- 'lib/utils/database_manager.rb'
- 'lib/utils/first_run_init.rb'
- 'lib/utils/system_information_gather.rb'
# Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods, MaxChainLength.
# AllowedMethods: present?, blank?, presence, try, try!
Style/SafeNavigation:
Exclude:
- 'lib/utils/database_manager.rb'
# Offense count: 40
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
# SupportedStyles: single_quotes, double_quotes
Style/StringLiterals:
Exclude:
- 'bin/NETRAVE'
- 'lib/Gemfile'
- 'lib/utils/GUI_launcher.rb'
- 'lib/utils/database_manager.rb'
- 'lib/utils/first_run_init.rb'
- 'lib/utils/system_information_gather.rb'
# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: MinSize, WordRegex.
# SupportedStyles: percent, brackets
Style/WordArray:
EnforcedStyle: brackets
# Offense count: 6
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
# URISchemes: http, https
Layout/LineLength:
Max: 239

View File

@ -1 +1 @@
3.0.5
3.2.2

View File

@ -1,3 +1,5 @@
{
"ruby.rubocop.autocorrectOnSave": true
"ruby.rubocop.autocorrectOnSave": true,
"ruby.rubocop.configFilePath": "/home/vetheon/VSCode/NETRAVE/.rubocop.yml",
"ruby.rubocop.executePath": "/home/vetheon/.rbenv/shims/"
}

View File

@ -1,31 +1,63 @@
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'yaml'
require_relative '../lib/utils/system_information_gather.rb'
require_relative '../lib/utils/database_manager.rb'
require_relative '../lib/utils/first_run_init.rb'
require 'dotenv'
require_relative '../lib/utils/system_information_gather'
require_relative '../lib/utils/database_manager'
require_relative '../lib/utils/first_run_init'
require_relative '../lib/utils/utilities'
# Check if config.yml exists, if not, create it
unless File.exist?('config.yml')
first_run_init = FirstRunInit.new
db_details = first_run_init.ask_for_db_details
first_run_init.write_db_details_to_config_file(db_details)
include Utilities # rubocop:disable Style/MixinUsage
# Create .env file if it doesn't exist
File.new('.env', 'w') unless File.exist?('.env')
# Load environment variables from .env file
Dotenv.load
# Initialize DatabaseManager
db_manager = DatabaseManager.new
# Get database details from environment variables
db_details = {
username: ENV['DB_USERNAME'],
password: ENV['DB_PASSWORD'],
key: ENV['DB_SECRET_KEY'],
database: ENV['DB_DATABASE']
}
# If any of the necessary details are missing, run the first run setup
if db_details.values.any?(&:nil?)
puts 'Missing or incomplete configuration. Running first run setup.'
first_run_init = FirstRunInit.new(db_manager)
first_run_init.run
# Reload environment variables after first run setup
Dotenv.load
db_details = {
username: ENV['DB_USERNAME'],
password: ENV['DB_PASSWORD'],
key: ENV['DB_SECRET_KEY'],
database: ENV['DB_DATABASE']
}
end
# Load database configuration
db_details = YAML.load_file('config.yml')
# Decrypt the password
db_details[:password] = decrypt_string_chacha20(db_details[:password], db_details[:key])
# Initialize DatabaseManager and test connection
db_manager = DatabaseManager.new
# Test connection
unless db_manager.test_db_connection(db_details)
puts 'Failed to connect to the database with existing configuration. Please re-enter your details.'
first_run_init = FirstRunInit.new(db_manager)
first_run_init.run
end
# Test connection again after potentially updating config
if db_manager.test_db_connection(db_details)
puts "Successfully connected to the database."
puts 'Successfully connected to the database.'
else
puts "Failed to connect to the database. Please check your configuration."
puts 'Failed to connect to the database. Please check your configuration.'
exit 1
end
# Initialize the first run setup
first_run_setup = FirstRunInit.new(db_manager)
first_run_setup.run
puts 'Program successfully ran with no errors'
# TODO: Add the rest of your application logic here

0
lib/.env Normal file
View File

View File

@ -1,22 +1,32 @@
# frozen_string_literal: true
source "https://rubygems.org"
source 'https://rubygems.org'
# gem "rails"
gem "curses", "~> 1.4"
gem 'console'
gem 'curses', '~> 1.4'
gem "rubocop", "~> 1.52"
gem 'rubocop', '~> 1.52'
gem "solargraph", "~> 0.49.0"
gem 'solargraph', '~> 0.49.0'
gem "sequel", "~> 5.69"
gem 'sequel', '~> 5.69'
gem "mysql2", "~> 0.5.5"
gem 'mysql2', '~> 0.5.5'
gem "yaml", "~> 0.2.1"
gem 'yaml', '~> 0.2.1'
gem "gtk3", "~> 4.1"
gem 'gtk3', '~> 4.1'
gem "reek", "~> 6.1"
gem 'reek', '~> 6.1'
gem 'dynamic_curses_input', '~> 1.0'
gem 'openssl', '~> 3.1'
gem 'base64', '~> 0.1.1'
gem 'securerandom', '~> 0.2.2'
gem 'dotenv', '~> 2.8'

View File

@ -5,6 +5,7 @@ GEM
atk (4.1.7)
glib2 (= 4.1.7)
backport (1.2.0)
base64 (0.1.1)
benchmark (0.2.1)
cairo (1.17.8)
native-package-installer (>= 1.0.3)
@ -13,11 +14,16 @@ GEM
cairo-gobject (4.1.7)
cairo (>= 1.16.2)
glib2 (= 4.1.7)
console (1.16.2)
console (1.17.2)
fiber-annotation
fiber-local
curses (1.4.4)
diff-lcs (1.5.0)
dotenv (2.8.1)
dynamic_curses_input (1.0.0)
curses
e2mmap (0.1.0)
fiber-annotation (0.2.0)
fiber-local (1.0.0)
fiddle (1.1.1)
gdk3 (4.1.7)
@ -49,14 +55,16 @@ GEM
native-package-installer (1.1.5)
nokogiri (1.15.2-x86_64-linux)
racc (~> 1.4)
openssl (3.1.0)
pango (4.1.7)
cairo-gobject (= 4.1.7)
gobject-introspection (= 4.1.7)
parallel (1.23.0)
parser (3.2.2.1)
parser (3.2.2.3)
ast (~> 2.4.1)
racc
pkg-config (1.5.1)
racc (1.6.2)
racc (1.7.0)
rainbow (3.1.1)
rbs (2.8.4)
red-colors (0.3.0)
@ -82,6 +90,7 @@ GEM
rubocop-ast (1.29.0)
parser (>= 3.2.1.0)
ruby-progressbar (1.13.0)
securerandom (0.2.2)
sequel (5.69.0)
solargraph (0.49.0)
backport (~> 1.2)
@ -100,7 +109,7 @@ GEM
tilt (~> 2.0)
yard (~> 0.9, >= 0.9.24)
thor (1.2.2)
tilt (2.1.0)
tilt (2.2.0)
unicode-display_width (2.4.2)
yaml (0.2.1)
yard (0.9.34)
@ -109,12 +118,17 @@ PLATFORMS
x86_64-linux
DEPENDENCIES
base64 (~> 0.1.1)
console
curses (~> 1.4)
dotenv (~> 2.8)
dynamic_curses_input (~> 1.0)
gtk3 (~> 4.1)
mysql2 (~> 0.5.5)
openssl (~> 3.1)
reek (~> 6.1)
rubocop (~> 1.52)
securerandom (~> 0.2.2)
sequel (~> 5.69)
solargraph (~> 0.49.0)
yaml (~> 0.2.1)

View File

@ -1,14 +1,15 @@
require 'gtk3'
class GUI_Launcher
def initialize
@app = Gtk::Application.new("com.netrave.gui", :flags_none)
# GUI launcher
class GUILauncher
def initialize # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
@app = Gtk::Application.new('com.netrave.gui', :flags_none)
@app.signal_connect "activate" do |application|
@app.signal_connect 'activate' do |application|
builder = Gtk::Builder.new
builder.add_from_file("./Glade/NETRAVE.glade")
builder.add_from_file('./Glade/NETRAVE.glade')
window = builder.get_object("main_window")
window = builder.get_object('main_window')
window.application = application
screen = Gdk::Screen.default
@ -31,7 +32,7 @@ class GUI_Launcher
end
def run
puts "Launching GUI..."
puts 'Launching GUI...'
@app.run
end
end

View File

@ -1,25 +1,30 @@
# frozen_string_literal: true
require 'sequel'
require 'mysql2'
require_relative 'system_information_gather.rb'
require_relative 'system_information_gather'
require_relative '../utils/utilities'
# database manager
class DatabaseManager
include Utilities
def initialize
@db = nil
end
def test_db_connection(db_details)
begin
connection_string = "mysql2://#{db_details[:username]}:#{db_details[:password]}@localhost/#{db_details[:database]}"
# Decrypt the password before using it
decrypted_password = decrypt_string_chacha20(db_details[:password], db_details[:key])
connection_string = "mysql2://#{db_details[:username]}:#{decrypted_password}@localhost/#{db_details[:database]}"
@db = Sequel.connect(connection_string)
# Try a simple query to test the connection
@db.run "SELECT 1"
@db.run 'SELECT 1'
true
rescue Sequel::DatabaseConnectionError
false
ensure
@db.disconnect if @db
end
@db&.disconnect
end
def create_system_info_table
@ -27,7 +32,7 @@ class DatabaseManager
primary_key :id
Integer :uplink_speed
Integer :downlink_speed
String :services, text: true
Integer :total_bandwidth
end
end
@ -36,16 +41,16 @@ class DatabaseManager
end
def create_services_table
@db.create_table :services do
@db.create_table? :services do
primary_key :id
String :service_name
Boolean :status
TrueClass :status, default: true
end
end
def store_services(services)
services.each do |service, status|
@db[:services].insert(service_name: service, status: status)
services.each do |service|
@db[:services].insert(service_name: service, status: true)
end
end
end

View File

@ -1,13 +1,19 @@
require 'curses'
require_relative 'database_manager.rb'
require_relative 'system_information_gather.rb'
require_relative 'utilities.rb'
# frozen_string_literal: true
require 'curses'
require 'dynamic_curses_input'
require 'dotenv'
require_relative 'database_manager'
require_relative 'system_information_gather'
require_relative 'utilities'
# first run class
class FirstRunInit
include Utilities
include Curses
def initialize(db_manager)
@db_manager = db_manager
def initialize(db_manager = nil)
@db_manager = db_manager || DatabaseManager.new
@info_gatherer = SystemInformationGather.new(@db_manager)
end
@ -15,70 +21,88 @@ class FirstRunInit
first_run_setup
end
def first_run_setup
def first_run_setup # rubocop:disable Metrics/MethodLength
db_details = ask_for_db_details
while !@db_manager.test_db_connection(db_details)
until @db_manager.test_db_connection(db_details)
Curses.setpos(4, 0)
Curses.addstr("Whoops! We couldn't connect to the database with the details you provided. Please try again!")
Curses.refresh
db_details = ask_for_db_details
end
@db_manager.create_system_info_table
@db_manager.create_services_table
uplink_speed = @info_gatherer.ask_for_uplink_speed
@db_manager.store_system_info(uplink_speed)
downlink_speed = @info_gatherer.ask_for_downlink_speed
@db_manager.store_system_info(downlink_speed)
total_bandwidth = calculate_total_bandwidth(uplink_speed, downlink_speed)
@db_manager.store_system_info(total_bandwidth)
services = @info_gatherer.ask_for_services
@db_manager.store_system_info(services)
system_info = {
uplink_speed:,
downlink_speed:,
total_bandwidth:
}
@db_manager.store_system_info(system_info)
@db_manager.store_services(services)
end
def ask_for_db_details
def ask_for_db_details # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
Curses.clear
Curses.setpos(1, 0)
Curses.addstr("Please enter your database username: ")
Curses.addstr('Please enter your database username: ')
Curses.refresh
username = Curses.getstr.strip
username = DCI.catch_input(true)
Curses.setpos(2, 0)
Curses.addstr("Please enter your database password: ")
Curses.addstr('Please enter your database password: ')
Curses.refresh
Curses.noecho
password = Curses.getstr.strip
password = DCI.catch_input(false)
Curses.echo
Curses.setpos(3, 0)
Curses.addstr("Please enter your database name: ")
Curses.addstr('Please enter your database name: ')
Curses.refresh
database = Curses.getstr.strip
database = DCI.catch_input(true)
{ username: username, password: password, database: database }
# Generate a secret key
key = generate_key
# Encrypt the password
encrypted_password = encrypt_string_chacha20(password, key)
{ username:, password: encrypted_password, key:, database: }
end
def write_db_details_to_config_file(db_details)
File.open("config.yml", "w") do |file|
file.write(db_details.to_yaml)
# Write the database details to the .env file
File.open('.env', 'w') do |file|
file.puts "DB_USERNAME=#{db_details[:username]}"
file.puts "DB_PASSWORD=#{db_details[:password]}"
file.puts "DB_SECRET_KEY=#{db_details[:key]}"
file.puts "DB_DATABASE=#{db_details[:database]}"
end
end
def ask_for_default_mode
while true
loop do
Curses.setpos(8, 0)
Curses.addstr("Please enter the default mode (TUI, GUI, or WebApp): ")
Curses.addstr('Please enter the default mode (TUI, GUI, or WebApp): ')
Curses.refresh
mode = Curses.getstr.strip.downcase
if valid_mode?(mode)
return mode
else
return mode if valid_mode?(mode)
Curses.setpos(9, 0)
Curses.addstr("Whoops! That didn't appear to be a valid mode. Please try again!")
Curses.refresh
end
end
end
def valid_mode?(mode)
['tui', 'gui', 'webapp'].include?(mode)
%w[tui gui webapp].include?(mode)
end
end

View File

@ -1,8 +1,10 @@
require 'curses'
require 'yaml'
require_relative 'utilities.rb'
require_relative 'database_manager.rb'
require_relative 'utilities'
require_relative 'database_manager'
require 'dynamic_curses_input'
# gather system info
class SystemInformationGather
include Utilities
@ -10,7 +12,7 @@ class SystemInformationGather
@db_manager = db_manager
end
def gather_system_info
def gather_system_info # rubocop:disable Metrics/MethodLength
uplink_speed = ask_for_uplink_speed
downlink_speed = ask_for_downlink_speed
services = ask_for_services
@ -18,9 +20,9 @@ class SystemInformationGather
total_bandwidth = uplink_speed + downlink_speed
system_info = {
uplink_speed: uplink_speed,
downlink_speed: downlink_speed,
total_bandwidth: total_bandwidth
uplink_speed:,
downlink_speed:,
total_bandwidth:
}
# Check if the system_info table exists, if not, create it
@ -36,79 +38,67 @@ class SystemInformationGather
@db_manager.store_services(services)
end
def ask_for_uplink_speed
while true
def ask_for_uplink_speed # rubocop:disable Metrics/MethodLength
Curses.clear
Curses.setpos(2, 0)
Curses.addstr("Please enter your uplink speed (upload speed, e.g., 1000Mbps or 1Gbps). ")
Curses.addstr("This is typically the maximum upload speed provided by your ISP. ")
Curses.addstr("You can check your ISP bill, use an online speed test, or contact your ISP if you're unsure. ")
Curses.addstr(" ")
Curses.setpos(5, 0)
Curses.addstr("Uplink Speed: ")
Curses.addstr("Please enter your uplink speed (upload speed, e.g., 1000Mbps or 1Gbps).\n" \
"This is typically the maximum upload speed provided by your ISP.\n" \
"You can check your ISP bill, use an online speed test, or contact your ISP if you're unsure.\n\n")
Curses.refresh
speed = Curses.getstr.strip.downcase
Curses.addstr('Uplink Speed: ')
speed = DCI.catch_input(true)
if valid_speed?(speed)
return speed.end_with?('gbps') ? convert_speed_to_mbps(speed) : speed.to_i
speed.end_with?('gbps') ? convert_speed_to_mbps(speed) : speed.to_i
else
Curses.setpos(5, 0)
Curses.addstr("Whoops! That didn't appear to be a valid speed. Please try again!")
Curses.refresh
end
ask_for_uplink_speed
end
end
def ask_for_downlink_speed
while true
def ask_for_downlink_speed # rubocop:disable Metrics/MethodLength
Curses.clear
Curses.setpos(2, 0)
Curses.addstr("Please enter your downlink speed (download speed, e.g., 1000Mbps or 1Gbps). ")
Curses.addstr("This is typically the maximum download speed provided by your ISP. ")
Curses.addstr("You can check your ISP bill, use an online speed test, or contact your ISP if you're unsure. ")
Curses.setpos(5, 0)
Curses.addstr("Downlink Speed: ")
Curses.addstr("Please enter your downlink speed (download speed, e.g., 1000Mbps or 1Gbps).\n" \
"This is typically the maximum download speed provided by your ISP.\n"\
"You can check your ISP bill, use an online speed test, or contact your ISP if you're unsure.\n\n")
Curses.refresh
speed = Curses.getstr.strip.downcase
Curses.addstr('Downlink Speed: ')
speed = DCI.catch_input(true)
if valid_speed?(speed)
return speed.end_with?('gbps') ? convert_speed_to_mbps(speed) : speed.to_i
speed.end_with?('gbps') ? convert_speed_to_mbps(speed) : speed.to_i
else
Curses.setpos(5, 0)
Curses.addstr("Whoops! That didn't appear to be a valid speed. Please try again!")
Curses.refresh
end
ask_for_downlink_speed
end
end
def valid_speed?(speed)
speed.to_i > 0
speed.to_i.positive?
end
def ask_for_services
while true
def ask_for_services # rubocop:disable Metrics/MethodLength
Curses.clear
Curses.setpos(6, 0)
Curses.addstr("Please enter the services the system should be aware of (e.g., webserver, database). ")
Curses.addstr("Enter the services as a comma-separated list (e.g., webserver,database). ")
Curses.addstr("Please enter the services the system should be aware of (e.g., webserver or database).\n" \
"Enter the services as a comma-separated list (e.g., webserver,database).\n\n")
Curses.refresh
services = Curses.getstr.strip.downcase.split(',').map(&:strip)
if valid_services?(services)
return services_to_hash(services)
Curses.addstr('Services: ')
services = DCI.catch_input(true)
services_arr = services.strip.downcase.split(',').map(&:strip)
if valid_services?(services_arr)
services_arr # return the array of services directly
else
Curses.setpos(7, 0)
Curses.addstr("Whoops! That didn't appear to be a valid list of services. Please try again!")
Curses.refresh
end
ask_for_services
end
end
def valid_services?(services)
def valid_services?(_services)
# TODO: Validate the services
true
end
def services_to_hash(services)
services_hash = {}
services.each { |service| services_hash[service] = true }
services_hash
end
end

View File

@ -1,6 +1,14 @@
# frozen_string_literal: true
require 'securerandom'
require 'digest'
require 'base64'
require 'openssl'
# Utiltiies Module
module Utilities
# Converts speed from Gbps to Mbps if necessary
def self.convert_speed_to_mbps(speed)
def convert_speed_to_mbps(speed)
if speed.end_with?('gbps')
speed.to_i * 1000
else
@ -9,14 +17,46 @@ module Utilities
end
# Converts an array of services into a hash
def self.services_to_hash(services)
def services_to_hash(services)
services_hash = {}
services.each { |service| services_hash[service] = true }
services_hash
end
# Calculates total bandwidth from uplink and downlink speeds
def self.calculate_total_bandwidth(uplink_speed, downlink_speed)
def calculate_total_bandwidth(uplink_speed, downlink_speed)
uplink_speed + downlink_speed
end
def generate_key
Base64.encode64(SecureRandom.bytes(32)).chomp
end
def encrypt_string_chacha20(string, key)
cipher = OpenSSL::Cipher.new('chacha20')
cipher.encrypt
cipher.key = Base64.decode64(key)
encrypted = cipher.update(string) + cipher.final
Base64.encode64(encrypted).chomp
end
def decrypt_string_chacha20(encrypted_string, key)
decipher = OpenSSL::Cipher.new('chacha20')
decipher.decrypt
decipher.key = Base64.decode64(key)
decrypted = Base64.decode64(encrypted_string)
decipher.update(decrypted) + decipher.final
end
# Encrypts a given data object using Blowfish and returns the encrypted string
def encrypt_data_blowfish(data, key)
plain_text = YAML.dump(data)
encrypt_string_blowfish(plain_text, key)
end
# Decrypts a given encrypted string using Blowfish and returns the original data object
def decrypt_data_blowfish(encrypted_text, key)
plain_text = decrypt_string_blowfish(encrypted_text, key)
YAML.load(plain_text)
end
end