Merge pull request #689 from warpc/672-rest-api-for-repositories

[refs #672]: REST API for Refositories
This commit is contained in:
Vladimir Sharshov 2012-10-15 04:44:08 -07:00
commit 8c7ac11ec7
8 changed files with 320 additions and 39 deletions

View File

@ -10,6 +10,38 @@ class Api::V1::BaseController < ApplicationController
protected
def add_member_to_subject(subject)
class_name = subject.class.name.downcase
if member.present? && subject.add_member(member)
render_json_response subject, "#{member.class.to_s} '#{member.id}' has been added to #{class_name} successfully"
else
render_validation_error subject, "Member has not been added to #{class_name}"
end
end
def remove_member_from_subject(subject)
class_name = subject.class.name.downcase
if member.present? && subject.remove_member(member)
render_json_response subject, "#{member.class.to_s} '#{member.id}' has been removed from #{class_name} successfully"
else
render_validation_error subject, "Member has not been removed from #{class_name}"
end
end
def destroy_subject(subject)
subject.destroy # later with resque
render_json_response subject, "#{subject.class.name} has been destroyed successfully"
end
def update_subject(subject)
class_name = subject.class.name
if subject.update_attributes(params[class_name.downcase.to_sym] || {})
render_json_response subject, "#{class_name} has been updated successfully"
else
render_validation_error subject, "#{class_name} has not been updated"
end
end
def paginate_params
per_page = params[:per_page].to_i
per_page = 20 if per_page < 1
@ -36,4 +68,13 @@ class Api::V1::BaseController < ApplicationController
render_json_response(subject, message, 422)
end
private
def member
if @member.blank? && %w(User Group).include?(params[:type])
@member = params[:type].constantize.where(:id => params[:member_id]).first
end
@member
end
end

View File

@ -33,11 +33,7 @@ class Api::V1::PlatformsController < Api::V1::BaseController
platform_params = params[:platform] || {}
owner = User.where(:id => platform_params[:owner_id]).first
platform_params[:owner] = owner if owner
if @platform.update_attributes(platform_params)
render_json_response @platform, 'Platform has been updated successfully'
else
render_validation_error @platform, 'Platform has not been updated'
end
update_subject @platform
end
def members
@ -45,19 +41,11 @@ class Api::V1::PlatformsController < Api::V1::BaseController
end
def add_member
if member.present? && @platform.add_member(member)
render_json_response @platform, "#{member.class.to_s} '#{member.id}' has been added to platform successfully"
else
render_validation_error @platform, 'Member has not been added to platform'
end
add_member_to_subject @platform
end
def remove_member
if member.present? && @platform.remove_member(member)
render_json_response @platform, "#{member.class.to_s} '#{member.id}' has been removed from platform successfully"
else
render_validation_error @platform, 'Member has not been removed from platform'
end
remove_member_from_subject @platform
end
def clone
@ -77,21 +65,7 @@ class Api::V1::PlatformsController < Api::V1::BaseController
end
def destroy
@platform.destroy # later with resque
render_json_response @platform, 'Platform has been destroyed successfully'
end
private
def member
return @member if @member
if params[:type] == 'User'
member = User
elsif params[:type] == 'Group'
member = Group
end
@member = member.where(:id => params[:member_id]).first if member
@member ||= ''
destroy_subject @platform
end
end

View File

@ -7,7 +7,57 @@ class Api::V1::RepositoriesController < Api::V1::BaseController
load_and_authorize_resource :repository, :through => :platform, :shallow => true
def show
end
end
def update
update_subject @repository
end
def add_member
add_member_to_subject @repository
end
def remove_member
remove_member_from_subject @repository
end
def destroy
destroy_subject @repository
end
def add_project
project = Project.where(:id => params[:project_id]).first
if project
begin
@repository.projects << project
render_json_response @repository, "Project '#{project.id}' has been added to repository successfully"
rescue ActiveRecord::RecordInvalid
render_validation_error @repository, t('flash.repository.project_not_added')
end
else
render_validation_error @repository, "Project has not been added to repository"
end
end
def remove_project
project_id = params[:project_id]
ProjectToRepository.where(:project_id => project_id, :repository_id => @repository.id).destroy_all
render_json_response @repository, "Project '#{project_id}' has been removed from repository successfully"
end
def signatures
key_pair = @repository.key_pair
key_pair.destroy if key_pair
key_pair = @repository.build_key_pair(params[:repository])
key_pair.user_id = current_user.id
if key_pair.save
render_json_response @repository, 'Signatures have been updated for repository successfully'
else
message = 'Signatures have not been updated for repository'
errors = key_pair.errors.full_messages.join('. ')
(message << '. ' << errors) if errors.present?
render_json_response @repository, message, 422
end
end
end

View File

@ -131,8 +131,7 @@ class Platforms::RepositoriesController < Platforms::BaseController
end
def remove_project
@project = Project.find(params[:project_id])
ProjectToRepository.where(:project_id => @project.id, :repository_id => @repository.id).destroy_all
ProjectToRepository.where(:project_id => params[:project_id], :repository_id => @repository.id).destroy_all
redirect_to platform_repository_path(@platform, @repository), :notice => t('flash.repository.project_removed')
end

View File

@ -100,7 +100,7 @@ class Ability
can [:read, :projects_list], Repository, :platform => {:owner_type => 'Group', :owner_id => user.group_ids}
can([:read, :projects_list], Repository, read_relations_for('repositories', 'platforms')) {|repository| local_reader? repository.platform}
can([:create, :edit, :update, :destroy, :projects_list, :add_project, :remove_project], Repository) {|repository| local_admin? repository.platform}
can([:remove_members, :remove_member, :add_member], Repository) {|repository| owner?(repository.platform) || local_admin?(repository.platform)}
can([:remove_members, :remove_member, :add_member, :signatures], Repository) {|repository| owner?(repository.platform) || local_admin?(repository.platform)}
can([:add_project, :remove_project], Repository) {|repository| repository.members.exists?(:id => user.id)}
can(:clear, Platform) {|platform| local_admin?(platform) && platform.personal?}
can([:change_visibility, :settings, :destroy, :edit, :update], Repository) {|repository| owner? repository.platform}

View File

@ -32,7 +32,15 @@ Rosa::Application.routes.draw do
put :clear
}
end
resources :repositories, :only => [:show]
resources :repositories, :only => [:show, :update, :destroy] do
member {
put :add_member
delete :remove_member
put :add_project
delete :remove_project
put :signatures
}
end
resources :projects, :only => [:show] do
collection { get :get_id }
member {

View File

@ -52,7 +52,7 @@ shared_examples_for 'api platform user with writer rights' do
delete :remove_member, {:member_id => member.id, :type => 'User', :id => @platform.id}, :format => :json
end
it 'should be able to perform update action' do
it 'should be able to perform remove_member action' do
response.should be_success
end
it 'ensures that member has been removed from platform' do

View File

@ -35,6 +35,209 @@ shared_examples_for "api repository user without show rights" do
end
end
shared_examples_for 'api repository user with writer rights' do
context 'api repository user with update rights' do
before do
put :update, {:repository => {:description => 'new description'}, :id => @repository.id}, :format => :json
end
it 'should be able to perform update action' do
response.should be_success
end
it 'ensures that repository has been updated' do
@repository.reload
@repository.description.should == 'new description'
end
end
context 'api repository user with add_member rights' do
let(:member) { FactoryGirl.create(:user) }
before do
put :add_member, {:member_id => member.id, :type => 'User', :id => @repository.id}, :format => :json
end
it 'should be able to perform add_member action' do
response.should be_success
end
it 'ensures that new member has been added to repository' do
@repository.members.should include(member)
end
end
context 'api repository user with remove_member rights' do
let(:member) { FactoryGirl.create(:user) }
before do
@repository.add_member(member)
delete :remove_member, {:member_id => member.id, :type => 'User', :id => @repository.id}, :format => :json
end
it 'should be able to perform remove_member action' do
response.should be_success
end
it 'ensures that member has been removed from repository' do
@repository.members.should_not include(member)
end
end
context 'api repository user with destroy rights' do
it 'should be able to perform destroy action for main platform' do
delete :destroy, :id => @repository.id, :format => :json
response.should be_success
end
it 'ensures that repository of main platform has been destroyed' do
lambda { delete :destroy, :id => @repository.id, :format => :json }.should change{ Repository.count }.by(-1)
end
it 'should not be able to perform destroy action for repository of personal platform' do
delete :destroy, :id => @personal_repository.id, :format => :json
response.should_not be_success
end
it 'ensures that repository of personal platform has not been destroyed' do
lambda { delete :destroy, :id => @personal_repository.id, :format => :json }.should_not change{ Repository.count }
end
end
context 'api repository user with add_project rights' do
before { put :add_project, :id => @repository.id, :project_id => @project.id, :format => :json }
it 'should be able to perform add_project action' do
response.should be_success
end
it 'ensures that project has been added to repository' do
@repository.projects.should include(@project)
end
end
context 'api repository user with remove_project rights' do
before do
@repository.projects << @project
delete :remove_project, :id => @repository.id, :project_id => @project.id, :format => :json
end
it 'should be able to perform remove_project action' do
response.should be_success
end
it 'ensures that project has been removed from repository' do
@repository.reload
@repository.projects.should_not include(@project)
end
end
context 'api repository user with update signatures rights' do
before do
stub_key_pairs_calls
put :signatures, :id => @repository.id, :repository => {:public => 'iampublic', :secret => 'iamsecret'}, :format => :json
end
it 'should be able to perform signatures action' do
response.should be_success
end
it 'ensures that signatures has been updated' do
@repository.key_pair.should_not be_nil
end
end
end
shared_examples_for 'api repository user without writer rights' do
context 'api repository user without update rights' do
before do
put :update, {:repository => {:description => 'new description'}, :id => @repository.id}, :format => :json
end
it 'should not be able to perform update action' do
response.should_not be_success
end
it 'ensures that repository has not been updated' do
@repository.reload
@repository.description.should_not == 'new description'
end
end
context 'api repository user without add_member rights' do
let(:member) { FactoryGirl.create(:user) }
before do
put :add_member, {:member_id => member.id, :type => 'User', :id => @repository.id}, :format => :json
end
it 'should not be able to perform add_member action' do
response.should_not be_success
end
it 'ensures that new member has not been added to repository' do
@repository.members.should_not include(member)
end
end
context 'api repository user without remove_member rights' do
let(:member) { FactoryGirl.create(:user) }
before do
@repository.add_member(member)
delete :remove_member, {:member_id => member.id, :type => 'User', :id => @repository.id}, :format => :json
end
it 'should be able to perform update action' do
response.should_not be_success
end
it 'ensures that member has not been removed from repository' do
@repository.members.should include(member)
end
end
context 'api repository user without destroy rights' do
it 'should not be able to perform destroy action for repository of main platform' do
delete :destroy, :id => @repository.id, :format => :json
response.should_not be_success
end
it 'ensures that repository of main platform has not been destroyed' do
lambda { delete :destroy, :id => @repository.id, :format => :json }.should_not change{ Repository.count }
end
it 'should not be able to perform destroy action for repository of personal platform' do
delete :destroy, :id => @personal_repository.id, :format => :json
response.should_not be_success
end
it 'ensures that repository of personal platform has not been destroyed' do
lambda { delete :destroy, :id => @personal_repository.id, :format => :json }.should_not change{ Repository.count }
end
end
context 'api repository user without add_project rights' do
before { put :add_project, :id => @repository.id, :project_id => @project.id, :format => :json }
it 'should not be able to perform add_project action' do
response.should_not be_success
end
it 'ensures that project has not been added to repository' do
@repository.projects.should_not include(@project)
end
end
context 'api repository user without remove_project rights' do
before do
@repository.projects << @project
delete :remove_project, :id => @repository.id, :project_id => @project.id, :format => :json
end
it 'should not be able to perform remove_project action' do
response.should_not be_success
end
it 'ensures that project has not been removed from repository' do
@repository.reload
@repository.projects.should include(@project)
end
end
context 'api repository user without update signatures rights' do
before do
stub_key_pairs_calls
put :signatures, :id => @repository.id, :repository => {:public => 'iampublic', :secret => 'iamsecret'}, :format => :json
end
it 'should not be able to perform signatures action' do
response.should_not be_success
end
it 'ensures that signatures has not been updated' do
@repository.key_pair.should be_nil
end
end
end
describe Api::V1::RepositoriesController do
before(:each) do
stub_symlink_methods
@ -52,8 +255,11 @@ describe Api::V1::RepositoriesController do
response.status.should == 401
end
it_should_behave_like 'api repository user without reader rights for hidden platform' if APP_CONFIG['anonymous_access']
it_should_behave_like 'api repository user with show rights' if APP_CONFIG['anonymous_access']
if APP_CONFIG['anonymous_access']
it_should_behave_like 'api repository user without reader rights for hidden platform'
it_should_behave_like 'api repository user with show rights'
end
it_should_behave_like 'api repository user without writer rights'
end
context 'for admin' do
@ -64,6 +270,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 for hidden platform'
it_should_behave_like 'api repository user with writer rights'
end
context 'for platform owner user' do
@ -77,6 +284,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 for hidden platform'
it_should_behave_like 'api repository user with writer rights'
end
context 'for user' do
@ -88,5 +296,6 @@ describe Api::V1::RepositoriesController do
it_should_behave_like 'api repository user with reader rights'
it_should_behave_like 'api repository user without reader rights for hidden platform'
it_should_behave_like 'api repository user with show rights'
it_should_behave_like 'api repository user without writer rights'
end
end