diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 81ca1e0..d981ca7 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,92 +1,104 @@ class ApplicationController < ActionController::Base # Prevent CSRF attacks by raising an exception. # For APIs, you may want to use :null_session instead. protect_from_forgery with: :exception helper_method :current_user, :warden def index redirect_to clients_path if current_user end + # Warden handler for authentication failure def unauthenticated - flash[:error] = warden.message + flash[:error] = warden.message || 'There was an error with your login' if attempted_path == '/grnet' redirect_to admin_login_path else redirect_to root_path end end # POST /grnet def grnet if current_user warden.logout reset_current_user end begin warden.authenticate!(:admin) rescue return unauthenticated end current_user redirect_to admin_path end + # GET /institutional + def institutional + begin + warden.authenticate!(:institutional) + rescue + return unauthenticated + end + current_user + redirect_to clients_path + end + # POST /vima def vima begin warden.authenticate!(:vima) rescue return unauthenticated end current_user redirect_to clients_path end def logout warden.logout reset_current_user redirect_to root_path end protected def warden request.env['warden'] end def current_user @current_user ||= warden.user end def reset_current_user @current_user = nil end def fetch_logs days_ago = params.fetch(:days_back, 7).to_i rescue 7 if @client @logs = Log.includes(:job).joins(job: :client).where(Client: { ClientId: @client.id }) else @logs = Log.includes(:job).joins(job: { client: { host: :users } }). where(users: { id: current_user.id }) end @logs = @logs.where('Time > ?', days_ago.days.ago). order(Time: :desc, LogId: :desc).page(params[:page]) end private def require_logged_in return if current_user flash[:alert] = 'You need to log in first' redirect_to root_path end def attempted_path (request.env['warden.options'] || {})[:attempted_path] end end diff --git a/app/views/application/index.html.erb b/app/views/application/index.html.erb index 90eca05..31e537e 100644 --- a/app/views/application/index.html.erb +++ b/app/views/application/index.html.erb @@ -1,35 +1,35 @@

Login


<%= link_to 'ViMa User', vima_path(vima: 'vima'), method: :post, role: :button, class: 'btn btn-default btn-lg', disabled: !Archiving.settings[:vima_oauth_enabled] %>

- <%= link_to 'Institutional User', '', role: :button, + <%= link_to 'Institutional User', institutional_path, role: :button, class: 'btn btn-default btn-lg', disabled: !Archiving.settings[:institutional_authentication_enabled] %>

<%= link_to 'Okeanos User', '', role: :button, class: 'btn btn-default btn-lg', disabled: !Archiving.settings[:okeanos_authentication_enabled] %>

diff --git a/config/initializers/00_settings.rb b/config/initializers/00_settings.rb index cffe487..86537d3 100644 --- a/config/initializers/00_settings.rb +++ b/config/initializers/00_settings.rb @@ -1,6 +1,6 @@ Baas.settings director_name: YAML.load_file(Rails.root.join('config', 'bacula.yml'))[Rails.env]. symbolize_keys[:director] Archiving.settings vima_oauth_enabled: true -Archiving.settings institutional_authentication_enabled: false +Archiving.settings institutional_authentication_enabled: true Archiving.settings okeanos_authentication_enabled: false diff --git a/config/routes.rb b/config/routes.rb index eedbac6..7da6c85 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,81 +1,82 @@ Rails.application.routes.draw do root 'application#index' post 'grnet' => 'application#grnet' + get 'institutional' => 'application#institutional' match 'vima', to: 'application#vima', :via => [:get, :post] get 'logout' => 'application#logout' resources :clients, only: [:index, :show] do member do get :jobs get :logs get :stats post :stats get :users get :restore post :run_restore end collection do post :index end end resources :hosts, only: [:new, :create, :show, :edit, :update, :destroy] do member do post :submit_config post :disable delete :revoke end resources :jobs, only: [:new, :create, :show, :edit, :update, :destroy] do member do patch :toggle_enable post :backup_now end end resources :filesets, only: [:show, :new, :create, :destroy] resources :schedules, only: [:show, :new, :edit, :create, :update, :destroy] end namespace :admin do match '/', to: 'base#index', via: [:get, :post] get '/login' => 'base#login', as: :login resources :settings, only: [:index, :new, :create, :edit, :update] do member do delete :reset end end resources :clients, only: [:index, :show] do member do get :jobs get :logs get :stats post :stats get :configuration post :disable delete :revoke end end resources :hosts, only: [:show] do collection do get :unverified end member do post :verify end end resources :users, only: [:index, :new, :create] do member do patch :ban patch :unban end end end end diff --git a/lib/peter/peter.rb b/lib/peter/peter.rb index 7a5eb58..c75aafb 100644 --- a/lib/peter/peter.rb +++ b/lib/peter/peter.rb @@ -1,27 +1,27 @@ require 'peter/strategies/admin' require 'peter/strategies/vima' +require 'peter/strategies/institutional' module Peter extend self def set_session(user, auth, opts) session = auth.session(:default) end Rails.configuration.middleware.insert_after ActionDispatch::Flash, Warden::Manager do |manager| - manager.default_strategies :admin, :vima manager.failure_app = ApplicationController end Warden::Manager.serialize_into_session do |user| user.id end Warden::Manager.serialize_from_session do |id| User.find_by_id(id) end end Warden::Manager.after_authentication do |user,auth,opts| Peter.set_session(user, auth, opts) end diff --git a/lib/peter/strategies/institutional.rb b/lib/peter/strategies/institutional.rb new file mode 100644 index 0000000..57851fd --- /dev/null +++ b/lib/peter/strategies/institutional.rb @@ -0,0 +1,38 @@ +Warden::Strategies.add(:institutional) do + def valid? + fetch_header('HTTP_PERSISTENT_ID').present? && + fetch_header('HTTP_MAIL').present? && + fetch_header('HTTP_ENTITLEMENT').present? && + fetch_header('HTTP_ENTITLEMENT').include?('urn:mace:grnet.gr:archiving:admin') + end + + def fetch_header(header) + request.env[header] + end + + def authenticate! + if !Archiving.settings[:institutional_authentication_enabled] + return fail!("Shibboleth is temporarily disabled") + end + + identifier = "institutional:#{fetch_header("HTTP_PERSISTENT_ID")}" + user = User.find_or_initialize_by(identifier: identifier) + + return fail!("Wrong credentials") unless user + + user.login_at = Time.now + + if user.new_record? + user.email = fetch_header("HTTP_MAIL") + user.username = fetch_header("HTTP_MAIL") + user.enabled = true + user.institutional! + else + user.save + end + + return fail!("Service not available") unless user.enabled? + + success!(user) + end +end