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:
parent
f96cf9e20a
commit
335cd89ebe
24
.rubocop.yml
24
.rubocop.yml
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -1 +1 @@
|
|||
3.0.5
|
||||
3.2.2
|
||||
|
|
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
|
@ -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/"
|
||||
}
|
||||
|
|
70
bin/NETRAVE
70
bin/NETRAVE
|
@ -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
|
||||
|
|
28
lib/Gemfile
28
lib/Gemfile
|
@ -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'
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]}"
|
||||
@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
|
||||
# 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'
|
||||
true
|
||||
rescue Sequel::DatabaseConnectionError
|
||||
false
|
||||
ensure
|
||||
@db&.disconnect
|
||||
end
|
||||
|
||||
def create_system_info_table
|
||||
|
@ -27,25 +32,25 @@ class DatabaseManager
|
|||
primary_key :id
|
||||
Integer :uplink_speed
|
||||
Integer :downlink_speed
|
||||
String :services, text: true
|
||||
Integer :total_bandwidth
|
||||
end
|
||||
end
|
||||
|
||||
def store_system_info(system_info)
|
||||
@db[:system_info].insert(system_info)
|
||||
end
|
||||
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
|
||||
end
|
||||
|
|
|
@ -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
|
||||
Curses.setpos(9, 0)
|
||||
Curses.addstr("Whoops! That didn't appear to be a valid mode. Please try again!")
|
||||
Curses.refresh
|
||||
end
|
||||
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
|
||||
|
||||
def valid_mode?(mode)
|
||||
['tui', 'gui', 'webapp'].include?(mode)
|
||||
%w[tui gui webapp].include?(mode)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
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(" ")
|
||||
def ask_for_uplink_speed # rubocop:disable Metrics/MethodLength
|
||||
Curses.clear
|
||||
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
|
||||
Curses.addstr('Uplink Speed: ')
|
||||
speed = DCI.catch_input(true)
|
||||
if valid_speed?(speed)
|
||||
speed.end_with?('gbps') ? convert_speed_to_mbps(speed) : speed.to_i
|
||||
else
|
||||
Curses.setpos(5, 0)
|
||||
Curses.addstr("Uplink Speed: ")
|
||||
Curses.addstr("Whoops! That didn't appear to be a valid speed. Please try again!")
|
||||
Curses.refresh
|
||||
speed = Curses.getstr.strip.downcase
|
||||
if valid_speed?(speed)
|
||||
return 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
|
||||
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. ")
|
||||
|
||||
def ask_for_downlink_speed # rubocop:disable Metrics/MethodLength
|
||||
Curses.clear
|
||||
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
|
||||
Curses.addstr('Downlink Speed: ')
|
||||
speed = DCI.catch_input(true)
|
||||
if valid_speed?(speed)
|
||||
speed.end_with?('gbps') ? convert_speed_to_mbps(speed) : speed.to_i
|
||||
else
|
||||
Curses.setpos(5, 0)
|
||||
Curses.addstr("Downlink Speed: ")
|
||||
Curses.addstr("Whoops! That didn't appear to be a valid speed. Please try again!")
|
||||
Curses.refresh
|
||||
speed = Curses.getstr.strip.downcase
|
||||
if valid_speed?(speed)
|
||||
return 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
|
||||
end
|
||||
|
||||
def valid_speed?(speed)
|
||||
speed.to_i > 0
|
||||
speed.to_i.positive?
|
||||
end
|
||||
|
||||
def ask_for_services
|
||||
while true
|
||||
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). ")
|
||||
def ask_for_services # rubocop:disable Metrics/MethodLength
|
||||
Curses.clear
|
||||
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
|
||||
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
|
||||
services = Curses.getstr.strip.downcase.split(',').map(&:strip)
|
||||
if valid_services?(services)
|
||||
return services_to_hash(services)
|
||||
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
|
||||
end
|
||||
|
|
|
@ -1,22 +1,62 @@
|
|||
# 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)
|
||||
if speed.end_with?('gbps')
|
||||
speed.to_i * 1000
|
||||
else
|
||||
speed.to_i
|
||||
end
|
||||
# Converts speed from Gbps to Mbps if necessary
|
||||
def convert_speed_to_mbps(speed)
|
||||
if speed.end_with?('gbps')
|
||||
speed.to_i * 1000
|
||||
else
|
||||
speed.to_i
|
||||
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
|
||||
end
|
||||
|
||||
# Converts an array of services into a hash
|
||||
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 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
|
||||
|
|
Loading…
Reference in New Issue
Block a user