From a6da78ad83ba1ab70ed2fd084b27ab2d60b645f3 Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Fri, 23 Jan 2015 19:27:01 +0100 Subject: [PATCH] v3: find repos for current user (used for dashboard) --- lib/travis/api/v3.rb | 3 +- .../api/v3/access_control/application.rb | 6 +-- lib/travis/api/v3/access_control/generic.rb | 11 ++++-- lib/travis/api/v3/access_control/user.rb | 4 ++ lib/travis/api/v3/error.rb | 2 +- lib/travis/api/v3/renderer/collection.rb | 11 ++++++ lib/travis/api/v3/renderer/repositories.rb | 9 +++++ lib/travis/api/v3/renderer/repository.rb | 2 +- lib/travis/api/v3/routes.rb | 5 +++ lib/travis/api/v3/service.rb | 4 ++ lib/travis/api/v3/service_index.rb | 2 +- .../services/repositories_for_current_user.rb | 10 +++++ spec/v3/service_index_spec.rb | 7 ++-- .../repositories_for_current_user_spec.rb | 38 +++++++++++++++++++ 14 files changed, 100 insertions(+), 14 deletions(-) create mode 100644 lib/travis/api/v3/renderer/collection.rb create mode 100644 lib/travis/api/v3/renderer/repositories.rb create mode 100644 lib/travis/api/v3/services/repositories_for_current_user.rb create mode 100644 spec/v3/services/repositories_for_current_user_spec.rb diff --git a/lib/travis/api/v3.rb b/lib/travis/api/v3.rb index bd63d030..397835c8 100644 --- a/lib/travis/api/v3.rb +++ b/lib/travis/api/v3.rb @@ -20,7 +20,8 @@ module Travis ClientError = Error .create(status: 400) NotFound = ClientError .create(:resource, status: 404, template: '%s not found (or insufficient access)') EnitityMissing = NotFound .create(type: 'not_found') - WrongCredentials = ClientError .create('access denied', status: 403) + WrongCredentials = ClientError .create('access denied', status: 403) + LoginRequired = ClientError .create('login required', status: 403) WrongParams = ClientError .create('wrong parameters') end end diff --git a/lib/travis/api/v3/access_control/application.rb b/lib/travis/api/v3/access_control/application.rb index 47ff63c8..f060e2dd 100644 --- a/lib/travis/api/v3/access_control/application.rb +++ b/lib/travis/api/v3/access_control/application.rb @@ -12,12 +12,12 @@ module Travis::API::V3 raise ArgumentError, 'cannot use %p without a user' % application_name if config.requires_user and not user end - protected - def logged_in? - !!user + full_access? or !!user end + protected + def full_access? config.full_access end diff --git a/lib/travis/api/v3/access_control/generic.rb b/lib/travis/api/v3/access_control/generic.rb index e9117468..f5ea01a6 100644 --- a/lib/travis/api/v3/access_control/generic.rb +++ b/lib/travis/api/v3/access_control/generic.rb @@ -11,6 +11,13 @@ module Travis::API::V3 full_access? or dispatch(object) end + def user + end + + def logged_in? + false + end + protected def repository_visible?(repository) @@ -26,10 +33,6 @@ module Travis::API::V3 false end - def logged_in? - false - end - def public_api? !Travis.config.private_api end diff --git a/lib/travis/api/v3/access_control/user.rb b/lib/travis/api/v3/access_control/user.rb index d6881a1f..181bb399 100644 --- a/lib/travis/api/v3/access_control/user.rb +++ b/lib/travis/api/v3/access_control/user.rb @@ -10,6 +10,10 @@ module Travis::API::V3 super() end + def logged_in? + true + end + protected def private_repository_visible?(repository) diff --git a/lib/travis/api/v3/error.rb b/lib/travis/api/v3/error.rb index fe098a9b..fefd2b08 100644 --- a/lib/travis/api/v3/error.rb +++ b/lib/travis/api/v3/error.rb @@ -27,7 +27,7 @@ module Travis::API::V3 def initialize(message = self.class.default_message, status: self.class.status, type: self.class.type, **payload) if message.is_a? Symbol - payload[:resource_type] ||= message + payload[:resource_type] ||= message unless message == :resource message = self.class.template % message end diff --git a/lib/travis/api/v3/renderer/collection.rb b/lib/travis/api/v3/renderer/collection.rb new file mode 100644 index 00000000..25e61dde --- /dev/null +++ b/lib/travis/api/v3/renderer/collection.rb @@ -0,0 +1,11 @@ + +module Travis::API::V3 + module Renderer::Collection + extend self + + def render(collection_type, entry_type, entries, **additional) + entries &&= entries.map { |entry| Renderer[entry_type].render(entry) } + { :@type => collection_type, collection_type => entries, **additional } + end + end +end diff --git a/lib/travis/api/v3/renderer/repositories.rb b/lib/travis/api/v3/renderer/repositories.rb new file mode 100644 index 00000000..3d86ef77 --- /dev/null +++ b/lib/travis/api/v3/renderer/repositories.rb @@ -0,0 +1,9 @@ +module Travis::API::V3 + module Renderer::Repositories + extend self + + def render(repositories) + Renderer[:collection].render(:repositories, :repository, repositories) + end + end +end diff --git a/lib/travis/api/v3/renderer/repository.rb b/lib/travis/api/v3/renderer/repository.rb index f618071c..4538db90 100644 --- a/lib/travis/api/v3/renderer/repository.rb +++ b/lib/travis/api/v3/renderer/repository.rb @@ -14,7 +14,7 @@ module Travis::API::V3 def nested_resources(repository) { owner: { - :@type => repository.owner_type.downcase, + :@type => repository.owner_type && repository.owner_type.downcase, :id => repository.owner_id, :login => repository.owner_name }, diff --git a/lib/travis/api/v3/routes.rb b/lib/travis/api/v3/routes.rb index 57efe10d..8f7821f3 100644 --- a/lib/travis/api/v3/routes.rb +++ b/lib/travis/api/v3/routes.rb @@ -7,5 +7,10 @@ module Travis::API::V3 route '/repo/{repository.id}' get :find_repository end + + resource :repositories do + route '/repos' + get :repositories_for_current_user + end end end diff --git a/lib/travis/api/v3/service.rb b/lib/travis/api/v3/service.rb index 374cae17..35cbbbae 100644 --- a/lib/travis/api/v3/service.rb +++ b/lib/travis/api/v3/service.rb @@ -30,5 +30,9 @@ module Travis::API::V3 def required_params self.class.required_params end + + def run_service(name, added_params = {}) + Services[name].new(access_control, params: params.merge(added_params)).run + end end end diff --git a/lib/travis/api/v3/service_index.rb b/lib/travis/api/v3/service_index.rb index f3a44c67..fbfe4072 100644 --- a/lib/travis/api/v3/service_index.rb +++ b/lib/travis/api/v3/service_index.rb @@ -27,7 +27,7 @@ module Travis::API::V3 routes.resources.each do |resource| resources[resource.identifier] ||= {} resource.services.each do |(request_method, sub_route), service| - service &&= service.to_s.sub(/_#{resource.identifier}$/, ''.freeze) + service &&= service.to_s.sub(/^#{resource.identifier}_|_#{resource.identifier}$/, ''.freeze) list = resources[resource.identifier][service] ||= [] pattern = sub_route ? resource.route + sub_route : resource.route pattern.to_templates.each do |template| diff --git a/lib/travis/api/v3/services/repositories_for_current_user.rb b/lib/travis/api/v3/services/repositories_for_current_user.rb new file mode 100644 index 00000000..56ff97f2 --- /dev/null +++ b/lib/travis/api/v3/services/repositories_for_current_user.rb @@ -0,0 +1,10 @@ +module Travis::API::V3 + class Services::RepositoriesForCurrentUser < Service + def run + raise LoginRequired unless access_control.logged_in? + raise NotFound, :repositories unless access_control.user + repositories = ::Repository::joins(:users).where(users: { id: access_control.user.id }) + Result.new(:repositories, repositories) + end + end +end diff --git a/spec/v3/service_index_spec.rb b/spec/v3/service_index_spec.rb index ea98e379..4b460def 100644 --- a/spec/v3/service_index_spec.rb +++ b/spec/v3/service_index_spec.rb @@ -8,9 +8,10 @@ describe Travis::API::V3::ServiceIndex do describe "custom json entry point" do let(:expected_resources) {{ - "repository" => { - "find" => [{"request-method"=>"GET", "uri-template"=>"#{path}repo/{repository.id}"}] - } + "repository" => { + "find" => [{"request-method"=>"GET", "uri-template"=>"#{path}repo/{repository.id}"}] }, + "repositories" => { + "for_current_user" => [{"request-method"=>"GET", "uri-template"=>"#{path}repos"}] } }} describe 'with /v3 prefix' do diff --git a/spec/v3/services/repositories_for_current_user_spec.rb b/spec/v3/services/repositories_for_current_user_spec.rb new file mode 100644 index 00000000..49b7c53b --- /dev/null +++ b/spec/v3/services/repositories_for_current_user_spec.rb @@ -0,0 +1,38 @@ +require 'spec_helper' + +describe Travis::API::V3::Services::FindRepository do + let(:repo) { Repository.by_slug('svenfuchs/minimal').first } + + describe "private repository, private API, authenticated as user with access" do + let(:token) { Travis::Api::App::AccessToken.create(user: repo.owner, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + before { Permission.create(repository: repo, user: repo.owner, pull: true) } + before { repo.update_attribute(:private, true) } + before { get("/v3/repos", {}, headers) } + before { repo.update_attribute(:private, false) } + example { expect(last_response).to be_ok } + example { expect(JSON.load(body)).to be == { + "@type" => "repositories", + "repositories" => [{ + "@type" => "repository", + "id" => repo.id, + "name" => "minimal", + "slug" => "svenfuchs/minimal", + "description" => nil, + "github_language" => nil, + "private" => true, + "owner" => { + "@type" => "user", + "id" => repo.owner_id, + "login" => "svenfuchs" }, + "last_build" => { + "@type" => "build", + "id" => repo.last_build_id, + "number" => "2", + "state" => "passed", + "duration" => nil, + "started_at" => "2010-11-12T12:30:00Z", + "finished_at" => "2010-11-12T12:30:20Z"}}] + }} + end +end \ No newline at end of file