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
|
load_resource :find_by => :advisory_id
|
||||||
authorize_resource
|
authorize_resource
|
||||||
|
|
||||||
before_filter :fetch_packages_info, :only => [:show]
|
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@advisories = @advisories.scoped(:include => :platforms)
|
@advisories = @advisories.scoped(:include => :platforms)
|
||||||
@advisories = @advisories.search_by_id(params[:q]) if params[:q]
|
@advisories = @advisories.search_by_id(params[:q]) if params[:q]
|
||||||
|
@ -18,6 +16,7 @@ class AdvisoriesController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def show
|
def show
|
||||||
|
@packages_info = @advisory.fetch_packages_info
|
||||||
end
|
end
|
||||||
|
|
||||||
def search
|
def search
|
||||||
|
@ -27,24 +26,4 @@ class AdvisoriesController < ApplicationController
|
||||||
format.json { render @advisory }
|
format.json { render @advisory }
|
||||||
end
|
end
|
||||||
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
|
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
|
id = status != 200 ? nil : subject.id
|
||||||
|
|
||||||
render :json => {
|
render :json => {
|
||||||
subject.class.name.downcase.to_sym => {
|
subject.class.name.underscore.to_sym => {
|
||||||
:id => id,
|
:id => id,
|
||||||
:message => message
|
:message => message
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,23 +196,13 @@ class Projects::BuildListsController < Projects::BaseController
|
||||||
|
|
||||||
if params[:attach_advisory] == 'new'
|
if params[:attach_advisory] == 'new'
|
||||||
# create new advisory
|
# create new advisory
|
||||||
unless @build_list.build_advisory(params[:build_list][:advisory]) do |a|
|
unless @build_list.associate_and_create_advisory(params[:build_list][:advisory])
|
||||||
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
|
|
||||||
redirect_to :back, :notice => t('layout.build_lists.publish_fail') and return
|
redirect_to :back, :notice => t('layout.build_lists.publish_fail') and return
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
# attach existing advisory
|
# attach existing advisory
|
||||||
a = Advisory.where(:advisory_id => params[:attach_advisory]).limit(1).first
|
a = Advisory.where(:advisory_id => params[:attach_advisory]).first
|
||||||
if a.update_type != @build_list.update_type
|
unless (a && a.attach_build_list(@build_list))
|
||||||
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
|
|
||||||
redirect_to :back, :notice => t('layout.build_lists.publish_fail') and return
|
redirect_to :back, :notice => t('layout.build_lists.publish_fail') and return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -21,6 +21,32 @@ class Advisory < ActiveRecord::Base
|
||||||
advisory_id
|
advisory_id
|
||||||
end
|
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
|
protected
|
||||||
|
|
||||||
def generate_advisory_id
|
def generate_advisory_id
|
||||||
|
|
|
@ -303,6 +303,18 @@ class BuildList < ActiveRecord::Base
|
||||||
#[WAITING_FOR_RESPONSE, BuildServer::BUILD_PENDING, BuildServer::BUILD_STARTED].include?(status)
|
#[WAITING_FOR_RESPONSE, BuildServer::BUILD_PENDING, BuildServer::BUILD_STARTED].include?(status)
|
||||||
end
|
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
|
protected
|
||||||
|
|
||||||
def notify_users
|
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 :api do
|
||||||
namespace :v1 do
|
namespace :v1 do
|
||||||
|
resources :advisories, :only => [:index, :show, :create, :update]
|
||||||
resources :build_lists, :only => [:index, :create, :show] do
|
resources :build_lists, :only => [:index, :create, :show] do
|
||||||
member {
|
member {
|
||||||
get :publish
|
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