defra_ruby_mocks 4.0.0 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c648dae3e678030c2d132615c0d148b673bedacde6d9d0e653dd2f20710fe4f9
4
- data.tar.gz: '0948298e72ee7c2adb8e5cd98ff71eaf0f72de6fe9a9faf0aa0e6ae1e3699c3b'
3
+ metadata.gz: fbc211a8e66923ea6517dd55d0f327c43b8b67e74981e8e49600a46eeb5ddd80
4
+ data.tar.gz: e28bfc2b91cfac3f76e8cf19dcee4cb00a2eb6e598826663f60d7e1ece4d2902
5
5
  SHA512:
6
- metadata.gz: 1cdb1d9e9b0f434ef1b7bcc58de8f5ec79c07bb10621772cd705ef33bad0a66a7767b764df299a8b506af750b296429b814a5b4575385b66d08cf8f985853778
7
- data.tar.gz: 4ca9a9935239757a5af2874392c85de2df9e9a1c93ee504610a8430b6179004de218b2ef9fb06ef20ffdc4e9edcc1f0d812d9ee14ed06a024ed14c46279dd50c
6
+ metadata.gz: b80a0af3f9ddd3711de5cac260152d2d7f503b74aece65788f6d96a805638501cb662ecec5a5c3572555a7972ab376ebf866b986ec1b56d8737763e6b571991e
7
+ data.tar.gz: c2036eb0aa7586a4d41c61ae7575b626f328e7900b5bc1318ea8c1c8b8648c84aab82d2826b8d29e81b7e75dca3ff6f67b07a90411bd7eb3cfcbe3b3cc98abc9
data/README.md CHANGED
@@ -178,7 +178,7 @@ In order to use the govpay mock you'll need to provide additional configuration
178
178
  require "defra_ruby_mocks"
179
179
 
180
180
  DefraRubyMocks.configure do |config|
181
- config.govpay_domain = File.join(ENV["WCRS_GOVPAY_DOMAIN"] || "http://localhost:3002", "/fo/mocks/govpay/v1")
181
+ config.govpay_domain = File.join(ENV["WCRS_GOVPAY_MOCK_DOMAIN"] || "http://localhost:3002", "/fo/mocks/govpay/v1")
182
182
  end
183
183
  ```
184
184
 
@@ -8,17 +8,30 @@ module DefraRubyMocks
8
8
  def create_payment
9
9
  valid_create_params
10
10
 
11
- # Enqueue the payment callback to run after the controller responds
12
- DefraRubyMocks::GovpayPaymentCallbackJob.perform_later(params[:return_url])
11
+ store_return_url(params[:return_url])
13
12
 
14
13
  render json: GovpayCreatePaymentService.new.run(
15
- amount: params[:amount], description: params[:description], return_url: params[:return_url]
14
+ amount: params[:amount], description: params[:description]
16
15
  )
17
16
  rescue StandardError => e
18
17
  Rails.logger.error("MOCKS: Govpay payment creation error: #{e.message}")
19
18
  head 500
20
19
  end
21
20
 
21
+ # This mocks the Govpay route which presents the payment details page to the user.
22
+ # We don't mock the actual payment details and payment confirmation pages - we go
23
+ # straight to the application callback route.
24
+ def next_url
25
+ response_url = retrieve_return_url
26
+ Rails.logger.warn "Govpay mock calling response URL #{response_url}"
27
+ redirect_to response_url, allow_other_host: true
28
+ rescue RestClient::ExceptionWithResponse => e
29
+ Rails.logger.warn "Govpay mock: RestClient received response: #{e}"
30
+ rescue StandardError => e
31
+ Rails.logger.error("Govpay mock: Error sending request to govpay: #{e}")
32
+ Airbrake.notify(e, message: "Error on govpay request")
33
+ end
34
+
22
35
  def payment_details
23
36
  valid_payment_id
24
37
  render json: GovpayGetPaymentService.new.run(payment_id: params[:payment_id])
@@ -44,6 +57,27 @@ module DefraRubyMocks
44
57
  head 500
45
58
  end
46
59
 
60
+ private
61
+
62
+ def s3_bucket_name
63
+ @s3_bucket_name = ENV.fetch("GOVPAY_MOCKS_BUCKET", "defra-ruby-mocks-s3bkt001")
64
+ end
65
+
66
+ def return_url_file_name
67
+ @return_url_file_name = "return_url_file"
68
+ end
69
+
70
+ # We need to persist the return_url between the initial payment creation request and the execution of next_url.
71
+ # We can't use tmp for multi-server environments so we load the temp file to AWS S3.
72
+ def store_return_url(return_url)
73
+ Rails.logger.warn ":::::: storing return_url #{return_url}"
74
+ AwsBucketService.write(s3_bucket_name, return_url_file_name, return_url)
75
+ end
76
+
77
+ def retrieve_return_url
78
+ AwsBucketService.read(s3_bucket_name, return_url_file_name)
79
+ end
80
+
47
81
  def valid_create_params
48
82
  params.require(%i[amount description return_url])
49
83
  end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DefraRubyMocks
4
+ class AwsBucketService
5
+
6
+ attr_accessor :bucket_name, :file_name
7
+
8
+ def self.write(bucket_name, file_name, content)
9
+ new.write(bucket_name, file_name, content)
10
+ end
11
+
12
+ def self.read(bucket_name, file_name)
13
+ new.read(bucket_name, file_name)
14
+ end
15
+
16
+ def write(bucket_name, file_name, content)
17
+ @bucket_name = bucket_name
18
+ @file_name = file_name
19
+
20
+ write_temp_file(content)
21
+
22
+ load_temp_file_to_s3
23
+
24
+ true
25
+ end
26
+
27
+ def read(bucket_name, file_name)
28
+ Rails.logger.warn ":::::: reading from S3"
29
+
30
+ s3 = Aws::S3::Client.new
31
+ s3.get_object(bucket: bucket_name, key: file_name)
32
+ rescue Aws::S3::NoSuchBucket => e
33
+ raise StandardError, e
34
+ end
35
+
36
+ private
37
+
38
+ def temp_filepath
39
+ "#{Dir.tmpdir}/#{file_name}"
40
+ end
41
+
42
+ def write_temp_file(content)
43
+ Rails.logger.warn ":::::: creating temp file for #{content}"
44
+ File.write(temp_filepath, content)
45
+ end
46
+
47
+ def load_temp_file_to_s3
48
+ Rails.logger.warn ":::::: loading temp file to S3"
49
+
50
+ result = nil
51
+
52
+ 3.times do
53
+ result = bucket.load(File.new(temp_filepath, "r"))
54
+
55
+ break if result.successful?
56
+ end
57
+
58
+ raise(result&.error) unless result&.successful?
59
+ end
60
+
61
+ def bucket
62
+ @bucket ||= DefraRuby::Aws.get_bucket(bucket_name)
63
+ end
64
+ end
65
+ end
@@ -5,12 +5,12 @@ require "securerandom"
5
5
  module DefraRubyMocks
6
6
  class GovpayCreatePaymentService < BaseService
7
7
 
8
- def run(amount:, description:, return_url:)
8
+ def run(amount:, description:)
9
9
  success_response.merge(
10
10
  {
11
11
  _links: {
12
12
  self: { href: "#{base_url}/#{payment_id}", method: "GET" },
13
- next_url: { href: return_url, method: "GET" }
13
+ next_url: { href: "#{base_url}/secure/next-url-uuid-abc123", method: "GET" }
14
14
  },
15
15
  amount: amount.to_i,
16
16
  description: description,
@@ -3,6 +3,8 @@
3
3
  module DefraRubyMocks
4
4
  class GovpayRefundDetailsService < BaseService
5
5
 
6
+ DEFAULT_LAST_REFUND_REQUEST_TIME = 1.day.ago.freeze
7
+
6
8
  def run(payment_id:, refund_id:) # rubocop:disable Lint/UnusedMethodArgument
7
9
  {
8
10
  amount: 2000,
@@ -19,24 +21,37 @@ module DefraRubyMocks
19
21
 
20
22
  # "submitted" for up to GOVPAY_REFUND_SUBMITTED_SUCCESS_LAG seconds after the last refund request, then "success"
21
23
  def status
22
- timestamp = File.read("#{Dir.tmpdir}/govpay_request_refund_service_last_run_time")
23
- last_refund_time = timestamp ? Time.parse(timestamp) : 1.day.ago
24
+ last_refund_time = refund_request_timestamp
24
25
  submitted_success_lag = ENV.fetch("GOVPAY_REFUND_SUBMITTED_SUCCESS_LAG", 0).to_i
25
26
  cutoff_time = (last_refund_time + submitted_success_lag.seconds).to_time
26
27
  return "success" if submitted_success_lag.zero?
27
28
 
28
29
  Time.zone.now < cutoff_time ? "submitted" : "success"
29
30
  rescue Errno::ENOENT
30
- write_timestamp_file("govpay_request_refund_service_last_run_time")
31
+ write_timestamp_file
31
32
 
32
33
  "success"
33
34
  end
34
35
 
35
- def write_timestamp_file(filename)
36
- filepath = "#{Dir.tmpdir}/#{filename}"
36
+ def write_timestamp_file
37
+ timestamp = Time.zone.now
38
+ Rails.logger.warn ":::::: writing timestamp file: #{timestamp}"
39
+ AwsBucketService.write(s3_bucket_name, timestamp_file_name, timestamp)
40
+ end
41
+
42
+ def s3_bucket_name
43
+ @s3_bucket_name = ENV.fetch("GOVPAY_MOCKS_BUCKET", "defra-ruby-mocks-s3bkt001")
44
+ end
45
+
46
+ def timestamp_file_name
47
+ @govpay_request_refund_service_last_run_time = "govpay_request_refund_service_last_run_time"
48
+ end
37
49
 
38
- # FileUtils.touch seems unreliable in VM so need to write/read the actual time
39
- File.write(filepath, Time.zone.now)
50
+ def refund_request_timestamp
51
+ timestamp = AwsBucketService.read(s3_bucket_name, timestamp_file_name)
52
+ timestamp ? Time.parse(timestamp) : DEFAULT_LAST_REFUND_REQUEST_TIME
53
+ rescue StandardError
54
+ DEFAULT_LAST_REFUND_REQUEST_TIME
40
55
  end
41
56
 
42
57
  end
@@ -19,9 +19,16 @@ module DefraRubyMocks
19
19
 
20
20
  # let the refund details service know how long since the refund was requested
21
21
  def write_timestamp
22
- filepath = "#{Dir.tmpdir}/govpay_request_refund_service_last_run_time"
23
- # FileUtils.touch seems unreliable in VM so need to write/read the actual time
24
- File.write(filepath, Time.zone.now)
22
+ Rails.logger.warn ":::::: storing refund request timestamp"
23
+ AwsBucketService.write(s3_bucket_name, timestamp_file_name, Time.zone.now.to_s)
24
+ end
25
+
26
+ def s3_bucket_name
27
+ @s3_bucket_name = ENV.fetch("GOVPAY_MOCKS_BUCKET", "defra-ruby-mocks-s3bkt001")
28
+ end
29
+
30
+ def timestamp_file_name
31
+ @timestamp_file_name = "govpay_request_refund_service_last_run_time"
25
32
  end
26
33
  end
27
34
  end
data/config/routes.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- DefraRubyMocks::Engine.routes.draw do
3
+ DefraRubyMocks::Engine.routes.draw do # rubocop:disable Metrics/BlockLength
4
4
  get "/company/:id",
5
5
  to: "company#show",
6
6
  as: "company",
@@ -16,6 +16,11 @@ DefraRubyMocks::Engine.routes.draw do
16
16
  as: "govpay_create_payment",
17
17
  constraints: ->(_request) { DefraRubyMocks.configuration.enabled? }
18
18
 
19
+ get "/govpay/v1/payments/secure/:uuid",
20
+ to: "govpay#next_url",
21
+ as: "govpay_next_url",
22
+ constraints: ->(_request) { DefraRubyMocks.configuration.enabled? }
23
+
19
24
  get "/govpay/v1/payments/:payment_id",
20
25
  to: "govpay#payment_details",
21
26
  as: "govpay_payment_details",
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DefraRubyMocks
4
- VERSION = "4.0.0"
4
+ VERSION = "4.2.0"
5
5
  end
@@ -12,12 +12,6 @@ module DefraRubyMocks
12
12
  def configuration
13
13
  @configuration ||= Configuration.new
14
14
  end
15
-
16
- # Added for testing. Without we cannot test both a config object with and
17
- # with set values in the same rspec session
18
- def reset_configuration
19
- @configuration = nil
20
- end
21
15
  end
22
16
 
23
17
  def self.configure
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: defra_ruby_mocks
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0
4
+ version: 4.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Defra
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-10-05 00:00:00.000000000 Z
11
+ date: 2024-05-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -28,30 +28,44 @@ dependencies:
28
28
  name: sprockets
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '4.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '4.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: sprockets-rails
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: '3.0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: defra_ruby_aws
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.5'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
53
67
  - !ruby/object:Gem::Version
54
- version: '0'
68
+ version: '0.5'
55
69
  description: A Rails engine which can be used to mock external services when loaded
56
70
  into an application
57
71
  email:
@@ -66,8 +80,7 @@ files:
66
80
  - app/controllers/defra_ruby_mocks/application_controller.rb
67
81
  - app/controllers/defra_ruby_mocks/company_controller.rb
68
82
  - app/controllers/defra_ruby_mocks/govpay_controller.rb
69
- - app/jobs/defra_ruby_mocks/application_job.rb
70
- - app/jobs/defra_ruby_mocks/govpay_payment_callback_job.rb
83
+ - app/services/defra_ruby_mocks/aws_bucket_service.rb
71
84
  - app/services/defra_ruby_mocks/base_service.rb
72
85
  - app/services/defra_ruby_mocks/companies_house_service.rb
73
86
  - app/services/defra_ruby_mocks/govpay_create_payment_service.rb
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DefraRubyMocks
4
- class ApplicationJob < ActiveJob::Base
5
- end
6
- end
@@ -1,17 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module DefraRubyMocks
4
- class GovpayPaymentCallbackJob < DefraRubyMocks::ApplicationJob
5
- queue_as :default
6
-
7
- def perform(*response_url)
8
- Rails.logger.debug "GovpayPaymentCallbackJob calling response URL #{response_url}"
9
- RestClient::Request.execute(method: :GET, url: response_url[0])
10
- rescue RestClient::ExceptionWithResponse => e
11
- Rails.logger.debug "GovpayPaymentCallbackJob: RestClient received response: #{e}"
12
- rescue StandardError => e
13
- Rails.logger.error("GovpayPaymentCallbackJob: Error sending request to govpay: #{e}")
14
- Airbrake.notify(e, message: "Error on govpay request")
15
- end
16
- end
17
- end