foreman-tasks 0.15.11 → 0.16.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/foreman_tasks/tasks_controller.rb +14 -19
- data/app/helpers/foreman_tasks/foreman_tasks_helper.rb +0 -20
- data/app/lib/actions/bulk_action.rb +1 -1
- data/app/models/foreman_tasks/lock.rb +0 -9
- data/app/models/foreman_tasks/task.rb +12 -74
- data/app/models/foreman_tasks/task/dynflow_task.rb +2 -1
- data/app/models/foreman_tasks/task/search.rb +52 -0
- data/app/views/foreman_tasks/tasks/index.html.erb +0 -3
- data/app/views/foreman_tasks/tasks/show.html.erb +9 -1
- data/db/migrate/20180927120509_add_user_id.foreman_tasks.rb +40 -0
- data/lib/foreman_tasks/dynflow/persistence.rb +0 -1
- data/lib/foreman_tasks/tasks/export_tasks.rake +1 -1
- data/lib/foreman_tasks/version.rb +1 -1
- data/test/controllers/tasks_controller_test.rb +0 -46
- data/test/factories/task_factory.rb +0 -8
- data/test/unit/actions/bulk_action_test.rb +0 -2
- data/test/unit/dynflow_console_authorizer_test.rb +1 -1
- data/test/unit/task_test.rb +6 -2
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/PausedTasksCard/PausedTasksCard.js +1 -6
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/PausedTasksCard/__snapshots__/PausedTasksCard.test.js.snap +0 -2
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/RunningTasksCard/RunningTasksCard.js +1 -6
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/RunningTasksCard/__snapshots__/RunningTasksCard.test.js.snap +0 -2
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.js +6 -3
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/ScheduledTasksCard.scss +3 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/ScheduledTasksCard/__snapshots__/ScheduledTasksCard.test.js.snap +0 -3
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.js +0 -2
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCard.scss +4 -0
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/StoppedTasksCardHelper.js +3 -3
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/StoppedTasksCard/__snapshots__/StoppedTasksCard.test.js.snap +54 -495
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.js +0 -1
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutCard/TasksDonutCard.scss +0 -6
- data/webpack/ForemanTasks/Components/TasksDashboard/Components/TasksCardsGrid/Components/TasksDonutChart/TasksDonutChart.scss +3 -0
- metadata +6 -5
- data/test/helpers/foreman_tasks/foreman_tasks_helper_test.rb +0 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a562e9a32057e45cbf20bcc2d511ee03580cee1181af686965683bccfc1d6f8e
|
4
|
+
data.tar.gz: bcffaac1d9efb02ef8677394c7af554058aad577d5e1a7ce9b32c66ac21206f1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e7acf7b281043c1ad3a3c0fcb45436258caf1f11a06295c5e4b69b43f8bbe5ea450d61e25346d638198c72596e1ac3e86fdad1eff2f092d4fc3254cb8e551d5f
|
7
|
+
data.tar.gz: e5c9234ef7ccd241c17ef37892a79d04b6de918034d1e305093bea7b54ce125dce88cb1c9360f4a7dab1674eefbd00db20b3848a445ea297eeaab37c271cd855
|
@@ -12,18 +12,26 @@ module ForemanTasks
|
|
12
12
|
|
13
13
|
def index
|
14
14
|
params[:order] ||= 'started_at DESC'
|
15
|
-
|
15
|
+
respond_to do |format|
|
16
|
+
format.html do
|
17
|
+
@tasks = filter(resource_base)
|
18
|
+
render :index, layout: !request.xhr?
|
19
|
+
end
|
20
|
+
format.csv do
|
21
|
+
@tasks = filter(resource_base, paginate: false)
|
22
|
+
csv_response(@tasks, [:id, :action, :state, :result, 'started_at.in_time_zone', 'ended_at.in_time_zone', :username], ['Id', 'Action', 'State', 'Result', 'Started At', 'Ended At', 'User'])
|
23
|
+
end
|
24
|
+
end
|
16
25
|
end
|
17
26
|
|
18
27
|
def summary
|
19
|
-
|
20
|
-
render json: Task::Summarizer.new(Task.where(:id => scope), params[:recent_timeframe].to_i).summary
|
28
|
+
render json: Task::Summarizer.new(resource_base, params[:recent_timeframe].to_i).summary
|
21
29
|
end
|
22
30
|
|
23
31
|
def sub_tasks
|
24
|
-
|
25
|
-
@
|
26
|
-
|
32
|
+
task = resource_base.find(params[:id])
|
33
|
+
@tasks = filter(task.sub_tasks)
|
34
|
+
render :index
|
27
35
|
end
|
28
36
|
|
29
37
|
def cancel_step
|
@@ -95,19 +103,6 @@ module ForemanTasks
|
|
95
103
|
|
96
104
|
private
|
97
105
|
|
98
|
-
def respond_with_tasks(scope)
|
99
|
-
respond_to do |format|
|
100
|
-
format.html do
|
101
|
-
@tasks = filter(scope)
|
102
|
-
render :index, layout: !request.xhr?
|
103
|
-
end
|
104
|
-
format.csv do
|
105
|
-
@tasks = filter(scope, paginate: false)
|
106
|
-
csv_response(@tasks, [:id, :action, :state, :result, 'started_at.in_time_zone', 'ended_at.in_time_zone', :username], ['Id', 'Action', 'State', 'Result', 'Started At', 'Ended At', 'User'])
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
106
|
def restrict_dangerous_actions
|
112
107
|
render_403 unless Setting['dynflow_allow_dangerous_actions']
|
113
108
|
end
|
@@ -122,26 +122,6 @@ module ForemanTasks
|
|
122
122
|
render :partial => 'common/trigger_form', :locals => { :f => f, :triggering => triggering }
|
123
123
|
end
|
124
124
|
|
125
|
-
def task_breadcrumb_item(task, active = false)
|
126
|
-
item = { :caption => format_task_input(task) }
|
127
|
-
item[:url] = url_for(foreman_tasks_task_path(task.id)) unless active
|
128
|
-
item
|
129
|
-
end
|
130
|
-
|
131
|
-
def index_breadcrumb_item
|
132
|
-
item = { :caption => _('Tasks') }
|
133
|
-
item[:url] = foreman_tasks_tasks_url if action_name != 'index'
|
134
|
-
item
|
135
|
-
end
|
136
|
-
|
137
|
-
def breadcrumb_items
|
138
|
-
items = [index_breadcrumb_item]
|
139
|
-
return items if action_name == 'index'
|
140
|
-
items << task_breadcrumb_item(@task, action_name == 'show')
|
141
|
-
items << { :caption => _('Sub tasks') } if action_name == 'sub_tasks'
|
142
|
-
items
|
143
|
-
end
|
144
|
-
|
145
125
|
private
|
146
126
|
|
147
127
|
def future_mode_fieldset(f, triggering)
|
@@ -46,7 +46,7 @@ module Actions
|
|
46
46
|
def create_sub_plans
|
47
47
|
action_class = input[:action_class].constantize
|
48
48
|
target_class = input[:target_class].constantize
|
49
|
-
targets = target_class.
|
49
|
+
targets = target_class.where(:id => current_batch)
|
50
50
|
|
51
51
|
missing = Array.new((current_batch - targets.map(&:id)).count) { nil }
|
52
52
|
|
@@ -118,11 +118,6 @@ module ForemanTasks
|
|
118
118
|
build_link(resource, uuid).available?
|
119
119
|
end
|
120
120
|
|
121
|
-
# Records the information about the user that triggered the task
|
122
|
-
def owner!(user, uuid)
|
123
|
-
build_owner(user, uuid).save!
|
124
|
-
end
|
125
|
-
|
126
121
|
private
|
127
122
|
|
128
123
|
def all_lock_names(resource, include_links = false)
|
@@ -166,10 +161,6 @@ module ForemanTasks
|
|
166
161
|
build(uuid, resource, LINK_LOCK_NAME, false)
|
167
162
|
end
|
168
163
|
|
169
|
-
def build_owner(user, uuid = nil)
|
170
|
-
build(uuid, user, OWNER_LOCK_NAME, false)
|
171
|
-
end
|
172
|
-
|
173
164
|
def build(uuid, resource, lock_name, exclusive)
|
174
165
|
new(task_id: uuid,
|
175
166
|
name: lock_name,
|
@@ -3,6 +3,7 @@ require 'securerandom'
|
|
3
3
|
module ForemanTasks
|
4
4
|
class Task < ApplicationRecord
|
5
5
|
include Authorizable
|
6
|
+
extend Search
|
6
7
|
|
7
8
|
def check_permissions_after_save
|
8
9
|
# there's no create_tasks permission, tasks are created as a result of internal actions, in such case we
|
@@ -29,10 +30,7 @@ module ForemanTasks
|
|
29
30
|
has_many :task_groups, :through => :task_group_members
|
30
31
|
has_many :recurring_logic_task_groups, -> { where :type => 'ForemanTasks::TaskGroups::RecurringLogicTaskGroup' },
|
31
32
|
:through => :task_group_members, :source => :task_group
|
32
|
-
|
33
|
-
# specify has_one relation though has_many relation
|
34
|
-
has_many :owners, -> { where(['foreman_tasks_locks.name = ?', Lock::OWNER_LOCK_NAME]) },
|
35
|
-
:through => :locks, :source => :resource, :source_type => 'User'
|
33
|
+
belongs_to :user
|
36
34
|
|
37
35
|
scoped_search :on => :id, :complete_value => false
|
38
36
|
scoped_search :on => :action, :complete_value => false
|
@@ -46,17 +44,15 @@ module ForemanTasks
|
|
46
44
|
scoped_search :on => :parent_task_id, :complete_value => true
|
47
45
|
scoped_search :relation => :locks, :on => :resource_id, :complete_value => false, :rename => 'location_id', :ext_method => :search_by_taxonomy, :only_explicit => true
|
48
46
|
scoped_search :relation => :locks, :on => :resource_id, :complete_value => false, :rename => 'organization_id', :ext_method => :search_by_taxonomy, :only_explicit => true
|
49
|
-
scoped_search :relation => :locks, :on => :resource_type, :complete_value => true, :rename => 'resource_type', :ext_method => :search_by_generic_resource
|
50
|
-
scoped_search :relation => :locks, :on => :resource_id, :complete_value => false, :rename => 'resource_id', :ext_method => :search_by_generic_resource
|
51
|
-
scoped_search :
|
52
|
-
:on => :id,
|
47
|
+
scoped_search :relation => :locks, :on => :resource_type, :complete_value => true, :rename => 'resource_type', :ext_method => :search_by_generic_resource, :only_explicit => true
|
48
|
+
scoped_search :relation => :locks, :on => :resource_id, :complete_value => false, :rename => 'resource_id', :ext_method => :search_by_generic_resource, :only_explicit => true
|
49
|
+
scoped_search :on => :user_id,
|
53
50
|
:complete_value => true,
|
54
|
-
:rename => '
|
55
|
-
:ext_method => :search_by_owner,
|
51
|
+
:rename => 'user.id',
|
56
52
|
:validator => ->(value) { ScopedSearch::Validators::INTEGER.call(value) || value == 'current_user' },
|
57
|
-
:aliases => ['
|
58
|
-
scoped_search :relation => :
|
59
|
-
scoped_search :relation => :
|
53
|
+
:aliases => ['owner.id'], :ext_method => :search_by_owner, :only_explicit => true
|
54
|
+
scoped_search :relation => :user, :on => :login, :rename => 'user.login', :complete_value => true, :aliases => ['owner.login', 'user'], :ext_method => :search_by_owner, :only_explicit => true
|
55
|
+
scoped_search :relation => :user, :on => :firstname, :rename => 'user.firstname', :complete_value => true, :aliases => ['owner.firstname'], :ext_method => :search_by_owner, :only_explicit => true
|
60
56
|
scoped_search :relation => :task_groups, :on => :id, :complete_value => true, :rename => 'task_group.id', :validator => ScopedSearch::Validators::INTEGER
|
61
57
|
|
62
58
|
scope :active, -> { where('foreman_tasks_tasks.state != ?', :stopped) }
|
@@ -77,11 +73,11 @@ module ForemanTasks
|
|
77
73
|
end
|
78
74
|
|
79
75
|
def owner
|
80
|
-
|
76
|
+
user
|
81
77
|
end
|
82
78
|
|
83
79
|
def username
|
84
|
-
owner
|
80
|
+
owner
|
85
81
|
end
|
86
82
|
|
87
83
|
def execution_type
|
@@ -150,7 +146,7 @@ module ForemanTasks
|
|
150
146
|
|
151
147
|
# used by Foreman notifications framework
|
152
148
|
def notification_recipients_ids
|
153
|
-
|
149
|
+
[owner.id]
|
154
150
|
end
|
155
151
|
|
156
152
|
def build_notifications
|
@@ -165,64 +161,6 @@ module ForemanTasks
|
|
165
161
|
notifications
|
166
162
|
end
|
167
163
|
|
168
|
-
def self.search_by_generic_resource(key, operator, value)
|
169
|
-
key = 'resource_type' if key.blank?
|
170
|
-
key_name = connection.quote_column_name(key.sub(/^.*\./, ''))
|
171
|
-
condition = sanitize_sql_for_conditions(["foreman_tasks_locks.#{key_name} #{operator} ?", value])
|
172
|
-
|
173
|
-
{ :conditions => condition, :joins => :locks }
|
174
|
-
end
|
175
|
-
|
176
|
-
def self.search_by_taxonomy(key, operator, value)
|
177
|
-
uniq_suffix = SecureRandom.hex(3)
|
178
|
-
resource_type = key == 'location_id' ? 'Location' : 'Organization'
|
179
|
-
|
180
|
-
joins = <<-SQL
|
181
|
-
LEFT JOIN foreman_tasks_locks AS foreman_tasks_locks_taxonomy#{uniq_suffix}
|
182
|
-
ON (foreman_tasks_locks_taxonomy#{uniq_suffix}.task_id = foreman_tasks_tasks.id AND
|
183
|
-
foreman_tasks_locks_taxonomy#{uniq_suffix}.resource_type = '#{resource_type}')
|
184
|
-
SQL
|
185
|
-
# Select only those tasks which either have the correct taxonomy or are not related to any
|
186
|
-
sql = "foreman_tasks_locks_taxonomy#{uniq_suffix}.resource_id #{operator} ? OR foreman_tasks_locks_taxonomy#{uniq_suffix}.resource_id IS NULL"
|
187
|
-
{ :conditions => sanitize_sql_for_conditions([sql, value]), :joins => joins }
|
188
|
-
end
|
189
|
-
|
190
|
-
def self.search_by_owner(key, operator, value)
|
191
|
-
return { :conditions => '0 = 1' } if value == 'current_user' && User.current.nil?
|
192
|
-
|
193
|
-
key = 'owners.login' if key == 'user'
|
194
|
-
# using uniq suffix to avoid colisions when searching by two different owners via ScopedSearch
|
195
|
-
uniq_suffix = SecureRandom.hex(3)
|
196
|
-
key_name = connection.quote_column_name(key.sub(/^.*\./, ''))
|
197
|
-
value.sub!('*', '%%')
|
198
|
-
condition = if key.blank?
|
199
|
-
sanitize_sql_for_conditions(["users#{uniq_suffix}.login #{operator} ? or users#{uniq_suffix}.firstname #{operator} ? ", value, value])
|
200
|
-
elsif key =~ /\.id\Z/
|
201
|
-
value = User.current.id if value == 'current_user'
|
202
|
-
sanitize_sql_for_conditions(["foreman_tasks_locks_owner#{uniq_suffix}.resource_id #{operator} ?", value])
|
203
|
-
else
|
204
|
-
placeholder, value = operator == 'IN' ? ['(?)', value.split(',').map(&:strip)] : ['?', value]
|
205
|
-
sanitize_sql_for_conditions(["users#{uniq_suffix}.#{key_name} #{operator} #{placeholder}", value])
|
206
|
-
end
|
207
|
-
{ :conditions => condition, :joins => joins_for_user_search(key, uniq_suffix) }
|
208
|
-
end
|
209
|
-
|
210
|
-
def self.joins_for_user_search(key, uniq_suffix)
|
211
|
-
joins = <<-SQL
|
212
|
-
INNER JOIN foreman_tasks_locks AS foreman_tasks_locks_owner#{uniq_suffix}
|
213
|
-
ON (foreman_tasks_locks_owner#{uniq_suffix}.task_id = foreman_tasks_tasks.id AND
|
214
|
-
foreman_tasks_locks_owner#{uniq_suffix}.resource_type = 'User' AND
|
215
|
-
foreman_tasks_locks_owner#{uniq_suffix}.name = '#{Lock::OWNER_LOCK_NAME}')
|
216
|
-
SQL
|
217
|
-
if key !~ /\.id\Z/
|
218
|
-
joins << <<-SQL
|
219
|
-
INNER JOIN users as users#{uniq_suffix}
|
220
|
-
ON (users#{uniq_suffix}.id = foreman_tasks_locks_owner#{uniq_suffix}.resource_id)
|
221
|
-
SQL
|
222
|
-
end
|
223
|
-
joins
|
224
|
-
end
|
225
|
-
|
226
164
|
def progress
|
227
165
|
case state.to_s
|
228
166
|
when 'running', 'paused'
|
@@ -208,7 +208,8 @@ module ForemanTasks
|
|
208
208
|
def self.new_for_execution_plan(execution_plan_id, data)
|
209
209
|
new(:external_id => execution_plan_id,
|
210
210
|
:state => data[:state].to_s,
|
211
|
-
:result => data[:result].to_s
|
211
|
+
:result => data[:result].to_s,
|
212
|
+
:user_id => User.current.try(:id))
|
212
213
|
end
|
213
214
|
|
214
215
|
def self.model_name
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module ForemanTasks
|
2
|
+
class Task
|
3
|
+
module Search
|
4
|
+
def search_by_generic_resource(key, operator, value)
|
5
|
+
key = 'resource_type' if key.blank?
|
6
|
+
key_name = connection.quote_column_name(key.sub(/^.*\./, ''))
|
7
|
+
condition = sanitize_sql_for_conditions(["foreman_tasks_locks.#{key_name} #{operator} ?", value])
|
8
|
+
|
9
|
+
{ :conditions => condition, :joins => :locks }
|
10
|
+
end
|
11
|
+
|
12
|
+
def search_by_taxonomy(key, operator, value)
|
13
|
+
uniq_suffix = SecureRandom.hex(3)
|
14
|
+
resource_type = key == 'location_id' ? 'Location' : 'Organization'
|
15
|
+
|
16
|
+
joins = <<-SQL
|
17
|
+
LEFT JOIN foreman_tasks_locks AS foreman_tasks_locks_taxonomy#{uniq_suffix}
|
18
|
+
ON (foreman_tasks_locks_taxonomy#{uniq_suffix}.task_id = foreman_tasks_tasks.id AND
|
19
|
+
foreman_tasks_locks_taxonomy#{uniq_suffix}.resource_type = '#{resource_type}')
|
20
|
+
SQL
|
21
|
+
# Select only those tasks which either have the correct taxonomy or are not related to any
|
22
|
+
sql = "foreman_tasks_locks_taxonomy#{uniq_suffix}.resource_id #{operator} ? OR foreman_tasks_locks_taxonomy#{uniq_suffix}.resource_id IS NULL"
|
23
|
+
{ :conditions => sanitize_sql_for_conditions([sql, value]), :joins => joins }
|
24
|
+
end
|
25
|
+
|
26
|
+
def search_by_owner(key, operator, value)
|
27
|
+
return { :conditions => '0 = 1' } if value == 'current_user' && User.current.nil?
|
28
|
+
|
29
|
+
key = 'owners.login' if key == 'user'
|
30
|
+
# using uniq suffix to avoid colisions when searching by two different owners via ScopedSearch
|
31
|
+
uniq_suffix = SecureRandom.hex(3)
|
32
|
+
key_name = connection.quote_column_name(key.sub(/^.*\./, ''))
|
33
|
+
value.sub!('*', '%%')
|
34
|
+
condition = if key.blank?
|
35
|
+
sanitize_sql_for_conditions(["users_#{uniq_suffix}.login #{operator} ? or users_#{uniq_suffix}.firstname #{operator} ? ", value, value])
|
36
|
+
elsif key =~ /\.id\Z/
|
37
|
+
value = User.current.id if value == 'current_user'
|
38
|
+
sanitize_sql_for_conditions(["foreman_tasks_tasks.user_id #{operator} ?", value])
|
39
|
+
else
|
40
|
+
placeholder, value = operator == 'IN' ? ['(?)', value.split(',').map(&:strip)] : ['?', value]
|
41
|
+
sanitize_sql_for_conditions(["users_#{uniq_suffix}.#{key_name} #{operator} #{placeholder}", value])
|
42
|
+
end
|
43
|
+
{ :conditions => condition, :joins => joins_for_user_search(key, uniq_suffix) }
|
44
|
+
end
|
45
|
+
|
46
|
+
def joins_for_user_search(key, uniq_suffix)
|
47
|
+
return '' if key =~ /\.id\Z/
|
48
|
+
"INNER JOIN users AS users_#{uniq_suffix} ON users_#{uniq_suffix}.id = foreman_tasks_tasks.user_id"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -1,7 +1,15 @@
|
|
1
1
|
<% stylesheet 'foreman_tasks/tasks' %>
|
2
2
|
|
3
3
|
<%= breadcrumbs(
|
4
|
-
items:
|
4
|
+
items: [
|
5
|
+
{
|
6
|
+
caption: _('Tasks'),
|
7
|
+
url: url_for(foreman_tasks_tasks_path)
|
8
|
+
},
|
9
|
+
{
|
10
|
+
caption: format_task_input(@task)
|
11
|
+
}
|
12
|
+
],
|
5
13
|
name_field: 'action',
|
6
14
|
resource_url: foreman_tasks_api_tasks_path,
|
7
15
|
switcher_item_url: foreman_tasks_task_path(:id => ':id')
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class AddUserId < ActiveRecord::Migration[5.0]
|
2
|
+
def up
|
3
|
+
add_reference :foreman_tasks_tasks, :user, :foreign_key => true
|
4
|
+
|
5
|
+
return if User.unscoped.find_by(:login => User::ANONYMOUS_ADMIN).nil?
|
6
|
+
User.as_anonymous_admin do
|
7
|
+
user_locks.select(:resource_id).distinct.pluck(:resource_id).each do |owner_id|
|
8
|
+
tasks = ForemanTasks::Task.joins(:locks).where(:locks => user_locks.where(:resource_id => owner_id))
|
9
|
+
tasks.update_all(:user_id => owner_id)
|
10
|
+
user_locks.where(:resource_id => owner_id).delete_all
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def down
|
16
|
+
User.as_anonymous_admin do
|
17
|
+
ForemanTasks::Task.select(:user_id).distinct.pluck(:user_id).compact.each do |user_id|
|
18
|
+
ForemanTasks::Task.where(:user_id => user_id).select(:id).find_in_batches do |group|
|
19
|
+
group.each { |task| create_lock user_id, task }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
remove_column :foreman_tasks_tasks, :user_id
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def create_lock(user_id, task)
|
30
|
+
ForemanTasks::Lock.new(:name => ForemanTasks::Lock::OWNER_LOCK_NAME,
|
31
|
+
:resource_type => User.name,
|
32
|
+
:resource_id => user_id,
|
33
|
+
:task_id => task.id,
|
34
|
+
:exclusive => false).save!
|
35
|
+
end
|
36
|
+
|
37
|
+
def user_locks
|
38
|
+
ForemanTasks::Lock.where(:name => ForemanTasks::Lock::OWNER_LOCK_NAME)
|
39
|
+
end
|
40
|
+
end
|
@@ -36,7 +36,6 @@ module ForemanTasks
|
|
36
36
|
when :planning
|
37
37
|
task = ::ForemanTasks::Task::DynflowTask.where(:external_id => execution_plan_id).first
|
38
38
|
task.update_from_dynflow(data)
|
39
|
-
Lock.owner!(::User.current, task.id) if ::User.current && ::User.current.id.present?
|
40
39
|
else
|
41
40
|
if (task = ::ForemanTasks::Task::DynflowTask.where(:external_id => execution_plan_id).first)
|
42
41
|
unless task.state.to_s == data[:state].to_s
|
@@ -244,7 +244,6 @@ namespace :foreman_tasks do
|
|
244
244
|
|
245
245
|
tasks = ForemanTasks::Task.search_for(filter)
|
246
246
|
|
247
|
-
puts _("Exporting all tasks matching filter #{filter}")
|
248
247
|
puts _("Gathering #{tasks.count} tasks.")
|
249
248
|
if format == 'html'
|
250
249
|
Dir.mktmpdir('task-export') do |tmp_dir|
|
@@ -256,6 +255,7 @@ namespace :foreman_tasks do
|
|
256
255
|
tasks.each_with_index do |task, count|
|
257
256
|
File.open(File.join(tmp_dir, "#{task.id}.html"), 'w') { |file| file.write(PageHelper.pagify(renderer.render_task(task))) }
|
258
257
|
puts "#{count + 1}/#{total}"
|
258
|
+
count += 1
|
259
259
|
end
|
260
260
|
|
261
261
|
File.open(File.join(tmp_dir, 'index.html'), 'w') { |file| file.write(PageHelper.pagify(PageHelper.generate_index(tasks))) }
|
@@ -41,41 +41,6 @@ module ForemanTasks
|
|
41
41
|
response = JSON.parse(@response.body)
|
42
42
|
assert_equal 0, response['stopped']['total']
|
43
43
|
end
|
44
|
-
|
45
|
-
describe 'taxonomy scoping' do
|
46
|
-
before do
|
47
|
-
@organizations = [0, 0].map { FactoryBot.create(:organization) }
|
48
|
-
@locations = [0, 0].map { FactoryBot.create(:location) }
|
49
|
-
@tasks = [0, 0].map { FactoryBot.create(:some_task) }
|
50
|
-
@tasks.zip(@organizations, @locations).each do |task, org, loc|
|
51
|
-
Lock.link!(org, task.id)
|
52
|
-
Lock.link!(loc, task.id)
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
it 'does not limit if unset' do
|
57
|
-
get(:summary, params: { recent_timeframe: 24 }, session: set_session_user)
|
58
|
-
assert_response :success
|
59
|
-
response = JSON.parse(@response.body)
|
60
|
-
assert_equal 2, response['stopped']['total']
|
61
|
-
end
|
62
|
-
|
63
|
-
it 'finds only tasks with matching taxonomies' do
|
64
|
-
get(:summary, params: { recent_timeframe: 24 },
|
65
|
-
session: set_session_user.merge(:organization_id => @organizations.first, :location_id => @locations.first))
|
66
|
-
assert_response :success
|
67
|
-
response = JSON.parse(@response.body)
|
68
|
-
assert_equal 1, response['stopped']['total']
|
69
|
-
end
|
70
|
-
|
71
|
-
it 'find no tasks when taxonomy combination contains no tasks' do
|
72
|
-
get(:summary, params: { recent_timeframe: 24 },
|
73
|
-
session: set_session_user.merge(:organization_id => @organizations.first, :location_id => @locations.last))
|
74
|
-
assert_response :success
|
75
|
-
response = JSON.parse(@response.body)
|
76
|
-
assert_equal 0, response['stopped']['total']
|
77
|
-
end
|
78
|
-
end
|
79
44
|
end
|
80
45
|
|
81
46
|
it 'supports csv export' do
|
@@ -102,17 +67,6 @@ module ForemanTasks
|
|
102
67
|
session: set_session_user(User.current)
|
103
68
|
assert_response :not_found
|
104
69
|
end
|
105
|
-
|
106
|
-
it 'supports csv export' do
|
107
|
-
parent = FactoryBot.create(:some_task, :action => 'Some action')
|
108
|
-
child = FactoryBot.create(:some_task, :action => 'Child action')
|
109
|
-
child.parent_task_id = parent.id
|
110
|
-
child.save!
|
111
|
-
get(:sub_tasks, params: { id: parent.id, format: :csv }, session: set_session_user)
|
112
|
-
assert_response :success
|
113
|
-
assert_equal 2, response.body.lines.size
|
114
|
-
assert_include response.body.lines[1], 'Child action'
|
115
|
-
end
|
116
70
|
end
|
117
71
|
|
118
72
|
describe 'taxonomy scoping' do
|