Merge pull request #699 from warpc/698-rest-api-for-advisories
[refs #698]: REST API for Advisories
This commit is contained in:
commit
d6db260385
|
@ -5,8 +5,6 @@ class AdvisoriesController < ApplicationController
|
|||
load_resource :find_by => :advisory_id
|
||||
authorize_resource
|
||||
|
||||
before_filter :fetch_packages_info, :only => [:show]
|
||||
|
||||
def index
|
||||
@advisories = @advisories.scoped(:include => :platforms)
|
||||
@advisories = @advisories.search_by_id(params[:q]) if params[:q]
|
||||
|
@ -18,6 +16,7 @@ class AdvisoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def show
|
||||
@packages_info = @advisory.fetch_packages_info
|
||||
end
|
||||
|
||||
def search
|
||||
|
@ -27,24 +26,4 @@ class AdvisoriesController < ApplicationController
|
|||
format.json { render @advisory }
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# this method fetches and structurize packages attached to current advisory.
|
||||
def fetch_packages_info
|
||||
@packages_info = Hash.new { |h, k| h[k] = {} } # maaagic, it's maaagic ;)
|
||||
@advisory.build_lists.find_in_batches(:include => [:save_to_platform, :packages, :project]) do |batch|
|
||||
batch.each do |build_list|
|
||||
tmp = build_list.packages.inject({:srpm => nil, :rpm => []}) do |h, p|
|
||||
p.package_type == 'binary' ? h[:rpm] << p.fullname : h[:srpm] = p.fullname
|
||||
h
|
||||
end
|
||||
h = { build_list.project => tmp }
|
||||
@packages_info[build_list.save_to_platform].merge!(h) do |pr, old, new|
|
||||
{:srpm => new[:srpm], :rpm => old[:rpm].concat(new[:rpm]).uniq}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
# -*- encoding : utf-8 -*-
|
||||
class Api::V1::AdvisoriesController < Api::V1::BaseController
|
||||
before_filter :authenticate_user!
|
||||
skip_before_filter :authenticate_user!, :only => [:index, :show] if APP_CONFIG['anonymous_access']
|
||||
load_resource :advisory, :find_by => :advisory_id
|
||||
before_filter :find_and_authorize_build_list, :only => [:create, :update]
|
||||
authorize_resource :build_list, :only => [:create, :update]
|
||||
|
||||
def index
|
||||
@advisories = @advisories.scoped(:include => :platforms).
|
||||
paginate(paginate_params)
|
||||
end
|
||||
|
||||
def show
|
||||
@packages_info = @advisory.fetch_packages_info
|
||||
end
|
||||
|
||||
def create
|
||||
if @build_list.can_attach_to_advisory? &&
|
||||
@build_list.associate_and_create_advisory(params[:advisory]) &&
|
||||
@build_list.save
|
||||
render_json_response @advisory, 'Advisory has been created successfully'
|
||||
else
|
||||
render_validation_error @advisory, error_message(@build_list, 'Advisory has not been created')
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
if @advisory && @build_list.can_attach_to_advisory? &&
|
||||
@advisory.attach_build_list(@build_list) && @build_list.save
|
||||
render_json_response @advisory, "Build list '#{@build_list.id}' has been attached to advisory successfully"
|
||||
else
|
||||
render_validation_error @advisory, error_message(@build_list, 'Build list has not been attached to advisory')
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def find_and_authorize_build_list
|
||||
@build_list = BuildList.find params[:build_list_id]
|
||||
authorize! :update, @build_list.save_to_platform
|
||||
end
|
||||
|
||||
end
|
|
@ -83,7 +83,7 @@ class Api::V1::BaseController < ApplicationController
|
|||
id = status != 200 ? nil : subject.id
|
||||
|
||||
render :json => {
|
||||
subject.class.name.downcase.to_sym => {
|
||||
subject.class.name.underscore.to_sym => {
|
||||
:id => id,
|
||||
:message => message
|
||||
}
|
||||
|
|
|
@ -196,23 +196,13 @@ class Projects::BuildListsController < Projects::BaseController
|
|||
|
||||
if params[:attach_advisory] == 'new'
|
||||
# create new advisory
|
||||
unless @build_list.build_advisory(params[:build_list][:advisory]) do |a|
|
||||
a.update_type = @build_list.update_type
|
||||
a.projects << @build_list.project
|
||||
a.platforms << @build_list.save_to_platform unless a.platforms.include? @build_list.save_to_platform
|
||||
end.save
|
||||
unless @build_list.associate_and_create_advisory(params[:build_list][:advisory])
|
||||
redirect_to :back, :notice => t('layout.build_lists.publish_fail') and return
|
||||
end
|
||||
else
|
||||
# attach existing advisory
|
||||
a = Advisory.where(:advisory_id => params[:attach_advisory]).limit(1).first
|
||||
if a.update_type != @build_list.update_type
|
||||
redirect_to :back, :notice => t('layout.build_lists.publish_fail') and return
|
||||
end
|
||||
a.platforms << @build_list.save_to_platform unless a.platforms.include? @build_list.save_to_platform
|
||||
a.projects << @build_list.project unless a.projects.include? @build_list.project
|
||||
@build_list.advisory = a
|
||||
unless a.save
|
||||
a = Advisory.where(:advisory_id => params[:attach_advisory]).first
|
||||
unless (a && a.attach_build_list(@build_list))
|
||||
redirect_to :back, :notice => t('layout.build_lists.publish_fail') and return
|
||||
end
|
||||
end
|
||||
|
|
|
@ -21,6 +21,32 @@ class Advisory < ActiveRecord::Base
|
|||
advisory_id
|
||||
end
|
||||
|
||||
def attach_build_list(build_list)
|
||||
return false if update_type != build_list.update_type
|
||||
self.platforms << build_list.save_to_platform unless platforms.include? build_list.save_to_platform
|
||||
self.projects << build_list.project unless projects.include? build_list.project
|
||||
build_list.advisory = self
|
||||
save
|
||||
end
|
||||
|
||||
# this method fetches and structurize packages attached to current advisory.
|
||||
def fetch_packages_info
|
||||
packages_info = Hash.new { |h, k| h[k] = {} } # maaagic, it's maaagic ;)
|
||||
build_lists.find_in_batches(:include => [:save_to_platform, :packages, :project]) do |batch|
|
||||
batch.each do |build_list|
|
||||
tmp = build_list.packages.inject({:srpm => nil, :rpm => []}) do |h, p|
|
||||
p.package_type == 'binary' ? h[:rpm] << p.fullname : h[:srpm] = p.fullname
|
||||
h
|
||||
end
|
||||
h = { build_list.project => tmp }
|
||||
packages_info[build_list.save_to_platform].merge!(h) do |pr, old, new|
|
||||
{:srpm => new[:srpm], :rpm => old[:rpm].concat(new[:rpm]).uniq}
|
||||
end
|
||||
end
|
||||
end
|
||||
packages_info
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def generate_advisory_id
|
||||
|
|
|
@ -303,6 +303,18 @@ class BuildList < ActiveRecord::Base
|
|||
#[WAITING_FOR_RESPONSE, BuildServer::BUILD_PENDING, BuildServer::BUILD_STARTED].include?(status)
|
||||
end
|
||||
|
||||
def associate_and_create_advisory(params)
|
||||
build_advisory(params){ |a| a.update_type = update_type }
|
||||
advisory.attach_build_list(self)
|
||||
end
|
||||
|
||||
def can_attach_to_advisory?
|
||||
!save_to_repository.publish_without_qa &&
|
||||
save_to_platform.main? &&
|
||||
save_to_platform.released &&
|
||||
status == BUILD_PUBLISHED
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def notify_users
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
json.id advisory.advisory_id
|
||||
json.(advisory, :description)
|
||||
json.platforms advisory.platforms do |json_platform, platform|
|
||||
json_platform.(platform, :id, :released)
|
||||
json_platform.url api_v1_platform_path(platform.id, :format => :json)
|
||||
end
|
||||
json.projects advisory.projects do |json_project, project|
|
||||
json_project.(project, :id, :name)
|
||||
json_project.fullname project.name_with_owner
|
||||
json_project.url api_v1_project_path(project.id, :format => :json)
|
||||
end
|
||||
json.url api_v1_advisory_path(advisory.advisory_id, :format => :json)
|
|
@ -0,0 +1,4 @@
|
|||
json.advisories @advisories do |json, advisory|
|
||||
json.partial! 'advisory', :advisory => advisory, :json => json
|
||||
end
|
||||
json.url api_v1_advisories_path(:format => :json)
|
|
@ -0,0 +1,27 @@
|
|||
json.advisory do |json|
|
||||
json.partial! 'advisory', :advisory => @advisory, :json => json
|
||||
json.created_at @advisory.created_at.to_i
|
||||
json.updated_at @advisory.updated_at.to_i
|
||||
json.(@advisory, :update_type)
|
||||
json.references @advisory.references.split('\n')
|
||||
|
||||
json.build_lists @advisory.build_lists do |json_build_list, build_list|
|
||||
json_build_list.(build_list, :id)
|
||||
json_build_list.url api_v1_build_list_path(build_list.id, :format => :json)
|
||||
end
|
||||
|
||||
json.affected_in @packages_info do |json_platform, package_info|
|
||||
platform = package_info[0]
|
||||
json_platform.(platform, :id)
|
||||
json_platform.url api_v1_platform_path(platform.id, :format => :json)
|
||||
json_platform.projects package_info[1] do |json_project, info|
|
||||
project = info[0]
|
||||
json_project.(project, :id)
|
||||
json_project.url api_v1_project_path(project.id, :format => :json)
|
||||
packages = info[1]
|
||||
json_project.srpm packages[:srpm]
|
||||
json_project.rpm packages[:rpm]
|
||||
end
|
||||
end
|
||||
|
||||
end
|
|
@ -12,6 +12,7 @@ Rosa::Application.routes.draw do
|
|||
|
||||
namespace :api do
|
||||
namespace :v1 do
|
||||
resources :advisories, :only => [:index, :show, :create, :update]
|
||||
resources :build_lists, :only => [:index, :create, :show] do
|
||||
member {
|
||||
get :publish
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
# -*- encoding : utf-8 -*-
|
||||
require 'spec_helper'
|
||||
|
||||
shared_examples_for 'api advisories user with show rights' do
|
||||
it 'should be able to perform show action' do
|
||||
get :show, :id => @advisory.advisory_id, :format => :json
|
||||
response.should be_success
|
||||
end
|
||||
|
||||
it 'should be able to perform index action' do
|
||||
get :index, :format => :json
|
||||
response.should be_success
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples_for 'api advisories user with admin rights' do
|
||||
context 'api advisories user with create rights' do
|
||||
let(:params) { {:build_list_id => @build_list.id, :advisory => {:description => 'test'}} }
|
||||
it 'should be able to perform create action' do
|
||||
post :create, params, :format => :json
|
||||
response.should be_success
|
||||
end
|
||||
it 'ensures that advisory has been created' do
|
||||
lambda { post :create, params, :format => :json }.should change{ Advisory.count }.by(1)
|
||||
end
|
||||
it 'ensures that build_list has been associated with advisory' do
|
||||
post :create, params, :format => :json
|
||||
@build_list.reload
|
||||
@build_list.advisory.should_not be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'api advisories user with update rights' do
|
||||
let(:params) { {:id => @advisory.advisory_id, :build_list_id => @build_list.id} }
|
||||
it 'should be able to perform update action' do
|
||||
put :update, params, :format => :json
|
||||
response.should be_success
|
||||
end
|
||||
it 'ensures that advisory has not been created' do
|
||||
lambda { put :update, params, :format => :json }.should_not change{ Advisory.count }
|
||||
end
|
||||
it 'ensures that build_list has been associated with advisory' do
|
||||
put :update, params, :format => :json
|
||||
@build_list.reload
|
||||
@build_list.advisory.should_not be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples_for 'api advisories user without admin rights' do
|
||||
context 'api advisories user without create rights' do
|
||||
let(:params) { {:build_list_id => @build_list.id, :advisory => {:description => 'test'}} }
|
||||
it 'should not be able to perform create action' do
|
||||
post :create, params, :format => :json
|
||||
response.should_not be_success
|
||||
end
|
||||
it 'ensures that advisory has not been created' do
|
||||
lambda { post :create, params, :format => :json }.should_not change{ Advisory.count }
|
||||
end
|
||||
it 'ensures that build_list has not been associated with advisory' do
|
||||
post :create, params, :format => :json
|
||||
@build_list.reload
|
||||
@build_list.advisory.should be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'api advisories user without update rights' do
|
||||
let(:params) { {:id => @advisory.advisory_id, :build_list_id => @build_list.id} }
|
||||
it 'should not be able to perform update action' do
|
||||
put :update, params, :format => :json
|
||||
response.should_not be_success
|
||||
end
|
||||
it 'ensures that advisory has not been created' do
|
||||
lambda { put :update, params, :format => :json }.should_not change{ Advisory.count }
|
||||
end
|
||||
it 'ensures that build_list has not been associated with advisory' do
|
||||
put :update, params, :format => :json
|
||||
@build_list.reload
|
||||
@build_list.advisory.should be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe Api::V1::AdvisoriesController do
|
||||
|
||||
before do
|
||||
stub_symlink_methods
|
||||
|
||||
@advisory = FactoryGirl.create(:advisory)
|
||||
@build_list = FactoryGirl.create(:build_list_core)
|
||||
@build_list.save_to_platform.update_column(:released, true)
|
||||
@build_list.save_to_repository.update_column(:publish_without_qa, false)
|
||||
@build_list.update_column(:status, BuildList::BUILD_PUBLISHED)
|
||||
end
|
||||
|
||||
context 'for guest' do
|
||||
|
||||
if APP_CONFIG['anonymous_access']
|
||||
it_should_behave_like 'api advisories user with show rights'
|
||||
end
|
||||
|
||||
it 'should not be able to perform show action', :anonymous_access => false do
|
||||
get :show, :id => @advisory.advisory_id, :format => :json
|
||||
response.should_not be_success
|
||||
end
|
||||
|
||||
it 'should not be able to perform index action', :anonymous_access => false do
|
||||
get :index, :format => :json
|
||||
response.should_not be_success
|
||||
end
|
||||
it_should_behave_like 'api advisories user without admin rights'
|
||||
end
|
||||
|
||||
context 'for simple user' do
|
||||
before do
|
||||
@user = FactoryGirl.create(:user)
|
||||
http_login(@user)
|
||||
end
|
||||
it_should_behave_like 'api advisories user with show rights'
|
||||
it_should_behave_like 'api advisories user without admin rights'
|
||||
end
|
||||
|
||||
context 'for admin' do
|
||||
before do
|
||||
@admin = FactoryGirl.create(:admin)
|
||||
http_login(@admin)
|
||||
end
|
||||
|
||||
it_should_behave_like 'api advisories user with show rights'
|
||||
it_should_behave_like 'api advisories user with admin rights'
|
||||
end
|
||||
|
||||
context 'for user who has access to update build_list' do
|
||||
before do
|
||||
@user = FactoryGirl.create(:user)
|
||||
@build_list.save_to_platform.relations.create(:role => 'admin', :actor => @user)
|
||||
http_login(@user)
|
||||
end
|
||||
|
||||
it_should_behave_like 'api advisories user with show rights'
|
||||
it_should_behave_like 'api advisories user with admin rights'
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,7 @@
|
|||
# -*- encoding : utf-8 -*-
|
||||
FactoryGirl.define do
|
||||
factory :advisory do
|
||||
description { FactoryGirl.generate(:string) }
|
||||
update_type 'security'
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue