diff --git a/conf/venice-db-init-mysql.sql b/conf/venice-db-init-mysql.sql index 63de7df..07a7846 100644 --- a/conf/venice-db-init-mysql.sql +++ b/conf/venice-db-init-mysql.sql @@ -889,11 +889,15 @@ INSERT INTO acedata (aceid, perm_nsid, perm_name) VALUES UPDATE groups SET gaclid = 4 WHERE gid = 5; # Create the ACL for the initial community. -# (ACL 5, ACEs 9, 10) +# (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 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 + (12, 14, 'unjoin'); INSERT INTO ace (aceid, pri, flags) VALUES (9, 2, 0); -INSERT INTO acldata (aclid, seq, aceid) VALUES (5, 0, 9); +INSERT INTO acldata (aclid, seq, aceid) VALUES (5, 1, 9); INSERT INTO acedata (aceid, perm_nsid, perm_name) VALUES (9, 14, 'grant.revoke.access'), (9, 15, 'set.category' ), @@ -901,16 +905,22 @@ INSERT INTO acedata (aceid, perm_nsid, perm_name) VALUES (9, 15, 'set.name' ), (9, 15, 'set.alias' ), (9, 15, 'set.property' ), - (9, 15, 'remove.property' ); + (9, 15, 'remove.property' ), + (9, 16, 'administration' ); INSERT INTO ace (aceid, pri, flags) VALUES (10, 5, 1); -INSERT INTO acldata (aclid, seq, aceid) VALUES (5, 1, 10); +INSERT INTO acldata (aclid, seq, aceid) VALUES (5, 2, 10); INSERT INTO acedata (aceid, perm_nsid, perm_name) VALUES (10, 14, 'grant.revoke.access'), (10, 15, 'set.category' ), (10, 15, 'set.visibility' ), (10, 15, 'set.name' ), (10, 15, 'set.alias' ), - (10, 15, 'set.property' ); + (10, 15, 'set.property' ), + (10, 16, 'administration' ); +INSERT INTO ace (aceid, pri, flags) VALUES (11, 3, 1); +INSERT INTO acldata (aclid, seq, aceid) VALUES (5, 3, 11); +INSERT INTO acedata (aceid, perm_nsid, perm_name) VALUES + (11, 14, 'unjoin'); #### following this line is initialization of Venice-specific tables #### @@ -1352,14 +1362,38 @@ UPDATE menuitems SET ifdef_var = 'use_categories' WHERE menuid = 4 AND sequence # Create the standard community menu. (ID #5) INSERT INTO menus (menuid, menu_nsid, menu_name, title, subtitle) - VALUES (5, 16, 'community.menu', '', NULL); + VALUES (5, 16, 'community.menu', '${name}', NULL); +INSERT INTO menuvars (menuid, var_name, default_val) VALUES + (5, 'alias', NULL), + (5, 'cid', NULL), + (5, 'name', NULL); INSERT INTO menuitems (menuid, sequence, itemtype, text, linktype, link) VALUES - (5, 0, 'TEXT', 'Home Page', 'SERVLET', 'TODO'), - (5, 60000, 'TEXT', 'Members', 'SERVLET', 'TODO'), - (5, 60100, 'TEXT', 'Profile', 'SERVLET', 'TODO'), - (5, 60200, 'TEXT', 'Administration', 'SERVLET', 'TODO'), - (5, 60300, 'SEPARATOR', NULL, NULL, NULL ), - (5, 60400, 'TEXT', 'Unjoin', 'SERVLET', 'TODO'); + (5, 0, 'TEXT', 'Home Page', 'SERVLET', 'community/${alias}'), + (5, 60000, 'TEXT', 'Members', 'SERVLET', 'TODO' ), + (5, 60100, 'TEXT', 'Profile', 'SERVLET', 'TODO' ), + (5, 60200, 'TEXT', 'Administration', 'SERVLET', 'TODO' ), + (5, 60300, 'SEPARATOR', NULL, NULL, NULL ), + (5, 60400, 'TEXT', 'Unjoin', 'SERVLET', 'TODO' ); +UPDATE menuitems SET perm_nsid = 16, perm_name = 'administration' WHERE menuid = 5 AND sequence = 60200; +UPDATE menuitems SET perm_nsid = 14, perm_name = 'unjoin' WHERE menuid = 5 AND sequence = 60300; +UPDATE menuitems SET perm_nsid = 14, perm_name = 'unjoin' WHERE menuid = 5 AND sequence = 60400; + +# Create the "top" menu (non-community). (ID #6) +INSERT INTO menus (menuid, menu_nsid, menu_name, title, subtitle) + VALUES (6, 1, 'top.menu', 'Services', NULL); +INSERT INTO menuitems (menuid, sequence, itemtype, text, linktype, link) VALUES + (6, 0, 'TEXT', 'Calendar', 'SERVLET', 'TODO'), + (6, 100, 'TEXT', 'Chat', 'SERVLET', 'TODO'); +UPDATE menuitems SET enable = 0 WHERE menuid = 6 AND sequence = 0; +UPDATE menuitems SET enable = 0 WHERE menuid = 6 AND sequence = 100; + +# Create the top-level community administration menu. (ID #7) +INSERT INTO menus (menuid, menu_nsid, menu_name, title, subtitle) + VALUES (7, 16, 'admin.menu', 'Community Administration:', '${name}'); +INSERT INTO menuvars (menuid, var_name, default_val) VALUES + (7, 'name', NULL); +INSERT INTO menuitems (menuid, sequence, itemtype, text, linktype, link, perm_nsid, perm_name) VALUES + (7, 0, 'TEXT', 'Edit Community Profile', 'SERVLET', 'TODO', 15, 'set.property'); # Create the sideboxes tables. INSERT INTO sbox_master (sbid, sb_nsid, sb_name, type_nsid, type_name, descr) VALUES 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 7f55965..94b3e09 100644 --- a/src/dynamo-framework/com/silverwrist/dynamo/security/AclOperations_mysql.java +++ b/src/dynamo-framework/com/silverwrist/dynamo/security/AclOperations_mysql.java @@ -21,6 +21,7 @@ import java.security.acl.LastOwnerException; import java.security.acl.NotOwnerException; import java.sql.*; import java.util.*; +import org.apache.log4j.Logger; import com.silverwrist.util.*; import com.silverwrist.dynamo.except.*; import com.silverwrist.dynamo.iface.*; @@ -33,6 +34,8 @@ class AclOperations_mysql extends AclOperations *-------------------------------------------------------------------------------- */ + private static Logger logger = Logger.getLogger(AclOperations_mysql.class); + private static final int OWNERFLAG_USER = 0; private static final int OWNERFLAG_GROUP = 1; @@ -690,6 +693,8 @@ class AclOperations_mysql extends AclOperations boolean testUserPermission(int aclid, int uid, PropertyKey perm) throws DatabaseException { + if (logger.isDebugEnabled()) + logger.debug("testUserPermission(): aclid = " + aclid + ", uid = " + uid + ", perm = " + perm); Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; @@ -700,7 +705,7 @@ class AclOperations_mysql extends AclOperations int table_index = 0; // test for positive and negative user values first - stmt = conn.prepareStatement("SELECT ace.flags FROM acedata, ace, acldata, groupmembers " + 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) " @@ -710,21 +715,35 @@ class AclOperations_mysql extends AclOperations stmt.setInt(3,aclid); stmt.setInt(4,uid); rs = stmt.executeQuery(); + boolean positive = false, negative = false; while (rs.next()) { // examine flag values - int flag = rs.getInt(1); - if (flag==0) - table_index += 8; // positive user + if (logger.isDebugEnabled()) + logger.debug("Matched ACE " + rs.getInt(1) + ", flag = " + rs.getInt(2)); + int flag = rs.getInt(2); + if ((flag==0) && !positive) + { // positive user + table_index += 8; + positive = true; + + } // end if else if (flag==16) - table_index += 2; // negative user + { // negative user + table_index += 2; + negative = true; + + } // end else if + + if (positive && negative) + break; // can't get better results } // end while // then test for positive and negative group values - SQLUtils.shutdown(rs); + rs.close(); rs = null; - SQLUtils.shutdown(stmt); - stmt = conn.prepareStatement("SELECT DISTINCT ace.flags FROM acedata, ace, acldata, groupmembers " + 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) " @@ -734,13 +753,27 @@ class AclOperations_mysql extends AclOperations stmt.setInt(3,aclid); stmt.setInt(4,uid); rs = stmt.executeQuery(); + positive = negative = false; while (rs.next()) { // examine flag values - int flag = rs.getInt(1); + if (logger.isDebugEnabled()) + logger.debug("Matched ACE " + rs.getInt(1) + ", flag = " + rs.getInt(2)); + int flag = rs.getInt(2); if (flag==1) - table_index += 4; // positive group + { // positive group + table_index += 4; + positive = true; + + } // end if else if (flag==17) - table_index += 1; // negative group + { // negative group + table_index += 1; + negative = true; + + } // end else if + + if (positive && negative) + break; // can't get better results } // end while @@ -765,6 +798,8 @@ class AclOperations_mysql extends AclOperations boolean testGroupPermission(int aclid, int gid, PropertyKey perm) throws DatabaseException { + if (logger.isDebugEnabled()) + logger.debug("testGroupPermission(): aclid = " + aclid + ", gid = " + gid + ", perm = " + perm); Connection conn = null; PreparedStatement stmt = null; ResultSet rs = null; @@ -776,8 +811,8 @@ class AclOperations_mysql extends AclOperations boolean negative = false; // test for positive and negative values simultaneously - stmt = conn.prepareStatement("SELECT acedata.aceflags FROM acedata, ace, acldata, groupmembers " - + "WHERE acedata.perm_nsid = ? AND acedata.perm_name = ? " + 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 = ?;"); @@ -788,11 +823,15 @@ class AclOperations_mysql extends AclOperations rs = stmt.executeQuery(); while (rs.next()) { // examine flag values - int flag = rs.getInt(1); + if (logger.isDebugEnabled()) + logger.debug("Matched ACE " + rs.getInt(1) + ", flag = " + rs.getInt(2)); + int flag = rs.getInt(2); if (flag==1) positive = true; // positive group else if (flag==17) negative = true; // negative group + if (positive && negative) + break; // can't get better results } // end while diff --git a/src/venice-base/com/silverwrist/venice/frame/FrameAssembler.java b/src/venice-base/com/silverwrist/venice/frame/FrameAssembler.java index 677859b..45212a2 100644 --- a/src/venice-base/com/silverwrist/venice/frame/FrameAssembler.java +++ b/src/venice-base/com/silverwrist/venice/frame/FrameAssembler.java @@ -17,6 +17,7 @@ */ package com.silverwrist.venice.frame; +import java.security.acl.AclNotFoundException; import java.text.MessageFormat; import java.util.*; import java.util.regex.*; @@ -370,14 +371,71 @@ public class FrameAssembler MenuRenderObject fixed_menu = m_menu_prov.getLeftMenu(user,VeniceNamespaces.FRAME_LAF_NAMESPACE, "fixed.menu",acls); + // get the "floating" menu selector + String menusel = ((FramedContent)input).getMenuSelector(); + String menusel_full = menusel; + VeniceCommunity comm = null; + if ((menusel!=null) && (menusel.equals("community"))) + { // figure out which menu selector we want to use... + comm = (VeniceCommunity)(PropertyUtils.getPropertyNoErr(r,VeniceNamespaces.COMMUNITY_NAMESPACE,"current")); + if (comm==null) + menusel = menusel_full = null; + else + menusel_full += (":" + comm.getCID()); + + } // end if + + // do we need to reload the floating menu? + boolean reload = false; + if (menusel!=null) + { // get the current menu selector + Object curr_menusel = PropertyUtils.getPropertyNoErr(session,SessionInfoParams.NAMESPACE, + SessionInfoParams.ATTR_MENU_SELECTOR); + if ((curr_menusel==null) || !(menusel_full.equals(curr_menusel.toString()))) + reload = true; // need to reload the menu + + } // end if + + MenuRenderObject floating_menu = null; + if (reload) + { // which menu do we load? + if (menusel.equals("top")) + { // load the "top" menu + // N.B.: the "acl" array still contains only the global ACL ID + floating_menu = m_menu_prov.getLeftMenu(user,VeniceNamespaces.FRAME_LAF_NAMESPACE,"top.menu",acls); + + } // end if + else if (menusel.equals("community")) + { // load the "community" menu + acls = new int[2]; + acls[0] = comm.getAcl().getAclID(); + acls[1] = m_srm.getGlobalAcl().getAclID(); + floating_menu = m_menu_prov.getLeftMenu(user,VeniceNamespaces.COMMUNITY_GLOBALS_NAMESPACE, + "community.menu",acls); + floating_menu.setVariable("alias",comm.getAlias()); + floating_menu.setVariable("cid",String.valueOf(comm.getCID())); + floating_menu.setVariable("name",comm.getName()); + + } // end else if + + // save the menu and menu selector into the session + session.setObject(SessionInfoParams.NAMESPACE,SessionInfoParams.ATTR_MENU,floating_menu); + session.setObject(SessionInfoParams.NAMESPACE,SessionInfoParams.ATTR_MENU_SELECTOR,menusel_full); + + } // end if + else // get the current menu from the session + floating_menu = (MenuRenderObject)(session.getObject(SessionInfoParams.NAMESPACE, + SessionInfoParams.ATTR_MENU)); + // get the footer and optionally insert line breaks String footer = (String)(m_blocks.getObject(NAMESPACE,BLOCK_FOOTER)); if (m_footer_breaks) // set up the regular expression system to replace carriage returns to insert a
footer = PAT_LINEBREAK.matcher(footer).replaceAll("
\r\n"); + // return the FrameRendering! return new FrameRendering((FramedContent)input,m_frame_template,m_base_params,user,location, - display_login,fixed_menu,footer); + display_login,fixed_menu,floating_menu,footer); } // end try catch (DatabaseException e) @@ -385,6 +443,11 @@ public class FrameAssembler throw new RenderingException(e); } // end catch + catch (AclNotFoundException e) + { // translate this exception into a RenderingException as well + throw new RenderingException(FrameAssembler.class,"FrameMessages","frame.noACL",e); + + } // end catch } // end if diff --git a/src/venice-base/com/silverwrist/venice/frame/FrameMessages.properties b/src/venice-base/com/silverwrist/venice/frame/FrameMessages.properties index 3b3fe21..47f269b 100644 --- a/src/venice-base/com/silverwrist/venice/frame/FrameMessages.properties +++ b/src/venice-base/com/silverwrist/venice/frame/FrameMessages.properties @@ -22,3 +22,4 @@ ss.noPrefix=Configuration error: no stylesheet prefix configured for servlet pat ss.noTemplate=No stylesheet template name found for property "{0}". ss.renderFail=Unable to render stylesheet template {0}: {1} generator=Venice Web Communities System {0}; Dynamo Application Framework {1} +frame.noACL=Unable to locate ACL for menu generation. diff --git a/src/venice-base/com/silverwrist/venice/frame/FrameRendering.java b/src/venice-base/com/silverwrist/venice/frame/FrameRendering.java index 941d5c6..51d4c8b 100644 --- a/src/venice-base/com/silverwrist/venice/frame/FrameRendering.java +++ b/src/venice-base/com/silverwrist/venice/frame/FrameRendering.java @@ -42,7 +42,8 @@ class FrameRendering implements VelocityRenderable */ FrameRendering(FramedContent content, String templ, VelocityParamSupplier base_params, DynamoUser user, - String location, Boolean display_login, MenuRenderObject fixed_menu, String footer) + String location, Boolean display_login, MenuRenderObject fixed_menu, MenuRenderObject floating_menu, + String footer) { m_templ = templ; m_base_params = base_params; @@ -56,6 +57,7 @@ class FrameRendering implements VelocityRenderable m_local_vars.put("location",location); m_local_vars.put("display_login",display_login); m_local_vars.put("fixed_menu",fixed_menu); + m_local_vars.put("floating_menu",floating_menu); m_local_vars.put("footer_text",footer); } // end constructor diff --git a/src/venice-base/com/silverwrist/venice/menu/InlineMenuRendering.java b/src/venice-base/com/silverwrist/venice/menu/InlineMenuRendering.java index 37281d8..a812d2f 100644 --- a/src/venice-base/com/silverwrist/venice/menu/InlineMenuRendering.java +++ b/src/venice-base/com/silverwrist/venice/menu/InlineMenuRendering.java @@ -258,9 +258,11 @@ class InlineMenuRendering implements MenuRenderObject, SelfRenderable wr.write("