From 7d0b2998dc05ec0c0c914c7685e0681094b64929 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Tue, 8 Apr 2014 01:30:01 +0400 Subject: [PATCH] #373: refactoring, added specs --- .../api/v1/platforms_controller.rb | 24 +++++++++++-- app/models/platform.rb | 36 +++++++++++-------- config/routes.rb | 5 +-- .../api/v1/platforms_controller_spec.rb | 14 ++++++++ 4 files changed, 60 insertions(+), 19 deletions(-) diff --git a/app/controllers/api/v1/platforms_controller.rb b/app/controllers/api/v1/platforms_controller.rb index 4fdeccf63..d8b8c2b53 100644 --- a/app/controllers/api/v1/platforms_controller.rb +++ b/app/controllers/api/v1/platforms_controller.rb @@ -1,12 +1,14 @@ class Api::V1::PlatformsController < Api::V1::BaseController before_filter :authenticate_user! skip_before_filter :authenticate_user!, only: :allowed - skip_before_filter :authenticate_user!, only: [:show, :platforms_for_build, :members] if APP_CONFIG['anonymous_access'] + skip_before_filter :authenticate_user!, only: %i(show platforms_for_build members cached_chroot) if APP_CONFIG['anonymous_access'] + before_filter :set_token, only: %i(allowed cached_chroot) - load_and_authorize_resource except: :allowed + load_and_authorize_resource except: %i(allowed cached_chroot) + load_resource only: :cached_chroot def allowed - if Platform.allowed?(params[:path] || '', request) + if Platform.allowed?(params[:path] || '', @token) render nothing: true else render nothing: true, status: 403 @@ -21,6 +23,14 @@ class Api::V1::PlatformsController < Api::V1::BaseController def show end + def cached_chroot + if sha1 = @platform.cached_chroot(@token, params[:arch]) + redirect_to "#{APP_CONFIG['file_store_url']}/api/v1/file_stores/#{sha1}" + else + render nothing: true, status: 403 + end + end + def platforms_for_build @platforms = Platform.main.opened.paginate(paginate_params) render :index @@ -72,4 +82,12 @@ class Api::V1::PlatformsController < Api::V1::BaseController destroy_subject @platform end + protected + + def set_token + if request.authorization.present? + @token, pass = *ActionController::HttpAuthentication::Basic::user_name_and_password(request) + end + end + end diff --git a/app/models/platform.rb b/app/models/platform.rb index 7b8fbc5fc..b1b5fe8f5 100644 --- a/app/models/platform.rb +++ b/app/models/platform.rb @@ -7,6 +7,7 @@ class Platform < ActiveRecord::Base include Owner include EventLoggable + CACHED_CHROOT_PRODUCT_NAME = 'cached-chroot' AUTOMATIC_METADATA_REGENERATIONS = %w(day week) VISIBILITIES = %w(open hidden) NAME_PATTERN = /[\w\-\.]+/ @@ -211,34 +212,41 @@ class Platform < ActiveRecord::Base end # Checks access rights to platform and caching for 1 day. - def self.allowed?(path, request) + def self.allowed?(path, token) platform_name = path.gsub(/^[\/]+/, '') .match(/^(#{NAME_PATTERN}\/|#{NAME_PATTERN}$)/) return true unless platform_name platform_name = platform_name[0].gsub(/\//, '') - if request.authorization.present? - token, pass = *ActionController::HttpAuthentication::Basic::user_name_and_password(request) - end - Rails.cache.fetch([platform_name, token, :platform_allowed], expires_in: 2.minutes) do platform = Platform.find_by name: platform_name next false unless platform next true unless platform.hidden? next false unless token - next true if platform.tokens.by_active.where(authentication_token: token).exists? - - user = User.find_by authentication_token: token - current_ability = Ability.new(user) - if user && current_ability.can?(:show, platform) - true - else - false - end + platform.has_access?(token) end end + def cached_chroot(token, arch) + return false if personal? + Rails.cache.fetch([:cached_chroot, token, name, arch], expires_in: 10.minutes) do + product = products.where(name: CACHED_CHROOT_PRODUCT_NAME).first + next false unless product + pbl = product.product_build_lists.for_status(ProductBuildList::BUILD_COMPLETED).recent.first + next false unless pbl + next false if hidden? && !has_access?(token) + pbl.results.results.find{ |r| r['file_name'] =~ /^cached-chroot-#{arch}/ } || false + end + end + + def has_access?(token) + return true if tokens.by_active.where(authentication_token: token).exists? + user = User.find_by(authentication_token: token) + current_ability = Ability.new(user) + user && current_ability.can?(:show, self) ? true : false + end + def self.autostart_metadata_regeneration(value) Platform.main.where(automatic_metadata_regeneration: value).each(&:regenerate) end diff --git a/config/routes.rb b/config/routes.rb index 10f43ecef..96c4bda6b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -33,13 +33,14 @@ Rosa::Application.routes.draw do put :publish_into_testing } end - resources :arches, only: [:index] - resources :platforms, only: [:index, :show, :update, :destroy, :create] do + resources :arches, only: :index + resources :platforms, only: %i(index show update destroy create), constraints: { id: Platform::NAME_PATTERN } do collection { get :platforms_for_build get :allowed } member { + get :cached_chroot get :members put :add_member delete :remove_member diff --git a/spec/controllers/api/v1/platforms_controller_spec.rb b/spec/controllers/api/v1/platforms_controller_spec.rb index b30d0f061..68735259f 100644 --- a/spec/controllers/api/v1/platforms_controller_spec.rb +++ b/spec/controllers/api/v1/platforms_controller_spec.rb @@ -12,6 +12,7 @@ shared_examples_for 'api platform user with reader rights' do get :members, id: @platform.id, format: :json response.should render_template(:members) end + end shared_examples_for 'api platform user with owner rights' do @@ -192,6 +193,12 @@ shared_examples_for 'api platform user without reader rights for hidden platform response.body.should == {"message" => "Access violation to this page!"}.to_json end end + + it "should not be able to perform cached_chroot action" do + get :cached_chroot, id: @platform.id, format: :json + response.status.should == 403 + end + end shared_examples_for "api platform user with show rights" do @@ -200,6 +207,13 @@ shared_examples_for "api platform user with show rights" do response.should render_template(:show) end + it 'should be able to perform cached_chroot action' do + Rails.stub_chain(:cache, :fetch).and_return('sha1') + http_login (@admin || @user).authentication_token, '' if @platform.hidden? + get :cached_chroot, id: @platform.id, format: :json + response.should redirect_to("#{APP_CONFIG['file_store_url']}/api/v1/file_stores/sha1") + end + it 'should be able to perform platforms_for_build action' do get :platforms_for_build, format: :json response.should render_template(:index)