/* * The contents of this file are subject to the Mozilla Public License Version 1.1 * (the "License"); you may not use this file except in compliance with the License. * You may obtain a copy of the License at . * * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT * WARRANTY OF ANY KIND, either express or implied. See the License for the specific * language governing rights and limitations under the License. * * The Original Code is the Venice Web Communities System. * * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are * Copyright (C) 2003 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ package com.silverwrist.venice.community; import java.security.Principal; import java.security.acl.AclNotFoundException; import java.util.*; import org.apache.commons.collections.*; import org.apache.log4j.Logger; import com.silverwrist.dynamo.db.NamespaceCache; import com.silverwrist.dynamo.db.UserManagement; import com.silverwrist.dynamo.iface.*; import com.silverwrist.dynamo.except.*; import com.silverwrist.dynamo.security.SecurityReferenceMonitor; import com.silverwrist.dynamo.util.*; import com.silverwrist.venice.CommunityVisibility; import com.silverwrist.venice.VeniceNamespaces; import com.silverwrist.venice.event.*; import com.silverwrist.venice.except.*; import com.silverwrist.venice.iface.*; /** * Concrete implementation of the {@link com.silverwrist.venice.iface.VeniceCommunity VeniceCommunity} interface, * which provides all the basic community functions. * * @author Eric J. Bowersox <erbo@silcom.com> * @version X */ class CommunityImpl implements VeniceCommunity { /*-------------------------------------------------------------------------------- * Internal join cleanup task class. *-------------------------------------------------------------------------------- */ private class JoinCleanupTask { /*==================================================================== * Attributes *==================================================================== */ private int m_ugid; private boolean m_is_group; /*==================================================================== * Constructor *==================================================================== */ JoinCleanupTask(int ugid, boolean is_group) { m_ugid = ugid; m_is_group = is_group; } // end constructor /*==================================================================== * External operations *==================================================================== */ void run() throws DatabaseException { m_ops.deleteSingleUseAuthData(m_id,m_ugid,m_is_group); } // end run } // end class JoinCleanupTask /*-------------------------------------------------------------------------------- * Static data members *-------------------------------------------------------------------------------- */ private static Logger logger = Logger.getLogger(CommunityImpl.class); /*-------------------------------------------------------------------------------- * Attributes *-------------------------------------------------------------------------------- */ private CommunityManager m_base; // base object private CommunityOps m_ops; // community operations object private NamespaceCache m_nscache; // namespace cache object private SecurityReferenceMonitor m_srm; // security reference monitor private UserManagement m_users; // user management object private AuthenticatorLookup m_alook; // authenticator lookup object private PostDynamicUpdate m_post; // where we post dynamic update events private CategoryService m_cats; // category service object private int m_id; // community ID private int m_member_gid; // member group ID private int m_host_gid; // hosts group ID private int m_host_uid; // primary host UID private int m_aclid; // ID of the community ACL private int m_catid; // category ID for the community private CommunityVisibility m_visibility; // community visibility private String m_name; // community name private String m_alias; // community alias private java.util.Date m_created; // date created private java.util.Date m_lastaccessed; // date last accessed private java.util.Date m_lastupdate; // date last updated private ReferenceMap m_properties; // properties cache private List m_service_list = null; // cached service list /*-------------------------------------------------------------------------------- * Constructors *-------------------------------------------------------------------------------- */ /** * Constructs a new concrete community implementation. * * @param ops The {@link com.silverwrist.venice.community.CommunityOps CommunityOps} object providing access to the * database. * @param nscache The {@link com.silverwrist.dynamo.db.NamespaceCache NamespaceCache} object providing conversion * between namespace URIs and integer namespace identifiers. * @param srm The {@link com.silverwrist.dynamo.security.SecurityReferenceMonitor SecurityReferenceMonitor} object * through which security is tested. * @param users The {@link com.silverwrist.dynamo.db.UserManagement UserManagetment} object used to retrieve user * and group objects. * @param alook The {@link com.silverwrist.dynamo.iface.AuthenticatorLookup AuthenticatorLookup} interface used * to find registered {@link com.silverwrist.dynamo.iface.Authenticator Authenticator} objects. * @param post The {@link com.silverwrist.dynamo.iface.PostDynamicUpdate PostDynamicUpdate} interface used * to post dynamic update events. * @param cats The {@link com.silverwrist.venice.community.CategoryService CategoryService} interface used to * retrieve category objects. * @param data A {@link java.util.Map Map} object containing the initial data for the community, with keys * corresponding to static fields of the * {@link com.silverwrist.venice.community.CommunityManagerOps CommunityManagerOps} object. */ CommunityImpl(CommunityManager base, CommunityOps ops, NamespaceCache nscache, SecurityReferenceMonitor srm, UserManagement users, AuthenticatorLookup alook, PostDynamicUpdate post, CategoryService cats, Map data) { m_base = base; m_ops = ops; m_nscache = nscache; m_srm = srm; m_users = users; m_alook = alook; m_post = post; m_cats = cats; m_id = ((Integer)(data.get(CommunityManagerOps.KEY_CID))).intValue(); m_member_gid = ((Integer)(data.get(CommunityManagerOps.KEY_MEMBER_GID))).intValue(); m_host_gid = ((Integer)(data.get(CommunityManagerOps.KEY_HOST_GID))).intValue(); m_host_uid = ((Integer)(data.get(CommunityManagerOps.KEY_HOST_UID))).intValue(); m_aclid = ((Integer)(data.get(CommunityManagerOps.KEY_ACLID))).intValue(); m_catid = ((Integer)(data.get(CommunityManagerOps.KEY_CATID))).intValue(); m_visibility = (CommunityVisibility)(data.get(CommunityManagerOps.KEY_VISIBILITY)); m_name = (String)(data.get(CommunityManagerOps.KEY_NAME)); m_alias = (String)(data.get(CommunityManagerOps.KEY_ALIAS)); m_created = (java.util.Date)(data.get(CommunityManagerOps.KEY_CREATE)); m_lastaccessed = (java.util.Date)(data.get(CommunityManagerOps.KEY_ACCESS)); m_lastupdate = (java.util.Date)(data.get(CommunityManagerOps.KEY_UPDATE)); m_properties = new ReferenceMap(ReferenceMap.HARD,ReferenceMap.SOFT); } // end constructor /*-------------------------------------------------------------------------------- * Internal operations *-------------------------------------------------------------------------------- */ /** * Performs a permission check on the community's ACL, as well as the global ACL. Returns without * incident if the permission check succeeds; throws a * {@link com.silverwrist.dynamo.except.DynamoSecurityException DynamoSecurityException} if it fails. * * @param caller The user makingt he call, to test the permission. * @param perm_namespace The namespace of the permission to be tested. * @param perm_name The name of the permission to be tested. * @param fail_message The message to be thrown as a DynamoSecurityException if the test fails. * Interpreted as a message identifier within the CommunityMessages resource * bundle, with one parameter: the name of the community. * @exception com.silverwrist.dynamo.except.DatabaseException If there was a database failure testing the permission. * @exception com.silverwrist.dynamo.except.DynamoSecurityException If the permission test failed. */ private final void testPermission(DynamoUser caller, String perm_namespace, String perm_name, String fail_message) throws DatabaseException, DynamoSecurityException { try { // perform security tests... if (caller.equals(m_srm.getAdminUser())) return; // Administrator can do anything if (m_srm.getAcl(m_aclid).testPermission(caller,perm_namespace,perm_name)) return; // we have the right permission in the community ACL if (m_srm.getGlobalAcl().testPermission(caller,perm_namespace,perm_name)) return; // or we can be authorized by the global ACL } // end try catch (AclNotFoundException e) { // just fall through and throw the exception } // end catch // throw the DynamoSecurityException DynamoSecurityException d = new DynamoSecurityException(CommunityImpl.class,"CommunityMessages",fail_message); d.setParameter(0,m_name); throw d; } // end testPermission /*-------------------------------------------------------------------------------- * Overrides from class Object *-------------------------------------------------------------------------------- */ /** * Indicates whether some other object is "equal to" this one. * * @param o The reference object with which to compare. * @return true if this object is the same as the o argument; false otherwise. */ public boolean equals(Object o) { if (o==null) return false; if (o instanceof VeniceCommunity) return (((VeniceCommunity)o).getCID()==m_id); return false; } // end equals /** * Returns a hash code value for the object. This method is supported for the benefit of hashtables such as those * provided by {@link java.util.Hashtable Hashtable}. * * @return A hash code value for this object. */ public int hashCode() { return m_id; } // end hashCode /** * Returns a string representation of the object. In general, the toString method returns a string * that "textually represents" this object. * * @return A string representation of the object. */ public String toString() { return "Community \"" + m_name + "\""; } // end toString /*-------------------------------------------------------------------------------- * Implementations from interface NamedObject *-------------------------------------------------------------------------------- */ /** * Returns the name of this community. * * @return The name of this community. */ public String getName() { return m_name; } // end getName /*-------------------------------------------------------------------------------- * Implementations from interface ObjectProvider *-------------------------------------------------------------------------------- */ /** * Retrieves an object from the community's properties. * * @param namespace The namespace to interpret the name relative to. * @param name The name of the object to be retrieved. * @return The object reference specified. */ public Object getObject(String namespace, String name) { if (logger.isDebugEnabled()) logger.debug("CommunityImpl.getObject: namespace = " + namespace + ", name = " + name); try { // convert the namespace name to an ID here PropertyKey key = new PropertyKey(m_nscache.namespaceNameToId(namespace),name); Object rc = null; synchronized (this) { // start by looking in the properties map rc = m_properties.get(key); if (rc==null) { // no use - need to try the database rc = m_ops.getProperty(m_id,key); if (rc!=null) { // found in the database m_properties.put(key,rc); logger.debug("value found in database"); } // end if } // end if else logger.debug("value found in cache"); } // end synchronized block if (rc==null) { // the object was not found logger.debug("value not found"); throw new NoSuchObjectException(this.toString(),namespace,name); } // end if return rc; } // end try catch (DatabaseException e) { // translate into our NoSuchObjectException but retain the DatabaseException logger.debug("Database exception while doing find",e); throw new NoSuchObjectException(this.toString(),namespace,name,e); } // end catch } // end getObject /*-------------------------------------------------------------------------------- * Implementations from interface SecureObjectStore *-------------------------------------------------------------------------------- */ /** * Sets an object into the community's properties. * * @param caller The user performing the operation. * @param namespace The namespace to interpret the name relative to. * @param name The name of the object to be set. * @param value The object to set into the community's properties. * @return The previous object that was set into the community's properties under this namespace and name, or * null if there was no such object. * @exception com.silverwrist.dynamo.except.DatabaseException If there was an error setting the object value. * @exception com.silverwrist.dynamo.except.DynamoSecurityException If the specified user is not permitted to * set this object value into this community's properties. */ public Object setObject(DynamoUser caller, String namespace, String name, Object value) throws DatabaseException, DynamoSecurityException { testPermission(caller,namespace,"set.property","auth.setProperty"); DateObjectPair rc = null; // convert the namespace name to an ID here PropertyKey key = new PropertyKey(m_nscache.namespaceNameToId(namespace),name); synchronized (this) { // start by setting the database value rc = m_ops.setProperty(m_id,key,value); // and cache it, too m_properties.put(key,value); // and save off the update date/time m_lastaccessed = m_lastupdate = rc.getDate(); } // end synchronized block m_post.postUpdate(new CommunityPropertyUpdateEvent(this,namespace,name)); return rc.getObject(); } // end setObject /** * Removes an object from this community's properties. * * @param caller The user performing the operation. * @param namespace The namespace to interpret the name relative to. * @param name The name of the object to be removed. * @return The previous object that was set into the community's properties under this namespace and name, or * null if there was no such object. * @exception com.silverwrist.dynamo.except.DatabaseException If there was an error removing the object value. * @exception com.silverwrist.dynamo.except.DynamoSecurityException If the specified user is not permitted to * remove this object value from this community's properties. */ public Object removeObject(DynamoUser caller, String namespace, String name) throws DatabaseException, DynamoSecurityException { testPermission(caller,namespace,"remove.property","sec.removeGlobalProperty"); DateObjectPair rc = null; // convert the namespace name to an ID here PropertyKey key = new PropertyKey(m_nscache.namespaceNameToId(namespace),name); synchronized (this) { // start by killing the database value rc = m_ops.removeProperty(m_id,key); // and remove the cached value, too m_properties.remove(key); if (rc!=null) // save off update date.time m_lastaccessed = m_lastupdate = rc.getDate(); } // end synchronized block m_post.postUpdate(new CommunityPropertyUpdateEvent(this,namespace,name)); return (rc==null) ? null : rc.getObject(); } // end removeObject /** * Returns a collection of all object namespaces that have been set into this community's properties. * * @return A {@link java.util.Collection Collection} containing {@link java.lang.String String} objects specifying * all the object namespaces. * @exception com.silverwrist.dynamo.except.DatabaseException If there was an error getting the namespace list. */ public Collection getNamespaces() throws DatabaseException { // call through to the database to get the list of namespace IDs int[] ids = m_ops.getPropertyNamespaceIDs(m_id); ArrayList rc = new ArrayList(ids.length); for (int i=0; imember group of this community. The member group specifies all * members of the community. * * @return The GID of the member group for this community. */ public int getMemberGID() { return m_member_gid; } // end getMemberGID /** * Returns a reference to the member group of this community. The member group specifies all * members of the community. * * @return A reference to the member group of this community. * @exception com.silverwrist.dynamo.except.DatabaseException If there was an error getting the member group. */ public DynamoGroup getMemberGroup() throws DatabaseException { return m_users.getGroup(m_member_gid); } // end getMemberGroup /** * Returns the GID of the host group of this community. The host group specifies all * hosts of the community, who generally have power to change most attributes of a community. * * @return The GID of the host group for this community. */ public int getHostGID() { return m_host_gid; } // end getHostGID /** * Returns a reference to the host group of this community. The host group specifies all * hosts of the community, who generally have power to change most attributes of a community. * * @return A reference to the host group of this community. * @exception com.silverwrist.dynamo.except.DatabaseException If there was an error getting the host group. */ public DynamoGroup getHostGroup() throws DatabaseException { return m_users.getGroup(m_host_gid); } // end getHostGroup /** * Returns the UID of the host user of this community. The host user is the primary host of the * community, who is the only one who has power to add or remove additional hosts. * * @return The UID of the host user of the community. */ public int getHostUID() { return m_host_uid; } // end getHostUID /** * Returns a reference to the host user of this community. The host user is the primary host of the * community, who is the only one who has power to add or remove additional hosts. * * @return A reference to the host user of the community. * @exception com.silverwrist.dynamo.except.DatabaseException If there was an error getting the host user. */ public DynamoUser getHostUser() throws DatabaseException { return m_users.getUser(m_host_uid); } // end getHostUser /** * Returns a reference to the community's access control list. * * @return A reference to the community's access control list. * @exception com.silverwrist.dynamo.except.DatabaseException If there was an error getting the ACL. * @exception java.security.acl.AclNotFoundException If the community ACL could not be found. */ public DynamoAcl getAcl() throws DatabaseException, AclNotFoundException { return m_srm.getAcl(m_aclid); } // end getAcl /** * Returns the category ID of the community, specifying its location in the community directory. * * @return The category ID of the community. */ public int getCategoryID() { return m_catid; } // end getCategoryID /** * Returns the category of the community, specifying its location in the community directory. * * @return The category of the community. * @exception com.silverwrist.dynamo.except.DatabaseException If there was an error getting the category object. */ public VeniceCategory getCategory() throws DatabaseException { return m_cats.getCategory(m_catid); } // end getCategory /** * Changes the category ID of the community, specifying its location in the community directory. * * @param caller The user attempting to change the category ID. * @param catid The new category ID for the community. * @exception com.silverwrist.dynamo.except.DatabaseException If there was an error resetting the category. * @exception com.silverwrist.dynamo.except.DynamoSecurityException If the specified user is not permitted to * change the category ID. */ public synchronized void setCategoryID(DynamoUser caller, int catid) throws DatabaseException, DynamoSecurityException { testPermission(caller,VeniceNamespaces.COMMUNITY_PROFILE_NAMESPACE,"set.category","auth.setCategory"); java.util.Date update = m_ops.setCategoryID(m_id,catid); m_catid = catid; m_lastaccessed = m_lastupdate = update; m_post.postUpdate(new CommunityBaseUpdateEvent(this,"category")); } // end setCategoryID /** * Changes the category of the community, specifying its location in the community directory. * * @param caller The user attempting to change the category. * @param catid The new category for the community. * @exception com.silverwrist.dynamo.except.DatabaseException If there was an error resetting the category. * @exception com.silverwrist.dynamo.except.DynamoSecurityException If the specified user is not permitted to * change the category. */ public void setCategory(DynamoUser caller, VeniceCategory cat) throws DatabaseException, DynamoSecurityException { this.setCategoryID(caller,cat.getCategoryID()); } // end setCategory /** * Returns the current {@link com.silverwrist.venice.CommunityVisibility visibility} of the community. * * @return The current visibility of the community. */ public CommunityVisibility getVisibility() { return m_visibility; } // end getVisibility /** * Sets the current {@link com.silverwrist.venice.CommunityVisibility visibility} of the community. * * @param caller The user attempting to change the community's visibility. * @param vis The new visibility for the community. * @exception com.silverwrist.dynamo.except.DatabaseException If there was an error resetting the visibility. * @exception com.silverwrist.dynamo.except.DynamoSecurityException If the specified user is not permitted to * change the community visibility. */ public synchronized void setVisibility(DynamoUser caller, CommunityVisibility vis) throws DatabaseException, DynamoSecurityException { testPermission(caller,VeniceNamespaces.COMMUNITY_PROFILE_NAMESPACE,"set.visibility","auth.setVisibility"); java.util.Date update = m_ops.setVisibility(m_id,vis); m_visibility = vis; m_lastaccessed = m_lastupdate = update; m_post.postUpdate(new CommunityBaseUpdateEvent(this,"visibility")); } // end setVisibility /** * Sets the name of the community. * * @param caller The user attempting to change the community's name. * @param name The new name for the community. * @exception com.silverwrist.dynamo.except.DatabaseException If there was an error resetting the name. * @exception com.silverwrist.dynamo.except.DynamoSecurityException If the specified user is not permitted to * change the community name. */ public synchronized void setName(DynamoUser caller, String name) throws DatabaseException, DynamoSecurityException { testPermission(caller,VeniceNamespaces.COMMUNITY_PROFILE_NAMESPACE,"set.name","auth.setName"); java.util.Date update = m_ops.setName(m_id,name); m_name = name; m_lastaccessed = m_lastupdate = update; m_post.postUpdate(new CommunityBaseUpdateEvent(this,"name")); } // end setName /** * Returns the alias of the community. The alias is a unique identifier for the community that must * conform to the rules for Dynamo identifiers. * * @return The alias for the community. */ public String getAlias() { return m_alias; } // end getAlias /** * Sets the alias of the community. The alias is a unique identifier for the community that must * conform to the rules for Dynamo identifiers. * * @param caller The user attempting to change the community's alias. * @param alias The new alias for the community. * @exception com.silverwrist.dynamo.except.DatabaseException If there was an error resetting the alias. * @exception com.silverwrist.dynamo.except.DynamoSecurityException If the specified user is not permitted to * change the community alias. */ public synchronized void setAlias(DynamoUser caller, String alias) throws DatabaseException, DynamoSecurityException { testPermission(caller,VeniceNamespaces.COMMUNITY_PROFILE_NAMESPACE,"set.alias","auth.setAlias"); java.util.Date update = m_ops.setAlias(m_id,alias); m_alias = alias; m_lastaccessed = m_lastupdate = update; m_post.postUpdate(new CommunityBaseUpdateEvent(this,"alias")); } // end setAlias /** * Returns the date and time at which this community was created. * * @return The creation date and time for this community. */ public java.util.Date getCreationDate() { return m_created; } // end getCreationDate /** * Returns the date and time at which this community was last accessed. * * @return The last access date and time for this community. */ public java.util.Date getLastAccessDate() { return m_lastaccessed; } // end getLastAccessDate /** * Sets the date and time at which this community was last accessed. * * @param caller The user attempting to change the community's access date/time. * @param date The new access date/time for the community. * @exception com.silverwrist.dynamo.except.DatabaseException If there was an error resetting the access date/time. * @exception com.silverwrist.dynamo.except.DynamoSecurityException If the specified user is not permitted to * change the community access date/time. */ public synchronized void setLastAccessDate(DynamoUser caller, java.util.Date date) throws DatabaseException { m_ops.setLastAccessDate(m_id,date); m_lastaccessed = date; } // end setLastAccessedDate /** * Returns the date and time at which this community was last updated. * * @return The last update date and time for this community. */ public java.util.Date getLastUpdateDate() { return m_lastupdate; } // end getLastUpdateDate /** * Sets the date and time at which this community was last updated. * * @param caller The user attempting to change the community's update date/time. * @param date The new update date/time for the community. * @exception com.silverwrist.dynamo.except.DatabaseException If there was an error resetting the update date/time. * @exception com.silverwrist.dynamo.except.DynamoSecurityException If the specified user is not permitted to * change the community update date/time. */ public synchronized void setLastUpdateDate(DynamoUser caller, java.util.Date date) throws DatabaseException { m_ops.setLastUpdateDate(m_id,date); m_lastaccessed = m_lastupdate = date; } // end setLastUpdateDate /** * Grants permission to join the community to a specific user or group. This permission may be contingent upon * the user authenticating with the community in some fashion, and it may also be single-use, meaning the permission * is automatically revoked whenever a user uses it to join the community. * * @param caller The person attempting to grant access to the community. * @param subject The {@link com.silverwrist.dynamo.iface.DynamoUser user} or * {@link com.silverwrist.dynamo.iface.DynamoGroup group} that we want to grant access to. * @param auth_namespace The namespace of the authenticator to use to grant access. If both this parameter and * auth_name are null, no authentication is required. * @param auth_name The name of the authenticator to use to grant access. If both this parameter and * auth_namespace are null, no authentication is required. * @param source_info The source information for the authenticator. If auth_namespace and * auth_name are null, this parameter is ignored. * @param auth_info The authentication information (such as a password) for the authenticator. If * auth_namespace and auth_name are null, this parameter is ignored. * @param single_use If this parameter is true, the permission will automatically be revoked after the * first time it is successfully used by a user to join the community. * @exception com.silverwrist.dynamo.except.AuthenticationException If the named authenticator is not a valid one. * @exception com.silverwrist.dynamo.except.DatabaseException If there was an error registering the access grant. * @exception com.silverwrist.dynamo.except.DynamoSecurityException If the specified user is not permitted to grant * access to this community. */ public void grantAccess(DynamoUser caller, Principal subject, String auth_namespace, String auth_name, String source_info, String auth_info, boolean single_use) throws AuthenticationException, DatabaseException, DynamoSecurityException { testPermission(caller,VeniceNamespaces.COMMUNITY_PERMS_NAMESPACE,"grant.revoke.access","auth.grantAccess"); // Translate the subject into an ID and group flag. int ugid = -1; boolean is_group = false; if (subject instanceof DynamoUser) ugid = ((DynamoUser)subject).getUID(); else if (subject instanceof DynamoGroup) { // it's a group ugid = ((DynamoGroup)subject).getGID(); is_group = true; } // end else if else throw new IllegalArgumentException("invalid subject"); // Make sure the authenticator is valid. int auth_nsid = 0; Authenticator auth = null; if ((auth_namespace!=null) || (auth_name!=null)) { // look up the authenticator to make sure it's registered auth = m_alook.findAuthenticator(auth_namespace,auth_name); if (auth==null) throw new IllegalArgumentException("invalid authenticator"); auth_nsid = m_nscache.namespaceNameToId(auth_namespace); } // end if else // force-map source info and auth info to null source_info = auth_info = null; // Preprocess the authentication information through the authenticator. String real_auth_info = auth_info; if ((auth_info!=null) && (auth!=null)) real_auth_info = auth.processInputData(auth_info); synchronized (this) { // update the access table and touch the community java.util.Date update = m_ops.grantAccess(m_id,ugid,is_group,single_use,auth_nsid,auth_name,source_info, real_auth_info); m_lastaccessed = m_lastupdate = update; } // end synchronized block } // end grantAccess /** * Revokes permission to join the community from a specific user or group. This does not affect any user who * has already joined the community. * * @param caller The person attempting to revoke access to the community. * @param subject The {@link com.silverwrist.dynamo.iface.DynamoUser user} or * {@link com.silverwrist.dynamo.iface.DynamoGroup group} that we want to revoke access from. * @exception com.silverwrist.dynamo.except.DatabaseException If there was an error registering the access revoke. * @exception com.silverwrist.dynamo.except.DynamoSecurityException If the specified user is not permitted to revoke * access to this community. */ public void revokeAccess(DynamoUser caller, Principal subject) throws DatabaseException, DynamoSecurityException { testPermission(caller,VeniceNamespaces.COMMUNITY_PERMS_NAMESPACE,"grant.revoke.access","auth.revokeAccess"); // Translate the subject into an ID and group flag. int ugid = -1; boolean is_group = false; if (subject instanceof DynamoUser) ugid = ((DynamoUser)subject).getUID(); else if (subject instanceof DynamoGroup) { // it's a group ugid = ((DynamoGroup)subject).getGID(); is_group = true; } // end else if else throw new IllegalArgumentException("invalid subject"); synchronized (this) { // update the access table and touch the community java.util.Date update = m_ops.revokeAccess(m_id,ugid,is_group); if (update!=null) m_lastaccessed = m_lastupdate = update; } // end synchronized block } // end revokeAccess /** * Tests to see what requirements must be fulfilled by a user to join this community. Returns values as follows: *
    *
  • If the user is not permitted to join the community under any circumstances, this method returns * null.
  • *
  • If the user is already a member of the community, this method returns Boolean.FALSE.
  • *
  • If the user may join the community without any authentication, this method returns * Boolean.TRUE.
  • *
  • Otherwise, the method returns a {@link java.util.Set Set} of * {@link com.silverwrist.dynamo.util.QualifiedNameKey QualifiedNameKey} objects, each of which specifies the * namespace and name of an authenticator which can be used to authenticate the user in order to join this * community.
  • *
* * @param joiner The user to test atainst the current community. * @return See above. * @exception com.silverwrist.dynamo.except.DatabaseException If there was an error getting the authenticator * information for this user. */ public Object getJoinRequirement(DynamoUser joiner) throws DatabaseException { if (logger.isDebugEnabled()) logger.debug("CommunityImpl.getJoinRequirement: " + joiner.getName() + " wants to join " + m_name); // If the user is already a member, return the value that dictates that we are already a member. if (m_users.getGroup(m_member_gid).isMember(joiner)) return Boolean.FALSE; // The Admin user is Superman and can do anything. if (joiner.equals(m_srm.getAdminUser())) return Boolean.TRUE; // Anyone with the global "join any" permission can join without authorization. if (m_srm.getGlobalAcl().testPermission(joiner,VeniceNamespaces.COMMUNITY_PERMS_NAMESPACE,"join.any")) return Boolean.TRUE; // Get the database's verdict. The return value from the low-level operation will either be a null, // a Boolean object, or a Set of PropertyKey objects. Object rc = m_ops.getJoinRequirement(m_id,joiner.getUID()); if (rc==null) return null; else if (rc instanceof Boolean) return rc; assert (rc instanceof Set); // The output must be translated to a Set of QualifiedNameKeys by resolving the namespace IDs. Set rcin = (Set)rc; HashSet rcout = new HashSet(); Iterator it = rcin.iterator(); while (it.hasNext()) { // convert each PropertyKey to a QualifiedNameKey PropertyKey k = (PropertyKey)(it.next()); rcout.add(new QualifiedNameKey(m_nscache.namespaceIdToName(k.getNamespaceID()),k.getName())); } // end while return Collections.unmodifiableSet(rcout); } // end getJoinRequirement public synchronized boolean join(DynamoUser joiner, String auth_namespace, String auth_name, String source_info, String auth_info) throws DatabaseException, DynamoSecurityException { if (logger.isDebugEnabled()) logger.debug("CommunityImpl.join: " + joiner.getName() + " joining " + m_name); // If the user is already a member, return the value that dictates that we are already a member. DynamoGroup mbr_group = m_users.getGroup(m_member_gid); if (mbr_group.isMember(joiner)) return false; boolean ok_to_join = false; JoinCleanupTask task = null; if (joiner.equals(m_srm.getAdminUser())) ok_to_join = true; else if (m_srm.getGlobalAcl().testPermission(joiner,VeniceNamespaces.COMMUNITY_PERMS_NAMESPACE,"join.any")) ok_to_join = true; else { // Look to see if we can find the right entry to let the user in with. boolean need_auth = false; Object which = m_ops.getJoinEntryNull(m_id,joiner.getUID()); if ((which==null) && (auth_namespace!=null) && (auth_name!=null)) { // OK, we may need to authenticate need_auth = true; which = m_ops.getJoinEntry(m_id,joiner.getUID(),m_nscache.namespaceNameToId(auth_namespace),auth_name, source_info); } // end which if (which!=null) { // We can get in...see if we need to check authentication. if (need_auth) { // Pull in the authentication data. String stored_auth_data; if (which instanceof Boolean) stored_auth_data = m_ops.getAuthData(m_id,joiner.getUID(),false); else stored_auth_data = m_ops.getAuthData(m_id,((Integer)which).intValue(),true); // Get the authenticator. Authenticator auth = m_alook.findAuthenticator(auth_namespace,auth_name); if (auth==null) throw new IllegalArgumentException("invalid authenticator"); // Checkitout checkitout checkitout checkitout checkitout checkitout checkitout.... try { // attempt to authenticate ok_to_join = auth.authenticate(stored_auth_data,auth_info); } // end try catch (AuthenticationException e) { // something went wrong... DynamoSecurityException de = new DynamoSecurityException(CommunityImpl.class,"CommunityMessages", "join.authFail",e); de.setParameter(0,m_name); throw de; } // end catch if (!ok_to_join) { // authentication failed - throw an error DynamoSecurityException de = new DynamoSecurityException(CommunityImpl.class,"CommunityMessages", "join.authFail"); de.setParameter(0,m_name); throw de; } // end if } // end if else // we're automatically OK to join ok_to_join = true; // Create the cleanup task. if (which instanceof Boolean) task = new JoinCleanupTask(joiner.getUID(),false); else task = new JoinCleanupTask(((Integer)which).intValue(),true); } // end if // else we can't join the group - fall through and eventually throw a DynamoSecurityException } // end else if (ok_to_join) { // we're OK to join this group! mbr_group.addMember(m_users.getUser(m_host_uid),joiner); if (task!=null) task.run(); return true; } // end if // We cannot join - throw an exception. DynamoSecurityException de = new DynamoSecurityException(CommunityImpl.class,"CommunityMessages", "join.disallowed"); de.setParameter(0,m_name); throw de; } // end join public boolean join(DynamoUser joiner) throws DatabaseException, DynamoSecurityException { return this.join(joiner,null,null,null,null); } // end join public void unjoin(DynamoUser unjoiner) throws DatabaseException, DynamoSecurityException { DynamoGroup mbr_group = m_users.getGroup(m_member_gid); if (!(mbr_group.isMember(unjoiner))) return; // if you're not a member, unjoining is a no-op testPermission(unjoiner,VeniceNamespaces.COMMUNITY_PERMS_NAMESPACE,"unjoin","auth.unjoin"); mbr_group.removeMember(m_users.getUser(m_host_uid),unjoiner); } // end unjoin public boolean isAdministrator(DynamoUser user) { try { // must be either the host UID or a member of the admin group if (user.getUID()==m_host_uid) return true; return m_users.getGroup(m_host_gid).isMember(user); } // end try catch (DatabaseException e) { // gotta catch it, even if we can't do anything with it logger.warn("CommunityImpl.isAdministrator caught DatabaseException",e); return false; } // end catch } // end isAdministrator public List getServices() throws DatabaseException { if (m_service_list==null) { // need to fake up the service list int[] svcids = m_ops.getServiceIDs(m_id); if (svcids.length>0) { // convert this to a list of ServiceDescriptors ArrayList rc = new ArrayList(svcids.length); for (int i=0; i