001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software GmbH, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.file; 029 030import org.opencms.db.CmsUserSettings; 031import org.opencms.main.CmsException; 032import org.opencms.main.CmsIllegalArgumentException; 033import org.opencms.main.OpenCms; 034import org.opencms.security.CmsPrincipal; 035import org.opencms.security.CmsSecurityException; 036import org.opencms.security.I_CmsPrincipal; 037import org.opencms.util.CmsMacroResolver; 038import org.opencms.util.CmsStringUtil; 039import org.opencms.util.CmsUUID; 040 041import java.util.Collections; 042import java.util.HashMap; 043import java.util.Locale; 044import java.util.Map; 045 046/** 047 * A user principal in the OpenCms permission system.<p> 048 * 049 * A user in OpenCms is uniquely defined by its user named returned by 050 * <code>{@link #getName()}</code>.<p> 051 * 052 * Basic users in OpenCms are users that can access the OpenCms Workplace. 053 * Moreover, the user must be created by another user with the 054 * <code>{@link org.opencms.security.CmsRole#ACCOUNT_MANAGER}</code> role. 055 * These users are "content managers" that actually have write permissions in 056 * at last some parts of the VFS.<p> 057 * 058 * Another possibility is to have users in a 'Guests' group. 059 * These users do not have access to the OpenCms Workplace. 060 * However, an user in a 'Guests' group can be created by every user, for example 061 * the "Guest" user. The main use case is that these users are used for users of 062 * the website that can generate their own accounts, in a "please register your 063 * account..." scenario. 064 * These user accounts can then be used to build personalized web sites.<p> 065 * 066 * @since 6.0.0 067 * 068 * @see CmsGroup 069 */ 070public class CmsUser extends CmsPrincipal implements Cloneable { 071 072 /** Storage for additional user information. */ 073 private Map<String, Object> m_additionalInfo; 074 075 /** The creation date. */ 076 private long m_dateCreated; 077 078 /** The email of the user. */ 079 private String m_email; 080 081 /** The first name of this user. */ 082 private String m_firstname; 083 084 /** Boolean flag whether the last-login time stamp of this user was modified. */ 085 private boolean m_isTouched; 086 087 /** The last login date of this user. */ 088 private long m_lastlogin; 089 090 /** The last name of this user. */ 091 private String m_lastname; 092 093 /** The password of this user. */ 094 private String m_password; 095 096 /** 097 * Creates a new, empty OpenCms user principal.<p> 098 * 099 * Mostly intended to be used with the <code>org.opencms.workplace.tools.accounts.A_CmsEditUserDialog</code>.<p> 100 */ 101 public CmsUser() { 102 103 this( 104 null, 105 "", 106 "", 107 "", 108 "", 109 "", 110 0, 111 I_CmsPrincipal.FLAG_ENABLED, 112 System.currentTimeMillis(), 113 Collections.singletonMap(CmsUserSettings.ADDITIONAL_INFO_DESCRIPTION, (Object)"")); 114 } 115 116 /** 117 * Creates a new OpenCms user principal.<p> 118 * 119 * @param id the unique id of the new user 120 * @param name the fully qualified name of the new user 121 * @param password the password of the user 122 * @param firstname the first name 123 * @param lastname the last name 124 * @param email the email address 125 * @param lastlogin time stamp 126 * @param flags flags 127 * @param dateCreated the creation date 128 * @param additionalInfo user related information 129 */ 130 public CmsUser( 131 CmsUUID id, 132 String name, 133 String password, 134 String firstname, 135 String lastname, 136 String email, 137 long lastlogin, 138 int flags, 139 long dateCreated, 140 Map<String, Object> additionalInfo) { 141 142 m_id = id; 143 m_name = name; 144 m_password = password; 145 m_firstname = firstname; 146 m_lastname = lastname; 147 m_email = email; 148 m_lastlogin = lastlogin; 149 m_flags = flags; 150 m_dateCreated = dateCreated; 151 if (additionalInfo != null) { 152 m_additionalInfo = new HashMap<String, Object>(additionalInfo); 153 } else { 154 m_additionalInfo = new HashMap<String, Object>(); 155 } 156 if (m_additionalInfo.get(CmsUserSettings.ADDITIONAL_INFO_ADDRESS) == null) { 157 m_additionalInfo.put(CmsUserSettings.ADDITIONAL_INFO_ADDRESS, ""); 158 } 159 if (m_additionalInfo.get(CmsUserSettings.ADDITIONAL_INFO_DESCRIPTION) == null) { 160 m_additionalInfo.put(CmsUserSettings.ADDITIONAL_INFO_DESCRIPTION, ""); 161 } 162 } 163 164 /** 165 * Validates an email address.<p> 166 * 167 * That means, the parameter should only be composed by digits and standard english letters, points, underscores and exact one "At" symbol.<p> 168 * 169 * @param email the email to validate 170 */ 171 public static void checkEmail(String email) { 172 173 OpenCms.getValidationHandler().checkEmail(email); 174 } 175 176 /** 177 * Validates a zip code.<p> 178 * 179 * That means, the parameter should only be composed by digits and standard english letters.<p> 180 * 181 * @param zipcode the zip code to validate 182 */ 183 public static void checkZipCode(String zipcode) { 184 185 OpenCms.getValidationHandler().checkZipCode(zipcode); 186 } 187 188 /** 189 * Returns the "full" name of the given user in the format <code>"{firstname} {lastname} ({username})"</code>, 190 * or the empty String <code>""</code> if the user is null.<p> 191 * 192 * @param user the user to get the full name from 193 * @return the "full" name the user 194 * 195 * @see #getFullName() 196 */ 197 public static String getFullName(CmsUser user) { 198 199 if (user == null) { 200 return ""; 201 } else { 202 return user.getFullName(); 203 } 204 } 205 206 /** 207 * Checks if the given String starts with {@link I_CmsPrincipal#PRINCIPAL_USER} followed by a dot.<p> 208 * 209 * <ul> 210 * <li>Works if the given String is <code>null</code>. 211 * <li>Removes white spaces around the String before the check. 212 * <li>Also works with prefixes not being in upper case. 213 * <li>Does not check if the user after the prefix actually exists. 214 * </ul> 215 * 216 * @param principalName the user name to check 217 * 218 * @return <code>true</code> in case the String starts with {@link I_CmsPrincipal#PRINCIPAL_USER} followed by a dot 219 */ 220 public static boolean hasPrefix(String principalName) { 221 222 return CmsStringUtil.isNotEmptyOrWhitespaceOnly(principalName) 223 && (principalName.trim().toUpperCase().startsWith(I_CmsPrincipal.PRINCIPAL_USER + ".")); 224 } 225 226 /** 227 * Removes the prefix if the given String starts with {@link I_CmsPrincipal#PRINCIPAL_USER} followed by a dot.<p> 228 * 229 * <ul> 230 * <li>Works if the given String is <code>null</code>. 231 * <li>If the given String does not start with {@link I_CmsPrincipal#PRINCIPAL_USER} followed by a dot it is returned unchanged. 232 * <li>Removes white spaces around the user name. 233 * <li>Also works with prefixes not being in upper case. 234 * <li>Does not check if the user after the prefix actually exists. 235 * </ul> 236 * 237 * @param principalName the user name to remove the prefix from 238 * 239 * @return the given String with the prefix {@link I_CmsPrincipal#PRINCIPAL_USER} and the following dot removed 240 */ 241 public static String removePrefix(String principalName) { 242 243 String result = principalName; 244 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(principalName)) { 245 if (hasPrefix(principalName)) { 246 result = principalName.trim().substring(I_CmsPrincipal.PRINCIPAL_USER.length() + 1); 247 } 248 } 249 return result; 250 } 251 252 /** 253 * Checks if the provided user name is a valid user name and can be used as an argument value 254 * for {@link #setName(String)}.<p> 255 * 256 * @param name the user name to check 257 * 258 * @throws CmsIllegalArgumentException if the check fails 259 */ 260 public void checkName(String name) throws CmsIllegalArgumentException { 261 262 OpenCms.getValidationHandler().checkUserName(name); 263 } 264 265 /** 266 * @see java.lang.Object#clone() 267 */ 268 @Override 269 public Object clone() { 270 271 return new CmsUser( 272 m_id, 273 m_name, 274 m_password, 275 m_firstname, 276 m_lastname, 277 m_email, 278 m_lastlogin, 279 m_flags, 280 m_dateCreated, 281 m_additionalInfo); 282 } 283 284 /** 285 * Deletes a value from this users "additional information" storage map.<p> 286 * 287 * @param key the additional user information to delete 288 * 289 * @see #getAdditionalInfo() 290 */ 291 public void deleteAdditionalInfo(String key) { 292 293 m_additionalInfo.remove(key); 294 } 295 296 /** 297 * Returns this users complete "additional information" storage map.<p> 298 * 299 * The "additional information" storage map is a simple {@link java.util.Map} 300 * that can be used to store any key / value pairs for the user. 301 * Some information parts of the users address are stored in this map 302 * by default.<p> 303 * 304 * @return this users complete "additional information" storage map 305 */ 306 public Map<String, Object> getAdditionalInfo() { 307 308 return m_additionalInfo; 309 } 310 311 /** 312 * Returns a value from this users "additional information" storage map, 313 * or <code>null</code> if no value for the given key is available.<p> 314 * 315 * @param key selects the value to return from the "additional information" storage map 316 * 317 * @return the selected value from this users "additional information" storage map 318 * 319 * @see #getAdditionalInfo() 320 */ 321 public Object getAdditionalInfo(String key) { 322 323 return m_additionalInfo.get(key); 324 } 325 326 /** 327 * Returns the address line of this user.<p> 328 * 329 * @return the address line of this user 330 */ 331 public String getAddress() { 332 333 return (String)getAdditionalInfo(CmsUserSettings.ADDITIONAL_INFO_ADDRESS); 334 } 335 336 /** 337 * Returns the city information of this user.<p> 338 * 339 * This information is stored in the "additional information" storage map 340 * using the key <code>{@link CmsUserSettings#ADDITIONAL_INFO_CITY}</code>.<p> 341 * 342 * @return the city information of this user 343 */ 344 public String getCity() { 345 346 return (String)getAdditionalInfo(CmsUserSettings.ADDITIONAL_INFO_CITY); 347 } 348 349 /** 350 * Returns the country information of this user.<p> 351 * 352 * This information is stored in the "additional information" storage map 353 * using the key <code>{@link CmsUserSettings#ADDITIONAL_INFO_COUNTRY}</code>.<p> 354 * 355 * @return the country information of this user 356 */ 357 public String getCountry() { 358 359 return (String)getAdditionalInfo(CmsUserSettings.ADDITIONAL_INFO_COUNTRY); 360 } 361 362 /** 363 * Returns the creation date.<p> 364 * 365 * @return the creation date 366 */ 367 public long getDateCreated() { 368 369 return m_dateCreated; 370 } 371 372 /** 373 * @see org.opencms.security.CmsPrincipal#getDescription() 374 */ 375 @Override 376 public String getDescription() { 377 378 return (String)getAdditionalInfo(CmsUserSettings.ADDITIONAL_INFO_DESCRIPTION); 379 } 380 381 /** 382 * Returns the description of this organizational unit.<p> 383 * 384 * @param locale the locale 385 * 386 * @return the description of this organizational unit 387 */ 388 public String getDescription(Locale locale) { 389 390 CmsMacroResolver macroResolver = new CmsMacroResolver(); 391 macroResolver.setMessages(org.opencms.db.generic.Messages.get().getBundle(locale)); 392 return macroResolver.resolveMacros((String)getAdditionalInfo(CmsUserSettings.ADDITIONAL_INFO_DESCRIPTION)); 393 } 394 395 /** 396 * @see org.opencms.security.CmsPrincipal#getDisplayName(org.opencms.file.CmsObject, java.util.Locale) 397 */ 398 @Override 399 public String getDisplayName(CmsObject cms, Locale locale) throws CmsException { 400 401 if (OpenCms.getOrgUnitManager().getOrganizationalUnits(cms, "", true).size() > 0) { 402 return org.opencms.security.Messages.get().getBundle(locale).key( 403 org.opencms.security.Messages.GUI_PRINCIPAL_DISPLAY_NAME_2, 404 getFullName(), 405 OpenCms.getOrgUnitManager().readOrganizationalUnit(cms, getOuFqn()).getDisplayName(locale)); 406 } else { 407 return getFullName(); 408 } 409 } 410 411 /** 412 * Returns the email address of this user.<p> 413 * 414 * @return the email address of this user 415 */ 416 public String getEmail() { 417 418 return m_email; 419 } 420 421 /** 422 * Returns the first name of this user.<p> 423 * 424 * @return the first name of this user 425 */ 426 public String getFirstname() { 427 428 return m_firstname; 429 } 430 431 /** 432 * Returns the "full" name of the this user in the format <code>"{firstname} {lastname} ({username})"</code>.<p> 433 * 434 * @return the "full" name this user 435 */ 436 public String getFullName() { 437 438 StringBuffer buf = new StringBuffer(); 439 String first = getFirstname(); 440 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(first)) { 441 buf.append(first); 442 buf.append(" "); 443 } 444 String last = getLastname(); 445 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(last)) { 446 buf.append(last); 447 buf.append(" "); 448 } 449 buf.append("("); 450 buf.append(getSimpleName()); 451 buf.append(")"); 452 return buf.toString(); 453 } 454 455 /** 456 * Returns the institution information of this user.<p> 457 * 458 * This information is stored in the "additional information" storage map 459 * using the key <code>{@link CmsUserSettings#ADDITIONAL_INFO_INSTITUTION}</code>.<p> 460 * 461 * @return the institution information of this user 462 */ 463 public String getInstitution() { 464 465 return (String)getAdditionalInfo(CmsUserSettings.ADDITIONAL_INFO_INSTITUTION); 466 } 467 468 /** 469 * Returns the time of the last login of this user.<p> 470 * 471 * @return the time of the last login of this user 472 */ 473 public long getLastlogin() { 474 475 return m_lastlogin; 476 } 477 478 /** 479 * Returns the last name of this user.<p> 480 * 481 * @return the last name of this user 482 */ 483 public String getLastname() { 484 485 return m_lastname; 486 } 487 488 /** 489 * Returns the encrypted user password.<p> 490 * 491 * @return the encrypted user password 492 */ 493 public String getPassword() { 494 495 return m_password; 496 } 497 498 /** 499 * Returns the zip code information of this user.<p> 500 * 501 * This information is stored in the "additional information" storage map 502 * using the key <code>{@link CmsUserSettings#ADDITIONAL_INFO_ZIPCODE}</code>.<p> 503 * 504 * @return the zip code information of this user 505 */ 506 public String getZipcode() { 507 508 return (String)getAdditionalInfo(CmsUserSettings.ADDITIONAL_INFO_ZIPCODE); 509 } 510 511 /** 512 * @see org.opencms.security.I_CmsPrincipal#isGroup() 513 */ 514 @Override 515 public boolean isGroup() { 516 517 return false; 518 } 519 520 /** 521 * Checks if this user is the default guest user.<p> 522 * 523 * @return <code>true</code> if this user is the default guest user 524 */ 525 public boolean isGuestUser() { 526 527 return OpenCms.getDefaultUsers().isUserGuest(getName()); 528 } 529 530 /** 531 * Returns <code>true</code> if this user is not able to manage itself.<p> 532 * 533 * @return <code>true</code> if this user is not able to manage itself 534 */ 535 public boolean isManaged() { 536 537 return (getFlags() & I_CmsPrincipal.FLAG_USER_MANAGED) == I_CmsPrincipal.FLAG_USER_MANAGED; 538 } 539 540 /** 541 * Returns <code>true</code> if this user was touched.<p> 542 * 543 * @return boolean true if this user was touched 544 */ 545 public boolean isTouched() { 546 547 return m_isTouched; 548 } 549 550 /** 551 * @see org.opencms.security.I_CmsPrincipal#isUser() 552 */ 553 @Override 554 public boolean isUser() { 555 556 return true; 557 } 558 559 /** 560 * Checks if the user is marked as webuser.<p> 561 * 562 * @return <code>true</code> if the user is marked as webuser 563 */ 564 public boolean isWebuser() { 565 566 return (getFlags() & FLAG_USER_WEBUSER) == FLAG_USER_WEBUSER; 567 } 568 569 /** 570 * Sets this users complete "additional information" storage map to the given value.<p> 571 * 572 * @param additionalInfo the complete "additional information" map to set 573 * 574 * @see #getAdditionalInfo() 575 */ 576 public void setAdditionalInfo(Map<String, Object> additionalInfo) { 577 578 m_additionalInfo = additionalInfo; 579 } 580 581 /** 582 * Stores a value in this users "additional information" storage map with the given access key.<p> 583 * 584 * @param key the key to store the value under 585 * @param value the value to store in the users "additional information" storage map 586 * 587 * @see #getAdditionalInfo() 588 */ 589 public void setAdditionalInfo(String key, Object value) { 590 591 if (key == null) { 592 throw new CmsIllegalArgumentException( 593 Messages.get().container(Messages.ERR_USER_ADDINFO_KEY_NULL_1, getFullName())); 594 } 595 m_additionalInfo.put(key, value); 596 } 597 598 /** 599 * Sets the address line of this user.<p> 600 * 601 * @param address the address line to set 602 */ 603 public void setAddress(String address) { 604 605 setAdditionalInfo(CmsUserSettings.ADDITIONAL_INFO_ADDRESS, address); 606 } 607 608 /** 609 * Sets the city information of this user.<p> 610 * 611 * @param city the city information to set 612 */ 613 public void setCity(String city) { 614 615 setAdditionalInfo(CmsUserSettings.ADDITIONAL_INFO_CITY, city); 616 } 617 618 /** 619 * Sets the country information of this user.<p> 620 * 621 * @param country the city information to set 622 */ 623 public void setCountry(String country) { 624 625 setAdditionalInfo(CmsUserSettings.ADDITIONAL_INFO_COUNTRY, country); 626 } 627 628 /** 629 * @see org.opencms.security.CmsPrincipal#setDescription(java.lang.String) 630 */ 631 @Override 632 public void setDescription(String description) { 633 634 setAdditionalInfo(CmsUserSettings.ADDITIONAL_INFO_DESCRIPTION, description); 635 } 636 637 /** 638 * Sets the email address of this user.<p> 639 * 640 * @param email the email address to set 641 */ 642 public void setEmail(String email) { 643 644 checkEmail(email); 645 if (email != null) { 646 email = email.trim(); 647 } 648 m_email = email; 649 } 650 651 /** 652 * Sets the first name of this user.<p> 653 * 654 * @param firstname the name to set 655 */ 656 public void setFirstname(String firstname) { 657 658 OpenCms.getValidationHandler().checkFirstname(firstname); 659 if (firstname != null) { 660 firstname = firstname.trim(); 661 } 662 m_firstname = firstname; 663 } 664 665 /** 666 * Sets the institution information of this user.<p> 667 * 668 * @param institution the institution information to set 669 */ 670 public void setInstitution(String institution) { 671 672 setAdditionalInfo(CmsUserSettings.ADDITIONAL_INFO_INSTITUTION, institution); 673 } 674 675 /** 676 * Sets the last login time stamp of this user.<p> 677 * 678 * @param value the last login time stamp to set 679 */ 680 public void setLastlogin(long value) { 681 682 m_isTouched = true; 683 m_lastlogin = value; 684 } 685 686 /** 687 * Sets the last name of this user.<p> 688 * 689 * @param lastname the name to set 690 */ 691 public void setLastname(String lastname) { 692 693 OpenCms.getValidationHandler().checkLastname(lastname); 694 if (lastname != null) { 695 lastname = lastname.trim(); 696 } 697 m_lastname = lastname; 698 } 699 700 /** 701 * Sets the managed flag for this user to the given value.<p> 702 * 703 * @param value the value to set 704 */ 705 public void setManaged(boolean value) { 706 707 if (isManaged() != value) { 708 setFlags(getFlags() ^ I_CmsPrincipal.FLAG_USER_MANAGED); 709 } 710 } 711 712 /** 713 * Sets the password of this user.<p> 714 * 715 * @param value the password to set 716 */ 717 public void setPassword(String value) { 718 719 try { 720 OpenCms.getPasswordHandler().validatePassword(value); 721 } catch (CmsSecurityException e) { 722 throw new CmsIllegalArgumentException(e.getMessageContainer()); 723 } 724 m_password = value; 725 } 726 727 /** 728 * Sets the zip code information of this user.<p> 729 * 730 * @param zipcode the zip code information to set 731 */ 732 public void setZipcode(String zipcode) { 733 734 checkZipCode(zipcode); 735 if (zipcode != null) { 736 zipcode = zipcode.toUpperCase(); 737 } 738 setAdditionalInfo(CmsUserSettings.ADDITIONAL_INFO_ZIPCODE, zipcode); 739 } 740 741 /** 742 * @see java.lang.Object#toString() 743 */ 744 @Override 745 public String toString() { 746 747 StringBuffer result = new StringBuffer(); 748 result.append("[User]"); 749 result.append(" name:"); 750 result.append(getName()); 751 result.append(" id:"); 752 result.append(m_id); 753 result.append(" flags:"); 754 result.append(getFlags()); 755 result.append(" description:"); 756 result.append(getDescription()); 757 return result.toString(); 758 } 759 760 /** 761 * Sets the "touched" status of this user to <code>true</code>.<p> 762 */ 763 public void touch() { 764 765 m_isTouched = true; 766 } 767}