forest_liana 1.1.22 → 1.1.23

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: 21865b20b7689f8391863232851fae17d931a22f
4
- data.tar.gz: f9fc1e5fcaee763363eb1cf08f938f729e34a4fa
3
+ metadata.gz: 1667b0443d65ca46628d3b67e05151ada194709e
4
+ data.tar.gz: 06ff809ebc4268988858885178755da79bca03e7
5
5
  SHA512:
6
- metadata.gz: 59ea6edeb1719c0f12cc49a99610cbd2ce5117d9347569602814c8efe7f3bc87c4af283ed570bc1d5a82c8a00a3593f6766188de8e9c736bf2aa3d37a771aa95
7
- data.tar.gz: be1c07ed787bee9dfcbf38a7153d7c624afb280c7cb8c36601de06c60377bb07b3dd6863effb233c3e32d83e4814c139ed2eae21d2942ce5df1b6a8680e65a3e
6
+ metadata.gz: cd67e80fa3f3c6cb3f1f179b754805e255ebf69bc2e5551c38e8e1a3859714beabb5a7b9319f188260b69a5559bb8795c0a4ffa6982888dba6690c2fdcef56b0
7
+ data.tar.gz: 65eca07f4f24cc212e37f6fd4c8350bfc257a6364ea1f8df0b5384bfa679a0ba7ea453fcd24452c375c60d5ff503aab7a9ddf2ac01a46da8af57e764e6fde0f7
@@ -0,0 +1,17 @@
1
+ module ForestLiana
2
+ class IntercomController < ForestLiana::ApplicationController
3
+ def user_conversations
4
+ getter = IntercomConversationsGetter.new(params)
5
+ getter.perform
6
+
7
+ render json: serialize_models(getter.records, { count: getter.count })
8
+ end
9
+
10
+ def attributes
11
+ getter = IntercomAttributesGetter.new(params)
12
+ getter.perform
13
+
14
+ render json: serialize_model(getter.records)
15
+ end
16
+ end
17
+ end
@@ -47,6 +47,5 @@ module ForestLiana
47
47
  include: ['customer']
48
48
  })
49
49
  end
50
-
51
50
  end
52
51
  end
@@ -4,10 +4,12 @@ class ForestLiana::Model::Collection
4
4
  include ActiveModel::Serialization
5
5
  extend ActiveModel::Naming
6
6
 
7
- attr_accessor :name, :fields, :actions
7
+ attr_accessor :name, :fields, :actions, :only_for_relationships, :is_virtual,
8
+ :is_read_only, :is_searchable
8
9
 
9
10
  def initialize(attributes = {})
10
11
  @actions = []
12
+ @is_searchable = true
11
13
 
12
14
  attributes.each do |name, value|
13
15
  send("#{name}=", value)
@@ -5,6 +5,10 @@ class ForestLiana::CollectionSerializer
5
5
 
6
6
  attribute :name
7
7
  attribute :fields
8
+ attribute :only_for_relationships
9
+ attribute :is_virtual
10
+ attribute :is_read_only
11
+ attribute :is_searchable
8
12
 
9
13
  has_many :actions do
10
14
  object.actions
@@ -0,0 +1,85 @@
1
+ module ForestLiana
2
+ class IntercomAttributeSerializer
3
+ include JSONAPI::Serializer
4
+
5
+ attribute :session_count
6
+ attribute :last_seen_ip
7
+
8
+ attribute :created_at do
9
+ object.created_at.utc.try(:iso8601)
10
+ end
11
+
12
+ attribute :updated_at do
13
+ object.updated_at.utc.try(:iso8601)
14
+ end
15
+
16
+ attribute :signed_up_at do
17
+ object.signed_up_at.utc.try(:iso8601)
18
+ end
19
+
20
+ attribute :last_request_at do
21
+ object.last_request_at.utc.try(:iso8601)
22
+ end
23
+
24
+ attribute :country do
25
+ object.location_data.country_name
26
+ end
27
+
28
+ attribute :city do
29
+ object.location_data.city_name
30
+ end
31
+
32
+ attribute :user_agent do
33
+ object.user_agent_data
34
+ end
35
+
36
+ attribute :companies do
37
+ object.companies.map(&:name)
38
+ end
39
+
40
+ attribute :segments do
41
+ object.segments.map(&:name)
42
+ end
43
+
44
+ attribute :tags do
45
+ object.tags.map(&:name)
46
+ end
47
+
48
+ attribute :browser do
49
+ useragent = UserAgent.parse(object.user_agent_data)
50
+ "#{useragent.try(:browser)} #{useragent.try(:version)}"
51
+ end
52
+
53
+ attribute :platform do
54
+ UserAgent.parse(object.user_agent_data).try(:platform)
55
+ end
56
+
57
+ attribute :geoloc do
58
+ [object.location_data.latitude, object.location_data.longitude]
59
+ end
60
+
61
+ def self_link
62
+ "/forest#{super}"
63
+ end
64
+
65
+ def type
66
+ 'intercom-attributes'
67
+ end
68
+
69
+ def format_name(attribute_name)
70
+ attribute_name.to_s
71
+ end
72
+
73
+ def unformat_name(attribute_name)
74
+ attribute_name.to_s.underscore
75
+ end
76
+
77
+ def relationship_self_link(attribute_name)
78
+ nil
79
+ end
80
+
81
+ def relationship_related_link(attribute_name)
82
+ nil
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,46 @@
1
+ module ForestLiana
2
+ class IntercomConversationSerializer
3
+ include JSONAPI::Serializer
4
+
5
+ attribute :created_at
6
+ attribute :updated_at
7
+ attribute :open
8
+ attribute :read
9
+
10
+ attribute :subject do
11
+ object.conversation_message.subject
12
+ end
13
+
14
+ attribute :body do
15
+ [object.conversation_message.body, object.link]
16
+ end
17
+
18
+ attribute :assignee do
19
+ object.assignee.try(:email)
20
+ end
21
+
22
+ def self_link
23
+ "/forest#{super}"
24
+ end
25
+
26
+ def type
27
+ 'intercom-conversations'
28
+ end
29
+
30
+ def format_name(attribute_name)
31
+ attribute_name.to_s
32
+ end
33
+
34
+ def unformat_name(attribute_name)
35
+ attribute_name.to_s.underscore
36
+ end
37
+
38
+ def relationship_self_link(attribute_name)
39
+ nil
40
+ end
41
+
42
+ def relationship_related_link(attribute_name)
43
+ nil
44
+ end
45
+ end
46
+ end
@@ -14,7 +14,11 @@ module ForestLiana
14
14
  end
15
15
 
16
16
  def self.get_serializer_name(active_record_class)
17
- if active_record_class == Stripe::Charge
17
+ if active_record_class == ::Intercom::Conversation
18
+ "ForestLiana::IntercomConversationSerializer"
19
+ elsif active_record_class == ::Intercom::User
20
+ "ForestLiana::IntercomAttributeSerializer"
21
+ elsif active_record_class == Stripe::Charge
18
22
  "ForestLiana::StripePaymentSerializer"
19
23
  elsif active_record_class == Stripe::Card
20
24
  "ForestLiana::StripeCardSerializer"
@@ -64,22 +68,58 @@ module ForestLiana
64
68
  def relationship_related_link(attribute_name)
65
69
  ret = {}
66
70
 
67
- relationship_records = object.send(attribute_name)
68
- if relationship_records.respond_to?(:each)
69
-
70
- if Rails::VERSION::MAJOR == 4
71
- ret[:href] = "/forest/#{object.class.table_name}/#{object.id}/#{attribute_name}"
72
- ret[:meta] = { count: relationship_records.distinct.count }
73
- else
74
- ret[:href] = "/forest/#{object.class.table_name}/#{object.id}/#{attribute_name}"
75
- ret[:meta] = {
76
- count: relationship_records.count(:id, distinct: true)
77
- }
71
+ if intercom_integration?
72
+ case attribute_name
73
+ when :intercom_conversations
74
+ ret[:href] = "/forest/#{object.class.table_name}/#{object.id}/intercom_conversations"
75
+ when :intercom_attributes
76
+ ret[:href] = "/forest/#{object.class.table_name}/#{object.id}/intercom_attributes"
77
+ end
78
+ end
79
+
80
+ if stripe_integration?
81
+ case attribute_name
82
+ when :stripe_payments
83
+ ret[:href] = "/forest/#{object.class.table_name}/#{object.id}/stripe_payments"
84
+ when :stripe_invoices
85
+ ret[:href] = "/forest/#{object.class.table_name}/#{object.id}/stripe_invoices"
86
+ when :stripe_cards
87
+ ret[:href] = "/forest/#{object.class.table_name}/#{object.id}/stripe_cards"
88
+ end
89
+ end
90
+
91
+ if ret[:href].blank?
92
+ relationship_records = object.send(attribute_name)
93
+
94
+ if relationship_records.respond_to?(:each)
95
+ if Rails::VERSION::MAJOR == 4
96
+ ret[:href] = "/forest/#{object.class.table_name}/#{object.id}/#{attribute_name}"
97
+ ret[:meta] = { count: relationship_records.distinct.count }
98
+ else
99
+ ret[:href] = "/forest/#{object.class.table_name}/#{object.id}/#{attribute_name}"
100
+ ret[:meta] = {
101
+ count: relationship_records.count(:id, distinct: true)
102
+ }
103
+ end
78
104
  end
79
105
  end
80
106
 
81
107
  ret
82
108
  end
109
+
110
+ private
111
+
112
+ def intercom_integration?
113
+ object.class.name == ForestLiana.integrations
114
+ .try(:[], :intercom)
115
+ .try(:[], :user_collection)
116
+ end
117
+
118
+ def stripe_integration?
119
+ object.class.name == ForestLiana.integrations
120
+ .try(:[], :stripe)
121
+ .try(:[], :user_collection)
122
+ end
83
123
  }
84
124
 
85
125
  attributes(active_record_class).each do |attr|
@@ -97,6 +137,21 @@ module ForestLiana
97
137
  serializer.send(serializer_association(a), a.name)
98
138
  end
99
139
 
140
+ # Intercom
141
+ if active_record_class.name == ForestLiana.integrations
142
+ .try(:[], :intercom).try(:[], :user_collection)
143
+ serializer.send(:has_many, :intercom_conversations) { }
144
+ serializer.send(:has_many, :intercom_attributes) { }
145
+ end
146
+
147
+ # Stripe
148
+ if active_record_class.name == ForestLiana.integrations
149
+ .try(:[], :stripe).try(:[], :user_collection)
150
+ serializer.send(:has_many, :stripe_payments) { }
151
+ serializer.send(:has_many, :stripe_invoices) { }
152
+ serializer.send(:has_many, :stripe_cards) { }
153
+ end
154
+
100
155
  SerializerFactory.define_serializer(active_record_class, serializer)
101
156
 
102
157
  serializer
@@ -130,6 +185,5 @@ module ForestLiana
130
185
  def foreign_keys(active_record_class)
131
186
  SchemaUtils.associations(active_record_class).map(&:foreign_key)
132
187
  end
133
-
134
188
  end
135
189
  end
@@ -0,0 +1,44 @@
1
+ module ForestLiana
2
+ class IntercomAttributesGetter
3
+ attr_accessor :records
4
+
5
+ def initialize(params)
6
+ @params = params
7
+ @intercom = ::Intercom::Client.new(
8
+ app_id: ForestLiana.integrations[:intercom][:app_id],
9
+ api_key: ForestLiana.integrations[:intercom][:api_key])
10
+ end
11
+
12
+ def count
13
+ @records.count
14
+ end
15
+
16
+ def perform
17
+ resource = user_collection.find(@params[:id])
18
+
19
+ begin
20
+ user = @intercom.users.find(email: resource.email)
21
+
22
+ user.segments = user.segments.map do |segment|
23
+ @intercom.segments.find(id: segment.id)
24
+ end
25
+
26
+ @records = user
27
+ rescue Intercom::ResourceNotFound
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def user_collection
34
+ ForestLiana.integrations
35
+ .try(:[], :intercom)
36
+ .try(:[], :user_collection)
37
+ .try(:constantize)
38
+ end
39
+
40
+ def user_collection?
41
+ user_collection.present?
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,87 @@
1
+ module ForestLiana
2
+ class IntercomConversationsGetter
3
+ def initialize(params)
4
+ @params = params
5
+ @app_id = ForestLiana.integrations[:intercom][:app_id]
6
+ @api_key = ForestLiana.integrations[:intercom][:api_key]
7
+
8
+ @intercom = ::Intercom::Client.new(app_id: @app_id, api_key: @api_key)
9
+ end
10
+
11
+ def count
12
+ @records.count
13
+ end
14
+
15
+ def records
16
+ @records[pagination].map do |conversation|
17
+ if conversation.assignee.is_a?(::Intercom::Admin)
18
+ admins = @intercom.admins.all.detect(id: conversation.assignee.id)
19
+ conversation.assignee = admins.first
20
+ end
21
+
22
+ conversation.link = link(conversation)
23
+
24
+ conversation
25
+ end
26
+ end
27
+
28
+ def perform
29
+ begin
30
+ resource = user_collection.find(@params[:id])
31
+ @records = @intercom.conversations.find_all(
32
+ email: resource.email,
33
+ type: 'user',
34
+ display_as: 'plaintext',
35
+ ).entries
36
+ rescue Intercom::ResourceNotFound
37
+ @records = []
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def user_collection
44
+ ForestLiana.integrations
45
+ .try(:[], :intercom)
46
+ .try(:[], :user_collection)
47
+ .try(:constantize)
48
+ end
49
+
50
+ def user_collection?
51
+ user_collection.present?
52
+ end
53
+
54
+ def link(conversation)
55
+ "#{@intercom.base_url}/a/apps/#{@app_id}/inbox/all/conversations/#{conversation.id}"
56
+ end
57
+
58
+ def pagination
59
+ offset..(offset + limit - 1)
60
+ end
61
+
62
+ def offset
63
+ return 0 unless pagination?
64
+
65
+ number = @params[:page][:number]
66
+ if number && number.to_i > 0
67
+ (number.to_i - 1) * limit
68
+ else
69
+ 0
70
+ end
71
+ end
72
+
73
+ def limit
74
+ return 10 unless pagination?
75
+
76
+ if @params[:page][:size]
77
+ @params[:page][:size].to_i
78
+ else
79
+ 10
80
+ end
81
+ end
82
+
83
+ def pagination?
84
+ @params[:page] && @params[:page][:number]
85
+ end
86
+ end
87
+ end
@@ -23,6 +23,54 @@ module ForestLiana
23
23
  @collection.fields << get_schema_for_column(column)
24
24
  end
25
25
 
26
+ # Intercom
27
+ if ForestLiana.integrations.try(:[], :intercom)
28
+ .try(:[], :user_collection) == @model.name
29
+ @collection.fields << {
30
+ field: :intercom_conversations,
31
+ type: ['String'],
32
+ reference: 'intercom_conversations.id',
33
+ column: nil,
34
+ is_searchable: false
35
+ }
36
+
37
+ @collection.fields << {
38
+ field: :intercom_attributes,
39
+ type: 'String',
40
+ reference: 'intercom_attributes.id',
41
+ column: nil,
42
+ is_searchable: false
43
+ }
44
+ end
45
+
46
+ # Stripe
47
+ if ForestLiana.integrations.try(:[], :stripe)
48
+ .try(:[], :user_collection) == @model.name
49
+ @collection.fields << {
50
+ field: :stripe_payments,
51
+ type: ['String'],
52
+ reference: 'stripe_payments.id',
53
+ column: nil,
54
+ is_searchable: false
55
+ }
56
+
57
+ @collection.fields << {
58
+ field: :stripe_invoices,
59
+ type: ['String'],
60
+ reference: 'stripe_invoices.id',
61
+ column: nil,
62
+ is_searchable: false
63
+ }
64
+
65
+ @collection.fields << {
66
+ field: :stripe_cards,
67
+ type: ['String'],
68
+ reference: 'stripe_cards.id',
69
+ column: nil,
70
+ is_searchable: false
71
+ }
72
+ end
73
+
26
74
  # Paperclip url attribute
27
75
  if @model.respond_to?(:attachment_definitions)
28
76
  @model.attachment_definitions.each do |key, value|
@@ -4,7 +4,6 @@ module ForestLiana
4
4
 
5
5
  def initialize(params, secret_key, reference)
6
6
  @params = params
7
- @reference_model, @reference_field = reference_model(reference)
8
7
  Stripe.api_key = ForestLiana.integrations[:stripe][:api_key]
9
8
  end
10
9
 
@@ -16,8 +15,8 @@ module ForestLiana
16
15
  params = { limit: limit, offset: offset, object: 'card' }
17
16
  params['include[]'] = 'total_count'
18
17
 
19
- resource = @reference_model.find(reference_model_id)
20
- customer = resource[@reference_field]
18
+ resource = user_collection.find(@params[:id])
19
+ customer = resource[user_field]
21
20
 
22
21
  if customer.blank?
23
22
  @records = []
@@ -35,24 +34,13 @@ module ForestLiana
35
34
 
36
35
  @records = @cards.data.map do |d|
37
36
  query = {}
38
- query[@reference_field] = d.customer
39
- d.customer = @reference_model.find_by(query)
37
+ query[user_field] = d.customer
38
+ d.customer = user_collection.find_by(query)
40
39
 
41
40
  d
42
41
  end
43
42
  end
44
43
 
45
- def reference_model(reference)
46
- resource_name, reference_field = reference.split('.')
47
- reference_model = SchemaUtils.find_model_from_table_name(resource_name)
48
-
49
- [reference_model, reference_field]
50
- end
51
-
52
- def reference_model_id
53
- @params["#{@reference_model.table_name.singularize()}Id"]
54
- end
55
-
56
44
  def offset
57
45
  return 0 unless pagination?
58
46
 
@@ -77,5 +65,18 @@ module ForestLiana
77
65
  def pagination?
78
66
  @params[:page] && @params[:page][:number]
79
67
  end
68
+
69
+ def user_collection
70
+ ForestLiana.integrations
71
+ .try(:[], :stripe)
72
+ .try(:[], :user_collection)
73
+ .try(:constantize)
74
+ end
75
+
76
+ def user_field
77
+ ForestLiana.integrations
78
+ .try(:[], :stripe)
79
+ .try(:[], :user_field)
80
+ end
80
81
  end
81
82
  end
@@ -4,7 +4,6 @@ module ForestLiana
4
4
 
5
5
  def initialize(params, secret_key, reference)
6
6
  @params = params
7
- @reference_model, @reference_field = reference_model(reference)
8
7
  Stripe.api_key = ForestLiana.integrations[:stripe][:api_key]
9
8
  end
10
9
 
@@ -15,9 +14,9 @@ module ForestLiana
15
14
  def perform
16
15
  query = { limit: limit, offset: offset }
17
16
 
18
- if reference_model_id
19
- resource = @reference_model.find(reference_model_id)
20
- query[:customer] = resource[@reference_field]
17
+ if @params[:id] && user_collection && user_field
18
+ resource = user_collection.find(@params[:id])
19
+ query[:customer] = resource[user_field]
21
20
  end
22
21
 
23
22
  query['include[]'] = 'total_count'
@@ -36,9 +35,9 @@ module ForestLiana
36
35
  d.amount_due /= 100.00
37
36
 
38
37
  query = {}
39
- query[@reference_field] = d.customer
40
- if @reference_model
41
- d.customer = @reference_model.find_by(query)
38
+ query[user_field] = d.customer
39
+ if user_collection
40
+ d.customer = user_collection.find_by(query)
42
41
  else
43
42
  d.customer = nil
44
43
  end
@@ -48,23 +47,10 @@ module ForestLiana
48
47
  end
49
48
 
50
49
  def fetch_invoices(params)
51
- return if reference_model_id && params[:customer].blank?
50
+ return if @params[:id] && params[:customer].blank?
52
51
  Stripe::Invoice.all(params)
53
52
  end
54
53
 
55
- def reference_model(reference)
56
- resource_name, reference_field = reference.split('.')
57
- reference_model = SchemaUtils.find_model_from_table_name(resource_name)
58
-
59
- [reference_model, reference_field]
60
- end
61
-
62
- def reference_model_id
63
- if @reference_model
64
- @params["#{@reference_model.table_name.singularize()}Id"]
65
- end
66
- end
67
-
68
54
  def offset
69
55
  return 0 unless pagination?
70
56
 
@@ -90,6 +76,18 @@ module ForestLiana
90
76
  @params[:page] && @params[:page][:number]
91
77
  end
92
78
 
79
+ def user_collection
80
+ ForestLiana.integrations
81
+ .try(:[], :stripe)
82
+ .try(:[], :user_collection)
83
+ .try(:constantize)
84
+ end
85
+
86
+ def user_field
87
+ ForestLiana.integrations
88
+ .try(:[], :stripe)
89
+ .try(:[], :user_field)
90
+ end
93
91
  end
94
92
  end
95
93
 
@@ -4,7 +4,6 @@ module ForestLiana
4
4
 
5
5
  def initialize(params, secret_key, reference)
6
6
  @params = params
7
- @reference_model, @reference_field = reference_model(reference)
8
7
  Stripe.api_key = ForestLiana.integrations[:stripe][:api_key]
9
8
  end
10
9
 
@@ -15,9 +14,9 @@ module ForestLiana
15
14
  def perform
16
15
  query = { limit: limit, offset: offset }
17
16
 
18
- if reference_model_id
19
- resource = @reference_model.find(reference_model_id)
20
- query[:customer] = resource[@reference_field]
17
+ if @params[:id] && user_collection && user_field
18
+ resource = user_collection.find(@params[:id])
19
+ query[:customer] = resource[user_field]
21
20
  end
22
21
 
23
22
  query['source'] = { object: :card }
@@ -34,9 +33,9 @@ module ForestLiana
34
33
  d.amount /= 100.00
35
34
 
36
35
  query = {}
37
- query[@reference_field] = d.customer
38
- if @reference_model
39
- d.customer = @reference_model.find_by(query)
36
+ query[user_field] = d.customer
37
+ if user_collection
38
+ d.customer = user_collection.find_by(query)
40
39
  else
41
40
  d.customer = nil
42
41
  end
@@ -46,23 +45,10 @@ module ForestLiana
46
45
  end
47
46
 
48
47
  def fetch_charges(params)
49
- return if reference_model_id && params[:customer].blank?
48
+ return if @params[:id] && params[:customer].blank?
50
49
  Stripe::Charge.all(params)
51
50
  end
52
51
 
53
- def reference_model(reference)
54
- resource_name, reference_field = reference.split('.')
55
- reference_model = SchemaUtils.find_model_from_table_name(resource_name)
56
-
57
- [reference_model, reference_field]
58
- end
59
-
60
- def reference_model_id
61
- if @reference_model
62
- @params["#{@reference_model.table_name.singularize()}Id"]
63
- end
64
- end
65
-
66
52
  def offset
67
53
  return 0 unless pagination?
68
54
 
@@ -88,5 +74,17 @@ module ForestLiana
88
74
  @params[:page] && @params[:page][:number]
89
75
  end
90
76
 
77
+ def user_collection
78
+ ForestLiana.integrations
79
+ .try(:[], :stripe)
80
+ .try(:[], :user_collection)
81
+ .try(:constantize)
82
+ end
83
+
84
+ def user_field
85
+ ForestLiana.integrations
86
+ .try(:[], :stripe)
87
+ .try(:[], :user_field)
88
+ end
91
89
  end
92
90
  end
@@ -0,0 +1 @@
1
+ Time::DATE_FORMATS[:forest_datetime] = "%d/%m/%Y %H:%M:%S"
data/config/routes.rb CHANGED
@@ -1,9 +1,15 @@
1
1
  ForestLiana::Engine.routes.draw do
2
2
  # Stripe Integration
3
3
  get 'stripe_payments' => 'stripe#payments'
4
+ get ':collection/:id/stripe_payments' => 'stripe#payments'
4
5
  post 'stripe_payments/refunds' => 'stripe#refund'
5
- get 'stripe_cards' => 'stripe#cards'
6
6
  get 'stripe_invoices' => 'stripe#invoices'
7
+ get ':collection/:id/stripe_invoices' => 'stripe#invoices'
8
+ get ':collection/:id/stripe_cards' => 'stripe#cards'
9
+
10
+ # Intercom Integration
11
+ get ':collection/:id/intercom_conversations' => 'intercom#user_conversations'
12
+ get ':collection/:id/intercom_attributes' => 'intercom#attributes'
7
13
 
8
14
  # Stats
9
15
  post '/stats/:collection' => 'stats#show'
@@ -0,0 +1,228 @@
1
+ module ForestLiana
2
+ class Bootstraper
3
+
4
+ def initialize(app)
5
+ @app = app
6
+ @logger = Logger.new(STDOUT)
7
+ end
8
+
9
+ def perform
10
+ create_serializers
11
+
12
+ if ForestLiana.jwt_signing_key
13
+ create_apimap
14
+ send_apimap
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def create_serializers
21
+ SchemaUtils.tables_names.map do |table_name|
22
+ model = SchemaUtils.find_model_from_table_name(table_name)
23
+ SerializerFactory.new.serializer_for(model) if \
24
+ model.try(:table_exists?)
25
+ end
26
+
27
+ # Monkey patch the find_serializer_class_name method to specify the
28
+ # good serializer to use.
29
+ JSONAPI::Serializer.class_eval do
30
+ def self.find_serializer_class_name(obj)
31
+ SerializerFactory.get_serializer_name(obj.class)
32
+ end
33
+ end
34
+ end
35
+
36
+ def create_apimap
37
+ SchemaUtils.tables_names.map do |table_name|
38
+ model = SchemaUtils.find_model_from_table_name(table_name)
39
+ if model.try(:table_exists?)
40
+ ForestLiana.apimap << SchemaAdapter.new(model).perform
41
+ end
42
+ end
43
+
44
+ Dir["#{@app.root}/app/models/forest/*.rb"].each {|file| require file }
45
+
46
+ setup_stripe_integration if stripe_integration?
47
+ setup_intercom_integration if intercom_integration?
48
+ end
49
+
50
+ def send_apimap
51
+ json = JSONAPI::Serializer.serialize(ForestLiana.apimap, {
52
+ is_collection: true,
53
+ include: ['actions'],
54
+ meta: { liana: 'forest-rails', liana_version: liana_version }
55
+ })
56
+
57
+ uri = URI.parse("#{forest_url}/forest/apimaps")
58
+ http = Net::HTTP.new(uri.host, uri.port)
59
+ http.use_ssl = true if forest_url.start_with?('https')
60
+ http.start do |client|
61
+ request = Net::HTTP::Post.new(uri.path)
62
+ request.body = json.to_json
63
+ request['Content-Type'] = 'application/json'
64
+ request['forest-secret-key'] = ForestLiana.jwt_signing_key
65
+ response = client.request(request)
66
+
67
+ if response.is_a?(Net::HTTPNotFound)
68
+ @logger.warn "Forest cannot find your project secret key. " \
69
+ "Please, run `rails g forest_liana:install`."
70
+ end
71
+ end
72
+ end
73
+
74
+ def setup_intercom_integration
75
+ ForestLiana.apimap << ForestLiana::Model::Collection.new({
76
+ name: 'intercom_conversations',
77
+ only_for_relationships: true,
78
+ is_virtual: true,
79
+ fields: [
80
+ { field: :subject, type: 'String' },
81
+ { field: :body, type: ['String'], widget: 'link' },
82
+ { field: :open, type: 'Boolean'},
83
+ { field: :read, type: 'Boolean'},
84
+ { field: :assignee, type: 'String' }
85
+ ]
86
+ })
87
+
88
+ ForestLiana.apimap << ForestLiana::Model::Collection.new({
89
+ name: 'intercom_attributes',
90
+ only_for_relationships: true,
91
+ is_virtual: true,
92
+ fields: [
93
+ { field: :created_at, type: 'Date', is_searchable: false },
94
+ { field: :updated_at, type: 'Date', is_searchable: false },
95
+ { field: :session_count, type: 'Number', is_searchable: false },
96
+ { field: :last_seen_ip, type: 'String', is_searchable: false },
97
+ { field: :signed_up_at, type: 'Date', is_searchable: false },
98
+ { field: :country, type: 'String', is_searchable: false },
99
+ { field: :city, type: 'String', is_searchable: false },
100
+ { field: :browser, type: 'String', is_searchable: false },
101
+ { field: :platform, type: 'String', is_searchable: false },
102
+ { field: :companies, type: 'String', is_searchable: false },
103
+ { field: :segments, type: 'String', is_searchable: false },
104
+ { field: :tags, type: 'String', is_searchable: false },
105
+ {
106
+ field: :geoloc,
107
+ type: 'String',
108
+ widget: 'google map',
109
+ is_searchable: false
110
+ }
111
+ ]
112
+ })
113
+ end
114
+
115
+ def intercom_integration?
116
+ ForestLiana.integrations
117
+ .try(:[], :intercom)
118
+ .try(:[], :user_collection)
119
+ .present?
120
+ end
121
+
122
+ def setup_stripe_integration
123
+ ForestLiana.apimap << ForestLiana::Model::Collection.new({
124
+ name: 'stripe_payments',
125
+ is_virtual: true,
126
+ is_read_only: true,
127
+ fields: [
128
+ { field: :id, type: 'String', is_searchable: false },
129
+ { field: :created, type: 'Date', is_searchable: false },
130
+ { field: :amount, type: 'Number', is_searchable: false },
131
+ { field: :status, type: 'String', is_searchable: false },
132
+ { field: :currency, type: 'String', is_searchable: false },
133
+ { field: :refunded, type: 'Boolean', is_searchable: false },
134
+ { field: :description, type: 'String', is_searchable: false },
135
+ {
136
+ field: :customer,
137
+ type: 'String',
138
+ reference: 'customers.id',
139
+ is_searchable: false
140
+ }
141
+ ],
142
+ actions: [
143
+ ForestLiana::Model::Action.new({
144
+ name: 'Refund',
145
+ endpoint: '/forest/stripe_payments/refunds'
146
+ })
147
+ ]
148
+ })
149
+
150
+ ForestLiana.apimap << ForestLiana::Model::Collection.new({
151
+ name: 'stripe_invoices',
152
+ is_virtual: true,
153
+ is_read_only: true,
154
+ fields: [
155
+ { field: :id, type: 'String', is_searchable: false },
156
+ { field: :amount_due, type: 'Number', is_searchable: false },
157
+ { field: :attempt_count, type: 'Number', is_searchable: false },
158
+ { field: :attempted, type: 'Boolean', is_searchable: false },
159
+ { field: :closed, type: 'Boolean', is_searchable: false },
160
+ { field: :currency, type: 'String', is_searchable: false },
161
+ { field: :date, type: 'Date', is_searchable: false },
162
+ { field: :forgiven, type: 'Boolean', is_searchable: false },
163
+ { field: :period_start, type: 'Date', is_searchable: false },
164
+ { field: :period_end, type: 'Date', is_searchable: false },
165
+ { field: :subtotal, type: 'Number', is_searchable: false },
166
+ { field: :total, type: 'Number', is_searchable: false },
167
+ { field: :application_fee, type: 'Number', is_searchable: false },
168
+ { field: :tax, type: 'Number', is_searchable: false },
169
+ { field: :tax_percent, type: 'Number', is_searchable: false },
170
+ {
171
+ field: :customer,
172
+ type: 'String',
173
+ reference: 'customers.id',
174
+ is_searchable: false
175
+ }
176
+ ]
177
+ })
178
+
179
+ ForestLiana.apimap << ForestLiana::Model::Collection.new({
180
+ name: 'stripe_cards',
181
+ is_virtual: true,
182
+ is_read_only: true,
183
+ only_for_relationships: true,
184
+ fields: [
185
+ { field: :id, type: 'String', is_searchable: false },
186
+ { field: :last4, type: 'String', is_searchable: false },
187
+ { field: :brand, type: 'String', is_searchable: false },
188
+ { field: :funding, type: 'String', is_searchable: false },
189
+ { field: :exp_month, type: 'Number', is_searchable: false },
190
+ { field: :exp_year, type: 'Number', is_searchable: false },
191
+ { field: :country, type: 'String', is_searchable: false },
192
+ { field: :name, type: 'String', is_searchable: false },
193
+ { field: :address_line1, type: 'String', is_searchable: false },
194
+ { field: :address_line2, type: 'String', is_searchable: false },
195
+ { field: :address_city, type: 'String', is_searchable: false },
196
+ { field: :address_state, type: 'String', is_searchable: false },
197
+ { field: :address_zip, type: 'String', is_searchable: false },
198
+ { field: :address_country, type: 'String', is_searchable: false },
199
+ { field: :cvc_check, type: 'String', is_searchable: false },
200
+ {
201
+ field: :customer,
202
+ type: 'String',
203
+ reference: 'customers.id',
204
+ is_searchable: false
205
+ }
206
+ ]
207
+ })
208
+ end
209
+
210
+ def stripe_integration?
211
+ ForestLiana.integrations
212
+ .try(:[], :stripe)
213
+ .try(:[], :api_key)
214
+ .present?
215
+ end
216
+
217
+ def forest_url
218
+ ENV['FOREST_URL'] || 'https://forestadmin-server.herokuapp.com';
219
+ end
220
+
221
+ def liana_version
222
+ Gem::Specification.find_all_by_name('forest_liana')
223
+ .try(:first)
224
+ .try(:version)
225
+ .try(:to_s)
226
+ end
227
+ end
228
+ end
@@ -2,12 +2,14 @@ require 'rack/cors'
2
2
  require 'stripe'
3
3
  require 'jsonapi-serializers'
4
4
  require 'groupdate'
5
- require "net/http"
5
+ require 'net/http'
6
+ require 'intercom'
7
+ require 'useragent'
8
+ require_relative 'bootstraper'
6
9
 
7
10
  module ForestLiana
8
11
  class Engine < ::Rails::Engine
9
12
  isolate_namespace ForestLiana
10
- logger = Logger.new(STDOUT)
11
13
 
12
14
  config.middleware.insert_before 0, 'Rack::Cors' do
13
15
  allow do
@@ -18,59 +20,8 @@ module ForestLiana
18
20
  end
19
21
 
20
22
  config.after_initialize do |app|
21
- unless Rails.env.test?
22
- SchemaUtils.tables_names.map do |table_name|
23
- model = SchemaUtils.find_model_from_table_name(table_name)
24
- SerializerFactory.new.serializer_for(model) if \
25
- model.try(:table_exists?)
26
- end
27
-
28
- # Monkey patch the find_serializer_class_name method to specify the
29
- # good serializer to use.
30
- JSONAPI::Serializer.class_eval do
31
- def self.find_serializer_class_name(obj)
32
- SerializerFactory.get_serializer_name(obj.class)
33
- end
34
- end
35
-
36
- if ForestLiana.jwt_signing_key
37
- forest_url = ENV['FOREST_URL'] ||
38
- 'https://forestadmin-server.herokuapp.com';
39
-
40
- SchemaUtils.tables_names.map do |table_name|
41
- model = SchemaUtils.find_model_from_table_name(table_name)
42
- if model.try(:table_exists?)
43
- ForestLiana.apimap << SchemaAdapter.new(model).perform
44
- end
45
- end
46
-
47
- Dir["#{app.root}/app/models/forest/*.rb"].each {|file| require file }
48
-
49
- liana_version = Gem::Specification.find_by_name('forest_liana')
50
- .version.to_s
51
- json = JSONAPI::Serializer.serialize(ForestLiana.apimap, {
52
- is_collection: true,
53
- include: ['actions'],
54
- meta: { liana: 'forest-rails', liana_version: liana_version }
55
- })
56
-
57
- uri = URI.parse("#{forest_url}/forest/apimaps")
58
- http = Net::HTTP.new(uri.host, uri.port)
59
- http.use_ssl = true if forest_url.start_with?('https')
60
- http.start do |client|
61
- request = Net::HTTP::Post.new(uri.path)
62
- request.body = json.to_json
63
- request['Content-Type'] = 'application/json'
64
- request['forest-secret-key'] = ForestLiana.jwt_signing_key
65
- response = client.request(request)
66
-
67
- if response.is_a?(Net::HTTPNotFound)
68
- logger.warn "Forest cannot find your project secret key. " \
69
- "Please, run `rails g forest_liana:install`."
70
- end
71
- end
72
- end
73
- end
23
+ return if Rails.env.test?
24
+ Bootstraper.new(app).perform
74
25
  end
75
26
  end
76
27
  end
@@ -1,3 +1,3 @@
1
1
  module ForestLiana
2
- VERSION = "1.1.22"
2
+ VERSION = "1.1.23"
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.1.22
4
+ version: 1.1.23
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sandro Munda
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-12-24 00:00:00.000000000 Z
11
+ date: 2016-01-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -108,6 +108,34 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: intercom
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: useragent
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
111
139
  description: Forest Rails Liana
112
140
  email:
113
141
  - sandro@munda.me
@@ -124,6 +152,7 @@ files:
124
152
  - app/controllers/forest_liana/apimaps_controller.rb
125
153
  - app/controllers/forest_liana/application_controller.rb
126
154
  - app/controllers/forest_liana/associations_controller.rb
155
+ - app/controllers/forest_liana/intercom_controller.rb
127
156
  - app/controllers/forest_liana/resources_controller.rb
128
157
  - app/controllers/forest_liana/stats_controller.rb
129
158
  - app/controllers/forest_liana/stripe_controller.rb
@@ -134,6 +163,8 @@ files:
134
163
  - app/models/forest_liana/model/stat.rb
135
164
  - app/serializers/forest_liana/action_serializer.rb
136
165
  - app/serializers/forest_liana/collection_serializer.rb
166
+ - app/serializers/forest_liana/intercom_attribute_serializer.rb
167
+ - app/serializers/forest_liana/intercom_conversation_serializer.rb
137
168
  - app/serializers/forest_liana/serializer_factory.rb
138
169
  - app/serializers/forest_liana/stat_serializer.rb
139
170
  - app/serializers/forest_liana/stripe_card_serializer.rb
@@ -141,6 +172,8 @@ files:
141
172
  - app/serializers/forest_liana/stripe_payment_serializer.rb
142
173
  - app/services/forest_liana/collection.rb
143
174
  - app/services/forest_liana/has_many_getter.rb
175
+ - app/services/forest_liana/intercom_attributes_getter.rb
176
+ - app/services/forest_liana/intercom_conversations_getter.rb
144
177
  - app/services/forest_liana/line_stat_getter.rb
145
178
  - app/services/forest_liana/operator_value_parser.rb
146
179
  - app/services/forest_liana/pie_stat_getter.rb
@@ -158,8 +191,10 @@ files:
158
191
  - app/views/layouts/forest_liana/application.html.erb
159
192
  - config/initializers/arel-helpers.rb
160
193
  - config/initializers/mimetype.rb
194
+ - config/initializers/time_formats.rb
161
195
  - config/routes.rb
162
196
  - lib/forest_liana.rb
197
+ - lib/forest_liana/bootstraper.rb
163
198
  - lib/forest_liana/engine.rb
164
199
  - lib/forest_liana/version.rb
165
200
  - lib/generators/forest_liana/install_generator.rb