001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (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, 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.security; 029 030import org.opencms.db.CmsDbEntryNotFoundException; 031import org.opencms.file.CmsGroup; 032import org.opencms.file.CmsObject; 033import org.opencms.file.CmsUser; 034import org.opencms.main.CmsException; 035import org.opencms.main.OpenCms; 036import org.opencms.util.CmsStringUtil; 037import org.opencms.util.CmsUUID; 038import org.opencms.workplace.I_CmsGroupNameTranslation; 039 040import java.util.Iterator; 041import java.util.List; 042import java.util.Locale; 043 044/** 045 * Common methods shared among user and group principals, 046 * also contains several utility functions to deal with principal instances.<p> 047 * 048 * @since 6.2.0 049 */ 050public abstract class CmsPrincipal implements I_CmsPrincipal, Comparable<I_CmsPrincipal> { 051 052 /** The serial version id. */ 053 private static final long serialVersionUID = -323281048875786320L; 054 055 /** The description of this principal. */ 056 protected String m_description; 057 058 /** The flags of this principal. */ 059 protected int m_flags; 060 061 /** The unique id of this principal. */ 062 protected CmsUUID m_id; 063 064 /** The fully qualified name of this principal. */ 065 protected String m_name; 066 067 /** 068 * Empty constructor for subclassing.<p> 069 */ 070 protected CmsPrincipal() { 071 072 // empty constructor for subclassing 073 } 074 075 /** 076 * Filters out all principals that do not have the given flag set, 077 * but leaving principals with flags less than <code>{@link I_CmsPrincipal#FLAG_CORE_LIMIT}</code> untouched.<p> 078 * 079 * The given parameter list is directly modified, so the returned list is the same object as the input list.<p> 080 * 081 * @param principals a list of <code>{@link CmsPrincipal}</code> objects 082 * @param flag the flag for filtering 083 * 084 * @return the filtered principal list 085 */ 086 public static List<? extends CmsPrincipal> filterCoreFlag(List<? extends CmsPrincipal> principals, int flag) { 087 088 Iterator<? extends CmsPrincipal> it = principals.iterator(); 089 while (it.hasNext()) { 090 CmsPrincipal p = it.next(); 091 if ((p.getFlags() > I_CmsPrincipal.FLAG_CORE_LIMIT) && ((p.getFlags() & flag) != flag)) { 092 it.remove(); 093 } 094 } 095 return principals; 096 } 097 098 /** 099 * Filters out all groups with flags greater than <code>{@link I_CmsPrincipal#FLAG_CORE_LIMIT}</code>.<p> 100 * 101 * The given parameter list is directly modified, so the returned list is the same object as the input list.<p> 102 * 103 * @param groups a list of <code>{@link CmsGroup}</code> objects 104 * 105 * @return the filtered principal list 106 */ 107 public static List<CmsGroup> filterCoreGroups(List<CmsGroup> groups) { 108 109 Iterator<CmsGroup> it = groups.iterator(); 110 while (it.hasNext()) { 111 CmsGroup p = it.next(); 112 if (p.getFlags() > I_CmsPrincipal.FLAG_CORE_LIMIT) { 113 it.remove(); 114 } 115 } 116 return groups; 117 } 118 119 /** 120 * Filters out all users with flags greater than <code>{@link I_CmsPrincipal#FLAG_CORE_LIMIT}</code>.<p> 121 * 122 * The given parameter list is directly modified, so the returned list is the same object as the input list.<p> 123 * 124 * @param users a list of <code>{@link CmsUser}</code> objects 125 * 126 * @return the filtered principal list 127 */ 128 public static List<CmsUser> filterCoreUsers(List<CmsUser> users) { 129 130 Iterator<CmsUser> it = users.iterator(); 131 while (it.hasNext()) { 132 I_CmsPrincipal p = it.next(); 133 if (p.getFlags() > I_CmsPrincipal.FLAG_CORE_LIMIT) { 134 it.remove(); 135 } 136 } 137 return users; 138 } 139 140 /** 141 * Filters out all principals that do not have the given flag set.<p> 142 * 143 * The given parameter list is directly modified, so the returned list is the same object as the input list.<p> 144 * 145 * @param principals the list of <code>{@link CmsPrincipal}</code> objects 146 * @param flag the flag for filtering 147 * 148 * @return the filtered principal list 149 */ 150 public static List<? extends CmsPrincipal> filterFlag(List<? extends CmsPrincipal> principals, int flag) { 151 152 Iterator<? extends CmsPrincipal> it = principals.iterator(); 153 while (it.hasNext()) { 154 CmsPrincipal p = it.next(); 155 if ((p.getFlags() & flag) != flag) { 156 it.remove(); 157 } 158 } 159 return principals; 160 } 161 162 /** 163 * Returns the provided group name prefixed with <code>{@link I_CmsPrincipal#PRINCIPAL_GROUP}.</code>.<p> 164 * 165 * @param name the name to add the prefix to 166 * @return the provided group name prefixed with <code>{@link I_CmsPrincipal#PRINCIPAL_GROUP}.</code> 167 */ 168 public static String getPrefixedGroup(String name) { 169 170 StringBuffer result = new StringBuffer(name.length() + 10); 171 result.append(I_CmsPrincipal.PRINCIPAL_GROUP); 172 result.append('.'); 173 result.append(name); 174 return result.toString(); 175 } 176 177 /** 178 * Returns the provided user name prefixed with <code>{@link I_CmsPrincipal#PRINCIPAL_USER}.</code>.<p> 179 * 180 * @param name the name to add the prefix to 181 * @return the provided user name prefixed with <code>{@link I_CmsPrincipal#PRINCIPAL_USER}.</code> 182 */ 183 public static String getPrefixedUser(String name) { 184 185 StringBuffer result = new StringBuffer(name.length() + 10); 186 result.append(I_CmsPrincipal.PRINCIPAL_USER); 187 result.append('.'); 188 result.append(name); 189 return result.toString(); 190 } 191 192 /** 193 * Gets the type of a principal.<p> 194 * 195 * @param principal the principal 196 * @return the principal type 197 */ 198 public static String getType(I_CmsPrincipal principal) { 199 200 if (principal == null) { 201 return null; 202 } 203 if (principal instanceof CmsRoleAsPrincipal) { 204 return CmsRole.PRINCIPAL_ROLE; 205 } else if (principal.isGroup()) { 206 return I_CmsPrincipal.PRINCIPAL_GROUP; 207 } else { 208 return I_CmsPrincipal.PRINCIPAL_USER; 209 } 210 } 211 212 /** 213 * Utility function to read a prefixed principal from the OpenCms database using the 214 * provided OpenCms user context.<p> 215 * 216 * The principal must be either prefixed with <code>{@link I_CmsPrincipal#PRINCIPAL_GROUP}.</code> or 217 * <code>{@link I_CmsPrincipal#PRINCIPAL_USER}.</code>.<p> 218 * 219 * @param cms the OpenCms user context to use when reading the principal 220 * @param name the prefixed principal name 221 * 222 * @return the principal read from the OpenCms database 223 * 224 * @throws CmsException in case the principal could not be read 225 */ 226 public static I_CmsPrincipal readPrefixedPrincipal(CmsObject cms, String name) throws CmsException { 227 228 if (CmsGroup.hasPrefix(name)) { 229 // this principal is a group 230 return cms.readGroup(CmsGroup.removePrefix(name)); 231 } else if (CmsUser.hasPrefix(name)) { 232 // this principal is a user 233 return cms.readUser(CmsUser.removePrefix(name)); 234 } 235 // invalid principal name was given 236 throw new CmsDbEntryNotFoundException(Messages.get().container(Messages.ERR_INVALID_PRINCIPAL_1, name)); 237 } 238 239 /** 240 * Utility function to read a principal by its id from the OpenCms database using the 241 * provided OpenCms user context.<p> 242 * 243 * @param cms the OpenCms user context to use when reading the principal 244 * @param id the id of the principal to read 245 * 246 * @return the principal read from the OpenCms database 247 * 248 * @throws CmsException in case the principal could not be read 249 */ 250 public static I_CmsPrincipal readPrincipal(CmsObject cms, CmsUUID id) throws CmsException { 251 252 try { 253 // first try to read the principal as a user 254 return cms.readUser(id); 255 } catch (CmsException exc) { 256 // assume user does not exist 257 } 258 try { 259 // now try to read the principal as a group 260 return cms.readGroup(id); 261 } catch (CmsException exc) { 262 // assume group does not exist 263 } 264 // invalid principal name was given 265 throw new CmsDbEntryNotFoundException(Messages.get().container(Messages.ERR_INVALID_PRINCIPAL_1, id)); 266 } 267 268 /** 269 * Utility function to read a principal by its id from the OpenCms database using the 270 * provided OpenCms user context.<p> 271 * 272 * @param cms the OpenCms user context to use when reading the principal 273 * @param name the name of the principal to read 274 * 275 * @return the principal read from the OpenCms database 276 * 277 * @throws CmsException in case the principal could not be read 278 */ 279 public static I_CmsPrincipal readPrincipal(CmsObject cms, String name) throws CmsException { 280 281 try { 282 // first try to read the principal as a user 283 return cms.readUser(name); 284 } catch (CmsException exc) { 285 // assume user does not exist 286 } 287 try { 288 // now try to read the principal as a group 289 return cms.readGroup(name); 290 } catch (CmsException exc) { 291 // assume group does not exist 292 } 293 // invalid principal name was given 294 throw new CmsDbEntryNotFoundException(Messages.get().container(Messages.ERR_INVALID_PRINCIPAL_1, name)); 295 } 296 297 /** 298 * Utility function to read a principal of the given type from the OpenCms database using the 299 * provided OpenCms user context.<p> 300 * 301 * The type must either be <code>{@link I_CmsPrincipal#PRINCIPAL_GROUP}</code> or 302 * <code>{@link I_CmsPrincipal#PRINCIPAL_USER}</code>.<p> 303 * 304 * @param cms the OpenCms user context to use when reading the principal 305 * @param type the principal type 306 * @param name the principal name 307 * 308 * @return the principal read from the OpenCms database 309 * 310 * @throws CmsException in case the principal could not be read 311 */ 312 public static I_CmsPrincipal readPrincipal(CmsObject cms, String type, String name) throws CmsException { 313 314 if (CmsStringUtil.isNotEmpty(type)) { 315 String upperCaseType = type.toUpperCase(); 316 if (PRINCIPAL_GROUP.equals(upperCaseType)) { 317 // this principal is a group 318 return cms.readGroup(name); 319 } else if (PRINCIPAL_USER.equals(upperCaseType)) { 320 // this principal is a user 321 return cms.readUser(name); 322 } 323 } 324 // invalid principal type was given 325 throw new CmsDbEntryNotFoundException( 326 Messages.get().container(Messages.ERR_INVALID_PRINCIPAL_TYPE_2, type, name)); 327 } 328 329 /** 330 * Utility function to read a principal by its id from the OpenCms database using the 331 * provided OpenCms user context.<p> 332 * 333 * @param cms the OpenCms user context to use when reading the principal 334 * @param id the id of the principal to read 335 * 336 * @return the principal read from the OpenCms database 337 * 338 * @throws CmsException in case the principal could not be read 339 */ 340 public static I_CmsPrincipal readPrincipalIncludingHistory(CmsObject cms, CmsUUID id) throws CmsException { 341 342 try { 343 // first try to read the principal as a user 344 return cms.readUser(id); 345 } catch (CmsException exc) { 346 // assume user does not exist 347 } 348 try { 349 // now try to read the principal as a group 350 return cms.readGroup(id); 351 } catch (CmsException exc) { 352 // assume group does not exist 353 } 354 try { 355 // at the end try to read the principal from the history 356 return cms.readHistoryPrincipal(id); 357 } catch (CmsException exc) { 358 // assume the principal does not exist at all 359 } 360 // invalid principal name was given 361 throw new CmsDbEntryNotFoundException(Messages.get().container(Messages.ERR_INVALID_PRINCIPAL_1, id)); 362 } 363 364 /** 365 * @see java.lang.Comparable#compareTo(java.lang.Object) 366 */ 367 public int compareTo(I_CmsPrincipal obj) { 368 369 if ((this == obj) || equals(obj)) { 370 return 0; 371 } 372 return getName().compareTo(obj.getName()); 373 } 374 375 /** 376 * @see java.lang.Object#equals(java.lang.Object) 377 */ 378 @Override 379 public boolean equals(Object obj) { 380 381 if (obj == this) { 382 return true; 383 } 384 if (obj instanceof I_CmsPrincipal) { 385 if (m_id != null) { 386 return m_id.equals(((I_CmsPrincipal)obj).getId()); 387 } 388 } 389 return false; 390 } 391 392 /** 393 * @see org.opencms.security.I_CmsPrincipal#getDescription() 394 */ 395 public String getDescription() { 396 397 return m_description; 398 } 399 400 /** 401 * Returns the display name of this principal including the organizational unit.<p> 402 * 403 * @param cms the cms context 404 * @param locale the locale 405 * 406 * @return the display name of this principal including the organizational unit 407 * 408 * @throws CmsException if the organizational unit could not be read 409 */ 410 public String getDisplayName(CmsObject cms, Locale locale) throws CmsException { 411 412 return Messages.get().getBundle(locale).key( 413 Messages.GUI_PRINCIPAL_DISPLAY_NAME_2, 414 getSimpleName(), 415 OpenCms.getOrgUnitManager().readOrganizationalUnit(cms, getOuFqn()).getDisplayName(locale)); 416 } 417 418 /** 419 * Returns the translated display name of this principal if it is a group and the display name otherwise.<p> 420 * 421 * @param cms the current CMS context 422 * @param locale the locale 423 * @param translation the group name translation to use 424 * 425 * @return the translated display name 426 * 427 * @throws CmsException if something goes wrong 428 */ 429 public String getDisplayName(CmsObject cms, Locale locale, I_CmsGroupNameTranslation translation) 430 throws CmsException { 431 432 if (!isGroup() || (translation == null)) { 433 return getDisplayName(cms, locale); 434 } 435 return Messages.get().getBundle(locale).key( 436 Messages.GUI_PRINCIPAL_DISPLAY_NAME_2, 437 translation.translateGroupName(getName(), false), 438 OpenCms.getOrgUnitManager().readOrganizationalUnit(cms, getOuFqn()).getDisplayName(locale)); 439 } 440 441 /** 442 * @see org.opencms.security.I_CmsPrincipal#getFlags() 443 */ 444 public int getFlags() { 445 446 return m_flags; 447 } 448 449 /** 450 * @see org.opencms.security.I_CmsPrincipal#getId() 451 */ 452 public CmsUUID getId() { 453 454 return m_id; 455 } 456 457 /** 458 * Returns the fully qualified name of this principal.<p> 459 * 460 * @return the fully qualified name of this principal 461 * 462 * @see java.security.Principal#getName() 463 */ 464 public String getName() { 465 466 return m_name; 467 } 468 469 /** 470 * Returns the fully qualified name of the associated organizational unit.<p> 471 * 472 * @return the fully qualified name of the associated organizational unit 473 */ 474 public String getOuFqn() { 475 476 return CmsOrganizationalUnit.getParentFqn(m_name); 477 } 478 479 /** 480 * @see org.opencms.security.I_CmsPrincipal#getPrefixedName() 481 */ 482 public String getPrefixedName() { 483 484 if (isUser()) { 485 return getPrefixedUser(getName()); 486 } else if (isGroup()) { 487 return getPrefixedGroup(getName()); 488 } 489 return getName(); 490 } 491 492 /** 493 * Returns the simple name of this organizational unit. 494 * 495 * @return the simple name of this organizational unit. 496 */ 497 public String getSimpleName() { 498 499 return CmsOrganizationalUnit.getSimpleName(m_name); 500 } 501 502 /** 503 * @see java.lang.Object#hashCode() 504 */ 505 @Override 506 public int hashCode() { 507 508 if (m_id != null) { 509 return m_id.hashCode(); 510 } 511 return CmsUUID.getNullUUID().hashCode(); 512 } 513 514 /** 515 * @see org.opencms.security.I_CmsPrincipal#isEnabled() 516 */ 517 public boolean isEnabled() { 518 519 return (getFlags() & I_CmsPrincipal.FLAG_DISABLED) == 0; 520 } 521 522 /** 523 * @see org.opencms.security.I_CmsPrincipal#isGroup() 524 */ 525 public boolean isGroup() { 526 527 return (this instanceof CmsGroup); 528 } 529 530 /** 531 * @see org.opencms.security.I_CmsPrincipal#isUser() 532 */ 533 public boolean isUser() { 534 535 return (this instanceof CmsUser); 536 } 537 538 /** 539 * @see org.opencms.security.I_CmsPrincipal#setDescription(java.lang.String) 540 */ 541 public void setDescription(String description) { 542 543 m_description = description; 544 } 545 546 /** 547 * @see org.opencms.security.I_CmsPrincipal#setEnabled(boolean) 548 */ 549 public void setEnabled(boolean enabled) { 550 551 if (enabled != isEnabled()) { 552 // toggle disabled flag if required 553 setFlags(getFlags() ^ I_CmsPrincipal.FLAG_DISABLED); 554 } 555 } 556 557 /** 558 * @see org.opencms.security.I_CmsPrincipal#setFlags(int) 559 */ 560 public void setFlags(int value) { 561 562 m_flags = value; 563 } 564 565 /** 566 * @see org.opencms.security.I_CmsPrincipal#setName(java.lang.String) 567 */ 568 public void setName(String name) { 569 570 checkName(CmsOrganizationalUnit.getSimpleName(name)); 571 m_name = name; 572 } 573}