forest_liana 1.4.4 → 1.4.5

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 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