forest_liana 1.4.4 → 1.4.5

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
  SHA1:
3
- metadata.gz: 1c7e65eaf32a280961a284a31d555dd41cb52b5a
4
- data.tar.gz: 68d912adea12939ab9bc20779434161c01fd993c
3
+ metadata.gz: 3abc2cedf799ed432538f68b9710ed9f48a20b69
4
+ data.tar.gz: 6e7adcf88252854a67c0c6d3d44f50b510435d17
5
5
  SHA512:
6
- metadata.gz: b336890472dd721f35d08aa754166436251d7e053f4e94eeaa9d2ea5f268e97145e6860e7a4e67e8ce19192fc31b49ce194446360a52075f97650422f20a1b33
7
- data.tar.gz: f2a40fd9fcfdda465440f7eb8911f5386fba5b28170bdddff0e9f093366a39c0fb74f4848e4d4f730d97ef9ad8c4baa8153c1529ea730c18cb6b70f1646600b0
6
+ metadata.gz: 8435daf472d626aacca2c6b7cdafb213fe8018993a15b306e21ec84d0a40211f90cae59dcdf87b78d5efc16885d9899c78c22dfacdae16e47ae9aea99482b30c
7
+ data.tar.gz: af9bf03170b9c886a26bb193057710ac7af2f981d56dec2f6766a56d26d050e9890a41334257b035ea888bbdec8c0eb95ecf957826be4be8760e858580d56363
@@ -2,34 +2,35 @@ module ForestLiana
2
2
  class SessionsController < ActionController::Base
3
3
 
4
4
  def create
5
- fetch_allowed_users
5
+ @user_class = ForestLiana.user_class_name.constantize rescue nil
6
+
6
7
  user = check_user
7
8
  token = encode_token(user) if user
8
9
 
9
10
  if token
10
11
  render json: { token: token }, serializer: nil
11
12
  else
12
- head :unauthorized
13
+ if !has_internal_authentication? && ForestLiana.allowed_users.empty?
14
+ render serializer: nil, json: JSONAPI::Serializer.serialize_errors(
15
+ [{ detail: 'Forest cannot retrieve any users for the project ' \
16
+ 'you\'re trying to unlock.' }]), status: :unauthorized
17
+ else
18
+ head :unauthorized
19
+ end
13
20
  end
14
21
  end
15
22
 
16
23
  private
17
24
 
18
- def fetch_allowed_users
19
- AllowedUsersGetter.new.perform(params['renderingId'])
20
- end
21
-
22
25
  def check_user
23
- # NOTICE: Use the ForestUser table for authentication.
24
- if defined? ForestUser
25
- user = ForestUser.find_by(email: params['email'])
26
- return nil if user.blank?
27
-
28
- if BCrypt::Password.new(user['password_hash']) == params['password']
29
- user
30
- end
31
- # NOTICE: Query Forest server for authentication.
26
+ if has_internal_authentication?
27
+ # NOTICE: Use the ForestUser table for authentication.
28
+ user = user_class.find_by(email: params['email'])
29
+ user if !user.blank? && authenticate_internal_user(user['password_digest'])
32
30
  else
31
+ # NOTICE: Query Forest server for authentication.
32
+ fetch_allowed_users
33
+
33
34
  ForestLiana.allowed_users.find do |allowed_user|
34
35
  allowed_user['email'] == params['email'] &&
35
36
  BCrypt::Password.new(allowed_user['password']) == params['password']
@@ -37,6 +38,18 @@ module ForestLiana
37
38
  end
38
39
  end
39
40
 
41
+ def fetch_allowed_users
42
+ AllowedUsersGetter.new.perform(params['renderingId'])
43
+ end
44
+
45
+ def has_internal_authentication?
46
+ @user_class && defined? @user_class
47
+ end
48
+
49
+ def authenticate_internal_user(password_digest)
50
+ BCrypt::Password.new(password_digest).is_password?(params['password'])
51
+ end
52
+
40
53
  def encode_token(user)
41
54
  JWT.encode({
42
55
  exp: Time.now.to_i + 2.weeks.to_i,
@@ -11,6 +11,7 @@ module ForestLiana
11
11
 
12
12
  def perform
13
13
  @attributes = extract_attributes
14
+ extract_attributes_serialize
14
15
  extract_relationships if @with_relationships
15
16
  extract_paperclip
16
17
  extract_carrierwave
@@ -22,12 +23,19 @@ module ForestLiana
22
23
 
23
24
  def extract_attributes
24
25
  if @params[:data][:attributes]
25
- @params['data']['attributes'].select {|attr| column?(attr)}
26
+ @params['data']['attributes'].select { |attribute| column?(attribute) }
26
27
  else
27
28
  ActionController::Parameters.new()
28
29
  end
29
30
  end
30
31
 
32
+ def extract_attributes_serialize
33
+ @resource.serialized_attributes.each do |attribute, serializer|
34
+ value = @params[:data][:attributes][attribute]
35
+ @attributes[attribute] = JSON::parse(value)
36
+ end
37
+ end
38
+
31
39
  def extract_relationships
32
40
  if @params['data']['relationships']
33
41
  @params['data']['relationships'].each do |name, relationship|
@@ -112,7 +120,7 @@ module ForestLiana
112
120
  end
113
121
 
114
122
  def column?(attribute)
115
- @resource.columns.find {|x| x.name == attribute}.present?
123
+ @resource.columns.find { |column| column.name == attribute }.present?
116
124
  end
117
125
 
118
126
  def carrierwave_attribute?(attr)
@@ -150,14 +150,14 @@ module ForestLiana
150
150
  end
151
151
  }
152
152
 
153
- attributes(active_record_class).each do |attr|
154
- serializer.attribute(attr)
153
+ attributes(active_record_class).each do |attribute|
154
+ serializer.attribute(attribute)
155
155
  end
156
156
 
157
- # NOTICE: Format properly the time type fields during the serialization.
158
- attributes_time(active_record_class).each do |attr|
159
- serializer.attribute(attr) do |x|
160
- value = object.send(attr)
157
+ # NOTICE: Format time type fields during the serialization.
158
+ attributes_time(active_record_class).each do |attribute|
159
+ serializer.attribute(attribute) do |x|
160
+ value = object.send(attribute)
161
161
  if value
162
162
  match = /(\d{2}:\d{2}:\d{2})/.match(value.to_s)
163
163
  (match && match[1]) ? match[1] : nil
@@ -167,21 +167,29 @@ module ForestLiana
167
167
  end
168
168
  end
169
169
 
170
- # CarrierWave url attribute
170
+ # NOTICE: Format serialized fields.
171
+ active_record_class.serialized_attributes.each do |attribute, serialization|
172
+ serializer.attribute(attribute) do |x|
173
+ value = object.send(attribute)
174
+ value ? value.to_json : nil
175
+ end
176
+ end
177
+
178
+ # NOTICE: Format CarrierWave url attribute
171
179
  if active_record_class.respond_to?(:mount_uploader)
172
180
  active_record_class.uploaders.each do |key, value|
173
181
  serializer.attribute(key) { |x| object.send(key).try(:url) }
174
182
  end
175
183
  end
176
184
 
177
- # Paperclip url attribute
185
+ # NOTICE: Format Paperclip url attribute
178
186
  if active_record_class.respond_to?(:attachment_definitions)
179
187
  active_record_class.attachment_definitions.each do |key, value|
180
188
  serializer.attribute(key) { |x| object.send(key) }
181
189
  end
182
190
  end
183
191
 
184
- # ActsAsTaggable attribute
192
+ # NOTICE: Format ActsAsTaggable attribute
185
193
  if active_record_class.respond_to?(:acts_as_taggable) &&
186
194
  active_record_class.acts_as_taggable.respond_to?(:to_a)
187
195
  active_record_class.acts_as_taggable.to_a.each do |key, value|
@@ -191,7 +199,7 @@ module ForestLiana
191
199
  end
192
200
  end
193
201
 
194
- # Devise attributes
202
+ # NOTICE: Format Devise attributes
195
203
  if active_record_class.respond_to?(:devise_modules?)
196
204
  serializer.attribute('password') do |x|
197
205
  '**********'
@@ -199,18 +207,23 @@ module ForestLiana
199
207
  end
200
208
 
201
209
  SchemaUtils.associations(active_record_class).each do |a|
202
- if SchemaUtils.model_included?(a.klass)
203
- serializer.send(serializer_association(a), a.name) {
204
- if [:has_one, :belongs_to].include?(a.macro)
205
- begin
206
- object.send(a.name)
207
- rescue ActiveRecord::RecordNotFound
208
- nil
210
+ begin
211
+ if SchemaUtils.model_included?(a.klass)
212
+ serializer.send(serializer_association(a), a.name) {
213
+ if [:has_one, :belongs_to].include?(a.macro)
214
+ begin
215
+ object.send(a.name)
216
+ rescue ActiveRecord::RecordNotFound
217
+ nil
218
+ end
219
+ else
220
+ []
209
221
  end
210
- else
211
- []
212
- end
213
- }
222
+ }
223
+ end
224
+ rescue NameError
225
+ # NOTICE: Let this error silent, a bad association warning will be
226
+ # displayed in the schema adapter.
214
227
  end
215
228
  end
216
229
 
@@ -4,23 +4,35 @@ module ForestLiana
4
4
  uri = URI.parse("#{forest_url}/forest/renderings/#{renderingId}/allowed-users")
5
5
  http = Net::HTTP.new(uri.host, uri.port)
6
6
  http.use_ssl = true if forest_url.start_with?('https')
7
- http.start do |client|
8
- request = Net::HTTP::Get.new(uri.path)
9
- request['Content-Type'] = 'application/json'
10
- request['forest-secret-key'] = ForestLiana.secret_key
11
- response = client.request(request)
12
7
 
13
- if response.is_a?(Net::HTTPOK)
14
- body = JSON.parse(response.body)
15
- ForestLiana.allowed_users = body['data'].map do |d|
16
- user = d['attributes']
17
- user['id'] = d['id']
8
+ begin
9
+ http.start do |client|
10
+ request = Net::HTTP::Get.new(uri.path)
11
+ request['Content-Type'] = 'application/json'
12
+ request['forest-secret-key'] = ForestLiana.secret_key
13
+ response = client.request(request)
18
14
 
19
- user
15
+ if response.is_a?(Net::HTTPOK)
16
+ body = JSON.parse(response.body)
17
+ ForestLiana.allowed_users = body['data'].map do |d|
18
+ user = d['attributes']
19
+ user['id'] = d['id']
20
+
21
+ user
22
+ end
23
+ elsif response.is_a?(Net::HTTPNotFound)
24
+ FOREST_LOGGER.error "Cannot retrieve the project you\'re trying " \
25
+ "to unlock. Can you check that you properly copied the Forest " \
26
+ "secret key in the forest_liana initializer?"
27
+ else
28
+ FOREST_LOGGER.error "Cannot retrieve any users for the project " \
29
+ "you\'re trying to unlock. An error occured in Forest API."
30
+ []
20
31
  end
21
- else
22
- []
23
32
  end
33
+ rescue => exception
34
+ FOREST_LOGGER.error "Cannot retrieve any users for the project " \
35
+ "you\'re trying to unlock. Forest API seems to be down right now."
24
36
  end
25
37
  end
26
38
 
@@ -18,7 +18,6 @@ module ForestLiana
18
18
  .unscoped
19
19
  .find(@params[:id])
20
20
  .send(@params[:association_name])
21
- .select(select)
22
21
  .eager_load(includes)
23
22
  @records = sort_query
24
23
  end
@@ -50,15 +49,6 @@ module ForestLiana
50
49
 
51
50
  private
52
51
 
53
- def select
54
- column_names = @association.klass.column_names.map { |name| name.to_sym }
55
- if @field_names_requested
56
- column_names & @field_names_requested
57
- else
58
- column_names
59
- end
60
- end
61
-
62
52
  def association_table_name
63
53
  @resource.reflect_on_association(@params[:association_name])
64
54
  .try(:table_name)
@@ -22,23 +22,33 @@ module ForestLiana
22
22
  .unscoped
23
23
  .eager_load(includes)
24
24
  .where(conditions.join(filter_operator))
25
- .group("#{@resource.table_name}.#{@params[:group_by_field]}")
25
+ .group(group_by_field)
26
26
  .order(order)
27
27
  .send(@params[:aggregate].downcase, @params[:aggregate_field])
28
- .map do |k, v|
28
+ .map do |key, value|
29
29
  # NOTICE: Display the enum name instead of a integer if "enum" type
30
30
  if @resource.respond_to?(:defined_enums) &&
31
31
  @resource.defined_enums.has_key?(@params[:group_by_field])
32
- k = @resource.defined_enums[@params[:group_by_field]].invert[k]
32
+ key = @resource.defined_enums[@params[:group_by_field]].invert[key]
33
33
  end
34
34
 
35
- { key: k, value: v }
35
+ { key: key, value: value }
36
36
  end
37
37
 
38
38
  @record = Model::Stat.new(value: value)
39
39
  end
40
40
  end
41
41
 
42
+ def group_by_field
43
+ if @params[:group_by_field].include? ':'
44
+ association, field = @params[:group_by_field].split ':'
45
+ resource = @resource.reflect_on_association(association.to_sym)
46
+ "#{resource.table_name}.#{field}"
47
+ else
48
+ "#{@resource.table_name}.#{@params[:group_by_field]}"
49
+ end
50
+ end
51
+
42
52
  def order
43
53
  # NOTICE: The generated alias for a count is "count_all", for a sum the
44
54
  # alias looks like "sum_#{aggregate_field}"
@@ -36,7 +36,7 @@ module ForestLiana
36
36
  end
37
37
 
38
38
  def records
39
- @sorted_records.select(select).offset(offset).limit(limit).to_a
39
+ @sorted_records.offset(offset).limit(limit).to_a
40
40
  end
41
41
 
42
42
  def count
@@ -109,15 +109,6 @@ module ForestLiana
109
109
  @resource.reflect_on_association(field.to_sym).present?
110
110
  end
111
111
 
112
- def select
113
- column_names = @resource.column_names.map { |name| name.to_sym }
114
- if @field_names_requested
115
- column_names & @field_names_requested
116
- else
117
- column_names
118
- end
119
- end
120
-
121
112
  def offset
122
113
  return 0 unless pagination?
123
114
 
@@ -8,10 +8,11 @@ module ForestLiana
8
8
  add_columns
9
9
  add_associations
10
10
 
11
- # ActsAsTaggable attribute
12
- if @model.respond_to?(:acts_as_taggable) && @model.acts_as_taggable.respond_to?(:to_a)
11
+ # NOTICE: Add ActsAsTaggable fields
12
+ if @model.respond_to?(:acts_as_taggable) &&
13
+ @model.acts_as_taggable.respond_to?(:to_a) &&
13
14
  @model.acts_as_taggable.to_a.each do |key, value|
14
- field = collection.fields.find {|x| x[:field] == key.to_s}
15
+ field = collection.fields.find { |x| x[:field] == key.to_s }
15
16
 
16
17
  if field
17
18
  field[:type] = 'String'
@@ -25,7 +26,7 @@ module ForestLiana
25
26
  end
26
27
  end
27
28
 
28
- # Devise attributes
29
+ # NOTICE: Add Devise fields
29
30
  if @model.respond_to?(:devise_modules?)
30
31
  collection.fields << {
31
32
  field: 'password',
@@ -66,7 +67,7 @@ module ForestLiana
66
67
  collection.fields << get_schema_for_column(column)
67
68
  end
68
69
 
69
- # Intercom
70
+ # NOTICE: Add Intercom fields
70
71
  if ForestLiana.integrations.try(:[], :intercom)
71
72
  .try(:[], :mapping).try(:include?, @model.name)
72
73
 
@@ -91,7 +92,7 @@ module ForestLiana
91
92
  }
92
93
  end
93
94
 
94
- # Stripe
95
+ # NOTICE: Add Stripe fields
95
96
  stripe_mapping = ForestLiana.integrations.try(:[], :stripe)
96
97
  .try(:[], :mapping)
97
98
 
@@ -149,7 +150,7 @@ module ForestLiana
149
150
  end
150
151
  end
151
152
 
152
- # Paperclip url attribute
153
+ # NOTICE: Add Paperclip url attributes
153
154
  if @model.respond_to?(:attachment_definitions)
154
155
  @model.attachment_definitions.each do |key, value|
155
156
  collection.fields << { field: key, type: 'File' }
@@ -161,10 +162,10 @@ module ForestLiana
161
162
  end
162
163
  end
163
164
 
164
- # CarrierWave attribute
165
+ # NOTICE: Add CarrierWave attributes
165
166
  if @model.respond_to?(:uploaders)
166
167
  @model.uploaders.each do |key, value|
167
- field = collection.fields.find {|x| x[:field] == key.to_s}
168
+ field = collection.fields.find { |x| x[:field] == key.to_s }
168
169
  field[:type] = 'File' if field
169
170
  end
170
171
  end
@@ -173,7 +174,7 @@ module ForestLiana
173
174
  def add_associations
174
175
  SchemaUtils.associations(@model).each do |association|
175
176
  begin
176
- # NOTICE: delete the association if the targeted model is excluded.
177
+ # NOTICE: Delete the association if the targeted model is excluded.
177
178
  if !SchemaUtils.model_included?(association.klass)
178
179
  field = collection.fields.find do |x|
179
180
  x[:field] == association.foreign_key
@@ -189,8 +190,12 @@ module ForestLiana
189
190
  else
190
191
  collection.fields << get_schema_for_association(association)
191
192
  end
192
- rescue => error
193
- puts error.inspect
193
+ rescue NameError
194
+ FOREST_LOGGER.warn "The association \"#{association.name.to_s}\" " \
195
+ "does not seem to exist for model \"#{@model.name}\"."
196
+ rescue => exception
197
+ FOREST_LOGGER.error "An error occured trying to add " \
198
+ "\"#{association.name.to_s}\" association:\n#{exception}"
194
199
  end
195
200
  end
196
201
  end
@@ -0,0 +1,25 @@
1
+ # encoding: UTF-8
2
+ module ForestLiana
3
+ class Logger
4
+ class << self
5
+ def log
6
+ logger = ::Logger.new(STDOUT)
7
+ logger_colors = {
8
+ DEBUG: 34,
9
+ WARN: 33,
10
+ ERROR: 31,
11
+ INFO: 37
12
+ }
13
+
14
+ logger.formatter = proc do |severity, datetime, progname, message|
15
+ displayed_message = "[#{datetime.to_s(:db)}] Forest 🌳🌳🌳 #{message}\n"
16
+ "\e[#{logger_colors[severity.to_sym]}m#{displayed_message}\033[0m"
17
+ end
18
+
19
+ logger
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ FOREST_LOGGER = ForestLiana::Logger.log
@@ -1,7 +1,26 @@
1
1
  ForestLiana::Engine.routes.draw do
2
- # Login
2
+ # Onboarding
3
+ get '/' => 'apimaps#index'
4
+
5
+ # Session
3
6
  post 'sessions' => 'sessions#create'
4
7
 
8
+ # CRUD
9
+ get ':collection' => 'resources#index'
10
+ get ':collection/:id' => 'resources#show'
11
+ post ':collection' => 'resources#create'
12
+ put ':collection/:id' => 'resources#update'
13
+ delete ':collection/:id' => 'resources#destroy'
14
+
15
+ # Associations
16
+ get ':collection/:id/relationships/:association_name' => 'associations#index'
17
+ put ':collection/:id/relationships/:association_name' => 'associations#update'
18
+ post ':collection/:id/relationships/:association_name' => 'associations#associate'
19
+ delete ':collection/:id/relationships/:association_name' => 'associations#dissociate'
20
+
21
+ # Stats
22
+ post '/stats/:collection' => 'stats#show'
23
+
5
24
  # Stripe Integration
6
25
  get '(:collection)_stripe_payments' => 'stripe#payments'
7
26
  get ':collection/:id/stripe_payments' => 'stripe#payments'
@@ -16,21 +35,4 @@ ForestLiana::Engine.routes.draw do
16
35
  # Intercom Integration
17
36
  get ':collection/:id/intercom_conversations' => 'intercom#user_conversations'
18
37
  get ':collection/:id/intercom_attributes' => 'intercom#attributes'
19
-
20
- # Stats
21
- post '/stats/:collection' => 'stats#show'
22
-
23
- # CRUD
24
- get '/' => 'apimaps#index'
25
- get ':collection' => 'resources#index'
26
- get ':collection/:id' => 'resources#show'
27
- post ':collection' => 'resources#create'
28
- put ':collection/:id' => 'resources#update'
29
- delete ':collection/:id' => 'resources#destroy'
30
-
31
- # Associations
32
- get ':collection/:id/relationships/:association_name' => 'associations#index'
33
- put ':collection/:id/relationships/:association_name' => 'associations#update'
34
- post ':collection/:id/relationships/:association_name' => 'associations#associate'
35
- delete ':collection/:id/relationships/:association_name' => 'associations#dissociate'
36
38
  end
@@ -15,13 +15,12 @@ module ForestLiana
15
15
  mattr_accessor :models
16
16
  mattr_accessor :excluded_models
17
17
  mattr_accessor :included_models
18
-
19
- # Legacy.
20
- mattr_accessor :jwt_signing_key
18
+ mattr_accessor :user_class_name
21
19
 
22
20
  self.apimap = []
23
21
  self.allowed_users = []
24
22
  self.models = []
25
23
  self.excluded_models = []
26
24
  self.included_models = []
25
+ self.user_class_name = nil
27
26
  end
@@ -1,4 +1,3 @@
1
- # encoding: UTF-8
2
1
  module ForestLiana
3
2
  class Bootstraper
4
3
 
@@ -7,29 +6,6 @@ module ForestLiana
7
6
 
8
7
  @integration_stripe_valid = false
9
8
  @integration_intercom_valid = false
10
-
11
- @logger = Logger.new(STDOUT)
12
-
13
- @@logger_colors = {
14
- DEBUG: 34,
15
- WARN: 33,
16
- ERROR: 31,
17
- INFO: 37
18
- }
19
-
20
- @logger.formatter = proc do |severity, datetime, progname, message|
21
- displayed_message = "[#{datetime.to_s(:db)}] Forest 🌳🌳🌳 #{message}\n"
22
- "\e[#{@@logger_colors[severity.to_sym]}m#{displayed_message}\033[0m"
23
- end
24
-
25
- if ForestLiana.jwt_signing_key
26
- @logger.warn "DEPRECATION WARNING: the use of \
27
- ForestLiana.jwt_signing_key (config/initializers/forest_liana.rb) is \
28
- deprecated. Use ForestLiana.secret_key and ForestLiana.auth_key instead. \
29
- More info at: https://github.com/ForestAdmin/forest-rails/releases/tag/1.2.0"
30
- ForestLiana.secret_key = ForestLiana.jwt_signing_key
31
- ForestLiana.auth_key = ForestLiana.jwt_signing_key
32
- end
33
9
  end
34
10
 
35
11
  def perform
@@ -47,7 +23,7 @@ More info at: https://github.com/ForestAdmin/forest-rails/releases/tag/1.2.0"
47
23
  private
48
24
 
49
25
  def fetch_sti_models(model)
50
- type_field = model.columns.find {|c| c.name == 'type' }
26
+ type_field = model.columns.find { |c| c.name == 'type' }
51
27
  if type_field
52
28
  model.descendants.each do |sti_model|
53
29
  if analyze_model?(sti_model)
@@ -63,19 +39,23 @@ More info at: https://github.com/ForestAdmin/forest-rails/releases/tag/1.2.0"
63
39
  end
64
40
 
65
41
  def fetch_models
66
- ActiveRecord::Base.subclasses.each {|model| fetch_model(model)}
42
+ ActiveRecord::Base.subclasses.each { |model| fetch_model(model) }
67
43
  end
68
44
 
69
45
  def fetch_model(model)
70
- if model.abstract_class?
71
- model.descendants.each {|submodel| fetch_model(submodel)}
72
- else
73
- fetch_sti_models(model) if model.try(:table_exists?)
46
+ begin
47
+ if model.abstract_class?
48
+ model.descendants.each { |submodel| fetch_model(submodel) }
49
+ else
50
+ fetch_sti_models(model) if model.try(:table_exists?)
74
51
 
75
- if analyze_model?(model)
76
- ForestLiana.models << model
52
+ if analyze_model?(model)
53
+ ForestLiana.models << model
54
+ end
77
55
  end
78
-
56
+ rescue => exception
57
+ FOREST_LOGGER.error "Cannot fetch properly model #{model.name}:\n" \
58
+ "#{exception}"
79
59
  end
80
60
  end
81
61
 
@@ -111,7 +91,7 @@ More info at: https://github.com/ForestAdmin/forest-rails/releases/tag/1.2.0"
111
91
  cast_to_array(ForestLiana.integrations[:stripe][:mapping])
112
92
  @integration_stripe_valid = true
113
93
  else
114
- @logger.error 'Cannot setup properly your Stripe integration.'
94
+ FOREST_LOGGER.error 'Cannot setup properly your Stripe integration.'
115
95
  end
116
96
  end
117
97
 
@@ -121,7 +101,7 @@ More info at: https://github.com/ForestAdmin/forest-rails/releases/tag/1.2.0"
121
101
  cast_to_array(ForestLiana.integrations[:intercom][:mapping])
122
102
  @integration_intercom_valid = true
123
103
  else
124
- @logger.error 'Cannot setup properly your Intercom integration.'
104
+ FOREST_LOGGER.error 'Cannot setup properly your Intercom integration.'
125
105
  end
126
106
  end
127
107
  end
@@ -156,30 +136,43 @@ More info at: https://github.com/ForestAdmin/forest-rails/releases/tag/1.2.0"
156
136
  end
157
137
 
158
138
  def send_apimap
159
- json = JSONAPI::Serializer.serialize(ForestLiana.apimap, {
160
- is_collection: true,
161
- include: ['actions'],
162
- meta: { liana: 'forest-rails', liana_version: liana_version }
163
- })
164
-
165
- begin
166
- uri = URI.parse("#{forest_url}/forest/apimaps")
167
- http = Net::HTTP.new(uri.host, uri.port)
168
- http.use_ssl = true if forest_url.start_with?('https')
169
- http.start do |client|
170
- request = Net::HTTP::Post.new(uri.path)
171
- request.body = json.to_json
172
- request['Content-Type'] = 'application/json'
173
- request['forest-secret-key'] = ForestLiana.secret_key
174
- response = client.request(request)
175
-
176
- if response.is_a?(Net::HTTPNotFound)
177
- @logger.warn "Cannot find your project secret key. " \
178
- "Please, run `rails g forest_liana:install`."
139
+ if ForestLiana.secret_key && ForestLiana.secret_key.length != 64
140
+ FOREST_LOGGER.error "Your secret key does not seem to be correct. " \
141
+ "Can you check on Forest that you copied it properly in the " \
142
+ "forest_liana initializer?"
143
+ else
144
+ json = JSONAPI::Serializer.serialize(ForestLiana.apimap, {
145
+ is_collection: true,
146
+ include: ['actions'],
147
+ meta: { liana: 'forest-rails', liana_version: liana_version }
148
+ })
149
+
150
+ begin
151
+ uri = URI.parse("#{forest_url}/forest/apimaps")
152
+ http = Net::HTTP.new(uri.host, uri.port)
153
+ http.use_ssl = true if forest_url.start_with?('https')
154
+ http.start do |client|
155
+ request = Net::HTTP::Post.new(uri.path)
156
+ request.body = json.to_json
157
+ request['Content-Type'] = 'application/json'
158
+ request['forest-secret-key'] = ForestLiana.secret_key
159
+ response = client.request(request)
160
+
161
+ # NOTICE: HTTP 404 Error
162
+ if response.is_a?(Net::HTTPNotFound)
163
+ FOREST_LOGGER.error "Cannot find the project related to the " \
164
+ "secret key you configured. Can you check on Forest that you " \
165
+ "copied it properly in the forest_liana initializer?"
166
+ # NOTICE: HTTP 400 Error
167
+ elsif response.is_a?(Net::HTTPBadRequest)
168
+ FOREST_LOGGER.error "An error occured with the apimap sent to " \
169
+ "Forest. Please contact support@forestadmin.com for further " \
170
+ "investigations."
171
+ end
179
172
  end
173
+ rescue Errno::ECONNREFUSED
174
+ FOREST_LOGGER.warn "Cannot send the apimap to Forest. Are you online?"
180
175
  end
181
- rescue Errno::ECONNREFUSED
182
- @logger.warn "Cannot send the apimap to Forest. Are you online?"
183
176
  end
184
177
  end
185
178
 
@@ -252,8 +245,8 @@ More info at: https://github.com/ForestAdmin/forest-rails/releases/tag/1.2.0"
252
245
  if is_deprecated
253
246
  integration[:mapping] = integration[:user_collection]
254
247
 
255
- @logger.warn "Intercom integration attribute \"user_collection\" is " \
256
- "now deprecated, please use \"mapping\" attribute."
248
+ FOREST_LOGGER.warn "Intercom integration attribute \"user_collection\"" \
249
+ "is now deprecated, please use \"mapping\" attribute."
257
250
  end
258
251
 
259
252
  is_deprecated
@@ -444,7 +437,7 @@ More info at: https://github.com/ForestAdmin/forest-rails/releases/tag/1.2.0"
444
437
  integration[:mapping] =
445
438
  "#{integration[:user_collection]}.#{integration[:user_field]}"
446
439
 
447
- @logger.warn "Stripe integration attributes \"user_collection\" and " \
440
+ FOREST_LOGGER.warn "Stripe integration attributes \"user_collection\" and " \
448
441
  "\"user_field\" are now deprecated, please use \"mapping\" attribute."
449
442
  end
450
443
 
@@ -14,16 +14,19 @@ module ForestLiana::Collection
14
14
  end
15
15
 
16
16
  def action(name, opts = {})
17
- opts[:id] = "#{self.collection_name.to_s}.#{name}"
17
+ opts[:id] = "#{self.collection_name.to_s}.#{name}"
18
18
  opts[:name] = name
19
19
  model.actions << ForestLiana::Model::Action.new(opts)
20
20
  end
21
21
 
22
22
  def field(name, opts, &block)
23
+ opts[:read_only] = true unless opts.has_key?(:read_only)
24
+ opts[:is_searchable] = false unless opts.has_key?(:is_searchable)
25
+
23
26
  model.fields << opts.merge({
24
27
  field: name,
25
- :'is-read-only' => true,
26
- :'is-searchable' => false,
28
+ :'is-read-only' => opts[:read_only],
29
+ :'is-searchable' => opts['is_searchable'],
27
30
  :'is-virtual' => true
28
31
  })
29
32
 
@@ -13,27 +13,39 @@ module ForestLiana
13
13
  isolate_namespace ForestLiana
14
14
 
15
15
  def configure_forest_cors
16
- rack_cors_class = Rack::Cors
17
- rack_cors_class = 'Rack::Cors' if Rails::VERSION::MAJOR < 5
16
+ begin
17
+ rack_cors_class = Rack::Cors
18
+ rack_cors_class = 'Rack::Cors' if Rails::VERSION::MAJOR < 5
18
19
 
19
- config.middleware.insert_before 0, rack_cors_class do
20
- allow do
21
- hostnames = ['localhost:4200', 'app.forestadmin.com',
22
- 'www.forestadmin.com']
23
- hostnames += ENV['CORS_ORIGINS'].split(',') if ENV['CORS_ORIGINS']
20
+ config.middleware.insert_before 0, rack_cors_class do
21
+ allow do
22
+ hostnames = ['localhost:4200', 'app.forestadmin.com',
23
+ 'www.forestadmin.com']
24
+ hostnames += ENV['CORS_ORIGINS'].split(',') if ENV['CORS_ORIGINS']
24
25
 
25
- origins hostnames
26
- resource '*', headers: :any, methods: :any
26
+ origins hostnames
27
+ resource '*', headers: :any, methods: :any
28
+ end
27
29
  end
30
+ nil
31
+ rescue => exception
32
+ exception
28
33
  end
29
34
  end
30
35
 
31
- configure_forest_cors unless ENV['FOREST_CORS_DEACTIVATED']
36
+ error = configure_forest_cors unless ENV['FOREST_CORS_DEACTIVATED']
32
37
 
33
38
  config.after_initialize do |app|
34
39
  unless Rails.env.test?
40
+ if error
41
+ FOREST_LOGGER.error "Impossible to set the whitelisted Forest " \
42
+ "domains for CORS constraint:\n#{error}"
43
+ end
44
+
35
45
  app.eager_load!
36
- Bootstraper.new(app).perform
46
+
47
+ # NOTICE: Do not run the code below on rails g forest_liana:install.
48
+ Bootstraper.new(app).perform if ForestLiana.secret_key
37
49
  end
38
50
  end
39
51
  end
@@ -1,3 +1,3 @@
1
1
  module ForestLiana
2
- VERSION = "1.4.4"
2
+ VERSION = "1.4.5"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: forest_liana
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.4
4
+ version: 1.4.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sandro Munda
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-18 00:00:00.000000000 Z
11
+ date: 2016-11-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -189,6 +189,7 @@ files:
189
189
  - app/services/forest_liana/value_stat_getter.rb
190
190
  - app/views/layouts/forest_liana/application.html.erb
191
191
  - config/initializers/arel-helpers.rb
192
+ - config/initializers/logger.rb
192
193
  - config/initializers/time_formats.rb
193
194
  - config/routes.rb
194
195
  - lib/forest_liana.rb