pact_broker 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. checksums.yaml +5 -13
  2. data/.gitignore +0 -1
  3. data/.rspec +1 -0
  4. data/CHANGELOG.md +47 -0
  5. data/README.md +4 -2
  6. data/config.ru +3 -5
  7. data/db/migrations/09_add_timestamps.rb +12 -0
  8. data/db/migrations/10_populate_timestamps.rb +15 -0
  9. data/db/migrations/11_made_timestamps_mandatory.rb +20 -0
  10. data/db/migrations/12_create_webhooks_table.rb +21 -0
  11. data/db/migrations/13_add_columns_to_webhooks.rb +8 -0
  12. data/lib/pact_broker/api.rb +14 -0
  13. data/lib/pact_broker/api/decorators.rb +2 -2
  14. data/lib/pact_broker/api/decorators/base_decorator.rb +2 -1
  15. data/lib/pact_broker/api/decorators/basic_pacticipant_decorator.rb +21 -0
  16. data/lib/pact_broker/api/decorators/decorator_context.rb +20 -0
  17. data/lib/pact_broker/api/decorators/latest_pact_decorator.rb +2 -2
  18. data/lib/pact_broker/api/decorators/pact_decorator.rb +12 -5
  19. data/lib/pact_broker/api/decorators/pact_details_decorator.rb +22 -0
  20. data/lib/pact_broker/api/decorators/pacticipant_decorator.rb +6 -4
  21. data/lib/pact_broker/api/decorators/relationships_csv_decorator.rb +25 -3
  22. data/lib/pact_broker/api/decorators/representable_pact.rb +3 -1
  23. data/lib/pact_broker/api/decorators/tag_decorator.rb +3 -0
  24. data/lib/pact_broker/api/decorators/webhook_decorator.rb +52 -0
  25. data/lib/pact_broker/api/decorators/webhook_execution_result_decorator.rb +58 -0
  26. data/lib/pact_broker/api/decorators/webhook_request_decorator.rb +18 -0
  27. data/lib/pact_broker/api/decorators/webhooks_decorator.rb +37 -0
  28. data/lib/pact_broker/api/pact_broker_urls.rb +16 -0
  29. data/lib/pact_broker/api/renderers/html_pact_renderer.rb +2 -1
  30. data/lib/pact_broker/api/resources/base_resource.rb +12 -1
  31. data/lib/pact_broker/api/resources/group.rb +38 -0
  32. data/lib/pact_broker/api/resources/index.rb +30 -21
  33. data/lib/pact_broker/api/resources/latest_pact.rb +1 -1
  34. data/lib/pact_broker/api/resources/latest_pacts.rb +1 -1
  35. data/lib/pact_broker/api/resources/pact.rb +18 -2
  36. data/lib/pact_broker/api/resources/pact_webhooks.rb +87 -0
  37. data/lib/pact_broker/api/resources/pacticipant.rb +15 -6
  38. data/lib/pact_broker/api/resources/pacticipants.rb +1 -1
  39. data/lib/pact_broker/api/resources/tag.rb +2 -2
  40. data/lib/pact_broker/api/resources/webhook.rb +44 -0
  41. data/lib/pact_broker/api/resources/webhook_execution.rb +43 -0
  42. data/lib/pact_broker/api/resources/webhooks.rb +29 -0
  43. data/lib/pact_broker/app.rb +46 -8
  44. data/lib/pact_broker/db.rb +10 -0
  45. data/lib/pact_broker/doc/controllers/app.rb +32 -0
  46. data/lib/pact_broker/doc/views/latest-pacts.markdown +3 -0
  47. data/lib/pact_broker/doc/views/layouts/main.haml +5 -0
  48. data/lib/pact_broker/doc/views/pacticipants.markdown +10 -0
  49. data/lib/pact_broker/doc/views/self.markdown +8 -0
  50. data/lib/pact_broker/doc/views/webhooks.markdown +48 -0
  51. data/lib/pact_broker/functions/groupify.rb +39 -0
  52. data/lib/pact_broker/jobs/after_pact_save.rb +13 -0
  53. data/lib/pact_broker/json.rb +4 -0
  54. data/lib/pact_broker/locale/en.yml +23 -0
  55. data/lib/pact_broker/messages.rb +18 -0
  56. data/lib/pact_broker/models/group.rb +21 -0
  57. data/lib/pact_broker/models/pact.rb +4 -2
  58. data/lib/pact_broker/models/pacticipant.rb +3 -1
  59. data/lib/pact_broker/models/relationship.rb +34 -0
  60. data/lib/pact_broker/models/tag.rb +3 -1
  61. data/lib/pact_broker/models/version.rb +3 -1
  62. data/lib/pact_broker/models/webhook.rb +53 -0
  63. data/lib/pact_broker/models/webhook_execution_result.rb +26 -0
  64. data/lib/pact_broker/models/webhook_request.rb +107 -0
  65. data/lib/pact_broker/models/webhook_request_header.rb +13 -0
  66. data/lib/pact_broker/repositories.rb +6 -0
  67. data/lib/pact_broker/repositories/pact_repository.rb +25 -7
  68. data/lib/pact_broker/repositories/pacticipant_repository.rb +4 -0
  69. data/lib/pact_broker/repositories/webhook_repository.rb +134 -0
  70. data/lib/pact_broker/services.rb +10 -0
  71. data/lib/pact_broker/services/group_service.rb +24 -0
  72. data/lib/pact_broker/services/pact_service.rb +37 -7
  73. data/lib/pact_broker/services/pacticipant_service.rb +12 -1
  74. data/lib/pact_broker/services/webhook_service.rb +63 -0
  75. data/lib/pact_broker/tasks.rb +0 -1
  76. data/lib/pact_broker/ui/controllers/base_controller.rb +1 -0
  77. data/lib/pact_broker/ui/controllers/groups.rb +25 -0
  78. data/lib/pact_broker/ui/controllers/relationships.rb +0 -2
  79. data/lib/pact_broker/ui/helpers/url_helper.rb +17 -0
  80. data/lib/pact_broker/ui/view_models/relationship.rb +13 -4
  81. data/lib/pact_broker/ui/view_models/relationships.rb +1 -1
  82. data/lib/pact_broker/ui/views/groups/show.html.erb +409 -0
  83. data/lib/pact_broker/ui/views/relationships/show.haml +4 -2
  84. data/lib/pact_broker/version.rb +1 -1
  85. data/pact_broker.gemspec +7 -6
  86. data/public/{d3.v3.js.pagespeed.ce.dFNRrGTALe.js → javascripts/d3.v3.js.pagespeed.ce.dFNRrGTALe.js} +0 -0
  87. data/public/stylesheets/relationships.css +4 -0
  88. data/spec/integration/endpoints/group.rb +22 -0
  89. data/spec/lib/pact_broker/api/decorators/pact_decorator_spec.rb +49 -0
  90. data/spec/lib/pact_broker/api/decorators/pacticipant_decorator_spec.rb +25 -0
  91. data/spec/lib/pact_broker/api/decorators/relationships_csv_decorator_spec.rb +7 -4
  92. data/spec/lib/pact_broker/api/decorators/webhook_decorator_spec.rb +121 -0
  93. data/spec/lib/pact_broker/api/decorators/webhook_execution_result_decorator_spec.rb +69 -0
  94. data/spec/lib/pact_broker/api/decorators/webhook_request_decorator_spec.rb +78 -0
  95. data/spec/lib/pact_broker/api/decorators/webhooks_decorator_spec.rb +46 -0
  96. data/spec/lib/pact_broker/api/resources/group_spec.rb +80 -0
  97. data/spec/lib/pact_broker/api/resources/pact_spec.rb +41 -0
  98. data/spec/lib/pact_broker/api/resources/pact_webhooks_spec.rb +184 -0
  99. data/spec/lib/pact_broker/api/resources/pacticipant_spec.rb +71 -0
  100. data/spec/lib/pact_broker/api/resources/webhook_execution_spec.rb +77 -0
  101. data/spec/lib/pact_broker/api/resources/webhook_spec.rb +60 -0
  102. data/spec/lib/pact_broker/api/resources/webhooks_spec.rb +44 -0
  103. data/spec/lib/pact_broker/doc/controllers/app_spec.rb +51 -0
  104. data/spec/lib/pact_broker/functions/groupify_spec.rb +50 -0
  105. data/spec/lib/pact_broker/models/group_spec.rb +26 -0
  106. data/spec/lib/pact_broker/models/webhook_request_spec.rb +175 -0
  107. data/spec/lib/pact_broker/models/webhook_spec.rb +59 -0
  108. data/spec/lib/pact_broker/repositories/pact_repository_spec.rb +40 -0
  109. data/spec/lib/pact_broker/repositories/webhook_repository_spec.rb +257 -0
  110. data/spec/lib/pact_broker/services/group_service_spec.rb +52 -0
  111. data/spec/lib/pact_broker/services/pact_service_spec.rb +49 -0
  112. data/spec/lib/pact_broker/services/pacticipant_service_spec.rb +50 -0
  113. data/spec/lib/pact_broker/services/webhook_service_spec.rb +51 -0
  114. data/spec/lib/pact_broker/ui/view_models/relationship_spec.rb +20 -6
  115. data/spec/lib/pact_broker/ui/view_models/relationships_spec.rb +33 -0
  116. data/spec/service_consumers/provider_states_for_pact_broker_client.rb +1 -1
  117. data/spec/spec_helper.rb +11 -4
  118. data/spec/support/provider_state_builder.rb +11 -0
  119. data/spec/support/shared_examples_for_responses.rb +25 -0
  120. data/vendor/hal-browser/js/hal/views/embedded_resource.js +3 -3
  121. data/vendor/hal-browser/js/hal/views/resource.js +3 -3
  122. metadata +174 -80
  123. data/assets/d3.v3.js +0 -9263
  124. data/assets/force.csv +0 -29
  125. data/assets/index.html +0 -186
  126. data/assets/index2.html +0 -224
  127. data/assets/relationships +0 -4
  128. data/assets/stylesheets/github.css +0 -387
  129. data/lib/pact_broker/tasks/delete.rake +0 -20
  130. data/public/Network Graph REA.html +0 -48
  131. data/public/rea.csv +0 -10
@@ -5,12 +5,14 @@ module PactBroker
5
5
  module Decorators
6
6
  class RepresentablePact
7
7
 
8
- attr_reader :consumer, :provider, :consumer_version
8
+ attr_reader :consumer, :provider, :consumer_version, :created_at, :updated_at
9
9
 
10
10
  def initialize pact
11
11
  @consumer_version = pact.consumer_version
12
12
  @consumer = OpenStruct.new(:version => @consumer_version, :name => pact.consumer.name)
13
13
  @provider = OpenStruct.new(:version => nil, :name => pact.provider.name)
14
+ @created_at = pact.created_at
15
+ @updated_at = pact.updated_at
14
16
  end
15
17
 
16
18
  end
@@ -9,6 +9,9 @@ module PactBroker
9
9
 
10
10
  class TagDecorator < BaseDecorator
11
11
 
12
+ property :createdAt, getter: lambda { |_| created_at ? created_at.xmlschema : nil }
13
+ property :updatedAt, getter: lambda { |_| updated_at ? updated_at.xmlschema : nil }
14
+
12
15
  link :self do | options |
13
16
  tag_url(options[:base_url], represented)
14
17
  end
@@ -0,0 +1,52 @@
1
+ require_relative 'base_decorator'
2
+ require 'pact_broker/api/decorators/webhook_request_decorator'
3
+ require 'pact_broker/models/webhook_request'
4
+ require 'pact_broker/api/decorators/basic_pacticipant_decorator'
5
+
6
+ module PactBroker
7
+ module Api
8
+ module Decorators
9
+ class WebhookDecorator < BaseDecorator
10
+
11
+ property :request, :class => PactBroker::Models::WebhookRequest, :extend => WebhookRequestDecorator
12
+
13
+ property :createdAt, getter: lambda { |_| created_at.xmlschema }, writeable: false
14
+ property :updatedAt, getter: lambda { |_| updated_at.xmlschema }, writeable: false
15
+
16
+ property :consumer, :extend => PactBroker::Api::Decorators::BasicPacticipantRepresenter, :embedded => true, writeable: false
17
+ property :provider, :extend => PactBroker::Api::Decorators::BasicPacticipantRepresenter, :embedded => true, writeable: false
18
+
19
+ link :self do | options |
20
+ {
21
+ title: represented.description,
22
+ href: webhook_url(represented, options[:base_url])
23
+ }
24
+
25
+ end
26
+
27
+ link :'pact-webhooks' do | options |
28
+ {
29
+ title: "All webhooks for the pact between #{represented.consumer.name} and #{represented.provider.name}",
30
+ href: webhooks_for_pact_url(represented.consumer, represented.provider, options[:base_url])
31
+ }
32
+ end
33
+
34
+ link :'webhooks' do | options |
35
+ {
36
+ title: "All webhooks",
37
+ href: webhooks_url(options[:base_url])
38
+ }
39
+ end
40
+
41
+ link :execute do | options |
42
+ {
43
+ title: "Test the execution of the webhook by sending a POST request to this URL",
44
+ href: webhook_execution_url(represented, options[:base_url])
45
+ }
46
+
47
+ end
48
+
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,58 @@
1
+ require_relative 'base_decorator'
2
+ require 'json'
3
+
4
+ module PactBroker
5
+ module Api
6
+ module Decorators
7
+
8
+ class WebhookExecutionResultDecorator < BaseDecorator
9
+
10
+ class ErrorDecorator < BaseDecorator
11
+
12
+ property :message
13
+ property :backtrace
14
+
15
+ end
16
+
17
+ class HTTPResponseDecorator < BaseDecorator
18
+
19
+ property :status, :getter => lambda { |_| code.to_i }
20
+ property :headers, exec_context: :decorator
21
+ property :body, exec_context: :decorator
22
+
23
+ def headers
24
+ headers_hash = represented.to_hash
25
+ headers_hash.keys.each_with_object({}) do | name, new_headers_hash|
26
+ new_headers_hash[name] = headers_hash[name].join(", ")
27
+ end
28
+ end
29
+
30
+ def body
31
+ begin
32
+ ::JSON.parse(represented.body)
33
+ rescue StandardError => e
34
+ represented.body
35
+ end
36
+ end
37
+
38
+ end
39
+
40
+ property :error, :extend => ErrorDecorator
41
+ property :response, :extend => HTTPResponseDecorator
42
+
43
+ link :webhook do | options |
44
+ {
45
+ href: webhook_url(options.fetch(:webhook), options.fetch(:base_url))
46
+ }
47
+ end
48
+
49
+ link :'try-again' do | options |
50
+ {
51
+ title: 'Execute the webhook again',
52
+ href: webhook_execution_url(options.fetch(:webhook), options.fetch(:base_url))
53
+ }
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,18 @@
1
+ require_relative 'base_decorator'
2
+
3
+ module PactBroker
4
+ module Api
5
+ module Decorators
6
+ class WebhookRequestDecorator < BaseDecorator
7
+
8
+ property :method
9
+ property :url
10
+ property :headers, getter: lambda { | _ | headers.empty? ? nil : headers }
11
+ property :body
12
+ property :username
13
+ property :password, getter: lambda { | _ | display_password }
14
+
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,37 @@
1
+ require_relative 'base_decorator'
2
+ require 'pact_broker/api/decorators/webhook_decorator'
3
+
4
+ module PactBroker
5
+ module Api
6
+ module Decorators
7
+ class WebhooksDecorator < BaseDecorator
8
+
9
+
10
+ link :'pb:self' do | context |
11
+ {
12
+ title: context.resource_title,
13
+ href: context.resource_url
14
+ }
15
+ end
16
+
17
+ links :webhooks do | context |
18
+ represented.entries.collect do | webhook |
19
+ {
20
+ title: webhook.description,
21
+ name: webhook.request_description,
22
+ href: webhook_url(webhook, context.base_url)
23
+ }
24
+ end
25
+ end
26
+
27
+ curies do | context |
28
+ [{
29
+ name: :pb,
30
+ href: context.base_url + '/doc/webhooks',
31
+ }]
32
+ end
33
+
34
+ end
35
+ end
36
+ end
37
+ end
@@ -43,6 +43,22 @@ module PactBroker
43
43
  "#{tags_url(base_url, tag.version)}/#{tag.name}"
44
44
  end
45
45
 
46
+ def webhooks_url base_url
47
+ "#{base_url}/webhooks"
48
+ end
49
+
50
+ def webhook_url webhook, base_url
51
+ "#{base_url}/webhooks/#{webhook.uuid}"
52
+ end
53
+
54
+ def webhook_execution_url webhook, base_url
55
+ "#{base_url}/webhooks/#{webhook.uuid}/execute"
56
+ end
57
+
58
+ def webhooks_for_pact_url consumer, provider, base_url
59
+ "#{base_url}/webhooks/provider/#{provider.name}/consumer/#{consumer.name}"
60
+ end
61
+
46
62
  private
47
63
 
48
64
  def representable_pact pact
@@ -1,6 +1,7 @@
1
1
  require 'pact/consumer_contract'
2
2
  require 'pact/reification'
3
3
  require 'redcarpet'
4
+ require 'pact/doc/markdown/consumer_contract_renderer'
4
5
 
5
6
  module PactBroker
6
7
  module Api
@@ -26,7 +27,7 @@ module PactBroker
26
27
  end
27
28
 
28
29
  def markdown
29
- Pact::Doc::Markdown::InteractionsRenderer.call consumer_contract
30
+ Pact::Doc::Markdown::ConsumerContractRenderer.call consumer_contract
30
31
  end
31
32
 
32
33
  def html
@@ -3,6 +3,7 @@ require 'pact_broker/services'
3
3
  require 'pact_broker/api/decorators'
4
4
  require 'pact_broker/logging'
5
5
  require 'pact_broker/api/pact_broker_urls'
6
+ require 'pact_broker/api/decorators/decorator_context'
6
7
 
7
8
  module PactBroker::Api
8
9
 
@@ -25,6 +26,7 @@ module PactBroker::Api
25
26
 
26
27
  include PactBroker::Services
27
28
  include PactBroker::Api::PactBrokerUrls
29
+ include PactBroker::Logging
28
30
 
29
31
  def identifier_from_path
30
32
  request.path_info.each_with_object({}) do | pair, hash|
@@ -32,10 +34,19 @@ module PactBroker::Api
32
34
  end
33
35
  end
34
36
 
35
- def resource_url
37
+ # This should be called base_url
38
+ def base_url
36
39
  request.uri.to_s.gsub(/#{request.uri.path}$/,'')
37
40
  end
38
41
 
42
+ def resource_url
43
+ request.uri.to_s
44
+ end
45
+
46
+ def decorator_context options = {}
47
+ Decorators::DecoratorContext.new(base_url, resource_url, options)
48
+ end
49
+
39
50
  def handle_exception e
40
51
  PactBroker::Api::Resources::ErrorHandler.handle_exception(e, response)
41
52
  end
@@ -0,0 +1,38 @@
1
+ require 'pact_broker/api/resources/base_resource'
2
+ require 'pact_broker/api/decorators/relationships_csv_decorator'
3
+
4
+ module PactBroker::Api
5
+
6
+ module Resources
7
+
8
+ class Group < BaseResource
9
+
10
+ def content_types_provided
11
+ [["text/csv", :to_csv]]
12
+ end
13
+
14
+ def allowed_methods
15
+ ["GET"]
16
+ end
17
+
18
+ def to_csv
19
+ generate_csv(group_service.find_group_containing @pacticipant)
20
+ end
21
+
22
+ def generate_csv group
23
+ PactBroker::Api::Decorators::RelationshipsCsvDecorator.new(group).to_csv
24
+ end
25
+
26
+ def pacticipant_name
27
+ identifier_from_path[:pacticipant_name]
28
+ end
29
+
30
+ def resource_exists?
31
+ @pacticipant = pacticipant_service.find_pacticipant_by_name(pacticipant_name)
32
+ @pacticipant != nil
33
+ end
34
+
35
+ end
36
+ end
37
+
38
+ end
@@ -19,31 +19,40 @@ module PactBroker::Api
19
19
  def to_json
20
20
  {
21
21
  _links: {
22
- 'index' => [
23
- {
24
- href: request.uri.to_s,
25
- title: 'The index page',
26
- templated: false
27
- }
28
- ],
29
- 'latest-pacts' => [
30
- {
31
- href: request.uri.to_s + 'pacts/latest',
32
- title: 'Retrieve latest pacts',
33
- templated: false
34
- }
35
- ],
36
- 'pacticpants' => [
37
- {
38
- href: request.uri.to_s + 'pacticipants',
39
- title: 'Retrieve pacticipants',
40
- templated: false
41
- }
42
- ]
22
+ 'pb:self' =>
23
+ {
24
+ href: request.uri.to_s,
25
+ title: 'The Pact Broker index page',
26
+ templated: false
27
+ },
28
+ 'pb:latest-pacts' =>
29
+ {
30
+ href: request.uri.to_s + 'pacts/latest',
31
+ title: 'Retrieve latest pacts',
32
+ templated: false
33
+ },
34
+ 'pb:pacticipants' =>
35
+ {
36
+ href: request.uri.to_s + 'pacticipants',
37
+ title: 'Retrieve pacticipants',
38
+ templated: false
39
+ },
40
+ 'pb:webhooks' =>
41
+ {
42
+ href: request.uri.to_s + 'webhooks',
43
+ title: 'Webhooks',
44
+ templated: false
45
+ },'curies' =>
46
+ [{
47
+ name: 'pb',
48
+ href: request.uri.to_s + 'doc/{rel}',
49
+ templated: true
50
+ }]
43
51
  }
44
52
  }.to_json
45
53
  end
46
54
 
55
+
47
56
  end
48
57
  end
49
58
 
@@ -23,7 +23,7 @@ module PactBroker::Api
23
23
 
24
24
  def to_json
25
25
  response.headers['X-Pact-Consumer-Version'] = @pact.consumer_version_number
26
- @pact.json_content
26
+ PactBroker::Api::Decorators::PactDecorator.new(@pact).to_json(base_url: base_url)
27
27
  end
28
28
 
29
29
  def to_html
@@ -19,7 +19,7 @@ module PactBroker::Api
19
19
  end
20
20
 
21
21
  def generate_json pacts
22
- PactBroker::Api::Decorators::PactCollectionDecorator.new(pacts).to_json(base_url: resource_url)
22
+ PactBroker::Api::Decorators::PactCollectionDecorator.new(pacts).to_json(base_url: base_url)
23
23
  end
24
24
 
25
25
  end
@@ -1,5 +1,7 @@
1
1
  require 'cgi'
2
2
  require 'pact_broker/api/resources/base_resource'
3
+ require 'pact_broker/api/decorators/pact_decorator'
4
+ require 'pact_broker/json'
3
5
 
4
6
  module PactBroker::Api
5
7
 
@@ -19,6 +21,20 @@ module PactBroker::Api
19
21
  ["GET", "PUT"]
20
22
  end
21
23
 
24
+ def malformed_request?
25
+ if request.put?
26
+ begin
27
+ JSON.parse(pact_content, PactBroker::PACT_PARSING_OPTIONS) #Not load! Otherwise it will try to load Ruby classes.
28
+ false
29
+ rescue StandardError => e
30
+ logger.error "Error parsing JSON #{e} - #{pact_content}"
31
+ response.headers['Content-Type'] = 'application/json'
32
+ response.body = {error: "Invalid JSON - #{e.message}"}.to_json
33
+ true
34
+ end
35
+ end
36
+ end
37
+
22
38
  def resource_exists?
23
39
  @pact = pact_service.find_pact(identifier_from_path)
24
40
  @pact != nil
@@ -26,12 +42,12 @@ module PactBroker::Api
26
42
 
27
43
  def from_json
28
44
  @pact, created = pact_service.create_or_update_pact(identifier_from_path.merge(:json_content => pact_content))
29
- response.headers["Location"] = pact_url(resource_url, @pact) if created
45
+ response.headers["Location"] = pact_url(base_url, @pact) if created
30
46
  response.body = to_json
31
47
  end
32
48
 
33
49
  def to_json
34
- @pact.json_content
50
+ PactBroker::Api::Decorators::PactDecorator.new(@pact).to_json(base_url: base_url)
35
51
  end
36
52
 
37
53
  def pact_content
@@ -0,0 +1,87 @@
1
+
2
+ require 'pact_broker/api/resources/base_resource'
3
+ require 'pact_broker/api/decorators/webhook_decorator'
4
+ require 'pact_broker/api/decorators/webhooks_decorator'
5
+
6
+ module PactBroker::Api
7
+
8
+ module Resources
9
+
10
+ class PactWebhooks < BaseResource
11
+
12
+ def allowed_methods
13
+ ["POST", "GET"]
14
+ end
15
+
16
+ def content_types_provided
17
+ [["application/hal+json", :to_json]]
18
+ end
19
+
20
+ def resource_exists?
21
+ (@consumer = find_pacticipant(identifier_from_path[:consumer_name], "consumer")) &&
22
+ (@provider = find_pacticipant(identifier_from_path[:provider_name], "provider"))
23
+ end
24
+
25
+ def malformed_request?
26
+ if request.post?
27
+ begin
28
+ if (errors = webhook.validate).any?
29
+ set_json_validation_error_messages errors
30
+ return true
31
+ end
32
+ rescue
33
+ set_json_error_message 'Invalid JSON'
34
+ return true
35
+ end
36
+ end
37
+ false
38
+ end
39
+
40
+ def process_post
41
+ saved_webhook = webhook_service.create webhook, consumer, provider
42
+ response.headers['Content-Type'] = 'application/json'
43
+ response.headers['Location'] = webhook_url saved_webhook, base_url
44
+ response.body = Decorators::WebhookDecorator.new(saved_webhook).to_json(base_url: base_url)
45
+ true
46
+ end
47
+
48
+ def to_json
49
+ Decorators::WebhooksDecorator.new(webhooks).to_json(decorator_context(resource_title: 'Pact webhooks'))
50
+ end
51
+
52
+ private
53
+
54
+ attr_reader :consumer, :provider
55
+
56
+ def webhooks
57
+ webhook_service.find_by_consumer_and_provider consumer, provider
58
+ end
59
+
60
+ def webhook
61
+ @webhook ||= Decorators::WebhookDecorator.new(PactBroker::Models::Webhook.new).from_json(request.body.to_s)
62
+ end
63
+
64
+ def set_json_error_message message
65
+ response.headers['Content-Type'] = 'application/json'
66
+ response.body = {error: message}.to_json
67
+ end
68
+
69
+ def set_json_validation_error_messages errors
70
+ response.headers['Content-Type'] = 'application/json'
71
+ response.body = {errors: errors}.to_json
72
+ end
73
+
74
+ def find_pacticipant name, role
75
+ pacticipant = pacticipant_service.find_pacticipant_by_name name
76
+ if pacticipant.nil?
77
+ set_json_error_message "No #{role} with name '#{name}' found"
78
+ nil
79
+ else
80
+ pacticipant
81
+ end
82
+ end
83
+
84
+ end
85
+ end
86
+
87
+ end