added code to auto-join new users to a new community, where necessary
This commit is contained in:
@@ -77,6 +77,18 @@ public class LibraryCast
|
||||
|
||||
} // end booleanObject
|
||||
|
||||
public final boolean isBooleanFalse(Object o)
|
||||
{
|
||||
return Boolean.FALSE.equals(o);
|
||||
|
||||
} // end isBooleanFalse
|
||||
|
||||
public final boolean isBooleanTrue(Object o)
|
||||
{
|
||||
return Boolean.TRUE.equals(o);
|
||||
|
||||
} // end isBooleanTrue
|
||||
|
||||
public final int[] newIntArray(int size)
|
||||
{
|
||||
return new int[size];
|
||||
|
||||
@@ -42,6 +42,46 @@ import com.silverwrist.venice.iface.*;
|
||||
*/
|
||||
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
|
||||
*--------------------------------------------------------------------------------
|
||||
@@ -863,6 +903,9 @@ class CommunityImpl implements VeniceCommunity
|
||||
*/
|
||||
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;
|
||||
@@ -899,4 +942,109 @@ class CommunityImpl implements VeniceCommunity
|
||||
|
||||
} // 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.
|
||||
if (m_users.getGroup(m_member_gid).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!
|
||||
m_users.getGroup(m_member_gid).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
|
||||
|
||||
} // end class CommunityImpl
|
||||
|
||||
@@ -183,6 +183,8 @@ public class CommunityManager
|
||||
|
||||
private final List translateCIDArray(int[] array) throws DatabaseException
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("translateCIDArray(): translating array of length " + array.length);
|
||||
if (array.length==0)
|
||||
return Collections.EMPTY_LIST;
|
||||
ArrayList rc = new ArrayList(array.length);
|
||||
@@ -196,6 +198,8 @@ public class CommunityManager
|
||||
{
|
||||
if (caller.equals(user))
|
||||
return true; // a user can always get his OWN member community list
|
||||
if (m_srm.getAdminUser().equals(caller))
|
||||
return true; // Administrator can do anything
|
||||
if (m_srm.getGlobalAcl().testPermission(caller,VeniceNamespaces.COMMUNITY_PERMS_NAMESPACE,
|
||||
"see.member.community.lists"))
|
||||
return true; // this user is permitted to see all member community lists
|
||||
@@ -335,8 +339,13 @@ public class CommunityManager
|
||||
public List getMemberCommunities(DynamoUser caller, DynamoUser user)
|
||||
throws DatabaseException, DynamoSecurityException
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("CommunityManager.getMemberCommunities: " + caller.getName() + " getting community list for "
|
||||
+ user.getName());
|
||||
if (!(canGetMemberCommunityList(caller,user)))
|
||||
{ // not permitted - bye!
|
||||
logger.error("CommunityManager.getMemberCommunities: permission denied for " + caller.getName()
|
||||
+ " to get community list for " + user.getName());
|
||||
DynamoSecurityException dse = new DynamoSecurityException(CommunityManager.class,"CommunityMessages",
|
||||
"auth.getCommList");
|
||||
dse.setParameter(0,user.getName());
|
||||
@@ -351,6 +360,8 @@ public class CommunityManager
|
||||
|
||||
public synchronized VeniceCommunity getCommunity(int cid) throws DatabaseException
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("CommunityManager.getCommunity(" + cid + ")");
|
||||
Integer key = new Integer(cid);
|
||||
CommunityImpl rc = (CommunityImpl)(m_id_to_comm.get(key));
|
||||
if (rc==null)
|
||||
|
||||
@@ -29,3 +29,5 @@ auth.setName=You are not authorized to change the name of community "{0}."
|
||||
auth.setAlias=You are not authorized to change the alias of community "{0}."
|
||||
auth.grantAccess=You are not authorized to grant access to community "{0}."
|
||||
auth.revokeAccess=You are not authorized to revoke access grants in community "{0}."
|
||||
join.disallowed=You are not permitted to join community "{0}."
|
||||
join.authFail=Unable to authenticate to community "{0}"; cannot join.
|
||||
|
||||
@@ -71,4 +71,13 @@ abstract class CommunityOps extends OpsBase
|
||||
|
||||
abstract Object getJoinRequirement(int cid, int uid) throws DatabaseException;
|
||||
|
||||
abstract Object getJoinEntryNull(int cid, int uid) throws DatabaseException;
|
||||
|
||||
abstract Object getJoinEntry(int cid, int uid, int auth_nsid, String auth_name, String source_data)
|
||||
throws DatabaseException;
|
||||
|
||||
abstract String getAuthData(int cid, int ugid, boolean is_group) throws DatabaseException;
|
||||
|
||||
abstract void deleteSingleUseAuthData(int cid, int ugid, boolean is_group) throws DatabaseException;
|
||||
|
||||
} // end class CommunityOps
|
||||
|
||||
@@ -811,4 +811,204 @@ class CommunityOps_mysql extends CommunityOps
|
||||
|
||||
} // end getJoinRequirement
|
||||
|
||||
Object getJoinEntryNull(int cid, int uid) throws DatabaseException
|
||||
{
|
||||
Connection conn = null;
|
||||
PreparedStatement stmt = null;
|
||||
ResultSet rs = null;
|
||||
try
|
||||
{ // get a connection
|
||||
conn = getConnection();
|
||||
|
||||
// try looking for a user-level entry first
|
||||
stmt = conn.prepareStatement("SELECT single_use FROM commaccess WHERE cid = ? AND ugid = ? AND is_group = 0 "
|
||||
+ "AND auth_nsid IS NULL AND auth_name IS NULL;");
|
||||
stmt.setInt(1,cid);
|
||||
stmt.setInt(2,uid);
|
||||
rs = stmt.executeQuery();
|
||||
if (rs.next())
|
||||
return Boolean.TRUE;
|
||||
|
||||
SQLUtils.shutdown(rs); // reset for next statement
|
||||
rs = null;
|
||||
SQLUtils.shutdown(stmt);
|
||||
|
||||
// Now look for a group matching the access for this user with no authenticator. Favor smaller groups
|
||||
// over larger ones.
|
||||
stmt = conn.prepareStatement("SELECT a.ugid, COUNT(g2.uid) AS gsize FROM commaccess a, groupmembers g, "
|
||||
+ "groupmembers g2 WHERE a.cid = ? AND a.ugid = g.gid AND g.uid = ? "
|
||||
+ "AND a.is_group = 1 AND a.auth_nsid IS NULL AND a.auth_name IS NULL "
|
||||
+ "AND g2.gid = a.ugid GROUP BY g2.gid ORDER BY gsize;");
|
||||
stmt.setInt(1,cid);
|
||||
stmt.setInt(2,uid);
|
||||
rs = stmt.executeQuery();
|
||||
if (rs.next())
|
||||
return new Integer(rs.getInt(1));
|
||||
|
||||
} // end try
|
||||
catch (SQLException e)
|
||||
{ // translate to a general DatabaseException
|
||||
throw generalException(e);
|
||||
|
||||
} // end catch
|
||||
finally
|
||||
{ // shut everything down
|
||||
SQLUtils.shutdown(rs);
|
||||
SQLUtils.shutdown(stmt);
|
||||
SQLUtils.shutdown(conn);
|
||||
|
||||
} // end finally
|
||||
|
||||
return null; // nothing else found...
|
||||
|
||||
} // end getJoinEntryNull
|
||||
|
||||
Object getJoinEntry(int cid, int uid, int auth_nsid, String auth_name, String source_data) throws DatabaseException
|
||||
{
|
||||
Connection conn = null;
|
||||
PreparedStatement stmt = null;
|
||||
ResultSet rs = null;
|
||||
try
|
||||
{ // get a connection
|
||||
conn = getConnection();
|
||||
|
||||
// try looking for a user-level entry first
|
||||
stmt = conn.prepareStatement("SELECT single_use FROM commaccess WHERE cid = ? AND ugid = ? AND is_group = 0 "
|
||||
+ "AND auth_nsid = ? AND auth_name = ? AND source_data = ?;");
|
||||
stmt.setInt(1,cid);
|
||||
stmt.setInt(2,uid);
|
||||
stmt.setInt(3,auth_nsid);
|
||||
stmt.setString(4,auth_name);
|
||||
stmt.setString(5,source_data);
|
||||
rs = stmt.executeQuery();
|
||||
if (rs.next())
|
||||
return Boolean.TRUE;
|
||||
|
||||
SQLUtils.shutdown(rs); // reset for next statement
|
||||
rs = null;
|
||||
SQLUtils.shutdown(stmt);
|
||||
|
||||
// Now look for a group matching the access for this user with the specified authenticator. Favor smaller groups
|
||||
// over larger ones.
|
||||
stmt = conn.prepareStatement("SELECT a.ugid, COUNT(g2.uid) AS gsize FROM commaccess a, groupmembers g, "
|
||||
+ "groupmembers g2 WHERE a.cid = ? AND a.ugid = g.gid AND g.uid = ? "
|
||||
+ "AND a.is_group = 1 AND a.auth_nsid = ? AND a.auth_name = ? "
|
||||
+ "AND a.source_data = ? AND g2.gid = a.ugid GROUP BY g2.gid ORDER BY gsize;");
|
||||
stmt.setInt(1,cid);
|
||||
stmt.setInt(2,uid);
|
||||
stmt.setInt(3,auth_nsid);
|
||||
stmt.setString(4,auth_name);
|
||||
stmt.setString(5,source_data);
|
||||
rs = stmt.executeQuery();
|
||||
if (rs.next())
|
||||
return new Integer(rs.getInt(1));
|
||||
|
||||
} // end try
|
||||
catch (SQLException e)
|
||||
{ // translate to a general DatabaseException
|
||||
throw generalException(e);
|
||||
|
||||
} // end catch
|
||||
finally
|
||||
{ // shut everything down
|
||||
SQLUtils.shutdown(rs);
|
||||
SQLUtils.shutdown(stmt);
|
||||
SQLUtils.shutdown(conn);
|
||||
|
||||
} // end finally
|
||||
|
||||
return null; // nothing else found...
|
||||
|
||||
} // end getJoinEntry
|
||||
|
||||
String getAuthData(int cid, int ugid, boolean is_group) throws DatabaseException
|
||||
{
|
||||
Connection conn = null;
|
||||
PreparedStatement stmt = null;
|
||||
ResultSet rs = null;
|
||||
try
|
||||
{ // get a connection
|
||||
conn = getConnection();
|
||||
|
||||
// create and execute the statement
|
||||
stmt = conn.prepareStatement("SELECT auth_data FROM commaccess WHERE cid = ? AND ugid = ? AND is_group = ?;");
|
||||
stmt.setInt(1,cid);
|
||||
stmt.setInt(2,ugid);
|
||||
stmt.setInt(3,(is_group ? 1 : 0));
|
||||
rs = stmt.executeQuery();
|
||||
if (rs.next())
|
||||
return rs.getString(1);
|
||||
else
|
||||
return null;
|
||||
|
||||
} // end try
|
||||
catch (SQLException e)
|
||||
{ // translate to a general DatabaseException
|
||||
throw generalException(e);
|
||||
|
||||
} // end catch
|
||||
finally
|
||||
{ // shut everything down
|
||||
SQLUtils.shutdown(rs);
|
||||
SQLUtils.shutdown(stmt);
|
||||
SQLUtils.shutdown(conn);
|
||||
|
||||
} // end finally
|
||||
|
||||
} // end getAuthData
|
||||
|
||||
void deleteSingleUseAuthData(int cid, int ugid, boolean is_group) throws DatabaseException
|
||||
{
|
||||
Connection conn = null;
|
||||
PreparedStatement stmt = null;
|
||||
Statement stmt2 = null;
|
||||
ResultSet rs = null;
|
||||
try
|
||||
{ // get a connection
|
||||
conn = getConnection();
|
||||
|
||||
// lock the commaccess table
|
||||
stmt2 = conn.createStatement();
|
||||
stmt2.executeUpdate("LOCK TABLES commaccess WRITE;");
|
||||
|
||||
// see whether the auth data is single-use
|
||||
stmt = conn.prepareStatement("SELECT single_use FROM commaccess WHERE cid = ? AND ugid = ? AND is_group = ?;");
|
||||
stmt.setInt(1,cid);
|
||||
stmt.setInt(2,ugid);
|
||||
stmt.setInt(3,(is_group ? 1 : 0));
|
||||
rs = stmt.executeQuery();
|
||||
if (!(rs.next()))
|
||||
return;
|
||||
if (rs.getInt(1)==0)
|
||||
return;
|
||||
|
||||
SQLUtils.shutdown(rs); // reset for next statement
|
||||
rs = null;
|
||||
SQLUtils.shutdown(stmt);
|
||||
|
||||
// Now delete the authentication data.
|
||||
stmt = conn.prepareStatement("DELETE FROM commaccess WHERE cid = ? AND ugid = ? AND is_group = ?;");
|
||||
stmt.setInt(1,cid);
|
||||
stmt.setInt(2,ugid);
|
||||
stmt.setInt(3,(is_group ? 1 : 0));
|
||||
stmt.executeUpdate();
|
||||
|
||||
} // end try
|
||||
catch (SQLException e)
|
||||
{ // translate to a general DatabaseException
|
||||
throw generalException(e);
|
||||
|
||||
} // end catch
|
||||
finally
|
||||
{ // shut everything down
|
||||
MySQLUtils.unlockTables(conn);
|
||||
SQLUtils.shutdown(rs);
|
||||
SQLUtils.shutdown(stmt);
|
||||
SQLUtils.shutdown(stmt2);
|
||||
SQLUtils.shutdown(conn);
|
||||
|
||||
} // end finally
|
||||
|
||||
} // end deleteSingleUseAuthData
|
||||
|
||||
} // end class CommunityOps_mysql
|
||||
|
||||
@@ -590,6 +590,19 @@ abstract class CommunityProxy implements VeniceCommunity, DynamicWrapper
|
||||
|
||||
} // end getJoinRequirement
|
||||
|
||||
public boolean join(DynamoUser joiner, String auth_namespace, String auth_name, String source_info,
|
||||
String auth_info) throws DatabaseException, DynamoSecurityException
|
||||
{
|
||||
return getRealCommunity().join(joiner,auth_namespace,auth_name,source_info,auth_info);
|
||||
|
||||
} // end join
|
||||
|
||||
public boolean join(DynamoUser joiner) throws DatabaseException, DynamoSecurityException
|
||||
{
|
||||
return this.join(joiner,null,null,null,null);
|
||||
|
||||
} // end join
|
||||
|
||||
/*--------------------------------------------------------------------------------
|
||||
* Implementations from interface DynamicWrapper
|
||||
*--------------------------------------------------------------------------------
|
||||
|
||||
@@ -299,11 +299,16 @@ public interface VeniceCommunity extends NamedObject, SecureObjectStore
|
||||
* community.</LI>
|
||||
* </UL>
|
||||
*
|
||||
* @param joiner The user to test atainst the current community.
|
||||
* @param joiner The user to test against 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;
|
||||
|
||||
public boolean join(DynamoUser joiner, String auth_namespace, String auth_name, String source_info,
|
||||
String auth_info) throws DatabaseException, DynamoSecurityException;
|
||||
|
||||
public boolean join(DynamoUser joiner) throws DatabaseException, DynamoSecurityException;
|
||||
|
||||
} // end interface VeniceCommunity
|
||||
|
||||
@@ -147,4 +147,12 @@ public class LibraryVeniceCast
|
||||
|
||||
} // end toSideboxDescriptor
|
||||
|
||||
public final VeniceCommunity toVeniceCommunity(Object obj)
|
||||
{
|
||||
if (obj instanceof VeniceCommunity)
|
||||
return (VeniceCommunity)obj;
|
||||
throw new ClassCastException("LibraryVeniceCast.toVeniceCommunity: invalid cast");
|
||||
|
||||
} // end toVeniceCommunity
|
||||
|
||||
} // end class LibraryVeniceCast
|
||||
|
||||
Reference in New Issue
Block a user