pact_broker 2.81.0 → 2.82.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +1 -1
  3. data/CHANGELOG.md +30 -0
  4. data/DEVELOPER_SETUP.md +1 -1
  5. data/README.md +7 -5
  6. data/config.ru +3 -28
  7. data/db/migrations/20210722_add_index_to_triggered_webhooks_webhook_uuid.rb +7 -0
  8. data/db/migrations/20210810_set_allow_contract_modification.rb +17 -0
  9. data/docs/CONFIGURATION.md +398 -0
  10. data/docs/configuration.yml +320 -0
  11. data/example/Gemfile +4 -4
  12. data/example/README.md +15 -22
  13. data/example/config.ru +1 -24
  14. data/example/config/pact_broker.yml +9 -0
  15. data/example/config/puma.rb +3 -0
  16. data/lib/db.rb +1 -1
  17. data/lib/pact_broker/api/authorization/resource_access_policy.rb +68 -0
  18. data/lib/pact_broker/api/authorization/resource_access_rules.rb +40 -0
  19. data/lib/pact_broker/api/decorators/deployed_version_decorator.rb +2 -0
  20. data/lib/pact_broker/api/decorators/released_version_decorator.rb +2 -0
  21. data/lib/pact_broker/api/middleware/basic_auth.rb +63 -0
  22. data/lib/pact_broker/api/resources/pact.rb +15 -6
  23. data/lib/pact_broker/api/resources/tag.rb +1 -14
  24. data/lib/pact_broker/app.rb +52 -30
  25. data/lib/pact_broker/config/basic_auth_configuration.rb +38 -0
  26. data/lib/pact_broker/config/load.rb +21 -10
  27. data/lib/pact_broker/config/runtime_configuration.rb +188 -0
  28. data/lib/pact_broker/config/runtime_configuration_coercion_methods.rb +41 -0
  29. data/lib/pact_broker/config/runtime_configuration_database_methods.rb +119 -0
  30. data/lib/pact_broker/config/runtime_configuration_logging_methods.rb +61 -0
  31. data/lib/pact_broker/configuration.rb +67 -131
  32. data/lib/pact_broker/contracts/notice.rb +4 -0
  33. data/lib/pact_broker/contracts/service.rb +4 -4
  34. data/lib/pact_broker/db/models.rb +3 -0
  35. data/lib/pact_broker/db/validate_encoding.rb +0 -4
  36. data/lib/pact_broker/deployments/deployed_version.rb +8 -2
  37. data/lib/pact_broker/deployments/deployed_version_service.rb +13 -6
  38. data/lib/pact_broker/deployments/environment.rb +1 -1
  39. data/lib/pact_broker/deployments/released_version.rb +8 -0
  40. data/lib/pact_broker/deployments/released_version_service.rb +12 -0
  41. data/lib/pact_broker/doc/views/provider-pacts-for-verification.markdown +4 -0
  42. data/lib/pact_broker/domain/pacticipant.rb +17 -13
  43. data/lib/pact_broker/domain/verification.rb +4 -22
  44. data/lib/pact_broker/domain/version.rb +9 -5
  45. data/lib/pact_broker/domain/webhook.rb +4 -0
  46. data/lib/pact_broker/error.rb +1 -0
  47. data/lib/pact_broker/errors.rb +1 -1
  48. data/lib/pact_broker/feature_toggle.rb +3 -5
  49. data/lib/pact_broker/hash_refinements.rb +0 -1
  50. data/lib/pact_broker/index/service.rb +4 -6
  51. data/lib/pact_broker/initializers/database_connection.rb +80 -0
  52. data/lib/pact_broker/integrations/integration.rb +5 -0
  53. data/lib/pact_broker/integrations/service.rb +4 -2
  54. data/lib/pact_broker/locale/en.yml +1 -0
  55. data/lib/pact_broker/logging.rb +2 -1
  56. data/lib/pact_broker/matrix/integration.rb +1 -1
  57. data/lib/pact_broker/matrix/parse_can_i_deploy_query.rb +2 -2
  58. data/lib/pact_broker/matrix/quick_row.rb +10 -0
  59. data/lib/pact_broker/matrix/repository.rb +64 -3
  60. data/lib/pact_broker/metrics/service.rb +16 -13
  61. data/lib/pact_broker/pacticipants/repository.rb +4 -0
  62. data/lib/pact_broker/pacticipants/service.rb +9 -1
  63. data/lib/pact_broker/pacts/pact_publication.rb +10 -13
  64. data/lib/pact_broker/pacts/pact_publication_dataset_module.rb +6 -1
  65. data/lib/pact_broker/pacts/pact_publication_selector_dataset_module.rb +1 -2
  66. data/lib/pact_broker/pacts/pact_version.rb +25 -11
  67. data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +54 -77
  68. data/lib/pact_broker/pacts/selected_pact.rb +1 -1
  69. data/lib/pact_broker/pacts/selector.rb +15 -2
  70. data/lib/pact_broker/pacts/selectors.rb +4 -0
  71. data/lib/pact_broker/pacts/service.rb +4 -0
  72. data/lib/pact_broker/repositories/scopes.rb +12 -1
  73. data/lib/pact_broker/string_refinements.rb +6 -0
  74. data/lib/pact_broker/tags/service.rb +8 -1
  75. data/lib/pact_broker/test/http_test_data_builder.rb +11 -5
  76. data/lib/pact_broker/ui/views/index/_css_and_js.haml +11 -9
  77. data/lib/pact_broker/ui/views/index/_pagination.haml +3 -1
  78. data/lib/pact_broker/ui/views/layouts/main.haml +5 -3
  79. data/lib/pact_broker/ui/views/matrix/show.haml +10 -8
  80. data/lib/pact_broker/verifications/required_verification.rb +28 -0
  81. data/lib/pact_broker/verifications/service.rb +49 -1
  82. data/lib/pact_broker/version.rb +1 -1
  83. data/lib/pact_broker/versions/repository.rb +15 -0
  84. data/lib/pact_broker/versions/service.rb +32 -2
  85. data/lib/pact_broker/webhooks/event_listener.rb +3 -0
  86. data/lib/pact_broker/webhooks/trigger_service.rb +30 -14
  87. data/lib/pact_broker/webhooks/triggered_webhook.rb +1 -0
  88. data/lib/pact_broker/webhooks/webhook.rb +2 -2
  89. data/lib/pact_broker/webhooks/webhook_event.rb +6 -1
  90. data/lib/semantic_logger/formatters/short.rb +29 -0
  91. data/pact_broker.gemspec +1 -0
  92. data/script/data/auto-create-things-for-tags.rb +19 -0
  93. data/script/data/contract-published-requiring-verification.rb +27 -0
  94. data/script/{reproduce-issue-expand-currently-deployed.rb → data/expand-currently-deployed.rb} +0 -0
  95. data/script/docs/generate-configuration-docs.rb +86 -0
  96. data/spec/features/get_latest_pact_badge_spec.rb +1 -0
  97. data/spec/features/get_matrix_badge_spec.rb +1 -0
  98. data/spec/features/publish_pact_spec.rb +21 -7
  99. data/spec/features/wip_pacts_spec.rb +1 -1
  100. data/spec/fixtures/approvals/matrix_integration_environment_spec.approved.json +62 -0
  101. data/spec/fixtures/approvals/matrix_integration_ignore_spec.approved.json +124 -0
  102. data/spec/fixtures/approvals/matrix_integration_spec.approved.json +173 -0
  103. data/spec/fixtures/approvals/publish_contract_no_branch.approved.json +9 -9
  104. data/spec/fixtures/approvals/publish_contract_nothing_exists.approved.json +7 -7
  105. data/spec/fixtures/approvals/publish_contract_nothing_exists_with_webhook.approved.json +5 -5
  106. data/spec/fixtures/approvals/publish_contract_verification_already_exists.approved.json +5 -5
  107. data/spec/lib/pact_broker/api/middleware/basic_auth_spec.rb +312 -0
  108. data/spec/lib/pact_broker/api/resources/tag_spec.rb +14 -39
  109. data/spec/lib/pact_broker/app_basic_auth_spec.rb +122 -0
  110. data/spec/lib/pact_broker/config/load_spec.rb +33 -6
  111. data/spec/lib/pact_broker/config/runtime_configuration_logging_methods_spec.rb +22 -0
  112. data/spec/lib/pact_broker/config/runtime_configuration_spec.rb +71 -0
  113. data/spec/lib/pact_broker/configuration_spec.rb +51 -25
  114. data/spec/lib/pact_broker/errors/error_logger_spec.rb +3 -0
  115. data/spec/lib/pact_broker/feature_toggle_spec.rb +18 -19
  116. data/spec/lib/pact_broker/matrix/integration_environment_spec.rb +12 -0
  117. data/spec/lib/pact_broker/matrix/integration_ignore_spec.rb +15 -3
  118. data/spec/lib/pact_broker/matrix/integration_spec.rb +47 -6
  119. data/spec/lib/pact_broker/matrix/parse_can_i_deploy_query_spec.rb +16 -1
  120. data/spec/lib/pact_broker/matrix/repository_dependency_spec.rb +0 -2
  121. data/spec/lib/pact_broker/matrix/repository_spec.rb +0 -2
  122. data/spec/lib/pact_broker/metrics/service_spec.rb +44 -0
  123. data/spec/lib/pact_broker/pacticipants/service_spec.rb +28 -5
  124. data/spec/lib/pact_broker/pacts/pact_publication_selector_dataset_module_spec.rb +25 -0
  125. data/spec/lib/pact_broker/pacts/pact_version_spec.rb +30 -1
  126. data/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb +107 -20
  127. data/spec/lib/pact_broker/pacts/verifiable_pact_messages_spec.rb +1 -1
  128. data/spec/lib/pact_broker/tags/service_spec.rb +24 -8
  129. data/spec/lib/pact_broker/verifications/service_spec.rb +146 -0
  130. data/spec/lib/pact_broker/versions/repository_spec.rb +38 -2
  131. data/spec/lib/pact_broker/versions/service_spec.rb +93 -2
  132. data/spec/lib/pact_broker/webhooks/trigger_service_spec.rb +54 -2
  133. data/spec/lib/rack/pact_broker/invalid_uri_protection_spec.rb +3 -3
  134. data/spec/spec_helper.rb +2 -1
  135. data/spec/support/approvals.rb +29 -0
  136. metadata +52 -13
  137. data/example/basic_auth/Gemfile +0 -5
  138. data/example/basic_auth/Procfile +0 -1
  139. data/example/basic_auth/README.md +0 -43
  140. data/example/basic_auth/config.ru +0 -19
  141. data/example/example_data.sql +0 -19
  142. data/spec/lib/pact_broker/config/save_and_load_spec.rb +0 -25
  143. data/spec/lib/pact_broker/pacts/service_find_for_verification_spec.rb +0 -50
data/lib/db.rb CHANGED
@@ -28,7 +28,7 @@ module DB
28
28
  def self.connect db_credentials
29
29
  # Keep this conifiguration in sync with lib/pact_broker/app.rb#configure_database_connection
30
30
  Sequel.datetime_class = DateTime
31
- if ENV["DEBUG"] == "true"
31
+ if ENV["DEBUG"] == "true" && ENV["PACT_BROKER_SQL_LOG_LEVEL"] != "none"
32
32
  logger = Logger.new($stdout)
33
33
  end
34
34
  if db_credentials.fetch("adapter") == "sqlite"
@@ -0,0 +1,68 @@
1
+ require "pact_broker/api/authorization/resource_access_rules"
2
+ require "pact_broker/api/paths"
3
+
4
+ module PactBroker
5
+ module Api
6
+ module Authorization
7
+ class ResourceAccessPolicy
8
+ include PactBroker::Api::Paths
9
+
10
+ READ_METHODS = %w{GET OPTIONS HEAD}.freeze
11
+ ALL_METHODS = %w{GET POST PUT PATCH DELETE HEAD OPTIONS}.freeze
12
+ POST = "POST".freeze
13
+ ALL_PATHS = %r{.*}.freeze
14
+ HEARTBEAT_PATH = %r{^/diagnostic/status/heartbeat$}.freeze
15
+ PACTS_FOR_VERIFICATION_PATH = %r{^/pacts/provider/[^/]+/for-verification$}.freeze
16
+
17
+ PUBLIC = 0
18
+ READ = 1
19
+ WRITE = 2
20
+
21
+ def initialize(resource_access_rules)
22
+ @resource_access_rules = resource_access_rules
23
+ end
24
+
25
+ def public_access_allowed?(env)
26
+ resource_access_rules.access_allowed?(env, PUBLIC)
27
+ end
28
+
29
+ def read_access_allowed?(env)
30
+ resource_access_rules.access_allowed?(env, READ)
31
+ end
32
+
33
+ def self.build(allow_public_read_access, allow_public_access_to_heartbeat, enable_public_badge_access)
34
+ rules = [
35
+ [WRITE, ALL_METHODS, ALL_PATHS],
36
+ [READ, READ_METHODS, ALL_PATHS],
37
+ [READ, [POST], PACTS_FOR_VERIFICATION_PATH],
38
+ ]
39
+
40
+ if enable_public_badge_access
41
+ rules.concat([
42
+ [PUBLIC, READ_METHODS, PACT_BADGE_PATH],
43
+ [PUBLIC, READ_METHODS, MATRIX_BADGE_PATH],
44
+ [PUBLIC, READ_METHODS, CAN_I_DEPLOY_BADGE_PATH]
45
+ ])
46
+ end
47
+
48
+ if allow_public_access_to_heartbeat
49
+ rules.unshift([PUBLIC, READ_METHODS, HEARTBEAT_PATH])
50
+ end
51
+
52
+ if allow_public_read_access
53
+ rules.unshift([PUBLIC, READ_METHODS, ALL_PATHS])
54
+ rules.unshift([PUBLIC, [POST], PACTS_FOR_VERIFICATION_PATH])
55
+ end
56
+
57
+ ResourceAccessPolicy.new(ResourceAccessRules.new(rules))
58
+ end
59
+
60
+ private
61
+
62
+ attr_reader :resource_access_rules
63
+ end
64
+
65
+ end
66
+ end
67
+ end
68
+
@@ -0,0 +1,40 @@
1
+ require "rack"
2
+
3
+ module PactBroker
4
+ module Api
5
+ module Authorization
6
+ class ResourceAccessRules
7
+ PATH_INFO = Rack::PATH_INFO
8
+ REQUEST_METHOD = Rack::REQUEST_METHOD
9
+
10
+ def initialize(rules)
11
+ @rules = rules
12
+ end
13
+
14
+ def access_allowed?(env, level)
15
+ !!rules.find do | rule_level, allowed_methods, path_pattern |
16
+ level_allowed?(level, rule_level) &&
17
+ method_allowed?(env, allowed_methods) &&
18
+ path_allowed?(env, path_pattern)
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ attr_reader :rules
25
+
26
+ def level_allowed?(level, rule_level)
27
+ level >= rule_level
28
+ end
29
+
30
+ def path_allowed?(env, pattern)
31
+ env[PATH_INFO] =~ pattern
32
+ end
33
+
34
+ def method_allowed?(env, allowed_methods)
35
+ allowed_methods.include?(env[REQUEST_METHOD])
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -1,4 +1,5 @@
1
1
  require "pact_broker/api/decorators/base_decorator"
2
+ require "pact_broker/api/decorators/embedded_pacticipant_decorator"
2
3
  require "pact_broker/api/decorators/embedded_version_decorator"
3
4
  require "pact_broker/api/decorators/environment_decorator"
4
5
 
@@ -12,6 +13,7 @@ module PactBroker
12
13
  include Timestamps
13
14
  property :undeployedAt, getter: lambda { |_| undeployed_at ? FormatDateTime.call(undeployed_at) : nil }, writeable: false
14
15
 
16
+ property :pacticipant, :extend => EmbeddedPacticipantDecorator, writeable: false, embedded: true
15
17
  property :version, :extend => EmbeddedVersionDecorator, writeable: false, embedded: true
16
18
  property :environment, :extend => EnvironmentDecorator, writeable: false, embedded: true
17
19
 
@@ -1,4 +1,5 @@
1
1
  require "pact_broker/api/decorators/base_decorator"
2
+ require "pact_broker/api/decorators/embedded_pacticipant_decorator"
2
3
  require "pact_broker/api/decorators/embedded_version_decorator"
3
4
  require "pact_broker/api/decorators/environment_decorator"
4
5
 
@@ -11,6 +12,7 @@ module PactBroker
11
12
  include Timestamps
12
13
  property :supportEndedAt, getter: lambda { |_| support_ended_at ? FormatDateTime.call(support_ended_at) : nil }, writeable: false
13
14
 
15
+ property :pacticipant, :extend => EmbeddedPacticipantDecorator, writeable: false, embedded: true
14
16
  property :version, :extend => EmbeddedVersionDecorator, writeable: false, embedded: true
15
17
  property :environment, :extend => EnvironmentDecorator, writeable: false, embedded: true
16
18
 
@@ -0,0 +1,63 @@
1
+ require "rack"
2
+ require "pact_broker/hash_refinements"
3
+
4
+ module PactBroker
5
+ module Api
6
+ module Middleware
7
+ class BasicAuth
8
+ using PactBroker::HashRefinements
9
+
10
+ def initialize(app, write_credentials, read_credentials, policy)
11
+ @app = app
12
+ @write_credentials = write_credentials
13
+ @read_credentials = read_credentials
14
+ @app_with_write_auth = build_app_with_write_auth
15
+ @app_with_read_auth = build_app_with_read_auth
16
+ @policy = policy
17
+ end
18
+
19
+ def call(env)
20
+ if policy.public_access_allowed?(env)
21
+ app.call(env)
22
+ elsif policy.read_access_allowed?(env)
23
+ app_with_read_auth.call(env)
24
+ else
25
+ app_with_write_auth.call(env)
26
+ end
27
+ end
28
+
29
+ protected
30
+
31
+ def write_credentials_match(*credentials)
32
+ is_present?(write_credentials) && credentials == write_credentials
33
+ end
34
+
35
+ def read_credentials_match(*credentials)
36
+ is_present?(read_credentials) && credentials == read_credentials
37
+ end
38
+
39
+ private
40
+
41
+ attr_reader :app, :app_with_read_auth, :app_with_write_auth, :write_credentials, :read_credentials, :policy
42
+
43
+ def build_app_with_write_auth
44
+ this = self
45
+ Rack::Auth::Basic.new(app, "Restricted area") do |username, password|
46
+ this.write_credentials_match(username, password)
47
+ end
48
+ end
49
+
50
+ def build_app_with_read_auth
51
+ this = self
52
+ Rack::Auth::Basic.new(app, "Restricted area") do |username, password|
53
+ this.write_credentials_match(username, password) || this.read_credentials_match(username, password)
54
+ end
55
+ end
56
+
57
+ def is_present?(credentials)
58
+ !credentials.first.blank? && !credentials.last.blank?
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -3,7 +3,7 @@ require "pact_broker/api/resources/base_resource"
3
3
  require "pact_broker/api/resources/pacticipant_resource_methods"
4
4
  require "pact_broker/api/decorators/pact_decorator"
5
5
  require "pact_broker/api/decorators/extended_pact_decorator"
6
- require "pact_broker/json"
6
+ require "pact_broker/messages"
7
7
  require "pact_broker/pacts/pact_params"
8
8
  require "pact_broker/api/contracts/put_pact_params_contract"
9
9
  require "pact_broker/webhooks/execution_configuration"
@@ -17,6 +17,7 @@ module PactBroker
17
17
  include PacticipantResourceMethods
18
18
  include WebhookExecutionMethods
19
19
  include PactResourceMethods
20
+ include PactBroker::Messages
20
21
 
21
22
  def content_types_provided
22
23
  [
@@ -36,16 +37,14 @@ module PactBroker
36
37
  end
37
38
 
38
39
  def is_conflict?
39
- merge_conflict = request.patch? && resource_exists? &&
40
- Pacts::Merger.conflict?(pact.json_content, pact_params.json_content)
40
+ merge_conflict = request.patch? && resource_exists? && Pacts::Merger.conflict?(pact.json_content, pact_params.json_content)
41
41
 
42
- potential_duplicate_pacticipants?(pact_params.pacticipant_names) || merge_conflict
42
+ potential_duplicate_pacticipants?(pact_params.pacticipant_names) || merge_conflict || disallowed_modification?
43
43
  end
44
44
 
45
45
  def malformed_request?
46
46
  if request.patch? || request.put?
47
- invalid_json? ||
48
- contract_validation_errors?(Contracts::PutPactParamsContract.new(pact_params), pact_params)
47
+ invalid_json? || contract_validation_errors?(Contracts::PutPactParamsContract.new(pact_params), pact_params)
49
48
  else
50
49
  false
51
50
  end
@@ -108,6 +107,16 @@ module PactBroker
108
107
  def pact
109
108
  @pact ||= pact_service.find_pact(pact_params)
110
109
  end
110
+
111
+ def disallowed_modification?
112
+ if request.really_put? && pact_service.disallowed_modification?(pact, pact_params.json_content)
113
+ message_params = { consumer_name: pact_params.consumer_name, consumer_version_number: pact_params.consumer_version_number }
114
+ set_json_error_message(message("errors.validation.pact_content_modification_not_allowed", message_params))
115
+ true
116
+ else
117
+ false
118
+ end
119
+ end
111
120
  end
112
121
  end
113
122
  end
@@ -23,7 +23,7 @@ module PactBroker
23
23
  # Make it return a 201 by setting the Location header
24
24
  response.headers["Location"] = tag_url(base_url, tag)
25
25
  end
26
- create_deployed_version
26
+ deployed_version_service.maybe_create_deployed_version_for_tag(tag.version, identifier_from_path[:tag_name])
27
27
  response.body = to_json
28
28
  end
29
29
 
@@ -47,19 +47,6 @@ module PactBroker
47
47
  def policy_name
48
48
  :'tags::tag'
49
49
  end
50
-
51
- def create_deployed_version
52
- if create_deployed_versions_for_tags?
53
- if (environment = environment_service.find_by_name(identifier_from_path[:tag_name]))
54
- deployed_version_service.find_or_create(deployed_version_service.next_uuid, tag.version, environment, nil)
55
- end
56
- end
57
- end
58
-
59
- # Come up with a cleaner way to abstract this for PF so it can be configured per tenant
60
- def create_deployed_versions_for_tags?
61
- PactBroker.configuration.create_deployed_versions_for_tags
62
- end
63
50
  end
64
51
  end
65
52
  end
@@ -1,5 +1,11 @@
1
+ # Must be defined before loading Padrino
2
+ PADRINO_LOGGER ||= {
3
+ ENV.fetch("RACK_ENV", "production").to_sym => { log_level: :error, stream: :stdout, format_datetime: "%Y-%m-%dT%H:%M:%S.000%:z" }
4
+ }
5
+
1
6
  require "pact_broker/configuration"
2
7
  require "pact_broker/db"
8
+ require "pact_broker/initializers/database_connection"
3
9
  require "pact_broker/project_root"
4
10
  require "pact_broker/logging/default_formatter"
5
11
  require "pact_broker/policies"
@@ -19,6 +25,9 @@ require "rack/pact_broker/reset_thread_data"
19
25
  require "rack/pact_broker/add_vary_header"
20
26
  require "rack/pact_broker/use_when"
21
27
  require "sucker_punch"
28
+ require "pact_broker/api/middleware/basic_auth"
29
+ require "pact_broker/config/basic_auth_configuration"
30
+ require "pact_broker/api/authorization/resource_access_policy"
22
31
 
23
32
  module PactBroker
24
33
 
@@ -84,7 +93,6 @@ module PactBroker
84
93
  attr_reader :custom_ui, :create_pact_broker_api_block
85
94
 
86
95
  def post_configure
87
- configure_logger
88
96
  SuckerPunch.logger = configuration.custom_logger || SemanticLogger["SuckerPunch"]
89
97
  configure_database_connection
90
98
  configure_sucker_punch
@@ -117,14 +125,13 @@ module PactBroker
117
125
  end
118
126
 
119
127
  def load_configuration_from_database
120
- require "pact_broker/config/load"
121
- PactBroker::Config::Load.call(configuration)
128
+ configuration.load_from_database!
122
129
  end
123
130
 
124
131
  def configure_database_connection
125
132
  # Keep this configuration in sync with lib/db.rb
133
+ configuration.database_connection ||= PactBroker.create_database_connection(configuration.database_configuration, configuration.logger)
126
134
  PactBroker::DB.connection = configuration.database_connection
127
- PactBroker::DB.connection.timezone = :utc
128
135
  PactBroker::DB.connection.extend_datasets do
129
136
  # rubocop: disable Lint/NestedMethodDefinition
130
137
  def any?
@@ -136,7 +143,7 @@ module PactBroker
136
143
  PactBroker::DB.set_mysql_strict_mode_if_mysql
137
144
  PactBroker::DB.connection.extension(:pagination)
138
145
  PactBroker::DB.connection.extension(:statement_timeout)
139
-
146
+ PactBroker::DB.connection.timezone = :utc
140
147
  Sequel.datetime_class = DateTime
141
148
  Sequel.database_timezone = :utc # Store all dates in UTC, assume any date without a TZ is UTC
142
149
  Sequel.application_timezone = :local # Convert dates to localtime when retrieving from database
@@ -148,9 +155,8 @@ module PactBroker
148
155
  logger.info "Seeding example data"
149
156
  configuration.example_data_seeder.call
150
157
  logger.info "Marking seed as done"
151
- configuration.seed_example_data = false
152
- require "pact_broker/config/save"
153
- PactBroker::Config::Save.call(configuration, [:seed_example_data])
158
+ require "pact_broker/config/repository"
159
+ PactBroker::Config::Repository.new.create_or_update_setting(:seed_example_data, false)
154
160
  else
155
161
  logger.info "Not seeding example data"
156
162
  end
@@ -172,19 +178,8 @@ module PactBroker
172
178
  end
173
179
 
174
180
  def configure_middleware
175
- # NOTE THAT NONE OF THIS IS PROTECTED BY AUTH - is that ok?
176
- if configuration.use_rack_protection
177
- @app_builder.use Rack::Protection, except: [:path_traversal, :remote_token, :session_hijacking, :http_origin]
178
-
179
- is_hal_browser = ->(env) { env["PATH_INFO"] == "/hal-browser/browser.html" }
180
- not_hal_browser = ->(env) { env["PATH_INFO"] != "/hal-browser/browser.html" }
181
-
182
- @app_builder.use_when not_hal_browser,
183
- Rack::Protection::ContentSecurityPolicy, configuration.content_security_policy
184
- @app_builder.use_when is_hal_browser,
185
- Rack::Protection::ContentSecurityPolicy,
186
- configuration.content_security_policy.merge(configuration.hal_browser_content_security_policy_overrides)
187
- end
181
+ configure_basic_auth
182
+ configure_rack_protection
188
183
  @app_builder.use Rack::PactBroker::InvalidUriProtection
189
184
  @app_builder.use Rack::PactBroker::ResetThreadData
190
185
  @app_builder.use Rack::PactBroker::AddPactBrokerVersionHeader
@@ -203,6 +198,40 @@ module PactBroker
203
198
  end
204
199
  end
205
200
 
201
+ def configure_basic_auth
202
+ if configuration.basic_auth_enabled
203
+ logger.info "Configuring basic auth"
204
+ logger.warn "No basic auth credentials are configured" unless configuration.basic_auth_credentials_provided?
205
+ logger.info "Public read access is enabled" if configuration.allow_public_read
206
+ policy = PactBroker::Api::Authorization::ResourceAccessPolicy
207
+ .build(
208
+ configuration.allow_public_read,
209
+ configuration.public_heartbeat,
210
+ configuration.enable_public_badge_access
211
+ )
212
+
213
+ @app_builder.use PactBroker::Api::Middleware::BasicAuth,
214
+ configuration.basic_auth_write_credentials,
215
+ configuration.basic_auth_read_credentials,
216
+ policy
217
+ end
218
+ end
219
+
220
+ def configure_rack_protection
221
+ if configuration.use_rack_protection
222
+ @app_builder.use Rack::Protection, except: [:path_traversal, :remote_token, :session_hijacking, :http_origin]
223
+
224
+ is_hal_browser = ->(env) { env["PATH_INFO"] == "/hal-browser/browser.html" }
225
+ not_hal_browser = ->(env) { env["PATH_INFO"] != "/hal-browser/browser.html" }
226
+
227
+ @app_builder.use_when not_hal_browser,
228
+ Rack::Protection::ContentSecurityPolicy, configuration.content_security_policy
229
+ @app_builder.use_when is_hal_browser,
230
+ Rack::Protection::ContentSecurityPolicy,
231
+ configuration.content_security_policy.merge(configuration.hal_browser_content_security_policy_overrides)
232
+ end
233
+ end
234
+
206
235
  def build_ui
207
236
  logger.info "Mounting UI"
208
237
  require "pact_broker/ui"
@@ -242,14 +271,6 @@ module PactBroker
242
271
  end
243
272
  end
244
273
 
245
- def configure_logger
246
- if SemanticLogger.appenders.empty?
247
- path = configuration.log_dir + "/pact_broker.log"
248
- FileUtils.mkdir_p(configuration.log_dir)
249
- SemanticLogger.add_appender(file_name: path, formatter: PactBroker::Logging::DefaultFormatter.new)
250
- end
251
- end
252
-
253
274
  def running_app
254
275
  @running_app ||= begin
255
276
  prepare_app
@@ -262,7 +283,8 @@ module PactBroker
262
283
  end
263
284
 
264
285
  def print_startup_message
265
- if ENV["PACT_BROKER_HIDE_PACTFLOW_MESSAGES"] != "true"
286
+ configuration.log_configuration if configuration.log_configuration_on_startup
287
+ unless configuration.hide_pactflow_messages
266
288
  logger.info "\n\n#{'*' * 80}\n\nWant someone to manage your Pact Broker for you? Check out https://pactflow.io/oss for a hardened, fully supported SaaS version of the Pact Broker with an improved UI + more.\n\n#{'*' * 80}\n"
267
289
  end
268
290
  end