From e75a6768957b07e7ffa4d5ac99dde99c6b0c1989 Mon Sep 17 00:00:00 2001 From: Pavel Shved Date: Thu, 31 May 2012 15:43:40 +0400 Subject: [PATCH] Add "assignee" JSON callback The callback reports the assignee of a package in a platform given. Used for integration with external bug trackers. --- .../platforms/maintainers_controller.rb | 40 +++++++++++++++++++ config/routes.rb | 4 ++ .../platforms/maintainers_controller_spec.rb | 28 +++++++++++-- 3 files changed, 68 insertions(+), 4 deletions(-) diff --git a/app/controllers/platforms/maintainers_controller.rb b/app/controllers/platforms/maintainers_controller.rb index 0d67980cd..4598b3cba 100644 --- a/app/controllers/platforms/maintainers_controller.rb +++ b/app/controllers/platforms/maintainers_controller.rb @@ -1,13 +1,53 @@ # -*- encoding : utf-8 -*- class Platforms::MaintainersController < ApplicationController + # External callbacks from bugzilla ET_CALLBACKS = [:assignee] before_filter :authenticate_user!, :except => ET_CALLBACKS load_and_authorize_resource :platform, :except => ET_CALLBACKS + # external callbacks are authorized with a lightweight scheme: they should only come from a specified IP addresses + before_filter :authenticate_external_tracker!, :only => ET_CALLBACKS + def index # Let's build a relation to query maintainers via 'build_list_packages' table @maintainers = BuildList::Package.maintainers.where(:platform_id => @platform).order('lower(name) ASC').includes(:project).paginate(:page => params[:page]) end + # Given platform_id, and the string that contains source or binary package name, or project name, find the email of the assignee of the project that contains the given package under the platform specified. + def assignee + ret = {} + # NOTE that platform is looked up here to handle the error of platform being not found + @platform = Platform.find(params[:platform_id]) rescue '' + @package = params[:package] + if @platform.blank? + ret[:error] = "ABF platform ##{params[:platform_id]} not found!" + elsif @package.blank? + # TODO: maybe, it should be the special case for "default" maintainer for the platform? + ret[:error] = "Package not specified" + else + # Ok, find a maintainer, and return it, if any. If source and binary package have the same name, we do not distinguish because most likely they'll have same assignee. + if maintainer = BuildList::Package.maintainers.where(:platform_id => @platform, :name => @package).includes(:project).first + ret[:assignee] = maintainer.assignee.email + # Package is not found; look for a project for this platform + elsif proj_id = @platform.repositories.joins(:projects).where(["projects.name = ?",@package]).select('projects.id').map(&:id).first + # Try to find a project? + begin + ret[:assignee] = Project.find(proj_id).assignee.email + rescue + ret[:error] = 'Not found' + end + else + ret[:error] = 'Not found' + end + end + render :json => ret + end + + protected + def authenticate_external_tracker! + if request.remote_ip != APP_CONFIG['external_tracker_ip'] + render :nothing => true, :status => 403 + end + end end diff --git a/config/routes.rb b/config/routes.rb index 3b61a460f..46a263b34 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -48,6 +48,10 @@ Rosa::Application.routes.draw do get :search, :on => :collection end + # Maintainer Database API + # (package name may contain dots, numbers, and all kinds of weird symbols, hence the :constraints relaxation) + match 'api/json/maintdb/assignee/:platform_id/:package' => 'platforms/maintainers#assignee', :format => :json, :constraints => { :package => /.*/ } + scope :module => 'platforms' do resources :platforms do resources :private_users, :except => [:show, :destroy, :update] diff --git a/spec/controllers/platforms/maintainers_controller_spec.rb b/spec/controllers/platforms/maintainers_controller_spec.rb index e59798eca..a2786813b 100644 --- a/spec/controllers/platforms/maintainers_controller_spec.rb +++ b/spec/controllers/platforms/maintainers_controller_spec.rb @@ -19,17 +19,37 @@ shared_examples_for 'guest user' do end describe Platforms::MaintainersController do - before(:each) do + before(:each) do stub_symlink_methods @platform = FactoryGirl.create(:platform) @platform.visibility = 'open' - end - context 'for guest' do - it_should_behave_like 'guest user' + @assignee_rq = { :platform_id => @platform.id, :package => 'test' } end + context 'for guest' do + it_should_behave_like 'guest user' + + it 'should not be able to get api' do + get :assignee, @assignee_rq + puts response.headers.inspect + response.response_code.should equal(403) + end + end + + context 'for bugzilla' do + before(:each) do + request.remote_addr = APP_CONFIG['external_tracker_ip'] + end + + it_should_behave_like 'guest user' + + it 'should be able to get api' do + get :assignee, @assignee_rq + response.response_code.should equal(200) + end + end end