diff --git a/lib/travis/api/v3/access_control/scoped.rb b/lib/travis/api/v3/access_control/scoped.rb index 5bf1df90..33b8017d 100644 --- a/lib/travis/api/v3/access_control/scoped.rb +++ b/lib/travis/api/v3/access_control/scoped.rb @@ -2,18 +2,27 @@ require 'travis/api/v3/access_control/generic' module Travis::API::V3 class AccessControl::Scoped < AccessControl::Generic - attr_accessor :unscoped, :owner_name, :name + attr_accessor :unscoped, :anonymous, :owner_name, :name def initialize(scope, unscoped) @owner_name, @name = scope.split(?/.freeze, 2) @unscoped = unscoped + @anonymous = AccessControl::Anonymous.new end protected def private_repository_visible?(repository) + scope_repository(repository).visible?(repository) + end + + def repository_writable?(repository) + scope_repository(repository).writable?(repository) + end + + def scope_repository(repository, method = caller_locations.first.base_label) return false if name and repository.name != name - unscoped.visible?(repository) if repository.owner_name == owner_name + repository.owner_name == owner_name ? unscoped : anonymous end end end diff --git a/lib/travis/api/v3/permissions/generic.rb b/lib/travis/api/v3/permissions/generic.rb index ac270bfe..5648adfd 100644 --- a/lib/travis/api/v3/permissions/generic.rb +++ b/lib/travis/api/v3/permissions/generic.rb @@ -2,11 +2,12 @@ module Travis::API::V3 class Permissions::Generic def self.access_rights @access_rights ||= begin - rights = superclass.respond_to?(:access_rights) ? superclass.access_rights.dup : [] - public_instance_methods(false) do |method| + rights = superclass.respond_to?(:access_rights) ? superclass.access_rights.dup : {} + public_instance_methods(false).each do |method| next unless method.to_s =~ /^([^_].+)\?$/ - rights << $1.to_sym + rights[$1.to_sym] = method end + rights end end @@ -46,6 +47,10 @@ module Travis::API::V3 access_control.visible? object end + def to_h + self.class.access_rights.map { |k,v| [k,!!public_send(v)] }.to_h + end + private def write? diff --git a/lib/travis/api/v3/renderer/model_renderer.rb b/lib/travis/api/v3/renderer/model_renderer.rb index 491aa627..81b4a864 100644 --- a/lib/travis/api/v3/renderer/model_renderer.rb +++ b/lib/travis/api/v3/renderer/model_renderer.rb @@ -43,7 +43,7 @@ module Travis::API::V3 @script_name = script_name @include = include @included = included - @access_control = access_control + @access_control = access_control || AccessControl::Anonymous.new end def href @@ -74,13 +74,17 @@ module Travis::API::V3 nested_included = included + [model] modes = {} + if permissions = access_control.permissions(model) and (representation != :minimal or include? :@permissions) + result[:@permissions] = permissions.to_h + end + if include.any? excepted_type = result[:@type].to_s fields = fields.dup end include.each do |qualified_field| - raise WrongParams, 'illegal format for include parameter'.freeze unless /\A(?\w+)\.(?\w+)\Z$/ =~ qualified_field + raise WrongParams, 'illegal format for include parameter'.freeze unless /\A(?\w+)\.(?@?\w+)\Z$/ =~ qualified_field next if prefix != excepted_type raise WrongParams, 'no field %p to include'.freeze % qualified_field unless self.class.available_attributes.include?(field) diff --git a/spec/v3/services/owner/find_spec.rb b/spec/v3/services/owner/find_spec.rb index 90152fd8..b5dd0c82 100644 --- a/spec/v3/services/owner/find_spec.rb +++ b/spec/v3/services/owner/find_spec.rb @@ -39,6 +39,11 @@ describe Travis::API::V3::Services::Owner::Find do "repositories" => [{ "@type" => "repository", "@href" => "/v3/repo/#{repo.id}", + "@permissions" => { + "read" => true, + "enable" => false, + "disable" => false, + "create_request"=> false}, "id" => repo.id, "name" => "example-repo", "slug" => "example-org/example-repo", @@ -76,6 +81,11 @@ describe Travis::API::V3::Services::Owner::Find do "repositories" => [{ "@type" => "repository", "@href" => "/v3/repo/#{repo.id}", + "@permissions" => { + "read" => true, + "enable" => false, + "disable" => false, + "create_request"=> false}, "id" => repo.id, "name" => "example-repo", "slug" => "example-org/example-repo", diff --git a/spec/v3/services/owner/repositories_spec.rb b/spec/v3/services/owner/repositories_spec.rb index 9f47fecb..77285bfc 100644 --- a/spec/v3/services/owner/repositories_spec.rb +++ b/spec/v3/services/owner/repositories_spec.rb @@ -18,6 +18,11 @@ describe Travis::API::V3::Services::Owner::Repositories do "repositories" => [{ "@type" => "repository", "@href" => "/v3/repo/#{repo.id}", + "@permissions" => { + "read" => true, + "enable" => false, + "disable" => false, + "create_request"=> false}, "id" => repo.id, "name" => "minimal", "slug" => "svenfuchs/minimal", diff --git a/spec/v3/services/repositories/for_current_user_spec.rb b/spec/v3/services/repositories/for_current_user_spec.rb index 67068f69..26fe6151 100644 --- a/spec/v3/services/repositories/for_current_user_spec.rb +++ b/spec/v3/services/repositories/for_current_user_spec.rb @@ -3,11 +3,11 @@ require 'spec_helper' describe Travis::API::V3::Services::Repositories::ForCurrentUser do let(:repo) { Repository.by_slug('svenfuchs/minimal').first } - 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) } - after { repo.update_attribute(:private, false) } + 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, push: true) } + before { repo.update_attribute(:private, true) } + after { repo.update_attribute(:private, false) } describe "private repository, private API, authenticated as user with access" do before { get("/v3/repos", {}, headers) } @@ -18,6 +18,11 @@ describe Travis::API::V3::Services::Repositories::ForCurrentUser do "repositories" => [{ "@type" => "repository", "@href" => "/v3/repo/#{repo.id}", + "@permissions" => { + "read" => true, + "enable" => true, + "disable" => true, + "create_request"=> true}, "id" => repo.id, "name" => "minimal", "slug" => "svenfuchs/minimal", diff --git a/spec/v3/services/repository/find_spec.rb b/spec/v3/services/repository/find_spec.rb index b92df8d0..d0d6d431 100644 --- a/spec/v3/services/repository/find_spec.rb +++ b/spec/v3/services/repository/find_spec.rb @@ -10,6 +10,11 @@ describe Travis::API::V3::Services::Repository::Find do example { expect(parsed_body).to be == { "@type" => "repository", "@href" => "/v3/repo/#{repo.id}", + "@permissions" => { + "read" => true, + "enable" => false, + "disable" => false, + "create_request"=> false}, "id" => repo.id, "name" => "minimal", "slug" => "svenfuchs/minimal", @@ -95,6 +100,11 @@ describe Travis::API::V3::Services::Repository::Find do example { expect(parsed_body).to be == { "@type" => "repository", "@href" => "/v3/repo/#{repo.id}", + "@permissions" => { + "read" => true, + "enable" => false, + "disable" => false, + "create_request"=> false}, "id" => repo.id, "name" => "minimal", "slug" => "svenfuchs/minimal", @@ -165,6 +175,11 @@ describe Travis::API::V3::Services::Repository::Find do example { expect(parsed_body).to be == { "@type" => "repository", "@href" => "/v3/repo/#{repo.id}", + "@permissions" => { + "read" => true, + "enable" => true, + "disable" => true, + "create_request"=> true}, "id" => repo.id, "name" => "minimal", "slug" => "svenfuchs/minimal", @@ -241,6 +256,11 @@ describe Travis::API::V3::Services::Repository::Find do example { expect(parsed_body).to be == { "@type" => "repository", "@href" => "/v3/repo/#{repo.id}", + "@permissions" => { + "read" => true, + "enable" => true, + "disable" => true, + "create_request"=> true}, "id" => repo.id, "name" => "minimal", "slug" => "svenfuchs/minimal",