package org.curriki.plugin.spacemanager.impl; import com.xpn.xwiki.XWikiContext; import com.xpn.xwiki.XWikiException; import com.xpn.xwiki.objects.BaseObject; import com.xpn.xwiki.doc.XWikiDocument; import com.xpn.xwiki.api.Api; import com.xpn.xwiki.plugin.XWikiPluginInterface; import com.xpn.xwiki.plugin.spacemanager.api.Space; import com.xpn.xwiki.plugin.spacemanager.api.SpaceManagerException; import com.xpn.xwiki.plugin.spacemanager.api.SpaceManagerExtension; import com.xpn.xwiki.plugin.spacemanager.impl.SpaceManagerImpl; import org.curriki.plugin.spacemanager.plugin.CurrikiSpaceManagerPluginApi; import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang.StringUtils; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * Created by IntelliJ IDEA. * User: ludovic * Date: 14 dec. 2007 * Time: 09:23:04 * To change this template use File | Settings | File Templates. */ public class CurrikiSpaceManager extends SpaceManagerImpl { public static final String CURRIKI_SPACEMANGER_NAME = "csm"; private static final String CURRIKI_SPACEMANAGER_DEFAULT_EXTENSION = "org.xwiki.plugin.spacemanager.impl.CurrikiSpaceManagerExtension"; private static final String CURRIKI_SPACEMANAGER_DEFAULT_PROTECTED_SUBSPACES = "UserProfiles,Messages,Documentation"; /** * Space manager constructor * @param name * @param className * @param context */ public CurrikiSpaceManager(String name, String className, XWikiContext context) { super(name, className, context); } public String getName() { return CURRIKI_SPACEMANGER_NAME; } /** * Loads the CurrikiSpaceManagerExtension specified in the config file * @return Returns the space manager extension * @throws SpaceManagerException */ public SpaceManagerExtension getSpaceManagerExtension(XWikiContext context) throws SpaceManagerException { if (spaceManagerExtension==null) { String extensionName = context.getWiki().Param(SPACEMANAGER_EXTENSION_CFG_PROP,CURRIKI_SPACEMANAGER_DEFAULT_EXTENSION); try { if (extensionName!=null){ spaceManagerExtension = (CurrikiSpaceManagerExtension)Class.forName(extensionName).newInstance(); } } catch (Throwable e){ try{ spaceManagerExtension = (CurrikiSpaceManagerExtension)Class.forName(CURRIKI_SPACEMANAGER_DEFAULT_EXTENSION).newInstance(); } catch(Throwable e2){ } } } if (spaceManagerExtension==null) { spaceManagerExtension = new CurrikiSpaceManagerExtension( ); } return spaceManagerExtension; } /** * Get the list of sub spaces to protect * @param context * @return */ public String[] getProtectedSubSpaces(XWikiContext context) { String protectedSubSpaces = context.getWiki().Param(SPACEMANAGER_PROTECTED_SUBSPACES_PROP, CURRIKI_SPACEMANAGER_DEFAULT_PROTECTED_SUBSPACES); if ((protectedSubSpaces!=null)&&(!protectedSubSpaces.equals(""))) { return protectedSubSpaces.split(","); } else { return new String[0]; } } /** * Gets the space plugin Api * @param plugin The plugin interface * @param context Xwiki context * @return */ public Api getPluginApi(XWikiPluginInterface plugin, XWikiContext context) { return new CurrikiSpaceManagerPluginApi((CurrikiSpaceManager) plugin, context); } protected Space newSpace(String spaceName, String spaceTitle, boolean create, XWikiContext context) throws SpaceManagerException { return new CurrikiSpace(spaceName, spaceTitle, create, this, context); //To change body of overridden methods use File | Settings | File Templates. } protected String getCurrikiSpaceClassName() { return ((CurrikiSpaceManagerExtension) getSpaceManagerExtension()).getCurrikiSpaceClassName(); } public List getSpacesByTopic(String topic, int nb, int start, XWikiContext context) throws SpaceManagerException { String currikiClassName = getCurrikiSpaceClassName(); String fromhql = ", BaseObject as cobj, DBStringListProperty as lprop"; String wheresql = " and doc.fullName=cobj.name and cobj.className='" + currikiClassName + "' and cobj.id=lprop.id.id and lprop.id.name='" + CurrikiSpace.SPACE_TOPIC + "' and '" + topic + "' in elements(lprop.list)" ; return searchSpaces(fromhql, wheresql, "order by doc.creationDate desc", nb, start, context); } public List getSpaceNamesByTopic(String topic, int nb, int start, XWikiContext context) throws SpaceManagerException { String currikiClassName = getCurrikiSpaceClassName(); String fromhql = ", BaseObject as cobj, DBStringListProperty as lprop"; String wheresql = " and doc.fullName=cobj.name and cobj.className='" + currikiClassName + "' and cobj.id=lprop.id.id and lprop.id.name='" + CurrikiSpace.SPACE_TOPIC + "' and '" + topic + "' in elements(lprop.list)" ; return searchSpaceNames(fromhql, wheresql, "order by doc.creationDate desc", nb, start, context); } public List countSpacesByTopic(String parentTopic, XWikiContext context) throws SpaceManagerException { String type = getSpaceTypeName(); String className = getSpaceClassName(); String currikiClassName = getCurrikiSpaceClassName(); String sql; String parentfromsql = (parentTopic==null) ? "" : ", XWikiDocument as doc2"; String parentsql = (parentTopic==null) ? "" : " and doc2.fullName = topic.id and doc2.parent='" + parentTopic + "'"; if (hasCustomMapping()) sql = "select topic.id, count(*) from XWikiDocument as doc, BaseObject as obj, " + className + " as space, BaseObject as cobj, DBStringListProperty as lprop join lprop.list as topic" + parentfromsql + " where doc.fullName = obj.name and obj.className='" + className + "' and obj.id = space.id and space.type='" + type + "'" + " and doc.fullName=cobj.name and cobj.className='" + currikiClassName + "' and cobj.id=lprop.id.id and lprop.id.name='" + CurrikiSpace.SPACE_TOPIC + "'" + parentsql + " group by 1" ; else sql = "select topic.id, count(*) from XWikiDocument as doc, BaseObject as obj, StringProperty as typeprop, BaseObject as cobj, DBStringListProperty as lprop join lprop.list as topic" + parentfromsql + " where doc.fullName=obj.name and obj.className = '" + className + "' and obj.id=typeprop.id.id and typeprop.id.name='type' and typeprop.value='" + type + "'" + " and doc.fullName=cobj.name and cobj.className='" + currikiClassName + "' and cobj.id=lprop.id.id and lprop.id.name='" + CurrikiSpace.SPACE_TOPIC + "'" + parentsql + " group by 1" ; try { return context.getWiki().search(sql, context); } catch (XWikiException e) { throw new SpaceManagerException(e); } } /** * {@inheritDoc} */ public Collection getRoles(String spaceName, XWikiContext context) throws SpaceManagerException { List parameterValues = new ArrayList(); String where = "where doc.web = ? and doc.name like ? order by doc.title"; parameterValues.add(spaceName); parameterValues.add("Role_%Group"); List roles; try { roles = context.getWiki().getStore().searchDocumentsNames(where, 0, 0, parameterValues, context); } catch (XWikiException e) { throw new SpaceManagerException(e); } return roles; } /** * Gives a group certain rights over a space * This function is overridden from standard space manager * which currently has a bug that needs to be fixed * * @param spaceName Name of the space * @param groupName Name of the group that will have the value * @param level Access level * @param allow True if the right is allow, deny if not */ protected boolean addRightToGroup(String spaceName, String groupName, String level, boolean allow, boolean global, XWikiContext context) throws XWikiException { final String rightsClass = global ? "XWiki.XWikiGlobalRights" : "XWiki.XWikiRights"; final String prefDocName = spaceName + ".WebPreferences"; final String groupsField = "groups"; final String levelsField = "levels"; final String allowField = "allow"; XWikiDocument prefDoc; prefDoc = context.getWiki().getDocument(prefDocName, context); // checks to see if the right is not already given boolean exists = false; boolean isUpdated = false; int indx = -1; boolean foundlevel = false; int allowInt; if (allow) allowInt = 1; else allowInt = 0; List objs = prefDoc.getObjects(rightsClass); if (objs != null) { for (int i = 0; i < objs.size(); i++) { BaseObject bobj = (BaseObject) objs.get(i); if (bobj == null) continue; String groups = bobj.getLargeStringValue(groupsField); String levels = bobj.getStringValue(levelsField); int allowDeny = bobj.getIntValue(allowField); boolean allowdeny = (bobj.getIntValue(allowField) == 1); String[] levelsarray = StringUtils.split(levels, " ,|"); String[] groupsarray = StringUtils.split(groups, " ,|"); if (ArrayUtils.contains(groupsarray, groupName)) { exists = true; if (!foundlevel) indx = i; if (ArrayUtils.contains(levelsarray, level)) { foundlevel = true; if (allowInt == allowDeny) { isUpdated = true; break; } } } } } // sets the rights. the aproach is to break rules/levels in as many // XWikiRigts elements so // we don't have to handle lots of situation when we change rights if (!exists) { BaseObject bobj = new BaseObject(); bobj.setClassName(rightsClass); bobj.setName(prefDoc.getFullName()); bobj.setLargeStringValue(groupsField, groupName); bobj.setStringValue(levelsField, level); bobj.setIntValue(allowField, allowInt); prefDoc.addObject(rightsClass, bobj); context.getWiki().saveDocument(prefDoc, context); return true; } else { if (isUpdated) { return true; } else { BaseObject bobj = (BaseObject) objs.get(indx); String groups = bobj.getLargeStringValue(groupsField); String levels = bobj.getStringValue(levelsField); String[] levelsarray = StringUtils.split(levels, " ,|"); String[] groupsarray = StringUtils.split(groups, " ,|"); if (levelsarray.length == 1 && groupsarray.length == 1 && levelsarray[0] == level) { // if there is only this group and this level in the rule // update this rule } else { // if there are more groups/levels, extract this one(s) bobj = new BaseObject(); bobj.setName(prefDoc.getFullName()); bobj.setClassName(rightsClass); bobj.setStringValue(levelsField, level); bobj.setIntValue(allowField, allowInt); bobj.setLargeStringValue(groupsField, groupName); } prefDoc.addObject(rightsClass, bobj); context.getWiki().saveDocument(prefDoc, context); return true; } } } /** * Gives a group certain rights over a space * This function is overridden from standard space manager * which currently has a bug that needs to be fixed * * @param spaceName Name of the space * @param groupName Name of the group that will have the value * @param level Access level * @param allow True if the right is allow, deny if not */ protected boolean removeRightFromGroup(String spaceName, String groupName, String level, boolean allow, boolean global, XWikiContext context) throws XWikiException { final String rightsClass = global ? "XWiki.XWikiGlobalRights" : "XWiki.XWikiRights"; final String prefDocName = spaceName + ".WebPreferences"; final String groupsField = "groups"; final String levelsField = "levels"; final String allowField = "allow"; XWikiDocument prefDoc; prefDoc = context.getWiki().getDocument(prefDocName, context); boolean foundlevel = false; int allowInt; if (allow) allowInt = 1; else allowInt = 0; List objs = prefDoc.getObjects(rightsClass); if (objs != null) { for (int i = 0; i < objs.size(); i++) { BaseObject bobj = (BaseObject) objs.get(i); if (bobj == null) continue; String groups = bobj.getLargeStringValue(groupsField); String levels = bobj.getStringValue(levelsField); int allowDeny = bobj.getIntValue(allowField); boolean allowdeny = (bobj.getIntValue(allowField) == 1); String[] levelsarray = StringUtils.split(levels, " ,|"); String[] groupsarray = StringUtils.split(groups, " ,|"); if (ArrayUtils.contains(groupsarray, groupName)) { if (ArrayUtils.contains(levelsarray, level)) { foundlevel = true; if (allowInt == allowDeny) { prefDoc.removeObject(bobj); } } } } } if (foundlevel) { context.getWiki().saveDocument(prefDoc, context); return true; } return false; } }