marty 9.3.0 → 9.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gemignore +2 -0
- data/.gitignore +3 -0
- data/.rubocop.yml +34 -1
- data/Gemfile +1 -0
- data/Rakefile +10 -0
- data/app/assets/javascripts/marty/cable.js +21 -9
- data/app/channels/application_cable/connection.rb +1 -1
- data/app/channels/marty/notification_channel.rb +4 -1
- data/app/components/marty/api_config_view.rb +1 -1
- data/app/components/marty/api_log_view.rb +1 -1
- data/app/components/marty/auth_app.rb +8 -1
- data/app/components/marty/auth_app/client/auth_app.js +6 -0
- data/app/components/marty/data_grid_view.rb +6 -6
- data/app/components/marty/extras/misc.rb +1 -1
- data/app/components/marty/log_view.rb +1 -1
- data/app/components/marty/posting_grid.rb +1 -1
- data/app/components/marty/script_form.rb +3 -3
- data/app/components/marty/user_view.rb +1 -1
- data/app/components/marty/users/user_view.rb +1 -1
- data/app/controllers/marty/application_controller.rb +7 -7
- data/app/controllers/marty/delayed_job_controller.rb +7 -4
- data/app/controllers/marty/diagnostic/controller.rb +1 -1
- data/app/controllers/marty/job_controller.rb +2 -2
- data/app/models/marty/api_auth.rb +3 -3
- data/app/models/marty/api_config.rb +1 -1
- data/app/models/marty/base_rule.rb +1 -1
- data/app/models/marty/config.rb +5 -5
- data/app/models/marty/data_grid.rb +3 -3
- data/app/models/marty/delorean_rule.rb +2 -2
- data/app/models/marty/grid_index_boolean.rb +2 -2
- data/app/models/marty/grid_index_int4range.rb +1 -1
- data/app/models/marty/grid_index_integer.rb +1 -1
- data/app/models/marty/grid_index_numrange.rb +1 -1
- data/app/models/marty/grid_index_string.rb +1 -1
- data/app/models/marty/import_type.rb +2 -2
- data/app/models/marty/notifications/notification.rb +2 -1
- data/app/models/marty/posting.rb +6 -6
- data/app/models/marty/posting_type.rb +2 -2
- data/app/models/marty/promise.rb +4 -3
- data/app/models/marty/script.rb +7 -7
- data/app/models/marty/tag.rb +5 -5
- data/app/models/marty/token.rb +1 -1
- data/app/models/marty/user.rb +11 -10
- data/app/models/marty/user_role.rb +2 -2
- data/app/models/marty/vw_promise.rb +2 -1
- data/app/services/marty/background_job/update_schedule.rb +1 -1
- data/app/services/marty/data_grid/constraint.rb +4 -3
- data/app/services/marty/jobs/schedule.rb +2 -2
- data/lib/marty/data_change.rb +1 -1
- data/lib/marty/data_conversion.rb +1 -1
- data/lib/marty/migrations.rb +2 -2
- data/lib/marty/rpc_call.rb +2 -1
- data/lib/marty/rule_script_set.rb +1 -3
- data/lib/marty/util.rb +2 -2
- data/lib/marty/version.rb +1 -1
- data/lib/tasks/scripts_tasks.rake +2 -2
- data/marty.gemspec +5 -1
- data/spec/controllers/job_controller_spec.rb +7 -7
- data/spec/controllers/rpc_controller_spec.rb +8 -8
- data/spec/controllers/rpc_import_spec.rb +3 -3
- data/spec/features/data_blame_report_spec.rb +1 -1
- data/spec/features/data_grid_spec.rb +101 -3
- data/spec/features/enum_values_report_spec.rb +1 -1
- data/spec/features/extjs_spec.rb +1 -1
- data/spec/features/jobs_dashboard_spec.rb +2 -2
- data/spec/features/log_view_spec.rb +1 -1
- data/spec/features/reporting_spec.rb +3 -3
- data/spec/features/scripting_spec.rb +3 -3
- data/spec/features/scripting_test_spec.rb +3 -3
- data/spec/features/user_list_report_spec.rb +1 -1
- data/spec/fixtures/misc/data_grid_6.txt +9 -0
- data/spec/fixtures/misc/data_grid_7.txt +7 -0
- data/spec/fixtures/misc/data_grid_8.txt +10 -0
- data/spec/fixtures/misc/data_grid_9.txt +10 -0
- data/spec/lib/data_blame_spec.rb +1 -1
- data/spec/lib/data_importer_spec.rb +4 -4
- data/spec/lib/delorean_query_spec.rb +1 -1
- data/spec/lib/logger_spec.rb +1 -1
- data/spec/lib/mcfly_model_spec.rb +2 -2
- data/spec/lib/table_report_spec.rb +1 -1
- data/spec/models/api_auth_spec.rb +2 -2
- data/spec/models/data_grid_spec.rb +3 -3
- data/spec/models/posting_spec.rb +12 -12
- data/spec/models/promise_spec.rb +1 -1
- data/spec/models/rule_spec.rb +1 -1
- data/spec/models/script_spec.rb +1 -1
- data/spec/other/diagnostic/delayed_job_version_spec.rb +1 -1
- data/spec/spec_helper.rb +3 -0
- data/spec/support/netzke.rb +2 -2
- data/spec/support/setup.rb +1 -1
- data/spec/support/simplecov_helper.rb +94 -0
- data/spec/support/users.rb +2 -2
- metadata +8 -3
- data/.gitlab-ci.yml +0 -117
@@ -69,7 +69,7 @@ class Marty::BaseRule < Marty::Base
|
|
69
69
|
"- Error in rule '#{name}' field 'results': #{res_err.capitalize}" if res_err
|
70
70
|
end
|
71
71
|
|
72
|
-
|
72
|
+
validates :name, presence: true
|
73
73
|
validate :validate
|
74
74
|
validate :validate_simple_guard_options
|
75
75
|
|
data/app/models/marty/config.rb
CHANGED
@@ -7,8 +7,8 @@ class Marty::Config < Marty::Base
|
|
7
7
|
end
|
8
8
|
end
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
validates :key, :value, presence: true
|
11
|
+
validates :key, uniqueness: true
|
12
12
|
validates_with ConfigValidator
|
13
13
|
|
14
14
|
delorean_fn :lookup, sig: 1 do |key|
|
@@ -29,7 +29,7 @@ class Marty::Config < Marty::Base
|
|
29
29
|
"(given #{args.size}, expected 1..2)"
|
30
30
|
end
|
31
31
|
|
32
|
-
entry =
|
32
|
+
entry = find_by(key: args[0])
|
33
33
|
return entry.get_value if entry
|
34
34
|
return args[1] if args.size > 1
|
35
35
|
|
@@ -37,7 +37,7 @@ class Marty::Config < Marty::Base
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def self.[]=(key, value)
|
40
|
-
entry =
|
40
|
+
entry = find_by(key: key)
|
41
41
|
if !entry
|
42
42
|
entry = new
|
43
43
|
entry.key = key
|
@@ -53,7 +53,7 @@ class Marty::Config < Marty::Base
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def self.del(key)
|
56
|
-
entry =
|
56
|
+
entry = find_by(key: key)
|
57
57
|
if entry
|
58
58
|
result = entry.get_value
|
59
59
|
entry.destroy
|
@@ -35,7 +35,7 @@ class Marty::DataGrid < Marty::Base
|
|
35
35
|
attr, type, keys, rs_keep =
|
36
36
|
inf['attr'], inf['type'], inf['keys'], inf['rs_keep']
|
37
37
|
|
38
|
-
|
38
|
+
if rs_keep.present?
|
39
39
|
m = /\A *(<|<=|>|>=)? *([a-z][a-z_0-9]+) *\z/.match(rs_keep)
|
40
40
|
unless m
|
41
41
|
dg.errors.add(:base, "invalid grid modifier expression: #{rs_keep}")
|
@@ -81,7 +81,7 @@ class Marty::DataGrid < Marty::Base
|
|
81
81
|
end
|
82
82
|
data_check = Marty::DataGrid::Constraint.check_data(dg.data_type,
|
83
83
|
dg.data, con_chk)
|
84
|
-
return
|
84
|
+
return if data_check.blank?
|
85
85
|
|
86
86
|
data_check.each do |(err, x, y)|
|
87
87
|
dg.errors.add(:base, "cell #{x}, #{y} fails constraint check") if
|
@@ -94,7 +94,7 @@ class Marty::DataGrid < Marty::Base
|
|
94
94
|
|
95
95
|
has_mcfly
|
96
96
|
|
97
|
-
|
97
|
+
validates :name, :data, :metadata, presence: true
|
98
98
|
|
99
99
|
mcfly_validates_uniqueness_of :name
|
100
100
|
validates_with DataGridValidator
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class Marty::DeloreanRule < Marty::BaseRule
|
2
2
|
self.abstract_class = true
|
3
3
|
|
4
|
-
|
4
|
+
validates :rule_type, :start_dt, presence: true
|
5
5
|
|
6
6
|
def validate
|
7
7
|
super
|
@@ -200,7 +200,7 @@ class Marty::DeloreanRule < Marty::BaseRule
|
|
200
200
|
|
201
201
|
def self.get_grid_rename_handler(klass)
|
202
202
|
proc do |old, new|
|
203
|
-
klass.where(obsoleted_dt: 'infinity').
|
203
|
+
klass.where(obsoleted_dt: 'infinity').find_each do |r|
|
204
204
|
r.grids.each { |k, v| r.grids[k] = new if v == old }
|
205
205
|
r.results.each do |k, _v|
|
206
206
|
r.results[k] = %Q("#{new}") if
|
@@ -1,4 +1,4 @@
|
|
1
1
|
class Marty::GridIndexBoolean < Marty::Base
|
2
|
-
|
3
|
-
|
2
|
+
validates :created_dt, :data_grid_id, :attr, :index, presence: true
|
3
|
+
validates :key, inclusion: { in: [true, false, nil] }
|
4
4
|
end
|
@@ -27,8 +27,8 @@ class Marty::ImportType < Marty::Base
|
|
27
27
|
self.preprocess_function = nil if preprocess_function.blank?
|
28
28
|
end
|
29
29
|
|
30
|
-
|
31
|
-
|
30
|
+
validates :name, :db_model_name, :role, presence: true
|
31
|
+
validates :name, uniqueness: true
|
32
32
|
validates_with ImportTypeValidator
|
33
33
|
|
34
34
|
def get_model_class
|
data/app/models/marty/posting.rb
CHANGED
@@ -2,7 +2,7 @@ class Marty::Posting < Marty::Base
|
|
2
2
|
has_mcfly append_only: true
|
3
3
|
|
4
4
|
mcfly_validates_uniqueness_of :name
|
5
|
-
|
5
|
+
validates :name, :posting_type_id, :comment, presence: true
|
6
6
|
|
7
7
|
belongs_to :user, class_name: 'Marty::User'
|
8
8
|
belongs_to :posting_type
|
@@ -16,19 +16,19 @@ class Marty::Posting < Marty::Base
|
|
16
16
|
# use Time.now.strftime to name the posting. This has the effect
|
17
17
|
# of using the host's timezone. i.e. since we're in PST8PDT, names
|
18
18
|
# will be based off of the Pacific TZ.
|
19
|
-
dt ||= Time.now
|
19
|
+
dt ||= Time.zone.now
|
20
20
|
"#{posting_type.name}-#{dt.strftime('%Y%m%d-%H%M')}"
|
21
21
|
end
|
22
22
|
|
23
23
|
before_validation :set_posting_name
|
24
24
|
def set_posting_name
|
25
|
-
posting_type = Marty::PostingType.
|
25
|
+
posting_type = Marty::PostingType.find_by(id: posting_type_id)
|
26
26
|
self.name = self.class.make_name(posting_type, created_dt)
|
27
27
|
true
|
28
28
|
end
|
29
29
|
|
30
30
|
def self.do_create(type_name, dt, comment)
|
31
|
-
posting_type = Marty::PostingType.
|
31
|
+
posting_type = Marty::PostingType.find_by(name: type_name)
|
32
32
|
|
33
33
|
raise "unknown posting type #{name}" unless posting_type
|
34
34
|
|
@@ -50,12 +50,12 @@ class Marty::Posting < Marty::Base
|
|
50
50
|
# might be created. Or, use regular validates_uniqueness_of instead
|
51
51
|
# of mcfly_validates_uniqueness_of.
|
52
52
|
delorean_fn :lookup, sig: 1 do |name|
|
53
|
-
p = select(get_struct_attrs).
|
53
|
+
p = select(get_struct_attrs).find_by(name: name)
|
54
54
|
make_openstruct(p)
|
55
55
|
end
|
56
56
|
|
57
57
|
delorean_fn :lookup_dt, sig: 1 do |name|
|
58
|
-
|
58
|
+
find_by(name: name).try(:created_dt)
|
59
59
|
end
|
60
60
|
|
61
61
|
delorean_fn :first_match, sig: [1, 2] do |dt, posting_type = nil|
|
data/app/models/marty/promise.rb
CHANGED
@@ -13,9 +13,10 @@ class Marty::Promise < Marty::Base
|
|
13
13
|
has_many :children,
|
14
14
|
foreign_key: 'parent_id',
|
15
15
|
class_name: 'Marty::Promise',
|
16
|
-
dependent: :destroy
|
16
|
+
dependent: :destroy,
|
17
|
+
inverse_of: :parent
|
17
18
|
|
18
|
-
|
19
|
+
validates :title, :promise_type, presence: true
|
19
20
|
|
20
21
|
belongs_to :parent, class_name: 'Marty::Promise'
|
21
22
|
belongs_to :user, class_name: 'Marty::User'
|
@@ -94,7 +95,7 @@ class Marty::Promise < Marty::Base
|
|
94
95
|
end
|
95
96
|
|
96
97
|
def self.job_by_id(job_id)
|
97
|
-
Delayed::Job.uncached { Delayed::Job.
|
98
|
+
Delayed::Job.uncached { Delayed::Job.find_by(id: job_id) }
|
98
99
|
end
|
99
100
|
|
100
101
|
def work_off_job(job)
|
data/app/models/marty/script.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
class Marty::Script < Marty::Base
|
2
2
|
has_mcfly
|
3
3
|
|
4
|
-
|
4
|
+
validates :name, :body, presence: true
|
5
5
|
mcfly_validates_uniqueness_of :name
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
validates :name,
|
7
|
+
format: { with: /\A[A-Z][a-zA-Z0-9]*(::[A-Z][a-zA-Z0-9]*)*\z/,
|
8
|
+
message: I18n.t('script.save_error') }
|
9
9
|
|
10
10
|
belongs_to :user, class_name: 'Marty::User'
|
11
11
|
|
@@ -50,7 +50,7 @@ class Marty::Script < Marty::Base
|
|
50
50
|
end
|
51
51
|
|
52
52
|
delorean_fn :pretty_print, sig: 1 do |id|
|
53
|
-
script =
|
53
|
+
script = find_by id: id
|
54
54
|
|
55
55
|
next "unknown script #{id}" unless script
|
56
56
|
|
@@ -96,7 +96,7 @@ class Marty::Script < Marty::Base
|
|
96
96
|
tag = Marty::Tag.get_latest1
|
97
97
|
latest = Marty::Script.order('created_dt DESC').first
|
98
98
|
|
99
|
-
tag_time = (dt || [latest.try(:created_dt), Time.now].compact.max) +
|
99
|
+
tag_time = (dt || [latest.try(:created_dt), Time.zone.now].compact.max) +
|
100
100
|
1.second
|
101
101
|
|
102
102
|
# If no tag_time is provided, the tag created_dt will be the same
|
@@ -149,7 +149,7 @@ class Marty::Script < Marty::Base
|
|
149
149
|
return paths_from_config if paths_from_config.present?
|
150
150
|
|
151
151
|
[
|
152
|
-
|
152
|
+
Rails.root.join('delorean'),
|
153
153
|
# FIXME: HACKY, wouldn't it be better to use
|
154
154
|
# Gem::Specification.find_by_name("marty").gem_dir??
|
155
155
|
File.expand_path('../../../../delorean', __FILE__),
|
data/app/models/marty/tag.rb
CHANGED
@@ -2,7 +2,7 @@ class Marty::Tag < Marty::Base
|
|
2
2
|
has_mcfly append_only: true
|
3
3
|
|
4
4
|
mcfly_validates_uniqueness_of :name
|
5
|
-
|
5
|
+
validates :name, :comment, presence: true
|
6
6
|
|
7
7
|
belongs_to :user, class_name: 'Marty::User'
|
8
8
|
|
@@ -17,7 +17,7 @@ class Marty::Tag < Marty::Base
|
|
17
17
|
# use Time.now.strftime to name the posting. This has the effect
|
18
18
|
# of using the host's timezone. i.e. since we're in PST8PDT, names
|
19
19
|
# will be based off of the Pacific TZ.
|
20
|
-
dt ||= Time.now
|
20
|
+
dt ||= Time.zone.now
|
21
21
|
dt.strftime('%Y%m%d-%H%M')
|
22
22
|
end
|
23
23
|
|
@@ -44,9 +44,9 @@ class Marty::Tag < Marty::Base
|
|
44
44
|
# many different types of arguments.
|
45
45
|
case tag_id
|
46
46
|
when Integer, /\A[0-9]+\z/
|
47
|
-
tag =
|
47
|
+
tag = find_by(id: tag_id)
|
48
48
|
when String
|
49
|
-
tag =
|
49
|
+
tag = find_by(name: tag_id)
|
50
50
|
# if tag name wasn't found, look for a matching
|
51
51
|
# posting, then find the tag whose created_dt <= posting dt.
|
52
52
|
if !tag
|
@@ -65,7 +65,7 @@ class Marty::Tag < Marty::Base
|
|
65
65
|
end
|
66
66
|
|
67
67
|
delorean_fn :lookup, cache: true, sig: 1 do |name|
|
68
|
-
t =
|
68
|
+
t = find_by(name: name).select(get_struct_attrs)
|
69
69
|
t && t.attributes
|
70
70
|
end
|
71
71
|
|
data/app/models/marty/token.rb
CHANGED
data/app/models/marty/user.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
class Marty::User < Marty::Base
|
2
|
-
|
3
|
-
|
2
|
+
validates :login, :firstname, :lastname, presence: true
|
3
|
+
validates :login, uniqueness: true
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
validates :login, format: { with: /\A[a-z0-9_\-@\.]*\z/i }
|
6
|
+
validates :login, :firstname, :lastname, length: { maximum: 100 }
|
7
7
|
|
8
8
|
MARTY_IMPORT_UNIQUENESS = [:login]
|
9
9
|
|
@@ -13,7 +13,8 @@ class Marty::User < Marty::Base
|
|
13
13
|
:notification_deliveries,
|
14
14
|
class_name: '::Marty::Notifications::Delivery',
|
15
15
|
dependent: :destroy,
|
16
|
-
foreign_key: :recipient_id
|
16
|
+
foreign_key: :recipient_id,
|
17
|
+
inverse_of: :recipient
|
17
18
|
)
|
18
19
|
|
19
20
|
scope :active, -> { where(active: true) }
|
@@ -56,7 +57,7 @@ class Marty::User < Marty::Base
|
|
56
57
|
# Make sure no one can sign in with an empty password
|
57
58
|
return nil if password.empty?
|
58
59
|
|
59
|
-
user =
|
60
|
+
user = find_by(login: login)
|
60
61
|
|
61
62
|
return nil if !user || !user.active?
|
62
63
|
|
@@ -93,7 +94,7 @@ class Marty::User < Marty::Base
|
|
93
94
|
raise "bad auth_source: #{auth_source.inspect}"
|
94
95
|
end
|
95
96
|
|
96
|
-
|
97
|
+
find_by(login: login) if ok
|
97
98
|
end
|
98
99
|
|
99
100
|
def self.current=(user)
|
@@ -135,8 +136,8 @@ class Marty::User < Marty::Base
|
|
135
136
|
# 1 - Do not allow user to edit own record
|
136
137
|
# 2 - Do not allow user to edit the application system record
|
137
138
|
if user_manager_only
|
138
|
-
system_user = Marty::User.
|
139
|
-
Rails.configuration.marty.system_account.to_s)
|
139
|
+
system_user = Marty::User.find_by(
|
140
|
+
login: Rails.configuration.marty.system_account.to_s)
|
140
141
|
system_id = system_user.id if system_user
|
141
142
|
|
142
143
|
roles = user_roles.map(&:role)
|
@@ -173,6 +174,6 @@ class Marty::User < Marty::Base
|
|
173
174
|
errors.add :base,
|
174
175
|
"Users cannot be deleted - set 'Active' to false to disable the account"
|
175
176
|
|
176
|
-
throw :abort
|
177
|
+
throw :abort if errors.present?
|
177
178
|
end
|
178
179
|
end
|
@@ -2,7 +2,8 @@ class Marty::VwPromise < Marty::Base
|
|
2
2
|
has_many :children,
|
3
3
|
foreign_key: 'parent_id',
|
4
4
|
class_name: 'Marty::VwPromise',
|
5
|
-
dependent: :destroy
|
5
|
+
dependent: :destroy,
|
6
|
+
inverse_of: :parent
|
6
7
|
|
7
8
|
belongs_to :parent, class_name: 'Marty::VwPromise'
|
8
9
|
belongs_to :user, class_name: 'Marty::User'
|
@@ -4,7 +4,7 @@ module Marty
|
|
4
4
|
def self.call(id:, job_class:)
|
5
5
|
model = Marty::BackgroundJob::Schedule.find_by(id: id)
|
6
6
|
|
7
|
-
return remove_schedule(job_class: job_class)
|
7
|
+
return remove_schedule(job_class: job_class) if model.blank?
|
8
8
|
return remove_schedule(job_class: job_class) if model.off?
|
9
9
|
return schedule(job_class: job_class) if model.on?
|
10
10
|
end
|
@@ -14,7 +14,7 @@ module Marty
|
|
14
14
|
[r[0, 2], r[2..-1].reverse]
|
15
15
|
else
|
16
16
|
raw_vals = constraint.split('|')
|
17
|
-
return
|
17
|
+
return if raw_vals.blank?
|
18
18
|
raise 'list constraint not allowed for type Float' if dt == 'float'
|
19
19
|
|
20
20
|
pt = 'infinity'
|
@@ -37,6 +37,7 @@ module Marty
|
|
37
37
|
[data_type]
|
38
38
|
end
|
39
39
|
types << Integer if types.include?(Float)
|
40
|
+
types
|
40
41
|
end
|
41
42
|
|
42
43
|
# if check_data is called from validation, data has already been converted
|
@@ -55,8 +56,8 @@ module Marty
|
|
55
56
|
err = nil
|
56
57
|
begin
|
57
58
|
cvt_val = cvt && !data_v.class.in?(rt) ?
|
58
|
-
DataGrid.parse_fvalue(pt, data_v, dt, klass)
|
59
|
-
|
59
|
+
[DataGrid.parse_fvalue(pt, data_v, dt, klass)].
|
60
|
+
flatten.first : data_v
|
60
61
|
rescue StandardError => e
|
61
62
|
err = e.message
|
62
63
|
end
|
@@ -4,10 +4,10 @@ module Marty
|
|
4
4
|
extend Delorean::Functions
|
5
5
|
|
6
6
|
delorean_fn :call, sig: 0 do
|
7
|
-
glob = Rails.root.join('app
|
7
|
+
glob = Rails.root.join('app/jobs/**/*_job.rb')
|
8
8
|
Dir.glob(glob).sort.each { |f| require f }
|
9
9
|
|
10
|
-
glob2 = Marty.root.join('app
|
10
|
+
glob2 = Marty.root.join('app/jobs/**/*_job.rb')
|
11
11
|
Dir.glob(glob2).sort.each { |f| require f }
|
12
12
|
|
13
13
|
Delayed::Job.where.not(cron: nil).each(&:destroy!)
|
data/lib/marty/data_change.rb
CHANGED