From 6319c9c238a234c70fcd41f6f1d33ea888880d3f Mon Sep 17 00:00:00 2001 From: VetheonGames Date: Sun, 4 Jun 2023 14:41:12 -0600 Subject: [PATCH] Refactoring for Modularity, Code Reuse, and Security Considerations In this commit, we have undertaken a significant refactoring of the codebase to improve modularity, promote code reuse, and consider security aspects. Modularity and Code Reuse: We introduced classes and modules to better organize the code and facilitate code reuse. Specifically, we created a new Utilities module to hold common methods that are used across different parts of the application. This module includes methods such as convert_speed_to_mbps, services_to_hash, and calculate_total_bandwidth. By placing these methods in a module, we can include this module in any class that needs these methods, thereby promoting code reuse and reducing duplication. We also created two new classes, SystemInformationGather and DatabaseManager. The SystemInformationGather class is responsible for gathering system information, such as uplink and downlink speed, and services. The DatabaseManager class handles database operations, including testing the database connection, creating the system information table, and storing system information in the database. By encapsulating these responsibilities within their respective classes, we have made the code more organized and easier to maintain. Database Connection Details: We made a decision to store the database connection details in a config file (config.yml) instead of the database itself. This decision was made for security reasons, as storing these details in the database could expose them to potential security risks. Storing these details in a config file allows us to better control access to these details. Database Encryption: We discussed the possibility of encrypting the database for additional security. While we have not implemented this feature in this commit, we have laid the groundwork for it by discussing potential libraries/gems that could be used for this purpose. This is an area that we will revisit in the future. System Information Gathering: We wrote methods to gather system information, such as uplink and downlink speed, and services, and store this information in the database. This information will be useful for monitoring system performance and for making decisions about resource allocation. This refactoring effort has made the codebase more organized, easier to maintain, and more secure. It also aligns with our project goals and roadmap. However, it's important to note that with any refactoring effort, there may be potential issues or trade-offs. We will need to thoroughly test the refactored code to ensure that it works as expected and that there are no unintended side effects. --- TUI/First_run_tui.rb | 37 ---------- TUI/main_tui.rb | 0 bin/NETRAVE | 44 ++++++------ lib/Gemfile | 2 + lib/Gemfile.lock | 2 + lib/utils/database_manager.rb | 54 ++++++++++----- lib/utils/first_run_init.rb | 93 ++++++++++++-------------- lib/utils/system_information_gather.rb | 36 ++++++---- lib/utils/utilities.rb | 22 ++++++ 9 files changed, 153 insertions(+), 137 deletions(-) delete mode 100644 TUI/First_run_tui.rb create mode 100644 TUI/main_tui.rb create mode 100644 lib/utils/utilities.rb diff --git a/TUI/First_run_tui.rb b/TUI/First_run_tui.rb deleted file mode 100644 index b9f1ffd..0000000 --- a/TUI/First_run_tui.rb +++ /dev/null @@ -1,37 +0,0 @@ -require 'curses' - -def init_screen - Curses.init_screen - Curses.start_color - # Define color pairs - Curses.init_pair(1, Curses::COLOR_WHITE, Curses::COLOR_BLUE) # Default - Curses.init_pair(2, Curses::COLOR_RED, Curses::COLOR_BLUE) # Alert - Curses.init_pair(3, Curses::COLOR_BLACK, Curses::COLOR_RED) # Emergent Alert -end - -def first_run_setup - # Ask for preferred color - # TODO: Implement function to ask for color - - # Ask for uplink speed - # TODO: Implement function to ask for uplink speed - - # Ask for total bandwidth - # TODO: Implement function to ask for total bandwidth - - # Ask for services the system should be aware of - # TODO: Implement function to ask for services - - # Ask for default mode - # TODO: Implement function to ask for default mode -end - -def main - init_screen - first_run_setup - # TODO: Implement the rest of the program -ensure - Curses.close_screen -end - -main \ No newline at end of file diff --git a/TUI/main_tui.rb b/TUI/main_tui.rb new file mode 100644 index 0000000..e69de29 diff --git a/bin/NETRAVE b/bin/NETRAVE index 397aab9..370fa9b 100644 --- a/bin/NETRAVE +++ b/bin/NETRAVE @@ -1,24 +1,24 @@ -#!/usr/bin/env bash +#!/usr/bin/env ruby -# Prompt the user to choose the mode using dialog -MODE=$(dialog --backtitle "NETRAVE Mode Selection" --title "Select Mode" --menu "Choose the mode to start NETRAVE:" 12 50 4 1 "CLI" 2 "GUI" 3 "WebApp" 2>&1 >/dev/tty) +# Require necessary files +require_relative '../lib/utils/system_information_gather.rb' +require_relative '../lib/utils/database_manager.rb' +require_relative '../lib/utils/first_run_init.rb' -# Execute different commands based on the selected mode -case $MODE in - 1) - # CLI mode - ruby ./lib/NETRAVE.rb cli - ;; - 2) - # GUI mode - ruby ./lib/NETRAVE.rb gui - ;; - 3) - # WebApp mode - ruby ./lib/NETRAVE.rb webapp - ;; - *) - # Invalid selection or canceled - echo "Invalid selection or canceled." - ;; -esac +# Load database configuration +db_details = YAML.load_file('config.yml') + +# Initialize DatabaseManager and test connection +db_manager = DatabaseManager.new +if db_manager.test_db_connection(db_details) + puts "Successfully connected to the database." +else + puts "Failed to connect to the database. Please check your configuration." + exit 1 +end + +# Initialize the first run setup +first_run_setup = FirstRunSetup.new(db_manager) +first_run_setup.run + +# TODO: Add the rest of your application logic here diff --git a/lib/Gemfile b/lib/Gemfile index 5bae36e..896e437 100644 --- a/lib/Gemfile +++ b/lib/Gemfile @@ -14,3 +14,5 @@ gem "solargraph", "~> 0.49.0" gem "sequel", "~> 5.69" gem "mysql2", "~> 0.5.5" + +gem "yaml", "~> 0.2.1" diff --git a/lib/Gemfile.lock b/lib/Gemfile.lock index 4da02b9..a6cb3ab 100644 --- a/lib/Gemfile.lock +++ b/lib/Gemfile.lock @@ -62,6 +62,7 @@ GEM thor (1.2.2) tilt (2.1.0) unicode-display_width (2.4.2) + yaml (0.2.1) yard (0.9.34) PLATFORMS @@ -74,6 +75,7 @@ DEPENDENCIES rubocop (~> 1.52) sequel (~> 5.69) solargraph (~> 0.49.0) + yaml (~> 0.2.1) BUNDLED WITH 2.4.13 diff --git a/lib/utils/database_manager.rb b/lib/utils/database_manager.rb index 95ef61f..c18eb35 100644 --- a/lib/utils/database_manager.rb +++ b/lib/utils/database_manager.rb @@ -1,20 +1,40 @@ +require_relative 'system_information_gather.rb' +require_relative '../utils/utilities' + class DatabaseManager - 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]}" - @db = Sequel.connect(connection_string) - # Try a simple query to test the connection - @db.run "SELECT 1" - true - rescue Sequel::DatabaseConnectionError - false - ensure - @db.disconnect if @db - end + def initialize + @db = nil + @info_gatherer = SystemInformationGather.new + end + + def test_db_connection(db_details) + begin + connection_string = "mysql2://#{db_details[:username]}:#{db_details[:password]}@localhost/#{db_details[:database]}" + @db = Sequel.connect(connection_string) + # Try a simple query to test the connection + @db.run "SELECT 1" + true + rescue Sequel::DatabaseConnectionError + false + ensure + @db.disconnect if @db end end - \ No newline at end of file + + def create_system_info_table + @db.create_table? :system_info do + primary_key :id + Integer :uplink_speed + Integer :downlink_speed + String :services, text: true + end + end + + def store_system_info + system_info = @info_gatherer.gather_system_info + system_info[:uplink_speed] = Utilities.convert_speed_to_mbps(system_info[:uplink_speed]) + system_info[:downlink_speed] = Utilities.convert_speed_to_mbps(system_info[:downlink_speed]) + system_info[:services] = Utilities.services_to_hash(system_info[:services]) + @db[:system_info].insert(system_info) + end +end \ No newline at end of file diff --git a/lib/utils/first_run_init.rb b/lib/utils/first_run_init.rb index ad10b14..36b7fb7 100644 --- a/lib/utils/first_run_init.rb +++ b/lib/utils/first_run_init.rb @@ -1,59 +1,54 @@ require 'curses' +require_relative 'database_manager.rb' +require_relative 'system_information_gather.rb' +require_relative 'utilities.rb' -def first_run_setup - color = ask_for_color - # TODO: Use the color for something - db_details = ask_for_db_details - while !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 +class FirstRunInit + include Utilities + + def initialize + @db_manager = DatabaseManager.new + @info_gatherer = SystemInformationGather.new end - uplink_speed = ask_for_uplink_speed - # TODO: Use the uplink speed for something - downlink_speed = ask_for_downlink_speed - # TODO: Use the downlink speed for something - total_bandwidth = calculate_total_bandwidth(uplink_speed, downlink_speed) - # TODO: Use the total bandwidth for something - services = ask_for_services - # TODO: Use the services for something - # ... -end -def ask_for_color - while true - Curses.clear - Curses.setpos(0, 0) - Curses.addstr("Please enter your preferred color (white, red, or black): ") - Curses.refresh - color = Curses.getstr.strip.downcase - if ['white', 'red', 'black'].include?(color) - return color - else - Curses.setpos(1, 0) - Curses.addstr("Whoops! That didn't appear to be a valid color. Please try again!") + def first_run_setup + color = @info_gatherer.ask_for_color + # TODO: Use the color for something + db_details = @info_gatherer.ask_for_db_details + while !@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 = @info_gatherer.ask_for_db_details + end + @db_manager.create_system_info_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) + end + + def ask_for_default_mode + while true + Curses.setpos(8, 0) + 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 + Curses.setpos(9, 0) + Curses.addstr("Whoops! That didn't appear to be a valid mode. Please try again!") + Curses.refresh + end end end -end -def ask_for_default_mode - while true - Curses.setpos(8, 0) - 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 - Curses.setpos(9, 0) - Curses.addstr("Whoops! That didn't appear to be a valid mode. Please try again!") - Curses.refresh - end + def valid_mode?(mode) + ['tui', 'gui', 'webapp'].include?(mode) end end - -def valid_mode?(mode) - ['tui', 'gui', 'webapp'].include?(mode) -end diff --git a/lib/utils/system_information_gather.rb b/lib/utils/system_information_gather.rb index 0379bfd..eab72f1 100644 --- a/lib/utils/system_information_gather.rb +++ b/lib/utils/system_information_gather.rb @@ -1,4 +1,11 @@ -def ask_for_uplink_speed +require 'curses' +require 'yaml' +require_relative 'utilities.rb' + +class SystemInformationGather + include Utilities + + def ask_for_uplink_speed while true Curses.clear Curses.setpos(2, 0) @@ -16,7 +23,7 @@ def ask_for_uplink_speed end end end - + def ask_for_downlink_speed while true Curses.clear @@ -38,8 +45,8 @@ def ask_for_uplink_speed def valid_speed?(speed) speed.to_i > 0 - end - + end + def ask_for_services while true Curses.clear @@ -57,12 +64,12 @@ def ask_for_uplink_speed end end end - + def valid_services?(services) # TODO: Validate the services true end - + def services_to_hash(services) services_hash = {} services.each { |service| services_hash[service] = true } @@ -75,19 +82,24 @@ def ask_for_uplink_speed Curses.addstr("Please enter your database username: ") Curses.refresh username = Curses.getstr.strip - + Curses.setpos(2, 0) Curses.addstr("Please enter your database password: ") Curses.refresh Curses.echo = false password = Curses.getstr.strip - Curses.echo = true - + Curses.echo Curses.setpos(3, 0) Curses.addstr("Please enter your database name: ") Curses.refresh database = Curses.getstr.strip - + { username: username, password: password, database: database } - end - \ No newline at end of file + end + + def write_db_details_to_config_file(db_details) + File.open("config.yml", "w") do |file| + file.write(db_details.to_yaml) + end + end +end \ No newline at end of file diff --git a/lib/utils/utilities.rb b/lib/utils/utilities.rb new file mode 100644 index 0000000..7df6869 --- /dev/null +++ b/lib/utils/utilities.rb @@ -0,0 +1,22 @@ +module Utilities + # Converts speed from Gbps to Mbps if necessary + def self.convert_speed_to_mbps(speed) + if speed.end_with?('gbps') + speed.to_i * 1000 + else + speed.to_i + end + end + + # Converts an array of services into a hash + def self.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) + uplink_speed + downlink_speed + end + end \ No newline at end of file