forest_liana 5.3.0 → 6.0.0.pre.beta.2
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.
- checksums.yaml +4 -4
- data/app/controllers/forest_liana/actions_controller.rb +0 -82
- data/app/controllers/forest_liana/application_controller.rb +1 -7
- data/app/controllers/forest_liana/authentication_controller.rb +122 -0
- data/app/controllers/forest_liana/base_controller.rb +4 -0
- data/app/controllers/forest_liana/router.rb +2 -2
- data/app/controllers/forest_liana/sessions_controller.rb +1 -1
- data/app/controllers/forest_liana/stats_controller.rb +5 -5
- data/app/helpers/forest_liana/adapter_helper.rb +1 -1
- data/app/models/forest_liana/model/action.rb +1 -2
- data/app/serializers/forest_liana/schema_serializer.rb +2 -2
- data/app/services/forest_liana/apimap_sorter.rb +1 -2
- data/app/services/forest_liana/authentication.rb +59 -0
- data/app/services/forest_liana/authorization_getter.rb +12 -20
- data/app/services/forest_liana/forest_api_requester.rb +14 -5
- data/app/services/forest_liana/ip_whitelist_checker.rb +1 -1
- data/app/services/forest_liana/login_handler.rb +3 -11
- data/app/services/forest_liana/oidc_client_manager.rb +34 -0
- data/app/services/forest_liana/oidc_configuration_retriever.rb +12 -0
- data/app/services/forest_liana/oidc_dynamic_client_registrator.rb +67 -0
- data/app/services/forest_liana/permissions_checker.rb +1 -1
- data/app/services/forest_liana/query_stat_getter.rb +5 -5
- data/app/services/forest_liana/resources_getter.rb +3 -3
- data/app/services/forest_liana/token.rb +27 -0
- data/config/initializers/error-messages.rb +20 -0
- data/config/routes.rb +5 -2
- data/lib/forest_liana.rb +1 -0
- data/lib/forest_liana/bootstrapper.rb +1 -20
- data/lib/forest_liana/collection.rb +2 -2
- data/lib/forest_liana/engine.rb +9 -0
- data/lib/forest_liana/json_printer.rb +1 -1
- data/lib/forest_liana/schema_file_updater.rb +0 -1
- data/lib/forest_liana/version.rb +1 -1
- data/spec/dummy/config/initializers/forest_liana.rb +1 -0
- data/spec/requests/authentications_spec.rb +107 -0
- data/spec/requests/sessions_spec.rb +55 -0
- data/spec/services/forest_liana/apimap_sorter_spec.rb +4 -6
- metadata +57 -9
- data/app/helpers/forest_liana/is_same_data_structure_helper.rb +0 -44
- data/spec/helpers/forest_liana/is_same_data_structure_helper_spec.rb +0 -87
- data/spec/requests/actions_controller_spec.rb +0 -136
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f2f88ccbd15c18a78b06d08ad2a17dfa2075d2b586728033cbe03564c95dd92e
|
4
|
+
data.tar.gz: e78f4892dc9ea07b8dbabb67d3183920f8ef41b6cb7ebe1edd8cb3d0c3b7ee2b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a1dfc618f2723448b2fea3b39a48be64fad619c87a3b7d9257e3be8292f1ae86632c38563a7c9d938fd9699a0d78bac50e521d390bb40077ab824996b987ed2
|
7
|
+
data.tar.gz: d1a6401e8e236b718f488e1a1b5641fb953a912c719a5ea1010f7f307c99e7b96fd9f153fc483ebd7dbef5861a5daf9c12e2bdc03f846b62850662ee1837209a
|
@@ -1,89 +1,7 @@
|
|
1
1
|
module ForestLiana
|
2
2
|
class ActionsController < ForestLiana::BaseController
|
3
|
-
|
4
3
|
def values
|
5
4
|
render serializer: nil, json: {}, status: :ok
|
6
5
|
end
|
7
|
-
|
8
|
-
def get_collection(collection_name)
|
9
|
-
ForestLiana.apimap.find { |collection| collection.name.to_s == collection_name }
|
10
|
-
end
|
11
|
-
|
12
|
-
def get_action(collection_name)
|
13
|
-
collection = get_collection(collection_name)
|
14
|
-
begin
|
15
|
-
collection.actions.find {|action| ActiveSupport::Inflector.parameterize(action.name) == params[:action_name]}
|
16
|
-
rescue => error
|
17
|
-
FOREST_LOGGER.error "Smart Action get action retrieval error: #{error}"
|
18
|
-
nil
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def get_record
|
23
|
-
model = ForestLiana::SchemaUtils.find_model_from_collection_name(params[:collectionName])
|
24
|
-
redord_getter = ForestLiana::ResourceGetter.new(model, {:id => params[:recordIds][0]})
|
25
|
-
redord_getter.perform
|
26
|
-
redord_getter.record
|
27
|
-
end
|
28
|
-
|
29
|
-
def get_smart_action_load_ctx(fields)
|
30
|
-
fields = fields.reduce({}) {|p, c| p.update(c[:field] => c.merge!(value: nil))}
|
31
|
-
{:record => get_record, :fields => fields}
|
32
|
-
end
|
33
|
-
|
34
|
-
def get_smart_action_change_ctx(fields)
|
35
|
-
fields = fields.reduce({}) {|p, c| p.update(c[:field] => c.permit!.to_h)}
|
36
|
-
{:record => get_record, :fields => fields}
|
37
|
-
end
|
38
|
-
|
39
|
-
def handle_result(result, formatted_fields, action)
|
40
|
-
if result.nil? || !result.is_a?(Hash)
|
41
|
-
return render status: 500, json: { error: 'Error in smart action load hook: hook must return an object' }
|
42
|
-
end
|
43
|
-
is_same_data_structure = ForestLiana::IsSameDataStructureHelper::Analyser.new(formatted_fields, result, 1)
|
44
|
-
unless is_same_data_structure.perform
|
45
|
-
return render status: 500, json: { error: 'Error in smart action hook: fields must be unchanged (no addition nor deletion allowed)' }
|
46
|
-
end
|
47
|
-
|
48
|
-
# Apply result on fields (transform the object back to an array), preserve order.
|
49
|
-
fields = action.fields.map { |field| result[field[:field]] }
|
50
|
-
|
51
|
-
render serializer: nil, json: { fields: fields}, status: :ok
|
52
|
-
end
|
53
|
-
|
54
|
-
def load
|
55
|
-
action = get_action(params[:collectionName])
|
56
|
-
|
57
|
-
if !action
|
58
|
-
render status: 500, json: {error: 'Error in smart action load hook: cannot retrieve action from collection'}
|
59
|
-
else
|
60
|
-
# Transform fields from array to an object to ease usage in hook, adds null value.
|
61
|
-
context = get_smart_action_load_ctx(action.fields)
|
62
|
-
formatted_fields = context[:fields].clone # clone for following test on is_same_data_structure
|
63
|
-
|
64
|
-
# Call the user-defined load hook.
|
65
|
-
result = action.hooks[:load].(context)
|
66
|
-
|
67
|
-
handle_result(result, formatted_fields, action)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
def change
|
72
|
-
action = get_action(params[:collectionName])
|
73
|
-
|
74
|
-
if !action
|
75
|
-
render status: 500, json: {error: 'Error in smart action change hook: cannot retrieve action from collection'}
|
76
|
-
else
|
77
|
-
# Transform fields from array to an object to ease usage in hook.
|
78
|
-
context = get_smart_action_change_ctx(params[:fields])
|
79
|
-
formatted_fields = context[:fields].clone # clone for following test on is_same_data_structure
|
80
|
-
|
81
|
-
# Call the user-defined change hook.
|
82
|
-
field_name = params[:fields].select { |field| field[:value] != field[:previousValue] }[0][:field]
|
83
|
-
result = action.hooks[:change][field_name].(context)
|
84
|
-
|
85
|
-
handle_result(result, formatted_fields, action)
|
86
|
-
end
|
87
|
-
end
|
88
6
|
end
|
89
7
|
end
|
@@ -3,8 +3,6 @@ require 'csv'
|
|
3
3
|
|
4
4
|
module ForestLiana
|
5
5
|
class ApplicationController < ForestLiana::BaseController
|
6
|
-
REGEX_COOKIE_SESSION_TOKEN = /forest_session_token=([^;]*)/;
|
7
|
-
|
8
6
|
def self.papertrail?
|
9
7
|
Object.const_get('PaperTrail::Version').is_a?(Class) rescue false
|
10
8
|
end
|
@@ -64,7 +62,7 @@ module ForestLiana
|
|
64
62
|
token = request.headers['Authorization'].split.second
|
65
63
|
# NOTICE: Necessary for downloads authentication.
|
66
64
|
elsif request.headers['cookie']
|
67
|
-
match = REGEX_COOKIE_SESSION_TOKEN.match(request.headers['cookie'])
|
65
|
+
match = ForestLiana::Token::REGEX_COOKIE_SESSION_TOKEN.match(request.headers['cookie'])
|
68
66
|
token = match[1] if match && match[1]
|
69
67
|
end
|
70
68
|
|
@@ -97,10 +95,6 @@ module ForestLiana
|
|
97
95
|
end
|
98
96
|
end
|
99
97
|
|
100
|
-
def route_not_found
|
101
|
-
head :not_found
|
102
|
-
end
|
103
|
-
|
104
98
|
def internal_server_error
|
105
99
|
head :internal_server_error
|
106
100
|
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module ForestLiana
|
5
|
+
class AuthenticationController < ForestLiana::BaseController
|
6
|
+
START_AUTHENTICATION_ROUTE = 'authentication'
|
7
|
+
CALLBACK_AUTHENTICATION_ROUTE = 'authentication/callback'
|
8
|
+
LOGOUT_ROUTE = 'authentication/logout';
|
9
|
+
PUBLIC_ROUTES = [
|
10
|
+
"/#{START_AUTHENTICATION_ROUTE}",
|
11
|
+
"/#{CALLBACK_AUTHENTICATION_ROUTE}",
|
12
|
+
"/#{LOGOUT_ROUTE}",
|
13
|
+
]
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@authentication_service = ForestLiana::Authentication.new()
|
17
|
+
end
|
18
|
+
|
19
|
+
def get_callback_url
|
20
|
+
URI.join(ForestLiana.application_url, "/forest/#{CALLBACK_AUTHENTICATION_ROUTE}").to_s
|
21
|
+
rescue => error
|
22
|
+
raise "application_url is not valid or not defined" if error.is_a?(ArgumentError)
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_and_check_rendering_id
|
26
|
+
if !params.has_key?('renderingId')
|
27
|
+
raise ForestLiana::MESSAGES[:SERVER_TRANSACTION][:MISSING_RENDERING_ID]
|
28
|
+
end
|
29
|
+
|
30
|
+
rendering_id = params[:renderingId]
|
31
|
+
|
32
|
+
if !(rendering_id.instance_of?(String) || rendering_id.instance_of?(Numeric)) || (rendering_id.instance_of?(Numeric) && rendering_id.nan?)
|
33
|
+
raise ForestLiana::MESSAGES[:SERVER_TRANSACTION][:INVALID_RENDERING_ID]
|
34
|
+
end
|
35
|
+
|
36
|
+
return rendering_id.to_i
|
37
|
+
end
|
38
|
+
|
39
|
+
def start_authentication
|
40
|
+
begin
|
41
|
+
rendering_id = get_and_check_rendering_id()
|
42
|
+
callback_url = get_callback_url()
|
43
|
+
|
44
|
+
result = @authentication_service.start_authentication(
|
45
|
+
callback_url,
|
46
|
+
{ 'renderingId' => rendering_id },
|
47
|
+
)
|
48
|
+
|
49
|
+
redirect_to(result['authorization_url'])
|
50
|
+
rescue => error
|
51
|
+
render json: { errors: [{ status: 500, detail: error.message }] },
|
52
|
+
status: :internal_server_error, serializer: nil
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def authentication_callback
|
57
|
+
begin
|
58
|
+
callback_url = get_callback_url()
|
59
|
+
|
60
|
+
token = @authentication_service.verify_code_and_generate_token(
|
61
|
+
callback_url,
|
62
|
+
params,
|
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
|
+
|
77
|
+
response_body = {
|
78
|
+
tokenData: JWT.decode(token, ForestLiana.auth_secret, true, { algorithm: 'HS256' })[0]
|
79
|
+
}
|
80
|
+
|
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
|
+
render json: response_body, status: 200
|
87
|
+
|
88
|
+
rescue => error
|
89
|
+
render json: { errors: [{ status: 500, detail: error.message }] },
|
90
|
+
status: :internal_server_error, serializer: nil
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def logout
|
95
|
+
begin
|
96
|
+
if cookies.has_key?(:forest_session_token)
|
97
|
+
forest_session_token = cookies[:forest_session_token]
|
98
|
+
|
99
|
+
if forest_session_token
|
100
|
+
response.set_cookie(
|
101
|
+
'forest_session_token',
|
102
|
+
{
|
103
|
+
value: forest_session_token,
|
104
|
+
httponly: true,
|
105
|
+
secure: true,
|
106
|
+
expires: Time.at(0),
|
107
|
+
samesite: 'none',
|
108
|
+
path: '/'
|
109
|
+
},
|
110
|
+
)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
render json: {}, status: 204
|
115
|
+
rescue => error
|
116
|
+
render json: { errors: [{ status: 500, detail: error.message }] },
|
117
|
+
status: :internal_server_error, serializer: nil
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
end
|
@@ -7,7 +7,7 @@ class ForestLiana::Router
|
|
7
7
|
if resource.nil?
|
8
8
|
FOREST_LOGGER.error "Routing error: Resource not found for collection #{collection_name}."
|
9
9
|
FOREST_LOGGER.error "If this is a Smart Collection, please ensure your Smart Collection routes are defined before the mounted ForestLiana::Engine?"
|
10
|
-
ForestLiana::
|
10
|
+
ForestLiana::BaseController.action(:route_not_found).call(env)
|
11
11
|
else
|
12
12
|
begin
|
13
13
|
component_prefix = ForestLiana.component_prefix(resource)
|
@@ -40,7 +40,7 @@ class ForestLiana::Router
|
|
40
40
|
controller.action(action.to_sym).call(env)
|
41
41
|
rescue NoMethodError => exception
|
42
42
|
FOREST_LOGGER.error "Routing error: #{exception}\n#{exception.backtrace.join("\n\t")}"
|
43
|
-
ForestLiana::
|
43
|
+
ForestLiana::BaseController.action(:route_not_found).call(env)
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
@@ -85,7 +85,7 @@ module ForestLiana
|
|
85
85
|
# NOTICE: Set a cookie to ensure secure authentication using export feature.
|
86
86
|
# NOTICE: The token is empty at first authentication step if the 2FA option is active.
|
87
87
|
if reponse_data[:token]
|
88
|
-
response.set_cookie("forest_session_token", { value: reponse_data[:token], expires: (
|
88
|
+
response.set_cookie("forest_session_token", { value: reponse_data[:token], expires: (ForestLiana::Token.expiration_in_days) })
|
89
89
|
end
|
90
90
|
|
91
91
|
render(json: reponse_data, serializer: nil)
|
@@ -6,11 +6,11 @@ module ForestLiana
|
|
6
6
|
before_action :find_resource, except: [:get_with_live_query]
|
7
7
|
end
|
8
8
|
|
9
|
-
CHART_TYPE_VALUE = 'Value'
|
10
|
-
CHART_TYPE_PIE = 'Pie'
|
11
|
-
CHART_TYPE_LINE = 'Line'
|
12
|
-
CHART_TYPE_LEADERBOARD = 'Leaderboard'
|
13
|
-
CHART_TYPE_OBJECTIVE = 'Objective'
|
9
|
+
CHART_TYPE_VALUE = 'Value'
|
10
|
+
CHART_TYPE_PIE = 'Pie'
|
11
|
+
CHART_TYPE_LINE = 'Line'
|
12
|
+
CHART_TYPE_LEADERBOARD = 'Leaderboard'
|
13
|
+
CHART_TYPE_OBJECTIVE = 'Objective'
|
14
14
|
|
15
15
|
def get
|
16
16
|
case params[:type]
|
@@ -5,7 +5,7 @@ class ForestLiana::Model::Action
|
|
5
5
|
extend ActiveModel::Naming
|
6
6
|
|
7
7
|
attr_accessor :id, :name, :base_url, :endpoint, :http_method, :fields, :redirect,
|
8
|
-
:type, :download
|
8
|
+
:type, :download
|
9
9
|
|
10
10
|
def initialize(attributes = {})
|
11
11
|
if attributes.key?(:global)
|
@@ -66,7 +66,6 @@ class ForestLiana::Model::Action
|
|
66
66
|
@base_url ||= nil
|
67
67
|
@type ||= "bulk"
|
68
68
|
@download ||= false
|
69
|
-
@hooks = !@hooks.nil? ? @hooks.symbolize_keys : nil
|
70
69
|
end
|
71
70
|
|
72
71
|
def persisted?
|
@@ -52,7 +52,7 @@ class ForestLiana::SchemaSerializer
|
|
52
52
|
@included << format_child_content('segments', segment_id, segment)
|
53
53
|
end
|
54
54
|
else
|
55
|
-
collection_serialized[:attributes][attribute.to_sym] = value
|
55
|
+
collection_serialized[:attributes][attribute.to_sym] = value
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
@@ -75,7 +75,7 @@ class ForestLiana::SchemaSerializer
|
|
75
75
|
}
|
76
76
|
|
77
77
|
object.each do |attribute, value|
|
78
|
-
child_serialized[:attributes][attribute.to_sym] = value
|
78
|
+
child_serialized[:attributes][attribute.to_sym] = value
|
79
79
|
end
|
80
80
|
|
81
81
|
child_serialized
|
@@ -39,7 +39,6 @@ module ForestLiana
|
|
39
39
|
'redirect',
|
40
40
|
'download',
|
41
41
|
'fields',
|
42
|
-
'hooks',
|
43
42
|
]
|
44
43
|
KEYS_ACTION_FIELD = [
|
45
44
|
'field',
|
@@ -61,7 +60,7 @@ module ForestLiana
|
|
61
60
|
def perform
|
62
61
|
begin
|
63
62
|
@apimap = reorder_keys_basic(@apimap)
|
64
|
-
sort_array_of_objects(@apimap['data'])
|
63
|
+
sort_array_of_objects(@apimap['data'])
|
65
64
|
@apimap['data'].map! do |collection|
|
66
65
|
collection = reorder_keys_child(collection)
|
67
66
|
collection['attributes'] = reorder_collection_attributes(collection['attributes'])
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module ForestLiana
|
2
|
+
class Authentication
|
3
|
+
def start_authentication(redirect_url, state)
|
4
|
+
client = ForestLiana::OidcClientManager.get_client_for_callback_url(redirect_url)
|
5
|
+
|
6
|
+
authorization_url = client.authorization_uri({
|
7
|
+
scope: 'openid email profile',
|
8
|
+
state: state.to_s,
|
9
|
+
})
|
10
|
+
|
11
|
+
{ 'authorization_url' => authorization_url }
|
12
|
+
end
|
13
|
+
|
14
|
+
def verify_code_and_generate_token(redirect_url, params)
|
15
|
+
client = ForestLiana::OidcClientManager.get_client_for_callback_url(redirect_url)
|
16
|
+
|
17
|
+
rendering_id = parse_state(params['state'])
|
18
|
+
client.authorization_code = params['code']
|
19
|
+
|
20
|
+
if Rails.env.development? || Rails.env.test?
|
21
|
+
OpenIDConnect.http_config do |config|
|
22
|
+
config.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
23
|
+
end
|
24
|
+
end
|
25
|
+
access_token_instance = client.access_token! 'none'
|
26
|
+
|
27
|
+
user = ForestLiana::AuthorizationGetter.authenticate(
|
28
|
+
rendering_id,
|
29
|
+
true,
|
30
|
+
{ :forest_token => access_token_instance.instance_variable_get(:@access_token) },
|
31
|
+
nil,
|
32
|
+
)
|
33
|
+
|
34
|
+
return ForestLiana::Token.create_token(user, rendering_id)
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
def parse_state(state)
|
39
|
+
unless state
|
40
|
+
raise ForestLiana::MESSAGES[:SERVER_TRANSACTION][:INVALID_STATE_MISSING]
|
41
|
+
end
|
42
|
+
|
43
|
+
rendering_id = nil
|
44
|
+
|
45
|
+
begin
|
46
|
+
parsed_state = JSON.parse(state.gsub("'",'"').gsub('=>',':'))
|
47
|
+
rendering_id = parsed_state["renderingId"].to_s
|
48
|
+
rescue
|
49
|
+
raise ForestLiana::MESSAGES[:SERVER_TRANSACTION][:INVALID_STATE_FORMAT]
|
50
|
+
end
|
51
|
+
|
52
|
+
if rendering_id.nil?
|
53
|
+
raise ForestLiana::MESSAGES[:SERVER_TRANSACTION][:INVALID_STATE_RENDERING_ID]
|
54
|
+
end
|
55
|
+
|
56
|
+
return rendering_id
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -1,39 +1,31 @@
|
|
1
1
|
module ForestLiana
|
2
2
|
class AuthorizationGetter
|
3
|
-
def
|
4
|
-
@rendering_id = rendering_id
|
5
|
-
@use_google_authentication = use_google_authentication
|
6
|
-
@auth_data = auth_data
|
7
|
-
@two_factor_registration = two_factor_registration
|
8
|
-
|
9
|
-
@route = "/liana/v2/renderings/#{rendering_id}"
|
10
|
-
@route += use_google_authentication ? "/google-authorization" : "/authorization"
|
11
|
-
end
|
12
|
-
|
13
|
-
def perform
|
3
|
+
def self.authenticate(rendering_id, use_google_authentication, auth_data, two_factor_registration)
|
14
4
|
begin
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
headers = { '
|
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] }
|
19
11
|
end
|
20
12
|
|
21
13
|
query_parameters = {}
|
22
14
|
|
23
|
-
|
15
|
+
unless two_factor_registration.nil?
|
24
16
|
query_parameters['two-factor-registration'] = true
|
25
17
|
end
|
26
18
|
|
27
19
|
response = ForestLiana::ForestApiRequester
|
28
|
-
.get(
|
20
|
+
.get(route, query: query_parameters, headers: headers)
|
29
21
|
|
30
|
-
if response.
|
31
|
-
body = JSON.parse(response.body)
|
22
|
+
if response.code.to_i == 200
|
23
|
+
body = JSON.parse(response.body, :symbolize_names => false)
|
32
24
|
user = body['data']['attributes']
|
33
25
|
user['id'] = body['data']['id']
|
34
26
|
user
|
35
27
|
else
|
36
|
-
|
28
|
+
unless use_google_authentication.nil?
|
37
29
|
raise "Cannot authorize the user using this google account. Forest API returned an #{Errors::HTTPErrorHelper.format(response)}"
|
38
30
|
else
|
39
31
|
raise "Cannot authorize the user using this email/password. Forest API returned an #{Errors::HTTPErrorHelper.format(response)}"
|