From 72bb25a6ad92088dd54d1a9794a6986ff59b9745 Mon Sep 17 00:00:00 2001 From: Gregory Ballantine Date: Fri, 31 Mar 2023 11:52:37 -0400 Subject: [PATCH] Modernized the app with app structure from Stage Manager --- .rubocop.yml | 21 ++++++++++++++ Gemfile | 14 +++++++-- Gemfile.lock | 63 ++++++++++++++++++++++++++++++++++++---- Guardfile | 6 ++++ Rakefile | 12 ++++++-- app/config.rb | 32 ++++++++++++++++++++ app/controllers/auth.rb | 47 +++++++++++++++++------------- app/controllers/index.rb | 17 +++++++---- app/helpers.rb | 24 +++++++++++++++ app/models/account.rb | 10 +++++++ app/settings.rb | 10 ------- config.ru | 26 +++++------------ config/defaults.yaml | 4 +++ config/puma.rb | 6 ++++ puma.rb | 11 ------- server.rb | 60 ++++++++++++++++++++++++++++++++++++++ 16 files changed, 285 insertions(+), 78 deletions(-) create mode 100644 .rubocop.yml create mode 100644 Guardfile create mode 100644 app/config.rb create mode 100644 app/helpers.rb delete mode 100644 app/settings.rb create mode 100644 config/puma.rb delete mode 100644 puma.rb create mode 100644 server.rb diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..13188ad --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1,21 @@ +AllCops: + NewCops: enable + +Layout/EmptyLinesAroundClassBody: + EnforcedStyle: 'empty_lines_except_namespace' +Layout/EmptyLinesAroundModuleBody: + EnforcedStyle: 'empty_lines_except_namespace' +Metrics/ClassLength: + Max: 150 +Style/ClassVars: + Enabled: false +Style/GlobalVars: + Enabled: false +Style/MethodCallWithoutArgsParentheses: + Enabled: false +Style/MethodCallWithArgsParentheses: + Enabled: true +Style/RedundantReturn: + Enabled: false +Style/TrailingCommaInHashLiteral: + EnforcedStyleForMultiline: consistent_comma diff --git a/Gemfile b/Gemfile index e3778e1..70e0844 100644 --- a/Gemfile +++ b/Gemfile @@ -1,8 +1,16 @@ source 'https://rubygems.org' gem 'sinatra', '~> 3.0' -gem 'puma', '~> 6.0' - -gem 'rerun' +gem 'puma', '~> 6.1' gem 'net-ldap', '~> 0.17' + +group :development, :test do + # Use guard-rack gem to auto-reload app + gem 'guard-rack' + gem 'wdm', '>= 0.1.0' if Gem.win_platform? + + # rubocop and extensions for code style + gem 'rubocop' +end + diff --git a/Gemfile.lock b/Gemfile.lock index d4dc597..06cee98 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,42 +1,93 @@ GEM remote: https://rubygems.org/ specs: + ast (2.4.2) + coderay (1.1.3) ffi (1.15.5) ffi (1.15.5-x64-mingw-ucrt) - listen (3.7.1) + formatador (1.1.0) + guard (2.18.0) + formatador (>= 0.2.4) + listen (>= 2.7, < 4.0) + lumberjack (>= 1.0.12, < 2.0) + nenv (~> 0.1) + notiffany (~> 0.0) + pry (>= 0.13.0) + shellany (~> 0.0) + thor (>= 0.18.1) + guard-rack (2.2.1) + ffi + guard (~> 2.3) + spoon + json (2.6.3) + listen (3.8.0) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) + lumberjack (1.2.8) + method_source (1.0.0) mustermann (3.0.0) ruby2_keywords (~> 0.0.1) + nenv (0.3.0) net-ldap (0.17.1) nio4r (2.5.8) - puma (6.0.0) + notiffany (0.1.3) + nenv (~> 0.1) + shellany (~> 0.0) + parallel (1.22.1) + parser (3.2.1.1) + ast (~> 2.4.1) + pry (0.14.2) + coderay (~> 1.1) + method_source (~> 1.0) + puma (6.2.1) nio4r (~> 2.0) rack (2.2.4) rack-protection (3.0.4) rack + rainbow (3.1.1) rb-fsevent (0.11.2) rb-inotify (0.10.1) ffi (~> 1.0) - rerun (0.13.1) - listen (~> 3.0) + regexp_parser (2.7.0) + rexml (3.2.5) + rubocop (1.48.1) + json (~> 2.3) + parallel (~> 1.10) + parser (>= 3.2.0.0) + rainbow (>= 2.2.2, < 4.0) + regexp_parser (>= 1.8, < 3.0) + rexml (>= 3.2.5, < 4.0) + rubocop-ast (>= 1.26.0, < 2.0) + ruby-progressbar (~> 1.7) + unicode-display_width (>= 2.4.0, < 3.0) + rubocop-ast (1.28.0) + parser (>= 3.2.1.0) + ruby-progressbar (1.13.0) ruby2_keywords (0.0.5) + shellany (0.0.1) sinatra (3.0.4) mustermann (~> 3.0) rack (~> 2.2, >= 2.2.4) rack-protection (= 3.0.4) tilt (~> 2.0) + spoon (0.0.6) + ffi + thor (1.2.1) tilt (2.0.11) + unicode-display_width (2.4.2) + wdm (0.1.1) PLATFORMS x64-mingw-ucrt x86_64-linux DEPENDENCIES + guard-rack net-ldap (~> 0.17) - puma (~> 6.0) - rerun + puma (~> 6.1) + rubocop sinatra (~> 3.0) + wdm (>= 0.1.0) BUNDLED WITH 2.3.5 diff --git a/Guardfile b/Guardfile new file mode 100644 index 0000000..8098666 --- /dev/null +++ b/Guardfile @@ -0,0 +1,6 @@ +guard 'rack' do + watch('Gemfile.lock') + watch('config.ru') + watch('server.rb') + watch(%r{^(app)/.*}) +end \ No newline at end of file diff --git a/Rakefile b/Rakefile index 2514748..e286847 100644 --- a/Rakefile +++ b/Rakefile @@ -1,11 +1,17 @@ require 'bundler/setup' namespace :server do - task :dev do - %x{puma -C puma.rb} + task :start do + system('bundle exec puma -C config/puma.rb') end task :reload do - %x{rerun --no-notify 'puma -C puma.rb'} + system('guard') + end +end + +namespace :test do + task :lint do + system("rubocop app/ server.rb") end end diff --git a/app/config.rb b/app/config.rb new file mode 100644 index 0000000..cabd7ee --- /dev/null +++ b/app/config.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require 'yaml' + +# Configuration loader - loads config defaults and an optional config file +class Config + + DEFAULT_CONFIG = 'config/defaults.yaml' + + def initialize(config_path) + # Load the default config + @data = YAML.load_file(DEFAULT_CONFIG) + + # End if the optional config file doesn't exist + return unless File.exist?(config_path) + + # If the optional config exists, load it up! + @data.merge!(YAML.load_file(config_path)) + end + + def get(key) + bits = key.split('.') + value = @data + + bits.each do |bit| + value = value[bit] + end + + return value + end + +end diff --git a/app/controllers/auth.rb b/app/controllers/auth.rb index 5ce957e..12f1a4d 100644 --- a/app/controllers/auth.rb +++ b/app/controllers/auth.rb @@ -1,26 +1,33 @@ -class AuthController < Sinatra::Base +# frozen_string_literal: true - get '/login' do - erb :'auth/login', :locals => { - :title => 'Login to your account' - } - end +require 'net/ldap' - post '/login' do - ldap = Net::LDAP.new - ldap.host = cnf['ldap']['server_url'] - ldap.port = 389 - ldap.auth(params[:login_username], params[:login_password]) - if ldap.bind() - session['ldap_uid'] = params[:username] - redirect '/account/view' - else - # Authentication failure - erb :'auth/login', :locals => { - :title => 'Login to your account', - :fail => true +class Webdap + # Handles /auth routes + class AuthController + + get '/login' do + erb :'auth/login', locals: { + title: 'Login to your account', } end - end + post '/login' do + ldap = Net::LDAP.new + ldap.host = cnf['ldap']['server_url'] + ldap.port = 389 + ldap.auth(params[:login_username], params[:login_password]) + if ldap.bind() + session['ldap_uid'] = params[:username] + redirect '/account/view' + else + # Authentication failure + erb :'auth/login', locals: { + title: 'Login to your account', + fail: true, + } + end + end + + end end diff --git a/app/controllers/index.rb b/app/controllers/index.rb index c5fd93a..fc57f75 100644 --- a/app/controllers/index.rb +++ b/app/controllers/index.rb @@ -1,9 +1,14 @@ -class IndexController < Sinatra::Base +# frozen_string_literal: true + +class Webdap + # Handles top-level routes + class IndexController + + get '/' do + erb :index, locals: { + title: 'Home', + } + end - get '/' do - erb :index, :locals => { - :title => 'Home' - } end - end diff --git a/app/helpers.rb b/app/helpers.rb new file mode 100644 index 0000000..78e3252 --- /dev/null +++ b/app/helpers.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +# ERB view helper functions +module Helpers + + def nullable(value) + # Returns the value if it actually exists + return value if value && (value != '') + + # Returns a default 'N/a' string + return 'N/a' + end + + def date_format(date) + dt = date.to_datetime + return dt.strftime('%B %d, %Y, %I:%M:%S %p') + end + + def date_format_input(date) + dt = date.to_datetime + return dt.strftime('%Y-%m-%dT%H:%M:%S') + end + +end diff --git a/app/models/account.rb b/app/models/account.rb index e69de29..d1fcedd 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +# Handles LDAP accounts +class Account + + def name + return 'N/a' + end + +end diff --git a/app/settings.rb b/app/settings.rb deleted file mode 100644 index 8f1d37c..0000000 --- a/app/settings.rb +++ /dev/null @@ -1,10 +0,0 @@ -class Sinatra::Base - - configure do - enable :sessions - - set :views, './views' - set :public_folder, './public' - end - -end diff --git a/config.ru b/config.ru index 87155f2..746132d 100644 --- a/config.ru +++ b/config.ru @@ -1,22 +1,10 @@ -require 'rubygems' -require 'sinatra/base' -require 'yaml' +# Load application config +require_relative 'app/config.rb' +$conf = Config.new(File.join(__dir__, 'config/config.yaml')) -require_relative 'app/settings.rb' +# Load Sinatra server +require_relative './server.rb' -defaultCnf = YAML::load_file(File.join(__dir__, 'config/defaults.yaml')) -cnf = YAML::load_file(File.join(__dir__, 'config/local.yaml')) -cnf = defaultCnf.merge(cnf) +# Run application +run Webdap -require 'net/ldap' - -require_relative 'app/controllers/index.rb' -require_relative 'app/controllers/auth.rb' - -map "/" do - run IndexController -end - -map "/auth" do - run AuthController -end diff --git a/config/defaults.yaml b/config/defaults.yaml index 9502a46..52a5154 100644 --- a/config/defaults.yaml +++ b/config/defaults.yaml @@ -1,3 +1,7 @@ ldap: server_url: 'ldap://ldap.example.com' port: 389 + +server: + address: '127.0.0.1' + port: 4567 diff --git a/config/puma.rb b/config/puma.rb new file mode 100644 index 0000000..4e5fe8a --- /dev/null +++ b/config/puma.rb @@ -0,0 +1,6 @@ +# Load application config +require './app/config.rb' +$conf = Config.new(File.join(__dir__, 'config/config.yaml')) + +bind_address = "tcp://#{$conf.get('server.address')}:#{$conf.get('server.port')}" +bind bind_address diff --git a/puma.rb b/puma.rb deleted file mode 100644 index 698b1e7..0000000 --- a/puma.rb +++ /dev/null @@ -1,11 +0,0 @@ -root = Dir.getwd.to_s - -bind_address = '0.0.0.0' -bind_port = 3108 -bind "tcp://#{bind_address}:#{bind_port}" - -pidfile './tmp/puma.pid' -state_path './tmp/puma.state' -rackup root.to_s + '/config.ru' - -threads 4, 8 diff --git a/server.rb b/server.rb new file mode 100644 index 0000000..d2b0278 --- /dev/null +++ b/server.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +require 'logger' +require 'sinatra/base' +require 'rack/protection' + +# Base Sinatra app +class Webdap < Sinatra::Base + + @@my_app = {} + + def self.new(*) + self < Webdap ? super : Rack::URLMap.new(@@my_app) + end + + def + self.map(url) @@my_app[url] = self + end + + configure do + enable :sessions + + # Enable rack protection middleware + use Rack::Protection + + # Set up static file serving + enable :static + set :public_folder, File.join(settings.root, '/public') + + # Set up our view engine + set :views, File.join(settings.root, '/views') + end + + # Initialize logging + logger = Logger.new($stdout) + logger.level = Logger::INFO + + # Load helper functions + require_relative 'app/helpers' + helpers Helpers + + ## Map controllers + # Top-level routes controller + class IndexController < Webdap + + map '/' + + end + + # Authentication routes controller + class AuthController < Webdap + + map '/auth' + + end + +end + +# Load controllers +Dir.glob('./app/controllers/*.rb').sort().each { |f| require f }