diff --git a/app/api/vmapi.rb b/app/api/vmapi.rb index 83649f44..50bb85aa 100644 --- a/app/api/vmapi.rb +++ b/app/api/vmapi.rb @@ -32,6 +32,11 @@ def vm_users(vm) # rubocop:disable Naming/UncommunicativeMethodParamName end end + def user_vms(user) + requests = user.requests.accepted + requests.inject([]) { |vms, request| vms << get_vm_info(request.name) } + end + def all_vm_infos connect all_vms.map do |vm| diff --git a/app/controllers/vms_controller.rb b/app/controllers/vms_controller.rb index e48b2951..7662c70d 100644 --- a/app/controllers/vms_controller.rb +++ b/app/controllers/vms_controller.rb @@ -2,14 +2,20 @@ require 'vmapi.rb' +# rubocop:disable Metrics/ClassLength class VmsController < ApplicationController attr_reader :vms include VmsHelper before_action :authenticate_admin, only: %i[archive_vm] + before_action :authorize_vm_access, only: %i[show] def index - @vms = filter VmApi.instance.all_vm_infos + @vms = if current_user.user? + filter current_user.vms + else + filter VmApi.instance.all_vm_infos + end @archived_vms = all_archived_vms @parameters = determine_params @pending_archivation_vms = all_pending_archived_vms @@ -30,8 +36,7 @@ def new end def show - @vm = VmApi.instance.get_vm_info(params[:id]) - render(template: 'errors/not_found', status: :not_found) if @vm.nil? + return render(template: 'errors/not_found', status: :not_found) if @vm.nil? end def request_vm_archivation @@ -132,4 +137,12 @@ def no_params_set? def vm_filter { up_vms: proc { |vm| vm[:state] }, down_vms: proc { |vm| !vm[:state] } } end + + def authorize_vm_access + @vm = VmApi.instance.get_vm_info(params[:id]) + return unless @vm + + redirect_to vms_path if current_user.user? && !current_user.vms.include?(@vm) + end end +# rubocop:enable Metrics/ClassLength diff --git a/app/models/user.rb b/app/models/user.rb index 02ee593a..5a97b6ac 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require 'sshkey' +require 'vmapi.rb' class User < ApplicationRecord # Include default devise modules. Others available are: @@ -64,6 +65,10 @@ def self.from_omniauth(auth) end end + def vms + VmApi.instance.user_vms(self) + end + private def set_default_role diff --git a/spec/controllers/vms_controller_spec.rb b/spec/controllers/vms_controller_spec.rb index 393b8036..629320f6 100644 --- a/spec/controllers/vms_controller_spec.rb +++ b/spec/controllers/vms_controller_spec.rb @@ -4,51 +4,69 @@ RSpec.describe VmsController, type: :controller do # Authenticate an user before do + @request.env['devise.mapping'] = Devise.mappings[:user] sign_in FactoryBot.create :user end describe 'GET #index' do before do + vm1 = { name: 'My insanely cool vm', state: true, boot_time: 'Thursday', vmwaretools: true } + vm2 = { name: 'another VM', state: false, boot_time: 'now', vmwaretools: true } double_api = double - allow(double_api).to receive(:all_vm_infos).and_return [{ name: 'My insanely cool vm', state: true, boot_time: 'Thursday', vmwaretools: true }, - { name: 'another VM', state: false, boot_time: 'now', vmwaretools: true }] - + allow(double_api).to receive(:all_vm_infos).and_return [vm1, vm2] allow(double_api).to receive(:ensure_folder) allow(double_api).to receive(:all_vms_in).and_return [] + allow(double_api).to receive(:user_vms).and_return [vm1] allow(VmApi).to receive(:instance).and_return double_api end - it 'returns http success' do - get :index - expect(response).to have_http_status(:success) - end + context 'when the current user is an admin' do + before do + sign_in FactoryBot.create :admin + end - it 'renders index page' do - expect(get(:index)).to render_template('vms/index') - end + it 'returns http success' do + get :index + expect(response).to have_http_status(:success) + end - it 'returns all VMs per default' do - controller = VmsController.new - controller.params = {} - controller.index - expect(controller.vms.size).to be VmApi.instance.all_vm_infos.size - end + it 'renders index page' do + expect(get(:index)).to render_template('vms/index') + end - it 'returns online VMs if requested' do - controller = VmsController.new - controller.params = { up_vms: 'true' } - controller.index - expect(controller.vms).to satisfy('include online VMs') { |vms| vms.any? { |vm| vm[:state] } } - expect(controller.vms).not_to satisfy('include offline VMs') { |vms| vms.any? { |vm| !vm[:state] } } + it 'returns all VMs' do + get(:index) + expect(subject.vms.size).to be VmApi.instance.all_vm_infos.size + end + + it 'returns online VMs if requested' do + get :index, params: { up_vms: 'true' } + expect(subject.vms).to satisfy('include online VMs') { |vms| vms.any? { |vm| vm[:state] } } + expect(subject.vms).not_to satisfy('include offline VMs') { |vms| vms.any? { |vm| !vm[:state] } } + end + + it 'returns offline VMs if requested' do + get :index, params: { down_vms: 'true' } + expect(subject.vms).to satisfy('include offline VMs') { |vms| vms.any? { |vm| !vm[:state] } } + expect(subject.vms).not_to satisfy('include online VMs') { |vms| vms.any? { |vm| vm[:state] } } + end end - it 'returns offline VMs if requested' do - controller = VmsController.new - controller.params = { down_vms: 'true' } - controller.index - expect(controller.vms).to satisfy('include offline VMs') { |vms| vms.any? { |vm| !vm[:state] } } - expect(controller.vms).not_to satisfy('include online VMs') { |vms| vms.any? { |vm| vm[:state] } } + context 'when the current user is a user' do + it 'returns http success' do + get :index + expect(response).to have_http_status(:success) + end + + it 'renders index page' do + expect(get(:index)).to render_template('vms/index') + end + + it 'returns only vms associated to current usera' do + get :index + expect(subject.vms.size).to be 1 + end end end @@ -96,18 +114,60 @@ end before do + @vm1 = { name: 'My insanely cool vm', state: true, boot_time: 'Thursday', vmwaretools: true } + allow(double_api).to receive(:user_vms).and_return [@vm1] allow(VmApi).to receive(:instance).and_return double_api end it 'returns http success or timeout or not found' do - allow(double_api).to receive(:get_vm_info).and_return({}) + allow(double_api).to receive(:get_vm_info).and_return(@vm1) get :show, params: { id: 1 } expect(response).to have_http_status(:success).or have_http_status(408) end - it 'renders show page' do - allow(double_api).to receive(:get_vm_info).and_return({}) - expect(get(:show, params: { id: 1 })).to render_template('vms/show') + context 'when current user is user' do + context 'when user is associated to vm' do + before do + allow(double_api).to receive(:get_vm_info).and_return(@vm1) + end + + it 'renders show page' do + expect(get(:show, params: { id: 1 })).to render_template('vms/show') + end + end + + context 'when user is not associated to vm' do + before do + allow(double_api).to receive(:get_vm_info).and_return({}) + end + + it 'redirects' do + get :show, params: { id: 1 } + expect(response).to have_http_status 302 + end + end + end + + context 'when current user is admin' do + context 'when user is associated to vm' do + before do + allow(double_api).to receive(:get_vm_info).and_return(@vm1) + end + + it 'renders show page' do + expect(get(:show, params: { id: 1 })).to render_template('vms/show') + end + end + + context 'when user is not associated to vm' do + before do + allow(double_api).to receive(:get_vm_info).and_return(@vm1) + end + + it 'renders show page' do + expect(get(:show, params: { id: 1 })).to render_template('vms/show') + end + end end it 'returns http status not found when no vm found' do