From 1fdcec33a4b1d1517ef4b16d551729e5f84b4fa8 Mon Sep 17 00:00:00 2001 From: Sven Fuchs Date: Fri, 14 Sep 2012 21:48:22 +0200 Subject: [PATCH 01/42] use services --- Gemfile | 2 +- Gemfile.lock | 9 +++++---- lib/travis/api/app/endpoint/artifacts.rb | 4 +++- lib/travis/api/app/endpoint/branches.rb | 9 +-------- lib/travis/api/app/endpoint/builds.rb | 14 ++------------ lib/travis/api/app/endpoint/hooks.rb | 8 ++++++-- lib/travis/api/app/endpoint/jobs.rb | 14 ++++---------- lib/travis/api/app/endpoint/repositories.rb | 14 ++++++++------ lib/travis/api/app/endpoint/stats.rb | 4 ++-- lib/travis/api/app/endpoint/workers.rb | 4 +++- 10 files changed, 35 insertions(+), 47 deletions(-) diff --git a/Gemfile b/Gemfile index 6b5df9fd..2acc2f12 100644 --- a/Gemfile +++ b/Gemfile @@ -4,7 +4,7 @@ source :rubygems gemspec gem 'travis-support', github: 'travis-ci/travis-support' -gem 'travis-core', github: 'travis-ci/travis-core' +gem 'travis-core', github: 'travis-ci/travis-core', branch: 'sf-moar-services' gem 'hubble', github: 'roidrage/hubble' gem 'yard-sinatra', github: 'rkh/yard-sinatra' gem 'gh', github: 'rkh/gh' diff --git a/Gemfile.lock b/Gemfile.lock index 43304774..dbf4e81f 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -32,7 +32,8 @@ GIT GIT remote: git://github.com/travis-ci/travis-core.git - revision: b71c3be388451581f2ca60e6fd862c2bfc56bfb6 + revision: db8c123f2e2a35a8983f10c6524ccbab96f27ba7 + branch: sf-moar-services specs: travis-core (0.0.1) actionmailer (~> 3.2.3) @@ -105,7 +106,7 @@ GEM atomic (1.0.1) avl_tree (1.1.3) backports (2.6.2) - builder (3.0.0) + builder (3.0.3) daemons (1.1.8) data_migrations (0.0.1) activerecord @@ -120,7 +121,7 @@ GEM ffi (1.1.0) foreman (0.53.0) thor (>= 0.13.6) - hashr (0.0.21) + hashr (0.0.22) hike (1.2.1) hitimes (1.1.1) i18n (0.6.0) @@ -196,7 +197,7 @@ GEM rspec-expectations (2.11.2) diff-lcs (~> 1.1.3) rspec-mocks (2.11.1) - signature (0.1.3) + signature (0.1.4) simple_states (0.1.1) activesupport hashr (~> 0.0.10) diff --git a/lib/travis/api/app/endpoint/artifacts.rb b/lib/travis/api/app/endpoint/artifacts.rb index 88fae5a9..d5fbfc86 100644 --- a/lib/travis/api/app/endpoint/artifacts.rb +++ b/lib/travis/api/app/endpoint/artifacts.rb @@ -5,7 +5,9 @@ class Travis::Api::App # TODO: Add documentation. class Artifacts < Endpoint # TODO: Add documentation. - get('/:id') { |id| body Artifact.find(id) } + get('/:id') do |id| + service(:artifacts).find_one(params) + end end end end diff --git a/lib/travis/api/app/endpoint/branches.rb b/lib/travis/api/app/endpoint/branches.rb index 39d48606..ffe83a6f 100644 --- a/lib/travis/api/app/endpoint/branches.rb +++ b/lib/travis/api/app/endpoint/branches.rb @@ -6,15 +6,8 @@ class Travis::Api::App class Branches < Endpoint # TODO: Add documentation. get('/') do - body repository, :type => "Branches" + body service(:branches).find_all(params) end - - private - - def repository - pass if params.empty? - Repository.find_by(params) || not_found - end end end end diff --git a/lib/travis/api/app/endpoint/builds.rb b/lib/travis/api/app/endpoint/builds.rb index 911913cc..14566d9f 100644 --- a/lib/travis/api/app/endpoint/builds.rb +++ b/lib/travis/api/app/endpoint/builds.rb @@ -6,23 +6,13 @@ class Travis::Api::App class Builds < Endpoint # TODO: Add documentation. get '/' do - scope = repository.builds.by_event_type(params[:event_type] || 'push') - scope = params[:after] ? scope.older_than(params[:after]) : scope.recent - scope + service(:builds).find_all(params) end # TODO: Add documentation. get '/:id' do - one = params[:repository_id] ? repository.builds : Build - body one.includes(:commit, :matrix => [:commit, :log]).find(params[:id]) + service(:builds).find_one(params) end - - private - - def repository - pass if params.empty? - Repository.find_by(params) || not_found - end end end end diff --git a/lib/travis/api/app/endpoint/hooks.rb b/lib/travis/api/app/endpoint/hooks.rb index b8dfbc50..1a4f2dcd 100644 --- a/lib/travis/api/app/endpoint/hooks.rb +++ b/lib/travis/api/app/endpoint/hooks.rb @@ -5,10 +5,14 @@ class Travis::Api::App # TODO: Add documentation. class Hooks < Endpoint # TODO: Add implementation and documentation. - get('/', scope: :private) { raise NotImplementedError } + get('/', scope: :private) do + service(:builds).find_all(params) + end # TODO: Add implementation and documentation. - put('/:id', scope: :admin) { raise NotImplementedError } + put('/:id', scope: :admin) do + respond_with service(:hooks).update(params) + end end end end diff --git a/lib/travis/api/app/endpoint/jobs.rb b/lib/travis/api/app/endpoint/jobs.rb index 923da07f..8c2f21bb 100644 --- a/lib/travis/api/app/endpoint/jobs.rb +++ b/lib/travis/api/app/endpoint/jobs.rb @@ -4,20 +4,14 @@ class Travis::Api::App class Endpoint # TODO: Add documentation. class Jobs < Endpoint - # TODO: Add implementation and documentation. + # TODO: Add documentation. get('/') do - if params[:ids] - Job.where(:id => params[:ids]).includes(:commit, :log) - else - jobs = Job.queued.includes(:commit, :log) - jobs = jobs.where(:queue => params[:queue]) if params[:queue] - jobs - end + service(:jobs).find_all(params) end - # TODO: Add implementation and documentation. + # TODO: Add documentation. get('/:id') do - body Job.find(params[:id]) + service(:jobs).find_one(params) end end end diff --git a/lib/travis/api/app/endpoint/repositories.rb b/lib/travis/api/app/endpoint/repositories.rb index 90040db2..3053093d 100644 --- a/lib/travis/api/app/endpoint/repositories.rb +++ b/lib/travis/api/app/endpoint/repositories.rb @@ -6,15 +6,17 @@ class Travis::Api::App class Repositories < Endpoint # TODO: Add documentation. get '/' do - scope = Repository.timeline.recent - scope = scope.by_owner_name(params[:owner_name]) if params[:owner_name] - scope = scope.by_slug(params[:slug]) if params[:slug] - scope = scope.search(params[:search]) if params[:search].present? - scope + body service(:repositories).find_all(params) end # TODO: Add documentation. - get('/:id') { body Repository.find_by(params) } + get('/:id') do + body service(:repositories).find_one(params) + end + + # TODO make sure status images and cc.xml work + # rescue ActiveRecord::RecordNotFound + # raise unless params[:format] == 'png' end end end diff --git a/lib/travis/api/app/endpoint/stats.rb b/lib/travis/api/app/endpoint/stats.rb index 51dfaac1..0301cb44 100644 --- a/lib/travis/api/app/endpoint/stats.rb +++ b/lib/travis/api/app/endpoint/stats.rb @@ -6,12 +6,12 @@ class Travis::Api::App class Stats < Endpoint # TODO: Add documentation. get('/repos') do - { :stats => Travis::Stats.daily_repository_counts } + { :stats => services(:stats).daily_repository_counts } end # TODO: Add documentation. get('/tests') do - { :stats => Travis::Stats.daily_tests_counts } + { :stats => services(:stats).daily_tests_counts } end end end diff --git a/lib/travis/api/app/endpoint/workers.rb b/lib/travis/api/app/endpoint/workers.rb index 4c5c25f3..90516ac0 100644 --- a/lib/travis/api/app/endpoint/workers.rb +++ b/lib/travis/api/app/endpoint/workers.rb @@ -5,7 +5,9 @@ class Travis::Api::App # TODO: Add documentation. class Workers < Endpoint # TODO: Add implementation and documentation. - get('/') { Worker.order(:host, :name) } + get('/') do + service(:workers).find_all(params) + end end end end From 79e382ce0b22dac2e413cdbb091c2ed07a987a7e Mon Sep 17 00:00:00 2001 From: Sven Fuchs Date: Sat, 15 Sep 2012 12:06:33 +0200 Subject: [PATCH 02/42] add services --- lib/travis/api/app.rb | 4 ++++ lib/travis/api/app/endpoint.rb | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/lib/travis/api/app.rb b/lib/travis/api/app.rb index 36d1f1d8..1b2b7230 100644 --- a/lib/travis/api/app.rb +++ b/lib/travis/api/app.rb @@ -75,6 +75,10 @@ class Travis::Api::App def self.setup_travis Travis::Database.connect + + Travis::Services.constants.each do |name| + Travis.services[name.to_s.underscore.to_sym] = Travis::Services.const_get(name) unless name == :Base + end end def self.load_endpoints diff --git a/lib/travis/api/app/endpoint.rb b/lib/travis/api/app/endpoint.rb index 9d96435f..6fc5ced8 100644 --- a/lib/travis/api/app/endpoint.rb +++ b/lib/travis/api/app/endpoint.rb @@ -10,5 +10,12 @@ class Travis::Api::App before { content_type :json } error(ActiveRecord::RecordNotFound, Sinatra::NotFound) { not_found } not_found { content_type =~ /json/ ? { 'file' => 'not found' } : 'file not found' } + + private + + def service(key) + const = Travis.services[key] || raise("no service registered for #{key}") + const.new(respond_to?(:current_user) ? current_user : nil) + end end end From c6ab5d3b981bb981a261764ae6d2590a9dc454d9 Mon Sep 17 00:00:00 2001 From: Sven Fuchs Date: Sat, 15 Sep 2012 12:09:44 +0200 Subject: [PATCH 03/42] bump travis-support --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index dbf4e81f..a69290d8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -32,7 +32,7 @@ GIT GIT remote: git://github.com/travis-ci/travis-core.git - revision: db8c123f2e2a35a8983f10c6524ccbab96f27ba7 + revision: cbddb4179552344b578b20e320ac7e9d7c335b3d branch: sf-moar-services specs: travis-core (0.0.1) @@ -54,7 +54,7 @@ GIT GIT remote: git://github.com/travis-ci/travis-support.git - revision: 27857bb4f5425b8aacc9b26e4661688dca962fb0 + revision: b150763d253331de9adadcb5b39f7df5efccb676 specs: travis-support (0.0.1) From a2d195ecf9340c31c4ee2c439e3b2aac54181157 Mon Sep 17 00:00:00 2001 From: Sven Fuchs Date: Sat, 15 Sep 2012 12:33:34 +0200 Subject: [PATCH 04/42] actually turn these objects into json --- lib/travis/api/app/endpoint/artifacts.rb | 2 +- lib/travis/api/app/endpoint/branches.rb | 2 +- lib/travis/api/app/endpoint/builds.rb | 4 ++-- lib/travis/api/app/endpoint/hooks.rb | 4 ++-- lib/travis/api/app/endpoint/jobs.rb | 4 ++-- lib/travis/api/app/endpoint/workers.rb | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/travis/api/app/endpoint/artifacts.rb b/lib/travis/api/app/endpoint/artifacts.rb index d5fbfc86..2a1d51b4 100644 --- a/lib/travis/api/app/endpoint/artifacts.rb +++ b/lib/travis/api/app/endpoint/artifacts.rb @@ -6,7 +6,7 @@ class Travis::Api::App class Artifacts < Endpoint # TODO: Add documentation. get('/:id') do |id| - service(:artifacts).find_one(params) + body service(:artifacts).find_one(params) end end end diff --git a/lib/travis/api/app/endpoint/branches.rb b/lib/travis/api/app/endpoint/branches.rb index ffe83a6f..29917ca7 100644 --- a/lib/travis/api/app/endpoint/branches.rb +++ b/lib/travis/api/app/endpoint/branches.rb @@ -6,7 +6,7 @@ class Travis::Api::App class Branches < Endpoint # TODO: Add documentation. get('/') do - body service(:branches).find_all(params) + body service(:branches).find_all(params), :type => :branches end end end diff --git a/lib/travis/api/app/endpoint/builds.rb b/lib/travis/api/app/endpoint/builds.rb index 14566d9f..cd74c36e 100644 --- a/lib/travis/api/app/endpoint/builds.rb +++ b/lib/travis/api/app/endpoint/builds.rb @@ -6,12 +6,12 @@ class Travis::Api::App class Builds < Endpoint # TODO: Add documentation. get '/' do - service(:builds).find_all(params) + body service(:builds).find_all(params) end # TODO: Add documentation. get '/:id' do - service(:builds).find_one(params) + body service(:builds).find_one(params) end end end diff --git a/lib/travis/api/app/endpoint/hooks.rb b/lib/travis/api/app/endpoint/hooks.rb index 1a4f2dcd..cf2ebfae 100644 --- a/lib/travis/api/app/endpoint/hooks.rb +++ b/lib/travis/api/app/endpoint/hooks.rb @@ -6,12 +6,12 @@ class Travis::Api::App class Hooks < Endpoint # TODO: Add implementation and documentation. get('/', scope: :private) do - service(:builds).find_all(params) + body service(:builds).find_all(params) end # TODO: Add implementation and documentation. put('/:id', scope: :admin) do - respond_with service(:hooks).update(params) + body service(:hooks).update(params) end end end diff --git a/lib/travis/api/app/endpoint/jobs.rb b/lib/travis/api/app/endpoint/jobs.rb index 8c2f21bb..66a70aff 100644 --- a/lib/travis/api/app/endpoint/jobs.rb +++ b/lib/travis/api/app/endpoint/jobs.rb @@ -6,12 +6,12 @@ class Travis::Api::App class Jobs < Endpoint # TODO: Add documentation. get('/') do - service(:jobs).find_all(params) + body service(:jobs).find_all(params) end # TODO: Add documentation. get('/:id') do - service(:jobs).find_one(params) + body service(:jobs).find_one(params) end end end diff --git a/lib/travis/api/app/endpoint/workers.rb b/lib/travis/api/app/endpoint/workers.rb index 90516ac0..47ff90c0 100644 --- a/lib/travis/api/app/endpoint/workers.rb +++ b/lib/travis/api/app/endpoint/workers.rb @@ -6,7 +6,7 @@ class Travis::Api::App class Workers < Endpoint # TODO: Add implementation and documentation. get('/') do - service(:workers).find_all(params) + body service(:workers).find_all(params) end end end From a8fc2f0e7ac41ee55b937e607b8897b2b118411b Mon Sep 17 00:00:00 2001 From: Sven Fuchs Date: Sat, 15 Sep 2012 14:35:37 +0200 Subject: [PATCH 05/42] it's service, not services --- lib/travis/api/app/endpoint/stats.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/travis/api/app/endpoint/stats.rb b/lib/travis/api/app/endpoint/stats.rb index 0301cb44..4463dcdb 100644 --- a/lib/travis/api/app/endpoint/stats.rb +++ b/lib/travis/api/app/endpoint/stats.rb @@ -6,12 +6,12 @@ class Travis::Api::App class Stats < Endpoint # TODO: Add documentation. get('/repos') do - { :stats => services(:stats).daily_repository_counts } + { :stats => service(:stats).daily_repository_counts } end # TODO: Add documentation. get('/tests') do - { :stats => services(:stats).daily_tests_counts } + { :stats => service(:stats).daily_tests_counts } end end end From 3387c185fa9e226cfc3d0aca4713eff166089348 Mon Sep 17 00:00:00 2001 From: Sven Fuchs Date: Sun, 16 Sep 2012 00:45:38 +0200 Subject: [PATCH 06/42] fake sign in --- lib/travis/api/app/endpoint.rb | 7 ++++- lib/travis/api/app/endpoint/branches.rb | 2 +- lib/travis/api/app/endpoint/hooks.rb | 5 ++-- lib/travis/api/app/endpoint/profile.rb | 39 +++++++++++++++++++++++-- 4 files changed, 47 insertions(+), 6 deletions(-) diff --git a/lib/travis/api/app/endpoint.rb b/lib/travis/api/app/endpoint.rb index 6fc5ced8..31eb233e 100644 --- a/lib/travis/api/app/endpoint.rb +++ b/lib/travis/api/app/endpoint.rb @@ -15,7 +15,12 @@ class Travis::Api::App def service(key) const = Travis.services[key] || raise("no service registered for #{key}") - const.new(respond_to?(:current_user) ? current_user : nil) + const.new(current_user) + end + + def current_user + # TODO + User.where(:login => 'svenfuchs').first end end end diff --git a/lib/travis/api/app/endpoint/branches.rb b/lib/travis/api/app/endpoint/branches.rb index 29917ca7..52d83a50 100644 --- a/lib/travis/api/app/endpoint/branches.rb +++ b/lib/travis/api/app/endpoint/branches.rb @@ -6,7 +6,7 @@ class Travis::Api::App class Branches < Endpoint # TODO: Add documentation. get('/') do - body service(:branches).find_all(params), :type => :branches + body service(:branches).find_all(params), type: :branches end end end diff --git a/lib/travis/api/app/endpoint/hooks.rb b/lib/travis/api/app/endpoint/hooks.rb index cf2ebfae..fd590db5 100644 --- a/lib/travis/api/app/endpoint/hooks.rb +++ b/lib/travis/api/app/endpoint/hooks.rb @@ -5,8 +5,9 @@ class Travis::Api::App # TODO: Add documentation. class Hooks < Endpoint # TODO: Add implementation and documentation. - get('/', scope: :private) do - body service(:builds).find_all(params) + # TODO scope: :private + get('/') do + body service(:hooks).find_all(params), type: :hooks end # TODO: Add implementation and documentation. diff --git a/lib/travis/api/app/endpoint/profile.rb b/lib/travis/api/app/endpoint/profile.rb index 8a9096c6..5e6f3fa7 100644 --- a/lib/travis/api/app/endpoint/profile.rb +++ b/lib/travis/api/app/endpoint/profile.rb @@ -18,10 +18,45 @@ class Travis::Api::App # "synced_at": "2012-08-14T22:11:21Z" # } # } - get('/', scope: :private) { body(user) } + get '/', scope: :private do + body user + end + + put '/', scope: :private do + raise NotImplementedError + update_locale if valid_locale? + 'ok' + end # TODO: Add implementation and documentation. - post('/sync', scope: :private) { raise NotImplementedError } + post '/sync', scope: :private do + raise NotImplementedError + sync_user(current_user) + 'ok' + end + + private + + def sync_user(user) + unless user.is_syncing? + publisher = Travis::Amqp::Publisher.new('sync.user') + publisher.publish({ user_id: user.id }, type: 'sync') + user.update_column(:is_syncing, true) + end + end + + def locale + params[:user][:locale] + end + + def valid_locale? + I18n.available_locales.include?(locale.to_sym) # ??? + end + + def update_locale + current_user.update_attributes!(:locale => locale.to_s) + session[:locale] = locale # ??? + end end end end From 957e9ee37896034237ad5e32abae9b432df9c228 Mon Sep 17 00:00:00 2001 From: Sven Fuchs Date: Sun, 16 Sep 2012 00:46:25 +0200 Subject: [PATCH 07/42] bump travis-core --- Gemfile | 2 +- Gemfile.lock | 40 ++++++++++++++++++++-------------------- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/Gemfile b/Gemfile index 2acc2f12..cd248d6b 100644 --- a/Gemfile +++ b/Gemfile @@ -4,7 +4,7 @@ source :rubygems gemspec gem 'travis-support', github: 'travis-ci/travis-support' -gem 'travis-core', github: 'travis-ci/travis-core', branch: 'sf-moar-services' +gem 'travis-core', github: 'travis-ci/travis-core', branch: 'sf-more-services' gem 'hubble', github: 'roidrage/hubble' gem 'yard-sinatra', github: 'rkh/yard-sinatra' gem 'gh', github: 'rkh/gh' diff --git a/Gemfile.lock b/Gemfile.lock index a69290d8..db903b3b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -32,8 +32,8 @@ GIT GIT remote: git://github.com/travis-ci/travis-core.git - revision: cbddb4179552344b578b20e320ac7e9d7c335b3d - branch: sf-moar-services + revision: fec30393c46107e1ce4bd1600887d24c290f520a + branch: sf-more-services specs: travis-core (0.0.1) actionmailer (~> 3.2.3) @@ -77,35 +77,35 @@ PATH GEM remote: http://rubygems.org/ specs: - actionmailer (3.2.6) - actionpack (= 3.2.6) + actionmailer (3.2.8) + actionpack (= 3.2.8) mail (~> 2.4.4) - actionpack (3.2.6) - activemodel (= 3.2.6) - activesupport (= 3.2.6) + actionpack (3.2.8) + activemodel (= 3.2.8) + activesupport (= 3.2.8) builder (~> 3.0.0) erubis (~> 2.7.0) - journey (~> 1.0.1) + journey (~> 1.0.4) rack (~> 1.4.0) rack-cache (~> 1.2) rack-test (~> 0.6.1) sprockets (~> 2.1.3) - activemodel (3.2.6) - activesupport (= 3.2.6) + activemodel (3.2.8) + activesupport (= 3.2.8) builder (~> 3.0.0) - activerecord (3.2.6) - activemodel (= 3.2.6) - activesupport (= 3.2.6) + activerecord (3.2.8) + activemodel (= 3.2.8) + activesupport (= 3.2.8) arel (~> 3.0.2) tzinfo (~> 0.3.29) - activesupport (3.2.6) + activesupport (3.2.8) i18n (~> 0.6) multi_json (~> 1.0) addressable (2.3.2) arel (3.0.2) atomic (1.0.1) avl_tree (1.1.3) - backports (2.6.2) + backports (2.6.4) builder (3.0.3) daemons (1.1.8) data_migrations (0.0.1) @@ -116,7 +116,7 @@ GEM eventmachine (0.12.10) factory_girl (2.4.2) activesupport - faraday (0.8.1) + faraday (0.8.4) multipart-post (~> 1.1) ffi (1.1.0) foreman (0.53.0) @@ -124,7 +124,7 @@ GEM hashr (0.0.22) hike (1.2.1) hitimes (1.1.1) - i18n (0.6.0) + i18n (0.6.1) journey (1.0.4) json (1.6.7) listen (0.4.7) @@ -169,9 +169,9 @@ GEM rack rack-test (0.6.1) rack (>= 1.0) - railties (3.2.6) - actionpack (= 3.2.6) - activesupport (= 3.2.6) + railties (3.2.8) + actionpack (= 3.2.8) + activesupport (= 3.2.8) rack-ssl (~> 1.3.2) rake (>= 0.8.7) rdoc (~> 3.4) From ea96905e8a06a8ee7ab578b91f14b43f4fbf3927 Mon Sep 17 00:00:00 2001 From: Sven Fuchs Date: Tue, 18 Sep 2012 00:04:20 +0200 Subject: [PATCH 08/42] un-private /profile --- lib/travis/api/app/endpoint/profile.rb | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/travis/api/app/endpoint/profile.rb b/lib/travis/api/app/endpoint/profile.rb index 5e6f3fa7..1e39238a 100644 --- a/lib/travis/api/app/endpoint/profile.rb +++ b/lib/travis/api/app/endpoint/profile.rb @@ -18,8 +18,9 @@ class Travis::Api::App # "synced_at": "2012-08-14T22:11:21Z" # } # } - get '/', scope: :private do - body user + # , scope: :private + get '/' do + body service(:user).find_one, type: :user end put '/', scope: :private do @@ -29,9 +30,10 @@ class Travis::Api::App end # TODO: Add implementation and documentation. - post '/sync', scope: :private do - raise NotImplementedError - sync_user(current_user) + # , scope: :private + post '/sync' do + # raise NotImplementedError + # sync_user(current_user) 'ok' end From 6606af4b43ef64d3ef97efeddda8524aff7c5281 Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Mon, 17 Sep 2012 23:58:57 +0200 Subject: [PATCH 09/42] start working on post_message auth flow Conflicts: Gemfile.lock --- lib/travis/api/app/endpoint/authorization.rb | 48 +++++++++++++++++--- script/server | 2 +- 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/lib/travis/api/app/endpoint/authorization.rb b/lib/travis/api/app/endpoint/authorization.rb index 6d90e9be..2df888e9 100644 --- a/lib/travis/api/app/endpoint/authorization.rb +++ b/lib/travis/api/app/endpoint/authorization.rb @@ -1,4 +1,6 @@ require 'travis/api/app' +require 'addressable/uri' +require 'faraday' class Travis::Api::App class Endpoint @@ -58,14 +60,31 @@ class Travis::Api::App # # * **token**: GitHub token for checking authorization (required) post '/github' do - data = GH.with(token: params[:token].to_s) { GH['user'] } - scopes = parse_scopes data.headers['x-oauth-scopes'] - user = User.find_by_login(data['login']) + { 'access_token' => github_to_travis(params[:token]) } + end - halt 403, 'not a Travis user' if user.nil? - halt 403, 'insufficient access' unless acceptable? scopes + get '/post_message' do + config = Travis.config.oauth2 + endpoint = Addressable::URI.parse(config.authorization_server) + values = { + client_id: config.client_id, + scope: config.scope, + redirect_uri: url + } - { 'access_token' => generate_token(user) } + if params[:code] + endpoint.path = config.access_token_path + values[:code] = params[:code] + values[:state] = params[:state] if params[:state] + values[:client_secret] = config.client_secret + + token = github_to_travis get_token(endpoint.to_s, values) + { 'access_token' => token } + else + endpoint.path = config.authorize_path + endpoint.query_values = values + redirect to(endpoint.to_s) + end end error Faraday::Error::ClientError do @@ -74,6 +93,23 @@ class Travis::Api::App private + def github_to_travis(token) + data = GH.with(token: token.to_s) { GH['user'] } + scopes = parse_scopes data.headers['x-oauth-scopes'] + user = User.find_by_login(data['login']) + + halt 403, 'not a Travis user' if user.nil? + halt 403, 'insufficient access' unless acceptable? scopes + + generate_token(user) + end + + def get_token(endoint, value) + response = Faraday.get(endoint, value) + parameters = Addressable::URI.form_unencode(response.body) + parameters.assoc("access_token").last + end + def parse_scopes(data) data.gsub(/\s/,'').split(',') if data end diff --git a/script/server b/script/server index ef6391d4..d7e105dd 100755 --- a/script/server +++ b/script/server @@ -1,6 +1,6 @@ #!/usr/bin/env bash cd "$(dirname "$0")/.." -[ $PORT ] || PORT=5000 +[ $PORT ] || PORT=3000 [ $RACK_ENV ] || RACK_ENV=development cmd="ruby -I lib -S bundle exec ruby -I lib -S thin start -p $PORT -e $RACK_ENV --threaded" From 4d6c8822e5c372cda27476d984b8bad9a29821a3 Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Tue, 18 Sep 2012 16:34:57 +0200 Subject: [PATCH 10/42] update travis-core --- Gemfile.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Gemfile.lock b/Gemfile.lock index db903b3b..5dac3a14 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -32,7 +32,7 @@ GIT GIT remote: git://github.com/travis-ci/travis-core.git - revision: fec30393c46107e1ce4bd1600887d24c290f520a + revision: ea7a1678a0388e586ac4778a9b6ee56a11dfb0aa branch: sf-more-services specs: travis-core (0.0.1) From 05acb00c2ed0fb3ba67f868bc2e68fdfdf9915cb Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Tue, 18 Sep 2012 16:35:29 +0200 Subject: [PATCH 11/42] reuse existing tokens for same app/scopes --- lib/travis/api/app/access_token.rb | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/lib/travis/api/app/access_token.rb b/lib/travis/api/app/access_token.rb index f4944cf9..e48bf367 100644 --- a/lib/travis/api/app/access_token.rb +++ b/lib/travis/api/app/access_token.rb @@ -4,7 +4,7 @@ require 'securerandom' class Travis::Api::App class AccessToken DEFAULT_SCOPES = [:public, :private] - attr_reader :token, :scopes, :user_id + attr_reader :token, :scopes, :user_id, :app_id def self.create(options = {}) new(options).tap(&:save) @@ -12,22 +12,25 @@ class Travis::Api::App def self.find_by_token(token) user_id, app_id, *scopes = redis.lrange(key(token), 0, -1) - new(token: token, scopes: scopes, user_id: user_id) if user_id + new(token: token, scopes: scopes, user_id: user_id, app_id: app_id) if user_id end def initialize(options = {}) raise ArgumentError, 'must supply either user_id or user' unless options.key?(:user) ^ options.key?(:user_id) + raise ArgumentError, 'must supply app_id' unless options.key?(:app_id) - @token = options[:token] || SecureRandom.urlsafe_base64(64) + @app_id = Integer(options[:app_id]) @scopes = Array(options[:scopes] || options[:scope] || DEFAULT_SCOPES).map(&:to_sym) @user = options[:user] @user_id = Integer(options[:user_id] || @user.id) + @token = options[:token] || reuse_token || SecureRandom.urlsafe_base64(16) end def save key = key(token) redis.del(key) redis.rpush(key, [user_id, '', *scopes].map(&:to_s)) + redis.set(reuse_key, token) end def user @@ -55,5 +58,19 @@ class Travis::Api::App include Helpers extend Helpers + + private + + def reuse_token + redis.get(reuse_key) + end + + def reuse_key + @reuse_key ||= begin + keys = ["r", user_id, app_id] + keys.append(scopes.mpa(&:to_s).sort) if scopes != DEFAULT_SCOPES + keys.join(':') + end + end end end From e9523dc21df0b7cbc8291db97ff720708bccd72e Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Tue, 18 Sep 2012 16:36:06 +0200 Subject: [PATCH 12/42] use state to avoid handshake spoofing --- lib/travis/api/app/endpoint.rb | 4 ++ lib/travis/api/app/endpoint/authorization.rb | 39 +++++++++++++------- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/lib/travis/api/app/endpoint.rb b/lib/travis/api/app/endpoint.rb index 31eb233e..ebfeec22 100644 --- a/lib/travis/api/app/endpoint.rb +++ b/lib/travis/api/app/endpoint.rb @@ -22,5 +22,9 @@ class Travis::Api::App # TODO User.where(:login => 'svenfuchs').first end + + def redis + Thread.current[:redis] ||= ::Redis.connect(url: Travis.config.redis.url) + end end end diff --git a/lib/travis/api/app/endpoint/authorization.rb b/lib/travis/api/app/endpoint/authorization.rb index 2df888e9..cc640549 100644 --- a/lib/travis/api/app/endpoint/authorization.rb +++ b/lib/travis/api/app/endpoint/authorization.rb @@ -1,6 +1,7 @@ require 'travis/api/app' require 'addressable/uri' require 'faraday' +require 'securerandom' class Travis::Api::App class Endpoint @@ -60,7 +61,7 @@ class Travis::Api::App # # * **token**: GitHub token for checking authorization (required) post '/github' do - { 'access_token' => github_to_travis(params[:token]) } + { 'access_token' => github_to_travis(params[:token], app_id: 1) } end get '/post_message' do @@ -72,17 +73,18 @@ class Travis::Api::App redirect_uri: url } - if params[:code] + if params[:code] and state_ok?(params[:state]) endpoint.path = config.access_token_path + values[:state] = params[:state] values[:code] = params[:code] - values[:state] = params[:state] if params[:state] values[:client_secret] = config.client_secret - - token = github_to_travis get_token(endpoint.to_s, values) + github_token = get_token(endpoint.to_s, values) + token = github_to_travis(github_token, app_id: 0) { 'access_token' => token } else - endpoint.path = config.authorize_path - endpoint.query_values = values + values[:state] = create_state + endpoint.path = config.authorize_path + endpoint.query_values = values redirect to(endpoint.to_s) end end @@ -93,7 +95,18 @@ class Travis::Api::App private - def github_to_travis(token) + def create_state + state = SecureRandom.urlsafe_base64(16) + redis.sadd('github:states', state) + redis.expire('github:states', 1800) + state + end + + def state_ok?(state) + redis.srem('github:states', state) if state + end + + def github_to_travis(token, options = {}) data = GH.with(token: token.to_s) { GH['user'] } scopes = parse_scopes data.headers['x-oauth-scopes'] user = User.find_by_login(data['login']) @@ -101,11 +114,11 @@ class Travis::Api::App halt 403, 'not a Travis user' if user.nil? halt 403, 'insufficient access' unless acceptable? scopes - generate_token(user) + generate_token options.merge(user: user) end - def get_token(endoint, value) - response = Faraday.get(endoint, value) + def get_token(endoint, values) + response = Faraday.post(endoint, values) parameters = Addressable::URI.form_unencode(response.body) parameters.assoc("access_token").last end @@ -114,8 +127,8 @@ class Travis::Api::App data.gsub(/\s/,'').split(',') if data end - def generate_token(user) - AccessToken.create(user: user).token + def generate_token(options) + AccessToken.create(options).token end def acceptable?(scopes) From 8a16b77281680ad637e998b5cf79b6cdff866502 Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Tue, 18 Sep 2012 17:02:01 +0200 Subject: [PATCH 13/42] disable threaded mode for now --- script/server | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/server b/script/server index d7e105dd..569491a1 100755 --- a/script/server +++ b/script/server @@ -3,6 +3,6 @@ cd "$(dirname "$0")/.." [ $PORT ] || PORT=3000 [ $RACK_ENV ] || RACK_ENV=development -cmd="ruby -I lib -S bundle exec ruby -I lib -S thin start -p $PORT -e $RACK_ENV --threaded" +cmd="ruby -I lib -S bundle exec ruby -I lib -S thin start -p $PORT -e $RACK_ENV" #--threaded" [[ $RACK_ENV == "development" ]] && exec rerun "$cmd -a 127.0.0.1" exec $cmd From 759ad4d1139eb05629ac0c4d1d3b353644ccb0c4 Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Tue, 18 Sep 2012 18:27:26 +0200 Subject: [PATCH 14/42] send messages after oauth handshake --- lib/travis/api/app/endpoint/authorization.rb | 31 +++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/lib/travis/api/app/endpoint/authorization.rb b/lib/travis/api/app/endpoint/authorization.rb index cc640549..b7ed528b 100644 --- a/lib/travis/api/app/endpoint/authorization.rb +++ b/lib/travis/api/app/endpoint/authorization.rb @@ -35,6 +35,19 @@ class Travis::Api::App # authorization flow to support third-party clients in the future, too. class Authorization < Endpoint set prefix: '/auth' + enable :inline_templates + + configure :development, :test do + set :target_origins, ['*'] + end + + configure :production do + set :target_origins, %W[ + https://#{Travis.config.domain} + https://staging.#{Travis.config.domain} + https://travis-ember.herokuapp.com + ] + end # Parameters: # @@ -80,7 +93,7 @@ class Travis::Api::App values[:client_secret] = config.client_secret github_token = get_token(endpoint.to_s, values) token = github_to_travis(github_token, app_id: 0) - { 'access_token' => token } + post_message(token: token) else values[:state] = create_state endpoint.path = config.authorize_path @@ -134,6 +147,22 @@ class Travis::Api::App def acceptable?(scopes) scopes.include? 'public_repo' or scopes.include? 'repo' end + + def post_message(payload) + content_type :html + erb(:post_message, locals: payload) + end end end end + +__END__ + +@@ post_message + + +SENT \ No newline at end of file From 3a64c87a7f76021dfd8021c3e63c13dae0371cfd Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Tue, 18 Sep 2012 19:15:12 +0200 Subject: [PATCH 15/42] send user data with post message --- lib/travis/api/app/endpoint.rb | 7 +++---- lib/travis/api/app/endpoint/authorization.rb | 19 ++++++++++++------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/lib/travis/api/app/endpoint.rb b/lib/travis/api/app/endpoint.rb index ebfeec22..c4cd2199 100644 --- a/lib/travis/api/app/endpoint.rb +++ b/lib/travis/api/app/endpoint.rb @@ -13,14 +13,13 @@ class Travis::Api::App private - def service(key) + def service(key, user = current_user) const = Travis.services[key] || raise("no service registered for #{key}") - const.new(current_user) + const.new(user) end def current_user - # TODO - User.where(:login => 'svenfuchs').first + env['travis.access_token'].user if env['travis.access_token'] end def redis diff --git a/lib/travis/api/app/endpoint/authorization.rb b/lib/travis/api/app/endpoint/authorization.rb index b7ed528b..fafa5ad5 100644 --- a/lib/travis/api/app/endpoint/authorization.rb +++ b/lib/travis/api/app/endpoint/authorization.rb @@ -92,8 +92,10 @@ class Travis::Api::App values[:code] = params[:code] values[:client_secret] = config.client_secret github_token = get_token(endpoint.to_s, values) - token = github_to_travis(github_token, app_id: 0) - post_message(token: token) + user = user_for_github_token(github_token) + token = generate_token(user: user, app_id: 0) + rendered_user = service(:user, user).find_one + post_message(token: token, user: rendered_user) else values[:state] = create_state endpoint.path = config.authorize_path @@ -120,14 +122,17 @@ class Travis::Api::App end def github_to_travis(token, options = {}) + generate_token options.merge(user: user_for_github_token(token)) + end + + def user_for_github_token(token) data = GH.with(token: token.to_s) { GH['user'] } scopes = parse_scopes data.headers['x-oauth-scopes'] user = User.find_by_login(data['login']) halt 403, 'not a Travis user' if user.nil? halt 403, 'insufficient access' unless acceptable? scopes - - generate_token options.merge(user: user) + user end def get_token(endoint, values) @@ -160,9 +165,9 @@ __END__ @@ post_message - -SENT \ No newline at end of file From 1e903129a31ab7785e17562740d0bfb69486e2f3 Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Tue, 18 Sep 2012 19:50:05 +0200 Subject: [PATCH 16/42] set app_id --- lib/travis/api/app/access_token.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/travis/api/app/access_token.rb b/lib/travis/api/app/access_token.rb index e48bf367..e3b98d6c 100644 --- a/lib/travis/api/app/access_token.rb +++ b/lib/travis/api/app/access_token.rb @@ -29,7 +29,7 @@ class Travis::Api::App def save key = key(token) redis.del(key) - redis.rpush(key, [user_id, '', *scopes].map(&:to_s)) + redis.rpush(key, [user_id, app_id, *scopes].map(&:to_s)) redis.set(reuse_key, token) end From 1a7a9daf4643abf6c954bf26c63816783ded9bda Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Tue, 18 Sep 2012 20:37:52 +0200 Subject: [PATCH 17/42] add endpoint for initial authorization --- lib/travis/api/app/endpoint/authorization.rb | 60 ++++++++++++-------- 1 file changed, 37 insertions(+), 23 deletions(-) diff --git a/lib/travis/api/app/endpoint/authorization.rb b/lib/travis/api/app/endpoint/authorization.rb index fafa5ad5..dfd2c415 100644 --- a/lib/travis/api/app/endpoint/authorization.rb +++ b/lib/travis/api/app/endpoint/authorization.rb @@ -77,30 +77,16 @@ class Travis::Api::App { 'access_token' => github_to_travis(params[:token], app_id: 1) } end - get '/post_message' do - config = Travis.config.oauth2 - endpoint = Addressable::URI.parse(config.authorization_server) - values = { - client_id: config.client_id, - scope: config.scope, - redirect_uri: url - } + get '/handshake' do + handshake do |*, redirect_uri| + redirect redirect_uri + end + end - if params[:code] and state_ok?(params[:state]) - endpoint.path = config.access_token_path - values[:state] = params[:state] - values[:code] = params[:code] - values[:client_secret] = config.client_secret - github_token = get_token(endpoint.to_s, values) - user = user_for_github_token(github_token) - token = generate_token(user: user, app_id: 0) - rendered_user = service(:user, user).find_one + get '/post_message' do + handshake do |user, token| + rendered_user = service(:user, user).find_one post_message(token: token, user: rendered_user) - else - values[:state] = create_state - endpoint.path = config.authorize_path - endpoint.query_values = values - redirect to(endpoint.to_s) end end @@ -110,15 +96,43 @@ class Travis::Api::App private + def handshake + config = Travis.config.oauth2 + endpoint = Addressable::URI.parse(config.authorization_server) + values = { + client_id: config.client_id, + scope: config.scope, + redirect_uri: url + } + + if params[:code] and state_ok?(params[:state]) + endpoint.path = config.access_token_path + values[:state] = params[:state] + values[:code] = params[:code] + values[:client_secret] = config.client_secret + github_token = get_token(endpoint.to_s, values) + user = user_for_github_token(github_token) + token = generate_token(user: user, app_id: 0) + payload = params[:state].split(":::", 2)[1] + yield user, token, payload + else + values[:state] = create_state + endpoint.path = config.authorize_path + endpoint.query_values = values + redirect to(endpoint.to_s) + end + end + def create_state state = SecureRandom.urlsafe_base64(16) redis.sadd('github:states', state) redis.expire('github:states', 1800) + state << ":::" << params[:redirect_uri] if params[:redirect_uri] state end def state_ok?(state) - redis.srem('github:states', state) if state + redis.srem('github:states', state.split(":::", 1)) if state end def github_to_travis(token, options = {}) From e8ab020af09c3b4cb0438df4422bfa07b0b1908f Mon Sep 17 00:00:00 2001 From: Sven Fuchs Date: Tue, 18 Sep 2012 21:04:54 +0200 Subject: [PATCH 18/42] use Api for generating the user payload --- lib/travis/api/app/endpoint/authorization.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/travis/api/app/endpoint/authorization.rb b/lib/travis/api/app/endpoint/authorization.rb index fafa5ad5..f32fb95d 100644 --- a/lib/travis/api/app/endpoint/authorization.rb +++ b/lib/travis/api/app/endpoint/authorization.rb @@ -94,7 +94,7 @@ class Travis::Api::App github_token = get_token(endpoint.to_s, values) user = user_for_github_token(github_token) token = generate_token(user: user, app_id: 0) - rendered_user = service(:user, user).find_one + rendered_user = Travis::Api.data(service(:user, user).find_one, type: :user, version: :v2) post_message(token: token, user: rendered_user) else values[:state] = create_state From 01e19e2888110af9c24c9b1d6e3bea2fbba1f096 Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Tue, 18 Sep 2012 22:21:38 +0200 Subject: [PATCH 19/42] use id rather than login for user --- lib/travis/api/app/endpoint/authorization.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/travis/api/app/endpoint/authorization.rb b/lib/travis/api/app/endpoint/authorization.rb index f7273db8..2885b637 100644 --- a/lib/travis/api/app/endpoint/authorization.rb +++ b/lib/travis/api/app/endpoint/authorization.rb @@ -142,7 +142,7 @@ class Travis::Api::App def user_for_github_token(token) data = GH.with(token: token.to_s) { GH['user'] } scopes = parse_scopes data.headers['x-oauth-scopes'] - user = User.find_by_login(data['login']) + user = User.find_by_github_id(data['id']) halt 403, 'not a Travis user' if user.nil? halt 403, 'insufficient access' unless acceptable? scopes From a67b8bf1ded02214afa6873c5a1894cfde7f25b9 Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Tue, 18 Sep 2012 23:33:35 +0200 Subject: [PATCH 20/42] create use if missing --- lib/travis/api/app/endpoint/authorization.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/travis/api/app/endpoint/authorization.rb b/lib/travis/api/app/endpoint/authorization.rb index 2885b637..e819a8aa 100644 --- a/lib/travis/api/app/endpoint/authorization.rb +++ b/lib/travis/api/app/endpoint/authorization.rb @@ -139,10 +139,18 @@ class Travis::Api::App generate_token options.merge(user: user_for_github_token(token)) end + def user_info(data, misc = {}) + info = data.to_hash.slice('name', 'login', 'github_oauth_token', 'gravatar_id') + info.merge! misc + info['github_id'] ||= data['id'] + info + end + def user_for_github_token(token) data = GH.with(token: token.to_s) { GH['user'] } scopes = parse_scopes data.headers['x-oauth-scopes'] user = User.find_by_github_id(data['id']) + user ||= User.create! user_info(data, github_oauth_token: token) halt 403, 'not a Travis user' if user.nil? halt 403, 'insufficient access' unless acceptable? scopes From 4a59e2286ef6bb3f239927988c3baeca863a5a9a Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Wed, 19 Sep 2012 00:21:53 +0200 Subject: [PATCH 21/42] fix some of the tests --- spec/endpoint/authorization_spec.rb | 16 +++++++++------- spec/endpoint/profile_spec.rb | 6 +++--- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/spec/endpoint/authorization_spec.rb b/spec/endpoint/authorization_spec.rb index 79bdc1b7..6810e796 100644 --- a/spec/endpoint/authorization_spec.rb +++ b/spec/endpoint/authorization_spec.rb @@ -10,8 +10,9 @@ describe Travis::Api::App::Endpoint::Authorization do end end - User.stubs(:find_by_login).with(user.login).returns(user) - User.stubs(:find).with(user.id).returns(user) + user.stubs(:github_id).returns(42) + User.stubs(:find_github_id).returns(user) + User.stubs(:find).returns(user) end describe 'GET /auth/authorize' do @@ -24,9 +25,10 @@ describe Travis::Api::App::Endpoint::Authorization do describe 'POST /auth/github' do before do - GH.stubs(:with).with(token: 'private repos').returns stub(:[] => user.login, :headers => {'x-oauth-scopes' => 'repo'}) - GH.stubs(:with).with(token: 'public repos').returns stub(:[] => user.login, :headers => {'x-oauth-scopes' => 'public_repo'}) - GH.stubs(:with).with(token: 'no repos').returns stub(:[] => user.login, :headers => {'x-oauth-scopes' => 'user'}) + data = { 'id' => user.github_id, 'name' => user.name, 'login' => user.login, 'gravatar_id' => user.gravatar_id } + GH.stubs(:with).with(token: 'private repos').returns stub(:[] => user.login, :headers => {'x-oauth-scopes' => 'repo'}, :to_hash => data) + GH.stubs(:with).with(token: 'public repos').returns stub(:[] => user.login, :headers => {'x-oauth-scopes' => 'public_repo'}, :to_hash => data) + GH.stubs(:with).with(token: 'no repos').returns stub(:[] => user.login, :headers => {'x-oauth-scopes' => 'user'}, :to_hash => data) GH.stubs(:with).with(token: 'invalid token').raises(Faraday::Error::ClientError, 'CLIENT ERROR!') end @@ -42,11 +44,11 @@ describe Travis::Api::App::Endpoint::Authorization do end it 'accepts tokens with repo scope' do - user_for('private repos').should == user + user_for('private repos').name.should == user.name end it 'accepts tokens with public_repo scope' do - user_for('public repos').should == user + user_for('public repos').name.should == user.name end it 'rejects tokens with user scope' do diff --git a/spec/endpoint/profile_spec.rb b/spec/endpoint/profile_spec.rb index 8298d76e..d02b63e5 100644 --- a/spec/endpoint/profile_spec.rb +++ b/spec/endpoint/profile_spec.rb @@ -2,11 +2,11 @@ require 'spec_helper' describe Travis::Api::App::Endpoint::Profile do include Travis::Testing::Stubs - let(:access_token) { Travis::Api::App::AccessToken.create(user: user) } + let(:access_token) { Travis::Api::App::AccessToken.create(user: user, app_id: 0) } before do - User.stubs(:find_by_login).with(user.login).returns(user) - User.stubs(:find).with(user.id).returns(user) + User.stubs(:find_by_github_id).returns(user) + User.stubs(:find).returns(user) end it 'needs to be authenticated' do From f5af1923a69dc2b800e6e0f89839e1bbf52207c7 Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Wed, 19 Sep 2012 10:19:20 +0200 Subject: [PATCH 22/42] set profile scope back to private --- lib/travis/api/app/endpoint/profile.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/travis/api/app/endpoint/profile.rb b/lib/travis/api/app/endpoint/profile.rb index 1e39238a..b8e8abad 100644 --- a/lib/travis/api/app/endpoint/profile.rb +++ b/lib/travis/api/app/endpoint/profile.rb @@ -18,8 +18,7 @@ class Travis::Api::App # "synced_at": "2012-08-14T22:11:21Z" # } # } - # , scope: :private - get '/' do + get '/', scope: :private do body service(:user).find_one, type: :user end From d708b79e135d3e7d672bd66b0754524ff8eb7cbf Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Wed, 19 Sep 2012 10:23:57 +0200 Subject: [PATCH 23/42] fix access token related tests --- lib/travis/api/app/access_token.rb | 2 +- spec/endpoint/profile_spec.rb | 2 +- spec/extensions/scoping_spec.rb | 2 +- spec/middleware/scope_check_spec.rb | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/travis/api/app/access_token.rb b/lib/travis/api/app/access_token.rb index e3b98d6c..bae8436d 100644 --- a/lib/travis/api/app/access_token.rb +++ b/lib/travis/api/app/access_token.rb @@ -68,7 +68,7 @@ class Travis::Api::App def reuse_key @reuse_key ||= begin keys = ["r", user_id, app_id] - keys.append(scopes.mpa(&:to_s).sort) if scopes != DEFAULT_SCOPES + keys.append(scopes.map(&:to_s).sort) if scopes != DEFAULT_SCOPES keys.join(':') end end diff --git a/spec/endpoint/profile_spec.rb b/spec/endpoint/profile_spec.rb index d02b63e5..43c1f19e 100644 --- a/spec/endpoint/profile_spec.rb +++ b/spec/endpoint/profile_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' describe Travis::Api::App::Endpoint::Profile do include Travis::Testing::Stubs - let(:access_token) { Travis::Api::App::AccessToken.create(user: user, app_id: 0) } + let(:access_token) { Travis::Api::App::AccessToken.create(user: user, app_id: -1) } before do User.stubs(:find_by_github_id).returns(user) diff --git a/spec/extensions/scoping_spec.rb b/spec/extensions/scoping_spec.rb index 5b037f58..ca4a1270 100644 --- a/spec/extensions/scoping_spec.rb +++ b/spec/extensions/scoping_spec.rb @@ -14,7 +14,7 @@ describe Travis::Api::App::Extensions::Scoping do end def with_scopes(url, *scopes) - token = Travis::Api::App::AccessToken.create(user: user, scopes: scopes) + token = Travis::Api::App::AccessToken.create(user: user, scopes: scopes, app_id: -1) get(url, {}, 'travis.access_token' => token) end diff --git a/spec/middleware/scope_check_spec.rb b/spec/middleware/scope_check_spec.rb index 3e6649aa..1eb820c7 100644 --- a/spec/middleware/scope_check_spec.rb +++ b/spec/middleware/scope_check_spec.rb @@ -4,7 +4,7 @@ describe Travis::Api::App::Middleware::ScopeCheck do include Travis::Testing::Stubs let :access_token do - Travis::Api::App::AccessToken.create(user: user, scope: :foo) + Travis::Api::App::AccessToken.create(user: user, scope: :foo, app_id: -1) end before do From e5ed22843f93d26c383a92f696baf13e520e2f74 Mon Sep 17 00:00:00 2001 From: Sven Fuchs Date: Wed, 19 Sep 2012 13:28:24 +0200 Subject: [PATCH 24/42] fix profile endpoint spec --- spec/endpoint/profile_spec.rb | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/spec/endpoint/profile_spec.rb b/spec/endpoint/profile_spec.rb index 43c1f19e..612a8e9c 100644 --- a/spec/endpoint/profile_spec.rb +++ b/spec/endpoint/profile_spec.rb @@ -7,6 +7,7 @@ describe Travis::Api::App::Endpoint::Profile do before do User.stubs(:find_by_github_id).returns(user) User.stubs(:find).returns(user) + user.stubs(:repositories).returns(stub(administratable: stub(select: [repository]))) end it 'needs to be authenticated' do @@ -15,14 +16,26 @@ describe Travis::Api::App::Endpoint::Profile do it 'replies with the current user' do get('/profile', access_token: access_token.to_s).should be_ok - parsed_body["user"].should == { - "login" => user.login, - "name" => user.name, - "email" => user.email, - "gravatar_id" => user.gravatar_id, - "locale" => user.locale, - "is_syncing" => user.is_syncing, - "synced_at" => user.synced_at.strftime('%Y-%m-%dT%H:%M:%SZ') + parsed_body['user'].should == { + 'id' => user.id, + 'login' => user.login, + 'name' => user.name, + 'email' => user.email, + 'gravatar_id' => user.gravatar_id, + 'locale' => user.locale, + 'is_syncing' => user.is_syncing, + 'synced_at' => user.synced_at.strftime('%Y-%m-%dT%H:%M:%SZ') } end + + it 'includes accounts' do + get('/profile', access_token: access_token.to_s).should be_ok + parsed_body['accounts'].should == [{ + 'id' => user.id, + 'login' => user.login, + 'name' => user.name, + 'type' => 'user', + 'reposCount' => nil + }] + end end From 3ddb2da33b29542aa093bcf0d28b324e6b38dcd4 Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Wed, 19 Sep 2012 15:30:46 +0200 Subject: [PATCH 25/42] better docs for authorization --- lib/travis/api/app/endpoint/authorization.rb | 45 +++++++++++++++++++- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/lib/travis/api/app/endpoint/authorization.rb b/lib/travis/api/app/endpoint/authorization.rb index e819a8aa..8a1572a5 100644 --- a/lib/travis/api/app/endpoint/authorization.rb +++ b/lib/travis/api/app/endpoint/authorization.rb @@ -18,6 +18,7 @@ class Travis::Api::App # authorize) against GitHub. # # This is the recommended way for third-party web apps. + # The entry point is [/auth/authorize](#/auth/authorize). # # ## GitHub Token # @@ -29,10 +30,14 @@ class Travis::Api::App # This is the recommended way for GitHub applications that also want Travis # integration. # + # The entry point is [/auth/github](#/auth/github). + # # ## Cross-Origin Window Messages # # This is the recommended way for the official client. We might improve the # authorization flow to support third-party clients in the future, too. + # + # The entry point is [/auth/post_message](#/auth/post_message). class Authorization < Endpoint set prefix: '/auth' enable :inline_templates @@ -49,6 +54,9 @@ class Travis::Api::App ] end + # Endpoint for retrieving an authorization code, which in turn can be used + # to generate an access token. + # # Parameters: # # * **client_id**: your App's client id (required) @@ -59,17 +67,21 @@ class Travis::Api::App raise NotImplementedError end + # Endpoint for generating an access token from an authorization code. + # # Parameters: # # * **client_id**: your App's client id (required) # * **client_secret**: your App's client secret (required) - # * **code**: code retrieved from redirect from [/authorize](#/authorize) (required) + # * **code**: code retrieved from redirect from [/auth/authorize](#/auth/authorize) (required) # * **redirect_uri**: URL to redirect to - # * **state**: same value sent to [/authorize](#/authorize) + # * **state**: same value sent to [/auth/authorize](#/auth/authorize) post '/access_token' do raise NotImplementedError end + # Endpoint for generating an access token from a GitHub access token. + # # Parameters: # # * **token**: GitHub token for checking authorization (required) @@ -77,12 +89,41 @@ class Travis::Api::App { 'access_token' => github_to_travis(params[:token], app_id: 1) } end + # Endpoint for making sure user authorized Travis CI to access GitHub. + # There are no restrictions on where to redirect to after handshake. + # However, no information whatsoever is being sent with the redirect. + # + # Parameters: + # + # * **redirect_uri**: URI to redirect after handshake. get '/handshake' do handshake do |*, redirect_uri| redirect redirect_uri end end + # This endpoint is meant to be embedded in an iframe, popup window or + # similar. It will perform the handshake and, once done, will send an + # access token and user payload to the parent window via postMessage. + # + # However, the endpoint to send the payload to has to be explicitely + # whitelisted in production, as this is endpoint is only meant to be used + # with the official Travis CI client at the moment. + # + # Example usage: + # + # window.addEventListener("message", function(event) { + # alert("received token: " + event.data.token); + # }); + # + # var iframe = $('