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("