forest_liana 1.3.47 → 1.3.48
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/forest_liana/application_controller.rb +6 -1
- data/app/controllers/forest_liana/associations_controller.rb +7 -3
- data/app/controllers/forest_liana/resources_controller.rb +5 -1
- data/app/controllers/forest_liana/sessions_controller.rb +14 -3
- data/app/controllers/forest_liana/stats_controller.rb +5 -1
- data/app/models/forest_liana/model/action.rb +1 -5
- data/app/services/forest_liana/operator_date_interval_parser.rb +118 -18
- data/app/services/forest_liana/pie_stat_getter.rb +6 -0
- data/lib/forest_liana/bootstraper.rb +22 -1
- data/lib/forest_liana/collection.rb +1 -0
- data/lib/forest_liana/engine.rb +4 -1
- data/lib/forest_liana/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6db1641f295cb1be97c63a55623100e571c14b6d
|
4
|
+
data.tar.gz: b2be28e7ba9d66e0dafd86f47cb8ca6826f438ad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2966c778d6a512d84cd9b3d23edc6a9fc18eca9ea1724509e2c44a1e2a30ca9f6e01ebcf969d9b0e4e45c50b1eaa58b6f3d146891b9d48aecc06762cba6598c2
|
7
|
+
data.tar.gz: 2ae9b44ba753511a8c3a14c9c8ebf101975a1ed3a011368e5b45240344c22f9b18ebf826523cd563ababa5b5382005532ed4a50e846396a33586fd70ec0f3d67
|
@@ -2,7 +2,12 @@ require 'jwt'
|
|
2
2
|
|
3
3
|
module ForestLiana
|
4
4
|
class ApplicationController < ActionController::Base
|
5
|
-
|
5
|
+
if Rails::VERSION::MAJOR < 4
|
6
|
+
before_filter :authenticate_user_from_jwt
|
7
|
+
else
|
8
|
+
before_action :authenticate_user_from_jwt
|
9
|
+
end
|
10
|
+
|
6
11
|
wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
|
7
12
|
|
8
13
|
|
@@ -1,8 +1,12 @@
|
|
1
1
|
module ForestLiana
|
2
2
|
class AssociationsController < ForestLiana::ApplicationController
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
if Rails::VERSION::MAJOR < 4
|
4
|
+
before_filter :find_resource
|
5
|
+
before_filter :find_association
|
6
|
+
else
|
7
|
+
before_action :find_resource
|
8
|
+
before_action :find_association
|
9
|
+
end
|
6
10
|
|
7
11
|
def index
|
8
12
|
getter = HasManyGetter.new(@resource, @association, params)
|
@@ -20,9 +20,20 @@ module ForestLiana
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def check_user
|
23
|
-
|
24
|
-
|
25
|
-
|
23
|
+
# NOTICE: Use the ForestUser table for authentication.
|
24
|
+
if defined? ForestUser
|
25
|
+
user = ForestUser.find_by(email: params['email'])
|
26
|
+
return nil if user.blank?
|
27
|
+
|
28
|
+
if BCrypt::Password.new(user['password_hash']) == params['password']
|
29
|
+
user
|
30
|
+
end
|
31
|
+
# NOTICE: Query Forest server for authentication.
|
32
|
+
else
|
33
|
+
ForestLiana.allowed_users.find do |allowed_user|
|
34
|
+
allowed_user['email'] == params['email'] &&
|
35
|
+
BCrypt::Password.new(allowed_user['password']) == params['password']
|
36
|
+
end
|
26
37
|
end
|
27
38
|
end
|
28
39
|
|
@@ -1,6 +1,10 @@
|
|
1
1
|
module ForestLiana
|
2
2
|
class StatsController < ForestLiana::ApplicationController
|
3
|
-
|
3
|
+
if Rails::VERSION::MAJOR < 4
|
4
|
+
before_action :find_resource
|
5
|
+
else
|
6
|
+
before_action :find_resource
|
7
|
+
end
|
4
8
|
|
5
9
|
def show
|
6
10
|
case params[:type].try(:downcase)
|
@@ -4,7 +4,7 @@ class ForestLiana::Model::Action
|
|
4
4
|
include ActiveModel::Serialization
|
5
5
|
extend ActiveModel::Naming
|
6
6
|
|
7
|
-
attr_accessor :name, :endpoint, :http_method, :fields, :redirect
|
7
|
+
attr_accessor :id, :name, :endpoint, :http_method, :fields, :redirect
|
8
8
|
|
9
9
|
def initialize(attributes = {})
|
10
10
|
attributes.each do |name, value|
|
@@ -15,8 +15,4 @@ class ForestLiana::Model::Action
|
|
15
15
|
def persisted?
|
16
16
|
false
|
17
17
|
end
|
18
|
-
|
19
|
-
def id
|
20
|
-
name
|
21
|
-
end
|
22
18
|
end
|
@@ -1,17 +1,35 @@
|
|
1
1
|
module ForestLiana
|
2
2
|
class OperatorDateIntervalParser
|
3
3
|
PERIODS = {
|
4
|
-
yesterday: { duration: 1, period: 'day' },
|
5
|
-
lastWeek: { duration: 1, period: 'week' },
|
6
|
-
last2Weeks: { duration: 2, period: 'week' },
|
7
|
-
lastMonth: { duration: 1, period: 'month' },
|
8
|
-
last3Months: { duration: 3, period: 'month' },
|
9
|
-
lastYear: { duration: 1, period: 'year' }
|
4
|
+
yesterday: { duration: 1, period: 'day' }, # TODO: Remove once new filter protocol is live
|
5
|
+
lastWeek: { duration: 1, period: 'week' }, # TODO: Remove once new filter protocol is live
|
6
|
+
last2Weeks: { duration: 2, period: 'week' }, # TODO: Remove once new filter protocol is live
|
7
|
+
lastMonth: { duration: 1, period: 'month' }, # TODO: Remove once new filter protocol is live
|
8
|
+
last3Months: { duration: 3, period: 'month' }, # TODO: Remove once new filter protocol is live
|
9
|
+
lastYear: { duration: 1, period: 'year' }, # TODO: Remove once new filter protocol is live
|
10
|
+
'$yesterday': { duration: 1, period: 'day' },
|
11
|
+
'$previousWeek': { duration: 1, period: 'week' },
|
12
|
+
'$previousMonth': { duration: 1, period: 'month' },
|
13
|
+
'$previousQuarter': { duration: 3, period: 'month',
|
14
|
+
period_of_time: 'quarter' },
|
15
|
+
'$previousYear': { duration: 1, period: 'year' },
|
16
|
+
'$weekToDate': { duration: 1, period: 'week', to_date: true },
|
17
|
+
'$monthToDate': { duration: 1, period: 'month', to_date: true },
|
18
|
+
'$quarterToDate': { duration: 3, period: 'month',
|
19
|
+
period_of_time: 'quarter', to_date: true },
|
20
|
+
'$yearToDate': { duration: 1, period: 'year', to_date: true }
|
10
21
|
}
|
11
22
|
|
12
|
-
PERIODS_FROM_NOW = 'fromNow'
|
13
|
-
|
14
|
-
|
23
|
+
PERIODS_FROM_NOW = 'fromNow' # TODO: Remove once new filter protocol is live
|
24
|
+
PERIODS_TODAY_DEPRECATED = 'today' # TODO: Remove once new filter protocol is live
|
25
|
+
|
26
|
+
PERIODS_PAST = '$past';
|
27
|
+
PERIODS_FUTURE = '$future';
|
28
|
+
PERIODS_TODAY = '$today';
|
29
|
+
|
30
|
+
PERIODS_LAST_X_DAYS = /^last(\d+)days$/ # TODO: Remove once new filter protocol is live
|
31
|
+
PERIODS_PREVIOUS_X_DAYS = /^\$previous(\d+)Days$/;
|
32
|
+
PERIODS_X_DAYS_TO_DATE = /^\$(\d+)DaysToDate$/;
|
15
33
|
|
16
34
|
def initialize(value)
|
17
35
|
@value = value
|
@@ -20,68 +38,150 @@ module ForestLiana
|
|
20
38
|
def is_interval_date_value
|
21
39
|
return false if @value.nil?
|
22
40
|
return true if PERIODS[@value.to_sym]
|
23
|
-
return true if [PERIODS_FROM_NOW, PERIODS_TODAY].include? @value
|
24
41
|
|
42
|
+
# TODO: Remove once new filter protocol is live
|
43
|
+
return true if [PERIODS_FROM_NOW, PERIODS_TODAY_DEPRECATED].include? @value
|
44
|
+
|
45
|
+
return true if [PERIODS_PAST, PERIODS_FUTURE, PERIODS_TODAY].include? @value
|
46
|
+
|
47
|
+
# TODO: Remove once new filter protocol is live
|
25
48
|
match = PERIODS_LAST_X_DAYS.match(@value)
|
26
49
|
return true if match && match[1]
|
27
50
|
|
51
|
+
match = PERIODS_PREVIOUS_X_DAYS.match(@value)
|
52
|
+
return true if match && match[1]
|
53
|
+
|
54
|
+
match = PERIODS_X_DAYS_TO_DATE.match(@value)
|
55
|
+
return true if match && match[1]
|
56
|
+
|
28
57
|
false
|
29
58
|
end
|
30
59
|
|
31
60
|
def has_previous_interval
|
32
61
|
return false if @value.nil?
|
33
62
|
return true if PERIODS[@value.to_sym]
|
63
|
+
|
64
|
+
# TODO: Remove once new filter protocol is live
|
65
|
+
return true if PERIODS_TODAY_DEPRECATED == @value
|
66
|
+
|
34
67
|
return true if PERIODS_TODAY == @value
|
35
68
|
|
69
|
+
# TODO: Remove once new filter protocol is live
|
36
70
|
match = PERIODS_LAST_X_DAYS.match(@value)
|
37
71
|
return true if match && match[1]
|
38
72
|
|
73
|
+
match = PERIODS_PREVIOUS_X_DAYS.match(@value)
|
74
|
+
return true if match && match[1]
|
75
|
+
|
76
|
+
match = PERIODS_X_DAYS_TO_DATE.match(@value)
|
77
|
+
return true if match && match[1]
|
78
|
+
|
39
79
|
false
|
40
80
|
end
|
41
81
|
|
42
82
|
def get_interval_date_filter
|
43
83
|
return nil unless is_interval_date_value()
|
44
84
|
|
85
|
+
# TODO: Remove once new filter protocol is live
|
45
86
|
return ">= '#{Time.now}'" if @value == PERIODS_FROM_NOW
|
46
87
|
|
88
|
+
return ">= '#{Time.now}'" if @value == PERIODS_FUTURE
|
89
|
+
return "<= '#{Time.now}'" if @value == PERIODS_PAST
|
90
|
+
|
91
|
+
# TODO: Remove once new filter protocol is live
|
92
|
+
if @value == PERIODS_TODAY_DEPRECATED
|
93
|
+
return "BETWEEN '#{Time.now.beginning_of_day}' AND " +
|
94
|
+
"'#{Time.now.end_of_day}'"
|
95
|
+
end
|
96
|
+
|
47
97
|
if @value == PERIODS_TODAY
|
48
98
|
return "BETWEEN '#{Time.now.beginning_of_day}' AND " +
|
49
99
|
"'#{Time.now.end_of_day}'"
|
50
100
|
end
|
51
101
|
|
102
|
+
# TODO: Remove once new filter protocol is live
|
52
103
|
match = PERIODS_LAST_X_DAYS.match(@value)
|
53
104
|
if match && match[1]
|
54
105
|
return "BETWEEN '#{Integer(match[1]).day.ago.beginning_of_day}'" +
|
55
106
|
" AND '#{1.day.ago.end_of_day}'"
|
56
107
|
end
|
57
108
|
|
109
|
+
match = PERIODS_PREVIOUS_X_DAYS.match(@value)
|
110
|
+
if match && match[1]
|
111
|
+
return "BETWEEN '#{Integer(match[1]).day.ago.beginning_of_day}'" +
|
112
|
+
" AND '#{1.day.ago.end_of_day}'"
|
113
|
+
end
|
114
|
+
|
115
|
+
match = PERIODS_X_DAYS_TO_DATE.match(@value)
|
116
|
+
if match && match[1]
|
117
|
+
return "BETWEEN '#{(Integer(match[1]) - 1).day.ago.beginning_of_day}'" +
|
118
|
+
" AND '#{Time.now}'"
|
119
|
+
end
|
120
|
+
|
58
121
|
duration = PERIODS[@value.to_sym][:duration]
|
59
122
|
period = PERIODS[@value.to_sym][:period]
|
60
|
-
|
61
|
-
|
62
|
-
|
123
|
+
period_of_time = PERIODS[@value.to_sym][:period_of_time] ||
|
124
|
+
PERIODS[@value.to_sym][:period]
|
125
|
+
to_date = PERIODS[@value.to_sym][:to_date]
|
126
|
+
|
127
|
+
if to_date
|
128
|
+
from = Time.now.send("beginning_of_#{period_of_time}")
|
129
|
+
to = Time.now
|
130
|
+
else
|
131
|
+
from = duration.send(period).ago.send("beginning_of_#{period_of_time}")
|
132
|
+
to = 1.send(period).ago.send("end_of_#{period_of_time}")
|
133
|
+
end
|
63
134
|
"BETWEEN '#{from}' AND '#{to}'"
|
64
135
|
end
|
65
136
|
|
66
137
|
def get_interval_date_filter_for_previous_interval
|
67
138
|
return nil unless has_previous_interval()
|
68
139
|
|
140
|
+
# TODO: Remove once new filter protocol is live
|
141
|
+
if @value == PERIODS_TODAY_DEPRECATED
|
142
|
+
return "BETWEEN '#{1.day.ago.beginning_of_day}' AND " +
|
143
|
+
"'#{1.day.ago.end_of_day}'"
|
144
|
+
end
|
145
|
+
|
69
146
|
if @value == PERIODS_TODAY
|
70
147
|
return "BETWEEN '#{1.day.ago.beginning_of_day}' AND " +
|
71
148
|
"'#{1.day.ago.end_of_day}'"
|
72
149
|
end
|
73
150
|
|
151
|
+
# TODO: Remove once new filter protocol is live
|
74
152
|
match = PERIODS_LAST_X_DAYS.match(@value)
|
75
153
|
if match && match[1]
|
76
|
-
return "BETWEEN '#{Integer(match[1] * 2).day.ago.beginning_of_day}'" +
|
77
|
-
" AND '#{Integer(match[1]).day.ago.end_of_day}'"
|
154
|
+
return "BETWEEN '#{(Integer(match[1]) * 2).day.ago.beginning_of_day}'" +
|
155
|
+
" AND '#{(Integer(match[1]) + 1).day.ago.end_of_day}'"
|
156
|
+
end
|
157
|
+
|
158
|
+
match = PERIODS_PREVIOUS_X_DAYS.match(@value)
|
159
|
+
if match && match[1]
|
160
|
+
return "BETWEEN '#{(Integer(match[1]) * 2).day.ago.beginning_of_day}'" +
|
161
|
+
" AND '#{(Integer(match[1]) + 1).day.ago.end_of_day}'"
|
162
|
+
end
|
163
|
+
|
164
|
+
match = PERIODS_X_DAYS_TO_DATE.match(@value)
|
165
|
+
if match && match[1]
|
166
|
+
return "BETWEEN '#{((Integer(match[1]) * 2) - 1).day.ago.beginning_of_day}'" +
|
167
|
+
" AND '#{Integer(match[1]).day.ago}'"
|
78
168
|
end
|
79
169
|
|
80
170
|
duration = PERIODS[@value.to_sym][:duration]
|
81
171
|
period = PERIODS[@value.to_sym][:period]
|
82
|
-
|
83
|
-
|
84
|
-
|
172
|
+
period_of_time = PERIODS[@value.to_sym][:period_of_time] ||
|
173
|
+
PERIODS[@value.to_sym][:period]
|
174
|
+
to_date = PERIODS[@value.to_sym][:to_date]
|
175
|
+
|
176
|
+
if to_date
|
177
|
+
from = (duration).send(period).ago
|
178
|
+
.send("beginning_of_#{period_of_time}")
|
179
|
+
to = (duration).send(period).ago
|
180
|
+
else
|
181
|
+
from = (duration * 2).send(period).ago
|
182
|
+
.send("beginning_of_#{period_of_time}")
|
183
|
+
to = (1 + duration).send(period).ago.send("end_of_#{period_of_time}")
|
184
|
+
end
|
85
185
|
"BETWEEN '#{from}' AND '#{to}'"
|
86
186
|
end
|
87
187
|
end
|
@@ -37,6 +37,12 @@ module ForestLiana
|
|
37
37
|
.order("#{@params[:aggregate].downcase}_#{field} DESC")
|
38
38
|
.send(@params[:aggregate].downcase, @params[:aggregate_field])
|
39
39
|
.map do |k, v|
|
40
|
+
# NOTICE: Display the enum name instead of a integer if "enum" type
|
41
|
+
if @resource.respond_to?(:defined_enums) &&
|
42
|
+
@resource.defined_enums.has_key?(@params[:group_by_field])
|
43
|
+
k = @resource.defined_enums[@params[:group_by_field]].invert[k]
|
44
|
+
end
|
45
|
+
|
40
46
|
{ key: k, value: v }
|
41
47
|
end
|
42
48
|
|
@@ -45,16 +45,36 @@ More info at: https://github.com/ForestAdmin/forest-rails/releases/tag/1.2.0"
|
|
45
45
|
|
46
46
|
private
|
47
47
|
|
48
|
+
def fetch_sti_models(model)
|
49
|
+
type_field = model.columns.find {|c| c.name == 'type' }
|
50
|
+
if type_field
|
51
|
+
model.descendants.each do |sti_model|
|
52
|
+
if analyze_model?(sti_model)
|
53
|
+
ForestLiana.models << sti_model
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
48
59
|
def analyze_model?(model)
|
49
60
|
return model && model.table_exists? && !SchemaUtils.habtm?(model) &&
|
50
61
|
SchemaUtils.model_included?(model)
|
51
62
|
end
|
52
63
|
|
53
64
|
def fetch_models
|
54
|
-
ActiveRecord::Base.subclasses.each
|
65
|
+
ActiveRecord::Base.subclasses.each {|model| fetch_model(model)}
|
66
|
+
end
|
67
|
+
|
68
|
+
def fetch_model(model)
|
69
|
+
if model.abstract_class?
|
70
|
+
model.descendants.each {|submodel| fetch_model(submodel)}
|
71
|
+
else
|
72
|
+
fetch_sti_models(model) if model.try(:table_exists?)
|
73
|
+
|
55
74
|
if analyze_model?(model)
|
56
75
|
ForestLiana.models << model
|
57
76
|
end
|
77
|
+
|
58
78
|
end
|
59
79
|
end
|
60
80
|
|
@@ -267,6 +287,7 @@ More info at: https://github.com/ForestAdmin/forest-rails/releases/tag/1.2.0"
|
|
267
287
|
],
|
268
288
|
actions: [
|
269
289
|
ForestLiana::Model::Action.new({
|
290
|
+
id: 'stripe.Refund',
|
270
291
|
name: 'Refund',
|
271
292
|
endpoint: '/forest/stripe_payments/refunds'
|
272
293
|
})
|
data/lib/forest_liana/engine.rb
CHANGED
@@ -12,7 +12,10 @@ module ForestLiana
|
|
12
12
|
class Engine < ::Rails::Engine
|
13
13
|
isolate_namespace ForestLiana
|
14
14
|
|
15
|
-
|
15
|
+
rack_cors_class = Rack::Cors
|
16
|
+
rack_cors_class = 'Rack::Cors' if Rails::VERSION::MAJOR < 5
|
17
|
+
|
18
|
+
config.middleware.insert_before 0, rack_cors_class do
|
16
19
|
allow do
|
17
20
|
hostnames = ['localhost:4200', 'app.forestadmin.com',
|
18
21
|
'www.forestadmin.com']
|
data/lib/forest_liana/version.rb
CHANGED
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.3.
|
4
|
+
version: 1.3.48
|
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-10-
|
11
|
+
date: 2016-10-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|