| /* |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| */ |
| package org.apache.wiki.auth.authorize; |
| |
| import org.apache.wiki.auth.GroupPrincipal; |
| |
| import java.security.Principal; |
| import java.util.Date; |
| import java.util.Vector; |
| |
| /** |
| * <p> |
| * Groups are a specialized type of ad-hoc role used by the wiki system. Unlike |
| * externally-provided roles (such as those provided by an LDAP server or web |
| * container), JSPWiki groups can be created dynamically by wiki users, without |
| * requiring special container privileges or administrator intervention. They |
| * are designed to provide a lightweight role-based access control system that |
| * complements existing role systems. |
| * </p> |
| * <p> |
| * Group names are case-insensitive, and have a few naming restrictions, which |
| * are enforced by the {@link GroupManager}: |
| * </p> |
| * <ul> |
| * <li>Groups cannot have the same name as a built-in Role (e.g., "Admin", |
| * "Authenticated" etc.)</li> |
| * <li>Groups cannot have the same name as an existing user</li> |
| * </ul> |
| * <p> |
| * <em>Note: prior to JSPWiki 2.4.19, Group was an interface; it |
| * is now a concrete, final class.</em> |
| * </p> |
| * <p> |
| * Groups are related to {@link GroupPrincipal}s. A GroupPrincipal, when |
| * injected into the Principal set of a Session's Subject, means that the |
| * user is a member of a Group of the same name -- it is, in essence, an |
| * "authorization token." GroupPrincipals, unlike Groups, are thread-safe, |
| * lightweight and immutable. That's why we use them in Subjects rather than the |
| * Groups themselves. |
| * </p> |
| * |
| * @since 2.3 |
| */ |
| public class Group { |
| |
| static final String[] RESTRICTED_GROUPNAMES = new String[] { "Anonymous", "All", "Asserted", "Authenticated" }; |
| |
| private final Vector<Principal> m_members = new Vector<>(); |
| |
| private String m_creator = null; |
| |
| private Date m_created = null; |
| |
| private String m_modifier = null; |
| |
| private Date m_modified = null; |
| |
| private final String m_name; |
| |
| private final Principal m_principal; |
| |
| private final String m_wiki; |
| |
| /** |
| * Protected constructor to prevent direct instantiation except by other |
| * package members. Callers should use |
| * {@link GroupManager#parseGroup(String, String, boolean)} or |
| * {@link GroupManager#parseGroup(org.apache.wiki.WikiContext, boolean)}. |
| * instead. |
| * @param name the name of the group |
| * @param wiki the wiki the group belongs to |
| */ |
| protected Group( final String name, final String wiki ) { |
| m_name = name; |
| m_wiki = wiki; |
| m_principal = new GroupPrincipal( name ); |
| } |
| |
| /** |
| * Adds a Principal to the group. |
| * |
| * @param user the principal to add |
| * @return <code>true</code> if the operation was successful |
| */ |
| public synchronized boolean add( final Principal user ) { |
| if( isMember( user ) ) { |
| return false; |
| } |
| |
| m_members.add( user ); |
| return true; |
| } |
| |
| /** |
| * Clears all Principals from the group list. |
| */ |
| public synchronized void clear() { |
| m_members.clear(); |
| } |
| |
| /** |
| * Two DefaultGroups are equal if they contain identical member Principals |
| * and have the same name. |
| * @param o the object to compare |
| * @return the comparison |
| */ |
| @Override |
| public boolean equals( final Object o ) { |
| if( !( o instanceof Group ) ) { |
| return false; |
| } |
| |
| final Group g = ( Group )o; // Just a shortcut. |
| |
| if( g.m_members.size() != m_members.size() ) { |
| return false; |
| } |
| |
| if( getName() != null && !getName().equals( g.getName() ) ) { |
| return false; |
| } else if( getName() == null && g.getName() != null ) { |
| return false; |
| } |
| |
| for( final Principal principal : m_members ) { |
| if( !g.isMember( principal ) ) { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| /** |
| * The hashcode is calculated as a XOR sum over all members of the Group. |
| * |
| * @return the hash code |
| */ |
| @Override |
| public int hashCode() { |
| int hc = 0; |
| for( final Principal member : m_members ) { |
| hc ^= member.hashCode(); |
| } |
| return hc; |
| } |
| |
| /** |
| * Returns the creation date. |
| * |
| * @return the creation date |
| */ |
| public synchronized Date getCreated() { |
| return m_created; |
| } |
| |
| /** |
| * Returns the creator of this Group. |
| * |
| * @return the creator |
| */ |
| public final synchronized String getCreator() { |
| return m_creator; |
| } |
| |
| /** |
| * Returns the last-modified date. |
| * |
| * @return the date and time of last modification |
| */ |
| public synchronized Date getLastModified() { |
| return m_modified; |
| } |
| |
| /** |
| * Returns the name of the user who last modified this group. |
| * |
| * @return the modifier |
| */ |
| public final synchronized String getModifier() { |
| return m_modifier; |
| } |
| |
| /** |
| * The name of the group. This is set in the class constructor. |
| * |
| * @return the name of the Group |
| */ |
| public String getName() { |
| return m_name; |
| } |
| |
| /** |
| * Returns the GroupPrincipal that represents this Group. |
| * |
| * @return the group principal |
| */ |
| public Principal getPrincipal() { |
| return m_principal; |
| } |
| |
| /** |
| * Returns the wiki name. |
| * |
| * @return the wiki name |
| */ |
| public String getWiki() { |
| return m_wiki; |
| } |
| |
| /** |
| * Returns <code>true</code> if a Principal is a member of the group. Specifically, the Principal's <code>getName()</code> method must |
| * return the same value as one of the Principals in the group member list. The Principal's type does <em>not</em> need to match. |
| * |
| * @param principal the principal about whom membeship status is sought |
| * @return the result of the operation |
| */ |
| public boolean isMember( final Principal principal ) { |
| return findMember( principal.getName() ) != null; |
| } |
| |
| /** |
| * Returns the members of the group as an array of Principal objects. |
| * |
| * @return the members |
| */ |
| public Principal[] members() { |
| return m_members.toArray( new Principal[ m_members.size() ] ); |
| } |
| |
| /** |
| * Removes a Principal from the group. |
| * |
| * @param user the principal to remove |
| * @return <code>true</code> if the operation was successful |
| */ |
| public synchronized boolean remove( Principal user ) { |
| user = findMember( user.getName() ); |
| if( user == null ) |
| return false; |
| |
| m_members.remove( user ); |
| |
| return true; |
| } |
| |
| /** |
| * Sets the created date. |
| * |
| * @param date the creation date |
| */ |
| public synchronized void setCreated( final Date date ) { |
| m_created = date; |
| } |
| |
| /** |
| * Sets the creator of this Group. |
| * @param creator the creator |
| */ |
| public final synchronized void setCreator( final String creator ) { |
| this.m_creator = creator; |
| } |
| |
| /** |
| * Sets the last-modified date |
| * |
| * @param date the last-modified date |
| */ |
| public synchronized void setLastModified( final Date date ) { |
| m_modified = date; |
| } |
| |
| /** |
| * Sets the name of the user who last modified this group. |
| * |
| * @param modifier the modifier |
| */ |
| public final synchronized void setModifier( final String modifier ) { |
| this.m_modifier = modifier; |
| } |
| |
| /** |
| * Returns a string representation of the Group. |
| * |
| * @return the string |
| * @see java.lang.Object#toString() |
| */ |
| @Override |
| public String toString() { |
| return "(Group " + getName() + ")"; |
| } |
| |
| private Principal findMember( final String name ) { |
| for( final Principal member : m_members ) { |
| if( member.getName().equals( name ) ) { |
| return member; |
| } |
| } |
| |
| return null; |
| } |
| |
| } |