Merge pull request #342 from abf/rosa-build:341-repository-packages-api

#341: repository packages api
This commit is contained in:
avm 2014-01-21 05:50:50 +04:00
commit 5954583959
7 changed files with 130 additions and 3 deletions

View File

@ -6,12 +6,26 @@ class Api::V1::BaseController < ApplicationController
rescue_from CanCan::AccessDenied do |exception| rescue_from CanCan::AccessDenied do |exception|
respond_to do |format| respond_to do |format|
format.json { render :json => {:message => t("flash.exception_message")}.to_json, :status => 403 } format.json { render json: {message: t('flash.exception_message')}.to_json, status: 403 }
format.csv { render text: t('flash.exception_message'), status: 403 }
end end
end end
protected protected
def set_csv_file_headers(file_name)
headers['Content-Type'] = 'text/csv'
headers['Content-disposition'] = "attachment; filename=\"#{file_name}.csv\""
end
def set_streaming_headers
# nginx doc: Setting this to "no" will allow unbuffered responses suitable for Comet and HTTP streaming applications
headers['X-Accel-Buffering'] = 'no'
headers['Cache-Control'] ||= 'no-cache'
headers.delete 'Content-Length'
end
def set_locale def set_locale
I18n.locale = :en I18n.locale = :en
end end

View File

@ -32,6 +32,36 @@ class Api::V1::RepositoriesController < Api::V1::BaseController
def key_pair def key_pair
end end
# Only one request per 15 minutes for each platform
def packages
key, now = [@repository.platform.id, :repository_packages], Time.zone.now
last_request = Rails.cache.read(key)
if last_request.present? && last_request + 15.minutes > now
raise CanCan::AccessDenied
else
Rails.cache.write(key, now, expires_at: 15.minutes)
respond_to do |format|
format.csv do
set_csv_file_headers :packages
set_streaming_headers
response.status = 200
# setting the body to an enumerator, rails will iterate this enumerator
self.response_body = Enumerator.new do |y|
y << Api::V1::RepositoryPackagePresenter.csv_header.to_s
BuildList::Package.by_repository(@repository) do |package|
y << Api::V1::RepositoryPackagePresenter.new(package).to_csv_row.to_s
end
end
end
end
end
end
def add_repo_lock_file def add_repo_lock_file
@repository.add_repo_lock_file @repository.add_repo_lock_file
render_json_response @repository, "'.repo.lock' file has been added to repository successfully" render_json_response @repository, "'.repo.lock' file has been added to repository successfully"

View File

@ -122,7 +122,7 @@ class Ability
can([:read, :projects_list, :projects], Repository, read_relations_for('repositories')) {|repository| can? :show, repository.platform} can([:read, :projects_list, :projects], Repository, read_relations_for('repositories')) {|repository| can? :show, repository.platform}
can([:read, :projects_list, :projects], Repository, read_relations_for('repositories', 'platforms')) {|repository| local_reader? repository.platform} can([:read, :projects_list, :projects], Repository, read_relations_for('repositories', 'platforms')) {|repository| local_reader? repository.platform}
can([:create, :edit, :update, :destroy, :projects_list, :projects, :add_project, :remove_project, :regenerate_metadata, :sync_lock_file, :add_repo_lock_file, :remove_repo_lock_file], Repository) {|repository| local_admin? repository.platform} can([:create, :edit, :update, :destroy, :projects_list, :projects, :add_project, :remove_project, :regenerate_metadata, :sync_lock_file, :add_repo_lock_file, :remove_repo_lock_file], Repository) {|repository| local_admin? repository.platform}
can([:remove_members, :remove_member, :add_member, :signatures], Repository) {|repository| owner?(repository.platform) || local_admin?(repository.platform)} can([:remove_members, :remove_member, :add_member, :signatures, :packages], Repository) {|repository| owner?(repository.platform) || local_admin?(repository.platform)}
can([:add_project, :remove_project], Repository) {|repository| repository.members.exists?(:id => user.id)} can([:add_project, :remove_project], Repository) {|repository| repository.members.exists?(:id => user.id)}
can(:clear, Platform) {|platform| owner?(platform) && platform.personal?} can(:clear, Platform) {|platform| owner?(platform) && platform.personal?}
can(:regenerate_metadata, Platform) {|platform| owner?(platform) || local_admin?(platform)} can(:regenerate_metadata, Platform) {|platform| owner?(platform) || local_admin?(platform)}
@ -167,6 +167,7 @@ class Ability
# Shared cannot rights for all users (registered, admin) # Shared cannot rights for all users (registered, admin)
cannot [:regenerate_metadata, :destroy], Platform, :platform_type => 'personal' cannot [:regenerate_metadata, :destroy], Platform, :platform_type => 'personal'
cannot [:create, :destroy], Repository, :platform => {:platform_type => 'personal'}, :name => 'main' cannot [:create, :destroy], Repository, :platform => {:platform_type => 'personal'}, :name => 'main'
cannot [:packages], Repository, :platform => {:platform_type => 'personal'}
cannot [:remove_members, :remove_member, :add_member, :sync_lock_file, :add_repo_lock_file, :remove_repo_lock_file], Repository, :platform => {:platform_type => 'personal'} cannot [:remove_members, :remove_member, :add_member, :sync_lock_file, :add_repo_lock_file, :remove_repo_lock_file], Repository, :platform => {:platform_type => 'personal'}
cannot :clear, Platform, :platform_type => 'main' cannot :clear, Platform, :platform_type => 'main'

View File

@ -28,7 +28,6 @@ class BuildList::Package < ActiveRecord::Base
project.maintainer project.maintainer
end end
# Comparison between versions # Comparison between versions
# @param [BuildList::Package] other # @param [BuildList::Package] other
# @return [Number] -1 if +other+ is greater than, 0 if +other+ is equal to, # @return [Number] -1 if +other+ is greater than, 0 if +other+ is equal to,
@ -37,6 +36,15 @@ class BuildList::Package < ActiveRecord::Base
RPM::C.rpmvercmp to_vre_epoch_zero, other.to_vre_epoch_zero RPM::C.rpmvercmp to_vre_epoch_zero, other.to_vre_epoch_zero
end end
def self.by_repository(repository, &block)
# find_each will batch the results instead of getting all in one go
actual.where(
build_lists: {save_to_repository_id: repository}
).joins(build_list: :save_to_repository).includes(project: :maintainer).find_each do |package|
yield package
end
end
protected protected
def set_epoch def set_epoch

View File

@ -0,0 +1,54 @@
require 'csv'
class Api::V1::RepositoryPackagePresenter < ApplicationPresenter
CSV_HEADERS = {
project_owner: 'Project owner',
project_name: 'Project name',
package_name: 'Package name',
epoch: 'Epoch',
version: 'Version',
release: 'Release',
maintainer_uname: 'Maintainer uname',
maintainer_email: 'Maintainer email',
committer_uname: 'Committer uname',
committer_email: 'Committer email'
}
attr_reader :package
delegate *%i(project name epoch version release assignee build_list), to: :package
def initialize(package)
@package = package
end
def to_csv_row
commit = project.repo.commit(build_list.commit_hash)
committer = User.where(email: commit.committer.email).first || commit.committer if commit
if committer.is_a? User
committer_uname, committer_email = committer.uname, committer.email
elsif committer.is_a? Grit::Actor
committer_uname, committer_email = committer.name, committer.email
end
CSV::Row.new(
CSV_HEADERS.keys,
[
project.owner_uname,
project.name,
name,
epoch,
version,
release,
assignee.uname,
assignee.email,
committer_uname,
committer_email
]
)
end
def self.csv_header
# Using ruby's built-in CSV::Row class
# true - means its a header
CSV::Row.new CSV_HEADERS.keys, CSV_HEADERS.values, true
end
end

View File

@ -44,6 +44,7 @@ Rosa::Application.routes.draw do
member { member {
get :projects get :projects
get :key_pair get :key_pair
get :packages
put :add_member put :add_member
delete :remove_member delete :remove_member
put :add_project put :add_project

View File

@ -12,6 +12,20 @@ shared_examples_for 'api repository user with reader rights for hidden platform'
it_should_behave_like 'api repository user with show rights' it_should_behave_like 'api repository user with show rights'
end end
shared_examples_for 'api repository user without packages rights' do
it 'should not be able to perform packages action' do
get :packages, :id => @repository.id, :format => :csv
response.should_not be_success
end
end
shared_examples_for 'api repository user with packages rights' do
it 'should be able to perform packages action' do
get :packages, :id => @repository.id, :format => :csv
response.should be_success
end
end
shared_examples_for 'api repository user without reader rights for hidden platform' do shared_examples_for 'api repository user without reader rights for hidden platform' do
before(:each) do before(:each) do
@platform.update_column(:visibility, 'hidden') @platform.update_column(:visibility, 'hidden')
@ -309,6 +323,7 @@ describe Api::V1::RepositoriesController do
it_should_behave_like 'api repository user without writer rights' it_should_behave_like 'api repository user without writer rights'
it_should_behave_like 'api repository user without project manage rights' it_should_behave_like 'api repository user without project manage rights'
it_should_behave_like 'api repository user without key_pair rights' it_should_behave_like 'api repository user without key_pair rights'
it_should_behave_like 'api repository user without packages rights'
it 'should not be able to perform projects action', :anonymous_access => false do it 'should not be able to perform projects action', :anonymous_access => false do
get :projects, :id => @repository.id, :format => :json get :projects, :id => @repository.id, :format => :json
@ -325,6 +340,7 @@ describe Api::V1::RepositoriesController do
it_should_behave_like 'api repository user with reader rights' it_should_behave_like 'api repository user with reader rights'
it_should_behave_like 'api repository user with reader rights for hidden platform' it_should_behave_like 'api repository user with reader rights for hidden platform'
it_should_behave_like 'api repository user with writer rights' it_should_behave_like 'api repository user with writer rights'
it_should_behave_like 'api repository user with packages rights'
it_should_behave_like 'api repository user without key_pair rights' it_should_behave_like 'api repository user without key_pair rights'
end end
@ -342,6 +358,7 @@ describe Api::V1::RepositoriesController do
it_should_behave_like 'api repository user with reader rights' it_should_behave_like 'api repository user with reader rights'
it_should_behave_like 'api repository user with reader rights for hidden platform' it_should_behave_like 'api repository user with reader rights for hidden platform'
it_should_behave_like 'api repository user with writer rights' it_should_behave_like 'api repository user with writer rights'
it_should_behave_like 'api repository user with packages rights'
it_should_behave_like 'api repository user without key_pair rights' it_should_behave_like 'api repository user without key_pair rights'
end end
@ -356,6 +373,7 @@ describe Api::V1::RepositoriesController do
it_should_behave_like 'api repository user with show rights' it_should_behave_like 'api repository user with show rights'
it_should_behave_like 'api repository user without writer rights' it_should_behave_like 'api repository user without writer rights'
it_should_behave_like 'api repository user without project manage rights' it_should_behave_like 'api repository user without project manage rights'
it_should_behave_like 'api repository user without packages rights'
it_should_behave_like 'api repository user without key_pair rights' it_should_behave_like 'api repository user without key_pair rights'
end end
@ -371,6 +389,7 @@ describe Api::V1::RepositoriesController do
it_should_behave_like 'api repository user with show rights' it_should_behave_like 'api repository user with show rights'
it_should_behave_like 'api repository user with project manage rights' it_should_behave_like 'api repository user with project manage rights'
it_should_behave_like 'api repository user without writer rights' it_should_behave_like 'api repository user without writer rights'
it_should_behave_like 'api repository user without packages rights'
it_should_behave_like 'api repository user without key_pair rights' it_should_behave_like 'api repository user without key_pair rights'
end end