forest_liana 1.4.6 → 1.4.7

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: 6dac4da1a71a663bfdd2f36870f8e5ccbc150b03
4
- data.tar.gz: ffc0af068f5056eaa86920ca86dcdc3097509d85
3
+ metadata.gz: bdc8fcb5df5a924d7903d9105b26b30810ef6a52
4
+ data.tar.gz: cd688dccec28feaf5a66f0ea47b7c0bed89ee051
5
5
  SHA512:
6
- metadata.gz: 06f4028b47406055fec5ff180cc966fafdef44b8b3dfbc1e756cf85a716647852e85db519480582d20d919ca98029d607b67de7acd2bfa7bbb9866bb565e9cb5
7
- data.tar.gz: ea027353665909b1c751896a84ccd0e96db8e0b97c4d5cf35a21c5f9bfe775adc3deb0c879a0e8d909e9912e32543acbe523c25d01a58d19ff271a740a0401c0
6
+ metadata.gz: 0ea7d3bb580c5cee0a84f80aff39d3d1c44d65c4ecdc2b694f0531e36c3edc1e12e0591b5a2c64838e04081675fcc09672a56323dc026a43ebcde19f7f5b3ddc
7
+ data.tar.gz: 0832ca416bd830169ea4bb3926fa839a0b245d4e8ea0c1d13732b4cbe9cd794c8dad561ad2ac6bb12496eeb209637f91e12759559830b424c229a22592e81534
@@ -2,6 +2,7 @@ module ForestLiana
2
2
  class SessionsController < ActionController::Base
3
3
 
4
4
  def create
5
+ @error_message = nil
5
6
  @user_class = ForestLiana.user_class_name.constantize rescue nil
6
7
 
7
8
  user = check_user
@@ -10,7 +11,10 @@ module ForestLiana
10
11
  if token
11
12
  render json: { token: token }, serializer: nil
12
13
  else
13
- if !has_internal_authentication? && ForestLiana.allowed_users.empty?
14
+ if @error_message
15
+ render serializer: nil, json: JSONAPI::Serializer.serialize_errors(
16
+ [{ detail: @error_message }]), status: :unauthorized
17
+ elsif !has_internal_authentication? && ForestLiana.allowed_users.empty?
14
18
  render serializer: nil, json: JSONAPI::Serializer.serialize_errors(
15
19
  [{ detail: 'Forest cannot retrieve any users for the project ' \
16
20
  'you\'re trying to unlock.' }]), status: :unauthorized
@@ -51,27 +55,35 @@ module ForestLiana
51
55
  end
52
56
 
53
57
  def encode_token(user)
54
- JWT.encode({
55
- exp: Time.now.to_i + 2.weeks.to_i,
56
- data: {
57
- id: user['id'],
58
- type: 'users',
58
+ if ForestLiana.auth_key.nil?
59
+ @error_message = "Your Forest auth key seems to be missing. Can " \
60
+ "you check that you properly set a Forest auth key in the " \
61
+ "forest_liana initializer?"
62
+ FOREST_LOGGER.error @error_message
63
+ nil
64
+ else
65
+ JWT.encode({
66
+ exp: Time.now.to_i + 2.weeks.to_i,
59
67
  data: {
60
- email: user['email'],
61
- first_name: user['first_name'],
62
- last_name: user['last_name'],
63
- teams: user['teams']
64
- },
65
- relationships: {
66
- renderings: {
67
- data: [{
68
- type: 'renderings',
69
- id: params['renderingId']
70
- }]
68
+ id: user['id'],
69
+ type: 'users',
70
+ data: {
71
+ email: user['email'],
72
+ first_name: user['first_name'],
73
+ last_name: user['last_name'],
74
+ teams: user['teams']
75
+ },
76
+ relationships: {
77
+ renderings: {
78
+ data: [{
79
+ type: 'renderings',
80
+ id: params['renderingId']
81
+ }]
82
+ }
71
83
  }
72
84
  }
73
- }
74
- } , ForestLiana.auth_key, 'HS256')
85
+ }, ForestLiana.auth_key, 'HS256')
86
+ end
75
87
  end
76
88
  end
77
89
  end
@@ -3,8 +3,25 @@ module ForestLiana
3
3
  attr_accessor :record
4
4
 
5
5
  def initialize(resource, params)
6
+ @timezone_offset = params[:timezone].to_i
6
7
  super(resource, params)
7
- @populates = {}
8
+ end
9
+
10
+ def client_timezone
11
+ ActiveSupport::TimeZone[@timezone_offset].name
12
+ end
13
+
14
+ def get_format
15
+ case @params[:time_range].try(:downcase)
16
+ when 'day'
17
+ '%d/%m/%Y'
18
+ when 'week'
19
+ 'W%W-%Y'
20
+ when 'month'
21
+ '%b %Y'
22
+ when 'year'
23
+ '%Y'
24
+ end
8
25
  end
9
26
 
10
27
  def perform
@@ -16,34 +33,17 @@ module ForestLiana
16
33
 
17
34
  @params[:filters].try(:each) do |filter|
18
35
  operator, filter_value = OperatorValueParser.parse(filter[:value])
19
- conditions << OperatorValueParser.get_condition(filter[:field],
20
- operator, filter_value, @resource)
36
+ conditions << OperatorValueParser.get_condition(filter[:field],
37
+ operator, filter_value, @resource, @params[:timezone])
21
38
  end
22
39
 
23
40
  value = value.where(conditions.join(filter_operator))
24
41
  end
25
42
 
26
- value = value.send(time_range, group_by_date_field)
27
- value = value.group(group_by_field || :id) if group_by_field
28
-
43
+ value = value.send(time_range, group_by_date_field, { time_zone: client_timezone })
29
44
  value = value.send(@params[:aggregate].downcase, @params[:aggregate_field])
30
45
  .map do |k, v|
31
- if k.kind_of?(Array)
32
- {
33
- label: k[0],
34
- values: {
35
- key: populate(k[1]),
36
- value: v
37
- }
38
- }
39
- else
40
- {
41
- label: k,
42
- values: {
43
- value: v
44
- }
45
- }
46
- end
46
+ { label: k.strftime(get_format), values: { value: v }}
47
47
  end
48
48
 
49
49
  @record = Model::Stat.new(value: value)
@@ -55,30 +55,6 @@ module ForestLiana
55
55
  "#{@resource.table_name}.#{@params[:group_by_date_field]}"
56
56
  end
57
57
 
58
- def group_by_field
59
- field_name = @params[:group_by_field]
60
- association = @resource.reflect_on_association(field_name) if field_name
61
-
62
- if association
63
- association.foreign_key
64
- else
65
- field_name
66
- end
67
- end
68
-
69
- def populate(id)
70
- @populates[id] ||= begin
71
- field_name = @params[:group_by_field]
72
- association = @resource.reflect_on_association(field_name)
73
-
74
- if association
75
- association.klass.find(id)
76
- else
77
- id
78
- end
79
- end
80
- end
81
-
82
58
  def time_range
83
59
  "group_by_#{@params[:time_range].try(:downcase) || 'month'}"
84
60
  end
@@ -21,8 +21,9 @@ module ForestLiana
21
21
  PERIODS_PREVIOUS_X_DAYS = /^\$previous(\d+)Days$/;
22
22
  PERIODS_X_DAYS_TO_DATE = /^\$(\d+)DaysToDate$/;
23
23
 
24
- def initialize(value)
24
+ def initialize(value, timezone)
25
25
  @value = value
26
+ @timezone_offset = timezone.to_i
26
27
  end
27
28
 
28
29
  def is_interval_date_value
@@ -55,6 +56,11 @@ module ForestLiana
55
56
  false
56
57
  end
57
58
 
59
+ def to_client_timezone(date)
60
+ # NOTICE: By default, Rails store the dates without timestamp in the database.
61
+ date - @timezone_offset.hours
62
+ end
63
+
58
64
  def get_interval_date_filter
59
65
  return nil unless is_interval_date_value()
60
66
 
@@ -62,20 +68,22 @@ module ForestLiana
62
68
  return "<= '#{Time.now}'" if @value == PERIODS_PAST
63
69
 
64
70
  if @value == PERIODS_TODAY
65
- return "BETWEEN '#{Time.now.beginning_of_day}' AND " +
66
- "'#{Time.now.end_of_day}'"
71
+ return "BETWEEN '#{to_client_timezone(Time.now.beginning_of_day)}' " +
72
+ "AND '#{to_client_timezone(Time.now.end_of_day)}'"
67
73
  end
68
74
 
69
75
  match = PERIODS_PREVIOUS_X_DAYS.match(@value)
70
76
  if match && match[1]
71
- return "BETWEEN '#{Integer(match[1]).day.ago.beginning_of_day}'" +
72
- " AND '#{1.day.ago.end_of_day}'"
77
+ return "BETWEEN '" +
78
+ "#{to_client_timezone(Integer(match[1]).day.ago.beginning_of_day)}'" +
79
+ " AND '#{to_client_timezone(1.day.ago.end_of_day)}'"
73
80
  end
74
81
 
75
82
  match = PERIODS_X_DAYS_TO_DATE.match(@value)
76
83
  if match && match[1]
77
- return "BETWEEN '#{(Integer(match[1]) - 1).day.ago.beginning_of_day}'" +
78
- " AND '#{Time.now}'"
84
+ return "BETWEEN '" +
85
+ "#{to_client_timezone((Integer(match[1]) - 1).day.ago.beginning_of_day)}'" +
86
+ " AND '#{to_client_timezone(Time.now)}'"
79
87
  end
80
88
 
81
89
  duration = PERIODS[@value.to_sym][:duration]
@@ -85,11 +93,13 @@ module ForestLiana
85
93
  to_date = PERIODS[@value.to_sym][:to_date]
86
94
 
87
95
  if to_date
88
- from = Time.now.send("beginning_of_#{period_of_time}")
89
- to = Time.now
96
+ from = to_client_timezone(Time.now.send("beginning_of_#{period_of_time}"))
97
+ to = to_client_timezone(Time.now)
90
98
  else
91
- from = duration.send(period).ago.send("beginning_of_#{period_of_time}")
92
- to = 1.send(period).ago.send("end_of_#{period_of_time}")
99
+ from = to_client_timezone(duration.send(period).ago
100
+ .send("beginning_of_#{period_of_time}"))
101
+ to = to_client_timezone(1.send(period).ago
102
+ .send("end_of_#{period_of_time}"))
93
103
  end
94
104
  "BETWEEN '#{from}' AND '#{to}'"
95
105
  end
@@ -98,20 +108,22 @@ module ForestLiana
98
108
  return nil unless has_previous_interval()
99
109
 
100
110
  if @value == PERIODS_TODAY
101
- return "BETWEEN '#{1.day.ago.beginning_of_day}' AND " +
102
- "'#{1.day.ago.end_of_day}'"
111
+ return "BETWEEN '#{to_client_timezone(1.day.ago.beginning_of_day)}' AND " +
112
+ "'#{to_client_timezone(1.day.ago.end_of_day)}'"
103
113
  end
104
114
 
105
115
  match = PERIODS_PREVIOUS_X_DAYS.match(@value)
106
116
  if match && match[1]
107
- return "BETWEEN '#{(Integer(match[1]) * 2).day.ago.beginning_of_day}'" +
108
- " AND '#{(Integer(match[1]) + 1).day.ago.end_of_day}'"
117
+ return "BETWEEN '" +
118
+ "#{to_client_timezone((Integer(match[1]) * 2).day.ago.beginning_of_day)}'" +
119
+ " AND '#{to_client_timezone((Integer(match[1]) + 1).day.ago.end_of_day)}'"
109
120
  end
110
121
 
111
122
  match = PERIODS_X_DAYS_TO_DATE.match(@value)
112
123
  if match && match[1]
113
- return "BETWEEN '#{((Integer(match[1]) * 2) - 1).day.ago.beginning_of_day}'" +
114
- " AND '#{Integer(match[1]).day.ago}'"
124
+ return "BETWEEN '" +
125
+ "#{to_client_timezone(((Integer(match[1]) * 2) - 1).day.ago.beginning_of_day)}'" +
126
+ " AND '#{to_client_timezone(Integer(match[1]).day.ago)}'"
115
127
  end
116
128
 
117
129
  duration = PERIODS[@value.to_sym][:duration]
@@ -121,13 +133,14 @@ module ForestLiana
121
133
  to_date = PERIODS[@value.to_sym][:to_date]
122
134
 
123
135
  if to_date
124
- from = (duration).send(period).ago
125
- .send("beginning_of_#{period_of_time}")
126
- to = (duration).send(period).ago
136
+ from = to_client_timezone((duration).send(period).ago
137
+ .send("beginning_of_#{period_of_time}"))
138
+ to = to_client_timezone((duration).send(period).ago)
127
139
  else
128
- from = (duration * 2).send(period).ago
129
- .send("beginning_of_#{period_of_time}")
130
- to = (1 + duration).send(period).ago.send("end_of_#{period_of_time}")
140
+ from = to_client_timezone((duration * 2).send(period).ago
141
+ .send("beginning_of_#{period_of_time}"))
142
+ to = to_client_timezone((1 + duration).send(period).ago
143
+ .send("end_of_#{period_of_time}"))
131
144
  end
132
145
  "BETWEEN '#{from}' AND '#{to}'"
133
146
  end
@@ -31,10 +31,12 @@ module ForestLiana
31
31
  [operator, value_comparison]
32
32
  end
33
33
 
34
- def self.get_condition(field, operator, value, resource)
34
+ def self.get_condition(field, operator, value, resource, timezone)
35
35
  field_name = self.get_field_name(field, resource)
36
36
 
37
- operator_date_interval_parser = OperatorDateIntervalParser.new(value)
37
+ operator_date_interval_parser = OperatorDateIntervalParser
38
+ .new(value, timezone)
39
+
38
40
  if operator_date_interval_parser.is_interval_date_value()
39
41
  filter = operator_date_interval_parser.get_interval_date_filter()
40
42
  "#{field_name} #{filter}"
@@ -4,6 +4,7 @@ module ForestLiana
4
4
 
5
5
  def perform
6
6
  if @params[:group_by_field]
7
+ timezone_offset = @params[:timezone].to_i
7
8
  value = @resource
8
9
  conditions = []
9
10
  filter_operator = ''
@@ -14,7 +15,7 @@ module ForestLiana
14
15
  @params[:filters].try(:each) do |filter|
15
16
  operator, filter_value = OperatorValueParser.parse(filter[:value])
16
17
  conditions << OperatorValueParser.get_condition(filter[:field],
17
- operator, filter_value, @resource)
18
+ operator, filter_value, @resource, @params[:timezone])
18
19
  end
19
20
  end
20
21
 
@@ -30,6 +31,8 @@ module ForestLiana
30
31
  if @resource.respond_to?(:defined_enums) &&
31
32
  @resource.defined_enums.has_key?(@params[:group_by_field])
32
33
  key = @resource.defined_enums[@params[:group_by_field]].invert[key]
34
+ elsif @resource.columns_hash[@params[:group_by_field]].type == :datetime
35
+ key = (key + timezone_offset.hours).strftime('%d/%m/%Y %T')
33
36
  end
34
37
 
35
38
  { key: key, value: value }
@@ -79,7 +79,7 @@ module ForestLiana
79
79
  values.split(',').each do |value|
80
80
  operator, value = OperatorValueParser.parse(value)
81
81
  conditions << OperatorValueParser.get_condition(field, operator,
82
- value, @resource)
82
+ value, @resource, @params[:timezone])
83
83
  end
84
84
  end
85
85
 
@@ -171,7 +171,8 @@ module ForestLiana
171
171
  @records = @records
172
172
  .joins(field.to_sym)
173
173
 
174
- operator_date_interval_parser = OperatorDateIntervalParser.new(value)
174
+ operator_date_interval_parser = OperatorDateIntervalParser.new(value,
175
+ @params[:timezone])
175
176
  if operator_date_interval_parser.is_interval_date_value()
176
177
  filter = operator_date_interval_parser.get_interval_date_filter()
177
178
  @records = @records.where("#{association.table_name}.#{subfield} #{filter}")
@@ -15,7 +15,7 @@ module ForestLiana
15
15
  @params[:filters].try(:each) do |filter|
16
16
  operator, filter_value = OperatorValueParser.parse(filter[:value])
17
17
  conditions << OperatorValueParser.get_condition(filter[:field],
18
- operator, filter_value, @resource)
18
+ operator, filter_value, @resource, @params[:timezone])
19
19
  end
20
20
 
21
21
  valueCurrent = valueCurrent.where(conditions.join(filter_operator))
@@ -26,7 +26,8 @@ module ForestLiana
26
26
  conditions = []
27
27
  @params[:filters].try(:each) do |filter|
28
28
  operator, filter_value = OperatorValueParser.parse(filter[:value])
29
- operator_date_interval_parser = OperatorDateIntervalParser.new(filter_value)
29
+ operator_date_interval_parser = OperatorDateIntervalParser
30
+ .new(filter_value, @params[:timezone])
30
31
  if operator_date_interval_parser.has_previous_interval()
31
32
  field_name = OperatorValueParser.get_field_name(filter[:field], @resource)
32
33
  filter = operator_date_interval_parser
@@ -35,7 +36,7 @@ module ForestLiana
35
36
  filter_date_interval = true
36
37
  else
37
38
  conditions << OperatorValueParser.get_condition(filter[:field],
38
- operator, filter_value, @resource)
39
+ operator, filter_value, @resource, @params[:timezone])
39
40
  end
40
41
  end
41
42
 
@@ -1,3 +1,3 @@
1
1
  module ForestLiana
2
- VERSION = "1.4.6"
2
+ VERSION = "1.4.7"
3
3
  end
@@ -4,7 +4,8 @@ module ForestLiana
4
4
  test 'StringField page 1 size 15' do
5
5
  getter = ResourcesGetter.new(StringField, {
6
6
  page: { size: 15, number: 1 },
7
- sort: '-id'
7
+ sort: '-id',
8
+ timezone: '-08:00'
8
9
  })
9
10
  getter.perform
10
11
  records = getter.records
@@ -19,7 +20,8 @@ module ForestLiana
19
20
  test 'StringField page 2 size 10' do
20
21
  getter = ResourcesGetter.new(StringField, {
21
22
  page: { size: 10, number: 2 },
22
- sort: '-id'
23
+ sort: '-id',
24
+ timezone: '-08:00'
23
25
  })
24
26
  getter.perform
25
27
  records = getter.records
@@ -34,7 +36,8 @@ module ForestLiana
34
36
  test 'StringField sort by field' do
35
37
  getter = ResourcesGetter.new(StringField, {
36
38
  page: { size: 10, number: 1 },
37
- sort: '-field'
39
+ sort: '-field',
40
+ timezone: '-08:00'
38
41
  })
39
42
  getter.perform
40
43
  records = getter.records
@@ -50,7 +53,8 @@ module ForestLiana
50
53
  test 'Sort by a belongs_to association' do
51
54
  getter = ResourcesGetter.new(BelongsToField, {
52
55
  page: { size: 10, number: 1 },
53
- sort: 'has_one_field.id'
56
+ sort: 'has_one_field.id',
57
+ timezone: '-08:00'
54
58
  })
55
59
  getter.perform
56
60
  records = getter.records
@@ -65,7 +69,8 @@ module ForestLiana
65
69
  test 'Sort by a has_one association' do
66
70
  getter = ResourcesGetter.new(HasOneField, {
67
71
  page: { size: 10, number: 1 },
68
- sort: '-belongs_to_field.id'
72
+ sort: '-belongs_to_field.id',
73
+ timezone: '-08:00'
69
74
  })
70
75
  getter.perform
71
76
  records = getter.records
@@ -84,7 +89,8 @@ module ForestLiana
84
89
  'created_at' => '>2015-06-18 08:00:00',
85
90
  'owner:name' => 'Arnaud Besnier'
86
91
  },
87
- filterType: 'and'
92
+ filterType: 'and',
93
+ timezone: '-08:00'
88
94
  })
89
95
  getter.perform
90
96
  records = getter.records
@@ -101,7 +107,8 @@ module ForestLiana
101
107
  getter = ResourcesGetter.new(Tree, {
102
108
  page: { size: 10, number: 1 },
103
109
  sort: '-name',
104
- filter: { 'owner:name' => 'Arnaud Besnier' }
110
+ filter: { 'owner:name' => 'Arnaud Besnier' },
111
+ timezone: '-08:00'
105
112
  })
106
113
  getter.perform
107
114
  records = getter.records
@@ -117,7 +124,8 @@ module ForestLiana
117
124
  getter = ResourcesGetter.new(Owner, {
118
125
  page: { size: 10, number: 1 },
119
126
  filter: { 'updated_at' => '$previousYear' },
120
- filterType: 'and'
127
+ filterType: 'and',
128
+ timezone: '-08:00'
121
129
  })
122
130
  getter.perform
123
131
  records = getter.records
@@ -132,7 +140,8 @@ module ForestLiana
132
140
  getter = ResourcesGetter.new(Tree, {
133
141
  page: { size: 10, number: 1 },
134
142
  filter: { 'owner:updated_at' => '$previousYear' },
135
- filterType: 'and'
143
+ filterType: 'and',
144
+ timezone: '-08:00'
136
145
  })
137
146
  getter.perform
138
147
  records = getter.records
@@ -148,7 +157,8 @@ module ForestLiana
148
157
  page: { size: 10, number: 1 },
149
158
  filter: {
150
159
  'owner:updated_at' => 'Sat Jul 02 2016 11:52:00 GMT-0400 (EDT)',
151
- }
160
+ },
161
+ timezone: '-08:00'
152
162
  })
153
163
  getter.perform
154
164
  records = getter.records
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.6
4
+ version: 1.4.7
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-11-29 00:00:00.000000000 Z
11
+ date: 2016-12-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails