Merge branch 'rkh-v3-permissions'
This commit is contained in:
commit
815a217536
|
@ -30,7 +30,6 @@ module Travis
|
||||||
WrongCredentials = ClientError .create('access denied', status: 403)
|
WrongCredentials = ClientError .create('access denied', status: 403)
|
||||||
LoginRequired = ClientError .create('login required', status: 403)
|
LoginRequired = ClientError .create('login required', status: 403)
|
||||||
InsufficientAccess = ClientError .create(status: 403)
|
InsufficientAccess = ClientError .create(status: 403)
|
||||||
PushAccessRequired = InsufficientAccess .create('push access required')
|
|
||||||
WrongParams = ClientError .create('wrong parameters')
|
WrongParams = ClientError .create('wrong parameters')
|
||||||
ServerError = Error .create(status: 500)
|
ServerError = Error .create(status: 500)
|
||||||
NotImplemented = ServerError .create('request not (yet) implemented', status: 501)
|
NotImplemented = ServerError .create('request not (yet) implemented', status: 501)
|
||||||
|
|
|
@ -36,8 +36,17 @@ module Travis::API::V3
|
||||||
list.select { |r| visible?(r) }
|
list.select { |r| visible?(r) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def permissions(object)
|
||||||
|
return unless factory = permission_class(object.class)
|
||||||
|
factory.new(self, object)
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
|
def account_visible?(account)
|
||||||
|
user and account.members.include?(user)
|
||||||
|
end
|
||||||
|
|
||||||
def build_visible?(build)
|
def build_visible?(build)
|
||||||
visible? build.repository
|
visible? build.repository
|
||||||
end
|
end
|
||||||
|
@ -78,13 +87,22 @@ module Travis::API::V3
|
||||||
send(method, object) if respond_to?(method, true)
|
send(method, object) if respond_to?(method, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@method_for_cache = Tool::ThreadLocal.new
|
|
||||||
|
@@unknown_permission = Object.new
|
||||||
|
@@permission_class_cache = Tool::ThreadLocal.new
|
||||||
|
@@method_for_cache = Tool::ThreadLocal.new
|
||||||
|
|
||||||
|
def permission_class(klass)
|
||||||
|
result = @@permission_class_cache[klass] ||= Permissions[normailze_type(klass), false] || @@unknown_permission
|
||||||
|
result unless result == @@unknown_permission
|
||||||
|
end
|
||||||
|
|
||||||
def method_for(type, method)
|
def method_for(type, method)
|
||||||
@@method_for_cache[[type, method]] ||= begin
|
@@method_for_cache[[type, method]] ||= "#{normailze_type(type)}_#{method}"
|
||||||
prefix = type.name.sub(/^Travis::API::V3::Models::/, ''.freeze).underscore
|
end
|
||||||
"#{prefix}_#{method}"
|
|
||||||
end
|
def normailze_type(type)
|
||||||
|
type.name.sub(/^Travis::API::V3::Models::/, ''.freeze).underscore.to_sym
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,18 +2,27 @@ require 'travis/api/v3/access_control/generic'
|
||||||
|
|
||||||
module Travis::API::V3
|
module Travis::API::V3
|
||||||
class AccessControl::Scoped < AccessControl::Generic
|
class AccessControl::Scoped < AccessControl::Generic
|
||||||
attr_accessor :unscoped, :owner_name, :name
|
attr_accessor :unscoped, :anonymous, :owner_name, :name
|
||||||
|
|
||||||
def initialize(scope, unscoped)
|
def initialize(scope, unscoped)
|
||||||
@owner_name, @name = scope.split(?/.freeze, 2)
|
@owner_name, @name = scope.split(?/.freeze, 2)
|
||||||
@unscoped = unscoped
|
@unscoped = unscoped
|
||||||
|
@anonymous = AccessControl::Anonymous.new
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def private_repository_visible?(repository)
|
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
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,12 +2,12 @@ require 'travis/api/v3/access_control/generic'
|
||||||
|
|
||||||
module Travis::API::V3
|
module Travis::API::V3
|
||||||
class AccessControl::User < AccessControl::Generic
|
class AccessControl::User < AccessControl::Generic
|
||||||
attr_reader :user, :permissions
|
attr_reader :user, :access_permissions
|
||||||
|
|
||||||
def initialize(user)
|
def initialize(user)
|
||||||
user = Models::User.find(user.id) if user.is_a? ::User
|
user = Models::User.find(user.id) if user.is_a? ::User
|
||||||
@user = user
|
@user = user
|
||||||
@permissions = user.permissions.where(user_id: user.id)
|
@access_permissions = user.permissions.where(user_id: user.id)
|
||||||
super()
|
super()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -20,11 +20,19 @@ module Travis::API::V3
|
||||||
end
|
end
|
||||||
|
|
||||||
def visible_repositories(list)
|
def visible_repositories(list)
|
||||||
list.where('repositories.private = false OR repositories.id IN (?)'.freeze, permissions.map(&:repository_id))
|
list.where('repositories.private = false OR repositories.id IN (?)'.freeze, access_permissions.map(&:repository_id))
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
|
def organization_writable?(organization)
|
||||||
|
organization.members.include? user
|
||||||
|
end
|
||||||
|
|
||||||
|
def user_writable?(user)
|
||||||
|
user == self.user
|
||||||
|
end
|
||||||
|
|
||||||
def repository_writable?(repository)
|
def repository_writable?(repository)
|
||||||
permission?(:push, repository)
|
permission?(:push, repository)
|
||||||
end
|
end
|
||||||
|
@ -35,7 +43,7 @@ module Travis::API::V3
|
||||||
|
|
||||||
def permission?(type, id)
|
def permission?(type, id)
|
||||||
id = id.id if id.is_a? ::Repository
|
id = id.id if id.is_a? ::Repository
|
||||||
permissions.where(type => true, :repository_id => id).any?
|
access_permissions.where(type => true, :repository_id => id).any?
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -23,6 +23,20 @@ module Travis::API::V3
|
||||||
subscription.present? and subscription.active?
|
subscription.present? and subscription.active?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def members
|
||||||
|
@members ||= if owner.respond_to? :members
|
||||||
|
owner.members
|
||||||
|
else
|
||||||
|
[owner]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def reload
|
||||||
|
@members = nil
|
||||||
|
owner.reload
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
alias_method :educational, :educational?
|
alias_method :educational, :educational?
|
||||||
alias_method :subscribed, :subscribed?
|
alias_method :subscribed, :subscribed?
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,5 +8,7 @@ module Travis::API::V3
|
||||||
def subscription
|
def subscription
|
||||||
super if Features.use_subscriptions?
|
super if Features.use_subscriptions?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
alias members users
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
5
lib/travis/api/v3/permissions.rb
Normal file
5
lib/travis/api/v3/permissions.rb
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
module Travis::API::V3
|
||||||
|
module Permissions
|
||||||
|
extend ConstantResolver
|
||||||
|
end
|
||||||
|
end
|
6
lib/travis/api/v3/permissions/account.rb
Normal file
6
lib/travis/api/v3/permissions/account.rb
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
require 'travis/api/v3/permissions/generic'
|
||||||
|
|
||||||
|
module Travis::API::V3
|
||||||
|
class Permissions::Account < Permissions::Generic
|
||||||
|
end
|
||||||
|
end
|
60
lib/travis/api/v3/permissions/generic.rb
Normal file
60
lib/travis/api/v3/permissions/generic.rb
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
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).each do |method|
|
||||||
|
next unless method.to_s =~ /^([^_].+)\?$/
|
||||||
|
rights[$1.to_sym] = method
|
||||||
|
end
|
||||||
|
rights
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# for any public method defined with a question mark in the end, it defines a method with an
|
||||||
|
# exclamation mark that will raise an InsufficientAccess error if the question mark version
|
||||||
|
# returns false
|
||||||
|
def self.method_added(method_name)
|
||||||
|
super
|
||||||
|
|
||||||
|
return unless public_method_defined?(method_name)
|
||||||
|
return unless method_name.to_s =~ /^([^_].+)\?$/
|
||||||
|
|
||||||
|
permission = $1
|
||||||
|
type = name[/[^:]+$/].underscore
|
||||||
|
|
||||||
|
class_eval <<-RUBY
|
||||||
|
def #{permission}!
|
||||||
|
return self if #{permission}?
|
||||||
|
payload = {
|
||||||
|
resource_type: "#{type}".freeze,
|
||||||
|
permission: "#{permission}".freeze
|
||||||
|
}
|
||||||
|
payload[:#{type}] = object if read?
|
||||||
|
raise InsufficientAccess.new('operation requires #{permission} access to #{type}', payload)
|
||||||
|
end
|
||||||
|
RUBY
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_accessor :access_control, :object
|
||||||
|
|
||||||
|
def initialize(access_control, object)
|
||||||
|
@access_control = access_control
|
||||||
|
@object = object
|
||||||
|
end
|
||||||
|
|
||||||
|
def read?
|
||||||
|
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?
|
||||||
|
access_control.writable? object
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
9
lib/travis/api/v3/permissions/organization.rb
Normal file
9
lib/travis/api/v3/permissions/organization.rb
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
require 'travis/api/v3/permissions/generic'
|
||||||
|
|
||||||
|
module Travis::API::V3
|
||||||
|
class Permissions::Organization < Permissions::Generic
|
||||||
|
def sync?
|
||||||
|
write?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
17
lib/travis/api/v3/permissions/repository.rb
Normal file
17
lib/travis/api/v3/permissions/repository.rb
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
require 'travis/api/v3/permissions/generic'
|
||||||
|
|
||||||
|
module Travis::API::V3
|
||||||
|
class Permissions::Repository < Permissions::Generic
|
||||||
|
def enable?
|
||||||
|
write?
|
||||||
|
end
|
||||||
|
|
||||||
|
def disable?
|
||||||
|
write?
|
||||||
|
end
|
||||||
|
|
||||||
|
def create_request?
|
||||||
|
write?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
9
lib/travis/api/v3/permissions/user.rb
Normal file
9
lib/travis/api/v3/permissions/user.rb
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
require 'travis/api/v3/permissions/generic'
|
||||||
|
|
||||||
|
module Travis::API::V3
|
||||||
|
class Permissions::User < Permissions::Generic
|
||||||
|
def sync?
|
||||||
|
write?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -43,7 +43,7 @@ module Travis::API::V3
|
||||||
@script_name = script_name
|
@script_name = script_name
|
||||||
@include = include
|
@include = include
|
||||||
@included = included
|
@included = included
|
||||||
@access_control = access_control
|
@access_control = access_control || AccessControl::Anonymous.new
|
||||||
end
|
end
|
||||||
|
|
||||||
def href
|
def href
|
||||||
|
@ -74,19 +74,26 @@ module Travis::API::V3
|
||||||
nested_included = included + [model]
|
nested_included = included + [model]
|
||||||
modes = {}
|
modes = {}
|
||||||
|
|
||||||
|
if permissions = access_control.permissions(model) and (representation != :minimal or include? :@permissions)
|
||||||
|
result[:@permissions] = permissions.to_h
|
||||||
|
end
|
||||||
|
|
||||||
if include.any?
|
if include.any?
|
||||||
excepted_type = result[:@type].to_s
|
excepted_type = result[:@type].to_s
|
||||||
fields = fields.dup
|
fields = fields.dup
|
||||||
end
|
end
|
||||||
|
|
||||||
include.each do |qualified_field|
|
include.each do |qualified_field|
|
||||||
raise WrongParams, 'illegal format for include parameter'.freeze unless /\A(?<prefix>\w+)\.(?<field>\w+)\Z$/ =~ qualified_field
|
raise WrongParams, 'illegal format for include parameter'.freeze unless /\A(?<prefix>\w+)\.(?<field>@?\w+)\Z$/ =~ qualified_field
|
||||||
next if prefix != excepted_type
|
next if prefix != excepted_type
|
||||||
raise WrongParams, 'no field %p to include'.freeze % qualified_field unless self.class.available_attributes.include?(field)
|
|
||||||
|
|
||||||
field &&= field.to_sym
|
if self.class.available_attributes.include?(field)
|
||||||
fields << field unless fields.include?(field)
|
field &&= field.to_sym
|
||||||
modes[field] = :standard
|
fields << field unless fields.include?(field)
|
||||||
|
modes[field] = :standard
|
||||||
|
else
|
||||||
|
raise WrongParams, 'no field %p to include'.freeze % qualified_field unless result.keys.any? { |k| k.to_s == field.to_s }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
fields.each do |field|
|
fields.each do |field|
|
||||||
|
|
|
@ -3,6 +3,7 @@ module Travis::API::V3
|
||||||
def run!(activate = false)
|
def run!(activate = false)
|
||||||
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
|
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
|
||||||
raise NotFound unless repository = find(:repository)
|
raise NotFound unless repository = find(:repository)
|
||||||
|
check_access(repository)
|
||||||
|
|
||||||
admin = access_control.admin_for(repository)
|
admin = access_control.admin_for(repository)
|
||||||
|
|
||||||
|
@ -11,5 +12,9 @@ module Travis::API::V3
|
||||||
|
|
||||||
repository
|
repository
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def check_access(repository)
|
||||||
|
access_control.permissions(repository).disable!
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,5 +3,9 @@ module Travis::API::V3
|
||||||
def run!
|
def run!
|
||||||
super(true)
|
super(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def check_access(repository)
|
||||||
|
access_control.permissions(repository).enable!
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,9 +8,9 @@ module Travis::API::V3
|
||||||
params "request", "user", :config, :message, :branch
|
params "request", "user", :config, :message, :branch
|
||||||
|
|
||||||
def run
|
def run
|
||||||
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
|
raise LoginRequired unless access_control.logged_in? or access_control.full_access?
|
||||||
raise NotFound unless repository = find(:repository)
|
raise NotFound unless repository = find(:repository)
|
||||||
raise PushAccessRequired, repository: repository unless access_control.writable?(repository)
|
access_control.permissions(repository).create_request!
|
||||||
|
|
||||||
user = find(:user) if access_control.full_access? and params_for? 'user'.freeze
|
user = find(:user) if access_control.full_access? and params_for? 'user'.freeze
|
||||||
user ||= access_control.user
|
user ||= access_control.user
|
||||||
|
|
|
@ -22,6 +22,7 @@ describe Travis::API::V3::Services::Accounts::ForCurrentUser do
|
||||||
"@href" => "/v3/accounts",
|
"@href" => "/v3/accounts",
|
||||||
"accounts" => [{
|
"accounts" => [{
|
||||||
"@type" => "account",
|
"@type" => "account",
|
||||||
|
"@permissions" => { "read"=>true },
|
||||||
"id" => repo.owner.github_id,
|
"id" => repo.owner.github_id,
|
||||||
"subscribed" => false,
|
"subscribed" => false,
|
||||||
"educational" => false,
|
"educational" => false,
|
||||||
|
@ -31,6 +32,7 @@ describe Travis::API::V3::Services::Accounts::ForCurrentUser do
|
||||||
"id" => repo.owner_id,
|
"id" => repo.owner_id,
|
||||||
"login" => "svenfuchs" }},
|
"login" => "svenfuchs" }},
|
||||||
{"@type" => "account",
|
{"@type" => "account",
|
||||||
|
"@permissions" => { "read"=>true },
|
||||||
"id" => 42,
|
"id" => 42,
|
||||||
"subscribed" => false,
|
"subscribed" => false,
|
||||||
"educational" => false,
|
"educational" => false,
|
||||||
|
|
|
@ -9,13 +9,14 @@ describe Travis::API::V3::Services::Organization::Find do
|
||||||
before { get("/v3/org/#{org.id}") }
|
before { get("/v3/org/#{org.id}") }
|
||||||
example { expect(last_response).to be_ok }
|
example { expect(last_response).to be_ok }
|
||||||
example { expect(JSON.load(body)).to be == {
|
example { expect(JSON.load(body)).to be == {
|
||||||
"@type" => "organization",
|
"@type" => "organization",
|
||||||
"@href" => "/v3/org/#{org.id}",
|
"@href" => "/v3/org/#{org.id}",
|
||||||
"id" => org.id,
|
"@permissions" => { "read"=>true, "sync"=>false },
|
||||||
"login" => "example-org",
|
"id" => org.id,
|
||||||
"name" => nil,
|
"login" => "example-org",
|
||||||
"github_id" => nil,
|
"name" => nil,
|
||||||
"avatar_url" => nil
|
"github_id" => nil,
|
||||||
|
"avatar_url" => nil
|
||||||
}}
|
}}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,16 +18,17 @@ describe Travis::API::V3::Services::Organizations::ForCurrentUser do
|
||||||
before { get("/v3/orgs", {}, headers) }
|
before { get("/v3/orgs", {}, headers) }
|
||||||
example { expect(last_response).to be_ok }
|
example { expect(last_response).to be_ok }
|
||||||
example { expect(JSON.load(body)).to be == {
|
example { expect(JSON.load(body)).to be == {
|
||||||
"@type" => "organizations",
|
"@type" => "organizations",
|
||||||
"@href" => "/v3/orgs",
|
"@href" => "/v3/orgs",
|
||||||
"organizations" => [{
|
"organizations" => [{
|
||||||
"@type" => "organization",
|
"@type" => "organization",
|
||||||
"@href" => "/v3/org/#{org.id}",
|
"@href" => "/v3/org/#{org.id}",
|
||||||
"id" => org.id,
|
"@permissions" => { "read"=>true, "sync"=>true },
|
||||||
"login" => "example-org",
|
"id" => org.id,
|
||||||
"name" => nil,
|
"login" => "example-org",
|
||||||
"github_id" => nil,
|
"name" => nil,
|
||||||
"avatar_url" => nil
|
"github_id" => nil,
|
||||||
|
"avatar_url" => nil
|
||||||
}]
|
}]
|
||||||
}}
|
}}
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,13 +10,14 @@ describe Travis::API::V3::Services::Owner::Find do
|
||||||
before { get("/v3/owner/example-org") }
|
before { get("/v3/owner/example-org") }
|
||||||
example { expect(last_response).to be_ok }
|
example { expect(last_response).to be_ok }
|
||||||
example { expect(JSON.load(body)).to be == {
|
example { expect(JSON.load(body)).to be == {
|
||||||
"@type" => "organization",
|
"@type" => "organization",
|
||||||
"@href" => "/v3/org/#{org.id}",
|
"@href" => "/v3/org/#{org.id}",
|
||||||
"id" => org.id,
|
"@permissions" => { "read"=>true, "sync"=>false },
|
||||||
"login" => "example-org",
|
"id" => org.id,
|
||||||
"name" => nil,
|
"login" => "example-org",
|
||||||
"github_id" => nil,
|
"name" => nil,
|
||||||
"avatar_url" => nil
|
"github_id" => nil,
|
||||||
|
"avatar_url" => nil
|
||||||
}}
|
}}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -31,6 +32,7 @@ describe Travis::API::V3::Services::Owner::Find do
|
||||||
example { expect(JSON.load(body)).to be == {
|
example { expect(JSON.load(body)).to be == {
|
||||||
"@type" => "organization",
|
"@type" => "organization",
|
||||||
"@href" => "/v3/org/#{org.id}",
|
"@href" => "/v3/org/#{org.id}",
|
||||||
|
"@permissions" => { "read"=>true, "sync"=>false },
|
||||||
"id" => org.id,
|
"id" => org.id,
|
||||||
"login" => "example-org",
|
"login" => "example-org",
|
||||||
"name" => nil,
|
"name" => nil,
|
||||||
|
@ -39,6 +41,11 @@ describe Travis::API::V3::Services::Owner::Find do
|
||||||
"repositories" => [{
|
"repositories" => [{
|
||||||
"@type" => "repository",
|
"@type" => "repository",
|
||||||
"@href" => "/v3/repo/#{repo.id}",
|
"@href" => "/v3/repo/#{repo.id}",
|
||||||
|
"@permissions" => {
|
||||||
|
"read" => true,
|
||||||
|
"enable" => false,
|
||||||
|
"disable" => false,
|
||||||
|
"create_request"=> false},
|
||||||
"id" => repo.id,
|
"id" => repo.id,
|
||||||
"name" => "example-repo",
|
"name" => "example-repo",
|
||||||
"slug" => "example-org/example-repo",
|
"slug" => "example-org/example-repo",
|
||||||
|
@ -68,6 +75,7 @@ describe Travis::API::V3::Services::Owner::Find do
|
||||||
example { expect(JSON.load(body)).to be == {
|
example { expect(JSON.load(body)).to be == {
|
||||||
"@type" => "organization",
|
"@type" => "organization",
|
||||||
"@href" => "/v3/org/#{org.id}",
|
"@href" => "/v3/org/#{org.id}",
|
||||||
|
"@permissions" => { "read"=>true, "sync"=>false },
|
||||||
"id" => org.id,
|
"id" => org.id,
|
||||||
"login" => "example-org",
|
"login" => "example-org",
|
||||||
"name" => nil,
|
"name" => nil,
|
||||||
|
@ -76,6 +84,11 @@ describe Travis::API::V3::Services::Owner::Find do
|
||||||
"repositories" => [{
|
"repositories" => [{
|
||||||
"@type" => "repository",
|
"@type" => "repository",
|
||||||
"@href" => "/v3/repo/#{repo.id}",
|
"@href" => "/v3/repo/#{repo.id}",
|
||||||
|
"@permissions" => {
|
||||||
|
"read" => true,
|
||||||
|
"enable" => false,
|
||||||
|
"disable" => false,
|
||||||
|
"create_request"=> false},
|
||||||
"id" => repo.id,
|
"id" => repo.id,
|
||||||
"name" => "example-repo",
|
"name" => "example-repo",
|
||||||
"slug" => "example-org/example-repo",
|
"slug" => "example-org/example-repo",
|
||||||
|
@ -98,13 +111,14 @@ describe Travis::API::V3::Services::Owner::Find do
|
||||||
before { get("/v3/owner/example-ORG") }
|
before { get("/v3/owner/example-ORG") }
|
||||||
example { expect(last_response).to be_ok }
|
example { expect(last_response).to be_ok }
|
||||||
example { expect(JSON.load(body)).to be == {
|
example { expect(JSON.load(body)).to be == {
|
||||||
"@type" => "organization",
|
"@type" => "organization",
|
||||||
"@href" => "/v3/org/#{org.id}",
|
"@href" => "/v3/org/#{org.id}",
|
||||||
"id" => org.id,
|
"@permissions" => { "read"=>true, "sync"=>false },
|
||||||
"login" => "example-org",
|
"id" => org.id,
|
||||||
"name" => nil,
|
"login" => "example-org",
|
||||||
"github_id" => nil,
|
"name" => nil,
|
||||||
"avatar_url" => nil
|
"github_id" => nil,
|
||||||
|
"avatar_url" => nil
|
||||||
}}
|
}}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -116,13 +130,14 @@ describe Travis::API::V3::Services::Owner::Find do
|
||||||
before { get("/v3/owner/example-org?organization.id=#{other.id}") }
|
before { get("/v3/owner/example-org?organization.id=#{other.id}") }
|
||||||
example { expect(last_response).to be_ok }
|
example { expect(last_response).to be_ok }
|
||||||
example { expect(JSON.load(body)).to be == {
|
example { expect(JSON.load(body)).to be == {
|
||||||
"@type" => "organization",
|
"@type" => "organization",
|
||||||
"@href" => "/v3/org/#{org.id}",
|
"@href" => "/v3/org/#{org.id}",
|
||||||
"id" => org.id,
|
"@permissions" => { "read"=>true, "sync"=>false },
|
||||||
"login" => "example-org",
|
"id" => org.id,
|
||||||
"name" => nil,
|
"login" => "example-org",
|
||||||
"github_id" => nil,
|
"name" => nil,
|
||||||
"avatar_url" => nil
|
"github_id" => nil,
|
||||||
|
"avatar_url" => nil
|
||||||
}}
|
}}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -136,15 +151,16 @@ describe Travis::API::V3::Services::Owner::Find do
|
||||||
before { get("/v3/owner/example-user") }
|
before { get("/v3/owner/example-user") }
|
||||||
example { expect(last_response).to be_ok }
|
example { expect(last_response).to be_ok }
|
||||||
example { expect(JSON.load(body)).to be == {
|
example { expect(JSON.load(body)).to be == {
|
||||||
"@type" => "user",
|
"@type" => "user",
|
||||||
"@href" => "/v3/user/#{user.id}",
|
"@href" => "/v3/user/#{user.id}",
|
||||||
"id" => user.id,
|
"@permissions" => {"read"=>true, "sync"=>false},
|
||||||
"login" => "example-user",
|
"id" => user.id,
|
||||||
"name" => nil,
|
"login" => "example-user",
|
||||||
"github_id" => nil,
|
"name" => nil,
|
||||||
"avatar_url" => nil,
|
"github_id" => nil,
|
||||||
"is_syncing" => nil,
|
"avatar_url" => nil,
|
||||||
"synced_at" => nil
|
"is_syncing" => nil,
|
||||||
|
"synced_at" => nil
|
||||||
}}
|
}}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -152,15 +168,16 @@ describe Travis::API::V3::Services::Owner::Find do
|
||||||
before { get("/v3/owner/example-USER") }
|
before { get("/v3/owner/example-USER") }
|
||||||
example { expect(last_response).to be_ok }
|
example { expect(last_response).to be_ok }
|
||||||
example { expect(JSON.load(body)).to be == {
|
example { expect(JSON.load(body)).to be == {
|
||||||
"@type" => "user",
|
"@type" => "user",
|
||||||
"@href" => "/v3/user/#{user.id}",
|
"@href" => "/v3/user/#{user.id}",
|
||||||
"id" => user.id,
|
"@permissions" => {"read"=>true, "sync"=>false},
|
||||||
"login" => "example-user",
|
"id" => user.id,
|
||||||
"name" => nil,
|
"login" => "example-user",
|
||||||
"github_id" => nil,
|
"name" => nil,
|
||||||
"avatar_url" => nil,
|
"github_id" => nil,
|
||||||
"is_syncing" => nil,
|
"avatar_url" => nil,
|
||||||
"synced_at" => nil
|
"is_syncing" => nil,
|
||||||
|
"synced_at" => nil
|
||||||
}}
|
}}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -172,15 +189,16 @@ describe Travis::API::V3::Services::Owner::Find do
|
||||||
before { get("/v3/owner/example-user?user.id=#{other.id}") }
|
before { get("/v3/owner/example-user?user.id=#{other.id}") }
|
||||||
example { expect(last_response).to be_ok }
|
example { expect(last_response).to be_ok }
|
||||||
example { expect(JSON.load(body)).to be == {
|
example { expect(JSON.load(body)).to be == {
|
||||||
"@type" => "user",
|
"@type" => "user",
|
||||||
"@href" => "/v3/user/#{user.id}",
|
"@href" => "/v3/user/#{user.id}",
|
||||||
"id" => user.id,
|
"@permissions" => {"read"=>true, "sync"=>false},
|
||||||
"login" => "example-user",
|
"id" => user.id,
|
||||||
"name" => nil,
|
"login" => "example-user",
|
||||||
"github_id" => nil,
|
"name" => nil,
|
||||||
"avatar_url" => nil,
|
"github_id" => nil,
|
||||||
"is_syncing" => nil,
|
"avatar_url" => nil,
|
||||||
"synced_at" => nil
|
"is_syncing" => nil,
|
||||||
|
"synced_at" => nil
|
||||||
}}
|
}}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -18,6 +18,11 @@ describe Travis::API::V3::Services::Owner::Repositories do
|
||||||
"repositories" => [{
|
"repositories" => [{
|
||||||
"@type" => "repository",
|
"@type" => "repository",
|
||||||
"@href" => "/v3/repo/#{repo.id}",
|
"@href" => "/v3/repo/#{repo.id}",
|
||||||
|
"@permissions" => {
|
||||||
|
"read" => true,
|
||||||
|
"enable" => false,
|
||||||
|
"disable" => false,
|
||||||
|
"create_request"=> false},
|
||||||
"id" => repo.id,
|
"id" => repo.id,
|
||||||
"name" => "minimal",
|
"name" => "minimal",
|
||||||
"slug" => "svenfuchs/minimal",
|
"slug" => "svenfuchs/minimal",
|
||||||
|
|
|
@ -3,11 +3,11 @@ require 'spec_helper'
|
||||||
describe Travis::API::V3::Services::Repositories::ForCurrentUser do
|
describe Travis::API::V3::Services::Repositories::ForCurrentUser do
|
||||||
let(:repo) { Repository.by_slug('svenfuchs/minimal').first }
|
let(:repo) { Repository.by_slug('svenfuchs/minimal').first }
|
||||||
|
|
||||||
let(:token) { Travis::Api::App::AccessToken.create(user: repo.owner, app_id: 1) }
|
let(:token) { Travis::Api::App::AccessToken.create(user: repo.owner, app_id: 1) }
|
||||||
let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }}
|
let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }}
|
||||||
before { Permission.create(repository: repo, user: repo.owner, pull: true) }
|
before { Permission.create(repository: repo, user: repo.owner, pull: true, push: true) }
|
||||||
before { repo.update_attribute(:private, true) }
|
before { repo.update_attribute(:private, true) }
|
||||||
after { repo.update_attribute(:private, false) }
|
after { repo.update_attribute(:private, false) }
|
||||||
|
|
||||||
describe "private repository, private API, authenticated as user with access" do
|
describe "private repository, private API, authenticated as user with access" do
|
||||||
before { get("/v3/repos", {}, headers) }
|
before { get("/v3/repos", {}, headers) }
|
||||||
|
@ -18,6 +18,11 @@ describe Travis::API::V3::Services::Repositories::ForCurrentUser do
|
||||||
"repositories" => [{
|
"repositories" => [{
|
||||||
"@type" => "repository",
|
"@type" => "repository",
|
||||||
"@href" => "/v3/repo/#{repo.id}",
|
"@href" => "/v3/repo/#{repo.id}",
|
||||||
|
"@permissions" => {
|
||||||
|
"read" => true,
|
||||||
|
"enable" => true,
|
||||||
|
"disable" => true,
|
||||||
|
"create_request"=> true},
|
||||||
"id" => repo.id,
|
"id" => repo.id,
|
||||||
"name" => "minimal",
|
"name" => "minimal",
|
||||||
"slug" => "svenfuchs/minimal",
|
"slug" => "svenfuchs/minimal",
|
||||||
|
|
|
@ -10,6 +10,11 @@ describe Travis::API::V3::Services::Repository::Find do
|
||||||
example { expect(parsed_body).to be == {
|
example { expect(parsed_body).to be == {
|
||||||
"@type" => "repository",
|
"@type" => "repository",
|
||||||
"@href" => "/v3/repo/#{repo.id}",
|
"@href" => "/v3/repo/#{repo.id}",
|
||||||
|
"@permissions" => {
|
||||||
|
"read" => true,
|
||||||
|
"enable" => false,
|
||||||
|
"disable" => false,
|
||||||
|
"create_request"=> false},
|
||||||
"id" => repo.id,
|
"id" => repo.id,
|
||||||
"name" => "minimal",
|
"name" => "minimal",
|
||||||
"slug" => "svenfuchs/minimal",
|
"slug" => "svenfuchs/minimal",
|
||||||
|
@ -95,6 +100,11 @@ describe Travis::API::V3::Services::Repository::Find do
|
||||||
example { expect(parsed_body).to be == {
|
example { expect(parsed_body).to be == {
|
||||||
"@type" => "repository",
|
"@type" => "repository",
|
||||||
"@href" => "/v3/repo/#{repo.id}",
|
"@href" => "/v3/repo/#{repo.id}",
|
||||||
|
"@permissions" => {
|
||||||
|
"read" => true,
|
||||||
|
"enable" => false,
|
||||||
|
"disable" => false,
|
||||||
|
"create_request"=> false},
|
||||||
"id" => repo.id,
|
"id" => repo.id,
|
||||||
"name" => "minimal",
|
"name" => "minimal",
|
||||||
"slug" => "svenfuchs/minimal",
|
"slug" => "svenfuchs/minimal",
|
||||||
|
@ -165,6 +175,11 @@ describe Travis::API::V3::Services::Repository::Find do
|
||||||
example { expect(parsed_body).to be == {
|
example { expect(parsed_body).to be == {
|
||||||
"@type" => "repository",
|
"@type" => "repository",
|
||||||
"@href" => "/v3/repo/#{repo.id}",
|
"@href" => "/v3/repo/#{repo.id}",
|
||||||
|
"@permissions" => {
|
||||||
|
"read" => true,
|
||||||
|
"enable" => true,
|
||||||
|
"disable" => true,
|
||||||
|
"create_request"=> true},
|
||||||
"id" => repo.id,
|
"id" => repo.id,
|
||||||
"name" => "minimal",
|
"name" => "minimal",
|
||||||
"slug" => "svenfuchs/minimal",
|
"slug" => "svenfuchs/minimal",
|
||||||
|
@ -241,6 +256,11 @@ describe Travis::API::V3::Services::Repository::Find do
|
||||||
example { expect(parsed_body).to be == {
|
example { expect(parsed_body).to be == {
|
||||||
"@type" => "repository",
|
"@type" => "repository",
|
||||||
"@href" => "/v3/repo/#{repo.id}",
|
"@href" => "/v3/repo/#{repo.id}",
|
||||||
|
"@permissions" => {
|
||||||
|
"read" => true,
|
||||||
|
"enable" => true,
|
||||||
|
"disable" => true,
|
||||||
|
"create_request"=> true},
|
||||||
"id" => repo.id,
|
"id" => repo.id,
|
||||||
"name" => "minimal",
|
"name" => "minimal",
|
||||||
"slug" => "svenfuchs/minimal",
|
"slug" => "svenfuchs/minimal",
|
||||||
|
|
|
@ -49,8 +49,10 @@ describe Travis::API::V3::Services::Requests::Create do
|
||||||
example { expect(last_response.status).to be == 403 }
|
example { expect(last_response.status).to be == 403 }
|
||||||
example { expect(JSON.load(body)).to be == {
|
example { expect(JSON.load(body)).to be == {
|
||||||
"@type" => "error",
|
"@type" => "error",
|
||||||
"error_type" => "push_access_required",
|
"error_type" => "insufficient_access",
|
||||||
"error_message" => "push access required",
|
"error_message" => "operation requires create_request access to repository",
|
||||||
|
"resource_type" => "repository",
|
||||||
|
"permission" => "create_request",
|
||||||
"repository" => {
|
"repository" => {
|
||||||
"@type" => "repository",
|
"@type" => "repository",
|
||||||
"@href" => "/repo/#{repo.id}",
|
"@href" => "/repo/#{repo.id}",
|
||||||
|
|
|
@ -10,15 +10,16 @@ describe Travis::API::V3::Services::User::Current do
|
||||||
before { get("/v3/user", {}, headers) }
|
before { get("/v3/user", {}, headers) }
|
||||||
example { expect(last_response).to be_ok }
|
example { expect(last_response).to be_ok }
|
||||||
example { expect(JSON.load(body)).to be == {
|
example { expect(JSON.load(body)).to be == {
|
||||||
"@type" => "user",
|
"@type" => "user",
|
||||||
"@href" => "/v3/user/#{user.id}",
|
"@href" => "/v3/user/#{user.id}",
|
||||||
"id" => user.id,
|
"@permissions" => {"read"=>true, "sync"=>true},
|
||||||
"login" => "svenfuchs",
|
"id" => user.id,
|
||||||
"name" =>"Sven Fuchs",
|
"login" => "svenfuchs",
|
||||||
"github_id" => user.github_id,
|
"name" =>"Sven Fuchs",
|
||||||
"avatar_url" => "https://0.gravatar.com/avatar/07fb84848e68b96b69022d333ca8a3e2",
|
"github_id" => user.github_id,
|
||||||
"is_syncing" => user.is_syncing,
|
"avatar_url" => "https://0.gravatar.com/avatar/07fb84848e68b96b69022d333ca8a3e2",
|
||||||
"synced_at" => user.synced_at
|
"is_syncing" => user.is_syncing,
|
||||||
|
"synced_at" => user.synced_at
|
||||||
}}
|
}}
|
||||||
end
|
end
|
||||||
end
|
end
|
|
@ -10,15 +10,16 @@ describe Travis::API::V3::Services::User::Find do
|
||||||
before { get("/v3/user/#{user.id}", {}, headers) }
|
before { get("/v3/user/#{user.id}", {}, headers) }
|
||||||
example { expect(last_response).to be_ok }
|
example { expect(last_response).to be_ok }
|
||||||
example { expect(JSON.load(body)).to be == {
|
example { expect(JSON.load(body)).to be == {
|
||||||
"@type" => "user",
|
"@type" => "user",
|
||||||
"@href" => "/v3/user/#{user.id}",
|
"@href" => "/v3/user/#{user.id}",
|
||||||
"id" => user.id,
|
"@permissions" => {"read"=>true, "sync"=>true},
|
||||||
"login" => "svenfuchs",
|
"id" => user.id,
|
||||||
"name" =>"Sven Fuchs",
|
"login" => "svenfuchs",
|
||||||
"github_id" => user.github_id,
|
"name" =>"Sven Fuchs",
|
||||||
"avatar_url" => "https://0.gravatar.com/avatar/07fb84848e68b96b69022d333ca8a3e2",
|
"github_id" => user.github_id,
|
||||||
"is_syncing" => user.is_syncing,
|
"avatar_url" => "https://0.gravatar.com/avatar/07fb84848e68b96b69022d333ca8a3e2",
|
||||||
"synced_at" => user.synced_at
|
"is_syncing" => user.is_syncing,
|
||||||
|
"synced_at" => user.synced_at
|
||||||
}}
|
}}
|
||||||
end
|
end
|
||||||
end
|
end
|
Loading…
Reference in New Issue
Block a user