forest_liana 6.0.0.pre.beta.3 → 6.0.3

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 (32) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/forest_liana/actions_controller.rb +12 -2
  3. data/app/controllers/forest_liana/authentication_controller.rb +5 -21
  4. data/app/serializers/forest_liana/stripe_invoice_serializer.rb +5 -5
  5. data/app/services/forest_liana/authentication.rb +0 -2
  6. data/app/services/forest_liana/authorization_getter.rb +23 -21
  7. data/app/services/forest_liana/oidc_client_manager.rb +9 -5
  8. data/app/services/forest_liana/resource_creator.rb +1 -1
  9. data/app/services/forest_liana/resource_updater.rb +3 -3
  10. data/app/services/forest_liana/schema_utils.rb +8 -3
  11. data/app/services/forest_liana/stripe_invoice_getter.rb +1 -1
  12. data/app/services/forest_liana/stripe_invoices_getter.rb +1 -1
  13. data/app/services/forest_liana/stripe_source_getter.rb +1 -1
  14. data/app/services/forest_liana/stripe_sources_getter.rb +1 -1
  15. data/config/initializers/error-messages.rb +3 -0
  16. data/config/initializers/errors.rb +21 -2
  17. data/config/routes.rb +0 -4
  18. data/lib/forest_liana.rb +1 -0
  19. data/lib/forest_liana/bootstrapper.rb +12 -5
  20. data/lib/forest_liana/version.rb +1 -1
  21. data/lib/generators/forest_liana/install_generator.rb +13 -5
  22. data/spec/requests/actions_controller_spec.rb +49 -1
  23. data/spec/requests/authentications_spec.rb +7 -20
  24. data/test/routing/route_test.rb +0 -12
  25. data/test/services/forest_liana/resources_getter_test.rb +1 -1
  26. metadata +119 -154
  27. data/app/controllers/forest_liana/sessions_controller.rb +0 -95
  28. data/app/serializers/forest_liana/session_serializer.rb +0 -33
  29. data/app/services/forest_liana/login_handler.rb +0 -99
  30. data/app/services/forest_liana/two_factor_registration_confirmer.rb +0 -36
  31. data/app/services/forest_liana/user_secret_creator.rb +0 -26
  32. data/spec/requests/sessions_spec.rb +0 -53
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3ea2912357a0fabb3b4c6527d848f9b728d2394c83155cd77314e54f66c1d8e2
4
- data.tar.gz: 69863c89f2668cb142f54ddc5a9fcc1c473417cef56fc307765e53a686572bd3
3
+ metadata.gz: 36413dbeacb065c65d37e3ac8b051c2f342d03f8deec1ebf8c4caf9b894f8838
4
+ data.tar.gz: d58009364bb2fa0bef186b2afeaee10242e26538926c98ae807286f21623dc79
5
5
  SHA512:
6
- metadata.gz: 11e36ad5a50676182d85029fe634e2874328c537bff2679e5a99661393e5d23c84fa3e30c165c376c06c0e8bc013beffc8d0b2497408276322a0811de8fbf222
7
- data.tar.gz: 3bb4aec7204cced667652ac92f1aef9e4897d282a578408603c2fd98b7b37079565ea39d58ef1d26ee4f62af545c41bd2e56666df4d0335f7b53a455c705f17a
6
+ metadata.gz: 4f0c61d238def23ff9fb17c5974238ea13a06cde678bec2c1937d590d13fe9a603ec32448c2fb433b0696436b038c21a47041f25491ec9954ff03f90f22bc068
7
+ data.tar.gz: 30dfc0f2f7b564e0581bb85fe0211457bf835ce0125c70de27c12ae5483cb26c40b828fd724ec9315a1b2564f0b6f509b59d56f1f42075029ec7fd1380b36db5
@@ -55,10 +55,20 @@ module ForestLiana
55
55
  # Apply result on fields (transform the object back to an array), preserve order.
56
56
  fields = action.fields.map do |field|
57
57
  updated_field = result[field[:field]]
58
+
58
59
  # Reset `value` when not present in `enums` (which means `enums` has changed).
59
- if updated_field[:enums].is_a?(Array) && !updated_field[:enums].include?(updated_field[:value])
60
- updated_field[:value] = nil
60
+ if updated_field[:enums].is_a?(Array)
61
+ # `value` can be an array if the type of fields is `[x]`
62
+ if updated_field[:type].is_a?(Array) && updated_field[:value].is_a?(Array) && !(updated_field[:value] - updated_field[:enums]).empty?
63
+ updated_field[:value] = nil
64
+ end
65
+
66
+ # `value` can be any other value
67
+ if !updated_field[:type].is_a?(Array) && !updated_field[:enums].include?(updated_field[:value])
68
+ updated_field[:value] = nil
69
+ end
61
70
  end
71
+
62
72
  updated_field
63
73
  end
64
74
 
@@ -46,7 +46,7 @@ module ForestLiana
46
46
  { 'renderingId' => rendering_id },
47
47
  )
48
48
 
49
- redirect_to(result['authorization_url'])
49
+ render json: { authorizationUrl: result['authorization_url']}, status: 200
50
50
  rescue => error
51
51
  render json: { errors: [{ status: 500, detail: error.message }] },
52
52
  status: :internal_server_error, serializer: nil
@@ -61,33 +61,17 @@ module ForestLiana
61
61
  callback_url,
62
62
  params,
63
63
  )
64
-
65
- response.set_cookie(
66
- 'forest_session_token',
67
- {
68
- value: token,
69
- httponly: true,
70
- secure: true,
71
- expires: ForestLiana::Token.expiration_in_days,
72
- samesite: 'none',
73
- path: '/'
74
- },
75
- )
76
64
 
77
65
  response_body = {
66
+ token: token,
78
67
  tokenData: JWT.decode(token, ForestLiana.auth_secret, true, { algorithm: 'HS256' })[0]
79
68
  }
80
69
 
81
- # The token is sent decoded, because we don't want to share the whole, signed token
82
- # that is used to authenticate people
83
- # but the token itself contains interesting values, such as its expiration date
84
- response_body[:token] = token if !ForestLiana.application_url.start_with?('https://')
85
-
86
70
  render json: response_body, status: 200
87
71
 
88
72
  rescue => error
89
- render json: { errors: [{ status: 500, detail: error.message }] },
90
- status: :internal_server_error, serializer: nil
73
+ render json: { errors: [{ status: error.try(:error_code) || 500, detail: error.message }] },
74
+ status: error.status || :internal_server_error, serializer: nil
91
75
  end
92
76
  end
93
77
 
@@ -104,7 +88,7 @@ module ForestLiana
104
88
  httponly: true,
105
89
  secure: true,
106
90
  expires: Time.at(0),
107
- samesite: 'none',
91
+ same_site: :None,
108
92
  path: '/'
109
93
  },
110
94
  )
@@ -3,20 +3,20 @@ module ForestLiana
3
3
  include JSONAPI::Serializer
4
4
 
5
5
  attribute :amount_due
6
+ attribute :amount_paid
7
+ attribute :amount_remaining
8
+ attribute :application_fee_amount
6
9
  attribute :attempt_count
7
10
  attribute :attempted
8
- attribute :closed
9
11
  attribute :currency
10
- attribute :date
11
- attribute :forgiven
12
+ attribute :due_date
12
13
  attribute :paid
13
14
  attribute :period_end
14
15
  attribute :period_start
16
+ attribute :status
15
17
  attribute :subtotal
16
18
  attribute :total
17
- attribute :application_fee
18
19
  attribute :tax
19
- attribute :tax_percent
20
20
 
21
21
  has_one :customer
22
22
 
@@ -26,9 +26,7 @@ module ForestLiana
26
26
 
27
27
  user = ForestLiana::AuthorizationGetter.authenticate(
28
28
  rendering_id,
29
- true,
30
29
  { :forest_token => access_token_instance.instance_variable_get(:@access_token) },
31
- nil,
32
30
  )
33
31
 
34
32
  return ForestLiana::Token.create_token(user, rendering_id)
@@ -1,23 +1,12 @@
1
1
  module ForestLiana
2
2
  class AuthorizationGetter
3
- def self.authenticate(rendering_id, use_google_authentication, auth_data, two_factor_registration)
3
+ def self.authenticate(rendering_id, auth_data)
4
4
  begin
5
5
  route = "/liana/v2/renderings/#{rendering_id.to_s}/authorization"
6
-
7
- if !use_google_authentication.nil?
8
- headers = { 'forest-token' => auth_data[:forest_token] }
9
- elsif !auth_data[:email].nil?
10
- headers = { 'email' => auth_data[:email], 'password' => auth_data[:password] }
11
- end
12
-
13
- query_parameters = {}
14
-
15
- unless two_factor_registration.nil?
16
- query_parameters['two-factor-registration'] = true
17
- end
6
+ headers = { 'forest-token' => auth_data[:forest_token] }
18
7
 
19
8
  response = ForestLiana::ForestApiRequester
20
- .get(route, query: query_parameters, headers: headers)
9
+ .get(route, query: {}, headers: headers)
21
10
 
22
11
  if response.code.to_i == 200
23
12
  body = JSON.parse(response.body, :symbolize_names => false)
@@ -25,15 +14,28 @@ module ForestLiana
25
14
  user['id'] = body['data']['id']
26
15
  user
27
16
  else
28
- unless use_google_authentication.nil?
29
- raise "Cannot authorize the user using this google account. Forest API returned an #{Errors::HTTPErrorHelper.format(response)}"
30
- else
31
- raise "Cannot authorize the user using this email/password. Forest API returned an #{Errors::HTTPErrorHelper.format(response)}"
32
- end
17
+ raise generate_authentication_error response
33
18
  end
34
- rescue
35
- raise ForestLiana::Errors::HTTP401Error
36
19
  end
37
20
  end
21
+
22
+ private
23
+ def self.generate_authentication_error(error)
24
+ case error[:message]
25
+ when ForestLiana::MESSAGES[:SERVER_TRANSACTION][:SECRET_AND_RENDERINGID_INCONSISTENT]
26
+ return ForestLiana::Errors::InconsistentSecretAndRenderingError.new()
27
+ when ForestLiana::MESSAGES[:SERVER_TRANSACTION][:SECRET_NOT_FOUND]
28
+ return ForestLiana::Errors::SecretNotFoundError.new()
29
+ else
30
+ end
31
+
32
+ serverError = error[:jse_cause][:response][:body][:errors][0] || nil
33
+
34
+ if !serverError.nil? && serverError[:name] == ForestLiana::MESSAGES[:SERVER_TRANSACTION][:names][:TWO_FACTOR_AUTHENTICATION_REQUIRED]
35
+ return ForestLiana::Errors::TwoFactorAuthenticationRequiredError.new()
36
+ end
37
+
38
+ return StandardError.new(error)
39
+ end
38
40
  end
39
41
  end
@@ -8,11 +8,15 @@ module ForestLiana
8
8
  if client_data.nil?
9
9
  configuration = ForestLiana::OidcConfigurationRetriever.retrieve()
10
10
 
11
- client_credentials = ForestLiana::OidcDynamicClientRegistrator.register({
12
- token_endpoint_auth_method: 'none',
13
- redirect_uris: [callback_url],
14
- registration_endpoint: configuration['registration_endpoint']
15
- })
11
+ if ForestLiana.forest_client_id.nil?
12
+ client_credentials = ForestLiana::OidcDynamicClientRegistrator.register({
13
+ token_endpoint_auth_method: 'none',
14
+ redirect_uris: [callback_url],
15
+ registration_endpoint: configuration['registration_endpoint']
16
+ })
17
+ else
18
+ client_credentials = { 'client_id' => ForestLiana.forest_client_id }
19
+ end
16
20
 
17
21
  client_data = { :client_id => client_credentials['client_id'], :issuer => configuration['issuer'] }
18
22
  Rails.cache.write(callback_url, client_data)
@@ -53,7 +53,7 @@ module ForestLiana
53
53
  end
54
54
 
55
55
  def has_strong_parameter
56
- Rails::VERSION::MAJOR > 5 || @resource.instance_method(:update_attributes!).arity == 1
56
+ Rails::VERSION::MAJOR > 5 || @resource.instance_method(:update!).arity == 1
57
57
  end
58
58
  end
59
59
  end
@@ -14,9 +14,9 @@ module ForestLiana
14
14
  @record = @resource.find(@params[:id])
15
15
 
16
16
  if has_strong_parameter
17
- @record.update_attributes(resource_params)
17
+ @record.update(resource_params)
18
18
  else
19
- @record.update_attributes(resource_params, without_protection: true)
19
+ @record.update(resource_params, without_protection: true)
20
20
  end
21
21
  rescue ActiveRecord::StatementInvalid => exception
22
22
  # NOTICE: SQL request cannot be executed properly
@@ -33,7 +33,7 @@ module ForestLiana
33
33
  end
34
34
 
35
35
  def has_strong_parameter
36
- Rails::VERSION::MAJOR > 5 || @resource.instance_method(:update_attributes!).arity == 1
36
+ Rails::VERSION::MAJOR > 5 || @resource.instance_method(:update!).arity == 1
37
37
  end
38
38
  end
39
39
  end
@@ -2,9 +2,14 @@ module ForestLiana
2
2
  class SchemaUtils
3
3
 
4
4
  def self.associations(active_record_class)
5
- active_record_class
6
- .reflect_on_all_associations
7
- .select { |association| !polymorphic?(association) && !is_active_type?(association.klass) }
5
+ active_record_class.reflect_on_all_associations.select do |association|
6
+ begin
7
+ !polymorphic?(association) && !is_active_type?(association.klass)
8
+ rescue
9
+ FOREST_LOGGER.warn "Unknown association #{association.name} on class #{active_record_class.name}"
10
+ false
11
+ end
12
+ end
8
13
  end
9
14
 
10
15
  def self.one_associations(active_record_class)
@@ -11,7 +11,7 @@ module ForestLiana
11
11
  query = {}
12
12
  @record = ::Stripe::Invoice.retrieve(@params[:invoice_id])
13
13
 
14
- @record.date = Time.at(@record.date).to_datetime
14
+ @record.due_date = Time.at(@record.due_date).to_datetime unless @record.due_date.nil?
15
15
  @record.period_start = Time.at(@record.period_start).to_datetime
16
16
  @record.period_end = Time.at(@record.period_end).to_datetime
17
17
  @record.subtotal /= 100.00
@@ -32,7 +32,7 @@ module ForestLiana
32
32
  end
33
33
 
34
34
  @records = @invoices.data.map do |d|
35
- d.date = Time.at(d.date).to_datetime
35
+ d.date = Time.at(d.created).to_datetime
36
36
  d.period_start = Time.at(d.period_start).to_datetime
37
37
  d.period_end = Time.at(d.period_end).to_datetime
38
38
  d.subtotal /= 100.00
@@ -12,7 +12,7 @@ module ForestLiana
12
12
  customer = resource[field]
13
13
 
14
14
  @record = ::Stripe::Customer
15
- .retrieve(customer)
15
+ .retrieve({ id: customer, expand: ['sources'] })
16
16
  .sources.retrieve(@params[:objectId])
17
17
 
18
18
  query = {}
@@ -32,7 +32,7 @@ module ForestLiana
32
32
 
33
33
  def fetch_bank_accounts(customer, params)
34
34
  begin
35
- @cards = ::Stripe::Customer.retrieve(customer).sources.list(params)
35
+ @cards = ::Stripe::Customer.retrieve({ id: customer, expand: ['sources'] }).sources.list(params)
36
36
  if @cards.blank?
37
37
  @records = []
38
38
  return
@@ -15,6 +15,9 @@ module ForestLiana
15
15
  INVALID_RENDERING_ID: "The parameter renderingId is not valid",
16
16
  REGISTRATION_FAILED: "The registration to the authentication API failed, response: ",
17
17
  OIDC_CONFIGURATION_RETRIEVAL_FAILED: "Failed to retrieve the provider's configuration.",
18
+ names: {
19
+ TWO_FACTOR_AUTHENTICATION_REQUIRED: 'TwoFactorAuthenticationRequiredForbiddenError',
20
+ }
18
21
  }
19
22
  }
20
23
  end
@@ -14,12 +14,13 @@ module ForestLiana
14
14
  end
15
15
 
16
16
  class ExpectedError < StandardError
17
- attr_reader :error_code, :status, :message
17
+ attr_reader :error_code, :status, :message, :name
18
18
 
19
- def initialize(error_code, status, message)
19
+ def initialize(error_code, status, message, name = nil)
20
20
  @error_code = error_code
21
21
  @status = status
22
22
  @message = message
23
+ @name = name
23
24
  end
24
25
 
25
26
  def display_error
@@ -45,6 +46,24 @@ module ForestLiana
45
46
  end
46
47
  end
47
48
 
49
+ class InconsistentSecretAndRenderingError < ExpectedError
50
+ def initialize(message=ForestLiana::MESSAGES[:SERVER_TRANSACTION][:SECRET_AND_RENDERINGID_INCONSISTENT])
51
+ super(500, :internal_server_error, message, 'InconsistentSecretAndRenderingError')
52
+ end
53
+ end
54
+
55
+ class SecretNotFoundError < ExpectedError
56
+ def initialize(message=ForestLiana::MESSAGES[:SERVER_TRANSACTION][:SECRET_NOT_FOUND])
57
+ super(500, :internal_server_error, message, 'SecretNotFoundError')
58
+ end
59
+ end
60
+
61
+ class TwoFactorAuthenticationRequiredError < ExpectedError
62
+ def initialize(message='Two factor authentication required')
63
+ super(403, :forbidden, message, 'TwoFactorAuthenticationRequiredError')
64
+ end
65
+ end
66
+
48
67
  class ExceptionHelper
49
68
  def self.recursively_print(error, margin: '', is_error: false)
50
69
  logger = is_error ?
data/config/routes.rb CHANGED
@@ -9,10 +9,6 @@ ForestLiana::Engine.routes.draw do
9
9
  get 'authentication/callback' => 'authentication#authentication_callback'
10
10
  post 'authentication/logout' => 'authentication#logout'
11
11
 
12
- # Session
13
- post 'sessions' => 'sessions#create_with_password'
14
- post 'sessions-google' => 'sessions#create_with_google'
15
-
16
12
  # Associations
17
13
  get ':collection/:id/relationships/:association_name' => 'associations#index'
18
14
  get ':collection/:id/relationships/:association_name/count' => 'associations#count'
data/lib/forest_liana.rb CHANGED
@@ -16,6 +16,7 @@ module ForestLiana
16
16
 
17
17
  mattr_accessor :env_secret
18
18
  mattr_accessor :auth_secret
19
+ mattr_accessor :forest_client_id
19
20
  mattr_accessor :application_url
20
21
  mattr_accessor :integrations
21
22
  mattr_accessor :apimap
@@ -18,6 +18,13 @@ module ForestLiana
18
18
  ForestLiana.auth_secret = ForestLiana.auth_key
19
19
  end
20
20
 
21
+ unless Rails.application.config.action_controller.perform_caching || Rails.env.test? || ForestLiana.forest_client_id
22
+ FOREST_LOGGER.error "You need to enable caching on your environment to use Forest Admin.\n" \
23
+ "For a development environment, run: `rails dev:cache`\n" \
24
+ "Or setup a static forest_client_id by following this part of the documentation:\n" \
25
+ "https://docs.forestadmin.com/documentation/how-tos/maintain/upgrade-notes-rails/upgrade-to-v6#setup-a-static-clientid"
26
+ end
27
+
21
28
  fetch_models
22
29
  check_integrations_setup
23
30
  namespace_duplicated_models
@@ -430,19 +437,19 @@ module ForestLiana
430
437
  fields: [
431
438
  { field: :id, type: 'String', is_filterable: false },
432
439
  { field: :amount_due, type: 'Number', is_filterable: false },
440
+ { field: :amount_paid, type: 'Number', is_filterable: false },
441
+ { field: :amount_remaining, type: 'Number', is_filterable: false },
442
+ { field: :application_fee_amount, type: 'Number', is_filterable: false },
433
443
  { field: :attempt_count, type: 'Number', is_filterable: false },
434
444
  { field: :attempted, type: 'Boolean', is_filterable: false },
435
- { field: :closed, type: 'Boolean', is_filterable: false },
436
445
  { field: :currency, type: 'String', is_filterable: false },
437
- { field: :date, type: 'Date', is_filterable: false },
438
- { field: :forgiven, type: 'Boolean', is_filterable: false },
446
+ { field: :due_date, type: 'Date', is_filterable: false },
439
447
  { field: :period_start, type: 'Date', is_filterable: false },
440
448
  { field: :period_end, type: 'Date', is_filterable: false },
449
+ { field: :status, type: 'String', enums: ['draft', 'open', 'paid', 'uncollectible', 'void'], is_filterable: false },
441
450
  { field: :subtotal, type: 'Number', is_filterable: false },
442
451
  { field: :total, type: 'Number', is_filterable: false },
443
- { field: :application_fee, type: 'Number', is_filterable: false },
444
452
  { field: :tax, type: 'Number', is_filterable: false },
445
- { field: :tax_percent, type: 'Number', is_filterable: false },
446
453
  {
447
454
  field: :customer,
448
455
  type: 'String',
@@ -1,3 +1,3 @@
1
1
  module ForestLiana
2
- VERSION = "6.0.0-beta.3"
2
+ VERSION = "6.0.3"
3
3
  end
@@ -5,6 +5,7 @@ module ForestLiana
5
5
  desc 'Forest Rails Liana installation generator'
6
6
 
7
7
  argument :env_secret, type: :string, required: true, desc: 'required', banner: 'env_secret'
8
+ argument :application_url, type: :string, required: false, desc: 'optional', banner: 'application_url', default: 'http://localhost:3000'
8
9
 
9
10
  def install
10
11
  if ForestLiana.env_secret.present?
@@ -27,35 +28,42 @@ module ForestLiana
27
28
  if File.exist? 'config/secrets.yml'
28
29
  inject_into_file 'config/secrets.yml', after: "development:\n" do
29
30
  " forest_env_secret: #{env_secret}\n" +
30
- " forest_auth_secret: #{auth_secret}\n"
31
+ " forest_auth_secret: #{auth_secret}\n" +
32
+ " forest_application_url: #{application_url}\n"
31
33
  end
32
34
 
33
35
  inject_into_file 'config/secrets.yml', after: "staging:\n", force: true do
34
36
  " forest_env_secret: <%= ENV[\"FOREST_ENV_SECRET\"] %>\n" +
35
- " forest_auth_secret: <%= ENV[\"FOREST_AUTH_SECRET\"] %>\n"
37
+ " forest_auth_secret: <%= ENV[\"FOREST_AUTH_SECRET\"] %>\n" +
38
+ " forest_application_url: <%= ENV[\"FOREST_APPLICATION_URL\"] %>\n"
36
39
  end
37
40
 
38
41
  inject_into_file 'config/secrets.yml', after: "production:\n", force: true do
39
42
  " forest_env_secret: <%= ENV[\"FOREST_ENV_SECRET\"] %>\n" +
40
- " forest_auth_secret: <%= ENV[\"FOREST_AUTH_SECRET\"] %>\n"
43
+ " forest_auth_secret: <%= ENV[\"FOREST_AUTH_SECRET\"] %>\n" +
44
+ " forest_application_url: <%= ENV[\"FOREST_APPLICATION_URL\"] %>\n"
41
45
  end
42
46
  else
43
47
  create_file 'config/secrets.yml' do
44
48
  "development:\n" +
45
49
  " forest_env_secret: #{env_secret}\n" +
46
50
  " forest_auth_secret: #{auth_secret}\n" +
51
+ " forest_application_url: #{application_url}\n" +
47
52
  "staging:\n" +
48
53
  " forest_env_secret: <%= ENV[\"FOREST_ENV_SECRET\"] %>\n" +
49
54
  " forest_auth_secret: <%= ENV[\"FOREST_AUTH_SECRET\"] %>\n" +
55
+ " forest_application_url: <%= ENV[\"FOREST_APPLICATION_URL\"] %>\n" +
50
56
  "production:\n" +
51
57
  " forest_env_secret: <%= ENV[\"FOREST_ENV_SECRET\"] %>\n" +
52
- " forest_auth_secret: <%= ENV[\"FOREST_AUTH_SECRET\"] %>\n"
58
+ " forest_auth_secret: <%= ENV[\"FOREST_AUTH_SECRET\"] %>\n" +
59
+ " forest_application_url: <%= ENV[\"FOREST_APPLICATION_URL\"] %>\n"
53
60
  end
54
61
  end
55
62
 
56
63
  initializer 'forest_liana.rb' do
57
64
  "ForestLiana.env_secret = Rails.application.secrets.forest_env_secret" +
58
- "\nForestLiana.auth_secret = Rails.application.secrets.forest_auth_secret"
65
+ "\nForestLiana.auth_secret = Rails.application.secrets.forest_auth_secret" +
66
+ "\nForestLiana.application_url = Rails.application.secrets.forest_application_url"
59
67
  end
60
68
  end
61
69
  end