marty 2.9.3 → 3.0.0
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 +4 -4
- data/.gitlab-ci.yml +6 -5
- data/Gemfile.lock +1 -1
- data/app/components/marty/data_grid_view.rb +64 -1
- data/app/components/marty/data_grid_view/client/data_grid_edit.js +550 -0
- data/app/components/marty/import_type_view.rb +11 -2
- data/app/components/marty/main_auth_app.rb +23 -23
- data/app/components/marty/promise_view.rb +1 -1
- data/app/components/marty/report_select.rb +1 -0
- data/app/components/marty/script_form.rb +1 -1
- data/app/components/marty/user_view.rb +30 -18
- data/app/models/marty/data_grid.rb +34 -8
- data/app/models/marty/import_type.rb +2 -4
- data/app/models/marty/role_type.rb +10 -0
- data/app/models/marty/user.rb +9 -4
- data/app/models/marty/user_role.rb +2 -3
- data/app/models/marty/vw_promise.rb +2 -2
- data/app/services/marty/data_grid/constraint.rb +73 -0
- data/app/services/marty/data_grid_view/save_grid.rb +63 -0
- data/config/locales/en.yml +1 -0
- data/db/migrate/107_add_data_grid_constraint.rb +8 -0
- data/db/migrate/507_migrate_marty_roles_to_enum.rb +72 -0
- data/db/seeds.rb +1 -6
- data/lib/marty/permissions.rb +6 -16
- data/lib/marty/version.rb +1 -1
- data/spec/dummy/config/locales/en.yml +1 -0
- data/spec/features/data_grid_spec.rb +499 -0
- data/spec/features/data_import_spec.rb +11 -8
- data/spec/features/user_view_spec.rb +1 -1
- data/spec/fixtures/json/data_grid.json +210 -0
- data/spec/fixtures/misc/data_grid_1.txt +15 -0
- data/spec/fixtures/misc/data_grid_2.txt +17 -0
- data/spec/fixtures/misc/data_grid_3.txt +9 -0
- data/spec/fixtures/misc/data_grid_4.txt +5 -0
- data/spec/fixtures/misc/data_grid_5.txt +19 -0
- data/spec/fixtures/misc/grid1_final_data.json +23 -0
- data/spec/fixtures/misc/grid1_final_meta.json +182 -0
- data/spec/fixtures/misc/grid2_final_data.json +11 -0
- data/spec/fixtures/misc/grid2_final_meta.json +181 -0
- data/spec/fixtures/misc/grid5_final_data.json +142 -0
- data/spec/fixtures/misc/grid5_final_meta.json +152 -0
- data/spec/fixtures/misc/grid_log_errs.json +418 -0
- data/spec/models/data_grid_spec.rb +689 -626
- data/spec/models/import_type_spec.rb +5 -5
- data/spec/spec_helper.rb +9 -7
- data/spec/support/users.rb +1 -1
- metadata +22 -3
- data/app/models/marty/role.rb +0 -6
@@ -13,7 +13,7 @@ class Marty::ImportTypeView < Marty::Grid
|
|
13
13
|
c.attributes =
|
14
14
|
[
|
15
15
|
:name,
|
16
|
-
:
|
16
|
+
:role,
|
17
17
|
:db_model_name,
|
18
18
|
:cleaner_function,
|
19
19
|
:validation_function,
|
@@ -26,8 +26,17 @@ class Marty::ImportTypeView < Marty::Grid
|
|
26
26
|
c.flex = 1
|
27
27
|
end
|
28
28
|
|
29
|
-
attribute :
|
29
|
+
attribute :role do |c|
|
30
30
|
c.width = 150
|
31
|
+
|
32
|
+
store = ::Marty::RoleType.get_all.sort
|
33
|
+
|
34
|
+
c.editor_config = {
|
35
|
+
multi_select: false,
|
36
|
+
store: store,
|
37
|
+
type: :string,
|
38
|
+
xtype: :combo,
|
39
|
+
}
|
31
40
|
end
|
32
41
|
|
33
42
|
attribute :db_model_name do |c|
|
@@ -27,7 +27,7 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def self.has_scripting_perm?
|
30
|
-
|
30
|
+
has_perm?(:admin)
|
31
31
|
end
|
32
32
|
|
33
33
|
def posting_menu
|
@@ -50,7 +50,7 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
50
50
|
{
|
51
51
|
text: 'Log Maintenance',
|
52
52
|
icon_cls: 'fa fa-wrench glyph',
|
53
|
-
disabled: !self.class.
|
53
|
+
disabled: !self.class.has_perm?(:admin),
|
54
54
|
menu: [
|
55
55
|
:log_view,
|
56
56
|
:log_cleanup,
|
@@ -64,7 +64,7 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
64
64
|
{
|
65
65
|
text: 'API Management',
|
66
66
|
icon_cls: 'fa fa-fighter-jet glyph',
|
67
|
-
disabled: !self.class.
|
67
|
+
disabled: !self.class.has_perm?(:admin),
|
68
68
|
menu: [
|
69
69
|
:api_auth_view,
|
70
70
|
:api_config_view,
|
@@ -108,7 +108,7 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
108
108
|
{
|
109
109
|
text: 'Background Jobs',
|
110
110
|
icon_cls: 'fa fa-user-clock glyph',
|
111
|
-
disabled: !self.class.
|
111
|
+
disabled: !self.class.has_perm?(:admin),
|
112
112
|
menu: [
|
113
113
|
:bg_status,
|
114
114
|
:bg_stop,
|
@@ -151,8 +151,8 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
151
151
|
return super unless self.class.has_any_perm?
|
152
152
|
|
153
153
|
[ident_menu, sep] +
|
154
|
-
(self.class.
|
155
|
-
self.class.
|
154
|
+
(self.class.has_perm?(:admin) ||
|
155
|
+
self.class.has_perm?(:user_manager) ? [system_menu, sep] : []) +
|
156
156
|
data_menus +
|
157
157
|
[
|
158
158
|
applications_menu, sep,
|
@@ -165,7 +165,7 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
165
165
|
action :import_type_view do |a|
|
166
166
|
a.text = I18n.t('import_type')
|
167
167
|
a.handler = :netzke_load_component_by_action
|
168
|
-
a.disabled = !self.class.
|
168
|
+
a.disabled = !self.class.has_perm?(:admin)
|
169
169
|
a.icon_cls = 'fa fa-file-import glyph'
|
170
170
|
end
|
171
171
|
|
@@ -194,30 +194,30 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
194
194
|
a.text = I18n.t('user_view')
|
195
195
|
a.handler = :netzke_load_component_by_action
|
196
196
|
a.icon_cls = 'fa fa-users glyph'
|
197
|
-
a.disabled = !self.class.
|
198
|
-
!self.class.
|
197
|
+
a.disabled = !self.class.has_perm?(:admin) &&
|
198
|
+
!self.class.has_perm?(:user_manager)
|
199
199
|
end
|
200
200
|
|
201
201
|
action :event_view do |a|
|
202
202
|
a.text = I18n.t('event_view')
|
203
203
|
a.handler = :netzke_load_component_by_action
|
204
204
|
a.icon_cls = 'fa fa-bolt glyph'
|
205
|
-
a.disabled = !self.class.
|
205
|
+
a.disabled = !self.class.has_perm?(:admin)
|
206
206
|
end
|
207
207
|
|
208
208
|
action :config_view do |a|
|
209
209
|
a.text = I18n.t('config_view')
|
210
210
|
a.handler = :netzke_load_component_by_action
|
211
211
|
a.icon_cls = 'fa fa-cog glyph'
|
212
|
-
a.disabled = !self.class.
|
213
|
-
!self.class.
|
212
|
+
a.disabled = !self.class.has_perm?(:admin) &&
|
213
|
+
!self.class.has_perm?(:user_manager)
|
214
214
|
end
|
215
215
|
|
216
216
|
action :api_auth_view do |a|
|
217
217
|
a.text = 'API Auth Management'
|
218
218
|
a.handler = :netzke_load_component_by_action
|
219
219
|
a.icon_cls = 'fa fa-key glyph'
|
220
|
-
a.disabled = !self.class.
|
220
|
+
a.disabled = !self.class.has_perm?(:admin)
|
221
221
|
end
|
222
222
|
|
223
223
|
action :api_config_view do |a|
|
@@ -225,7 +225,7 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
225
225
|
a.tooltip = 'Manage API behavior and settings'
|
226
226
|
a.handler = :netzke_load_component_by_action
|
227
227
|
a.icon_cls = 'fa fa-sliders-h glyph'
|
228
|
-
a.disabled = !self.class.
|
228
|
+
a.disabled = !self.class.has_perm?(:admin)
|
229
229
|
end
|
230
230
|
|
231
231
|
action :api_log_view do |a|
|
@@ -233,7 +233,7 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
233
233
|
a.tooltip = 'View API logs'
|
234
234
|
a.handler = :netzke_load_component_by_action
|
235
235
|
a.icon_cls = 'fa fa-pencil-alt glyph'
|
236
|
-
a.disabled = !self.class.
|
236
|
+
a.disabled = !self.class.has_perm?(:admin)
|
237
237
|
end
|
238
238
|
|
239
239
|
action :data_grid_view do |a|
|
@@ -247,42 +247,42 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
247
247
|
a.text = 'Reload Scripts'
|
248
248
|
a.tooltip = 'Reload and tag Delorean scripts'
|
249
249
|
a.icon_cls = 'fa fa-sync-alt glyph'
|
250
|
-
a.disabled = !self.class.
|
250
|
+
a.disabled = !self.class.has_perm?(:admin)
|
251
251
|
end
|
252
252
|
|
253
253
|
action :load_seed do |a|
|
254
254
|
a.text = 'Load Seeds'
|
255
255
|
a.tooltip = 'Load Seeds'
|
256
256
|
a.icon_cls = 'fa fa-retweet glyph'
|
257
|
-
a.disabled = !self.class.
|
257
|
+
a.disabled = !self.class.has_perm?(:admin)
|
258
258
|
end
|
259
259
|
|
260
260
|
action :bg_status do |a|
|
261
261
|
a.text = 'Show Delayed Jobs Status'
|
262
262
|
a.tooltip = 'Run delayed_job status script'
|
263
263
|
a.icon_cls = 'fa fa-desktop glyph'
|
264
|
-
a.disabled = !self.class.
|
264
|
+
a.disabled = !self.class.has_perm?(:admin)
|
265
265
|
end
|
266
266
|
|
267
267
|
action :bg_stop do |a|
|
268
268
|
a.text = 'Stop Delayed Jobs'
|
269
269
|
a.tooltip = 'Run delayed_job stop script'
|
270
270
|
a.icon_cls = 'fa fa-skull glyph'
|
271
|
-
a.disabled = !self.class.
|
271
|
+
a.disabled = !self.class.has_perm?(:admin)
|
272
272
|
end
|
273
273
|
|
274
274
|
action :bg_restart do |a|
|
275
275
|
a.text = 'Restart Delayed Jobs'
|
276
276
|
a.tooltip = 'Run delayed_job restart script using DELAYED_JOB_PARAMS'
|
277
277
|
a.icon_cls = 'fa fa-power-off glyph'
|
278
|
-
a.disabled = !self.class.
|
278
|
+
a.disabled = !self.class.has_perm?(:admin)
|
279
279
|
end
|
280
280
|
|
281
281
|
action :schedule_jobs_dashboard do |a|
|
282
282
|
a.text = 'Schedule Jobs Dashboard'
|
283
283
|
a.tooltip = 'Edit Delayed Jobs Cron schedules'
|
284
284
|
a.icon_cls = 'fa fa-cog glyph'
|
285
|
-
a.disabled = !self.class.
|
285
|
+
a.disabled = !self.class.has_perm?(:admin)
|
286
286
|
a.handler = :netzke_load_component_by_action
|
287
287
|
end
|
288
288
|
|
@@ -291,14 +291,14 @@ class Marty::MainAuthApp < Marty::AuthApp
|
|
291
291
|
a.tooltip = 'View Log'
|
292
292
|
a.handler = :netzke_load_component_by_action
|
293
293
|
a.icon_cls = 'fa fa-cog glyph'
|
294
|
-
a.disabled = !self.class.
|
294
|
+
a.disabled = !self.class.has_perm?(:admin)
|
295
295
|
end
|
296
296
|
|
297
297
|
action :log_cleanup do |a|
|
298
298
|
a.text = 'Cleanup Log Table'
|
299
299
|
a.tooltip = 'Delete old log records'
|
300
300
|
a.icon_cls = 'fa fa-cog glyph'
|
301
|
-
a.disabled = !self.class.
|
301
|
+
a.disabled = !self.class.has_perm?(:admin)
|
302
302
|
end
|
303
303
|
|
304
304
|
######################################################################
|
@@ -39,7 +39,7 @@ class Marty::ScriptForm < Marty::Form
|
|
39
39
|
end
|
40
40
|
|
41
41
|
def can_save?(script)
|
42
|
-
script && self.class.
|
42
|
+
script && self.class.has_perm?(:dev) && Mcfly.is_infinity(script.obsoleted_dt)
|
43
43
|
end
|
44
44
|
|
45
45
|
######################################################################
|
@@ -11,7 +11,7 @@ module Marty; class UserView < Marty::Grid
|
|
11
11
|
:firstname,
|
12
12
|
:lastname,
|
13
13
|
:active,
|
14
|
-
:
|
14
|
+
:user_roles,
|
15
15
|
]
|
16
16
|
end
|
17
17
|
|
@@ -27,21 +27,27 @@ module Marty; class UserView < Marty::Grid
|
|
27
27
|
c.store_config.merge!(sorters: [{ property: :login,
|
28
28
|
direction: 'ASC',
|
29
29
|
}]) if c.attributes.include?(:login)
|
30
|
-
c.scope = ->(arel) { arel.includes(:
|
30
|
+
c.scope = ->(arel) { arel.includes(:user_roles) }
|
31
31
|
end
|
32
32
|
|
33
33
|
def self.set_roles(roles, user)
|
34
|
-
roles
|
34
|
+
roles = [] unless roles.present?
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
ur.destroy unless roles.include?(I18n.t("roles.#{ur.role.name}"))
|
36
|
+
roles = Marty::RoleType.get_all.select do |role|
|
37
|
+
roles.include?(I18n.t("roles.#{role}", default: role))
|
39
38
|
end
|
40
39
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
40
|
+
roles_in_user = user.user_roles.map(&:role)
|
41
|
+
roles_to_delete = roles_in_user - roles
|
42
|
+
roles_to_add = roles - roles_in_user
|
43
|
+
|
44
|
+
Marty::User.transaction do
|
45
|
+
user.user_roles.where(role: roles_to_delete).map(&:destroy!)
|
46
|
+
|
47
|
+
roles_to_add.each do |role|
|
48
|
+
user.user_roles.create!(role: role)
|
49
|
+
end
|
50
|
+
end
|
45
51
|
end
|
46
52
|
|
47
53
|
def self.create_edit_user(data)
|
@@ -49,12 +55,12 @@ module Marty; class UserView < Marty::Grid
|
|
49
55
|
user = data['id'].nil? ? User.new : User.find(data['id'])
|
50
56
|
|
51
57
|
user_columns.each do |c|
|
52
|
-
user.send("#{c}=", data[c.to_s]) unless c == :
|
58
|
+
user.send("#{c}=", data[c.to_s]) unless c == :user_roles
|
53
59
|
end
|
54
60
|
|
55
61
|
if user.valid?
|
56
62
|
user.save
|
57
|
-
set_roles(data['
|
63
|
+
set_roles(data['user_roles'], user)
|
58
64
|
end
|
59
65
|
|
60
66
|
user
|
@@ -139,20 +145,26 @@ module Marty; class UserView < Marty::Grid
|
|
139
145
|
c.label = I18n.t('user_grid.active')
|
140
146
|
end
|
141
147
|
|
142
|
-
attribute :
|
148
|
+
attribute :user_roles do |c|
|
143
149
|
c.width = 100
|
144
150
|
c.flex = 1
|
145
151
|
c.label = I18n.t('user_grid.roles')
|
146
|
-
c.type = :string
|
152
|
+
c.type = :string
|
147
153
|
|
148
|
-
|
149
|
-
|
150
|
-
|
154
|
+
c.getter = lambda do |r|
|
155
|
+
r.user_roles.map do |ur|
|
156
|
+
I18n.t("roles.#{ur.role}", default: ur.role)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
store = ::Marty::RoleType.get_all.sort.map do |role|
|
161
|
+
I18n.t("roles.#{role}", default: role)
|
162
|
+
end
|
151
163
|
|
152
164
|
c.editor_config = {
|
153
165
|
multi_select: true,
|
154
166
|
empty_text: I18n.t('user_grid.select_roles'),
|
155
|
-
store:
|
167
|
+
store: store,
|
156
168
|
type: :string,
|
157
169
|
xtype: :combo,
|
158
170
|
}
|
@@ -70,6 +70,23 @@ class Marty::DataGrid < Marty::Base
|
|
70
70
|
|
71
71
|
dg.errors.add(:base, 'duplicate vertical key combination') unless
|
72
72
|
v_zip_keys.uniq.length == v_zip_keys.length
|
73
|
+
|
74
|
+
con_chk = []
|
75
|
+
begin
|
76
|
+
con_chk = Marty::DataGrid::Constraint.parse(dg.data_type, dg.constraint)
|
77
|
+
rescue StandardError => e
|
78
|
+
dg.errors.add(:base, "Error in constraint: #{e.message}")
|
79
|
+
end
|
80
|
+
data_check = Marty::DataGrid::Constraint.check_data(dg.data_type,
|
81
|
+
dg.data, con_chk)
|
82
|
+
return unless data_check.present?
|
83
|
+
|
84
|
+
data_check.each do |(err, x, y)|
|
85
|
+
dg.errors.add(:base, "cell #{x}, #{y} fails constraint check") if
|
86
|
+
err == :constraint
|
87
|
+
dg.errors.add(:base, "cell #{x}, #{y} incorrect type") if
|
88
|
+
err == :type
|
89
|
+
end
|
73
90
|
end
|
74
91
|
end
|
75
92
|
|
@@ -342,10 +359,14 @@ class Marty::DataGrid < Marty::Base
|
|
342
359
|
|
343
360
|
def export_array
|
344
361
|
# add data type metadata row if not default
|
345
|
-
|
346
|
-
|
362
|
+
lenstr = 'lenient' if lenient
|
363
|
+
typestr = data_type unless [nil, DEFAULT_DATA_TYPE].member?(data_type) &&
|
364
|
+
!constraint.present?
|
365
|
+
|
366
|
+
len_dt = [lenstr, typestr].compact.join(' ')
|
347
367
|
|
348
|
-
meta_rows =
|
368
|
+
meta_rows = len_dt.present? || constraint.present? ?
|
369
|
+
[[len_dt, constraint]] : []
|
349
370
|
|
350
371
|
meta_rows += metadata.map do |inf|
|
351
372
|
[inf['attr'], inf['type'], inf['dir'], inf['rs_keep'] || '']
|
@@ -466,7 +487,7 @@ class Marty::DataGrid < Marty::Base
|
|
466
487
|
data_type, lenient = nil, false
|
467
488
|
|
468
489
|
# check if there's a data_type definition
|
469
|
-
dt, *x = rows[0]
|
490
|
+
dt, constraint, *x = rows[0]
|
470
491
|
if dt && x.all?(&:nil?)
|
471
492
|
dts = dt.split
|
472
493
|
raise "bad data type '#{dt}'" if dts.count > 2
|
@@ -474,8 +495,10 @@ class Marty::DataGrid < Marty::Base
|
|
474
495
|
lenient = dts.delete 'lenient'
|
475
496
|
data_type = dts.first
|
476
497
|
end
|
498
|
+
constraint = nil if x.first.in?(['v', 'h'])
|
477
499
|
|
478
|
-
|
500
|
+
start_md = constraint || data_type || lenient ? 1 : 0
|
501
|
+
rows_for_metadata = rows[start_md...blank_index]
|
479
502
|
metadata = rows_for_metadata.map do |attr, type, dir, rs_keep, key|
|
480
503
|
raise 'metadata elements must include attr/type/dir' unless
|
481
504
|
attr && type && dir
|
@@ -549,11 +572,12 @@ class Marty::DataGrid < Marty::Base
|
|
549
572
|
end
|
550
573
|
end
|
551
574
|
|
552
|
-
[metadata, data, data_type, lenient]
|
575
|
+
[metadata, data, data_type, lenient, constraint]
|
553
576
|
end
|
554
577
|
|
555
578
|
def self.create_from_import(name, import_text, created_dt = nil)
|
556
|
-
metadata, data, data_type, lenient = parse(created_dt,
|
579
|
+
metadata, data, data_type, lenient, constraint = parse(created_dt,
|
580
|
+
import_text, {})
|
557
581
|
dg = new
|
558
582
|
dg.name = name
|
559
583
|
dg.data = data
|
@@ -561,12 +585,13 @@ class Marty::DataGrid < Marty::Base
|
|
561
585
|
dg.lenient = !!lenient
|
562
586
|
dg.metadata = metadata
|
563
587
|
dg.created_dt = created_dt if created_dt
|
588
|
+
dg.constraint = constraint
|
564
589
|
dg.save!
|
565
590
|
dg
|
566
591
|
end
|
567
592
|
|
568
593
|
def update_from_import(name, import_text, created_dt = nil)
|
569
|
-
new_metadata, data, data_type, lenient =
|
594
|
+
new_metadata, data, data_type, lenient, constraint =
|
570
595
|
self.class.parse(created_dt, import_text, {})
|
571
596
|
|
572
597
|
self.name = name
|
@@ -575,6 +600,7 @@ class Marty::DataGrid < Marty::Base
|
|
575
600
|
self.lenient = !!lenient
|
576
601
|
# Otherwise changed will depend on order in hashes
|
577
602
|
self.metadata = new_metadata unless metadata == new_metadata
|
603
|
+
self.constraint = constraint
|
578
604
|
self.created_dt = created_dt if created_dt
|
579
605
|
save!
|
580
606
|
end
|
@@ -27,9 +27,7 @@ class Marty::ImportType < Marty::Base
|
|
27
27
|
self.preprocess_function = nil if preprocess_function.blank?
|
28
28
|
end
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
validates_presence_of :name, :db_model_name, :role_id
|
30
|
+
validates_presence_of :name, :db_model_name, :role
|
33
31
|
validates_uniqueness_of :name
|
34
32
|
validates_with ImportTypeValidator
|
35
33
|
|
@@ -38,6 +36,6 @@ class Marty::ImportType < Marty::Base
|
|
38
36
|
end
|
39
37
|
|
40
38
|
def allow_import?
|
41
|
-
Mcfly.whodunnit && Mcfly.whodunnit.roles.
|
39
|
+
Mcfly.whodunnit && Mcfly.whodunnit.roles.include?(role)
|
42
40
|
end
|
43
41
|
end
|