Page MenuHomeGRNET

No OneTemporary

File Metadata

Created
Sat, Mar 21, 2:14 PM
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 @@
<tr>
- <td>#<%= user.id %></td>
- <td><%= user.username %></td>
+ <td><%= link_to "##{user.id}", admin_user_path(user) %></td>
+ <td><%= link_to user.username, admin_user_path(user) %></td>
<td><%= user.email %></td>
<td><%= user.user_type %></td>
<td><%= I18n.l(user.created_at, format: :short) %></td>
<td><%= inline_list @baculized_host_names[user.id] %></td>
<td><%= inline_list @unverified_host_names[user.id] %></td>
<td><%= inline_list @non_baculized_host_names[user.id] %></td>
<td>
+ <%= link_to admin_user_path(user) do %>
+ <label class="glyphicon glyphicon-eye-open text-primary" alt="show"></label>
+ <% end %>
+ <% if user.editable? %>
+ <%= link_to edit_admin_user_path(user) do %>
+ <label class="glyphicon glyphicon-edit text-primary" alt="show"></label>
+ <% end %>
+ <% end %>
+ </td>
+ <td>
<% if user.enabled? %>
<%= link_to ban_admin_user_path(user), method: :patch, class: 'btn btn-default',
- data: { confirm: 'User will be banned' } do %>
- <label class="glyphicon glyphicon-remove text-danger"></label>
+ data: { confirm: "User #{user.username} will be banned" } do %>
+ <label class="glyphicon glyphicon-ban-circle text-danger"></label>
Ban
<% end %>
<% else %>
<%= link_to unban_admin_user_path(user), method: :patch, class: 'btn btn-default',
- data: { confirm: 'User will be unbanned' } do %>
- <label class="glyphicon glyphicon-ok text-success"></label>
+ data: { confirm: "User #{user.username} will be unbanned" } do %>
+ <label class="glyphicon glyphicon-ok-circle text-success"></label>
Unban
<% end %>
<% end %>
</td>
</tr>
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' %>
+
<div class="row">
<div class="col-xs-4">
<div class="panel panel-default">
<div class="panel-heading">
- <h3>New Admin</h3>
+ <h3>Edit Admin</h3>
<%= render partial: 'form' %>
</div>
</div>
</div>
</div>
diff --git a/app/views/admin/users/index.html.erb b/app/views/admin/users/index.html.erb
index d0fa88c..1f06a17 100644
--- a/app/views/admin/users/index.html.erb
+++ b/app/views/admin/users/index.html.erb
@@ -1,34 +1,35 @@
<div class="row right">
<%= link_to new_admin_user_path, class: "btn btn-default", role: "button" do %>
<label class="glyphicon glyphicon-plus text-primary"></label>
New Admin
<% end %>
</div>
<h1>Users</h1>
<div class="row">
<div class="col-xs-12">
<div class="table-responsive">
<table class="table table-striped table-bordered table-condensed">
<thead>
<tr>
<th>id</th>
- <th>username</th>
- <th>email</th>
- <th>user type</th>
- <th>created at</th>
- <th>clients</th>
- <th>unverified hosts</th>
- <th>pending hosts</th>
- <th>actions</th>
+ <th>Username</th>
+ <th>Email</th>
+ <th>User type</th>
+ <th>Created at</th>
+ <th>Clients</th>
+ <th>Unverified hosts</th>
+ <th>Pending hosts</th>
+ <th>Actions</th>
+ <th>Ban</th>
</tr>
</thead>
<tbody>
<%= render partial: 'user', collection: @users %>
</tbody>
</table>
</div>
</div>
</div>
diff --git a/app/views/admin/users/new.html.erb b/app/views/admin/users/new.html.erb
index 010faa0..5427af3 100644
--- a/app/views/admin/users/new.html.erb
+++ b/app/views/admin/users/new.html.erb
@@ -1,11 +1,13 @@
+<%= render partial: 'header' %>
+
<div class="row">
<div class="col-xs-4">
<div class="panel panel-default">
<div class="panel-heading">
<h3>New Admin</h3>
<%= render partial: 'form' %>
</div>
</div>
</div>
</div>
diff --git a/app/views/admin/users/show.html.erb b/app/views/admin/users/show.html.erb
new file mode 100644
index 0000000..6c637a6
--- /dev/null
+++ b/app/views/admin/users/show.html.erb
@@ -0,0 +1,71 @@
+<%= render partial: 'header' %>
+
+<div class="col-xs-5">
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ <h2>User details</h2>
+ </div>
+
+ <br/>
+
+ <div class="table-responsive">
+ <table class="table table-striped table-bordered table-condensed">
+ <tr>
+ <td><b>Username</b></td>
+ <td><%= @user.username %></td>
+ </tr>
+ <tr>
+ <td><b>Email</b></td>
+ <td><%= @user.email %></td>
+ </tr>
+ <tr>
+ <td><b>User Type</b></td>
+ <td><%= @user.user_type %></td>
+ </tr>
+ <tr>
+ <td><b>Created At</b></td>
+ <td><%= I18n.l(@user.created_at, format: :short) rescue '-' %></td>
+ </tr>
+ <tr>
+ <td><b>Login At</b></td>
+ <td><%= I18n.l(@user.login_at, format: :short) rescue '-' %></td>
+ </tr>
+ <tr>
+ <td><b>Clients</b></td>
+ <td><%= inline_list @user.baculized_hosts %></td>
+ </tr>
+ <tr>
+ <td><b>Pending Hosts</b></td>
+ <td><%= inline_list @user.non_baculized_hosts %></td>
+ </tr>
+ <% if @user.institutional? %>
+ <tr>
+ <td><b>Unverified Hosts</b></td>
+ <td><%= inline_list @user.unverified_hosts %></td>
+ </tr>
+ <% end %>
+ </table>
+ </div>
+ </div>
+ <% if @user.editable? %>
+ <%= link_to edit_admin_user_path(@user), class: 'btn btn-primary' do %>
+ <label class="glyphicon glyphicon-ok-edit text-success"></label>
+ 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 %>
+ <label class="glyphicon glyphicon-ban-circle text-danger"></label>
+ 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 %>
+ <label class="glyphicon glyphicon-ok-circle text-success"></label>
+ Unban User
+ <% end %>
+ <% end %>
+
+ <%= link_to 'Back to users', admin_users_path, class: 'right' %>
+</div>
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 @@
<!-- Fixed navbar -->
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="logo">
<%= link_to root_path do %>
<p><b>GRNET NOC</b></p>
<p>Archiving</p>
<% end %>
</li>
<% if current_user %>
<%= content_tag(:li, active_class(clients_path, true)) do %>
<%= link_to 'Clients', clients_path %>
<% end %>
<li><%= link_to current_user.username, '#' %></li>
<% end %>
</ul>
<% if current_user %>
<ul class="nav navbar-nav navbar-right">
<li>
<%= link_to logout_path do %>
<label class="glyphicon glyphicon-log-out"></label>
Logout
<% end %>
</li>
</ul>
<% end %>
<% if current_user.try(:admin?) %>
<ul class="nav navbar-nav navbar-right">
<%= content_tag(:li, active_class(admin_path)) do %>
<%= link_to 'Admin', admin_path %>
<% end %>
<%= content_tag(:li, active_class(admin_clients_path, true)) do %>
<%= link_to 'Clients', admin_clients_path %>
<% end %>
<%= content_tag(:li, active_class(unverified_admin_hosts_path, true)) do %>
<%= link_to 'Hosts', unverified_admin_hosts_path %>
<% end %>
<%= content_tag(:li, { class: "dropdown #{active_class(admin_users_path)[:class]}" }) do %>
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
Users <span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li>
<%= link_to 'All Users', admin_users_path %>
</li>
<li class="divider"></li>
<li>
<%= link_to 'ViMa Users', admin_users_path(type: :vima) %>
</li>
<li>
+ <%= link_to 'Institutional Users', admin_users_path(type: :institutional) %>
+ </li>
+ <li>
<%= link_to 'Admins', admin_users_path(type: :admin) %>
</li>
<li>
</ul>
<% end %>
<%= content_tag(:li, active_class(admin_settings_path)) do %>
<%= link_to 'Settings', admin_settings_path %>
<% end %>
</ul>
<% end %>
</div><!--/.nav-collapse -->
</div>
</nav>
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

Event Timeline