pact_broker 2.0.5 → 2.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 (78) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/RELEASING.md +1 -1
  4. data/db/migrations/33_create_config_table.rb +1 -1
  5. data/db/migrations/34_create_index_on_consumer_version_order.rb +1 -1
  6. data/db/migrations/35_create_index_on_names.rb +1 -1
  7. data/db/pact_broker_database.sqlite3 +0 -0
  8. data/lib/pact_broker/api.rb +1 -0
  9. data/lib/pact_broker/api/resources/authentication.rb +30 -0
  10. data/lib/pact_broker/api/resources/base_resource.rb +14 -0
  11. data/lib/pact_broker/app.rb +2 -0
  12. data/lib/pact_broker/configuration.rb +34 -0
  13. data/lib/pact_broker/db/migrate.rb +15 -0
  14. data/lib/pact_broker/db/version.rb +17 -0
  15. data/lib/pact_broker/diagnostic/resources/base_resource.rb +13 -0
  16. data/lib/pact_broker/pacts/all_pact_publications.rb +5 -0
  17. data/lib/pact_broker/pacts/repository.rb +6 -1
  18. data/lib/pact_broker/repositories/helpers.rb +4 -0
  19. data/lib/pact_broker/tasks.rb +1 -0
  20. data/lib/pact_broker/tasks/migration_task.rb +7 -6
  21. data/lib/pact_broker/tasks/version_task.rb +38 -0
  22. data/lib/pact_broker/version.rb +1 -1
  23. data/lib/rack/pact_broker/ui_authentication.rb +26 -0
  24. data/pact_broker.gemspec +1 -0
  25. data/script/recreate-pg-db.sh +6 -5
  26. data/spec/features/create_webhook_spec.rb +2 -2
  27. data/spec/features/delete_pact_spec.rb +1 -1
  28. data/spec/features/delete_version_spec.rb +2 -2
  29. data/spec/features/delete_webhook_spec.rb +2 -2
  30. data/spec/features/get_diff_spec.rb +2 -2
  31. data/spec/features/get_latest_tagged_pact_spec.rb +22 -0
  32. data/spec/features/get_latest_untagged_pact_spec.rb +22 -0
  33. data/spec/features/get_pact_spec.rb +2 -2
  34. data/spec/features/get_pact_versions_spec.rb +2 -2
  35. data/spec/features/get_previous_distinct_version.rb +2 -2
  36. data/spec/features/get_provider_pacts_spec.rb +2 -2
  37. data/spec/features/get_verifications_for_consumer_version_spec.rb +2 -2
  38. data/spec/features/get_version_spec.rb +3 -3
  39. data/spec/features/get_versions_spec.rb +2 -2
  40. data/spec/features/merge_pact_spec.rb +2 -2
  41. data/spec/features/publish_pact_spec.rb +1 -1
  42. data/spec/features/publish_verification_spec.rb +1 -1
  43. data/spec/integration/app_spec.rb +1 -1
  44. data/spec/integration/endpoints/group.rb +1 -1
  45. data/spec/lib/pact_broker/api/decorators/embedded_tag_decorator_spec.rb +2 -2
  46. data/spec/lib/pact_broker/api/decorators/embedded_version_decorator_spec.rb +1 -1
  47. data/spec/lib/pact_broker/api/decorators/latest_pact_decorator_spec.rb +1 -1
  48. data/spec/lib/pact_broker/api/decorators/relationships_csv_decorator_spec.rb +1 -1
  49. data/spec/lib/pact_broker/api/decorators/representable_pact_spec.rb +2 -2
  50. data/spec/lib/pact_broker/api/decorators/tag_decorator_spec.rb +2 -2
  51. data/spec/lib/pact_broker/api/decorators/version_decorator_spec.rb +1 -1
  52. data/spec/lib/pact_broker/api/decorators/versions_decorator_spec.rb +1 -1
  53. data/spec/lib/pact_broker/app_spec.rb +128 -0
  54. data/spec/lib/pact_broker/domain/order_versions_spec.rb +4 -4
  55. data/spec/lib/pact_broker/domain/verification_spec.rb +2 -2
  56. data/spec/lib/pact_broker/domain/version_spec.rb +2 -2
  57. data/spec/lib/pact_broker/pacticipants/repository_spec.rb +4 -4
  58. data/spec/lib/pact_broker/pacticipants/service_spec.rb +1 -1
  59. data/spec/lib/pact_broker/pacts/diff_spec.rb +1 -1
  60. data/spec/lib/pact_broker/pacts/merger_spec.rb +1 -1
  61. data/spec/lib/pact_broker/pacts/pact_version_spec.rb +3 -3
  62. data/spec/lib/pact_broker/pacts/repository_spec.rb +61 -14
  63. data/spec/lib/pact_broker/tags/repository_spec.rb +4 -4
  64. data/spec/lib/pact_broker/tags/service_spec.rb +1 -1
  65. data/spec/lib/pact_broker/ui/controllers/relationships_spec.rb +1 -1
  66. data/spec/lib/pact_broker/verifications/repository_spec.rb +7 -7
  67. data/spec/lib/pact_broker/verifications/service_spec.rb +1 -1
  68. data/spec/lib/pact_broker/versions/repository_spec.rb +3 -3
  69. data/spec/lib/pact_broker/versions/service_spec.rb +1 -1
  70. data/spec/lib/pact_broker/webhooks/repository_spec.rb +2 -2
  71. data/spec/lib/pact_broker/webhooks/service_spec.rb +1 -1
  72. data/spec/service_consumers/provider_states_for_pact_broker_client.rb +10 -10
  73. data/spec/support/rspec_matchers.rb +2 -2
  74. data/spec/support/{provider_state_builder.rb → test_data_builder.rb} +2 -2
  75. data/tasks/database.rb +8 -9
  76. data/tasks/db.rake +0 -5
  77. data/tasks/test_db.rake +11 -0
  78. metadata +29 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a2edb308c7e322351a0d87be210ccd4c9eaf4153
4
- data.tar.gz: 24b63e6f8b5806bb363391f7b862ee3537855076
3
+ metadata.gz: 941974e21c5b34f41911366af7278a0b436436a1
4
+ data.tar.gz: 7e6f31d82d4da9f20838edd731f2af50852cef85
5
5
  SHA512:
6
- metadata.gz: dc2bf80f0f162989597ff0046c506ba67d0020b4cf0210ac33bca85221e8bc1ca54ef59bd7b356915daeb533e041e45eafdf2e39b2823c54ffc7ab25506b2c20
7
- data.tar.gz: 9c81983d516bb00fc61d6dae594b33c9202c3b2ba4e33d7ef6901d25800615c574578e9701c3ea16b8f70b526cdf8d9dc70ba61d16ec139232d31f9beb08b668
6
+ metadata.gz: dd4d89bdaca1e461cf662aa47f95b2ed6557d7731b7ed3364075c759e1a2d40d9cd8da5c0354e5781be23b0d6a800a8d267e99e0eeacf00583fbea6ae290646f
7
+ data.tar.gz: dfca11736f092764368478fde2ae871863c8b6a4092be8c4e17355e29ef69546261413e5e990ca06de80e40506325ae52c13c14f2c9c55471195ef66be2fd302
@@ -2,6 +2,11 @@ Do this to generate your change history
2
2
 
3
3
  $ git log --pretty=format:' * %h - %s (%an, %ad)'
4
4
 
5
+ #### 2.1.0 (2017-07-03)
6
+ * 53f0b5e - feat(get latest untagged pact): Add /latest-untagged endpoint to return the latest untagged pact (Beth Skurrie, Mon Jul 3 08:31:18 2017 +1000)
7
+ * a963fce - Add pact_broker:db:version task. (Beth Skurrie, Thu Jun 29 20:29:55 2017 +1000)
8
+ * 7ee134f - Add basic auth (authentication) to the UI, but no authorization (Beth Skurrie, Mon Jun 26 10:44:07 2017 +1000)
9
+
5
10
  #### 2.0.5 (2017-06-15)
6
11
  * e924c96 - Fixed webhook deletion bug (Beth Skurrie, Tue Jun 13 10:04:33 2017 +1000)
7
12
 
@@ -8,7 +8,7 @@
8
8
  3. Add files to git
9
9
 
10
10
  $ git add CHANGELOG.md lib/pact_broker/version.rb
11
- $ git commit -m "Releasing version X.Y.Z"
11
+ $ git commit -m "Releasing version $(ruby -r ./lib/pact_broker/version.rb -e "puts PactBroker::VERSION")"
12
12
 
13
13
  3. Release:
14
14
 
@@ -1,7 +1,7 @@
1
1
  require_relative 'migration_helper'
2
2
 
3
3
  Sequel.migration do
4
- up do
4
+ change do
5
5
  create_table(:config, charset: 'utf8') do
6
6
  primary_key :id
7
7
  String :name, null: false
@@ -1,5 +1,5 @@
1
1
  Sequel.migration do
2
- up do
2
+ change do
3
3
  alter_table(:versions) do
4
4
  # Not actually sure which index it will use for OrderVersions, so CREATE ALL THE INDEXES!
5
5
  add_index [:number], name: 'ndx_ver_num' # Not sure if this is useful give we use LIKE not EQ
@@ -1,5 +1,5 @@
1
1
  Sequel.migration do
2
- up do
2
+ change do
3
3
  alter_table(:pacticipants) do
4
4
  add_index [:name], name: 'ndx_ppt_name' # Not sure if this is useful give we use LIKE not EQ
5
5
  end
@@ -52,6 +52,7 @@ module PactBroker
52
52
  # Latest pacts
53
53
  add ['pacts', 'provider', :provider_name, 'consumer', :consumer_name, 'latest'], Api::Resources::LatestPact, {resource_name: "latest_pact_publication"}
54
54
  add ['pacts', 'provider', :provider_name, 'consumer', :consumer_name, 'latest', :tag], Api::Resources::LatestPact, {resource_name: "latest_tagged_pact_publication"}
55
+ add ['pacts', 'provider', :provider_name, 'consumer', :consumer_name, 'latest-untagged'], Api::Resources::LatestPact, {resource_name: "latest_untagged_pact_publication", tag: :untagged}
55
56
  add ['pacts', 'provider', :provider_name, 'latest'], Api::Resources::LatestProviderPacts, {resource_name: "latest_provider_pact_publications"}
56
57
  add ['pacts', 'provider', :provider_name, 'latest', :tag], Api::Resources::LatestProviderPacts, {resource_name: "latest_tagged_provider_pact_publications"}
57
58
  add ['pacts', 'latest'], Api::Resources::LatestPacts, {resource_name: "latest_pacts"}
@@ -0,0 +1,30 @@
1
+ require 'webmachine/resource/authentication'
2
+
3
+ module PactBroker
4
+ module Api
5
+ module Resources
6
+ module Authentication
7
+
8
+ include Webmachine::Resource::Authentication
9
+
10
+ def authenticated? resource, authorization_header
11
+ return true unless PactBroker.configuration.authentication_configured?
12
+
13
+ if PactBroker.configuration.authenticate
14
+ authorized = PactBroker.configuration.authenticate.call(resource, authorization_header, {})
15
+ return true if authorized
16
+ end
17
+
18
+ if PactBroker.configuration.authenticate_with_basic_auth
19
+ basic_auth(authorization_header, "Pact Broker") do |username, password|
20
+ authorized = PactBroker.configuration.authenticate_with_basic_auth.call(resource, username, password, {})
21
+ return true if authorized
22
+ end
23
+ end
24
+
25
+ false
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -6,6 +6,7 @@ require 'pact_broker/api/pact_broker_urls'
6
6
  require 'pact_broker/api/decorators/decorator_context'
7
7
  require 'pact_broker/json'
8
8
  require 'pact_broker/pacts/pact_params'
9
+ require 'pact_broker/api/resources/authentication'
9
10
 
10
11
  module PactBroker
11
12
 
@@ -29,8 +30,12 @@ module PactBroker
29
30
 
30
31
  include PactBroker::Services
31
32
  include PactBroker::Api::PactBrokerUrls
33
+ include PactBroker::Api::Resources::Authentication
32
34
  include PactBroker::Logging
33
35
 
36
+
37
+ attr_accessor :user
38
+
34
39
  def initialize
35
40
  PactBroker.configuration.before_resource.call(self)
36
41
  end
@@ -39,6 +44,15 @@ module PactBroker
39
44
  PactBroker.configuration.after_resource.call(self)
40
45
  end
41
46
 
47
+ def is_authorized?(authorization_header)
48
+ authenticated?(self, authorization_header)
49
+ end
50
+
51
+ def forbidden?
52
+ return false if PactBroker.configuration.authorize.nil?
53
+ !PactBroker.configuration.authorize.call(self, {})
54
+ end
55
+
42
56
  def identifier_from_path
43
57
  request.path_info.each_with_object({}) do | pair, hash|
44
58
  hash[pair.first] = pair.last === String ? URI.decode(pair.last) : pair.last
@@ -8,6 +8,7 @@ require 'rack/pact_broker/convert_file_extension_to_accept_header'
8
8
  require 'rack/pact_broker/database_transaction'
9
9
  require 'rack/pact_broker/invalid_uri_protection'
10
10
  require 'rack/pact_broker/accepts_html_filter'
11
+ require 'rack/pact_broker/ui_authentication'
11
12
  require 'sucker_punch'
12
13
 
13
14
  module PactBroker
@@ -97,6 +98,7 @@ module PactBroker
97
98
  require 'pact_broker/ui'
98
99
  builder = ::Rack::Builder.new
99
100
  builder.use Rack::PactBroker::AcceptsHtmlFilter
101
+ builder.use Rack::PactBroker::UIAuthentication
100
102
  builder.run PactBroker::UI::App.new
101
103
  builder
102
104
  end
@@ -22,6 +22,8 @@ module PactBroker
22
22
  def initialize
23
23
  @before_resource_hook = ->(resource){}
24
24
  @after_resource_hook = ->(resource){}
25
+ @authenticate_with_basic_auth = nil
26
+ @authorize = nil
25
27
  end
26
28
 
27
29
  def logger
@@ -53,6 +55,38 @@ module PactBroker
53
55
  }
54
56
  end
55
57
 
58
+ def authentication_configured?
59
+ !!authenticate || !!authenticate_with_basic_auth
60
+ end
61
+
62
+ def authenticate &block
63
+ if block_given?
64
+ @authenticate = block
65
+ else
66
+ @authenticate
67
+ end
68
+ end
69
+
70
+ def authenticate_with_basic_auth &block
71
+ if block_given?
72
+ @authenticate_with_basic_auth = block
73
+ else
74
+ @authenticate_with_basic_auth
75
+ end
76
+ end
77
+
78
+ def authorization_configured?
79
+ !!authorize
80
+ end
81
+
82
+ def authorize &block
83
+ if block_given?
84
+ @authorize = block
85
+ else
86
+ @authorize
87
+ end
88
+ end
89
+
56
90
  def before_resource &block
57
91
  if block_given?
58
92
  @before_resource_hook = block
@@ -0,0 +1,15 @@
1
+ require 'sequel'
2
+ require 'pact_broker/project_root'
3
+ Sequel.extension :migration
4
+
5
+ module PactBroker
6
+ module DB
7
+ class Migrate
8
+ def self.call database_connection, options = {}
9
+ db_migrations_dir = PactBroker.project_root.join('db','migrations')
10
+ puts "Running migrations in directory #{db_migrations_dir}, target=#{options.fetch(:target, 'end')}"
11
+ Sequel::Migrator.run(database_connection, db_migrations_dir, options)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ module PactBroker
2
+ module DB
3
+ class Version
4
+ def self.call database_connection
5
+ # if database_connection.tables.include?(:schema_migrations)
6
+ # last_migration_filename = database_connection[:schema_migrations].order(:filename).last[:filename]
7
+ # last_migration_filename.split(MIGRATION_SPLITTER, 2).first.to_i
8
+
9
+ if database_connection.tables.include?(:schema_info)
10
+ database_connection[:schema_info].first[:version]
11
+ else
12
+ 0
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,9 +1,22 @@
1
1
  require 'webmachine'
2
+ require 'pact_broker/api/resources/authentication'
2
3
 
3
4
  module PactBroker
4
5
  module Diagnostic
5
6
  module Resources
6
7
  class BaseResource < Webmachine::Resource
8
+
9
+ include PactBroker::Api::Resources::Authentication
10
+
11
+ def is_authorized?(authorization_header)
12
+ authenticated?(self, authorization_header)
13
+ end
14
+
15
+ def forbidden?
16
+ return false if PactBroker.configuration.authorize.nil?
17
+ !PactBroker.configuration.authorize.call(self, {})
18
+ end
19
+
7
20
  def initialize
8
21
  PactBroker.configuration.before_resource.call(self)
9
22
  end
@@ -33,6 +33,11 @@ module PactBroker
33
33
  join(:tags, {version_id: :consumer_version_id}).where(filter)
34
34
  end
35
35
 
36
+ def untagged
37
+ left_outer_join(:tags, {version_id: :consumer_version_id})
38
+ .where(Sequel.qualify(:tags, :name) => nil)
39
+ end
40
+
36
41
  def consumer_version_number number
37
42
  where(name_like(:consumer_version_number, number))
38
43
  end
@@ -91,9 +91,14 @@ module PactBroker
91
91
 
92
92
  def find_latest_pact(consumer_name, provider_name, tag = nil)
93
93
  query = LatestPactPublicationsByConsumerVersion
94
+ .select_all_qualified
94
95
  .consumer(consumer_name)
95
96
  .provider(provider_name)
96
- query = query.tag(tag) unless tag.nil?
97
+ if tag == :untagged
98
+ query = query.untagged
99
+ elsif tag
100
+ query = query.tag(tag)
101
+ end
97
102
  query.latest.all.collect(&:to_domain_with_content)[0]
98
103
  end
99
104
 
@@ -20,6 +20,10 @@ module PactBroker
20
20
  Sequel::Model.db.adapter_scheme.to_s =~ /mysql/
21
21
  end
22
22
 
23
+ def select_all_qualified
24
+ select(Sequel[model.table_name].*)
25
+ end
26
+
23
27
  def select_for_subquery column
24
28
  if mysql? #stoopid mysql doesn't allow subqueries
25
29
  select(column).collect{ | it | it[column] }
@@ -1 +1,2 @@
1
1
  require 'pact_broker/tasks/migration_task'
2
+ require 'pact_broker/tasks/version_task'
@@ -25,13 +25,14 @@ module PactBroker
25
25
  namespace :pact_broker do
26
26
  namespace :db do
27
27
  desc "Run sequel migrations for pact broker database"
28
- task :migrate do
28
+ task :migrate, [:target] do | t, args |
29
+ require 'pact_broker/db/migrate'
29
30
  instance_eval(&block)
30
- require 'sequel'
31
- Sequel.extension :migration
32
- db_migrations_dir = File.expand_path("../../../../db/migrations", __FILE__)
33
- puts "Running migrations in directory #{db_migrations_dir}"
34
- Sequel::Migrator.run(database_connection, db_migrations_dir)
31
+ options = {}
32
+ if args[:target]
33
+ options[:target] = args[:target].to_i
34
+ end
35
+ PactBroker::DB::Migrate.call(database_connection, options)
35
36
  end
36
37
  end
37
38
  end
@@ -0,0 +1,38 @@
1
+ require 'rake/tasklib'
2
+
3
+ =begin
4
+
5
+ require 'pact_broker/tasks'
6
+
7
+ PactBroker::DB::VersionTask.new do | task |
8
+ require 'my_app/db'
9
+ task.database_connection = MyApp::DB
10
+ end
11
+
12
+ =end
13
+
14
+ module PactBroker
15
+ module DB
16
+ class VersionTask < ::Rake::TaskLib
17
+
18
+ attr_accessor :database_connection
19
+
20
+ def initialize &block
21
+ rake_task &block
22
+ end
23
+
24
+ def rake_task &block
25
+ namespace :pact_broker do
26
+ namespace :db do
27
+ desc "Display the current database migration version"
28
+ task :version do
29
+ instance_eval(&block)
30
+ require 'pact_broker/db/version'
31
+ puts PactBroker::DB::Version.call(database_connection)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,3 +1,3 @@
1
1
  module PactBroker
2
- VERSION = '2.0.5'
2
+ VERSION = '2.1.0'
3
3
  end
@@ -0,0 +1,26 @@
1
+ require 'pact_broker/api/resources/authentication'
2
+
3
+ module Rack
4
+ module PactBroker
5
+ class UIAuthentication
6
+
7
+ include ::PactBroker::Api::Resources::Authentication
8
+
9
+ def initialize app
10
+ @app = app
11
+ end
12
+
13
+ def call env
14
+ if auth? env
15
+ @app.call(env)
16
+ else
17
+ [401, {'WWW-Authenticate' => 'Basic realm="Restricted Area"'}, []]
18
+ end
19
+ end
20
+
21
+ def auth? env
22
+ authenticated? nil, env['HTTP_AUTHORIZATION']
23
+ end
24
+ end
25
+ end
26
+ end
@@ -48,4 +48,5 @@ Gem::Specification.new do |gem|
48
48
  gem.add_development_dependency 'rspec-its'
49
49
  gem.add_development_dependency 'database_cleaner'
50
50
  gem.add_development_dependency 'pg'
51
+ gem.add_development_dependency 'dry-types', '~> 0.10.3' # https://travis-ci.org/pact-foundation/pact_broker/jobs/249448621
51
52
  end
@@ -1,13 +1,14 @@
1
+ SCHEMA="pact_broker"
1
2
  set -e
2
- psql postgres -c "DROP DATABASE pact_broker;"
3
- psql postgres -c "CREATE DATABASE pact_broker;"
4
- psql postgres -c "GRANT ALL PRIVILEGES ON DATABASE pact_broker TO pact_broker;"
3
+ psql postgres -c "DROP DATABASE ${SCHEMA};"
4
+ psql postgres -c "CREATE DATABASE ${SCHEMA};"
5
+ psql postgres -c "GRANT ALL PRIVILEGES ON DATABASE ${SCHEMA} TO pact_broker;"
5
6
  ip=$(ifconfig en0 | sed -n -e '/inet/s/.*inet \([0-9.]*\) netmask .*/\1/p')
6
7
  echo ""
7
8
  echo "run the following command to set your environment variables:"
8
9
  echo "export PACT_BROKER_DATABASE_USERNAME=pact_broker"
9
10
  echo "export PACT_BROKER_DATABASE_PASSWORD=pact_broker"
10
- echo "export PACT_BROKER_DATABASE_NAME=pact_broker"
11
+ echo "export PACT_BROKER_DATABASE_NAME=${SCHEMA}"
11
12
  echo "export PACT_BROKER_DATABASE_HOST=${ip}"
12
13
  echo "To test:"
13
- echo "psql -h \$PACT_BROKER_DATABASE_HOST -d \$PACT_BROKER_DATABASE_NAME -U \$PACT_BROKER_DATABASE_USERNAME"
14
+ echo "psql -h \$PACT_BROKER_DATABASE_HOST -d \$PACT_BROKER_DATABASE_NAME -U \$PACT_BROKER_DATABASE_USERNAME"
@@ -1,9 +1,9 @@
1
- require 'support/provider_state_builder'
1
+ require 'support/test_data_builder'
2
2
 
3
3
  describe "Creating a webhook" do
4
4
 
5
5
  before do
6
- ProviderStateBuilder.new.create_pact_with_hierarchy("Some Consumer", "1", "Some Provider")
6
+ TestDataBuilder.new.create_pact_with_hierarchy("Some Consumer", "1", "Some Provider")
7
7
  end
8
8
 
9
9
  let(:path) { "/webhooks/provider/Some%20Provider/consumer/Some%20Consumer" }
@@ -8,7 +8,7 @@ describe "Deleting a pact" do
8
8
 
9
9
  context "when the pact exists" do
10
10
  before do
11
- ProviderStateBuilder.new.create_pact_with_hierarchy "A Consumer", "1.2.3", "A Provider"
11
+ TestDataBuilder.new.create_pact_with_hierarchy "A Consumer", "1.2.3", "A Provider"
12
12
  end
13
13
 
14
14
  it "deletes the pact" do