-
Notifications
You must be signed in to change notification settings - Fork 433
/
request_controller.rb
254 lines (204 loc) · 7.04 KB
/
request_controller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
require 'base64'
require_dependency 'event/all'
include MaintenanceHelper
class RequestController < ApplicationController
validate_action show: { method: :get, response: :request }
validate_action request_create: { method: :post, response: :request }
# TODO: allow PUT for non-admins
before_action :require_admin, only: [:update, :destroy]
# GET /request
def index
# Do not allow a full collection to avoid server load
return render_request_collection if params[:view] == 'collection'
# directory list of all requests. not very useful but for backward compatibility...
# OBS3: make this more useful
@request_list = BsRequest.order(:number).pluck(:number)
end
class RequireFilter < APIException
setup 404, 'This call requires at least one filter, either by user, project or package or states or types or reviewstates'
end
def render_request_collection
# if all params areblank, something is wrong
raise RequireFilter.new if [:project, :user, :states, :types, :reviewstates, :ids].all? { |f| params[f].blank? }
# convert comma seperated values into arrays
params[:roles] = params[:roles].split(',') if params[:roles]
params[:types] = params[:types].split(',') if params[:types]
params[:states] = params[:states].split(',') if params[:states]
params[:review_states] = params[:reviewstates].split(',') if params[:reviewstates]
params[:ids] = params[:ids].split(',').map { |i| i.to_i } if params[:ids]
rel = BsRequest.collection(params).includes([:reviews]).
includes({bs_request_actions: :bs_request_action_accept_info}).
order('bs_requests.id').references(:bs_requests)
rel = rel.limit(params[:limit].to_i) if params[:limit].to_i > 0
xml = ActiveXML::Node.new '<collection/>'
matches=0
rel.each do |r|
matches = matches+1
xml.add_node(r.render_xml(params))
end
xml.set_attribute('matches', matches.to_s)
render xml: xml.dump_xml
end
# GET /request/:id
def show
required_parameters :id
req = BsRequest.find_by_number!(params[:id])
render xml: req.render_xml(params)
end
# POST /request?cmd=create
def global_command
unless %w(create).include? params[:cmd]
raise UnknownCommandError.new "Unknown command '#{params[opt[:cmd_param]]}' for path #{request.path}"
end
# refuse request creation for anonymous users
be_not_nobody!
# no need for dispatch_command, there is only one command
request_create
end
# POST /request/:id?cmd=$CMD
def request_command
return request_command_diff if params[:cmd] == 'diff'
# refuse request manipulation for anonymous users
be_not_nobody!
params[:user] = User.current.login
@req = BsRequest.find_by_number!(params[:id])
# transform request body into query parameter 'comment'
# the query parameter is preferred if both are set
params[:comment] = request.raw_post if params[:comment].blank?
# might raise an exception (which then renders an error)
# FIXME: this should be moved into the model functions, doing
# these actions
case params[:cmd]
when 'create', 'changestate', 'addreview', 'setpriority', 'setincident', 'setacceptat'
# create -> noop
# permissions are checked by the model
when 'changereviewstate', 'assignreview'
@req.permission_check_change_review!(params)
when 'addrequest', 'removerequest'
# FIXME3.0: to be dropped
@req.permission_check_change_groups!
else
raise UnknownCommandError.new "Unknown command '#{params[:cmd]}' for path #{request.path}"
end
# permission granted for the request at this point
# special command defining an incident to be merged
params[:check_for_patchinfo] = false
dispatch_command(:request_command, params[:cmd])
end
# PUT /request/:id
def update
body = request.raw_post
Suse::Validator.validate(:request, body)
BsRequest.transaction do
oldrequest = BsRequest.find_by_number!(params[:id])
notify = oldrequest.notify_parameters
oldrequest.destroy
req = BsRequest.new_from_xml(body)
req.number = params[:id]
req.skip_sanitize
req.save!
notify[:who] = User.current.login
Event::RequestChange.create notify
render xml: req.render_xml
end
end
# DELETE /request/:id
def destroy
request = BsRequest.find_by_number!(params[:id])
notify = request.notify_parameters
request.destroy # throws us out of here if failing
notify[:who] = User.current.login
Event::RequestDelete.create notify
render_ok
end
private
# POST /request?cmd=create
def request_create
xml = nil
BsRequest.transaction do
@req = BsRequest.new_from_xml(request.raw_post.to_s)
@req.set_add_revision unless params[:addrevision].blank?
@req.set_ignore_build_state unless params[:ignore_build_state].blank?
@req.save!
xml = @req.render_xml
Suse::Validator.validate(:request, xml)
end
# cache the diff (in the backend)
@req.bs_request_actions.each do |a|
a.delay.webui_infos
end
render xml: xml
end
def request_command_diff
req = BsRequest.find_by_number!(params[:id])
diff_text = ''
xml_request = if params[:view] == 'xml'
ActiveXML::Node.new("<request id='#{req.number}'/>")
end
req.bs_request_actions.each do |action|
withissues = ["1", "true"].include?(params[:withissues].to_s)
action_diff = action.sourcediff(view: params[:view], withissues: withissues)
if xml_request
# Inject backend-provided XML diff into action XML:
builder = Nokogiri::XML::Builder.new
action.render_xml(builder)
a = xml_request.add_node(builder.to_xml)
a.add_node(action_diff)
else
diff_text += action_diff
end
end
if xml_request
xml_request.set_attribute('actions', "0")
render xml: xml_request.dump_xml
else
render plain: diff_text
end
end
class PostRequestMissingParamater < APIException
setup 403
end
class GroupRequestSpecial < APIException
setup 'command_only_valid_for_group'
end
def request_command_addrequest
@req.bs_request_actions.first.addrequest(params)
render_ok
end
def request_command_removerequest
@req.bs_request_actions.first.removerequest(params)
render_ok
end
def request_command_setincident
@req.setincident(params[:incident])
render_ok
end
def request_command_setacceptat
time = DateTime.parse(params[:time]) unless params[:time].blank?
@req.set_accept_at!(time)
render_ok
end
def request_command_addreview
@req.addreview(params)
render_ok
end
def request_command_setpriority
@req.setpriority(params)
render_ok
end
def request_command_assignreview
@req.assignreview(params)
render_ok
end
def request_command_changereviewstate
@req.change_review_state(params[:newstate], params)
render_ok
end
class MultipleMaintenanceIncidents < APIException
setup 404
end
def request_command_changestate
@req.change_state(params)
render_ok
end
end