diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index 5752c2c..4d9137d 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -1,71 +1,106 @@
class Admin::UsersController < Admin::BaseController
+ before_action :fetch_user, only: [:show, :edit, :update, :ban, :unban]
+ before_action :editable_users_only, only: [:edit, :update]
+
# GET /admin/users
def index
@baculized_host_names = Hash.new { |h, k| h[k] = [] }
@non_baculized_host_names = Hash.new { |h, k| h[k] = [] }
@unverified_host_names = Hash.new { |h, k| h[k] = [] }
@users = User.all.includes(:hosts)
@users = @users.admin if params[:type] == 'admin'
@users = @users.vima if params[:type] == 'vima'
+ @users = @users.institutional if params[:type] == 'institutional'
@users.each do |user|
user.hosts.each do |host|
if host.deployed? || host.updated? || host.dispatched? || host.for_removal?
@baculized_host_names[user.id] << host.name
else
@non_baculized_host_names[user.id] << host.name
@unverified_host_names[user.id] << host.name if !host.verified?
end
end
end
end
# GET /admin/users/new
def new
- @user = User.new
+ @user = User.new(user_type: :admin)
end
# POST /admin/users
def create
@user = User.new(fetch_params)
@user.user_type = :admin
if @user.add_password(@user.password)
flash[:success] = 'User created'
redirect_to admin_users_path
else
flash[:error] = 'User was not created'
render 'new'
end
end
+ # GET /admin/users/1
+ def show
+ end
+
+ # GET /admin/users/1/edit
+ def edit
+ end
+
+ # PATCH /admin/users/1/update
+ def update
+ if @user.admin? && @user.update_attributes(fetch_params)
+ flash[:success] = 'User updated'
+ redirect_to admin_user_path(@user)
+ elsif @user.admin?
+ flash[:error] = 'User not updated'
+ redirect_to edit_admin_user_path(@user)
+ else
+ flash[:error] = "User is #{@user.user_type} and thus accepts no updates"
+ redirect_to admin_user_path(@user)
+ end
+ end
+
# PATCH /admin/users/1/ban
def ban
- @user = User.find(params[:id])
if @user.ban
flash[:success] = 'User banned'
else
flash[:error] = 'User NOT banned'
end
redirect_to admin_users_path
end
# PATCH /admin/users/1/unban
def unban
- @user = User.find(params[:id])
if @user.unban
flash[:success] = 'User enabled'
else
flash[:error] = 'User NOT enabled'
end
redirect_to admin_users_path
end
private
def fetch_params
params.require(:user).permit(:username, :email, :password, :retype_password)
end
+
+ def fetch_user
+ @user = User.find(params[:id])
+ end
+
+ def editable_users_only
+ return if @user.editable?
+
+ flash[:error] = "User #{@user.username} is not editable"
+ redirect_to admin_users_path
+ end
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 7fc1c97..614d625 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1,101 +1,109 @@
class User < ActiveRecord::Base
attr_accessor :password, :retype_password
has_many :ownerships
has_many :hosts, through: :ownerships, inverse_of: :users
enum user_type: { institutional: 0, vima: 1, okeanos: 2, admin: 3 }
validates :user_type, presence: true
validates :username, presence: true, uniqueness: { scope: :user_type }
validates :email, presence: true, uniqueness: { scope: :user_type }
before_create :confirm_passwords, if: :admin?
# Returns an admin user with the given password
#
# @param username[String] username from user input
# @param a_password[String] password from user input
#
# @return [User] the admin user or nil
def self.fetch_admin_with_password(username, a_password)
hashed_pass = Digest::SHA256.hexdigest(a_password + Rails.application.secrets.salt)
admin = User.admin.find_by_username_and_password_hash(username, hashed_pass)
admin
end
# Composes the user's display name from the user's username and email
#
# @return [String]
def display_name
"#{username} <#{email}>"
end
# Determines if the user must select hosts from a list or enter their
# FQDN manually
#
# @return [Boolean]
def needs_host_list?
vima? || okeanos?
end
+ # Determines if the user is editable or not.
+ # Editable users are only admin users, all others come from 3rd party authorization
+ #
+ # @return [Boolean]
+ def editable?
+ admin?
+ end
+
# Marks a user as not enabled
def ban
self.enabled = false
save
end
# Marks a user as enabled
def unban
self.enabled = true
save
end
# Stores a hashed password as a password_hash
#
# @param a_password[String] the user submitted password
#
# @return [Boolean] the save exit status
def add_password(a_password)
self.password_hash = Digest::SHA256.hexdigest(a_password + Rails.application.secrets.salt)
self.save
end
# Fetches the user's unverified hosts
#
# @return [Array] of Strings containing the hosts' names
def unverified_hosts
hosts.unverified.pluck(:name)
end
# Fetches the user's hosts that are being backed up by bacula
#
# @return [Array] of Strings configuration the host's names
def baculized_hosts
hosts.in_bacula.pluck(:name)
end
# Fetches the user's hosts that are NOT being backed up by bacula
#
# @return [Array] of Strings configuration the host's names
def non_baculized_hosts
hosts.not_baculized.pluck(:name)
end
private
def confirm_passwords
if password.blank?
self.errors.add(:password, 'Must give a password')
return false
end
if password != retype_password
self.errors.add(:password, 'Passwords mismatch')
self.errors.add(:retype_password, 'Passwords mismatch')
return false
end
true
end
end
diff --git a/app/views/admin/users/_header.html.erb b/app/views/admin/users/_header.html.erb
new file mode 100644
index 0000000..a332735
--- /dev/null
+++ b/app/views/admin/users/_header.html.erb
@@ -0,0 +1,5 @@
+<%= breadcrumb_with Admin: admin_path,
+ Users: admin_users_path,
+ @user.user_type.capitalize => admin_users_path(type: @user.user_type),
+ (@user.username || 'New') => @user.persisted? ? admin_user_path(@user):''
+ %>
diff --git a/app/views/admin/users/_user.html.erb b/app/views/admin/users/_user.html.erb
index 20a857d..2ca9474 100644
--- a/app/views/admin/users/_user.html.erb
+++ b/app/views/admin/users/_user.html.erb
@@ -1,25 +1,35 @@
+ <%= link_to admin_user_path(user) do %>
+
+ <% end %>
+ <% if user.editable? %>
+ <%= link_to edit_admin_user_path(user) do %>
+
+ <% end %>
+ <% end %>
+
+
<% if user.enabled? %>
<%= link_to ban_admin_user_path(user), method: :patch, class: 'btn btn-default',
- data: { confirm: 'User will be banned' } do %>
-
+ data: { confirm: "User #{user.username} will be banned" } do %>
+
Ban
<% end %>
<% else %>
<%= link_to unban_admin_user_path(user), method: :patch, class: 'btn btn-default',
- data: { confirm: 'User will be unbanned' } do %>
-
+ data: { confirm: "User #{user.username} will be unbanned" } do %>
+
Unban
<% end %>
<% end %>
diff --git a/app/views/admin/users/new.html.erb b/app/views/admin/users/edit.html.erb
similarity index 76%
copy from app/views/admin/users/new.html.erb
copy to app/views/admin/users/edit.html.erb
index 010faa0..52f80b6 100644
--- a/app/views/admin/users/new.html.erb
+++ b/app/views/admin/users/edit.html.erb
@@ -1,11 +1,13 @@
+<%= render partial: 'header' %>
+
+ <% if @user.editable? %>
+ <%= link_to edit_admin_user_path(@user), class: 'btn btn-primary' do %>
+
+ Edit User
+ <% end %>
+ <% end %>
+ <% if @user.enabled? %>
+ <%= link_to ban_admin_user_path(@user), method: :patch, class: 'btn btn-default',
+ data: { confirm: "User #{@user.username} will be banned" } do %>
+
+ Ban User
+ <% end %>
+ <% else %>
+ <%= link_to unban_admin_user_path(@user), method: :patch, class: 'btn btn-default',
+ data: { confirm: "User #{@user.username} will be unbanned" } do %>
+
+ Unban User
+ <% end %>
+ <% end %>
+
+ <%= link_to 'Back to users', admin_users_path, class: 'right' %>
+
diff --git a/app/views/shared/_nav.html.erb b/app/views/shared/_nav.html.erb
index ca41736..bfacf33 100644
--- a/app/views/shared/_nav.html.erb
+++ b/app/views/shared/_nav.html.erb
@@ -1,73 +1,76 @@
diff --git a/config/routes.rb b/config/routes.rb
index 7da6c85..91eb988 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,82 +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
+ resources :users, only: [:index, :new, :create, :show, :edit, :update] do
member do
patch :ban
patch :unban
end
end
end
end