Add SingletonSettingsEndpoint
This class allows to easily add an endpoint for a nested model in settings.
This commit is contained in:
parent
38e069567f
commit
4005760c8c
46
lib/travis/api/app/endpoint/singleton_settings_endpoint.rb
Normal file
46
lib/travis/api/app/endpoint/singleton_settings_endpoint.rb
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
require 'travis/api/app'
|
||||||
|
require 'travis/api/app/endpoint/setting_endpoint'
|
||||||
|
|
||||||
|
class Travis::Api::App
|
||||||
|
class SingletonSettingsEndpoint < SettingsEndpoint
|
||||||
|
class << self
|
||||||
|
def create_settings_class(name)
|
||||||
|
klass = Class.new(self) do
|
||||||
|
define_method(:name) { name }
|
||||||
|
get("/", scope: :private) do show end
|
||||||
|
patch("/", scope: :private) do update end
|
||||||
|
delete("/", scope: :private) do destroy end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
record = parent.update(name, JSON.parse(request.body.read)[singular_name])
|
||||||
|
if record.valid?
|
||||||
|
repo_settings.save
|
||||||
|
respond_with(record, type: singular_name, version: :v2)
|
||||||
|
else
|
||||||
|
status 422
|
||||||
|
respond_with(record, type: :validation_error, version: :v2)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def destroy
|
||||||
|
record = parent.delete(name)
|
||||||
|
repo_settings.save
|
||||||
|
respond_with(record, type: singular_name, version: :v2)
|
||||||
|
end
|
||||||
|
|
||||||
|
def record
|
||||||
|
parent.get(name) || record_not_found
|
||||||
|
end
|
||||||
|
|
||||||
|
def parent
|
||||||
|
repo_settings
|
||||||
|
end
|
||||||
|
|
||||||
|
def record_not_found
|
||||||
|
halt(404, { error: "Could not find a requested setting" })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
123
spec/integration/singleton_settings_endpoint_spec.rb
Normal file
123
spec/integration/singleton_settings_endpoint_spec.rb
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe Travis::Api::App::SettingsEndpoint do
|
||||||
|
let(:repo) { Repository.by_slug('svenfuchs/minimal').first }
|
||||||
|
let(:headers) { { 'HTTP_ACCEPT' => 'application/vnd.travis-ci.2+json' } }
|
||||||
|
|
||||||
|
before do
|
||||||
|
model_class = Class.new(Repository::Settings::Model) do
|
||||||
|
attribute :name, String
|
||||||
|
attribute :secret, Travis::Settings::EncryptedValue
|
||||||
|
|
||||||
|
validates :name, presence: true
|
||||||
|
validates :secret, presence: true
|
||||||
|
end
|
||||||
|
Repository::Settings.class_eval do
|
||||||
|
attribute :item, model_class
|
||||||
|
end
|
||||||
|
serializer_class = Class.new(Travis::Api::Serializer) do
|
||||||
|
attributes :name
|
||||||
|
end
|
||||||
|
Travis::Api::V2::Http.const_set(:Item, serializer_class)
|
||||||
|
|
||||||
|
add_settings_endpoint :item, singleton: true
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
Travis::Api::App.send :remove_const, :Item
|
||||||
|
Travis::Api::V2::Http.send :remove_const, :Item
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'with authenticated user' do
|
||||||
|
let(:user) { User.where(login: 'svenfuchs').first }
|
||||||
|
let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: -1) }
|
||||||
|
let(:headers) { { 'HTTP_ACCEPT' => 'application/vnd.travis-ci.2+json', 'HTTP_AUTHORIZATION' => "token #{token}" } }
|
||||||
|
|
||||||
|
before { user.permissions.create!(:repository_id => repo.id, :admin => true, :push => true) }
|
||||||
|
|
||||||
|
describe 'GET /item' do
|
||||||
|
it 'returns an item' do
|
||||||
|
settings = repo.settings
|
||||||
|
item = settings.create(:item, name: 'an item', secret: 'TEH SECRET')
|
||||||
|
settings.save
|
||||||
|
|
||||||
|
response = get '/settings/item', { repository_id: repo.id }, headers
|
||||||
|
json = JSON.parse(response.body)
|
||||||
|
json['item']['name'].should == 'an item'
|
||||||
|
json['item'].should_not have_key('secret')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns 404 if item can\'t be found' do
|
||||||
|
response = get '/settings/item', { repository_id: repo.id }, headers
|
||||||
|
json = JSON.parse(response.body)
|
||||||
|
json['error'].should == "Could not find a requested setting"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'PATCH /item' do
|
||||||
|
it 'should update an item' do
|
||||||
|
settings = repo.settings
|
||||||
|
item = settings.create(:item, name: 'an item', secret: 'TEH SECRET')
|
||||||
|
settings.save
|
||||||
|
|
||||||
|
body = { item: { name: 'a new name', secret: 'a new secret' } }.to_json
|
||||||
|
response = patch "/settings/item?repository_id=#{repo.id}", body, headers
|
||||||
|
json = JSON.parse(response.body)
|
||||||
|
json['item']['name'].should == 'a new name'
|
||||||
|
json['item'].should_not have_key('secret')
|
||||||
|
|
||||||
|
updated_item = repo.reload.settings.item
|
||||||
|
updated_item.name.should == 'a new name'
|
||||||
|
updated_item.secret.decrypt.should == 'a new secret'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'should create an item if it does not exist' do
|
||||||
|
repo.settings.item.should be_nil
|
||||||
|
|
||||||
|
body = { item: { name: 'a name', secret: 'a secret' } }.to_json
|
||||||
|
response = patch "/settings/item?repository_id=#{repo.id}", body, headers
|
||||||
|
json = JSON.parse(response.body)
|
||||||
|
json['item']['name'].should == 'a name'
|
||||||
|
json['item'].should_not have_key('secret')
|
||||||
|
|
||||||
|
item = repo.reload.settings.item
|
||||||
|
item.name.should == 'a name'
|
||||||
|
item.secret.decrypt.should == 'a secret'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns an error message if item is invalid' do
|
||||||
|
body = { item: { name: '' } }.to_json
|
||||||
|
response = patch "/settings/item?repository_id=#{repo.id}", body, headers
|
||||||
|
response.status.should == 422
|
||||||
|
|
||||||
|
json = JSON.parse(response.body)
|
||||||
|
json['message'].should == 'Validation failed'
|
||||||
|
json['errors'].should == [{
|
||||||
|
'field' => 'name',
|
||||||
|
'code' => 'missing_field'
|
||||||
|
}, {
|
||||||
|
'field' => 'secret',
|
||||||
|
'code' => 'missing_field'
|
||||||
|
}]
|
||||||
|
|
||||||
|
repo.reload.settings.item.should be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'DELETE /item' do
|
||||||
|
it 'should delete an item' do
|
||||||
|
settings = repo.settings
|
||||||
|
item = settings.create(:item, name: 'an item')
|
||||||
|
settings.save
|
||||||
|
|
||||||
|
params = { repository_id: repo.id }
|
||||||
|
response = delete '/settings/item', params, headers
|
||||||
|
json = JSON.parse(response.body)
|
||||||
|
json['item']['name'].should == 'an item'
|
||||||
|
json['item'].should_not have_key('secret')
|
||||||
|
|
||||||
|
repo.reload.settings.item.should be_nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -26,8 +26,12 @@ module TestHelpers
|
||||||
@custom_endpoints ||= []
|
@custom_endpoints ||= []
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_settings_endpoint(name)
|
def add_settings_endpoint(name, options = {})
|
||||||
Travis::Api::App::SettingsEndpoint.subclass(name)
|
if options[:singleton]
|
||||||
|
Travis::Api::App::SingletonSettingsEndpoint.subclass(name)
|
||||||
|
else
|
||||||
|
Travis::Api::App::SettingsEndpoint.subclass(name)
|
||||||
|
end
|
||||||
set_app Travis::Api::App.new
|
set_app Travis::Api::App.new
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user