forest_liana 1.4.7 → 1.5.0

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: bdc8fcb5df5a924d7903d9105b26b30810ef6a52
4
- data.tar.gz: cd688dccec28feaf5a66f0ea47b7c0bed89ee051
3
+ metadata.gz: 370f07e1de98a6ce3327d97c481023c434f85b45
4
+ data.tar.gz: bcb19bdd6901d1e41fea931f89d9da81c52ffdde
5
5
  SHA512:
6
- metadata.gz: 0ea7d3bb580c5cee0a84f80aff39d3d1c44d65c4ecdc2b694f0531e36c3edc1e12e0591b5a2c64838e04081675fcc09672a56323dc026a43ebcde19f7f5b3ddc
7
- data.tar.gz: 0832ca416bd830169ea4bb3926fa839a0b245d4e8ea0c1d13732b4cbe9cd794c8dad561ad2ac6bb12496eeb209637f91e12759559830b424c229a22592e81534
6
+ metadata.gz: 9e30e668b9116aaaa701bd0046747c33dac6cc22e806970af081a34b346f7bc6810a4df5ec4f50d4013d9dc6ec93af3d9bc9eefdbd97e5599e1c7829c7be8efe
7
+ data.tar.gz: 0aa6c921a2fab719a0425b5fc8f75578c733c71a47c5e392de4ee69e12d32dea561f77eaf6516a7f7e4aa2742ece9aad82974f5114dd16b8f28f0af1d53130fe
@@ -41,7 +41,7 @@ module ForestLiana
41
41
  if request.headers['Authorization']
42
42
  begin
43
43
  token = request.headers['Authorization'].split.second
44
- @jwt_decoded_token = JWT.decode(token, ForestLiana.auth_key, true, {
44
+ @jwt_decoded_token = JWT.decode(token, ForestLiana.auth_secret, true, {
45
45
  algorithm: 'HS256',
46
46
  leeway: 30
47
47
  }).try(:first)
@@ -55,7 +55,7 @@ module ForestLiana
55
55
  end
56
56
 
57
57
  def encode_token(user)
58
- if ForestLiana.auth_key.nil?
58
+ if ForestLiana.auth_secret.nil?
59
59
  @error_message = "Your Forest auth key seems to be missing. Can " \
60
60
  "you check that you properly set a Forest auth key in the " \
61
61
  "forest_liana initializer?"
@@ -82,7 +82,7 @@ module ForestLiana
82
82
  }
83
83
  }
84
84
  }
85
- }, ForestLiana.auth_key, 'HS256')
85
+ }, ForestLiana.auth_secret, 'HS256')
86
86
  end
87
87
  end
88
88
  end
@@ -0,0 +1,9 @@
1
+ module ForestLiana
2
+ module AdapterHelper
3
+ def self.format_column_name(table_name, column_name)
4
+ quoted_table_name = ActiveRecord::Base.connection.quote_table_name(table_name)
5
+ quoted_column_name = ActiveRecord::Base.connection.quote_column_name(column_name)
6
+ "#{quoted_table_name}.#{quoted_column_name}"
7
+ end
8
+ end
9
+ end
@@ -4,11 +4,13 @@ class ForestLiana::Model::Collection
4
4
  include ActiveModel::Serialization
5
5
  extend ActiveModel::Naming
6
6
 
7
- attr_accessor :name, :fields, :actions, :only_for_relationships, :is_virtual,
8
- :is_read_only, :is_searchable, :display_name, :icon, :pagination_type
7
+ attr_accessor :name, :fields, :actions, :segments, :only_for_relationships,
8
+ :is_virtual, :is_read_only, :is_searchable, :display_name, :icon,
9
+ :pagination_type
9
10
 
10
11
  def initialize(attributes = {})
11
12
  @actions = []
13
+ @segments = []
12
14
  @is_searchable = true
13
15
  @is_read_only = false
14
16
 
@@ -0,0 +1,20 @@
1
+ class ForestLiana::Model::Segment
2
+ include ActiveModel::Validations
3
+ include ActiveModel::Conversion
4
+ include ActiveModel::Serialization
5
+ extend ActiveModel::Naming
6
+
7
+ attr_accessor :id, :name, :scope, :where
8
+
9
+ def initialize(attributes = {}, &block)
10
+ attributes.each do |name, value|
11
+ send("#{name}=", value)
12
+ end
13
+
14
+ @where = block if block
15
+ end
16
+
17
+ def persisted?
18
+ false
19
+ end
20
+ end
@@ -17,6 +17,10 @@ class ForestLiana::CollectionSerializer
17
17
  object.actions
18
18
  end
19
19
 
20
+ has_many :segments do
21
+ object.segments
22
+ end
23
+
20
24
  def relationship_related_link(attribute_name)
21
25
  nil
22
26
  end
@@ -0,0 +1,15 @@
1
+ require 'jsonapi-serializers'
2
+
3
+ class ForestLiana::SegmentSerializer
4
+ include JSONAPI::Serializer
5
+
6
+ attribute :name
7
+
8
+ def relationship_related_link(attribute_name)
9
+ nil
10
+ end
11
+
12
+ def relationship_self_link(attribute_name)
13
+ nil
14
+ end
15
+ end
@@ -41,6 +41,8 @@ module ForestLiana
41
41
  "ForestLiana::CollectionSerializer"
42
42
  elsif active_record_class == ForestLiana::Model::Action
43
43
  "ForestLiana::ActionSerializer"
44
+ elsif active_record_class == ForestLiana::Model::Segment
45
+ "ForestLiana::SegmentSerializer"
44
46
  else
45
47
  class_name = active_record_class.table_name.classify
46
48
  module_name = class_name.deconstantize
@@ -9,7 +9,7 @@ module ForestLiana
9
9
  http.start do |client|
10
10
  request = Net::HTTP::Get.new(uri.path)
11
11
  request['Content-Type'] = 'application/json'
12
- request['forest-secret-key'] = ForestLiana.secret_key
12
+ request['forest-secret-key'] = ForestLiana.env_secret
13
13
  response = client.request(request)
14
14
 
15
15
  if response.is_a?(Net::HTTPOK)
@@ -23,7 +23,7 @@ module ForestLiana
23
23
  elsif response.is_a?(Net::HTTPNotFound)
24
24
  FOREST_LOGGER.error "Cannot retrieve the project you\'re trying " \
25
25
  "to unlock. Can you check that you properly copied the Forest " \
26
- "secret key in the forest_liana initializer?"
26
+ "env_secret in the forest_liana initializer?"
27
27
  else
28
28
  FOREST_LOGGER.error "Cannot retrieve any users for the project " \
29
29
  "you\'re trying to unlock. An error occured in Forest API."
@@ -12,8 +12,8 @@ module ForestLiana
12
12
  associated_records = @resource.find(@params[:id]).send(@association.name)
13
13
 
14
14
  if @data.is_a?(Array)
15
- @data.each do |record_deleted|
16
- associated_records << @association.klass.find(record_deleted[:id])
15
+ @data.each do |record_added|
16
+ associated_records << @association.klass.find(record_added[:id])
17
17
  end
18
18
  end
19
19
  end
@@ -7,12 +7,6 @@ module ForestLiana
7
7
  @field_names_requested = field_names_requested
8
8
  end
9
9
 
10
- def field_names_requested
11
- return nil unless @params[:fields] && @params[:fields][@association.table_name]
12
- @params[:fields][@association.table_name].split(',')
13
- .map { |name| name.to_sym }
14
- end
15
-
16
10
  def perform
17
11
  @records = @resource
18
12
  .unscoped
@@ -49,6 +43,12 @@ module ForestLiana
49
43
 
50
44
  private
51
45
 
46
+ def field_names_requested
47
+ return nil unless @params[:fields] && @params[:fields][@association.table_name]
48
+ @params[:fields][@association.table_name].split(',')
49
+ .map { |name| name.to_sym }
50
+ end
51
+
52
52
  def association_table_name
53
53
  @resource.reflect_on_association(@params[:association_name])
54
54
  .try(:table_name)
@@ -66,12 +66,10 @@ module ForestLiana
66
66
  end
67
67
 
68
68
  def limit
69
- return 10 unless pagination?
70
-
71
- if @params[:page][:size]
69
+ if @params[:page] && @params[:page][:size]
72
70
  @params[:page][:size].to_i
73
71
  else
74
- 10
72
+ 5
75
73
  end
76
74
  end
77
75
 
@@ -4,33 +4,21 @@ module ForestLiana
4
4
  @resource = resource
5
5
  @params = params
6
6
  @field_names_requested = field_names_requested
7
- end
8
-
9
- def field_names_requested
10
- return nil unless @params[:fields] && @params[:fields][@resource.table_name]
11
7
 
12
- associations_for_query = []
8
+ get_segment()
9
+ end
13
10
 
14
- # NOTICE: Populate the necessary associations for filters
15
- if @params[:filter]
16
- @params[:filter].each do |field, values|
17
- if field.include? ':'
18
- associations_for_query << field.split(':').first.to_sym
19
- end
20
- end
21
- end
11
+ def perform
12
+ @records = @resource.unscoped
22
13
 
23
- if @params[:sort] && @params[:sort].include?('.')
24
- associations_for_query << @params[:sort].split('.').first.to_sym
14
+ if @segment && @segment.scope
15
+ @records = @records.send(@segment.scope)
16
+ elsif @segment && @segment.where
17
+ @records = @records.where(@segment.where.call())
25
18
  end
26
19
 
27
- field_names = @params[:fields][@resource.table_name].split(',')
28
- .map { |name| name.to_sym }
29
- field_names | associations_for_query
30
- end
20
+ @records = @records.eager_load(includes)
31
21
 
32
- def perform
33
- @records = @resource.unscoped.eager_load(includes)
34
22
  @records = search_query
35
23
  @sorted_records = sort_query
36
24
  end
@@ -57,6 +45,41 @@ module ForestLiana
57
45
 
58
46
  private
59
47
 
48
+ def get_segment
49
+ if @params[:segment]
50
+ current_collection = ForestLiana.apimap.find do |collection|
51
+ collection.name.to_s == @resource.table_name
52
+ end
53
+
54
+ @segment = current_collection.segments.find do |segment|
55
+ segment.name == @params[:segment]
56
+ end
57
+ end
58
+ end
59
+
60
+ def field_names_requested
61
+ return nil unless @params[:fields] && @params[:fields][@resource.table_name]
62
+
63
+ associations_for_query = []
64
+
65
+ # NOTICE: Populate the necessary associations for filters
66
+ if @params[:filter]
67
+ @params[:filter].each do |field, values|
68
+ if field.include? ':'
69
+ associations_for_query << field.split(':').first.to_sym
70
+ end
71
+ end
72
+ end
73
+
74
+ if @params[:sort] && @params[:sort].include?('.')
75
+ associations_for_query << @params[:sort].split('.').first.to_sym
76
+ end
77
+
78
+ field_names = @params[:fields][@resource.table_name].split(',')
79
+ .map { |name| name.to_sym }
80
+ field_names | associations_for_query
81
+ end
82
+
60
83
  def search_query
61
84
  SearchQueryBuilder.new(@records, @params, includes).perform
62
85
  end
@@ -96,7 +119,8 @@ module ForestLiana
96
119
  .find {|a| a.name == ref.to_sym }
97
120
 
98
121
  if association
99
- "\"#{association.table_name}\".\"#{field}\""
122
+ ForestLiana::AdapterHelper
123
+ .format_column_name(association.table_name, field)
100
124
  else
101
125
  param
102
126
  end
@@ -24,11 +24,16 @@ module ForestLiana
24
24
  @records
25
25
  end
26
26
 
27
+ def format_column_name(table_name, column_name)
28
+ ForestLiana::AdapterHelper.format_column_name(table_name, column_name)
29
+ end
30
+
27
31
  def search_param
28
32
  if @params[:search]
29
33
  conditions = []
30
34
 
31
35
  @resource.columns.each_with_index do |column, index|
36
+ column_name = format_column_name(@resource.table_name, column.name)
32
37
  if column.name == 'id'
33
38
  if column.type == :integer
34
39
  conditions << "#{@resource.table_name}.id =
@@ -41,13 +46,11 @@ module ForestLiana
41
46
  elsif @resource.respond_to?(:defined_enums) &&
42
47
  @resource.defined_enums.has_key?(column.name) &&
43
48
  !@resource.defined_enums[column.name][@params[:search].downcase].nil?
44
- conditions << "\"#{@resource.table_name}\".\"#{column.name}\" =
49
+ conditions << "#{column_name} =
45
50
  #{@resource.defined_enums[column.name][@params[:search].downcase]}"
46
- elsif !column.array && (column.type == :string ||
47
- column.type == :text)
48
- conditions <<
49
- "LOWER(\"#{@resource.table_name}\".\"#{column.name}\") LIKE " +
50
- "'%#{@params[:search].downcase}%'"
51
+ elsif !(column.respond_to?(:array) && column.array) &&
52
+ (column.type == :string || column.type == :text)
53
+ conditions << "LOWER(#{column_name}) LIKE '%#{@params[:search].downcase}%'"
51
54
  end
52
55
  end
53
56
 
@@ -55,9 +58,11 @@ module ForestLiana
55
58
  if @includes.include? association.to_sym
56
59
  resource = @resource.reflect_on_association(association.to_sym)
57
60
  resource.klass.columns.each do |column|
58
- if !column.array && (column.type == :string || column.type == :text)
59
- conditions <<
60
- "LOWER(\"#{resource.table_name}\".\"#{column.name}\") LIKE " +
61
+ if !(column.respond_to?(:array) && column.array) &&
62
+ (column.type == :string || column.type == :text)
63
+ column_name = format_column_name(resource.table_name,
64
+ column.name)
65
+ conditions << "LOWER(#{column_name}) LIKE " +
61
66
  "'%#{@params[:search].downcase}%'"
62
67
  end
63
68
  end
data/lib/forest_liana.rb CHANGED
@@ -7,8 +7,12 @@ module ForestLiana
7
7
  module UserSpace
8
8
  end
9
9
 
10
+ # NOTICE: Deprecated secret value names
10
11
  mattr_accessor :secret_key
11
12
  mattr_accessor :auth_key
13
+
14
+ mattr_accessor :env_secret
15
+ mattr_accessor :auth_secret
12
16
  mattr_accessor :integrations
13
17
  mattr_accessor :apimap
14
18
  mattr_accessor :allowed_users
@@ -6,6 +6,15 @@ module ForestLiana
6
6
 
7
7
  @integration_stripe_valid = false
8
8
  @integration_intercom_valid = false
9
+
10
+ if ForestLiana.secret_key && ForestLiana.auth_key
11
+ FOREST_LOGGER.warn "DEPRECATION WARNING: The use of " \
12
+ "ForestLiana.secret_key and ForestLiana.auth_key " \
13
+ "(config/initializers/forest_liana.rb) is deprecated. Please use " \
14
+ "ForestLiana.env_secret and ForestLiana.auth_secret instead."
15
+ ForestLiana.env_secret = ForestLiana.secret_key
16
+ ForestLiana.auth_secret = ForestLiana.auth_key
17
+ end
9
18
  end
10
19
 
11
20
  def perform
@@ -13,7 +22,7 @@ module ForestLiana
13
22
  check_integrations_setup
14
23
  create_serializers
15
24
 
16
- if ForestLiana.secret_key
25
+ if ForestLiana.env_secret
17
26
  create_apimap
18
27
  require_lib_forest_liana
19
28
  send_apimap
@@ -136,14 +145,14 @@ module ForestLiana
136
145
  end
137
146
 
138
147
  def send_apimap
139
- if ForestLiana.secret_key && ForestLiana.secret_key.length != 64
140
- FOREST_LOGGER.error "Your secret key does not seem to be correct. " \
148
+ if ForestLiana.env_secret && ForestLiana.env_secret.length != 64
149
+ FOREST_LOGGER.error "Your env_secret does not seem to be correct. " \
141
150
  "Can you check on Forest that you copied it properly in the " \
142
151
  "forest_liana initializer?"
143
152
  else
144
153
  json = JSONAPI::Serializer.serialize(ForestLiana.apimap, {
145
154
  is_collection: true,
146
- include: ['actions'],
155
+ include: ['actions', 'segments'],
147
156
  meta: { liana: 'forest-rails', liana_version: liana_version }
148
157
  })
149
158
 
@@ -155,13 +164,13 @@ module ForestLiana
155
164
  request = Net::HTTP::Post.new(uri.path)
156
165
  request.body = json.to_json
157
166
  request['Content-Type'] = 'application/json'
158
- request['forest-secret-key'] = ForestLiana.secret_key
167
+ request['forest-secret-key'] = ForestLiana.env_secret
159
168
  response = client.request(request)
160
169
 
161
170
  # NOTICE: HTTP 404 Error
162
171
  if response.is_a?(Net::HTTPNotFound)
163
172
  FOREST_LOGGER.error "Cannot find the project related to the " \
164
- "secret key you configured. Can you check on Forest that you " \
173
+ "env_secret you configured. Can you check on Forest that you " \
165
174
  "copied it properly in the forest_liana initializer?"
166
175
  # NOTICE: HTTP 400 Error
167
176
  elsif response.is_a?(Net::HTTPBadRequest)
@@ -19,6 +19,12 @@ module ForestLiana::Collection
19
19
  model.actions << ForestLiana::Model::Action.new(opts)
20
20
  end
21
21
 
22
+ def segment(name, opts = {}, &block)
23
+ opts[:id] = "#{self.collection_name.to_s}.#{name}"
24
+ opts[:name] = name
25
+ model.segments << ForestLiana::Model::Segment.new(opts, &block)
26
+ end
27
+
22
28
  def field(name, opts, &block)
23
29
  opts[:read_only] = true unless opts.has_key?(:read_only)
24
30
  opts[:is_searchable] = false unless opts.has_key?(:is_searchable)
@@ -45,7 +45,7 @@ module ForestLiana
45
45
  app.eager_load!
46
46
 
47
47
  # NOTICE: Do not run the code below on rails g forest_liana:install.
48
- Bootstraper.new(app).perform if ForestLiana.secret_key
48
+ Bootstraper.new(app).perform if ForestLiana.env_secret || ForestLiana.secret_key
49
49
  end
50
50
  end
51
51
  end
@@ -1,3 +1,3 @@
1
1
  module ForestLiana
2
- VERSION = "1.4.7"
2
+ VERSION = "1.5.0"
3
3
  end
@@ -4,11 +4,35 @@ module ForestLiana
4
4
  class InstallGenerator < Rails::Generators::Base
5
5
  desc 'Forest Rails Liana installation generator'
6
6
 
7
+ argument :env_secret, type: :string, required: true, desc: 'required', banner: 'env_secret'
8
+
7
9
  def install
8
- secret_key = ask('What\'s your project secret key?')
9
- route("mount ForestLiana::Engine => '/forest'")
10
+ route "mount ForestLiana::Engine => '/forest'"
11
+
10
12
  initializer 'forest_liana.rb' do
11
- "ForestLiana.secret_key = '#{secret_key}'\nForestLiana.auth_key = '#{SecureRandom.urlsafe_base64}'"
13
+ "ForestLiana.env_secret = Rails.application.secrets.forest_env_secret" +
14
+ "\nForestLiana.auth_secret = Rails.application.secrets.forest_auth_secret"
15
+ end
16
+
17
+ auth_secret = SecureRandom.urlsafe_base64
18
+
19
+ puts "\nForest generated a random authentication secret to secure the " +
20
+ "data access of your local project.\nYou can change it at any time in " +
21
+ "your config/secrets.yml file.\n\n"
22
+
23
+ inject_into_file 'config/secrets.yml', after: "development:" do
24
+ "\n forest_env_secret: #{env_secret}" +
25
+ "\n forest_auth_secret: #{auth_secret}"
26
+ end
27
+
28
+ inject_into_file 'config/secrets.yml', after: "staging:", force: true do
29
+ "\n forest_env_secret: <%= ENV[\"FOREST_ENV_SECRET\"] %>" +
30
+ "\n forest_auth_secret: <%= ENV[\"FOREST_AUTH_SECRET\"] %>"
31
+ end
32
+
33
+ inject_into_file 'config/secrets.yml', after: "production:", force: true do
34
+ "\n forest_env_secret: <%= ENV[\"FOREST_ENV_SECRET\"] %>" +
35
+ "\n forest_auth_secret: <%= ENV[\"FOREST_AUTH_SECRET\"] %>"
12
36
  end
13
37
  end
14
38
  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.7
4
+ version: 1.5.0
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-12-05 00:00:00.000000000 Z
11
+ date: 2016-12-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -145,14 +145,17 @@ files:
145
145
  - app/controllers/forest_liana/stats_controller.rb
146
146
  - app/controllers/forest_liana/stripe_controller.rb
147
147
  - app/deserializers/forest_liana/resource_deserializer.rb
148
+ - app/helpers/forest_liana/adapter_helper.rb
148
149
  - app/helpers/forest_liana/application_helper.rb
149
150
  - app/models/forest_liana/model/action.rb
150
151
  - app/models/forest_liana/model/collection.rb
152
+ - app/models/forest_liana/model/segment.rb
151
153
  - app/models/forest_liana/model/stat.rb
152
154
  - app/serializers/forest_liana/action_serializer.rb
153
155
  - app/serializers/forest_liana/collection_serializer.rb
154
156
  - app/serializers/forest_liana/intercom_attribute_serializer.rb
155
157
  - app/serializers/forest_liana/intercom_conversation_serializer.rb
158
+ - app/serializers/forest_liana/segment_serializer.rb
156
159
  - app/serializers/forest_liana/serializer_factory.rb
157
160
  - app/serializers/forest_liana/session_serializer.rb
158
161
  - app/serializers/forest_liana/stat_serializer.rb
@@ -199,7 +202,6 @@ files:
199
202
  - lib/forest_liana/engine.rb
200
203
  - lib/forest_liana/version.rb
201
204
  - lib/generators/forest_liana/install_generator.rb
202
- - lib/tasks/forest_tasks.rake
203
205
  - test/dummy/README.rdoc
204
206
  - test/dummy/Rakefile
205
207
  - test/dummy/app/assets/javascripts/application.js
@@ -1,4 +0,0 @@
1
- # desc "Explaining what the task does"
2
- # task :forest do
3
- # # Task goes here
4
- # end