/
CreateChannelCommand.java
441 lines (371 loc) · 14.1 KB
/
CreateChannelCommand.java
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
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
/**
* Copyright (c) 2009--2010 Red Hat, Inc.
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package com.redhat.rhn.manager.channel;
import com.redhat.rhn.domain.channel.Channel;
import com.redhat.rhn.domain.channel.ChannelArch;
import com.redhat.rhn.domain.channel.ChannelFactory;
import com.redhat.rhn.domain.common.ChecksumType;
import com.redhat.rhn.domain.role.RoleFactory;
import com.redhat.rhn.domain.user.User;
import com.redhat.rhn.frontend.xmlrpc.InvalidChannelLabelException;
import com.redhat.rhn.frontend.xmlrpc.InvalidChannelNameException;
import com.redhat.rhn.frontend.xmlrpc.InvalidGPGKeyException;
import com.redhat.rhn.frontend.xmlrpc.InvalidGPGUrlException;
import com.redhat.rhn.frontend.xmlrpc.InvalidParentChannelException;
import org.apache.commons.lang.StringUtils;
import java.util.regex.Pattern;
/**
* CreateChannelCommand - command to create a new channel.
* @version $Rev$
*/
public class CreateChannelCommand {
public static final int CHANNEL_NAME_MIN_LENGTH = 6;
public static final int CHANNEL_NAME_MAX_LENGTH = 64;
public static final int CHANNEL_LABEL_MIN_LENGTH = 6;
protected static final String CHANNEL_NAME_REGEX =
"^[a-zA-Z][\\w\\d\\s\\-\\.\\'\\(\\)\\/\\_]*$";
protected static final String CHANNEL_LABEL_REGEX =
"^[a-z\\d][a-z\\d\\-\\.\\_]*$";
// we ignore case with the red hat regex
protected static final String REDHAT_REGEX = "^(rhn|red\\s*hat)";
protected static final String GPG_KEY_REGEX = "^[0-9A-F]{8}$";
protected static final String GPG_URL_REGEX = "^(https?|file)://.*?$";
protected static final String GPG_FP_REGEX = "^(\\s*[0-9A-F]{4}\\s*){10}$";
protected static final String WEB_CHANNEL_CREATED = "web.channel_created";
protected User user;
protected String label;
protected String name;
protected String summary;
protected String description;
protected String archLabel;
protected String parentLabel;
protected Long parentId;
protected String gpgKeyUrl;
protected String gpgKeyId;
protected String gpgKeyFp;
protected String checksum;
protected String maintainerName;
protected String maintainerEmail;
protected String maintainerPhone;
protected String supportPolicy;
protected String access = Channel.PRIVATE;
/**
* default constructor.
*/
public CreateChannelCommand() {
user = null;
label = null;
name = null;
summary = null;
archLabel = null;
checksum = null;
parentLabel = null;
parentId = null;
}
/**
* @param archLabelIn The archLabel to set.
*/
public void setArchLabel(String archLabelIn) {
archLabel = archLabelIn;
}
/**
* @param labelIn The label to set.
*/
public void setLabel(String labelIn) {
label = labelIn;
}
/**
* @param nameIn The name to set.
*/
public void setName(String nameIn) {
name = nameIn;
}
/**
* @param checksumIn The name to set.
*/
public void setChecksum(String checksumIn) {
this.checksum = checksumIn;
}
/**
* @param parentLabelIn The parentLabel to set.
*/
public void setParentLabel(String parentLabelIn) {
parentLabel = parentLabelIn;
}
/**
* @param pid The parent id to set.
*/
public void setParentId(Long pid) {
parentId = pid;
}
/**
* @param fp gpgkey fingerprint
*/
public void setGpgKeyFp(String fp) {
gpgKeyFp = fp;
}
/**
* @param id gpgkey id
*/
public void setGpgKeyId(String id) {
gpgKeyId = id;
}
/**
* @param url gpgkey url
*/
public void setGpgKeyUrl(String url) {
gpgKeyUrl = url;
}
/**
* @param email maintainer's email address
*/
public void setMaintainerEmail(String email) {
maintainerEmail = email;
}
/**
* @param mname maintainers name
*/
public void setMaintainerName(String mname) {
maintainerName = mname;
}
/**
* @param phone maintainer's phone number (string)
*/
public void setMaintainerPhone(String phone) {
maintainerPhone = phone;
}
/**
* @param policy support policy
*/
public void setSupportPolicy(String policy) {
supportPolicy = policy;
}
/**
* @param summaryIn The summary to set.
*/
public void setSummary(String summaryIn) {
summary = summaryIn;
}
/**
* @param desc The description.
*/
public void setDescription(String desc) {
description = desc;
}
/**
* @param userIn The user to set.
*/
public void setUser(User userIn) {
user = userIn;
}
/**
* @param acc public, protected, or private
*/
public void setAccess(String acc) {
if (acc == null || acc.equals("")) {
access = Channel.PRIVATE;
}
else {
access = acc;
}
}
/**
* Creates the Channel based on the parameters that were set.
* @return the newly created Channel
* @throws InvalidChannelLabelException thrown if label is in use or invalid.
* @throws InvalidChannelNameException throw if name is in use or invalid.
* @throws IllegalArgumentException thrown if label, name or user are null.
* @throws InvalidParentChannelException thrown if parent label is not a
* valid base channel.
*/
public Channel create()
throws InvalidChannelLabelException, InvalidChannelNameException,
InvalidParentChannelException {
verifyRequiredParameters();
verifyChannelName(name);
verifyChannelLabel(label);
verifyGpgInformation();
if (ChannelFactory.doesChannelNameExist(name)) {
throw new InvalidChannelNameException(name,
InvalidChannelNameException.Reason.NAME_IN_USE,
"edit.channel.invalidchannelname.nameinuse", name);
}
if (ChannelFactory.doesChannelLabelExist(label)) {
throw new InvalidChannelLabelException(label,
InvalidChannelLabelException.Reason.LABEL_IN_USE,
"edit.channel.invalidchannellabel.labelinuse", label);
}
ChannelArch ca = ChannelFactory.findArchByLabel(archLabel);
if (ca == null) {
throw new IllegalArgumentException("Invalid architecture label");
}
ChecksumType ct = ChannelFactory.findChecksumTypeByLabel(checksum);
Channel c = ChannelFactory.createChannel();
c.setLabel(label);
c.setName(name);
c.setSummary(summary);
c.setDescription(description);
c.setOrg(user.getOrg());
c.setBaseDir("/dev/null");
c.setChannelArch(ca);
c.setChecksumType(ct);
c.setGPGKeyId(gpgKeyId);
c.setGPGKeyUrl(gpgKeyUrl);
c.setGPGKeyFp(gpgKeyFp);
c.setAccess(access);
c.setMaintainerName(maintainerName);
c.setMaintainerEmail(maintainerEmail);
c.setMaintainerPhone(maintainerPhone);
c.setSupportPolicy(supportPolicy);
// handles either parent id or label
setParentChannel(c, user, parentLabel, parentId);
c.addChannelFamily(user.getOrg().getPrivateChannelFamily());
// need to save before calling stored proc below
ChannelFactory.save(c);
ChannelManager.queueChannelChange(c.getLabel(), "createchannel", "createchannel");
ChannelFactory.refreshNewestPackageCache(c, WEB_CHANNEL_CREATED);
return c;
}
/**
* sets the parent channel of the given affected channel if pLabel or pid
* is given. pLabel is preferred if both are given. If both pLabel and
* pid are null or if no channel is found for the given label or pid, the
* affected channel is unchanged.
* @param affected The Channel to receive a new parent, if one is found.
* @param usr The usr
* @param lbl The parent Channel label, can be null.
* @param pid The parent Channel id, can be null.
*/
protected void setParentChannel(Channel affected, User usr,
String lbl, Long pid) {
Channel parent = null;
if ((lbl == null || lbl.equals("")) &&
pid == null) {
// these are not the droids you seek
return;
}
if (lbl != null && !lbl.equals("")) {
parent = ChannelManager.lookupByLabelAndUser(lbl, usr);
}
else if (pid != null) {
parent = ChannelManager.lookupByIdAndUser(pid, usr);
}
if (parent == null) {
throw new IllegalArgumentException("Invalid Parent Channel lbl");
}
if (!parent.isBaseChannel()) {
throw new InvalidParentChannelException();
}
// man that's a lot of conditionals :) finally we do what
// we came here to do.
affected.setParentChannel(parent);
}
/**
* Verifies that the required parameters are not null.
* @throws IllegalArgumentException thrown if label, name, user or summary
* are null.
*/
protected void verifyRequiredParameters() {
if (user == null || StringUtils.isEmpty(summary)) {
throw new IllegalArgumentException(
"edit.channel.invalidchannelsummary");
}
}
protected void verifyChannelName(String cname) throws InvalidChannelNameException {
if (user == null) {
// can never be too careful
throw new IllegalArgumentException("Required param [user] is null");
}
if (cname == null || cname.trim().length() == 0) {
throw new InvalidChannelNameException(cname,
InvalidChannelNameException.Reason.IS_MISSING,
"edit.channel.invalidchannelname.missing", "");
}
if (!Pattern.compile(CHANNEL_NAME_REGEX).matcher(cname).find()) {
throw new InvalidChannelNameException(cname,
InvalidChannelNameException.Reason.REGEX_FAILS,
"edit.channel.invalidchannelname.supportedregex", "");
}
if (cname.length() < CHANNEL_NAME_MIN_LENGTH) {
Integer minLength = new Integer(CreateChannelCommand.CHANNEL_NAME_MIN_LENGTH);
throw new InvalidChannelNameException(cname,
InvalidChannelNameException.Reason.TOO_SHORT,
"edit.channel.invalidchannelname.minlength",
minLength.toString());
}
if (cname.length() > CHANNEL_NAME_MAX_LENGTH) {
Integer maxLength = new Integer(CreateChannelCommand.CHANNEL_NAME_MAX_LENGTH);
throw new InvalidChannelNameException(cname,
InvalidChannelNameException.Reason.TOO_LONG,
"edit.channel.invalidchannelname.maxlength",
maxLength.toString());
}
// the perl code used to ignore case with a /i at the end of
// the regex, so we toLowerCase() the channel name to make it
// work the same.
if (!user.hasRole(RoleFactory.RHN_SUPERUSER) &&
Pattern.compile(REDHAT_REGEX).matcher(cname.toLowerCase()).find()) {
throw new InvalidChannelNameException(cname,
InvalidChannelNameException.Reason.RHN_CHANNEL_BAD_PERMISSIONS,
"edit.channel.invalidchannelname.redhat", "");
}
}
protected void verifyChannelLabel(String clabel) throws InvalidChannelLabelException {
if (user == null) {
// can never be too careful
throw new IllegalArgumentException("Required param is null");
}
if (clabel == null || clabel.trim().length() == 0) {
throw new InvalidChannelLabelException(clabel,
InvalidChannelLabelException.Reason.IS_MISSING,
"edit.channel.invalidchannellabel.missing", "");
}
if (!Pattern.compile(CHANNEL_LABEL_REGEX).matcher(clabel).find()) {
throw new InvalidChannelLabelException(clabel,
InvalidChannelLabelException.Reason.REGEX_FAILS,
"edit.channel.invalidchannellabel.supportedregex", "");
}
if (clabel.length() < CHANNEL_LABEL_MIN_LENGTH) {
Integer minLength = new Integer(CreateChannelCommand.CHANNEL_LABEL_MIN_LENGTH);
throw new InvalidChannelLabelException(clabel,
InvalidChannelLabelException.Reason.TOO_SHORT,
"edit.channel.invalidchannellabel.minlength",
minLength.toString());
}
// the perl code used to ignore case with a /i at the end of
// the regex, so we toLowerCase() the channel name to make it
// work the same.
if (!user.hasRole(RoleFactory.RHN_SUPERUSER) &&
Pattern.compile(REDHAT_REGEX).matcher(clabel.toLowerCase()).find()) {
throw new InvalidChannelLabelException(clabel,
InvalidChannelLabelException.Reason.RHN_CHANNEL_BAD_PERMISSIONS,
"edit.channel.invalidchannellabel.redhat", "");
}
}
protected void verifyGpgInformation() {
if (gpgKeyId != null && !gpgKeyId.equals("") &&
!Pattern.compile(GPG_KEY_REGEX).matcher(gpgKeyId).find()) {
throw new InvalidGPGKeyException();
}
if (gpgKeyFp != null && !gpgKeyFp.equals("") &&
!Pattern.compile(GPG_FP_REGEX).matcher(gpgKeyFp).find()) {
throw new InvalidGPGFingerprintException();
}
if (gpgKeyUrl != null && !gpgKeyUrl.equals("") &&
!Pattern.compile(GPG_URL_REGEX).matcher(gpgKeyUrl).find()) {
throw new InvalidGPGUrlException();
}
}
}