This repository has been archived by the owner on Jun 3, 2020. It is now read-only.
/
CreateUserCommand.java
438 lines (389 loc) · 14.4 KB
/
CreateUserCommand.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
/**
* Copyright (c) 2009--2014 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.user;
import com.redhat.rhn.common.conf.UserDefaults;
import com.redhat.rhn.common.hibernate.LookupException;
import com.redhat.rhn.common.localization.LocalizationService;
import com.redhat.rhn.common.messaging.MessageQueue;
import com.redhat.rhn.common.validator.ParsedConstraint;
import com.redhat.rhn.common.validator.ValidatorError;
import com.redhat.rhn.domain.org.Org;
import com.redhat.rhn.domain.role.Role;
import com.redhat.rhn.domain.role.RoleFactory;
import com.redhat.rhn.domain.server.ManagedServerGroup;
import com.redhat.rhn.domain.server.ServerGroup;
import com.redhat.rhn.domain.server.ServerGroupFactory;
import com.redhat.rhn.domain.user.Address;
import com.redhat.rhn.domain.user.User;
import com.redhat.rhn.domain.user.UserFactory;
import com.redhat.rhn.frontend.events.NewUserEvent;
import org.apache.commons.lang.StringUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.SortedSet;
import java.util.regex.Pattern;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
/**
* A command to create or edit users
* @version $Rev$
*/
public class CreateUserCommand {
private User user;
private Org org;
private Address addr;
private boolean makeOrgAdmin;
private boolean makeSatAdmin;
private Set<Role> temporaryRoles = new HashSet<Role>();
private Set<ServerGroup> serverGroups = new HashSet<ServerGroup>();
private List<ValidatorError> errors;
private List<ValidatorError> passwordErrors;
/*
* Why we need passwordErrors.
* The setPassword method on UserImpl encrypts passwords (If configured to do so).
* If we don't validate the password before we set it, we will only ever be able
* to get to the encrypted password back which will always be valid.
*/
/**
* Constructor... creates an empty user object
*/
public CreateUserCommand() {
user = UserFactory.createUser();
}
/**
* Validates the user object. Checks login and email attributes.
* @return an Object array of ValidatorErrors.
*/
public ValidatorError[] validate() {
errors = new ArrayList(); //clear validation errors
if (passwordErrors != null) {
errors.addAll(passwordErrors); //add any password validation errors
}
validateEmail();
validateLogin();
validatePrefix();
return errors.toArray(new ValidatorError[0]);
}
/**
* Publishes a new user event to the message queue
* @param accountCreator The person whom created the user
* @param admins Org admins
* @param domain The servername for this server (used to build url).
* @param password The user's password. It must be explicitly passed in
* seperate from the user because the password associated with the User object
* might be encrypted, thus useless for this method
*/
public void publishNewUserEvent(User accountCreator,
List admins,
String domain,
String password) {
NewUserEvent userevt = new NewUserEvent();
userevt.setAccountCreator(accountCreator);
userevt.setAdmins(admins);
userevt.setPassword(password);
userevt.setDomain(domain);
userevt.setUser(this.user);
MessageQueue.publish(userevt);
}
/**
* Saves the new user object (along with the Org and Address).
*/
public void storeNewUser() {
/*
* Ok, this is a bloody ugly hack, but since the pl/sql used by
* UserFactory.saveNewUser() is shared and the use pam authentication seems to be
* the only thing affected by it, we are going to work around it here.
*
* The Create_New_User function in the db creates an entry in rhnUserInfo with the
* default values. This means that anything stored in User.personalInfo gets
* reset. We need to be able to update the use_pam_authentication column in this
* table, so save the value, save the user, then set the attribute back to what it
* was before we called UserManager.createUser(). This will ensure that what was
* selected on the form is what gets stored with the user (since hibernate will
* then be taking care of the db values).
*
* We really need to a) divorce ourselves from www and oracle apps b) get rid of the
* application/business logic stored in pl/sql functions in the db and c) clean up
* the dirty hacks like this that are throughout our code. We shouldn't have to work
* around the db in our code.
*/
boolean usePam = user.getUsePamAuthentication(); //save what we got from the form
user = UserManager.createUser(user, org, addr);
if (this.makeOrgAdmin) {
user.addPermanentRole(RoleFactory.ORG_ADMIN);
}
if (this.makeSatAdmin) {
user.addPermanentRole(RoleFactory.SAT_ADMIN);
}
user.setUsePamAuthentication(usePam); //set it back
UserManager.resetTemporaryRoles(user, temporaryRoles);
if (org.getOrgConfig().isCreateDefaultSg()) {
ManagedServerGroup sg = ServerGroupFactory.lookupByNameAndOrg(
user.getLogin(), user.getOrg());
if (sg == null) {
// create default system group for the user
sg = ServerGroupFactory.create(user.getLogin(),
user.getLogin() + " default system group", user.getOrg());
}
UserManager.grantServerGroupPermission(user, sg.getId());
user.setDefaultSystemGroupIds(new HashSet<Long>(Arrays.asList(sg.getId())));
}
// assign server groups permissions
for (ServerGroup sg : serverGroups) {
UserManager.grantServerGroupPermission(user, sg.getId());
}
UserManager.storeUser(user); //save the user via hibernate
}
/**
* Private helper method to validate the user's email address. Puts errors into the
* errors list.
*/
private void validateEmail() {
// Make sure user and email are not null
if (user == null || user.getEmail() == null) {
errors.add(new ValidatorError("error.addr_invalid", "null"));
return;
}
// Make email is not over the max length
if (user.getEmail().length() > UserDefaults.get().getMaxEmailLength()) {
errors.add(new ValidatorError("error.maxemail"));
return;
}
// Make sure set email is valid
try {
new InternetAddress(user.getEmail()).validate();
}
catch (AddressException e) {
errors.add(new ValidatorError("error.addr_invalid", user.getEmail()));
}
}
/**
* Private helper method to validate the user's login. Puts errors into the errors List.
*/
private void validateLogin() {
int max = UserDefaults.get().getMaxUserLength();
if (user == null) {
errors.add(new ValidatorError("error.minlogin", "null"));
return;
}
String login = StringUtils.defaultString(user.getLogin());
/*
* Check for login minimum length
* Since login.getBytes().length >= login.length(), just check for min length
*/
if (login.length() < UserDefaults.get().getMinUserLength()) {
errors.add(new ValidatorError("error.minlogin",
UserDefaults.get().getMinUserLength()));
return;
}
/*
* Check for login maximum length
* Since we are allowing utf8 input, but not supporting it in the db, we need to
* check the length of the bytes here as well.
* TODO: Do better error checking here once the db and code is fully localized and
* we are supporting it on logins
*/
else if (login.length() > max || login.getBytes().length > max) {
errors.add(new ValidatorError("error.maxlogin", login));
return;
}
// validate using the webui code. I must say that RequiredConstraint
// is a stupid place for hiding username validation. But nevertheless
// I will continue to propogate this crap until we want to revisit
// validation.
ParsedConstraint rc = new ParsedConstraint("CreateUserCommand");
if (!rc.isValidUserName(login)) {
errors.add(new ValidatorError("errors.username", login));
return;
}
// Make sure desiredLogin isn't taken already
try {
UserFactory.lookupByLogin(login);
errors.add(new ValidatorError("error.login_already_taken", login));
}
catch (LookupException le) {
// User is not taken
// so we can coolly add him.
}
}
/**
* Private helper method to validate the user's prefix. Puts errors into the
* errors list.
*/
private void validatePrefix() {
String prefix = user.getPrefix();
if (prefix != null) {
// Make sure whether prefix is valid, if it is set
SortedSet validPrefixes = LocalizationService.getInstance().availablePrefixes();
if (prefix.isEmpty()) {
user.setPrefix(" ");
}
if (!validPrefixes.contains(user.getPrefix())) {
errors.add(new ValidatorError("error.user_invalid_prefix",
prefix, validPrefixes.toString()));
}
}
}
/**
* Private helper method to validate the password. This happens when the setPassword
* method of this class is called. Puts errors into the passwordErrors list.
* @param passwordIn The password to check.
*/
private void validatePassword(String passwordIn) {
if (passwordIn == null || passwordIn.length() <
UserDefaults.get().getMinPasswordLength()) {
passwordErrors.add(new ValidatorError("error.minpassword",
UserDefaults.get().getMinPasswordLength()));
}
// Newlines and tab characters can slip through the API much easier than the UI:
if (Pattern.compile("[\\t\\n]").matcher(passwordIn).find()) {
passwordErrors.add(new ValidatorError("error.invalidpasswordcharacters"));
}
else if (passwordIn.length() > UserDefaults.get().getMaxPasswordLength()) {
passwordErrors.add(new ValidatorError("error.maxpassword",
user.getPassword()));
}
}
/***** User accessors *****/
/**
* @param companyIn The company sent
*/
public void setCompany(String companyIn) {
user.setCompany(companyIn);
}
/**
* @param emailIn The email to set
*/
public void setEmail(String emailIn) {
user.setEmail(emailIn);
}
/**
* @param loginIn The login to set
*/
public void setLogin(String loginIn) {
user.setLogin(loginIn);
}
/**
* @param passwordIn The raw password to set
*/
public void setRawPassword(String passwordIn) {
passwordErrors = new ArrayList(); //init password errors list
user.setRawPassword(passwordIn);
}
/**
* @param passwordIn The password to set
*/
public void setPassword(String passwordIn) {
passwordErrors = new ArrayList(); //init password errors list
validatePassword(passwordIn);
user.setPassword(passwordIn);
}
/**
* @param prefixIn The prefix to set
*/
public void setPrefix(String prefixIn) {
user.setPrefix(prefixIn);
}
/**
* @param firstNamesIn The first names to set
*/
public void setFirstNames(String firstNamesIn) {
user.setFirstNames(firstNamesIn);
}
/**
* @param lastNameIn The last name to set
*/
public void setLastName(String lastNameIn) {
user.setLastName(lastNameIn);
}
/**
* @param phoneIn The phone to set
*/
public void setPhone(String phoneIn) {
user.setPhone(phoneIn);
}
/**
* @param faxIn The fax to set
*/
public void setFax(String faxIn) {
user.setFax(faxIn);
}
/**
* @param val Should this user use pam authentication?
*/
public void setUsePamAuthentication(boolean val) {
user.setUsePamAuthentication(val);
}
/**
* Setter for the org object.
* @param orgIn the org to set
*/
public void setOrg(Org orgIn) {
this.org = orgIn;
}
/**
* Sets the Address object
* @param addrIn The address to set
*/
public void setAddress(Address addrIn) {
this.addr = addrIn;
}
/**
* @param val Should this user be an org admin?
*/
public void setMakeOrgAdmin(boolean val) {
this.makeOrgAdmin = val;
}
/**
* @return The user object
*/
public User getUser() {
return this.user;
}
/**
*
* @param val Should this user be a sat admin?
*/
public void setMakeSatAdmin(boolean val) {
this.makeSatAdmin = val;
}
/**
* @return Returns the roles.
*/
public Set<Role> getTemporaryRoles() {
return temporaryRoles;
}
/**
* @param rolesIn The roles to set.
*/
public void setTemporaryRoles(Set<Role> rolesIn) {
temporaryRoles = rolesIn;
}
/**
* @return Returns the Server Groups.
*/
public Set<ServerGroup> getServerGroups() {
return serverGroups;
}
/**
* @param sgsIn The Server Groups to set.
*/
public void setServerGroups(Set<ServerGroup> sgsIn) {
serverGroups = sgsIn;
}
}