source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/Authentication.java@ 25635

Last change on this file since 25635 was 25635, checked in by sjm84, 12 years ago

Fixing Greenstone 3's use (or lack thereof) of generics, this was done automatically so we may want to change it over time. This change will also auto-format any files that have not already been formatted.

File size: 30.5 KB
RevLine 
[14295]1package org.greenstone.gsdl3.service;
2
3import org.greenstone.gsdl3.util.GSXML;
4import org.greenstone.gsdl3.util.DerbyWrapper;
5import org.greenstone.gsdl3.util.UserQueryResult;
6import org.greenstone.gsdl3.util.UserTermInfo;
7
8import org.w3c.dom.Element;
[25311]9import org.w3c.dom.NodeList;
[14295]10
[25318]11import java.math.BigInteger;
[25258]12import java.util.ArrayList;
[25124]13import java.util.HashMap;
[25258]14import java.util.UUID;
[14295]15import java.util.Vector;
[25258]16import java.security.MessageDigest;
[14295]17import java.sql.SQLException;
18import java.util.regex.Pattern;
19import java.io.File;
[25635]20import java.io.Serializable;
[14295]21
[25258]22import net.tanesha.recaptcha.ReCaptchaImpl;
23import net.tanesha.recaptcha.ReCaptchaResponse;
24
[24978]25public class Authentication extends ServiceRack
26{
[25258]27 //Error codes
28 protected static final int NO_ERROR = 0;
29 protected static final int ERROR_REQUEST_HAS_NO_PARAM_LIST = -1;
30 protected static final int ERROR_NOT_LOGGED_IN = -2;
31 protected static final int ERROR_ADMIN_NOT_LOGGED_IN = -3;
32 protected static final int ERROR_COULD_NOT_GET_USER_INFO = -4;
33 protected static final int ERROR_USERNAME_NOT_SPECIFIED = -5;
34 protected static final int ERROR_REQUESTED_USER_NOT_FOUND = -6;
35 protected static final int ERROR_SQL_EXCEPTION = -7;
36 protected static final int ERROR_INVALID_USERNAME = -8;
37 protected static final int ERROR_INVALID_PASSWORD = -9;
38 protected static final int ERROR_INCORRECT_PASSWORD = -10;
39 protected static final int ERROR_USER_ALREADY_EXISTS = -11;
40 protected static final int ERROR_ADDING_USER = -12;
41 protected static final int ERROR_REMOVING_USER = -13;
42 protected static final int ERROR_CAPTCHA_DOES_NOT_MATCH = -14;
43 protected static final int ERROR_CAPTCHA_MISSING = -15;
44 protected static final int ERROR_NOT_AUTHORISED = -16;
45
46 protected static final HashMap<Integer, String> _errorMessageMap;
47 static
48 {
49 //Corresponding error messages
50 HashMap<Integer, String> errorMessageMap = new HashMap<Integer, String>();
51 errorMessageMap.put(ERROR_REQUEST_HAS_NO_PARAM_LIST, "The list of parameters for this request was empty.");
52 errorMessageMap.put(ERROR_NOT_LOGGED_IN, "You must be logged in to access this page.");
53 errorMessageMap.put(ERROR_ADMIN_NOT_LOGGED_IN, "You must be logged in as an administrator to access this page.");
54 errorMessageMap.put(ERROR_COULD_NOT_GET_USER_INFO, "There was a error getting the user information.");
55 errorMessageMap.put(ERROR_USERNAME_NOT_SPECIFIED, "No username was specified.");
56 errorMessageMap.put(ERROR_REQUESTED_USER_NOT_FOUND, "The requested user was not found in the database.");
57 errorMessageMap.put(ERROR_SQL_EXCEPTION, "There was an SQL exception while accessing the database.");
58 errorMessageMap.put(ERROR_INVALID_USERNAME, "The username specified was invalid.");
59 errorMessageMap.put(ERROR_INVALID_PASSWORD, "The password specified was invalid.");
60 errorMessageMap.put(ERROR_INCORRECT_PASSWORD, "The password specified was incorrect.");
61 errorMessageMap.put(ERROR_USER_ALREADY_EXISTS, "This user already exists and therefore cannot be added.");
62 errorMessageMap.put(ERROR_ADDING_USER, "There was an error adding this user to the database.");
63 errorMessageMap.put(ERROR_REMOVING_USER, "There was an error removing this user from the database.");
64 errorMessageMap.put(ERROR_CAPTCHA_DOES_NOT_MATCH, "The words you entered did not match the image, please try again.");
65 errorMessageMap.put(ERROR_CAPTCHA_MISSING, "The information from the captcha is missing.");
66 errorMessageMap.put(ERROR_NOT_AUTHORISED, "You are not authorised to access this page.");
67
68 _errorMessageMap = errorMessageMap;
69 }
70
71 //Admin-required operations
72 protected static final String LIST_USERS = "ListUsers";
73 protected static final String PERFORM_ADD = "PerformAdd";
74 protected static final String PERFORM_EDIT = "PerformEdit";
75 protected static final String ADD_USER = "AddUser";
76 protected static final String EDIT_USER = "EditUser";
77 protected static final String PERFORM_DELETE_USER = "PerformDeleteUser";
78
79 protected static final ArrayList<String> _adminOpList;
80 static
81 {
82 ArrayList<String> opList = new ArrayList<String>();
83 opList.add(LIST_USERS);
84 opList.add(PERFORM_ADD);
85 opList.add(PERFORM_EDIT);
86 opList.add(EDIT_USER);
87 opList.add(PERFORM_DELETE_USER);
88
89 _adminOpList = opList;
90 }
91
92 //User-required operations
93 protected static final String ACCOUNT_SETTINGS = "AccountSettings";
94 protected static final String PERFORM_ACCOUNT_EDIT = "PerformAccEdit";
95 protected static final String PERFORM_RESET_PASSWORD = "PerformResetPassword";
96 protected static final ArrayList<String> _userOpList;
97 static
98 {
99 ArrayList<String> opList = new ArrayList<String>();
100 opList.add(ACCOUNT_SETTINGS);
101 opList.add(PERFORM_ACCOUNT_EDIT);
102 opList.add(PERFORM_RESET_PASSWORD);
103 opList.addAll(_adminOpList);
104 _userOpList = opList;
105 }
106
107 //Other operations
108 protected static final String REGISTER = "Register";
109 protected static final String PERFORM_REGISTER = "PerformRegister";
110 protected static final String LOGIN = "Login";
111
[17452]112 //the services on offer
[24978]113 protected static final String AUTHENTICATION_SERVICE = "Authentication";
[25124]114 protected static final String GET_USER_INFORMATION_SERVICE = "GetUserInformation";
[14295]115
[25258]116 protected DerbyWrapper _derbyWrapper = null;
117
[25311]118 protected String _recaptchaPrivateKey = null;
119 protected String _recaptchaPublicKey = null;
120
[17452]121 /** constructor */
122 public Authentication()
[24978]123 {
124 }
[14295]125
[24978]126 public boolean configure(Element info, Element extra_info)
[17452]127 {
128 logger.info("Configuring Authentication...");
129 this.config_info = info;
[14295]130
[17452]131 // set up Authentication service info - for now just has name and type
[24978]132 Element authentication_service = this.doc.createElement(GSXML.SERVICE_ELEM);
133 authentication_service.setAttribute(GSXML.TYPE_ATT, "authen");
[17452]134 authentication_service.setAttribute(GSXML.NAME_ATT, AUTHENTICATION_SERVICE);
135 this.short_service_info.appendChild(authentication_service);
[14295]136
[25124]137 // set up Authentication service info - for now just has name and type
138 Element getUserInformation_service = this.doc.createElement(GSXML.SERVICE_ELEM);
139 getUserInformation_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
140 getUserInformation_service.setAttribute(GSXML.NAME_ATT, GET_USER_INFORMATION_SERVICE);
141 this.short_service_info.appendChild(getUserInformation_service);
142
[25311]143 NodeList recaptchaElems = info.getElementsByTagName("recaptcha");
144
145 for (int i = 0; i < recaptchaElems.getLength(); i++)
146 {
147 Element currentElem = (Element) recaptchaElems.item(i);
148 if (currentElem.getAttribute(GSXML.NAME_ATT) != null && currentElem.getAttribute(GSXML.NAME_ATT).equals("public_key"))
149 {
150 if (currentElem.getAttribute(GSXML.VALUE_ATT) != null)
151 {
152 _recaptchaPublicKey = currentElem.getAttribute(GSXML.VALUE_ATT);
153 }
154 }
155 else if (currentElem.getAttribute(GSXML.NAME_ATT) != null && currentElem.getAttribute(GSXML.NAME_ATT).equals("private_key"))
156 {
157 if (currentElem.getAttribute(GSXML.VALUE_ATT) != null)
158 {
159 _recaptchaPrivateKey = currentElem.getAttribute(GSXML.VALUE_ATT);
160 }
161 }
162 }
163
[17452]164 return true;
165 }
[14295]166
[24978]167 protected Element getServiceDescription(String service_id, String lang, String subset)
[17452]168 {
169
[24978]170 Element authen_service = this.doc.createElement(GSXML.SERVICE_ELEM);
[17452]171
[24978]172 if (service_id.equals(AUTHENTICATION_SERVICE))
173 {
174 authen_service.setAttribute(GSXML.TYPE_ATT, "authen");
[17452]175 authen_service.setAttribute(GSXML.NAME_ATT, AUTHENTICATION_SERVICE);
[24978]176 }
[25124]177 else if (service_id.equals(GET_USER_INFORMATION_SERVICE))
178 {
179 authen_service.setAttribute(GSXML.TYPE_ATT, GSXML.SERVICE_TYPE_PROCESS);
180 authen_service.setAttribute(GSXML.NAME_ATT, GET_USER_INFORMATION_SERVICE);
181 }
[24978]182 else
183 {
[17452]184 return null;
185 }
186
[25124]187 if (service_id.equals(AUTHENTICATION_SERVICE) && (subset == null || subset.equals(GSXML.DISPLAY_TEXT_ELEM + GSXML.LIST_MODIFIER)))
[24978]188 {
189 authen_service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_NAME, getServiceName(service_id, lang)));
[17452]190 authen_service.appendChild(GSXML.createDisplayTextElement(this.doc, GSXML.DISPLAY_TEXT_DESCRIPTION, getServiceDescription(service_id, lang)));
191 }
[24978]192 return authen_service;
[14295]193 }
[17452]194
[24978]195 protected String getServiceName(String service_id, String lang)
196 {
197 return getTextString(service_id + ".name", lang);
[14295]198 }
199
[24978]200 protected String getServiceSubmit(String service_id, String lang)
201 {
202 return getTextString(service_id + ".submit", lang);
[17452]203 }
[14295]204
[24978]205 protected String getServiceDescription(String service_id, String lang)
206 {
207 return getTextString(service_id + ".description", lang);
[17452]208 }
[14295]209
[24978]210 protected void addCustomParams(String service, Element param_list, String lang)
211 {
[17452]212 }
[14295]213
[24978]214 protected void createParameter(String name, Element param_list, String lang)
215 {
[17452]216 }
[14295]217
[25124]218 protected Element processGetUserInformation(Element request)
219 {
220 // Create a new (empty) result message
221 Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
222
223 result.setAttribute(GSXML.FROM_ATT, GET_USER_INFORMATION_SERVICE);
224 result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
225
226 Element paramList = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
227 if (paramList == null)
228 {
[25258]229 GSXML.addError(this.doc, result, _errorMessageMap.get(ERROR_REQUEST_HAS_NO_PARAM_LIST));
230 return result;
[25124]231 }
232
[25635]233 HashMap<String, Serializable> params = GSXML.extractParams(paramList, true);
[25124]234
235 String username = (String) params.get("username");
236
237 if (username == null)
238 {
[25258]239 GSXML.addError(this.doc, result, _errorMessageMap.get(ERROR_USERNAME_NOT_SPECIFIED));
[25124]240 return result;
241 }
242
243 DerbyWrapper dbWrapper = new DerbyWrapper();
244
245 String usersDB_dir = this.site_home + File.separatorChar + "etc" + File.separatorChar + "usersDB";
246 dbWrapper.connectDatabase(usersDB_dir, true);
247
248 UserQueryResult userQueryResult;
249 try
250 {
251 userQueryResult = dbWrapper.findUser(username);
252 Vector<UserTermInfo> terms = userQueryResult.getUserTerms();
253
254 if (terms.size() == 0)
255 {
[25258]256 GSXML.addError(this.doc, result, _errorMessageMap.get(ERROR_REQUESTED_USER_NOT_FOUND));
[25124]257 return result;
258 }
259
260 UserTermInfo userInfo = terms.get(0);
261 Element userInfoList = this.doc.createElement(GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
262 result.appendChild(userInfoList);
263
[25258]264 Element usernameField = GSXML.createParameter(this.doc, "username", userInfo.username);
265 Element passwordField = GSXML.createParameter(this.doc, "password", userInfo.password);
266 Element groupsField = GSXML.createParameter(this.doc, "groups", userInfo.groups);
267 Element accountStatusField = GSXML.createParameter(this.doc, "accountstatus", userInfo.accountstatus);
268 Element commentField = GSXML.createParameter(this.doc, "comment", userInfo.comment);
[25124]269
270 userInfoList.appendChild(usernameField);
271 userInfoList.appendChild(passwordField);
272 userInfoList.appendChild(groupsField);
273 userInfoList.appendChild(accountStatusField);
274 userInfoList.appendChild(commentField);
275 }
[25258]276 catch (SQLException ex)
[25124]277 {
[25258]278 GSXML.addError(this.doc, result, _errorMessageMap.get(ERROR_SQL_EXCEPTION));
[25124]279 ex.printStackTrace();
280 }
281
282 return result;
283 }
284
[25258]285 protected Element processAuthentication(Element request)
[24978]286 {
[25258]287 checkAdminUserExists();
[14295]288
[17452]289 // Create a new (empty) result message
290 Element result = this.doc.createElement(GSXML.RESPONSE_ELEM);
291 result.setAttribute(GSXML.FROM_ATT, AUTHENTICATION_SERVICE);
292 result.setAttribute(GSXML.TYPE_ATT, GSXML.REQUEST_TYPE_PROCESS);
[14295]293
[25258]294 // Create an Authentication node put into the result
295 Element authenNode = this.doc.createElement(GSXML.AUTHEN_NODE_ELEM);
296 result.appendChild(authenNode);
297 result.appendChild(getCollectList(this.site_home + File.separatorChar + "collect"));
298
299 // Create a service node added into the Authentication node
300 Element serviceNode = this.doc.createElement(GSXML.SERVICE_ELEM);
301 authenNode.appendChild(serviceNode);
302
[17452]303 // Get the parameters of the request
[24978]304 Element param_list = (Element) GSXML.getChildByTagName(request, GSXML.PARAM_ELEM + GSXML.LIST_MODIFIER);
305 if (param_list == null)
306 {
[25258]307 serviceNode.setAttribute("operation", LOGIN);
308 GSXML.addError(this.doc, result, _errorMessageMap.get(ERROR_REQUEST_HAS_NO_PARAM_LIST));
[24978]309 return result; // Return the empty result
[17452]310 }
[25635]311 HashMap<String, Serializable> paramMap = GSXML.extractParams(param_list, false);
[25258]312 String op = (String) paramMap.get("authpage");
313 serviceNode.setAttribute("operation", op);
[14295]314
[25258]315 String username = null;
316 String groups = null;
[14295]317
[25258]318 Element userInformation = (Element) GSXML.getChildByTagName(request, GSXML.USER_INFORMATION_ELEM);
319 if (userInformation == null && _userOpList.contains(op))
320 {
321 serviceNode.setAttribute("operation", LOGIN);
322 GSXML.addError(this.doc, result, _errorMessageMap.get(ERROR_NOT_LOGGED_IN));
323 return result;
324 }
[14295]325
[25258]326 if (userInformation != null)
327 {
328 username = userInformation.getAttribute(GSXML.USERNAME_ATT);
329 groups = userInformation.getAttribute(GSXML.GROUPS_ATT);
330 }
[17452]331
[25258]332 if (username == null && _userOpList.contains(op))
333 {
334 serviceNode.setAttribute("operation", LOGIN);
335 GSXML.addError(this.doc, result, _errorMessageMap.get(ERROR_NOT_LOGGED_IN));
336 return result;
337 }
[24978]338
[25258]339 if (_adminOpList.contains(op) && (groups == null || !groups.matches(".*\\badministrator\\b.*")))
[24978]340 {
[25258]341 serviceNode.setAttribute("operation", LOGIN);
342 GSXML.addError(this.doc, result, _errorMessageMap.get(ERROR_ADMIN_NOT_LOGGED_IN));
343 return result;
344 }
[17452]345
[25258]346 if (op.equals(LIST_USERS))
347 {
348 int error = addUserInformationToNode(null, serviceNode);
349 if (error != NO_ERROR)
[24978]350 {
[25258]351 GSXML.addError(this.doc, result, _errorMessageMap.get(error));
[24978]352 }
[25258]353 }
354 else if (op.equals(PERFORM_ADD))
355 {
356 String newUsername = (String) paramMap.get("username");
357 String newPassword = (String) paramMap.get("password");
358 String newGroups = (String) paramMap.get("groups");
359 String newStatus = (String) paramMap.get("status");
360 String newComment = (String) paramMap.get("comment");
361 String newEmail = (String) paramMap.get("email");
[25311]362
363 //Check the given user name
364 int error;
365 if ((error = checkUsername(newUsername)) != NO_ERROR)
366 {
367 GSXML.addError(this.doc, result, _errorMessageMap.get(error));
368 return result;
369 }
[25258]370
[25311]371 //Check the given password
372 if ((error = checkPassword(newPassword)) != NO_ERROR)
373 {
374 GSXML.addError(this.doc, result, _errorMessageMap.get(error));
375 return result;
376 }
377
378 newPassword = hashPassword(newPassword);
379
380 error = addUser(newUsername, newPassword, newGroups, newStatus, newComment, newEmail);
[25258]381 if (error != NO_ERROR)
[24978]382 {
[25258]383 serviceNode.setAttribute("operation", ADD_USER);
384 GSXML.addError(this.doc, result, _errorMessageMap.get(error));
[24978]385 }
[25258]386 else
[24978]387 {
[25258]388 addUserInformationToNode(null, serviceNode);
389 serviceNode.setAttribute("operation", LIST_USERS);
[24978]390 }
[25258]391 }
392 else if (op.equals(PERFORM_REGISTER))
393 {
394 String newUsername = (String) paramMap.get("username");
395 String newPassword = (String) paramMap.get("password");
396 String newEmail = (String) paramMap.get("email");
[25311]397
398 //Check the given user name
399 int error;
400 if ((error = checkUsername(newUsername)) != NO_ERROR)
[24978]401 {
[25311]402 GSXML.addError(this.doc, result, _errorMessageMap.get(error));
[25258]403 return result;
[24978]404 }
[25258]405
[25311]406 //Check the given password
407 if ((error = checkPassword(newPassword)) != NO_ERROR)
[24978]408 {
[25311]409 GSXML.addError(this.doc, result, _errorMessageMap.get(error));
[25258]410 return result;
[24978]411 }
[25311]412
413 newPassword = hashPassword(newPassword);
[25258]414
[25311]415 if(_recaptchaPrivateKey != null)
416 {
417 ReCaptchaImpl reCaptcha = new ReCaptchaImpl();
418 reCaptcha.setPrivateKey(_recaptchaPrivateKey);
419
420 String challenge = (String) paramMap.get("recaptcha_challenge_field");
421 String uResponse = (String) paramMap.get("recaptcha_response_field");
422
423 if (challenge == null || uResponse == null)
424 {
425 serviceNode.setAttribute("operation", REGISTER);
426 GSXML.addError(this.doc, result, _errorMessageMap.get(ERROR_CAPTCHA_MISSING));
427 return result;
428 }
429
430 ReCaptchaResponse reCaptchaResponse = reCaptcha.checkAnswer(request.getAttribute("remoteAddress"), challenge, uResponse);
431
432 if (!reCaptchaResponse.isValid())
433 {
434 serviceNode.setAttribute("operation", REGISTER);
435 GSXML.addError(this.doc, result, _errorMessageMap.get(ERROR_CAPTCHA_DOES_NOT_MATCH));
436 return result;
437 }
438 }
439
440 error = addUser(newUsername, newPassword, "", "true", "", newEmail);
[25258]441 if (error != NO_ERROR)
[24978]442 {
[25258]443 serviceNode.setAttribute("operation", REGISTER);
444 GSXML.addError(this.doc, result, _errorMessageMap.get(error));
[24978]445 }
[25258]446 }
447 else if (op.equals(PERFORM_EDIT))
448 {
449 String previousUsername = (String) paramMap.get("prevUsername");
450 String newUsername = (String) paramMap.get("newUsername");
451 String newPassword = (String) paramMap.get("password");
452 String newGroups = (String) paramMap.get("groups");
453 String newStatus = (String) paramMap.get("status");
454 String newComment = (String) paramMap.get("comment");
455 String newEmail = (String) paramMap.get("email");
456
[25311]457 //Check the given user name
458 int error;
459 if ((error = checkUsername(newUsername)) != NO_ERROR)
460 {
461 GSXML.addError(this.doc, result, _errorMessageMap.get(error));
462 return result;
463 }
464
[25258]465 if (newPassword == null)
[24978]466 {
[25258]467 newPassword = retrieveDataForUser(previousUsername, "password");
[24978]468 }
[25311]469 else
470 {
471 //Check the given password
472 if ((error = checkPassword(newPassword)) != NO_ERROR)
473 {
474 GSXML.addError(this.doc, result, _errorMessageMap.get(error));
475 return result;
476 }
477
478 newPassword = hashPassword(newPassword);
479 }
480
481 error = removeUser(previousUsername);
[25258]482 if (error != NO_ERROR)
[24978]483 {
[25258]484 if (error == ERROR_USERNAME_NOT_SPECIFIED)
485 {
486 addUserInformationToNode(null, serviceNode);
487 serviceNode.setAttribute("operation", LIST_USERS);
488 }
489 else
490 {
491 serviceNode.setAttribute("operation", EDIT_USER);
492 GSXML.addError(this.doc, result, _errorMessageMap.get(error));
493 }
494 return result;
[24978]495 }
[25311]496
[25258]497 error = addUser(newUsername, newPassword, newGroups, newStatus, newComment, newEmail);
498 if (error != NO_ERROR)
[24978]499 {
[25258]500 serviceNode.setAttribute("operation", EDIT_USER);
501 GSXML.addError(this.doc, result, _errorMessageMap.get(error));
[24978]502 }
[25258]503 else
[24978]504 {
[25258]505 addUserInformationToNode(null, serviceNode);
506 serviceNode.setAttribute("operation", LIST_USERS);
[24978]507 }
[25258]508 }
509 else if (op.equals(PERFORM_ACCOUNT_EDIT))
510 {
511 String previousUsername = (String) paramMap.get("prevUsername");
512 String newUsername = (String) paramMap.get("newUsername");
513 String oldPassword = (String) paramMap.get("oldPassword");
514 String newPassword = (String) paramMap.get("newPassword");
515 String newEmail = (String) paramMap.get("newEmail");
516
517 //Make sure the user name does not already exist
518 if (!previousUsername.equals(newUsername) && checkUserExists(newUsername))
[24978]519 {
[25258]520 addUserInformationToNode(previousUsername, serviceNode);
521 serviceNode.setAttribute("operation", ACCOUNT_SETTINGS);
522 GSXML.addError(this.doc, result, _errorMessageMap.get(ERROR_USER_ALREADY_EXISTS));
523 return result;
[24978]524 }
[17452]525
[25258]526 String prevPassword = retrieveDataForUser(previousUsername, "password");
[14295]527
[25258]528 if (newPassword != null)
529 {
530 oldPassword = hashPassword(oldPassword);
[17452]531
[25258]532 if (oldPassword == null || !oldPassword.equals(prevPassword))
[24978]533 {
[25258]534 addUserInformationToNode(previousUsername, serviceNode);
535 serviceNode.setAttribute("operation", ACCOUNT_SETTINGS);
[25352]536 GSXML.addError(this.doc, result, _errorMessageMap.get(ERROR_INCORRECT_PASSWORD), "Incorrect Password");
[17452]537 return result;
538 }
[25311]539
540 //Check the given password
541 int error;
542 if ((error = checkPassword(newPassword)) != NO_ERROR)
543 {
544 GSXML.addError(this.doc, result, _errorMessageMap.get(error));
545 return result;
546 }
547
548 newPassword = hashPassword(newPassword);
[17452]549 }
[25258]550 else
551 {
552 newPassword = prevPassword;
553 }
[25311]554
555 //Check the given user name
556 int error;
557 if ((error = checkUsername(newUsername)) != NO_ERROR)
558 {
559 GSXML.addError(this.doc, result, _errorMessageMap.get(error));
560 return result;
561 }
562
[25258]563 String prevGroups = retrieveDataForUser(previousUsername, "groups");
564 String prevStatus = retrieveDataForUser(previousUsername, "status");
565 String prevComment = retrieveDataForUser(previousUsername, "comment");
566
[25311]567 error = removeUser(previousUsername);
[25258]568 if (error != NO_ERROR)
[24978]569 {
[25258]570 if (error == ERROR_USERNAME_NOT_SPECIFIED)
[24978]571 {
[25258]572 addUserInformationToNode(null, serviceNode);
573 serviceNode.setAttribute("operation", LIST_USERS);
[17452]574 }
[24978]575 else
576 {
[25258]577 addUserInformationToNode(previousUsername, serviceNode);
578 serviceNode.setAttribute("operation", ACCOUNT_SETTINGS);
579 GSXML.addError(this.doc, result, _errorMessageMap.get(error));
[17452]580 }
[25258]581 return result;
[14295]582 }
[17452]583
[25258]584 error = addUser(newUsername, newPassword, prevGroups, prevStatus, prevComment, newEmail);
585 if (error != NO_ERROR)
[24978]586 {
[25258]587 GSXML.addError(this.doc, result, _errorMessageMap.get(error));
[14295]588 }
[25258]589
590 addUserInformationToNode(null, serviceNode);
591 serviceNode.setAttribute("operation", LIST_USERS);
[14295]592 }
[25258]593 else if (op.equals(EDIT_USER))
[24978]594 {
[25258]595 String editUsername = (String) paramMap.get("username");
596 int error = addUserInformationToNode(editUsername, serviceNode);
597 if (error != NO_ERROR)
[24978]598 {
[25258]599 GSXML.addError(this.doc, result, _errorMessageMap.get(error));
600 }
601 }
602 else if (op.equals(ACCOUNT_SETTINGS))
603 {
604 String editUsername = (String) paramMap.get("username");
[25311]605
606 if (editUsername == null)
[25258]607 {
608 serviceNode.setAttribute("operation", "");
609 GSXML.addError(this.doc, result, _errorMessageMap.get(ERROR_USERNAME_NOT_SPECIFIED));
[17452]610 return result;
611 }
[25311]612
613 if (!editUsername.equals(username))
[24978]614 {
[25258]615 serviceNode.setAttribute("operation", LOGIN);
616 GSXML.addError(this.doc, result, _errorMessageMap.get(ERROR_NOT_AUTHORISED));
[17452]617 return result;
618 }
[25258]619 int error = addUserInformationToNode(editUsername, serviceNode);
620 if (error != NO_ERROR)
[24978]621 {
[25258]622 GSXML.addError(this.doc, result, _errorMessageMap.get(error));
[17452]623 }
[14295]624 }
[25258]625 else if (op.equals(PERFORM_RESET_PASSWORD))
[24978]626 {
[25258]627 String passwordResetUser = (String) paramMap.get("username");
[25311]628
[25258]629 String newPassword = UUID.randomUUID().toString();
630 newPassword = newPassword.substring(0, newPassword.indexOf("-"));
[25311]631
[25258]632 String email = retrieveDataForUser(passwordResetUser, "email");
633 String from = "[email protected]";
634 String host = request.getAttribute("remoteAddress");
[25311]635
[25270]636 //TODO: FINISH THIS
[25258]637 }
[25311]638 else if (op.equals(REGISTER))
639 {
640 if(_recaptchaPublicKey != null && _recaptchaPrivateKey != null)
641 {
642 Element recaptchaElem = this.doc.createElement("recaptcha");
643 recaptchaElem.setAttribute("publicKey", _recaptchaPublicKey);
644 recaptchaElem.setAttribute("privateKey", _recaptchaPrivateKey);
645 result.appendChild(recaptchaElem);
646 }
647 }
[25258]648 else if (op.equals(PERFORM_DELETE_USER))
649 {
650 String usernameToDelete = (String) paramMap.get("username");
651 int error = removeUser(usernameToDelete);
652 if (error != NO_ERROR)
[24978]653 {
[25258]654 GSXML.addError(this.doc, result, _errorMessageMap.get(error));
[17452]655 }
[25258]656 addUserInformationToNode(null, serviceNode);
657 serviceNode.setAttribute("operation", LIST_USERS);
658 }
[17452]659
[25258]660 return result;
661 }
[25311]662
663 public int checkUsernameAndPassword(String username, String password)
664 {
665 int uResult = checkUsername(username);
666 int pResult = checkPassword(password);
667
668 return (uResult != NO_ERROR ? uResult : (pResult != NO_ERROR ? pResult : NO_ERROR));
669 }
670
671 public int checkUsername(String username)
672 {
673 //Check the given user name
674 if ((username == null) || (username.length() < 2) || (username.length() > 30) || (!(Pattern.matches("[a-zA-Z0-9//_//.]+", username))))
675 {
676 return ERROR_INVALID_USERNAME;
677 }
678 return NO_ERROR;
679 }
680
681 public int checkPassword(String password)
682 {
683 //Check the given password
684 if ((password == null) || (password.length() < 3) || (password.length() > 8) || (!(Pattern.matches("[\\p{ASCII}]+", password))))
685 {
686 return ERROR_INVALID_PASSWORD;
687 }
688 return NO_ERROR;
689 }
[17452]690
[25258]691 public static String hashPassword(String password)
692 {
693 String hashedPassword = null;
694 try
695 {
696 MessageDigest digest = MessageDigest.getInstance("SHA-1");
697 digest.reset();
[25318]698 hashedPassword = new String(digest.digest(password.getBytes("US-ASCII"))); // toHex after using ASCII charset will result in acceptable length of hex string
699 hashedPassword = toHex(hashedPassword); // this conversion is required to avoid the strange error of login failure on some legal password strings
[14295]700 }
[25258]701 catch (Exception ex)
702 {
703 ex.printStackTrace();
704 }
705 return hashedPassword;
706 }
[14295]707
[25318]708
709
710 // This method can also be used for printing out the password in hex (in case
711 // the password used the UTF-8 Charset), or the hex values in any unicode string.
712 // From http://stackoverflow.com/questions/923863/converting-a-string-to-hexadecimal-in-java
713 public static String toHex(String arg) {
714 try {
715 return String.format("%x", new BigInteger(arg.getBytes("US-ASCII"))); // set to same charset as used by hashPassword
716 } catch (Exception e) { // UnsupportedEncodingException
717 e.printStackTrace();
718 }
719 return "Unable to print";
720 }
721
722
[25258]723 private void checkAdminUserExists()
724 {
725 if (_derbyWrapper == null)
[24978]726 {
[25258]727 openDatabase();
728 }
[17452]729
[25258]730 UserQueryResult userQueryResult = _derbyWrapper.findUser(null, null);
731 closeDatabase();
[17452]732
[25258]733 if (userQueryResult != null)
734 {
735 Vector userInfo = userQueryResult.users;
[17452]736
[25258]737 boolean adminFound = false;
738 for (int i = 0; i < userQueryResult.getSize(); i++)
[24978]739 {
[25258]740 if (((UserTermInfo) userInfo.get(i)).groups != null && ((UserTermInfo) userInfo.get(i)).groups.matches(".*\\badministrator\\b.*"))
[24978]741 {
[25258]742 adminFound = true;
[17452]743 }
744 }
745
[25258]746 if (!adminFound)
[24978]747 {
[25258]748 addUser("admin", "admin", "administrator", "true", "Change the password for this account as soon as possible", "");
[17452]749 }
[14295]750 }
751
[25258]752 closeDatabase();
753 }
754
755 private boolean openDatabase()
756 {
757 _derbyWrapper = new DerbyWrapper();
758
759 // check the usersDb database, if it isn't existing, check the etc dir, create the etc dir if it isn't existing, then create the user database and add a "admin" user
760 String usersDB_dir = this.site_home + File.separatorChar + "etc" + File.separatorChar + "usersDB";
761 File usersDB_file = new File(usersDB_dir);
762 if (!usersDB_file.exists())
[24978]763 {
[25258]764 String etc_dir = this.site_home + File.separatorChar + "etc";
765 File etc_file = new File(etc_dir);
766 if (!etc_file.exists())
[24978]767 {
[25258]768 boolean success = etc_file.mkdir();
769 if (!success)
770 {
771 logger.error("Couldn't create the etc dir under " + this.site_home + ".");
772 return false;
773 }
[17452]774 }
[25258]775 _derbyWrapper.connectDatabase(usersDB_dir, true);
776 _derbyWrapper.createDatabase();
777 }
778 else
779 {
780 _derbyWrapper.connectDatabase(usersDB_dir, false);
781 }
782 return true;
783 }
[14295]784
[25258]785 private void closeDatabase()
786 {
787 if (_derbyWrapper != null)
788 {
789 _derbyWrapper.closeDatabase();
790 _derbyWrapper = null;
791 }
792 }
[17452]793
[25258]794 private int addUserInformationToNode(String username, Element serviceNode)
795 {
796 if (_derbyWrapper == null)
797 {
798 openDatabase();
799 }
[17452]800
[25258]801 UserQueryResult userQueryResult = _derbyWrapper.findUser(username, null);
802 closeDatabase();
[17452]803
[25258]804 if (userQueryResult != null)
805 {
806 Element user_node = getUserNode(userQueryResult);
807 serviceNode.appendChild(user_node);
808 closeDatabase();
809 return NO_ERROR;
810 }
[17452]811
[25258]812 closeDatabase();
813 return ERROR_COULD_NOT_GET_USER_INFO;
814 }
[17452]815
[25258]816 private int removeUser(String username)
817 {
818 if (username == null)
819 {
820 return ERROR_USERNAME_NOT_SPECIFIED;
821 }
[17452]822
[25258]823 if (_derbyWrapper == null)
824 {
825 openDatabase();
826 }
827
828 boolean success = _derbyWrapper.deleteUser(username);
829 closeDatabase();
830
831 if (success)
832 {
833 return NO_ERROR;
834 }
835
836 return ERROR_REMOVING_USER;
837 }
838
839 private int addUser(String newUsername, String newPassword, String newGroups, String newStatus, String newComment, String newEmail)
840 {
841 if (_derbyWrapper == null)
842 {
843 openDatabase();
844 }
845
846 newGroups = newGroups.replaceAll(" ", "");
847
848 //Check if the user already exists
849 UserQueryResult userQueryResult = _derbyWrapper.findUser(newUsername, null);
850 if (userQueryResult != null)
851 {
[25311]852 closeDatabase();
[25258]853 return ERROR_USER_ALREADY_EXISTS;
854 }
855 else
856 {
857 System.err.println("ADDING " + newUsername + " " + newPassword);
858 boolean success = _derbyWrapper.addUser(newUsername, newPassword, newGroups, newStatus, newComment, newEmail);
859 if (!success)
[24978]860 {
[25258]861 closeDatabase();
862 return ERROR_ADDING_USER;
[17452]863 }
[25258]864 }
865 closeDatabase();
866 return NO_ERROR;
867 }
[17452]868
[25258]869 private boolean checkUserExists(String username)
870 {
871 if (_derbyWrapper == null)
872 {
873 openDatabase();
874 }
875
876 try
877 {
878 UserQueryResult result = _derbyWrapper.findUser(username);
879
880 if (result != null)
[24978]881 {
[25258]882 return true;
[24978]883 }
884 else
885 {
[25258]886 return false;
[17452]887 }
[25258]888
[14295]889 }
[25258]890 catch (Exception ex)
891 {
892 return false;
893 }
894 finally
895 {
896 closeDatabase();
897 }
898 }
[17452]899
[25258]900 private String retrieveDataForUser(String username, String dataType)
901 {
902 if (_derbyWrapper == null)
[24978]903 {
[25258]904 openDatabase();
905 }
906
907 String password = null;
908
909 try
910 {
911 UserQueryResult result = _derbyWrapper.findUser(username);
912 Vector userInfo = result.users;
913
914 for (int i = 0; i < result.getSize(); i++)
[24978]915 {
[25258]916 if (dataType.equals("password"))
[24978]917 {
[25258]918 return ((UserTermInfo) userInfo.get(i)).password;
[24978]919 }
[25258]920 else if (dataType.equals("groups"))
[24978]921 {
[25258]922 return ((UserTermInfo) userInfo.get(i)).groups;
[17452]923 }
[25258]924 else if (dataType.equals("status"))
925 {
926 return ((UserTermInfo) userInfo.get(i)).accountstatus;
927 }
928 else if (dataType.equals("comment"))
929 {
930 return ((UserTermInfo) userInfo.get(i)).comment;
931 }
932 else if (dataType.equals("email"))
933 {
934 return ((UserTermInfo) userInfo.get(i)).email;
935 }
[24978]936 }
[14295]937 }
[25258]938 catch (Exception ex)
939 {
940 ex.printStackTrace();
941 }
[14295]942
[25258]943 closeDatabase();
944 return password;
[14295]945 }
946
[24978]947 private Element getUserNode(UserQueryResult userQueryResult)
948 {
949 Element user_list_node = this.doc.createElement(GSXML.USER_NODE_ELEM + "List");
[14295]950
[25258]951 Vector userInfo = userQueryResult.users;
[14295]952
[24978]953 for (int i = 0; i < userQueryResult.getSize(); i++)
954 {
955 Element user_node = this.doc.createElement(GSXML.USER_NODE_ELEM);
[25258]956 String username = ((UserTermInfo) userInfo.get(i)).username;
957 String groups = ((UserTermInfo) userInfo.get(i)).groups;
958 String accountstatus = ((UserTermInfo) userInfo.get(i)).accountstatus;
959 String comment = ((UserTermInfo) userInfo.get(i)).comment;
960 String email = ((UserTermInfo) userInfo.get(i)).email;
961 user_node.setAttribute("username", username);
962 user_node.setAttribute("groups", groups);
963 user_node.setAttribute("status", accountstatus);
964 user_node.setAttribute("comment", comment);
965 user_node.setAttribute("email", email);
[14295]966
[17452]967 user_list_node.appendChild(user_node);
[14295]968 }
[24978]969 return user_list_node;
[14295]970 }
971
[24978]972 private Element getCollectList(String collect)
973 {
974 Element collect_list_node = this.doc.createElement(GSXML.COLLECTION_ELEM + "List");
975 File[] collect_dir = (new File(collect)).listFiles();
976 if (collect_dir != null && collect_dir.length > 0)
977 {
978 for (int i = 0; i < collect_dir.length; i++)
979 {
980 if (collect_dir[i].isDirectory() && (!collect_dir[i].getName().startsWith(".svn")))
981 {
[17452]982 Element collect_node = this.doc.createElement(GSXML.COLLECTION_ELEM);
[24978]983 collect_node.setAttribute("name", collect_dir[i].getName());
[17452]984 collect_list_node.appendChild(collect_node);
985 }
986 }
[14402]987 }
[17452]988 return collect_list_node;
[14402]989 }
[14295]990}
Note: See TracBrowser for help on using the repository browser.