forest_liana 1.1.22 → 1.1.23

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