forest_liana 1.4.7 → 1.5.0

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