diff --git a/app/assets/javascripts/clients.js b/app/assets/javascripts/clients.js index 6762bc5..1a77cee 100644 --- a/app/assets/javascripts/clients.js +++ b/app/assets/javascripts/clients.js @@ -1,36 +1,39 @@ $(document).ready(function() { if ($('#select-files').size() > 0) { $('#file-selector').hide(); $('#select-files').click(function() { $('#file-selector').show(); }); } }); $(document).ready(function() { if ($('#file-submitter').size() > 0) { $("#file-tree").on("select_node.jstree", function(evt, data) { add_input(data.node.id); }); $("#file-tree").on("deselect_node.jstree", function(evt, data) { remove_input(data.node.id); }); } + if ($('#invitation_user_id').size() > 0) { + $('#invitation_user_id').chosen(); + } }); function add_input(id) { $('#file-submitter'). append(''); if ($('.js-file-input').size() > 0 && $('#file-submitter > input[type="submit"]').attr('disabled') == 'disabled') { $('#file-submitter > input[type="submit"]').attr('disabled', false); } } function remove_input(id) { $('#js-file-id-' + id).remove(); if ($('.js-file-input').size() == 0) { $('#file-submitter > input[type="submit"]').attr('disabled', true); } } diff --git a/app/controllers/clients_controller.rb b/app/controllers/clients_controller.rb index de975eb..1653a86 100644 --- a/app/controllers/clients_controller.rb +++ b/app/controllers/clients_controller.rb @@ -1,154 +1,159 @@ class ClientsController < ApplicationController before_action :require_logged_in before_action :fetch_client, only: [:show, :jobs, :logs, :stats, :users, :restore, :run_restore, :restore_selected, :remove_user] before_action :fetch_logs, only: [:logs] # GET /clients # POST /clients def index @client_ids = Client.for_user(current_user.id).pluck(:ClientId) @clients = Client.where(ClientId: @client_ids).includes(:jobs) @hosts = current_user.hosts.not_baculized fetch_jobs_info get_charts end # GET /clients/1 def show @schedules = @client.host.job_templates.map(&:schedule) @filesets = @client.host.job_templates.map(&:fileset) end # GET /clients/1/jobs def jobs @jobs = @client.recent_jobs.page(params[:page]) end # GET /clients/1/logs def logs; end # GET /clients/1/stats # POST /clients/1/stats def stats get_charts end # GET /clients/1/users def users @users = @client.host.users + if @client.manually_inserted? + @invitation = @client.host.invitations.new + excluded_ids = @users.pluck(:id) + @client.host.invitations.pluck(:user_id) + @available_users = User.institutional.where.not(id: excluded_ids).pluck(:username, :id) + end end # DELETE /clients/1/user def remove_user user = @client.host.users.find(params[:user_id]) if @client.host.users.delete(user) flash[:success] = if @client.manually_inserted? 'User successfully removed' else 'User must be removed from the VM\'s list form your VM provider too (ViMa or Okeanos).' end else flash[:alert] = 'User not removed, something went wrong' end redirect_to users_client_path(@client) end # GET /clients/1/restore def restore return if @client.is_backed_up? flash[:error] = 'Can not issue a restore for this client' redirect_to client_path(@client) end # POST /clients/1/run_restore def run_restore @location = params[:restore_location].blank? ? '/tmp/bacula_restore' : params[:restore_location] fileset = params[:fileset] restore_point = fetch_restore_point if params[:commit] == 'Restore All Files' if @location.nil? || fileset.nil? || !@client.host.restore(fileset, @location, restore_point) flash[:error] = 'Something went wrong, try again later' else flash[:success] = "Restore job issued successfully, files will be soon available in #{@location}" end render js: "window.location = '#{client_path(@client)}'" else session[:job_ids] = @client.get_job_ids(fileset, restore_point) Bvfs.new(@client, session[:job_ids]).update_cache render 'select_files' end end # POST /clients/1/restore_selected def restore_selected Bvfs.new(@client, session[:job_ids]).restore_selected_files(params[:files], params[:location]) session.delete(:job_ids) flash[:success] = "Restore job issued successfully, files will be soon available in #{params[:location]}" redirect_to client_path(@client) end # GET /clients/1/tree?id=1 def tree @client = Client.for_user(current_user.id).find(params[:client_id]) bvfs = Bvfs.new(@client, session[:job_ids]) pathid = params[:id].to_i if pathid.nonzero? bvfs.fetch_dirs(pathid) else bvfs.fetch_dirs end tree = bvfs.extract_dir_id_and_name.map do |id, name| { id: id, text: name, state: { checkbox_disabled: true }, children: true } end if pathid.nonzero? bvfs.fetch_files(pathid) bvfs.extract_file_id_and_name.each do |id, name| tree << { id: id, text: name, type: 'file' } end end render json: tree end private def fetch_client @client = Client.for_user(current_user.id).find(params[:id]) @client_ids = [@client.id] end def fetch_jobs_info @stats = JobStats.new(@client_ids) end def get_charts days_ago = params.fetch(:days_back, 7).to_i rescue 7 @job_status = ChartGenerator.job_statuses(@client_ids, days_ago) @job_stats = ChartGenerator.job_stats(@client_ids, days_ago - 1) end def fetch_restore_point if params['restore_time(4i)'].blank? || params['restore_time(5i)'].blank? || params[:restore_date].blank? return nil end restore_point = "#{params[:restore_date]} #{params['restore_time(4i)']}:#{params['restore_time(5i)']}:00" begin DateTime.strptime(restore_point, '%Y-%m-%d %H:%M:%S') rescue return nil end restore_point end end diff --git a/app/controllers/invitations_controller.rb b/app/controllers/invitations_controller.rb new file mode 100644 index 0000000..94ab580 --- /dev/null +++ b/app/controllers/invitations_controller.rb @@ -0,0 +1,19 @@ +class InvitationsController < ApplicationController + # POST /invitations + def create + invitation = Invitation.new(fetch_params) + if invitation.save + flash[:success] = "User #{invitation.user.username} has been invited to the client" + else + flash[:alert] = 'Invitation not created' + end + + redirect_to :back + end + + private + + def fetch_params + params.require(:invitation).permit(:user_id, :host_id) + end +end diff --git a/app/views/clients/users.html.erb b/app/views/clients/users.html.erb index 602d601..f90ec0e 100644 --- a/app/views/clients/users.html.erb +++ b/app/views/clients/users.html.erb @@ -1,13 +1,26 @@ <%= render partial: 'header' %>

Collaborators for <%= @client.host.name %>

+ <% if @client.manually_inserted? && @available_users.any? %> +
+ <%= bootstrap_form_for(@invitation, layout: :inline) do |f| %> + <%= f.select :user_id, options_for_select(@available_users), + include_blank: 'Pick a user', skip_label: true %> + <%= f.hidden_field :host_id %> + <%= button_tag type: :submit, class: 'btn btn-default' do %> + + Invite New User + <% end %> + <% end %> +
+ <% end %>
<%= render partial: 'users' %>
<%= link_to 'Back to clients', clients_path %> diff --git a/config/routes.rb b/config/routes.rb index 3b64306..d46cffe 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,94 +1,96 @@ 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 post :restore_selected delete :remove_user end collection do post :index end end resources :clients, only: [], param: :client_id do member do get :tree end end + resources :invitations, only: [:create] + 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, :edit, :update, :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 post :block post :unblock 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, :show, :edit, :update] do member do patch :ban patch :unban end end resources :pools, only: [:index, :new, :create, :show, :edit, :update] end end diff --git a/spec/routing/invitation_routing_spec.rb b/spec/routing/invitation_routing_spec.rb new file mode 100644 index 0000000..48b3bb9 --- /dev/null +++ b/spec/routing/invitation_routing_spec.rb @@ -0,0 +1,8 @@ +require 'spec_helper' + +describe InvitationsController do + it 'routes POST /invitations' do + expect(post('/invitations')).to route_to(controller: 'invitations', action: 'create') + end +end +