| 1 16 package org.outerj.daisy.repository.serverimpl.user; 17 18 import java.sql.*; 19 import java.util.*; 20 import java.util.Date ; 21 import java.security.MessageDigest ; 22 23 import org.apache.avalon.framework.logger.Logger; 24 import org.apache.xmlbeans.XmlObject; 25 import org.apache.commons.collections.primitives.LongList; 26 import org.apache.commons.collections.primitives.ArrayLongList; 27 import org.outerj.daisy.repository.commonimpl.AuthenticatedUser; 28 import org.outerj.daisy.repository.commonimpl.user.RoleImpl; 29 import org.outerj.daisy.repository.commonimpl.user.RolesImpl; 30 import org.outerj.daisy.repository.commonimpl.user.RolesUtil; 31 import org.outerj.daisy.repository.commonimpl.user.UserImpl; 32 import org.outerj.daisy.repository.commonimpl.user.UserManagementStrategy; 33 import org.outerj.daisy.repository.commonimpl.user.UsersImpl; 34 import org.outerj.daisy.jdbcutil.JdbcHelper; 35 import org.outerj.daisy.repository.serverimpl.EventHelper; 36 import org.outerj.daisy.repository.serverimpl.LocalRepositoryManager.Context; 37 import org.outerj.daisy.repository.user.*; 38 import org.outerj.daisy.repository.RepositoryEventType; 39 import org.outerj.daisy.repository.RepositoryException; 40 import org.outerx.daisy.x10.*; 41 42 public class LocalUserManagementStrategy implements UserManagementStrategy { 43 private static final String SELECT_ALL_FROM_USERS = "select id, login, default_role, first_name, last_name, email, updateable_by_user, confirmed, confirmkey, auth_scheme, last_modified, last_modifier,updatecount from users"; 44 private static final String SELECT_USER_WHERE_LOGIN = SELECT_ALL_FROM_USERS+" where login=?"; 45 private static final String SELECT_USER_WHERE_ID = SELECT_ALL_FROM_USERS+" where id=?"; 46 private static final String SELECT_USERS_WHERE_EMAIL = SELECT_ALL_FROM_USERS+" where email=?"; 47 private static final String SELECT_ALL_FROM_ROLES = "select id, \"name\", description, last_modified, last_modifier, updatecount from roles"; 48 private static final String SELECT_ROLE_WHERE_NAME = SELECT_ALL_FROM_ROLES+" where \"name\"=?"; 49 private static final String SELECT_ROLE_WHERE_ID = SELECT_ALL_FROM_ROLES+" where id=?"; 50 private static final String SELECT_ROLES_WHERE_USERID = "select role_id from user_roles where user_id=?"; 51 private static final String INSERT_ROLES = "insert into user_roles(role_id, user_id) values (?,?)"; 52 private static final String DELETE_ROLES = "delete from user_roles where user_id=?"; 53 private Logger logger; 54 private Context context; 55 private JdbcHelper jdbcHelper; 56 private EventHelper eventHelper; 57 58 61 public LocalUserManagementStrategy(Context context, JdbcHelper jdbcHelper) { 62 this.context = context; 63 this.logger = context.getLogger(); 64 this.jdbcHelper = jdbcHelper; 65 this.eventHelper = new EventHelper(context, jdbcHelper); 66 } 67 68 public Users loadUsers(AuthenticatedUser requestingUser) throws UserManagementException { 69 if (!requestingUser.isInAdministratorRole()) 70 throw new UserManagementException("Non-Administrator users cannot retrieve other users then themselve."); 71 72 Connection conn = null; 73 PreparedStatement stmt = null; 74 ArrayList users = new ArrayList(); 75 76 try { 77 conn = context.getDataSource().getConnection(); 78 79 stmt = conn.prepareStatement(SELECT_ALL_FROM_USERS); 80 ResultSet rs = stmt.executeQuery(); 81 82 while (rs.next()) { 83 UserImpl user = getUserFromResultSet(rs, requestingUser); 84 users.add(user); 85 } 86 } catch (Exception e) { 87 throw new UserManagementException("Error while loading user list.", e); 88 } finally { 89 jdbcHelper.closeStatement(stmt); 90 jdbcHelper.closeConnection(conn); 91 } 92 93 return new UsersImpl((User[])users.toArray(new User[users.size()])); 94 } 95 96 private UserImpl getUserFromResultSet(ResultSet rs, AuthenticatedUser requestingUser) throws SQLException, UserManagementException { 97 long id = rs.getLong(1); 98 String login = rs.getString(2); 99 long defaultRoleId = rs.getLong(3); 100 String firstName = rs.getString(4); 101 String lastName = rs.getString(5); 102 String email = rs.getString(6); 103 boolean updateableByUser = rs.getBoolean(7); 104 boolean confirmed = rs.getBoolean(8); 105 String confirmKey = rs.getString(9); 106 String authenticationScheme = rs.getString(10); 107 Date lastModified = rs.getTimestamp(11); 108 long lastModifier = rs.getLong(12); 109 long updateCount = rs.getLong(13); 110 111 UserImpl user = new UserImpl(this, login, requestingUser); 112 UserImpl.IntimateAccess userInt = user.getIntimateAccess(this); 113 userInt.saved(id, firstName, lastName, email, lastModified, lastModifier, updateCount); 116 user.setUpdateableByUser(updateableByUser); 117 user.setConfirmed(confirmed); 118 user.setConfirmKey(confirmKey); 119 user.setAuthenticationScheme(authenticationScheme); 120 121 Role[] userRoles = getUserRoles(id, requestingUser); 122 for (int i = 0; i < userRoles.length; i++) { 123 Role role = userRoles[i]; 124 userInt.addToRole(role); 125 } 126 127 if (defaultRoleId == -1) { 128 user.setDefaultRole(null); 129 } else { 130 Role defaultRole = RolesUtil.getRole(user.getAllRoles(), defaultRoleId); 131 user.setDefaultRole(defaultRole); 132 } 133 134 return user; 135 } 136 137 public long[] getUserIds(AuthenticatedUser requestingUser) throws UserManagementException { 138 Connection conn = null; 139 Statement stmt = null; 140 try { 141 conn = context.getDataSource().getConnection(); 142 stmt = conn.createStatement(); 143 ResultSet rs = stmt.executeQuery("select id from users"); 144 LongList userIds = new ArrayLongList(); 145 while (rs.next()) 146 userIds.add(rs.getLong(1)); 147 return userIds.toArray(); 148 } catch (Exception e) { 149 throw new UserManagementException("Error while loading user list.", e); 150 } finally { 151 jdbcHelper.closeStatement(stmt); 152 jdbcHelper.closeConnection(conn); 153 } 154 } 155 156 public Roles loadRoles(AuthenticatedUser requestingUser) throws UserManagementException { 157 Connection conn = null; 158 PreparedStatement stmt = null; 159 ArrayList roles = new ArrayList(); 160 161 try { 162 conn = context.getDataSource().getConnection(); 163 164 stmt = conn.prepareStatement(SELECT_ALL_FROM_ROLES); 165 ResultSet rs = stmt.executeQuery(); 166 167 while (rs.next()) { 168 long id = rs.getLong(1); 169 String name = rs.getString(2); 170 String description = rs.getString(3); 171 Date lastModified = rs.getTimestamp(4); 172 long lastModifier = rs.getLong(5); 173 RoleImpl role = new RoleImpl(this, name, requestingUser); 174 role.setDescription(description); 175 RoleImpl.IntimateAccess roleInt = role.getIntimateAccess(this); 176 roleInt.setId(id); 177 roleInt.setLastModified(lastModified); 178 roleInt.setLastModifier(lastModifier); 179 roles.add(role); 180 } 181 182 rs.close(); 183 } catch (Exception e) { 184 throw new UserManagementException("Error while loading role list.", e); 185 } finally { 186 jdbcHelper.closeStatement(stmt); 187 jdbcHelper.closeConnection(conn); 188 } 189 190 return new RolesImpl((Role[])roles.toArray(new Role[roles.size()])); 191 } 192 193 public void deleteUser(long userId, AuthenticatedUser requestingUser) throws UserManagementException { 194 if (logger.isDebugEnabled()) 195 logger.debug("start user deletion for user with login "+userId); 196 197 if (!requestingUser.isInAdministratorRole()) 198 throw new UserManagementException("Only Administrators can delete users."); 199 200 if (userId == 1) 201 throw new UserManagementException("The system user (id 1) cannot be deleted."); 202 203 Connection conn = null; 204 PreparedStatement stmt = null; 205 try { 206 conn = context.getDataSource().getConnection(); 207 jdbcHelper.startTransaction(conn); 209 210 UserImpl user = getUser(userId, requestingUser); 211 212 logger.debug("first we need to remove child records from user_roles"); 213 214 stmt = conn.prepareStatement("delete from user_roles where user_id=?"); 215 stmt.setLong(1, userId); 216 217 stmt.executeUpdate(); 218 stmt.close(); 219 logger.debug("user_roles should be clear for this user. User can be deleted now"); 220 221 stmt = conn.prepareStatement("update users set last_modifier = 1 where id = ?"); 226 stmt.setLong(1, userId); 227 stmt.execute(); 228 stmt.close(); 229 230 stmt = conn.prepareStatement("delete from users where id=?"); 231 stmt.setLong(1, userId); 232 233 int modifiedRecords = stmt.executeUpdate(); 234 if (modifiedRecords!=1) { 235 throw new UserManagementException("Something went wrong " + 236 "when trying to delete user with login "+userId+". " + 237 "No records were affected."); 238 } 239 240 XmlObject eventDescription = createUserDeletedEvent(user, requestingUser.getId()); 241 eventHelper.createEvent(eventDescription, "UserDeleted", conn); 242 243 conn.commit(); 244 } catch (Throwable e) { 245 jdbcHelper.rollback(conn); 246 throw new UserManagementException("Error deleting the user with ID " + userId 247 + ". This might be because the user is still in use (referenced by other objects such as documents), in which case it is impossible to delete the user.", e); 248 } finally { 249 jdbcHelper.closeStatement(stmt); 250 jdbcHelper.closeConnection(conn); 251 logger.debug("end user deletion"); 252 } 253 254 context.getCommonRepository().fireRepositoryEvent(RepositoryEventType.USER_DELETED, userId, -1); 256 } 257 258 private UserDeletedDocument createUserDeletedEvent(UserImpl user, long deleterId) { 259 UserDeletedDocument userDeletedDocument = UserDeletedDocument.Factory.newInstance(); 260 UserDeletedDocument.UserDeleted userDeleted = userDeletedDocument.addNewUserDeleted(); 261 userDeleted.setDeleterId(deleterId); 262 userDeleted.setDeletedTime(new GregorianCalendar()); 263 UserDocument.User userXml = user.getXml().getUser(); 264 if (userXml.isSetPassword()) 265 userXml.unsetPassword(); 266 userDeleted.addNewDeletedUser().setUser(userXml); 267 return userDeletedDocument; 268 } 269 270 public void deleteRole(long roleId, AuthenticatedUser requestingUser) throws UserManagementException { 271 if (!requestingUser.isInAdministratorRole()) 272 throw new UserManagementException("Only Administrators can delete roles."); 273 274 if (roleId == 1) 275 throw new UserManagementException("The Administrator role (id 1) cannot be deleted."); 276 277 296 Connection conn = null; 297 PreparedStatement stmt = null; 298 299 try { 300 conn = context.getDataSource().getConnection(); 301 302 stmt = conn.prepareStatement("select count(*) from users where default_role=?"); 303 stmt.setLong(1, roleId); 304 305 ResultSet rs = stmt.executeQuery(); 306 307 rs.next(); 308 long userCount = rs.getInt(1); 310 if (userCount>0) { 311 throw new UserManagementException("Cannot delete the role with id "+roleId+" because " + 312 "there are still "+userCount+" users who have this role as their default. " + 313 "Change their default roles before deleting this role."); 314 } 315 316 } catch (Exception e) { 317 throw new UserManagementException("Error while deleting role.", e); 318 } finally { 319 jdbcHelper.closeStatement(stmt); 320 jdbcHelper.closeConnection(conn); 321 } 322 323 325 try { 326 conn = context.getDataSource().getConnection(); 327 jdbcHelper.startTransaction(conn); 328 329 RoleImpl role = getRole(roleId, requestingUser); 330 331 stmt = conn.prepareStatement("delete from user_roles where role_id=?"); 332 stmt.setLong(1, roleId); 333 334 stmt.executeUpdate(); 335 stmt.close(); 336 338 stmt = conn.prepareStatement("delete from roles where id=?"); 339 stmt.setLong(1, roleId); 340 341 int modifiedRecords = stmt.executeUpdate(); 342 if (modifiedRecords!=1) { 343 throw new UserManagementException("Something went wrong " + 344 "when trying to delete role with id "+roleId +". " + 345 "Most likely the role didn't exist." + 346 modifiedRecords +" records modified."); 347 } 348 stmt.close(); 349 350 eventHelper.createEvent(createRoleDeletedEvent(role), "RoleDeleted", conn); 351 352 conn.commit(); 353 354 } catch (Throwable e) { 355 jdbcHelper.rollback(conn); 356 throw new UserManagementException("Error deleting the role with ID " + roleId + ".", e); 357 } finally { 358 jdbcHelper.closeStatement(stmt); 359 jdbcHelper.closeConnection(conn); 360 } 361 362 context.getCommonRepository().fireRepositoryEvent(RepositoryEventType.ROLE_DELETED, roleId, -1); 364 } 365 366 private RoleDeletedDocument createRoleDeletedEvent(RoleImpl role) { 367 RoleDeletedDocument roleDeletedDocument = RoleDeletedDocument.Factory.newInstance(); 368 RoleDeletedDocument.RoleDeleted roleDeleted = roleDeletedDocument.addNewRoleDeleted(); 369 roleDeleted.addNewDeletedRole().setRole(role.getXml().getRole()); 370 roleDeleted.setDeletedTime(new GregorianCalendar()); 371 roleDeleted.setDeleterId(role.getIntimateAccess(this).getCurrentUser().getId()); 372 return roleDeletedDocument; 373 } 374 375 public UserImpl getUser(String userLogin, AuthenticatedUser requestingUser) throws UserManagementException { 376 Connection conn = null; 377 PreparedStatement stmt = null; 378 UserImpl user = null; 379 380 try { 381 conn = context.getDataSource().getConnection(); 382 stmt = conn.prepareStatement(SELECT_USER_WHERE_LOGIN); 383 stmt.setString(1, userLogin); 384 ResultSet rs = stmt.executeQuery(); 385 386 if (rs.next()) { 387 user = getUserFromResultSet(rs, requestingUser); 388 389 if (user.getId() != requestingUser.getId() && !requestingUser.isInAdministratorRole()) 390 throw new UserManagementException("Non-Administrator users can only access their own user record."); 391 392 } else { 393 throw new UserNotFoundException(userLogin); 394 } 395 396 rs.close(); 397 } catch (Exception e) { 398 if (e instanceof UserManagementException) 399 throw (UserManagementException)e; 400 else 401 throw new UserManagementException("Error while loading user with login "+userLogin+".", e); 402 } finally { 403 jdbcHelper.closeStatement(stmt); 404 jdbcHelper.closeConnection(conn); 405 } 406 407 return user; 408 } 409 410 413 private Role[] getUserRoles(long id, AuthenticatedUser requestingUser) throws UserManagementException { 414 if (logger.isDebugEnabled()) 415 logger.debug("start loading roles for user with id "+id); 416 Connection conn = null; 417 PreparedStatement stmt = null; 418 ArrayList ids = new ArrayList(); 419 Role[] roles=null; 420 421 try { 422 conn = context.getDataSource().getConnection(); 423 stmt = conn.prepareStatement(SELECT_ROLES_WHERE_USERID); 424 stmt.setLong(1, id); 425 ResultSet rs = stmt.executeQuery(); 426 427 while (rs.next()) { 428 long roleId = rs.getLong(1); 429 if (logger.isDebugEnabled()) 430 logger.debug("role found with id "+roleId); 431 ids.add(new Long (roleId)); 432 } 433 rs.close(); 434 } catch (Exception e) { 435 throw new UserManagementException("Error while loading role list for user with id "+id+".", e); 436 } finally { 437 jdbcHelper.closeStatement(stmt); 438 jdbcHelper.closeConnection(conn); 439 } 440 441 Iterator iter = ids.iterator(); 442 roles = new Role[ids.size()]; 443 for (int i=0; i<roles.length; i++) { 444 long roleId = ((Long )iter.next()).longValue(); 445 roles[i] = getRoleWhereId(roleId, requestingUser); 446 } 447 448 return roles; 449 450 } 451 452 public RoleImpl getRole(String roleName, AuthenticatedUser requestingUser) throws UserManagementException{ 453 Connection conn = null; 454 PreparedStatement stmt = null; 455 RoleImpl role = null; 456 457 try { 458 conn = context.getDataSource().getConnection(); 459 stmt = conn.prepareStatement(SELECT_ROLE_WHERE_NAME); 460 stmt.setString(1, roleName); 461 ResultSet rs = stmt.executeQuery(); 462 463 if (rs.next()) { 464 long id = rs.getLong(1); 465 String name = rs.getString(2); 466 String description = rs.getString(3); 467 Date lastModified = rs.getTimestamp(4); 468 long lastModifier = rs.getLong(5); 469 long updateCount = rs.getLong(6); 470 471 role = new RoleImpl(this, name, requestingUser); 472 RoleImpl.IntimateAccess roleInt = role.getIntimateAccess(this); 473 roleInt.saved(id, name, description, updateCount); 474 roleInt.setLastModified(lastModified); 475 roleInt.setLastModifier(lastModifier); 476 477 } else { 478 throw new RoleNotFoundException(roleName); 479 } 480 rs.close(); 481 } catch (Exception e) { 482 if (e instanceof UserManagementException) 483 throw (UserManagementException)e; 484 else 485 throw new UserManagementException("Error while loading role with name "+roleName+".", e); 486 } finally { 487 jdbcHelper.closeStatement(stmt); 488 jdbcHelper.closeConnection(conn); 489 } 490 491 return role; 492 } 493 494 private Role getRoleWhereId(long roleId, AuthenticatedUser requestingUser) throws UserManagementException{ 495 Connection conn = null; 496 PreparedStatement stmt = null; 497 RoleImpl role = null; 498 499 try { 500 conn = context.getDataSource().getConnection(); 501 stmt = conn.prepareStatement(SELECT_ROLE_WHERE_ID); 502 stmt.setLong(1, roleId); 503 ResultSet rs = stmt.executeQuery(); 504 505 if (rs.next()) { 506 long id = rs.getLong(1); 507 String name = rs.getString(2); 508 String description = rs.getString(3); 509 Date lastModified = rs.getTimestamp(4); 510 long lastModifier = rs.getLong(5); 511 long updateCount = rs.getLong(6); 512 513 role = new RoleImpl(this, name, requestingUser); 514 RoleImpl.IntimateAccess roleInt = role.getIntimateAccess(this); 515 roleInt.saved(id, name, description, updateCount); 516 roleInt.setLastModified(lastModified); 517 roleInt.setLastModifier(lastModifier); 518 519 } else { 520 throw new UserManagementException("No role found with id "+roleId); 521 } 522 rs.close(); 523 } catch (Exception e) { 524 throw new UserManagementException("Error while loading role with id "+roleId+".", e); 525 } finally { 526 jdbcHelper.closeStatement(stmt); 527 jdbcHelper.closeConnection(conn); 528 } 529 530 return role; 531 } 532 533 public void store(UserImpl user) throws UserManagementException { 534 logger.debug("starting storage of user"); 535 536 if (user.getId() == 1) { 537 throw new UserManagementException("User $system is read-only."); 538 } 539 540 UserImpl.IntimateAccess userInt = user.getIntimateAccess(this); 541 542 if (user.getId() == -1 && !userInt.getCurrentUser().isInAdministratorRole()) 544 throw new UserManagementException("Only Administrators can update user records."); 545 546 547 if (user.getId() == -1 && user.getAuthenticationScheme().equals("daisy") && userInt.getPassword() == null) { 548 throw new UserManagementException("Password is required if the authentication scheme is daisy."); 549 } 550 551 if (userInt.getPassword() != null && !UserImpl.isValidPassword(userInt.getPassword())) { 552 throw new UserManagementException("Password does not adhere to password rules."); 553 } 554 555 if (user.getDefaultRole() != null) { 556 if (!user.hasRole(user.getDefaultRole().getId())) { 557 throw new UserManagementException("The user has a default role that does not belong to its assigned roles."); 558 } 559 } 560 561 if (user.getAllRoles().getArray().length < 1) { 562 throw new UserManagementException("A user must have at least one role."); 563 } 564 565 long id = user.getId(); 566 boolean isNew = (id == -1); 567 568 Connection conn = null; 569 PreparedStatement stmt = null; 570 try { 571 conn = context.getDataSource().getConnection(); 572 jdbcHelper.startTransaction(conn); 574 575 String login = user.getLogin(); 576 java.util.Date lastModified = new Date (); 577 logger.debug("the last_modified date that will be stored is "+lastModified); 578 579 582 long lastModifier = userInt.getCurrentUser().getId(); 583 XmlObject eventDescription; 584 585 if (id == -1) { 586 stmt = conn.prepareStatement("select id from users where login = ?"); 588 stmt.setString(1, login); 589 ResultSet rs = stmt.executeQuery(); 590 if (rs.next()) 591 throw new DuplicateLoginException(login); 592 stmt.close(); 593 594 stmt = conn.prepareStatement("insert into users(id, login, password, default_role, first_name, last_name, email, updateable_by_user, confirmed, confirmkey, auth_scheme, last_modified, last_modifier, updatecount) values (?,?,?,?,?,?,?,?,?,?,?,?,?,?)"); 596 id = context.getNextUserId(); 597 stmt.setLong(1, id); 598 stmt.setString(2, login); 599 stmt.setString(3, hashPassword(userInt.getPassword())); 600 stmt.setLong(4, user.getDefaultRole() == null ? -1 : user.getDefaultRole().getId()); 601 stmt.setString(5, user.getFirstName()); 602 stmt.setString(6, user.getLastName()); 603 stmt.setString(7, user.getEmail()); 604 stmt.setBoolean(8, user.isUpdateableByUser()); 605 stmt.setBoolean(9, user.isConfirmed()); 606 stmt.setString(10, user.getConfirmKey()); 607 stmt.setString(11, user.getAuthenticationScheme()); 608 stmt.setTimestamp(12, new Timestamp(lastModified.getTime())); 609 stmt.setLong(13, lastModifier); 610 stmt.setLong(14, 1L); 611 stmt.executeUpdate(); 612 613 storeRolesForUser(user, id, conn); 614 615 eventDescription = createUserCreatedEvent(user, lastModified); 616 } else { 617 UserImpl oldUser = getUser(user.getId(), userInt.getCurrentUser()); 619 620 if (!userInt.getCurrentUser().isInAdministratorRole()) { 621 if (!oldUser.isUpdateableByUser() || (user.getId() != userInt.getCurrentUser().getId())) { 622 throw new UserManagementException("Updating the user " + user.getId() + " is not allowed for user " + userInt.getCurrentUser().getId()); 623 } 624 625 if (!oldUser.isConfirmed()) { 626 throw new UserManagementException("A non-confimred user cannot by changed by a non-Administrator."); 627 } 628 629 if (userInt.hasRoleChanges() || (user.getDefaultRole() == null && oldUser.getDefaultRole() != null) || (user.getDefaultRole() != null && user.getDefaultRole().getId() != oldUser.getDefaultRole().getId()) 630 || !user.getLogin().equals(oldUser.getLogin())) { 631 throw new UserManagementException("Changes to the roles or login of a user can only be done by an Administrator."); 632 } 633 } 634 635 String oldPassword; 636 stmt = conn.prepareStatement("select updatecount, password from users where id = ? " + jdbcHelper.getSharedLockClause()); 638 stmt.setLong(1, id); 639 ResultSet rs = stmt.executeQuery(); 640 if (!rs.next()) { 641 throw new UserManagementException("Unexpected error: the User with id " + id + " does not exist in the database."); 642 } else { 643 long dbUpdateCount = rs.getLong(1); 644 if (dbUpdateCount != user.getUpdateCount()) { 645 throw new UserManagementException("The User was concurrently changed."); 646 } 647 oldPassword = rs.getString(2); 648 } 649 stmt.close(); 650 651 if (!oldUser.getLogin().equals(user.getLogin())) { 652 stmt = conn.prepareStatement("select id from users where login = ?"); 655 stmt.setString(1, login); 656 ResultSet rs2 = stmt.executeQuery(); 657 if (rs2.next() && rs2.getLong(1) != user.getId()) 658 throw new DuplicateLoginException(login); 659 stmt.close(); 660 } 661 662 if (userInt.hasRoleChanges()) { 664 stmt = conn.prepareStatement("delete from user_roles where user_id=?"); 665 stmt.setLong(1, user.getId()); 666 667 stmt.executeUpdate(); 668 stmt.close(); 669 } 670 671 long newUpdateCount = user.getUpdateCount() + 1; 672 673 String password = null; 674 if (user.getAuthenticationScheme().equals("daisy")) { 675 password = userInt.getPassword() == null ? oldPassword: hashPassword(userInt.getPassword()); 676 if (password == null) 677 throw new UserManagementException("If the authentication scheme is daisy, then the password is required."); 678 } 679 680 stmt = conn.prepareStatement("update users set login=?, password=?, default_role=?, first_name=?, last_name=?, email=?, updateable_by_user=?, confirmed=?, confirmkey=?, auth_scheme=?, last_modified=?, last_modifier=?, updatecount=? where id=?"); 681 stmt.setString(1, login); 682 stmt.setString(2, password); 683 stmt.setLong(3, user.getDefaultRole() == null ? -1 : user.getDefaultRole().getId()); 684 stmt.setString(4, user.getFirstName()); 685 stmt.setString(5, user.getLastName()); 686 stmt.setString(6, user.getEmail()); 687 stmt.setBoolean(7, user.isUpdateableByUser()); 688 stmt.setBoolean(8, user.isConfirmed()); 689 stmt.setString(9, user.getConfirmKey()); 690 stmt.setString(10, user.getAuthenticationScheme()); 691 stmt.setTimestamp(11, new Timestamp(lastModified.getTime())); 692 stmt.setLong(12, lastModifier); 693 stmt.setLong(13, newUpdateCount); 694 stmt.setLong(14, user.getId()); 695 696 stmt.executeUpdate(); 697 storeRolesForUser(user, user.getId(), conn); 698 699 eventDescription = createUserUpdatedEvent(oldUser, user, lastModified, newUpdateCount); 700 } 701 702 eventHelper.createEvent(eventDescription, isNew ? "UserCreated" : "UserUpdated", conn); 703 704 conn.commit(); 706 userInt.saved(id, user.getFirstName(), user.getLastName(), user.getEmail(), lastModified, lastModifier, user.getUpdateCount() + 1); 707 708 } catch (Throwable e) { 709 jdbcHelper.rollback(conn); 710 if (e instanceof DuplicateLoginException) 711 throw (DuplicateLoginException)e; 712 else 713 throw new UserManagementException("Error storing user.", e); 714 } finally { 715 jdbcHelper.closeStatement(stmt); 716 jdbcHelper.closeConnection(conn); 717 } 718 719 if (isNew) 721 context.getCommonRepository().fireRepositoryEvent(RepositoryEventType.USER_CREATED, id, user.getUpdateCount()); 722 else 723 context.getCommonRepository().fireRepositoryEvent(RepositoryEventType.USER_UPDATED, id, user.getUpdateCount()); 724 } 725 726 public static String hashPassword(String password) { 727 if (password == null) 728 return null; 729 try { 730 byte[] data = password.getBytes("UTF-8"); 731 MessageDigest digest = MessageDigest.getInstance("SHA-1"); 732 digest.update(data); 733 byte[] result = digest.digest(); 734 return toHexString(result); 735 } catch (Exception e) { 736 throw new RuntimeException ("Problem calculating password hash.", e); 737 } 738 } 739 740 public static String toHexString(byte[] b) { 741 StringBuffer sb = new StringBuffer (b.length * 2); 742 for (int i = 0; i < b.length; i++) { 743 sb.append(hexChar[(b[i] & 0xf0) >>> 4]); 744 sb.append(hexChar[b[i] & 0x0f]); 745 } 746 return sb.toString(); 747 } 748 749 static char[] hexChar = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; 750 751 private UserCreatedDocument createUserCreatedEvent(UserImpl user, Date lastModified) { 752 UserDocument.User userXml = user.getXml().getUser(); 753 userXml.setLastModified(getCalendar(lastModified)); 754 userXml.setLastModifier(user.getIntimateAccess(this).getCurrentUser().getId()); 755 userXml.setUpdateCount(1); 756 if (userXml.isSetPassword()) 757 userXml.unsetPassword(); 758 759 UserCreatedDocument userCreatedDocument = UserCreatedDocument.Factory.newInstance(); 760 userCreatedDocument.addNewUserCreated().addNewNewUser().setUser(userXml); 761 762 return userCreatedDocument; 763 } 764 765 private UserUpdatedDocument createUserUpdatedEvent(UserImpl oldUser, UserImpl newUser, Date lastModified, long newUpdateCount) { 766 UserUpdatedDocument userUpdatedDocument = UserUpdatedDocument.Factory.newInstance(); 767 UserUpdatedDocument.UserUpdated userUpdated = userUpdatedDocument.addNewUserUpdated(); 768 769 UserDocument.User oldUserXml = oldUser.getXml().getUser(); 770 if (oldUserXml.isSetPassword()) 771 oldUserXml.unsetPassword(); 772 userUpdated.addNewOldUser().setUser(oldUserXml); 773 774 UserDocument.User newUserXml = newUser.getXml().getUser(); 775 newUserXml.setLastModified(getCalendar(lastModified)); 776 newUserXml.setLastModifier(newUser.getIntimateAccess(this).getCurrentUser().getId()); 777 newUserXml.setUpdateCount(newUpdateCount); 778 if (newUserXml.isSetPassword()) 779 newUserXml.unsetPassword(); 780 userUpdated.addNewNewUser().setUser(newUserXml); 781 782 return userUpdatedDocument; 783 } 784 785 private Calendar getCalendar(Date date) { 786 GregorianCalendar calendar = new GregorianCalendar(); 787 calendar.setTime(date); 788 return calendar; 789 } 790 791 795 private void storeRolesForUser(UserImpl user, long userId, Connection conn) throws SQLException { 796 logger.debug("ARRAY SIZE: "+user.getAllRoles().getArray().length); 797 UserImpl.IntimateAccess userInt = user.getIntimateAccess(this); 798 799 802 if (userInt.hasRoleChanges()) { 803 logger.debug("there are role changes"); 804 PreparedStatement delRoles = null; 805 PreparedStatement insertRoles = null; 806 try { 807 delRoles = conn.prepareStatement(DELETE_ROLES); 809 delRoles.setLong(1, userId); 810 delRoles.executeUpdate(); 811 812 insertRoles = conn.prepareStatement(INSERT_ROLES); 814 Role[] userRoles = user.getAllRoles().getArray(); 815 for (int i = 0; i < userRoles.length; i++) { 816 Role role = userRoles[i]; 817 insertRoles.setLong(1, role.getId()); 818 insertRoles.setLong(2, userId); 819 insertRoles.executeUpdate(); 820 } 821 } finally { 822 jdbcHelper.closeStatement(delRoles); 823 jdbcHelper.closeStatement(insertRoles); 824 } 825 } 826 } 827 828 public void store(RoleImpl role) throws UserManagementException { 829 830 RoleImpl.IntimateAccess roleInt = role.getIntimateAccess(this); 831 832 if (!roleInt.getCurrentUser().isInAdministratorRole()) 833 throw new UserManagementException("Only Administrators can create or update roles."); 834 835 long id = role.getId(); 836 boolean isNew = id == -1; 837 838 Connection conn = null; 839 PreparedStatement stmt = null; 840 try { 841 conn = context.getDataSource().getConnection(); 842 jdbcHelper.startTransaction(conn); 843 844 String roleName = role.getName(); 845 java.util.Date lastModified = new Date (); 846 847 850 long lastModifier = roleInt.getCurrentUser().getId(); 851 XmlObject eventDescription; 852 853 if (id == -1) { 854 stmt = conn.prepareStatement("insert into roles(id, \"name\", description, last_modified, last_modifier, updatecount) values (?,?,?,?,?,?)"); 856 id = context.getNextRoleId(); 857 stmt.setLong(1, id); 858 stmt.setString(2, roleName); 859 stmt.setString(3, role.getDescription()); 860 stmt.setTimestamp(4, new Timestamp(lastModified.getTime())); 861 stmt.setLong(5, lastModifier); 862 stmt.setLong(6, 1); 863 stmt.executeUpdate(); 864 865 eventDescription = createRoleCreatedEvent(role, lastModified); 866 } else { 867 869 stmt = conn.prepareStatement("select updatecount from roles where id = ? " + jdbcHelper.getSharedLockClause()); 871 stmt.setLong(1, id); 872 ResultSet rs = stmt.executeQuery(); 873 if (!rs.next()) { 874 throw new UserManagementException("Unexpected error: the Role with id " + id + " does not exist in the database."); 875 } else { 876 long dbUpdateCount = rs.getLong(1); 877 if (dbUpdateCount != role.getUpdateCount()) { 878 throw new UserManagementException("The role was concurrently changed by someone else."); 879 } 880 } 881 stmt.close(); 882 883 RoleImpl oldRole = getRole(role.getId(), roleInt.getCurrentUser()); 884 long newUpdateCount = role.getUpdateCount() + 1; 885 886 stmt = conn.prepareStatement("update roles set \"name\"=?, description=?, last_modified=?, last_modifier=?, updatecount=? where id=?"); 887 stmt.setString(1, roleName); 888 stmt.setString(2, role.getDescription()); 889 stmt.setTimestamp(3, new Timestamp(lastModified.getTime())); 890 stmt.setLong(4, lastModifier); 891 stmt.setLong(5, newUpdateCount); 892 stmt.setLong(6, id); 893 stmt.executeUpdate(); 894 895 eventDescription = createRoleUpdatedEvent(oldRole, role, lastModified, newUpdateCount); 896 } 897 898 eventHelper.createEvent(eventDescription, isNew ? "RoleCreated" : "RoleUpdated", conn); 899 900 conn.commit(); 901 902 roleInt.saved(id, roleName, role.getDescription(), role.getUpdateCount() + 1); 904 roleInt.setLastModified(lastModified); 905 roleInt.setLastModifier(lastModifier); 906 907 } catch (Throwable e) { 908 jdbcHelper.rollback(conn); 909 throw new UserManagementException("Error storing role.", e); 910 } finally { 911 jdbcHelper.closeStatement(stmt); 912 jdbcHelper.closeConnection(conn); 913 } 914 915 if (isNew) 917 context.getCommonRepository().fireRepositoryEvent(RepositoryEventType.ROLE_CREATED, id, role.getUpdateCount()); 918 else 919 context.getCommonRepository().fireRepositoryEvent(RepositoryEventType.ROLE_UPDATED, id, role.getUpdateCount()); 920 } 921 922 private RoleCreatedDocument createRoleCreatedEvent(RoleImpl role, Date lastModified) { 923 RoleCreatedDocument roleCreatedDocument = RoleCreatedDocument.Factory.newInstance(); 924 925 RoleDocument.Role roleXml = role.getXml().getRole(); 926 roleXml.setLastModified(getCalendar(lastModified)); 927 roleXml.setLastModifier(role.getIntimateAccess(this).getCurrentUser().getId()); 928 roleXml.setUpdateCount(1); 929 930 roleCreatedDocument.addNewRoleCreated().addNewNewRole().setRole(roleXml); 931 932 return roleCreatedDocument; 933 } 934 935 private RoleUpdatedDocument createRoleUpdatedEvent(RoleImpl oldRole, RoleImpl newRole, Date lastModified, long newUpdateCount) { 936 RoleUpdatedDocument roleUpdatedDocument = RoleUpdatedDocument.Factory.newInstance(); 937 RoleUpdatedDocument.RoleUpdated roleUpdated = roleUpdatedDocument.addNewRoleUpdated(); 938 roleUpdated.addNewOldRole().setRole(oldRole.getXml().getRole()); 939 940 RoleDocument.Role newRoleXml = newRole.getXml().getRole(); 941 newRoleXml.setLastModified(getCalendar(lastModified)); 942 newRoleXml.setLastModifier(newRole.getIntimateAccess(this).getCurrentUser().getId()); 943 newRoleXml.setUpdateCount(newUpdateCount); 944 945 roleUpdated.addNewNewRole().setRole(newRoleXml); 946 947 return roleUpdatedDocument; 948 } 949 950 public UserImpl getUser(long userId, AuthenticatedUser requestingUser) throws UserManagementException { 951 if (userId != requestingUser.getId() && !requestingUser.isInAdministratorRole()) 952 throw new UserManagementException("Non-Administrator users can only access their own user record."); 953 954 Connection conn = null; 955 PreparedStatement stmt = null; 956 UserImpl user = null; 957 958 try { 959 conn = context.getDataSource().getConnection(); 960 stmt = conn.prepareStatement(SELECT_USER_WHERE_ID); 961 stmt.setLong(1, userId); 962 ResultSet rs = stmt.executeQuery(); 963 964 if (rs.next()) { 965 user = getUserFromResultSet(rs, requestingUser); 966 } else { 967 throw new UserNotFoundException(userId); 968 } 969 970 rs.close(); 971 } catch (Exception e) { 972 if (e instanceof UserManagementException) 973 throw (UserManagementException)e; 974 else 975 throw new UserManagementException("Error while loading user with id "+userId+".", e); 976 } finally { 977 jdbcHelper.closeStatement(stmt); 978 jdbcHelper.closeConnection(conn); 979 } 980 return user; 981 } 982 983 public RoleImpl getRole(long roleId, AuthenticatedUser requestingUser) throws UserManagementException { 984 Connection conn = null; 985 PreparedStatement stmt = null; 986 RoleImpl role = null; 987 988 try { 989 conn = context.getDataSource().getConnection(); 990 stmt = conn.prepareStatement(SELECT_ROLE_WHERE_ID); 991 stmt.setLong(1, roleId); 992 ResultSet rs = stmt.executeQuery(); 993 994 if (rs.next()) { 995 long id = rs.getLong(1); 996 String name = rs.getString(2); 997 String description = rs.getString(3); 998 Date lastModified = rs.getTimestamp(4); 999 long lastModifier = rs.getLong(5); 1000 long updateCount = rs.getLong(6); 1001 1002 role = new RoleImpl(this, name, requestingUser); 1003 RoleImpl.IntimateAccess roleInt = role.getIntimateAccess(this); 1004 roleInt.saved(id, name, description, updateCount); 1005 roleInt.setLastModified(lastModified); 1006 roleInt.setLastModifier(lastModifier); 1007 1008 } else { 1009 throw new RoleNotFoundException(roleId); 1010 } 1011 rs.close(); 1012 } catch (Exception e) { 1013 if (e instanceof UserManagementException) 1014 throw (UserManagementException)e; 1015 else 1016 throw new UserManagementException("Error while loading role with id "+roleId+".", e); 1017 } finally { 1018 jdbcHelper.closeStatement(stmt); 1019 jdbcHelper.closeConnection(conn); 1020 } 1021 1022 return role; 1023 } 1024 1025 public UsersImpl getUsersByEmail(String email, AuthenticatedUser requestingUser) throws RepositoryException { 1026 if (!requestingUser.isInAdministratorRole()) 1027 throw new UserManagementException("Non-Administrator users cannot retrieve other users then themselve."); 1028 1029 Connection conn = null; 1030 PreparedStatement stmt = null; 1031 ArrayList users = new ArrayList(); 1032 1033 try { 1034 conn = context.getDataSource().getConnection(); 1035 1036 stmt = conn.prepareStatement(SELECT_USERS_WHERE_EMAIL); 1037 stmt.setString(1, email); 1038 ResultSet rs = stmt.executeQuery(); 1039 1040 while (rs.next()) { 1041 UserImpl user = getUserFromResultSet(rs, requestingUser); 1042 users.add(user); 1043 } 1044 } catch (Exception e) { 1045 throw new UserManagementException("Error while loading list of users by email.", e); 1046 } finally { 1047 jdbcHelper.closeStatement(stmt); 1048 jdbcHelper.closeConnection(conn); 1049 } 1050 1051 return new UsersImpl((User[])users.toArray(new User[users.size()])); 1052 } 1053 1054 public AuthenticationSchemeInfos getAuthenticationSchemes(AuthenticatedUser requestingUser) { 1055 return context.getUserAuthenticator().getAuthenticationSchemes(); 1056 } 1057} 1058 | Popular Tags |