From db492cf185d9bfb1ccec66275812cda5379a8d56 Mon Sep 17 00:00:00 2001 From: "Eric J. Bowersox" Date: Wed, 25 Jun 2003 07:46:20 +0000 Subject: [PATCH] some work on the ACLs to improve their editability, creation of the ACL helper, creation of the first conferencing permissions, and the use of those permissions in the first conference display --- conf/venice-db-init-mysql.sql | 8 +- .../scripts/conferences.js | 13 + .../velocity/conferences.vm | 17 +- .../venice/conf/ConfNamespaces.java | 3 + .../venice/conf/module/Controller.java | 78 ++++- .../venice/conf/module/ModuleMain.java | 26 +- .../conf/module/ModuleMessages.properties | 2 + .../silverwrist/dynamo/iface/DynamoAce.java | 13 +- .../silverwrist/dynamo/iface/DynamoAcl.java | 7 +- .../dynamo/security/AceObject.java | 45 ++- .../dynamo/security/AclObject.java | 18 +- .../dynamo/security/AclOperations.java | 8 +- .../dynamo/security/AclOperations_mysql.java | 278 +++++++++++------- .../dynamo/security/SRMObject.java | 3 +- .../venice/util/AclEditHelper.java | 160 ++++++++++ 15 files changed, 556 insertions(+), 123 deletions(-) create mode 100644 src/venice-base/com/silverwrist/venice/util/AclEditHelper.java diff --git a/conf/venice-db-init-mysql.sql b/conf/venice-db-init-mysql.sql index 77cb82b..718c66c 100644 --- a/conf/venice-db-init-mysql.sql +++ b/conf/venice-db-init-mysql.sql @@ -586,8 +586,12 @@ INSERT INTO globalprop (nsid, prop_name, prop_value) VALUES (6, 'bnc.configure', '!Configure' ), (6, 'bn.create', '!create.jpg' ), (6, 'bnc.create', '!Create' ), + (6, 'bn.create.new', '!create_new.jpg' ), + (6, 'bnc.create.new', '!Create New' ), (6, 'bn.federate', '!federate.jpg' ), (6, 'bnc.federate', '!Federate' ), + (6, 'bn.find', '!find.jpg' ), + (6, 'bnc.find', '!Find' ), (6, 'bn.i.accept', '!user_accept.jpg' ), (6, 'bnc.i.accept', '!I Accept' ), (6, 'bn.i.decline', '!user_decline.jpg' ), @@ -596,6 +600,8 @@ INSERT INTO globalprop (nsid, prop_name, prop_value) VALUES (6, 'bnc.login', '!Log In' ), (6, 'bn.logout', '!logout.jpg' ), (6, 'bnc.logout', '!Log Out' ), + (6, 'bn.manage', '!manage.jpg' ), + (6, 'bnc.manage', '!Manage' ), (6, 'bn.next', '!arrow_next.jpg' ), (6, 'bnc.next', '!Next' ), (6, 'bn.no', '!no.jpg' ), @@ -937,7 +943,7 @@ UPDATE groups SET gaclid = 4 WHERE gid = 5; # Create the ACL for the initial community. # (ACL 5, ACEs 9, 10, 11, 12) INSERT INTO acl (aclid, aclname) VALUES (5, 'ACL:piazza'); -INSERT INTO aclowner (aclid, ownerid, flags) VALUES (5, 5, 1); +INSERT INTO aclowner (aclid, ownerid, flags) VALUES (5, 5, 1), (5, 1, 1), (5, 1, 0); INSERT INTO ace (aceid, pri, flags) VALUES (12, 2, 16); INSERT INTO acldata (aclid, seq, aceid) VALUES (5, 0, 12); INSERT INTO acedata (aceid, perm_nsid, perm_name) VALUES diff --git a/resources/conferencing-module/scripts/conferences.js b/resources/conferencing-module/scripts/conferences.js index 0284967..b3d6033 100644 --- a/resources/conferencing-module/scripts/conferences.js +++ b/resources/conferencing-module/scripts/conferences.js @@ -30,4 +30,17 @@ comm = vlib.getCommunity(req); // get community // Create the view. rc = new VelocityView("Conference List: " + comm.name,"conf/conferences.vm"); rc.setParameter("community",comm); + +// Can we manage the conference list? +perm_namespace = "http://www.silverwrist.com/NS/venice/2003/06/25/conferencing.permissions"; +srm = cast.querySecurityReferenceMonitor(req_help.getRequestObject(Namespaces.DYNAMO_OBJECT_NAMESPACE,"srm")); +acl1 = comm.getAcl(); +acl2 = srm.getGlobalAcl(); +if (acl1.testPermission(user,perm_namespace,"manage.order") || acl2.testPermission(user,perm_namespace,"manage.order")) + rc.setParameter("can_manage",Boolean.TRUE); + +// Can we create new conferences? +if (acl1.testPermission(user,perm_namespace,"create") || acl2.testPermission(user,perm_namespace,"create")) + rc.setParameter("can_create",Boolean.TRUE); + dynamo.scriptOutput(rc); diff --git a/resources/conferencing-module/velocity/conferences.vm b/resources/conferencing-module/velocity/conferences.vm index b81670c..677fabb 100644 --- a/resources/conferencing-module/velocity/conferences.vm +++ b/resources/conferencing-module/velocity/conferences.vm @@ -17,7 +17,9 @@ *# #* Parameters: - community = The community we're getting the conferences of. + community = The community we're getting the conferences of. + can_manage = Set if we can manage the ordering of conferences. + can_create = Set if we can create new conferences. *# #header2( "Conference List:" $community.Name ) ## TEMPORARY @@ -25,3 +27,16 @@ magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

+## END TEMPORARY +
+ #set( $cid = $community.getCID() ) + #button( "IMAGE" "find" ) + #if( $can_manage ) +    + #button( "IMAGE" "manage" ) + #end + #if( $can_create ) +    + #button( "IMAGE" "create.new" ) + #end +
diff --git a/src/conferencing-module/com/silverwrist/venice/conf/ConfNamespaces.java b/src/conferencing-module/com/silverwrist/venice/conf/ConfNamespaces.java index aad8d1f..d195de1 100644 --- a/src/conferencing-module/com/silverwrist/venice/conf/ConfNamespaces.java +++ b/src/conferencing-module/com/silverwrist/venice/conf/ConfNamespaces.java @@ -22,4 +22,7 @@ public interface ConfNamespaces public static final String CONFERENCING_NAMESPACE = "http://www.silverwrist.com/NS/venice/2003/06/19/conferencing"; + public static final String PERMISSIONS_NAMESPACE = + "http://www.silverwrist.com/NS/venice/2003/06/25/conferencing.permissions"; + } // end interface ConfNamespaces diff --git a/src/conferencing-module/com/silverwrist/venice/conf/module/Controller.java b/src/conferencing-module/com/silverwrist/venice/conf/module/Controller.java index 0667af6..bf02fbe 100644 --- a/src/conferencing-module/com/silverwrist/venice/conf/module/Controller.java +++ b/src/conferencing-module/com/silverwrist/venice/conf/module/Controller.java @@ -17,16 +17,29 @@ */ package com.silverwrist.venice.conf.module; +import java.security.Principal; +import java.security.acl.*; import java.util.*; +import org.apache.log4j.Logger; import com.silverwrist.dynamo.except.*; import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.security.SecurityReferenceMonitor; import com.silverwrist.venice.except.*; import com.silverwrist.venice.iface.*; import com.silverwrist.venice.obj.*; +import com.silverwrist.venice.util.*; +import com.silverwrist.venice.conf.ConfNamespaces; import com.silverwrist.venice.conf.iface.UseCount; class Controller implements CommunityServiceController { + /*-------------------------------------------------------------------------------- + * Static data members + *-------------------------------------------------------------------------------- + */ + + private static Logger logger = Logger.getLogger(Controller.class); + /*-------------------------------------------------------------------------------- * Attributes *-------------------------------------------------------------------------------- @@ -34,17 +47,19 @@ class Controller implements CommunityServiceController private DynamicImplCommunityServiceController m_dobj; private UseCount m_uc; + private String m_srm_name; /*-------------------------------------------------------------------------------- * Constructor *-------------------------------------------------------------------------------- */ - Controller(UseCount uc) + Controller(UseCount uc, String srm_name) { m_dobj = new DynamicImplCommunityServiceController(this); m_uc = uc; uc.incrementUseCount(); + m_srm_name = srm_name; } // end constructor @@ -110,12 +125,67 @@ class Controller implements CommunityServiceController public void addServiceToCommunity(Request req, VeniceCommunity comm) throws DatabaseException, CommunityServiceException { - } + if (logger.isDebugEnabled()) + logger.debug("[Conferencing service] addServiceToCommunity(" + req.toString() + ", " + comm.getName() + ")"); + AclEditHelper helper = new AclEditHelper(req,m_srm_name); + DynamoUser hostuser = comm.getHostUser(); + DynamoGroup hostgroup = comm.getHostGroup(); + try + { // add the necessary default permissions to the community ACL + DynamoAcl acl = comm.getAcl(); + helper.addPermission(hostuser,acl,hostgroup,false,ConfNamespaces.PERMISSIONS_NAMESPACE,"create"); + helper.addPermission(hostuser,acl,hostgroup,false,ConfNamespaces.PERMISSIONS_NAMESPACE,"manage.order"); + + } // end try + catch (AclNotFoundException e) + { // what happened to the community's ACL? + CommunityServiceException cse = new CommunityServiceException(Controller.class,"ModuleMessages","cse.noAcl",e); + cse.setParameter(0,comm.getName()); + throw cse; + + } // end catch + catch (NotOwnerException e) + { // damn! we need to be the ACL owner! + CommunityServiceException cse = new CommunityServiceException(Controller.class,"ModuleMessages", + "cse.notAclOwner",e); + cse.setParameter(0,comm.getName()); + throw cse; + + } // end catch + + } // end addServiceToCommunity public void removeServiceFromCommunity(Request req, VeniceCommunity comm) throws DatabaseException, CommunityServiceException { - } + if (logger.isDebugEnabled()) + logger.debug("[Conferencing service] removeServiceFromCommunity(" + req.toString() + ", " + comm.getName() + + ")"); + AclEditHelper helper = new AclEditHelper(req,m_srm_name); + DynamoUser hostuser = comm.getHostUser(); + try + { // remove permissions from the community ACL + DynamoAcl acl = comm.getAcl(); + helper.stripPermission(hostuser,acl,ConfNamespaces.PERMISSIONS_NAMESPACE,"create"); + helper.stripPermission(hostuser,acl,ConfNamespaces.PERMISSIONS_NAMESPACE,"manage.order"); + + } // end try + catch (AclNotFoundException e) + { // what happened to the community's ACL? + CommunityServiceException cse = new CommunityServiceException(Controller.class,"ModuleMessages","cse.noAcl",e); + cse.setParameter(0,comm.getName()); + throw cse; + + } // end catch + catch (NotOwnerException e) + { // damn! we need to be the ACL owner! + CommunityServiceException cse = new CommunityServiceException(Controller.class,"ModuleMessages", + "cse.notAclOwner",e); + cse.setParameter(0,comm.getName()); + throw cse; + + } // end catch + + } // end removeServiceFromCommunity } // end class Controller - diff --git a/src/conferencing-module/com/silverwrist/venice/conf/module/ModuleMain.java b/src/conferencing-module/com/silverwrist/venice/conf/module/ModuleMain.java index 70a31c6..eb31275 100644 --- a/src/conferencing-module/com/silverwrist/venice/conf/module/ModuleMain.java +++ b/src/conferencing-module/com/silverwrist/venice/conf/module/ModuleMain.java @@ -57,6 +57,7 @@ public class ModuleMain implements ModuleFunctions, UseCount private int m_usecount = 0; private ModuleSite m_site = null; + private String m_srm_name = null; private Controller m_controller = null; private ComponentShutdown m_res1; private ComponentShutdown m_res2; @@ -93,6 +94,15 @@ public class ModuleMain implements ModuleFunctions, UseCount } // end getInstallScript + private synchronized final void loadSRMName(ServiceProvider sp) + { + if (m_srm_name!=null) + return; + ModuleConfigurationData conf_data = (ModuleConfigurationData)(sp.queryService(ModuleConfigurationData.class)); + m_srm_name = conf_data.getValue(Namespaces.DYNAMO_OBJECT_NAMESPACE,"security"); + + } // end loadSRMName + /*-------------------------------------------------------------------------------- * Implementations from interface ModuleFunctions *-------------------------------------------------------------------------------- @@ -113,6 +123,7 @@ public class ModuleMain implements ModuleFunctions, UseCount public void initialize(ModuleSite site, ServiceProvider services) throws ModuleException { + loadSRMName(services); m_site = site; try @@ -151,15 +162,12 @@ public class ModuleMain implements ModuleFunctions, UseCount public boolean canInstall(ServiceProvider services, Principal installer) { + loadSRMName(services); try - { // get the module configuration data to get the SRM name, then use that to get the actual SRM, then get - // the global ACL, then test permissions - ModuleConfigurationData conf_data = - (ModuleConfigurationData)(services.queryService(ModuleConfigurationData.class)); - String srm_name = conf_data.getValue(Namespaces.DYNAMO_OBJECT_NAMESPACE,"security"); + { // get the actual SRM, then get the global ACL, then test permissions SecurityReferenceMonitor srm = (SecurityReferenceMonitor)(GetObjectUtils.getDynamoComponent(services,SecurityReferenceMonitor.class, - srm_name)); + m_srm_name)); DynamoAcl gacl = srm.getGlobalAcl(); return gacl.testPermission((DynamoUser)installer,VeniceNamespaces.SYSTEM_PERMS_NAMESPACE,"edit.menus"); @@ -175,10 +183,11 @@ public class ModuleMain implements ModuleFunctions, UseCount public void install(ModuleSite site, ServiceProvider services, Principal installer, DynamoLog log) throws ModuleException { + loadSRMName(services); synchronized (this) { // create Controller object if necessary if (m_controller==null) - m_controller = new Controller(this); + m_controller = new Controller(this,m_srm_name); } // end synchronized block @@ -236,6 +245,7 @@ public class ModuleMain implements ModuleFunctions, UseCount public void uninstall(ModuleSite site, ServiceProvider services, Principal uninstaller, DynamoLog log) throws ModuleException { + loadSRMName(services); try { // uninstall the community service CommunityServiceInstall csi = (CommunityServiceInstall)(services.queryService(CommunityServiceInstall.class)); @@ -290,7 +300,7 @@ public class ModuleMain implements ModuleFunctions, UseCount synchronized (this) { // create it if necessary if (m_controller==null) - m_controller = new Controller(this); + m_controller = new Controller(this,m_srm_name); return m_controller; } // end synchronized block diff --git a/src/conferencing-module/com/silverwrist/venice/conf/module/ModuleMessages.properties b/src/conferencing-module/com/silverwrist/venice/conf/module/ModuleMessages.properties index eb0a9f3..0af9415 100644 --- a/src/conferencing-module/com/silverwrist/venice/conf/module/ModuleMessages.properties +++ b/src/conferencing-module/com/silverwrist/venice/conf/module/ModuleMessages.properties @@ -22,3 +22,5 @@ uninstall.service.fail=Failed to uninstall community service object: {0} install.cmenu.fail=Failed to install community menu items: {0} uninstall.cmenu.fail=Failed to uninstall community menu items: {0} no.db.script=Unable to find the database initialization script "{0}." +cse.notAclOwner=Internal error: host of community "{0}" must be an owner of its ACL. +cse.noAcl=Internal error: ACL not found for community "{0}." diff --git a/src/dynamo-framework/com/silverwrist/dynamo/iface/DynamoAce.java b/src/dynamo-framework/com/silverwrist/dynamo/iface/DynamoAce.java index 1202a83..6ab7506 100644 --- a/src/dynamo-framework/com/silverwrist/dynamo/iface/DynamoAce.java +++ b/src/dynamo-framework/com/silverwrist/dynamo/iface/DynamoAce.java @@ -11,16 +11,27 @@ * * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are - * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ package com.silverwrist.dynamo.iface; import java.security.acl.AclEntry; +import com.silverwrist.dynamo.except.DatabaseException; public interface DynamoAce extends AclEntry { public int getAceID(); + public boolean isGroupAce(); + + public int getNumPermissions(); + + public boolean addPermission(String namespace, String name) throws DatabaseException; + + public boolean removePermission(String namespace, String name) throws DatabaseException; + + public boolean checkPermission(String namespace, String name) throws DatabaseException; + } // end interface DynamoAce diff --git a/src/dynamo-framework/com/silverwrist/dynamo/iface/DynamoAcl.java b/src/dynamo-framework/com/silverwrist/dynamo/iface/DynamoAcl.java index 86ddff9..5596a80 100644 --- a/src/dynamo-framework/com/silverwrist/dynamo/iface/DynamoAcl.java +++ b/src/dynamo-framework/com/silverwrist/dynamo/iface/DynamoAcl.java @@ -11,7 +11,7 @@ * * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are - * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ @@ -31,6 +31,11 @@ public interface DynamoAcl extends Acl, NamedObject public DynamoAce getAce(Principal caller, int index) throws DatabaseException, NotOwnerException; + public DynamoAce getMatchingAce(Principal caller, Principal target, boolean negative) + throws DatabaseException, NotOwnerException; + + public int getIndexOfAce(Principal caller, DynamoAce ace) throws DatabaseException, NotOwnerException; + public boolean insertEntry(Principal caller, AclEntry entry, int at_index) throws DatabaseException, NotOwnerException; diff --git a/src/dynamo-framework/com/silverwrist/dynamo/security/AceObject.java b/src/dynamo-framework/com/silverwrist/dynamo/security/AceObject.java index d6f1094..faad784 100644 --- a/src/dynamo-framework/com/silverwrist/dynamo/security/AceObject.java +++ b/src/dynamo-framework/com/silverwrist/dynamo/security/AceObject.java @@ -11,7 +11,7 @@ * * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are - * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ @@ -309,6 +309,49 @@ class AceObject implements DynamoAce } // end getAceID + public boolean isGroupAce() + { + return m_pr.isGroup(); + + } // end isGroupAce + + public int getNumPermissions() + { + return m_perms.size(); + + } // end getNumPermissions + + public synchronized boolean addPermission(String namespace, String name) throws DatabaseException + { + PropertyKey pkey = new PropertyKey(m_ns_cache.namespaceNameToId(namespace),name); + PermObject pobj = new PermObject(pkey,m_ns_cache); + if (m_perms.contains(pobj)) + return false; + m_ops.addPermission(m_aceid,pkey); + m_perms.add(pobj); + return true; + + } // end addPermission + + public synchronized boolean removePermission(String namespace, String name) throws DatabaseException + { + PropertyKey pkey = new PropertyKey(m_ns_cache.namespaceNameToId(namespace),name); + PermObject pobj = new PermObject(pkey,m_ns_cache); + if (!(m_perms.contains(pobj))) + return false; + m_ops.removePermission(m_aceid,pkey); + m_perms.remove(pobj); + return true; + + } // end removePermission + + public synchronized boolean checkPermission(String namespace, String name) throws DatabaseException + { + PermObject pobj = new PermObject(new PropertyKey(m_ns_cache.namespaceNameToId(namespace),name),m_ns_cache); + return m_perms.contains(pobj); + + } // end checkPermission + /*-------------------------------------------------------------------------------- * External operations *-------------------------------------------------------------------------------- diff --git a/src/dynamo-framework/com/silverwrist/dynamo/security/AclObject.java b/src/dynamo-framework/com/silverwrist/dynamo/security/AclObject.java index 6325398..e93229d 100644 --- a/src/dynamo-framework/com/silverwrist/dynamo/security/AclObject.java +++ b/src/dynamo-framework/com/silverwrist/dynamo/security/AclObject.java @@ -11,7 +11,7 @@ * * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are - * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ @@ -327,6 +327,22 @@ class AclObject implements DynamoAcl } // end getAce + public DynamoAce getMatchingAce(Principal caller, Principal target, boolean negative) + throws DatabaseException, NotOwnerException + { + int aid = m_ops.getMatchingAceID(m_aclid,new PrincipalID(caller),new PrincipalID(target),negative); + if (aid<0) + return null; + return m_ace_cache.getAce(aid); + + } // end getMatchingAce + + public int getIndexOfAce(Principal caller, DynamoAce ace) throws DatabaseException, NotOwnerException + { + return m_ops.getIndexOfAceIDInAcl(m_aclid,new PrincipalID(caller),ace.getAceID()); + + } // end getIndexOfAce + public boolean insertEntry(Principal caller, AclEntry entry, int at_index) throws DatabaseException, NotOwnerException { diff --git a/src/dynamo-framework/com/silverwrist/dynamo/security/AclOperations.java b/src/dynamo-framework/com/silverwrist/dynamo/security/AclOperations.java index 1917fab..6a10802 100644 --- a/src/dynamo-framework/com/silverwrist/dynamo/security/AclOperations.java +++ b/src/dynamo-framework/com/silverwrist/dynamo/security/AclOperations.java @@ -11,7 +11,7 @@ * * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are - * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ @@ -69,6 +69,12 @@ abstract class AclOperations extends OpsBase abstract int getAceID(int aclid, PrincipalID caller, int index) throws DatabaseException, NotOwnerException; + abstract int getMatchingAceID(int aclid, PrincipalID caller, PrincipalID target, boolean negative) + throws DatabaseException, NotOwnerException; + + abstract int getIndexOfAceIDInAcl(int aclid, PrincipalID caller, int aceid) + throws DatabaseException, NotOwnerException; + abstract boolean insertAce(int aclid, PrincipalID caller, int aceid, int at_index) throws DatabaseException, NotOwnerException; diff --git a/src/dynamo-framework/com/silverwrist/dynamo/security/AclOperations_mysql.java b/src/dynamo-framework/com/silverwrist/dynamo/security/AclOperations_mysql.java index f2f6d3f..fef3366 100644 --- a/src/dynamo-framework/com/silverwrist/dynamo/security/AclOperations_mysql.java +++ b/src/dynamo-framework/com/silverwrist/dynamo/security/AclOperations_mysql.java @@ -75,6 +75,42 @@ class AclOperations_mysql extends AclOperations } // end constructor + /*-------------------------------------------------------------------------------- + * Internal operations + *-------------------------------------------------------------------------------- + */ + + private static final boolean testOwner(Connection conn, int aclid, PrincipalID owner) throws SQLException + { + PreparedStatement stmt = null; + ResultSet rs = null; + try + { // prepare the statement + stmt = conn.prepareStatement(OWNER_TEST_STMT); + stmt.setInt(1,aclid); + stmt.setInt(2,owner.getID()); + stmt.setInt(3,(owner.isGroup() ? OWNERFLAG_GROUP : OWNERFLAG_USER)); + rs = stmt.executeQuery(); + return rs.next(); + + } // end try + finally + { // shut down things + SQLUtils.shutdown(rs); + SQLUtils.shutdown(stmt); + + } // end finally + + } // end testOwner + + private static final void ensureOwner(Connection conn, int aclid, PrincipalID owner) + throws SQLException, NotOwnerException + { + if (!testOwner(conn,aclid,owner)) + throw new NotOwnerException(); + + } // end ensureOwner + /*-------------------------------------------------------------------------------- * Abstract implementations from class AclOperations *-------------------------------------------------------------------------------- @@ -83,19 +119,10 @@ class AclOperations_mysql extends AclOperations boolean testOwner(int aclid, PrincipalID owner) throws DatabaseException { Connection conn = null; - PreparedStatement stmt = null; - ResultSet rs = null; try { // get a connection conn = getConnection(); - - // create the appropriate SQL statement - stmt = conn.prepareStatement(OWNER_TEST_STMT); - stmt.setInt(1,aclid); - stmt.setInt(2,owner.getID()); - stmt.setInt(3,(owner.isGroup() ? OWNERFLAG_GROUP : OWNERFLAG_USER)); - rs = stmt.executeQuery(); - return rs.next(); + return testOwner(conn,aclid,owner); } // end try catch (SQLException e) @@ -105,8 +132,6 @@ class AclOperations_mysql extends AclOperations } // end catch finally { // shut everything down - SQLUtils.shutdown(rs); - SQLUtils.shutdown(stmt); SQLUtils.shutdown(conn); } // end finally @@ -141,15 +166,15 @@ class AclOperations_mysql extends AclOperations stmt.setInt(1,aclid); stmt.setInt(2,owner.getID()); stmt.setInt(3,(owner.isGroup() ? OWNERFLAG_GROUP : OWNERFLAG_USER)); - SQLUtils.shutdown(rs); + rs.close(); rs = stmt.executeQuery(); if (rs.next()) return false; // owner already present // insert the new owner record - SQLUtils.shutdown(rs); + rs.close(); rs = null; - SQLUtils.shutdown(stmt); + stmt.close(); stmt = conn.prepareStatement("INSERT INTO aclowner (aclid, ownerid, flags) VALUES (?, ?, ?);"); stmt.setInt(1,aclid); stmt.setInt(2,owner.getID()); @@ -203,15 +228,15 @@ class AclOperations_mysql extends AclOperations stmt.setInt(1,aclid); stmt.setInt(2,owner.getID()); stmt.setInt(3,(owner.isGroup() ? OWNERFLAG_GROUP : OWNERFLAG_USER)); - SQLUtils.shutdown(rs); + rs.close(); rs = stmt.executeQuery(); if (!(rs.next())) return false; // owner not present // is the owner we're about to remove the last one? - SQLUtils.shutdown(rs); + rs.close(); rs = null; - SQLUtils.shutdown(stmt); + stmt.close(); stmt = conn.prepareStatement("SELECT COUNT(*) FROM aclowner WHERE aclid = ?;"); stmt.setInt(1,aclid); rs = stmt.executeQuery(); @@ -219,9 +244,9 @@ class AclOperations_mysql extends AclOperations throw new LastOwnerException(); // OK, go ahead and delete it. - SQLUtils.shutdown(rs); + rs.close(); rs = null; - SQLUtils.shutdown(stmt); + stmt.close(); stmt = conn.prepareStatement("DELETE FROM aclowner WHERE aclid = ? AND ownerid = ? AND flags = ?;"); stmt.setInt(1,aclid); stmt.setInt(2,owner.getID()); @@ -252,7 +277,6 @@ class AclOperations_mysql extends AclOperations Connection conn = null; PreparedStatement stmt = null; Statement stmt2 = null; - ResultSet rs = null; try { // get a connection conn = getConnection(); @@ -262,24 +286,14 @@ class AclOperations_mysql extends AclOperations stmt2.executeUpdate("LOCK TABLES acl WRITE, aclowner READ;"); // test to see if we own the thing first - stmt = conn.prepareStatement(OWNER_TEST_STMT); - stmt.setInt(1,aclid); - stmt.setInt(2,caller.getID()); - stmt.setInt(3,(caller.isGroup() ? OWNERFLAG_GROUP : OWNERFLAG_USER)); - rs = stmt.executeQuery(); - if (!(rs.next())) - throw new NotOwnerException(); + ensureOwner(conn,aclid,caller); // poke in the new name - SQLUtils.shutdown(rs); - rs = null; - SQLUtils.shutdown(stmt); stmt = conn.prepareStatement("UPDATE acl SET aclname = ? WHERE aclid = ?;"); stmt.setString(1,name); stmt.setInt(2,aclid); stmt.executeUpdate(); - } // end try catch (SQLException e) { // translate to a general DatabaseException @@ -289,7 +303,6 @@ class AclOperations_mysql extends AclOperations finally { // shut everything down MySQLUtils.unlockTables(conn); - SQLUtils.shutdown(rs); SQLUtils.shutdown(stmt); SQLUtils.shutdown(stmt2); SQLUtils.shutdown(conn); @@ -344,18 +357,9 @@ class AclOperations_mysql extends AclOperations stmt2.executeUpdate("LOCK TABLES acldata READ, aclowner READ;"); // test to see if we own the thing first - stmt = conn.prepareStatement(OWNER_TEST_STMT); - stmt.setInt(1,aclid); - stmt.setInt(2,caller.getID()); - stmt.setInt(3,(caller.isGroup() ? OWNERFLAG_GROUP : OWNERFLAG_USER)); - rs = stmt.executeQuery(); - if (!(rs.next())) - throw new NotOwnerException(); + ensureOwner(conn,aclid,caller); // now query the ACL data to find the ACE ID - SQLUtils.shutdown(rs); - rs = null; - SQLUtils.shutdown(stmt); stmt = conn.prepareStatement("SELECT aceid FROM acldata WHERE aclid = ? AND seq = ?;"); stmt.setInt(1,aclid); stmt.setInt(2,index); @@ -382,6 +386,100 @@ class AclOperations_mysql extends AclOperations } // end getAceId + int getMatchingAceID(int aclid, PrincipalID caller, PrincipalID target, boolean negative) + throws DatabaseException, NotOwnerException + { + Connection conn = null; + PreparedStatement stmt = null; + Statement stmt2 = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // lock the tables we need + stmt2 = conn.createStatement(); + stmt2.executeUpdate("LOCK TABLES acldata READ, ace READ, aclowner READ;"); + + // test to see if we own the thing first + ensureOwner(conn,aclid,caller); + + // prepare and execute the query statement + stmt = conn.prepareStatement("SELECT f.aceid FROM acldata f, ace a WHERE f.aceid = a.aceid AND f.aclid = ? " + + "AND a.pri = ? AND a.flags = ? ORDER BY f.seq;"); + stmt.setInt(1,aclid); + stmt.setInt(2,target.getID()); + stmt.setInt(3,(target.isGroup() ? PRINCIPALFLAG_GROUP : PRINCIPALFLAG_USER) + | (negative ? ACEFLAG_NEGATIVE : ACEFLAG_POSITIVE)); + rs = stmt.executeQuery(); + if (rs.next()) + return rs.getInt(1); + else + return -1; + + } // 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 getMatchingAceID + + int getIndexOfAceIDInAcl(int aclid, PrincipalID caller, int aceid) throws DatabaseException, NotOwnerException + { + Connection conn = null; + PreparedStatement stmt = null; + Statement stmt2 = null; + ResultSet rs = null; + try + { // get a connection + conn = getConnection(); + + // lock the tables we need + stmt2 = conn.createStatement(); + stmt2.executeUpdate("LOCK TABLES acldata READ, aclowner READ;"); + + // test to see if we own the thing first + ensureOwner(conn,aclid,caller); + + // create and execute the statement + stmt = conn.prepareStatement("SELECT seq FROM acldata WHERE aclid = ? AND aceid = ?;"); + stmt.setInt(1,aclid); + stmt.setInt(2,aceid); + rs = stmt.executeQuery(); + if (rs.next()) + return rs.getInt(1); + else + return -1; + + } // 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 getIndexOfAceIDInAcl + boolean insertAce(int aclid, PrincipalID caller, int aceid, int at_index) throws DatabaseException, NotOwnerException { @@ -398,20 +496,11 @@ class AclOperations_mysql extends AclOperations stmt2.executeUpdate("LOCK TABLES acldata WRITE, aclowner READ, ace READ;"); // test to see if we own the thing first - stmt = conn.prepareStatement(OWNER_TEST_STMT); - stmt.setInt(1,aclid); - stmt.setInt(2,caller.getID()); - stmt.setInt(3,(caller.isGroup() ? OWNERFLAG_GROUP : OWNERFLAG_USER)); - rs = stmt.executeQuery(); - if (!(rs.next())) - throw new NotOwnerException(); + ensureOwner(conn,aclid,caller); // An ACL can contain at most one positive and one negative ACE for each unique Principal. // This translates out to a unique combination of principal ID and flags for each ACE. So // get the principal ID and flags from our specified ACE to test against the current ACL contents. - SQLUtils.shutdown(rs); - rs = null; - SQLUtils.shutdown(stmt); stmt = conn.prepareStatement("SELECT pri, flags FROM ace WHERE aceid = ?;"); stmt.setInt(1,aceid); rs = stmt.executeQuery(); @@ -428,9 +517,9 @@ class AclOperations_mysql extends AclOperations int ace_flags = rs.getInt(2); // Now conduct a query to look for another ACE with that same combination already in our ACL. - SQLUtils.shutdown(rs); + rs.close(); rs = null; - SQLUtils.shutdown(stmt); + stmt.close(); stmt = conn.prepareStatement("SELECT ace.aceid FROM ace, acldata WHERE ace.pri = ? AND ace.flags = ? " + "AND ace.aceid = acldata.aceid AND acldata.aclid = ?;"); stmt.setInt(1,ace_pri); @@ -441,9 +530,9 @@ class AclOperations_mysql extends AclOperations return false; // Figure out the new sequence number for this ACE. - SQLUtils.shutdown(rs); + rs.close(); rs = null; - SQLUtils.shutdown(stmt); + stmt.close(); stmt = conn.prepareStatement("SELECT MAX(seq) FROM acldata WHERE aclid = ?;"); stmt.setInt(1,aclid); rs = stmt.executeQuery(); @@ -458,9 +547,9 @@ class AclOperations_mysql extends AclOperations if (renumber) { // Renumber the other ACEs to provide room. - SQLUtils.shutdown(rs); + rs.close(); rs = null; - SQLUtils.shutdown(stmt); + stmt.close(); stmt = conn.prepareStatement("UPDATE acldata SET seq = seq + 1 WHERE seq >= ?;"); stmt.setInt(1,at_index); stmt.executeUpdate(); @@ -468,9 +557,9 @@ class AclOperations_mysql extends AclOperations } // end if // Now add the new record to the ACL data table. - SQLUtils.shutdown(rs); + rs.close(); rs = null; - SQLUtils.shutdown(stmt); + stmt.close(); stmt = conn.prepareStatement("INSERT INTO acldata (aclid, seq, aceid) VALUES (?, ?, ?);"); stmt.setInt(1,aclid); stmt.setInt(2,at_index); @@ -511,18 +600,9 @@ class AclOperations_mysql extends AclOperations stmt2.executeUpdate("LOCK TABLES acldata WRITE, aclowner READ;"); // test to see if we own the thing first - stmt = conn.prepareStatement(OWNER_TEST_STMT); - stmt.setInt(1,aclid); - stmt.setInt(2,caller.getID()); - stmt.setInt(3,(caller.isGroup() ? OWNERFLAG_GROUP : OWNERFLAG_USER)); - rs = stmt.executeQuery(); - if (!(rs.next())) - throw new NotOwnerException(); + ensureOwner(conn,aclid,caller); // Look for the ACE ID in the list, and get the old sequence number. - SQLUtils.shutdown(rs); - rs = null; - SQLUtils.shutdown(stmt); stmt = conn.prepareStatement("SELECT seq FROM acldata WHERE aclid = ? AND aceid = ?;"); stmt.setInt(1,aclid); stmt.setInt(2,aceid); @@ -532,16 +612,16 @@ class AclOperations_mysql extends AclOperations int old_seq = rs.getInt(1); // Remove this entry from the table. - SQLUtils.shutdown(rs); + rs.close(); rs = null; - SQLUtils.shutdown(stmt); + stmt.close(); stmt = conn.prepareStatement("DELETE FROM acldata WHERE aclid = ? AND seq = ?;"); stmt.setInt(1,aclid); stmt.setInt(2,old_seq); stmt.executeUpdate(); // Now renumber all the entries after the one we just updated. - SQLUtils.shutdown(stmt); + stmt.close(); stmt = conn.prepareStatement("UPDATE acldata SET seq = seq - 1 WHERE aclid = ? AND seq > ?;"); stmt.setInt(1,aclid); stmt.setInt(2,old_seq); @@ -576,12 +656,9 @@ class AclOperations_mysql extends AclOperations conn = getConnection(); // and here's the query... - stmt = conn.prepareStatement("SELECT acedata.perm_nsid, acedata.perm_name " - + "FROM acedata, ace, acldata, groupmembers " - + "WHERE acedata.aceid = ace.aceid AND ace.aceid = acldata.aceid " - + "AND acldata.aclid = ? AND ace.flags = ? " - + "AND ace.pri = groupmembers.gid AND groupmembers.uid = ? " - + "ORDER BY acldata.seq;"); + stmt = conn.prepareStatement("SELECT d.perm_nsid, d.perm_name FROM acedata d, ace a, acldata f, groupmembers m " + + "WHERE d.aceid = a.aceid AND a.aceid = f.aceid AND f.aclid = ? AND a.flags = ? " + + "AND a.pri = m.gid AND m.uid = ? ORDER BY f.seq;"); stmt.setInt(1,aclid); stmt.setInt(2,PRINCIPALFLAG_GROUP | (negative ? ACEFLAG_NEGATIVE : ACEFLAG_POSITIVE)); stmt.setInt(3,uid); @@ -619,10 +696,9 @@ class AclOperations_mysql extends AclOperations conn = getConnection(); // and here's the query... - stmt = conn.prepareStatement("SELECT acedata.perm_nsid, acedata.perm_name FROM acedata, ace, acldata " - + "WHERE acedata.aceid = ace.aceid AND ace.aceid = acldata.aceid " - + "AND acldata.aclid = ? AND ace.flags = ? AND ace.pri = ? " - + "ORDER BY acldata.seq;"); + stmt = conn.prepareStatement("SELECT d.perm_nsid, d.perm_name FROM acedata d, ace a, acldata f " + + "WHERE d.aceid = a.aceid AND a.aceid = f.aceid AND f.aclid = ? AND a.flags = ? " + + "AND a.pri = ? ORDER BY f.seq;"); stmt.setInt(1,aclid); stmt.setInt(2,PRINCIPALFLAG_GROUP | (negative ? ACEFLAG_NEGATIVE : ACEFLAG_POSITIVE)); stmt.setInt(3,gid); @@ -660,10 +736,9 @@ class AclOperations_mysql extends AclOperations conn = getConnection(); // and here's the query... - stmt = conn.prepareStatement("SELECT acedata.perm_nsid, acedata.perm_name FROM acedata, ace, acldata " - + "WHERE acedata.aceid = ace.aceid AND ace.aceid = acldata.aceid " - + "AND acldata.aclid = ? AND ace.flags = ? AND ace.pri = ? " - + "ORDER BY acldata.seq;"); + stmt = conn.prepareStatement("SELECT d.perm_nsid, d.perm_name FROM acedata d, ace a, acldata f " + + "WHERE d.aceid = a.aceid AND a.aceid = f.aceid AND f.aclid = ? AND a.flags = ? " + + "AND a.pri = ? ORDER BY f.seq;"); stmt.setInt(1,aclid); stmt.setInt(2,PRINCIPALFLAG_USER | (negative ? ACEFLAG_NEGATIVE : ACEFLAG_POSITIVE)); stmt.setInt(3,uid); @@ -705,11 +780,10 @@ class AclOperations_mysql extends AclOperations int table_index = 0; // test for positive and negative user values first - stmt = conn.prepareStatement("SELECT DISTINCT ace.aceid, ace.flags FROM acedata, ace, acldata, groupmembers " - + "WHERE acedata.perm_nsid = ? AND acedata.perm_name = ? " - + "AND acedata.aceid = ace.aceid AND ace.aceid = acldata.aceid " - + "AND acldata.aclid = ? AND (ace.flags = 0 OR ace.flags = 16) " - + "AND ace.pri = ?;"); + stmt = conn.prepareStatement("SELECT DISTINCT a.aceid, a.flags FROM acedata d, ace a, acldata f " + + "WHERE d.perm_nsid = ? AND d.perm_name = ? AND d.aceid = a.aceid " + + "AND a.aceid = f.aceid AND f.aclid = ? AND (a.flags = 0 OR a.flags = 16) " + + "AND a.pri = ?;"); stmt.setInt(1,perm.getNamespaceID()); stmt.setString(2,perm.getName()); stmt.setInt(3,aclid); @@ -743,11 +817,10 @@ class AclOperations_mysql extends AclOperations rs.close(); rs = null; stmt.close(); - stmt = conn.prepareStatement("SELECT DISTINCT ace.aceid, ace.flags FROM acedata, ace, acldata, groupmembers " - + "WHERE acedata.perm_nsid = ? AND acedata.perm_name = ? " - + "AND acedata.aceid = ace.aceid AND ace.aceid = acldata.aceid " - + "AND acldata.aclid = ? AND (ace.flags = 1 OR ace.flags = 17) " - + "AND ace.pri = groupmembers.gid AND groupmembers.uid = ?;"); + stmt = conn.prepareStatement("SELECT DISTINCT a.aceid, a.flags FROM acedata d, ace a, acldata f, groupmembers m " + + "WHERE d.perm_nsid = ? AND d.perm_name = ? AND d.aceid = a.aceid " + + "AND a.aceid = f.aceid AND d.aclid = ? AND (a.flags = 1 OR a.flags = 17) " + + "AND a.pri = m.gid AND m.uid = ?;"); stmt.setInt(1,perm.getNamespaceID()); stmt.setString(2,perm.getName()); stmt.setInt(3,aclid); @@ -811,11 +884,10 @@ class AclOperations_mysql extends AclOperations boolean negative = false; // test for positive and negative values simultaneously - stmt = conn.prepareStatement("SELECT DISTINCT acedata.aceid, acedata.aceflags FROM acedata, ace, acldata, " - + "groupmembers WHERE acedata.perm_nsid = ? AND acedata.perm_name = ? " - + "AND acedata.aceid = ace.aceid AND ace.aceid = acldata.aceid " - + "AND acldata.aclid = ? AND (ace.flags = 1 OR ace.flags = 17) " - + "AND ace.pri = ?;"); + stmt = conn.prepareStatement("SELECT DISTINCT d.aceid, d.aceflags FROM acedata d, ace a, acldata f, " + + "groupmembers m WHERE d.perm_nsid = ? AND d.perm_name = ? AND d.aceid = a.aceid " + + "AND a.aceid = f.aceid AND f.aclid = ? AND (a.flags = 1 OR a.flags = 17) " + + "AND a.pri = ?;"); stmt.setInt(1,perm.getNamespaceID()); stmt.setString(2,perm.getName()); stmt.setInt(3,aclid); diff --git a/src/dynamo-framework/com/silverwrist/dynamo/security/SRMObject.java b/src/dynamo-framework/com/silverwrist/dynamo/security/SRMObject.java index 15b046b..ee90168 100644 --- a/src/dynamo-framework/com/silverwrist/dynamo/security/SRMObject.java +++ b/src/dynamo-framework/com/silverwrist/dynamo/security/SRMObject.java @@ -11,7 +11,7 @@ * * The Initial Developer of the Original Code is Eric J. Bowersox , * for Silverwrist Design Studios. Portions created by Eric J. Bowersox are - * Copyright (C) 2002 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. + * Copyright (C) 2002-03 Eric J. Bowersox/Silverwrist Design Studios. All Rights Reserved. * * Contributor(s): */ @@ -282,6 +282,7 @@ public class SRMObject implements NamedObject, ComponentInitialize, ComponentShu } // end catch + // Register the property serializer. PropertySerializerRegistration pszreg = (PropertySerializerRegistration)(services.queryService(PropertySerializerRegistration.class)); m_shut_psz = pszreg.registerPropertySerializer(new AclSerialize()); diff --git a/src/venice-base/com/silverwrist/venice/util/AclEditHelper.java b/src/venice-base/com/silverwrist/venice/util/AclEditHelper.java new file mode 100644 index 0000000..7f132fa --- /dev/null +++ b/src/venice-base/com/silverwrist/venice/util/AclEditHelper.java @@ -0,0 +1,160 @@ +/* + * 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.util; + +import java.security.Principal; +import java.security.acl.*; +import java.util.*; +import org.apache.log4j.Logger; +import com.silverwrist.dynamo.Namespaces; +import com.silverwrist.dynamo.except.*; +import com.silverwrist.dynamo.iface.*; +import com.silverwrist.dynamo.security.SecurityReferenceMonitor; + +public class AclEditHelper +{ + /*-------------------------------------------------------------------------------- + * Attributes + *-------------------------------------------------------------------------------- + */ + + private SecurityReferenceMonitor m_srm; + + /*-------------------------------------------------------------------------------- + * Constructor + *-------------------------------------------------------------------------------- + */ + + public AclEditHelper(ServiceProvider services, String srm_name) + { + ObjectProvider op = (ObjectProvider)(services.queryService(ObjectProvider.class)); + Object tmp = op.getObject(Namespaces.DYNAMO_OBJECT_NAMESPACE,srm_name); + if (tmp instanceof SecurityReferenceMonitor) + m_srm = (SecurityReferenceMonitor)tmp; + else if (tmp instanceof ServiceProvider) + m_srm = (SecurityReferenceMonitor)(((ServiceProvider)tmp).queryService(SecurityReferenceMonitor.class)); + + } // end AclEditHelper + + /*-------------------------------------------------------------------------------- + * External operations + *-------------------------------------------------------------------------------- + */ + + public SecurityReferenceMonitor getSRM() + { + return m_srm; + + } // end getSRM + + public void insertAce(DynamoUser caller, DynamoAcl acl, DynamoAce ace) throws DatabaseException, NotOwnerException + { + // Locate the place to insert this ACE into the ACL. + int acecount = acl.getAceCount(); + int ipoint = 0; + if (ace.isNegative()) + { // negative ACEs get inserted before positive ACEs + if (ace.isGroupAce()) + { // skip all user ACEs, insert before group ACEs (or before positive ACEs) + DynamoAce tmp = acl.getAce(caller,ipoint); + while ((ipoint0) + { // zap the ACEs that are now empty + DynamoAce ace = (DynamoAce)(null_aces.removeFirst()); + acl.removeEntry(caller,ace); + + } // end while + + } // end stripPermission + +} // end class AclEditHelper