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.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +1 -1
- data/CHANGELOG.md +30 -0
- data/DEVELOPER_SETUP.md +1 -1
- data/README.md +7 -5
- data/config.ru +3 -28
- data/db/migrations/20210722_add_index_to_triggered_webhooks_webhook_uuid.rb +7 -0
- data/db/migrations/20210810_set_allow_contract_modification.rb +17 -0
- data/docs/CONFIGURATION.md +398 -0
- data/docs/configuration.yml +320 -0
- data/example/Gemfile +4 -4
- data/example/README.md +15 -22
- data/example/config.ru +1 -24
- data/example/config/pact_broker.yml +9 -0
- data/example/config/puma.rb +3 -0
- data/lib/db.rb +1 -1
- data/lib/pact_broker/api/authorization/resource_access_policy.rb +68 -0
- data/lib/pact_broker/api/authorization/resource_access_rules.rb +40 -0
- data/lib/pact_broker/api/decorators/deployed_version_decorator.rb +2 -0
- data/lib/pact_broker/api/decorators/released_version_decorator.rb +2 -0
- data/lib/pact_broker/api/middleware/basic_auth.rb +63 -0
- data/lib/pact_broker/api/resources/pact.rb +15 -6
- data/lib/pact_broker/api/resources/tag.rb +1 -14
- data/lib/pact_broker/app.rb +52 -30
- data/lib/pact_broker/config/basic_auth_configuration.rb +38 -0
- data/lib/pact_broker/config/load.rb +21 -10
- data/lib/pact_broker/config/runtime_configuration.rb +188 -0
- data/lib/pact_broker/config/runtime_configuration_coercion_methods.rb +41 -0
- data/lib/pact_broker/config/runtime_configuration_database_methods.rb +119 -0
- data/lib/pact_broker/config/runtime_configuration_logging_methods.rb +61 -0
- data/lib/pact_broker/configuration.rb +67 -131
- data/lib/pact_broker/contracts/notice.rb +4 -0
- data/lib/pact_broker/contracts/service.rb +4 -4
- data/lib/pact_broker/db/models.rb +3 -0
- data/lib/pact_broker/db/validate_encoding.rb +0 -4
- data/lib/pact_broker/deployments/deployed_version.rb +8 -2
- data/lib/pact_broker/deployments/deployed_version_service.rb +13 -6
- data/lib/pact_broker/deployments/environment.rb +1 -1
- data/lib/pact_broker/deployments/released_version.rb +8 -0
- data/lib/pact_broker/deployments/released_version_service.rb +12 -0
- data/lib/pact_broker/doc/views/provider-pacts-for-verification.markdown +4 -0
- data/lib/pact_broker/domain/pacticipant.rb +17 -13
- data/lib/pact_broker/domain/verification.rb +4 -22
- data/lib/pact_broker/domain/version.rb +9 -5
- data/lib/pact_broker/domain/webhook.rb +4 -0
- data/lib/pact_broker/error.rb +1 -0
- data/lib/pact_broker/errors.rb +1 -1
- data/lib/pact_broker/feature_toggle.rb +3 -5
- data/lib/pact_broker/hash_refinements.rb +0 -1
- data/lib/pact_broker/index/service.rb +4 -6
- data/lib/pact_broker/initializers/database_connection.rb +80 -0
- data/lib/pact_broker/integrations/integration.rb +5 -0
- data/lib/pact_broker/integrations/service.rb +4 -2
- data/lib/pact_broker/locale/en.yml +1 -0
- data/lib/pact_broker/logging.rb +2 -1
- data/lib/pact_broker/matrix/integration.rb +1 -1
- data/lib/pact_broker/matrix/parse_can_i_deploy_query.rb +2 -2
- data/lib/pact_broker/matrix/quick_row.rb +10 -0
- data/lib/pact_broker/matrix/repository.rb +64 -3
- data/lib/pact_broker/metrics/service.rb +16 -13
- data/lib/pact_broker/pacticipants/repository.rb +4 -0
- data/lib/pact_broker/pacticipants/service.rb +9 -1
- data/lib/pact_broker/pacts/pact_publication.rb +10 -13
- data/lib/pact_broker/pacts/pact_publication_dataset_module.rb +6 -1
- data/lib/pact_broker/pacts/pact_publication_selector_dataset_module.rb +1 -2
- data/lib/pact_broker/pacts/pact_version.rb +25 -11
- data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +54 -77
- data/lib/pact_broker/pacts/selected_pact.rb +1 -1
- data/lib/pact_broker/pacts/selector.rb +15 -2
- data/lib/pact_broker/pacts/selectors.rb +4 -0
- data/lib/pact_broker/pacts/service.rb +4 -0
- data/lib/pact_broker/repositories/scopes.rb +12 -1
- data/lib/pact_broker/string_refinements.rb +6 -0
- data/lib/pact_broker/tags/service.rb +8 -1
- data/lib/pact_broker/test/http_test_data_builder.rb +11 -5
- data/lib/pact_broker/ui/views/index/_css_and_js.haml +11 -9
- data/lib/pact_broker/ui/views/index/_pagination.haml +3 -1
- data/lib/pact_broker/ui/views/layouts/main.haml +5 -3
- data/lib/pact_broker/ui/views/matrix/show.haml +10 -8
- data/lib/pact_broker/verifications/required_verification.rb +28 -0
- data/lib/pact_broker/verifications/service.rb +49 -1
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/versions/repository.rb +15 -0
- data/lib/pact_broker/versions/service.rb +32 -2
- data/lib/pact_broker/webhooks/event_listener.rb +3 -0
- data/lib/pact_broker/webhooks/trigger_service.rb +30 -14
- data/lib/pact_broker/webhooks/triggered_webhook.rb +1 -0
- data/lib/pact_broker/webhooks/webhook.rb +2 -2
- data/lib/pact_broker/webhooks/webhook_event.rb +6 -1
- data/lib/semantic_logger/formatters/short.rb +29 -0
- data/pact_broker.gemspec +1 -0
- data/script/data/auto-create-things-for-tags.rb +19 -0
- data/script/data/contract-published-requiring-verification.rb +27 -0
- data/script/{reproduce-issue-expand-currently-deployed.rb → data/expand-currently-deployed.rb} +0 -0
- data/script/docs/generate-configuration-docs.rb +86 -0
- data/spec/features/get_latest_pact_badge_spec.rb +1 -0
- data/spec/features/get_matrix_badge_spec.rb +1 -0
- data/spec/features/publish_pact_spec.rb +21 -7
- data/spec/features/wip_pacts_spec.rb +1 -1
- data/spec/fixtures/approvals/matrix_integration_environment_spec.approved.json +62 -0
- data/spec/fixtures/approvals/matrix_integration_ignore_spec.approved.json +124 -0
- data/spec/fixtures/approvals/matrix_integration_spec.approved.json +173 -0
- data/spec/fixtures/approvals/publish_contract_no_branch.approved.json +9 -9
- data/spec/fixtures/approvals/publish_contract_nothing_exists.approved.json +7 -7
- data/spec/fixtures/approvals/publish_contract_nothing_exists_with_webhook.approved.json +5 -5
- data/spec/fixtures/approvals/publish_contract_verification_already_exists.approved.json +5 -5
- data/spec/lib/pact_broker/api/middleware/basic_auth_spec.rb +312 -0
- data/spec/lib/pact_broker/api/resources/tag_spec.rb +14 -39
- data/spec/lib/pact_broker/app_basic_auth_spec.rb +122 -0
- data/spec/lib/pact_broker/config/load_spec.rb +33 -6
- data/spec/lib/pact_broker/config/runtime_configuration_logging_methods_spec.rb +22 -0
- data/spec/lib/pact_broker/config/runtime_configuration_spec.rb +71 -0
- data/spec/lib/pact_broker/configuration_spec.rb +51 -25
- data/spec/lib/pact_broker/errors/error_logger_spec.rb +3 -0
- data/spec/lib/pact_broker/feature_toggle_spec.rb +18 -19
- data/spec/lib/pact_broker/matrix/integration_environment_spec.rb +12 -0
- data/spec/lib/pact_broker/matrix/integration_ignore_spec.rb +15 -3
- data/spec/lib/pact_broker/matrix/integration_spec.rb +47 -6
- data/spec/lib/pact_broker/matrix/parse_can_i_deploy_query_spec.rb +16 -1
- data/spec/lib/pact_broker/matrix/repository_dependency_spec.rb +0 -2
- data/spec/lib/pact_broker/matrix/repository_spec.rb +0 -2
- data/spec/lib/pact_broker/metrics/service_spec.rb +44 -0
- data/spec/lib/pact_broker/pacticipants/service_spec.rb +28 -5
- data/spec/lib/pact_broker/pacts/pact_publication_selector_dataset_module_spec.rb +25 -0
- data/spec/lib/pact_broker/pacts/pact_version_spec.rb +30 -1
- data/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb +107 -20
- data/spec/lib/pact_broker/pacts/verifiable_pact_messages_spec.rb +1 -1
- data/spec/lib/pact_broker/tags/service_spec.rb +24 -8
- data/spec/lib/pact_broker/verifications/service_spec.rb +146 -0
- data/spec/lib/pact_broker/versions/repository_spec.rb +38 -2
- data/spec/lib/pact_broker/versions/service_spec.rb +93 -2
- data/spec/lib/pact_broker/webhooks/trigger_service_spec.rb +54 -2
- data/spec/lib/rack/pact_broker/invalid_uri_protection_spec.rb +3 -3
- data/spec/spec_helper.rb +2 -1
- data/spec/support/approvals.rb +29 -0
- metadata +52 -13
- data/example/basic_auth/Gemfile +0 -5
- data/example/basic_auth/Procfile +0 -1
- data/example/basic_auth/README.md +0 -43
- data/example/basic_auth/config.ru +0 -19
- data/example/example_data.sql +0 -19
- data/spec/lib/pact_broker/config/save_and_load_spec.rb +0 -25
- 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/
|
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
|
-
|
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
|
data/lib/pact_broker/app.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
152
|
-
|
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
|
-
|
176
|
-
|
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
|
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
|