implement accounts api

This commit is contained in:
Konstantin Haase 2015-04-13 13:12:18 +02:00
parent 0511223ca5
commit 5efdcc24c8
10 changed files with 175 additions and 20 deletions

View File

@ -50,7 +50,7 @@ GIT
GIT GIT
remote: git://github.com/travis-ci/travis-core.git remote: git://github.com/travis-ci/travis-core.git
revision: ba10e214824632f15598555a2634ce3347d2f227 revision: 4834399048b8c9cff4882d435f770826930665f6
specs: specs:
travis-core (0.0.1) travis-core (0.0.1)
actionmailer (~> 3.2.19) actionmailer (~> 3.2.19)
@ -81,7 +81,7 @@ GIT
GIT GIT
remote: git://github.com/travis-ci/travis-support.git remote: git://github.com/travis-ci/travis-support.git
revision: 4fdd220ed7b06a12951e5d74a763c05a80eb0d20 revision: e7f81093f83bd029cca6508739c5720e57e3d571
specs: specs:
travis-support (0.0.1) travis-support (0.0.1)

View File

@ -0,0 +1,20 @@
module Travis::API::V3
class Queries::Account < Query
def find
find!(:organization) || find!(:user)
end
private
def query(type, main_type: self.main_type, params: self.params)
main_type = type if main_type == :account
params = params.merge("#{type}.login" => params["account.login".freeze]) if params["account.login".freeze]
Queries[type].new(params, main_type)
end
def find!(type)
query(type).find
rescue WrongParams => e
end
end
end

View File

@ -1,10 +1,11 @@
module Travis::API::V3 module Travis::API::V3
class Queries::Organization < Query class Queries::Organization < Query
params :id params :id, :login
def find def find
return Models::Organization.find_by_id(id) if id return Models::Organization.find_by_id(id) if id
raise WrongParams, 'missing organization.id'.freeze return Models::Organization.find_by_login(login) if login
raise WrongParams, 'missing organization.id or organization.login'.freeze
end end
end end
end end

View File

@ -1,10 +1,11 @@
module Travis::API::V3 module Travis::API::V3
class Queries::User < Query class Queries::User < Query
params :id params :id, :login
def find def find
return Models::User.find_by_id(id) if id return Models::User.find_by_id(id) if id
raise WrongParams, 'missing user.id'.freeze return Models::User.find_by_login(login) if login
raise WrongParams, 'missing user.id or user.login'.freeze
end end
end end
end end

View File

@ -3,6 +3,11 @@ module Travis::API::V3
require 'travis/api/v3/routes/dsl' require 'travis/api/v3/routes/dsl'
extend DSL extend DSL
resource :account do
route '/account/({account.login}|{user.login}|{organization.login})'
get :find
end
resource :repository do resource :repository do
route '/repo/{repository.id}' route '/repo/{repository.id}'
get :find get :find

View File

@ -16,15 +16,15 @@ module Travis::API::V3
@github = {} @github = {}
end end
def query(type = self.class.result_type) def query(type = result_type)
@queries[type] ||= Queries[type].new(params, self.class.result_type) @queries[type] ||= Queries[type].new(params, result_type)
end end
def github(user = nil) def github(user = nil)
@github[user] ||= GitHub.new(user) @github[user] ||= GitHub.new(user)
end end
def find(type = self.class.result_type, *args) def find(type = result_type, *args)
not_found(true, type) unless object = query(type).find(*args) not_found(true, type) unless object = query(type).find(*args)
not_found(false, type) unless access_control.visible? object not_found(false, type) unless access_control.visible? object
object object
@ -33,16 +33,20 @@ module Travis::API::V3
def not_found(actually_not_found = false, type = nil) def not_found(actually_not_found = false, type = nil)
type, actually_not_found = actually_not_found, false if actually_not_found.is_a? Symbol type, actually_not_found = actually_not_found, false if actually_not_found.is_a? Symbol
error = actually_not_found ? EntityMissing : NotFound error = actually_not_found ? EntityMissing : NotFound
raise(error, type || self.class.result_type) raise(error, type || result_type)
end end
def run! def run!
not_implemented not_implemented
end end
def result_type
self.class.result_type
end
def run def run
not_found unless result = run! not_found unless result = run!
result = Result.new(self.class.result_type, result) unless result.is_a? Result result = Result.new(result_type, result) unless result.is_a? Result
result result
end end
@ -53,7 +57,7 @@ module Travis::API::V3
end end
def accepted(**payload) def accepted(**payload)
payload[:resource_type] ||= self.class.result_type payload[:resource_type] ||= result_type
Result.new(:accepted, payload, status: 202) Result.new(:accepted, payload, status: 202)
end end

View File

@ -2,6 +2,7 @@ module Travis::API::V3
module Services module Services
extend ConstantResolver extend ConstantResolver
Account = Module.new { extend Services }
Branch = Module.new { extend Services } Branch = Module.new { extend Services }
Build = Module.new { extend Services } Build = Module.new { extend Services }
Organization = Module.new { extend Services } Organization = Module.new { extend Services }

View File

@ -0,0 +1,20 @@
module Travis::API::V3
class Services::Account::Find < Service
def result_type
@result_type ||= super
end
def run!
account = find
@result_type = type_for(account)
account
end
def type_for(account)
case account
when Models::User then :user
when Models::Organization then :organization
end
end
end
end

View File

@ -86,6 +86,19 @@ describe Travis::API::V3::ServiceIndex do
"request_method"=>"GET", "request_method"=>"GET",
"uri_template"=>"#{path}org/{organization.id}"}]}, "uri_template"=>"#{path}org/{organization.id}"}]},
"attributes"=>["id", "login", "name", "github_id"]}, "attributes"=>["id", "login", "name", "github_id"]},
"account"=>
{"@type"=>"resource",
"actions"=>
{"find"=>
[{"@type"=>"template",
"request_method"=>"GET",
"uri_template"=>"#{path}account/{account.login}"},
{"@type"=>"template",
"request_method"=>"GET",
"uri_template"=>"#{path}account/{user.login}"},
{"@type"=>"template",
"request_method"=>"GET",
"uri_template"=>"#{path}account/{organization.login}"}]}},
"organizations"=> "organizations"=>
{"@type"=>"resource", {"@type"=>"resource",
"actions"=> "actions"=>
@ -108,22 +121,27 @@ describe Travis::API::V3::ServiceIndex do
"attributes"=>["id", "login", "name", "github_id", "is_syncing", "synced_at"]}} "attributes"=>["id", "login", "name", "github_id", "is_syncing", "synced_at"]}}
} }
shared_examples 'service index' do
describe :resources do
specify { expect(json['resources']).to include(expected_resources) }
specify { expect(json['resources'].keys.sort) .to be == expected_resources.keys.sort }
end
specify { expect(json['@href']).to be == path }
end
describe 'with /v3 prefix' do describe 'with /v3 prefix' do
let(:path) { '/v3/' } let(:path) { '/v3/' }
specify(:resources) { expect(json['resources']) .to be == expected_resources } it_behaves_like 'service index'
specify(:@href) { expect(json['@href']) .to be == '/v3/' }
end end
describe 'with Accept header' do describe 'with Accept header' do
let(:headers) { { 'HTTP_ACCEPT' => 'application/vnd.travis-ci.3+json' } } let(:headers) { { 'HTTP_ACCEPT' => 'application/vnd.travis-ci.3+json' } }
specify(:resources) { expect(json['resources']) .to be == expected_resources } it_behaves_like 'service index'
specify(:@href) { expect(json['@href']) .to be == '/' }
end end
describe 'with Travis-API-Version header' do describe 'with Travis-API-Version header' do
let(:headers) { { 'HTTP_TRAVIS_API_VERSION' => '3' } } let(:headers) { { 'HTTP_TRAVIS_API_VERSION' => '3' } }
specify(:resources) { expect(json['resources']) .to be == expected_resources } it_behaves_like 'service index'
specify(:@href) { expect(json['@href']) .to be == '/' }
end end
end end

View File

@ -0,0 +1,85 @@
require 'spec_helper'
describe Travis::API::V3::Services::Account::Find do
describe "organization" do
let(:org) { Organization.new(login: 'example-org') }
before { org.save! }
after { org.delete }
describe 'existing org, public api' do
before { get("/v3/account/example-org") }
example { expect(last_response).to be_ok }
example { expect(JSON.load(body)).to be == {
"@type" => "organization",
"@href" => "/v3/org/#{org.id}",
"id" => org.id,
"login" => "example-org",
"name" => nil,
"github_id" => nil
}}
end
describe "does not allow overriding org id" do
let(:other) { Organization.new(login: 'other-org') }
before { other.save! }
after { other.delete }
before { get("/v3/account/example-org?organization.id=#{other.id}") }
example { expect(last_response).to be_ok }
pending "param whitelisting not yet implemented" do
example { expect(JSON.load(body)).to be == {
"@type" => "organization",
"@href" => "/v3/org/#{org.id}",
"id" => org.id,
"login" => "example-org",
"name" => nil,
"github_id" => nil
}}
end
end
end
describe "user" do
let(:user) { User.new(login: 'example-user') }
before { user.save! }
after { user.delete }
describe 'existing user, public api' do
before { get("/v3/account/example-user") }
example { expect(last_response).to be_ok }
example { expect(JSON.load(body)).to be == {
"@type" => "user",
"@href" => "/v3/user/#{user.id}",
"id" => user.id,
"login" => "example-user",
"name" => nil,
"github_id" => nil,
"is_syncing"=> nil,
"synced_at" => nil
}}
end
describe "does not allow overriding user id" do
let(:other) { User.new(login: 'other-user') }
before { other.save! }
after { other.delete }
before { get("/v3/account/example-org?user.id=#{other.id}") }
example { expect(last_response).to be_ok }
pending "param whitelisting not yet implemented" do
example { expect(JSON.load(body)).to be == {
"@type" => "user",
"@href" => "/v3/user/#{user.id}",
"id" => user.id,
"login" => "example-user",
"name" => nil,
"github_id" => nil,
"is_syncing"=> nil,
"synced_at" => nil
}}
end
end
end
end