From 28e3e52b3eb38b6e7a61b4cc5a926103705fd07d Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Fri, 21 Aug 2015 14:39:19 +0200 Subject: [PATCH 01/10] fix alignment --- lib/travis/api/v3/services.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/travis/api/v3/services.rb b/lib/travis/api/v3/services.rb index 4aabfb7c..85ecef01 100644 --- a/lib/travis/api/v3/services.rb +++ b/lib/travis/api/v3/services.rb @@ -5,7 +5,7 @@ module Travis::API::V3 Accounts = Module.new { extend Services } Branch = Module.new { extend Services } Build = Module.new { extend Services } - Builds = Module.new { extend Services } + Builds = Module.new { extend Services } Organization = Module.new { extend Services } Organizations = Module.new { extend Services } Owner = Module.new { extend Services } From b3f47d385695210e2bff276a300d3f55246f158c Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Fri, 21 Aug 2015 17:04:12 +0200 Subject: [PATCH 02/10] v3: add pagination --- lib/travis/api/v3/access_control/anonymous.rb | 4 + lib/travis/api/v3/paginator.rb | 42 ++++++++ lib/travis/api/v3/paginator/url_generator.rb | 95 +++++++++++++++++++ .../api/v3/renderer/collection_renderer.rb | 35 +++++-- lib/travis/api/v3/result.rb | 13 ++- lib/travis/api/v3/service.rb | 23 ++++- lib/travis/api/v3/services/builds/find.rb | 2 + 7 files changed, 199 insertions(+), 15 deletions(-) create mode 100644 lib/travis/api/v3/paginator.rb create mode 100644 lib/travis/api/v3/paginator/url_generator.rb diff --git a/lib/travis/api/v3/access_control/anonymous.rb b/lib/travis/api/v3/access_control/anonymous.rb index c41df37f..08300b33 100644 --- a/lib/travis/api/v3/access_control/anonymous.rb +++ b/lib/travis/api/v3/access_control/anonymous.rb @@ -2,6 +2,10 @@ require 'travis/api/v3/access_control/generic' module Travis::API::V3 class AccessControl::Anonymous < AccessControl::Generic + def self.new + @instace ||= super + end + # use when Authorization header is not set auth_type(nil) diff --git a/lib/travis/api/v3/paginator.rb b/lib/travis/api/v3/paginator.rb new file mode 100644 index 00000000..26503c2d --- /dev/null +++ b/lib/travis/api/v3/paginator.rb @@ -0,0 +1,42 @@ +module Travis::API::V3 + class Paginator + attr_accessor :default_limit, :max_limit + + def initialize(default_limit: 25, max_limit: 100) + @default_limit = default_limit + @max_limit = max_limit + end + + def paginate(result, limit: nil, offset: nil, access_control: AccessControl::Anonymous.new) + limit &&= Integer(limit, :limit) + limit ||= default_limit + limit = default_limit if limit < 0 + + unless access_control.full_access? + limit = max_limit if limit > max_limit or limit < 1 + end + + offset &&= Integer(offset, :offset) + offset = 0 if offset.nil? or offset < 0 + + count = result.resource ? result.resource.count : 0 + result.resource &&= result.resource.limit(limit) unless limit == 0 + result.resource &&= result.resource.offset(offset) unless offset == 0 + + pagination_info = { + limit: limit, + offset: offset, + count: count, + } + + result.meta_data[:pagination] = pagination_info + result + end + + def Integer(value, key) + super(value) + rescue ArgumentError + raise WrongParams, "#{key} must be an integer" + end + end +end diff --git a/lib/travis/api/v3/paginator/url_generator.rb b/lib/travis/api/v3/paginator/url_generator.rb new file mode 100644 index 00000000..da29c34e --- /dev/null +++ b/lib/travis/api/v3/paginator/url_generator.rb @@ -0,0 +1,95 @@ +require "addressable/uri" + +module Travis::API::V3 + class Paginator + class URLGenerator + class FancyParser + def initialize(href) + @uri = Addressable::URI.parse(href) + end + + def generate(offset, limit) + uri = @uri.dup + uri.query_values = uri.query_values.merge("offset".freeze => offset, "limit".freeze => limit) + uri.to_s + end + end + + class FastParser + PATTERN = /\?(?:&?(?:limit|offset)=[^=]*)*\Z/ + + def self.can_handle?(href) + return true unless href.include? ??.freeze + href =~ PATTERN + end + + def initialize(href) + @path_info = href.split(??.freeze, 2).first + end + + def generate(offset, limit) + "#{@path_info}?limit=#{limit}&offset=#{offset}" + end + end + + def initialize(href, limit: 0, offset: 0, count: 0, **) + @parser = FastParser.can_handle?(href) ? FastParser.new(href) : FancyParser.new(href) + @href = href + @limit = limit + @offset = offset + @count = count + end + + def last? + @count <= @offset + @limit + end + + def first? + @offset == 0 + end + + def next_info + info(offset: @offset + @limit) unless last? + end + + def previous_info + return if @offset == 0 + @offset <= @limit ? info(offset: 0, limit: @offset) : info(offset: @offset - @limit, limit: @limit) + end + + def first_info + info(offset: 0) + end + + def last_info + offset = @count / @limit * @limit + offset -= @limit if offset == @count + info(offset: offset) + end + + def info(offset: @offset, limit: @limit) + { + :@href => uri_with(offset, limit), + :offset => offset, + :limit => limit + } + end + + def to_h + { + is_first: first?, + is_last: last?, + next: next_info, + prev: previous_info, + first: first_info, + last: last_info + } + end + + def uri_with(offset, limit) + return @href if offset == @offset and limit == @limit + @parser.generate(offset, limit) + end + end + end +end diff --git a/lib/travis/api/v3/renderer/collection_renderer.rb b/lib/travis/api/v3/renderer/collection_renderer.rb index 1be17af6..461c7353 100644 --- a/lib/travis/api/v3/renderer/collection_renderer.rb +++ b/lib/travis/api/v3/renderer/collection_renderer.rb @@ -17,19 +17,34 @@ module Travis::API::V3 available_attributes << value end - def initialize(list, href: nil, included: [], **options) - @href = href - @options = options - @list = list - @included = included + attr_reader :href, :options, :list, :included, :meta_data + + def initialize(list, href: nil, included: [], meta_data: {}, **options) + @href = href + @options = options + @list = list + @included = included + @meta_data = meta_data + end + + def fields + fields = { :"@type" => type } + fields[:@href] = href if href + fields[:pagination] = pagination_info if meta_data.include? :pagination + fields + end + + def pagination_info + return meta_data[:@pagination] unless href + generator = V3::Paginator::URLGenerator.new(href, **meta_data[:pagination]) + meta_data[:pagination].merge generator.to_h end def render - result = { :"@type" => type } - result[:@href] = @href if @href - included = @included.dup - result[collection_key] = @list.map do |entry| - rendered = render_entry(entry, included: included, mode: :standard, **@options) + result = fields + included = self.included.dup + result[collection_key] = list.map do |entry| + rendered = render_entry(entry, included: included, mode: :standard, **options) included << entry rendered end diff --git a/lib/travis/api/v3/result.rb b/lib/travis/api/v3/result.rb index 1cf5733b..7f8d2b0d 100644 --- a/lib/travis/api/v3/result.rb +++ b/lib/travis/api/v3/result.rb @@ -1,9 +1,9 @@ module Travis::API::V3 class Result - attr_accessor :access_control, :type, :resource, :status, :href + attr_accessor :access_control, :type, :resource, :status, :href, :meta_data - def initialize(access_control, type, resource = [], status: 200) - @access_control, @type, @resource, @status = access_control, type, resource, status + def initialize(access_control, type, resource = [], status: 200, **meta_data) + @access_control, @type, @resource, @status, @meta_data = access_control, type, resource, status, meta_data end def respond_to_missing?(method, *) @@ -19,7 +19,12 @@ module Travis::API::V3 href = self.href href = V3.location(env) if href.nil? and env['REQUEST_METHOD'.freeze] == 'GET'.freeze include = params['include'.freeze].to_s.split(?,.freeze) - Renderer[type].render(resource, href: href, script_name: env['SCRIPT_NAME'.freeze], include: include, access_control: access_control) + Renderer[type].render(resource, + href: href, + script_name: env['SCRIPT_NAME'.freeze], + include: include, + access_control: access_control, + meta_data: meta_data) end def method_missing(method, *args) diff --git a/lib/travis/api/v3/service.rb b/lib/travis/api/v3/service.rb index c8c90249..2a0011e0 100644 --- a/lib/travis/api/v3/service.rb +++ b/lib/travis/api/v3/service.rb @@ -24,6 +24,19 @@ module Travis::API::V3 @params end + def self.paginate(**options) + params("limit".freeze, "offset".freeze) + @paginator = Paginator.new(**options) + end + + def self.paginator + @paginator ||= nil + end + + def self.paginate? + !!@paginator if defined? @paginator + end + attr_accessor :access_control, :params def initialize(access_control, params) @@ -68,7 +81,15 @@ module Travis::API::V3 def run not_found unless result = run! result = result(result_type, result) unless result.is_a? Result - result + self.class.paginate? ? paginate(result) : result + end + + def paginate(result) + p params + self.class.paginator.paginate(result, + limit: params['limit'.freeze], + offset: params['offset'.freeze], + access_control: access_control) end def params_for?(prefix) diff --git a/lib/travis/api/v3/services/builds/find.rb b/lib/travis/api/v3/services/builds/find.rb index 48354927..9c2a69f9 100644 --- a/lib/travis/api/v3/services/builds/find.rb +++ b/lib/travis/api/v3/services/builds/find.rb @@ -1,5 +1,7 @@ module Travis::API::V3 class Services::Builds::Find < Service + paginate + def run! query.find(find(:repository)) end From 34bff32c3dae0eaa1701558eb925bb3cf519fb0e Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Fri, 21 Aug 2015 17:27:42 +0200 Subject: [PATCH 03/10] v3: pagination => @pagination --- lib/travis/api/v3/renderer/collection_renderer.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/travis/api/v3/renderer/collection_renderer.rb b/lib/travis/api/v3/renderer/collection_renderer.rb index 461c7353..cd415343 100644 --- a/lib/travis/api/v3/renderer/collection_renderer.rb +++ b/lib/travis/api/v3/renderer/collection_renderer.rb @@ -28,14 +28,14 @@ module Travis::API::V3 end def fields - fields = { :"@type" => type } - fields[:@href] = href if href - fields[:pagination] = pagination_info if meta_data.include? :pagination + fields = { :"@type" => type } + fields[:@href] = href if href + fields[:@pagination] = pagination_info if meta_data.include? :pagination fields end def pagination_info - return meta_data[:@pagination] unless href + return meta_data[:pagination] unless href generator = V3::Paginator::URLGenerator.new(href, **meta_data[:pagination]) meta_data[:pagination].merge generator.to_h end From cbc5329b3d1439f61b5fd561b70a3edfcc8094d5 Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Fri, 21 Aug 2015 18:26:21 +0200 Subject: [PATCH 04/10] v3: avoid N+1 query in builds endpoint --- lib/travis/api/v3/queries/builds.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/travis/api/v3/queries/builds.rb b/lib/travis/api/v3/queries/builds.rb index 0877bac5..319ee9bd 100644 --- a/lib/travis/api/v3/queries/builds.rb +++ b/lib/travis/api/v3/queries/builds.rb @@ -1,7 +1,12 @@ module Travis::API::V3 class Queries::Builds < Query def find(repository) - repository.builds + filter(repository.builds) + end + + def filter(list) + # filtering by branch, type, etc would go here + list.includes(:commit).includes(branch: :last_build) end end end From cc346ce16524dd4752269463cb2415c5bcc4ab02 Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Fri, 21 Aug 2015 18:33:27 +0200 Subject: [PATCH 05/10] v3: more eager-loading --- lib/travis/api/v3/queries/builds.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/travis/api/v3/queries/builds.rb b/lib/travis/api/v3/queries/builds.rb index 319ee9bd..4a533ce1 100644 --- a/lib/travis/api/v3/queries/builds.rb +++ b/lib/travis/api/v3/queries/builds.rb @@ -6,7 +6,9 @@ module Travis::API::V3 def filter(list) # filtering by branch, type, etc would go here - list.includes(:commit).includes(branch: :last_build) + list = list.includes(:commit).includes(branch: :last_build).includes(:repository) + list = list.includes(branch: { last_build: :commit }) if includes? 'build.commit'.freeze + list end end end From 73ec1d496e53efff5d1d0dfcc2ddcbc2b9ae695d Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Fri, 21 Aug 2015 18:46:42 +0200 Subject: [PATCH 06/10] v3: allow filtering builds by event_type, state and previous_state --- lib/travis/api/v3/queries/builds.rb | 7 ++++++- lib/travis/api/v3/query.rb | 4 ++++ lib/travis/api/v3/services/builds/find.rb | 1 + 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/lib/travis/api/v3/queries/builds.rb b/lib/travis/api/v3/queries/builds.rb index 4a533ce1..286fa347 100644 --- a/lib/travis/api/v3/queries/builds.rb +++ b/lib/travis/api/v3/queries/builds.rb @@ -1,11 +1,16 @@ module Travis::API::V3 class Queries::Builds < Query + params :state, :event_type, :previous_state, prefix: :build + def find(repository) filter(repository.builds) end def filter(list) - # filtering by branch, type, etc would go here + list = list.where(state: list(state)) if state + list = list.where(previous_state: list(previous_state)) if previous_state + list = list.where(event_type: list(state)) if event_type + list = list.includes(:commit).includes(branch: :last_build).includes(:repository) list = list.includes(branch: { last_build: :commit }) if includes? 'build.commit'.freeze list diff --git a/lib/travis/api/v3/query.rb b/lib/travis/api/v3/query.rb index 5c89da27..ae8d1efc 100644 --- a/lib/travis/api/v3/query.rb +++ b/lib/travis/api/v3/query.rb @@ -51,6 +51,10 @@ module Travis::API::V3 !!value end + def list(value) + value.split(?,.freeze) + end + def user_condition(value) case value when String then { login: value } diff --git a/lib/travis/api/v3/services/builds/find.rb b/lib/travis/api/v3/services/builds/find.rb index 9c2a69f9..720fe8a1 100644 --- a/lib/travis/api/v3/services/builds/find.rb +++ b/lib/travis/api/v3/services/builds/find.rb @@ -1,5 +1,6 @@ module Travis::API::V3 class Services::Builds::Find < Service + params :state, :event_type, :previous_state, prefix: :build paginate def run! From 4eb89ab141bf13438b02ea022d1d718bab0b4714 Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Fri, 21 Aug 2015 18:56:51 +0200 Subject: [PATCH 07/10] =?UTF-8?q?v3:=20allow=20filtering=20by=20/repo/?= =?UTF-8?q?=E2=80=A6/builds=3Fstate=3D=E2=80=A6=20as=20a=20shorthand=20for?= =?UTF-8?q?=20/repo/=E2=80=A6/builds=3Fbuild.state=3D=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/travis/api/v3/query.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/travis/api/v3/query.rb b/lib/travis/api/v3/query.rb index ae8d1efc..b94d865d 100644 --- a/lib/travis/api/v3/query.rb +++ b/lib/travis/api/v3/query.rb @@ -11,6 +11,7 @@ module Travis::API::V3 return @%s = @params['%s.%s'.freeze] if @params.include? '%s.%s'.freeze return @%s = @params['%s'.freeze]['%s'.freeze] if @params.include? '%s'.freeze and @params['%s'.freeze].is_a? Hash return @%s = @params['%s'.freeze] if (@params['@type'.freeze] || @main_type) == '%s'.freeze + return @%s = @params['%s'.freeze] if %p and (@params['@type'.freeze] || @main_type) == '%s'.freeze @%s = nil end @@ -20,8 +21,9 @@ module Travis::API::V3 RUBY def self.params(*list, prefix: nil) - prefix ||= name[/[^:]+$/].underscore - list.each { |e| class_eval(@@params_accessor % { name: e, prefix: prefix }) } + type = name[/[^:]+$/].underscore + prefix ||= type.to_s + list.each { |e| class_eval(@@params_accessor % { name: e, prefix: prefix, type: type, check_type: type != prefix }) } end attr_reader :params, :main_type From 462b2aed0da78aca530474b436129a1980d1407f Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Fri, 21 Aug 2015 19:11:27 +0200 Subject: [PATCH 08/10] v3: allow filtering builds by branch --- lib/travis/api/v3/queries/builds.rb | 4 ++- lib/travis/api/v3/query.rb | 37 ++++++++++++++--------- lib/travis/api/v3/services/builds/find.rb | 1 + 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/lib/travis/api/v3/queries/builds.rb b/lib/travis/api/v3/queries/builds.rb index 286fa347..f45d3daf 100644 --- a/lib/travis/api/v3/queries/builds.rb +++ b/lib/travis/api/v3/queries/builds.rb @@ -1,6 +1,7 @@ module Travis::API::V3 class Queries::Builds < Query params :state, :event_type, :previous_state, prefix: :build + params :name, prefix: :branch, method_name: :branch_name def find(repository) filter(repository.builds) @@ -9,7 +10,8 @@ module Travis::API::V3 def filter(list) list = list.where(state: list(state)) if state list = list.where(previous_state: list(previous_state)) if previous_state - list = list.where(event_type: list(state)) if event_type + list = list.where(event_type: list(event_type)) if event_type + list = list.where(branch: list(branch_name)) if branch_name list = list.includes(:commit).includes(branch: :last_build).includes(:repository) list = list.includes(branch: { last_build: :commit }) if includes? 'build.commit'.freeze diff --git a/lib/travis/api/v3/query.rb b/lib/travis/api/v3/query.rb index b94d865d..84a31da9 100644 --- a/lib/travis/api/v3/query.rb +++ b/lib/travis/api/v3/query.rb @@ -4,26 +4,35 @@ module Travis::API::V3 # generate from eval to avoid additional string allocations on every params access @@params_accessor = <<-RUBY - attr_writer :%s + attr_writer :%s - def %s - return @%s if defined? @%s - return @%s = @params['%s.%s'.freeze] if @params.include? '%s.%s'.freeze - return @%s = @params['%s'.freeze]['%s'.freeze] if @params.include? '%s'.freeze and @params['%s'.freeze].is_a? Hash - return @%s = @params['%s'.freeze] if (@params['@type'.freeze] || @main_type) == '%s'.freeze - return @%s = @params['%s'.freeze] if %p and (@params['@type'.freeze] || @main_type) == '%s'.freeze - @%s = nil + def %s + return @%s if defined? @%s + return @%s = @params['%s.%s'.freeze] if @params.include? '%s.%s'.freeze + return @%s = @params['%s'.freeze]['%s'.freeze] if @params.include? '%s'.freeze and @params['%s'.freeze].is_a? Hash + return @%s = @params['%s'.freeze] if (@params['@type'.freeze] || @main_type) == '%s'.freeze + return @%s = @params['%s'.freeze] if %p and (@params['@type'.freeze] || @main_type) == '%s'.freeze + @%s = nil end - def %s! - %s or raise WrongParams, 'missing %s.%s'.freeze + def %s! + %s or raise WrongParams, 'missing %s.%s'.freeze end RUBY - def self.params(*list, prefix: nil) - type = name[/[^:]+$/].underscore - prefix ||= type.to_s - list.each { |e| class_eval(@@params_accessor % { name: e, prefix: prefix, type: type, check_type: type != prefix }) } + def self.params(*list, prefix: nil, method_name: nil) + type = name[/[^:]+$/].underscore + prefix ||= type.to_s + check_type = method_name.nil? and type != prefix + list.each do |entry| + class_eval(@@params_accessor % { + name: entry, + prefix: prefix, + type: type, + method_name: method_name || entry, + check_type: check_type + }) + end end attr_reader :params, :main_type diff --git a/lib/travis/api/v3/services/builds/find.rb b/lib/travis/api/v3/services/builds/find.rb index 720fe8a1..77d928e1 100644 --- a/lib/travis/api/v3/services/builds/find.rb +++ b/lib/travis/api/v3/services/builds/find.rb @@ -1,6 +1,7 @@ module Travis::API::V3 class Services::Builds::Find < Service params :state, :event_type, :previous_state, prefix: :build + params "branch.name" paginate def run! From b4a3bdeb0e52be58bec42546a0de50a4447ff0b9 Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Fri, 21 Aug 2015 19:22:59 +0200 Subject: [PATCH 09/10] allow skipping simplecov --- spec/support/coverage.rb | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/spec/support/coverage.rb b/spec/support/coverage.rb index f5b93400..ab12f3fa 100644 --- a/spec/support/coverage.rb +++ b/spec/support/coverage.rb @@ -1,7 +1,9 @@ -require 'simplecov' +unless ENV['SKIP_COVERAGE'] + require 'simplecov' -SimpleCov.start do - coverage_dir '.coverage' - add_filter "/spec/" - add_group "v3", "lib/travis/api/v3" + SimpleCov.start do + coverage_dir '.coverage' + add_filter "/spec/" + add_group "v3", "lib/travis/api/v3" + end end From 09df0612689edadbf5855b45b58c41870747cad3 Mon Sep 17 00:00:00 2001 From: Konstantin Haase Date: Fri, 21 Aug 2015 19:50:37 +0200 Subject: [PATCH 10/10] v3: add @warnings --- lib/travis/api/v3.rb | 1 - lib/travis/api/v3/result.rb | 22 ++++++++++++++++++++-- lib/travis/api/v3/router.rb | 5 ++++- spec/v3/services/owner/find_spec.rb | 28 +++++++++++++++++++--------- 4 files changed, 43 insertions(+), 13 deletions(-) diff --git a/lib/travis/api/v3.rb b/lib/travis/api/v3.rb index 8e0d3909..221df59b 100644 --- a/lib/travis/api/v3.rb +++ b/lib/travis/api/v3.rb @@ -37,4 +37,3 @@ module Travis end end end - diff --git a/lib/travis/api/v3/result.rb b/lib/travis/api/v3/result.rb index 7f8d2b0d..c6875af1 100644 --- a/lib/travis/api/v3/result.rb +++ b/lib/travis/api/v3/result.rb @@ -1,8 +1,9 @@ module Travis::API::V3 class Result - attr_accessor :access_control, :type, :resource, :status, :href, :meta_data + attr_accessor :access_control, :type, :resource, :status, :href, :meta_data, :warnings def initialize(access_control, type, resource = [], status: 200, **meta_data) + @warnings = [] @access_control, @type, @resource, @status, @meta_data = access_control, type, resource, status, meta_data end @@ -10,6 +11,15 @@ module Travis::API::V3 super or method.to_sym == type.to_sym end + def warn(message, **info) + warnings << { :@type => 'warning'.freeze, :message => message, **info } + end + + def ignored_param(param, reason: nil, **info) + message = reason ? "query parameter #{param} #{reason}, ignored" : "query parameter #{param} ignored" + warn(message, warning_type: :ignored_parameter, parameter: param, **info) + end + def <<(value) resource << value self @@ -19,7 +29,7 @@ module Travis::API::V3 href = self.href href = V3.location(env) if href.nil? and env['REQUEST_METHOD'.freeze] == 'GET'.freeze include = params['include'.freeze].to_s.split(?,.freeze) - Renderer[type].render(resource, + add_info Renderer[type].render(resource, href: href, script_name: env['SCRIPT_NAME'.freeze], include: include, @@ -27,6 +37,14 @@ module Travis::API::V3 meta_data: meta_data) end + def add_info(payload) + if warnings.any? + payload = { :@warnings => [] }.merge!(payload) unless payload.include? :@warnings + payload[:@warnings].concat(warnings) + end + payload + end + def method_missing(method, *args) return super unless method.to_sym == type.to_sym raise ArgumentError, 'wrong number of arguments (1 for 0)'.freeze if args.any? diff --git a/lib/travis/api/v3/router.rb b/lib/travis/api/v3/router.rb index 1c89ffd4..8e39fc15 100644 --- a/lib/travis/api/v3/router.rb +++ b/lib/travis/api/v3/router.rb @@ -16,8 +16,11 @@ module Travis::API::V3 raise NotFound unless factory - service = factory.new(access_control, factory.filter_params(env_params).merge(params)) + filtered = factory.filter_params(env_params) + service = factory.new(access_control, filtered.merge(params)) result = service.run + + env_params.each_key { |key| result.ignored_param(key, reason: "not whitelisted".freeze) unless filtered.include?(key) } render(result, env_params, env) rescue Error => error result = Result.new(access_control, :error, error) diff --git a/spec/v3/services/owner/find_spec.rb b/spec/v3/services/owner/find_spec.rb index 66d3feca..fd8fc6fa 100644 --- a/spec/v3/services/owner/find_spec.rb +++ b/spec/v3/services/owner/find_spec.rb @@ -130,14 +130,19 @@ describe Travis::API::V3::Services::Owner::Find do before { get("/v3/owner/example-org?organization.id=#{other.id}") } example { expect(last_response).to be_ok } example { expect(JSON.load(body)).to be == { - "@type" => "organization", - "@href" => "/v3/org/#{org.id}", - "@permissions" => { "read"=>true, "sync"=>false }, - "id" => org.id, - "login" => "example-org", - "name" => nil, - "github_id" => nil, - "avatar_url" => nil + "@type" => "organization", + "@href" => "/v3/org/#{org.id}", + "@permissions" => { "read"=>true, "sync"=>false }, + "id" => org.id, + "login" => "example-org", + "name" => nil, + "github_id" => nil, + "avatar_url" => nil, + "@warnings" => [{ + "@type" => "warning", + "message" => "query parameter organization.id not whitelisted, ignored", + "warning_type" => "ignored_parameter", + "parameter" => "organization.id"}] }} end end @@ -198,7 +203,12 @@ describe Travis::API::V3::Services::Owner::Find do "github_id" => nil, "avatar_url" => nil, "is_syncing" => nil, - "synced_at" => nil + "synced_at" => nil, + "@warnings" => [{ + "@type" => "warning", + "message" => "query parameter user.id not whitelisted, ignored", + "warning_type" => "ignored_parameter", + "parameter" => "user.id"}] }} end end