CCM NG/ccm-cms: BrowsePane migrated to NG APIs

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4527 8810af33-2d31-482b-a856-94f89814c4df
ccm-docs
jensp 2017-01-20 16:38:39 +00:00
parent 26455a2ae4
commit fafba0080d
33 changed files with 4187 additions and 1291 deletions

1
build-site.sh 100755
View File

@ -0,0 +1 @@
mvn clean package site site:stage -Dmaven.test.failure.ignore=true -Pwildfly-remote-h2-mem

View File

@ -36,11 +36,7 @@ import com.arsdigita.cms.ui.folder.FolderTreeModelBuilder;
import com.arsdigita.globalization.GlobalizedMessage; import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.toolbox.ui.LayoutPanel; import com.arsdigita.toolbox.ui.LayoutPanel;
import com.arsdigita.util.Assert; import com.arsdigita.util.Assert;
import com.arsdigita.web.Web;
import java.math.BigDecimal;
import org.apache.log4j.Logger;
import org.libreccm.categorization.Category; import org.libreccm.categorization.Category;
import org.libreccm.core.CcmObject; import org.libreccm.core.CcmObject;
import org.librecms.CmsConstants; import org.librecms.CmsConstants;
@ -51,25 +47,23 @@ import org.librecms.CmsConstants;
* the "Browse" tab. * the "Browse" tab.
* *
* @author David LutterKort <dlutter@redhat.com> * @author David LutterKort <dlutter@redhat.com>
* @version $Id: BrowsePane.java 1325 2006-09-22 08:11:33Z sskracic $ * @author <a href="jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */
public class BrowsePane extends LayoutPanel implements Resettable { public class BrowsePane extends LayoutPanel implements Resettable {
private static final Logger s_log = Logger.getLogger(BrowsePane.class); private final BaseTree tree;
private final SingleSelectionModel selectionModel;
private final BaseTree m_tree; private final FolderSelectionModel folderModel; // To support legacy UI code
private final SingleSelectionModel m_model; private final FolderRequestLocal folderRequestLocal;
private final FolderSelectionModel m_folderModel; // To support legacy UI code private final FlatItemList flatItemList;
private final FolderRequestLocal m_folder;
private final FlatItemList m_fil;
public BrowsePane() { public BrowsePane() {
/* The folder tree displayed on the left side / left column */ /* The folder tree displayed on the left side / left column */
m_tree = new BaseTree(new FolderTreeModelBuilder()); tree = new BaseTree(new FolderTreeModelBuilder());
m_model = m_tree.getSelectionModel(); selectionModel = tree.getSelectionModel();
m_folderModel = new FolderSelectionModel(m_model); folderModel = new FolderSelectionModel(selectionModel);
m_folder = new FolderRequestLocal(m_folderModel); folderRequestLocal = new FolderRequestLocal(folderModel);
final SegmentedPanel left = new SegmentedPanel(); final SegmentedPanel left = new SegmentedPanel();
setLeft(left); setLeft(left);
@ -77,21 +71,21 @@ public class BrowsePane extends LayoutPanel implements Resettable {
final Label heading = new Label( final Label heading = new Label(
new GlobalizedMessage("cms.ui.folder_browser", new GlobalizedMessage("cms.ui.folder_browser",
CmsConstants.CMS_FOLDER_BUNDLE)); CmsConstants.CMS_FOLDER_BUNDLE));
left.addSegment(heading, m_tree); left.addSegment(heading, tree);
m_fil = new FlatItemList(m_folder, m_folderModel); flatItemList = new FlatItemList(folderRequestLocal, folderModel);
setBody(m_fil); setBody(flatItemList);
m_fil.getManipulator().getItemView().addProcessListener( flatItemList.getManipulator().getItemView().addProcessListener(
new ProcessListener()); new ProcessListener());
m_fil.getManipulator().getTargetSelector().addProcessListener( flatItemList.getManipulator().getTargetSelector().addProcessListener(
new ProcessListener()); new ProcessListener());
m_fil.getManipulator().getTargetSelector().addSubmissionListener( flatItemList.getManipulator().getTargetSelector().addSubmissionListener(
new SubmissionListener()); new SubmissionListener());
} }
@Override @Override
public final void register(Page page) { public final void register(final Page page) {
super.register(page); super.register(page);
page.addActionListener(new FolderListener()); page.addActionListener(new FolderListener());
@ -99,10 +93,10 @@ public class BrowsePane extends LayoutPanel implements Resettable {
} }
@Override @Override
public final void reset(PageState state) { public final void reset(final PageState state) {
super.reset(state); super.reset(state);
m_fil.reset(state); flatItemList.reset(state);
} }
// Private classes and methods // Private classes and methods
@ -111,19 +105,16 @@ public class BrowsePane extends LayoutPanel implements Resettable {
*/ */
private final class ProcessListener implements FormProcessListener { private final class ProcessListener implements FormProcessListener {
/** @Override
* public final void process(final FormSectionEvent event) {
* @param e final PageState state = event.getPageState();
*/
public final void process(final FormSectionEvent e) {
final PageState state = e.getPageState();
if (e.getSource() == m_fil.getManipulator().getItemView()) { if (event.getSource() == flatItemList.getManipulator().getItemView()) {
// Hide everything except for the flat item list // Hide everything except for the flat item list
m_tree.setVisible(state, false); tree.setVisible(state, false);
} else if (e.getSource() == m_fil.getManipulator() } else if (event.getSource() == flatItemList.getManipulator()
.getTargetSelector()) { .getTargetSelector()) {
m_tree.setVisible(state, true); tree.setVisible(state, true);
} }
} }
@ -131,12 +122,15 @@ public class BrowsePane extends LayoutPanel implements Resettable {
private final class SubmissionListener implements FormSubmissionListener { private final class SubmissionListener implements FormSubmissionListener {
public final void submitted(final FormSectionEvent e) { @Override
final PageState s = e.getPageState(); public final void submitted(final FormSectionEvent event) {
final PageState state = event.getPageState();
if (e.getSource() == m_fil.getManipulator().getTargetSelector()) { if (event.getSource() == flatItemList.getManipulator()
if (!m_fil.getManipulator().getTargetSelector().isVisible(s)) { .getTargetSelector()) {
m_tree.setVisible(s, true); if (!flatItemList.getManipulator().getTargetSelector()
.isVisible(state)) {
tree.setVisible(state, true);
} }
} }
} }
@ -145,17 +139,18 @@ public class BrowsePane extends LayoutPanel implements Resettable {
private final class FolderListener implements ActionListener { private final class FolderListener implements ActionListener {
public final void actionPerformed(final ActionEvent e) { @Override
final PageState state = e.getPageState(); public final void actionPerformed(final ActionEvent event) {
final PageState state = event.getPageState();
if (!m_model.isSelected(state)) { if (!selectionModel.isSelected(state)) {
final String folder = state.getRequest().getParameter( final String folder = state.getRequest().getParameter(
ContentSectionPage.SET_FOLDER); ContentSectionPage.SET_FOLDER);
if (folder == null) { if (folder == null) {
final Category root = CMS.getContext().getContentSection() final Category root = CMS.getContext().getContentSection()
.getRootDocumentsFolder(); .getRootDocumentsFolder();
Long folderID = root.getObjectId(); final Long folderID = root.getObjectId();
/* /*
ToDo ToDo
@ -168,9 +163,9 @@ public class BrowsePane extends LayoutPanel implements Resettable {
} }
}*/ }*/
m_model.setSelectedKey(state, folderID); selectionModel.setSelectedKey(state, folderID);
} else { } else {
m_model.setSelectedKey(state, folder); selectionModel.setSelectedKey(state, folder);
} }
} }
} }
@ -179,21 +174,22 @@ public class BrowsePane extends LayoutPanel implements Resettable {
private final class TreeListener implements ActionListener { private final class TreeListener implements ActionListener {
public final void actionPerformed(final ActionEvent e) { @Override
final PageState state = e.getPageState(); public final void actionPerformed(final ActionEvent event) {
final PageState state = event.getPageState();
if (Assert.isEnabled()) { if (Assert.isEnabled()) {
Assert.isTrue(m_model.isSelected(state)); Assert.isTrue(selectionModel.isSelected(state));
} }
final Category root = CMS.getContext().getContentSection() final Category root = CMS.getContext().getContentSection()
.getRootDocumentsFolder(); .getRootDocumentsFolder();
if (!root.equals(m_folder.getFolder(state))) { if (!root.equals(folderRequestLocal.getFolder(state))) {
// Expand the ancestor nodes of the currently // Expand the ancestor nodes of the currently
// selected node. // selected node.
CcmObject object = m_folder.getFolder(state); CcmObject object = folderRequestLocal.getFolder(state);
while (object != null) { while (object != null) {
if (object instanceof Category) { if (object instanceof Category) {
@ -204,7 +200,7 @@ public class BrowsePane extends LayoutPanel implements Resettable {
if (result instanceof Category) { if (result instanceof Category) {
object = result; object = result;
m_tree.expand( tree.expand(
((Long) object.getObjectId()).toString(), ((Long) object.getObjectId()).toString(),
state); state);
} else { } else {

View File

@ -119,7 +119,7 @@ public class ContentSectionPage extends CMSPage implements ActionListener {
private TabbedPane m_tabbedPane; private TabbedPane m_tabbedPane;
private FolderAdminPane m_folderPane; private FolderAdminPane m_folderPane;
//ToDo NG private BrowsePane m_browsePane; private BrowsePane m_browsePane;
private ItemSearch m_searchPane; private ItemSearch m_searchPane;
//ToDo NG private ImagesPane m_imagesPane; //ToDo NG private ImagesPane m_imagesPane;
private RoleAdminPane m_rolePane; private RoleAdminPane m_rolePane;
@ -146,7 +146,7 @@ public class ContentSectionPage extends CMSPage implements ActionListener {
// Initialize the individual panes // Initialize the individual panes
m_folderPane = getFolderAdminPane(); m_folderPane = getFolderAdminPane();
//ToDo NG m_browsePane = getBrowsePane(); m_browsePane = getBrowsePane();
m_searchPane = getSearchPane(); m_searchPane = getSearchPane();
//ToDo NG m_imagesPane = getImagesPane(); //ToDo NG m_imagesPane = getImagesPane();
m_rolePane = getRoleAdminPane(); m_rolePane = getRoleAdminPane();
@ -237,13 +237,12 @@ public class ContentSectionPage extends CMSPage implements ActionListener {
* *
* @return * @return
*/ */
// ToDo NG protected BrowsePane getBrowsePane() {
// protected BrowsePane getBrowsePane() { if (m_browsePane == null) {
// if (m_browsePane == null) { m_browsePane = new BrowsePane();
// m_browsePane = new BrowsePane(); }
// } return m_browsePane;
// return m_browsePane; }
// }
/** /**
* Creates, and then caches, the search pane. Overriding this method to * Creates, and then caches, the search pane. Overriding this method to
* return null will prevent this tab from appearing. * return null will prevent this tab from appearing.

View File

@ -0,0 +1,535 @@
/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui;
import com.arsdigita.bebop.ActionLink;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.ParameterSingleSelectionModel;
import com.arsdigita.bebop.Resettable;
import com.arsdigita.bebop.SegmentedPanel;
import com.arsdigita.bebop.SingleSelectionModel;
import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener;
import com.arsdigita.bebop.event.ChangeEvent;
import com.arsdigita.bebop.event.ChangeListener;
import com.arsdigita.bebop.event.FormProcessListener;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.event.FormSubmissionListener;
import com.arsdigita.bebop.event.PrintEvent;
import com.arsdigita.bebop.event.PrintListener;
import com.arsdigita.bebop.parameters.LongParameter;
import com.arsdigita.cms.CMS;
import org.librecms.contentsection.ContentSection;
import com.arsdigita.cms.ui.authoring.CreationSelector;
import com.arsdigita.cms.ui.authoring.NewItemForm;
import com.arsdigita.cms.ui.folder.FolderCreator;
import com.arsdigita.cms.ui.folder.FolderEditor;
import com.arsdigita.cms.ui.folder.FolderManipulator;
import com.arsdigita.cms.ui.folder.FolderPath;
import com.arsdigita.cms.ui.folder.FolderRequestLocal;
import com.arsdigita.cms.ui.folder.FolderSelectionModel;
import com.arsdigita.cms.ui.permissions.CMSPermissionsPane;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.toolbox.ui.ActionGroup;
import com.arsdigita.ui.CcmObjectSelectionModel;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.security.PermissionChecker;
import org.libreccm.security.PermissionManager;
import org.librecms.CmsConstants;
import org.librecms.contentsection.Folder;
import org.librecms.contentsection.privileges.ItemPrivileges;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Encapsulates a {@link FolderManipulator} in order to create a flat item
* listing. Also contains a new item form.
*
* @author <a href="mailto:sfreidin@arsdigita.com">Stanislav Freidin</a>
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class FlatItemList extends SegmentedPanel implements FormProcessListener,
ChangeListener,
FormSubmissionListener,
Resettable,
ActionListener {
private static final String CONTENT_TYPE_ID = "ct";
// The folder selectors
private final FolderSelectionModel folderSelectionModel;
private final FolderRequestLocal folderRequestLocal;
private final NewItemForm newItemForm;
private final SingleSelectionModel<Long> typeSelectionModel;
private final CreationSelector creationSelector;
private final FolderManipulator folderManipulator;
private final FolderCreator folderCreator;
// private final ActionLink m_setHomeFolderAction;
// private final ActionLink m_removeHomeFolderAction;
private final ActionLink createFolderAction;
private final ActionLink togglePrivateAction;
// private final Label m_homeFolderLabel;
private final Segment browseSegment;
private final Segment newItemSegment;
private final Segment newFolderSegment;
private final Segment editFolderSegment;
private final Segment permissionsSegment;
private final CMSPermissionsPane permissionsPane;
// Folder edit/rename functionality.
private final ActionLink editFolderAction;
private final FolderEditor folderEditor;
private final Label contentLabel;
private final FolderPath folderPath;
private final Label chooseLabel;
/**
* Construct a new item listing pane. The provided folder selection model is
* used to keep track of the currently displayed folder.
*
* @param folderRequestLocal
* @param folderSelectionModel maintains the currently displayed folder.
*/
@SuppressWarnings("unchecked")
public FlatItemList(final FolderRequestLocal folderRequestLocal,
final FolderSelectionModel folderSelectionModel) {
this.folderRequestLocal = folderRequestLocal;
this.folderSelectionModel = folderSelectionModel;
folderSelectionModel.addChangeListener(event -> reset(event
.getPageState()));
setIdAttr("flat-item-list");
newItemSegment = addSegment();
newItemSegment.setIdAttr("folder-new-item");
newFolderSegment = addSegment();
newFolderSegment.setIdAttr("folder-new-folder");
editFolderSegment = addSegment();
editFolderSegment.setIdAttr("folder-edit-folder");
browseSegment = addSegment();
browseSegment.setIdAttr("folder-browse");
final ActionGroup browseActions = new ActionGroup();
browseSegment.add(browseActions);
// The top 'browse' segment
contentLabel = new Label(globalize("cms.ui.contents_of"), false);
browseSegment.addHeader(contentLabel);
chooseLabel = new Label(globalize("cms.ui.choose_target_folder"),
false);
browseSegment.addHeader(chooseLabel);
folderPath = new FolderPath(folderSelectionModel);
browseSegment.addHeader(folderPath);
folderManipulator = new FolderManipulator(folderSelectionModel);
folderManipulator.getItemView().addProcessListener(this);
folderManipulator.getTargetSelector().addProcessListener(this);
folderManipulator.getTargetSelector().addSubmissionListener(this);
browseActions.setSubject(folderManipulator);
// The actions
createFolderAction = new ActionLink(new Label(globalize(
"cms.ui.new_folder")));
createFolderAction.addActionListener(this);
browseActions.addAction(createFolderAction);
editFolderAction = new ActionLink(new Label(globalize(
"cms.ui.edit_folder")));
editFolderAction.addActionListener(this);
browseActions.addAction(editFolderAction);
// m_setHomeFolderAction = new ActionLink(new Label(globalize(
// "cms.ui.set_home_folder")));
// m_setHomeFolderAction.addActionListener(this);
// browseActions.addAction(m_setHomeFolderAction);
// m_homeFolderLabel = new Label(new PrintListener() {
//
// @Override
// public final void prepare(final PrintEvent event) {
// Label label = (Label) event.getTarget();
// User user = Web.getWebContext().getUser();
//
// Folder folder = Folder.getUserHomeFolder(user, CMS.getContext()
// .getContentSection());
// if (folder != null) {
// String url = folder.getContentSection().getURL()
// + PageLocations.SECTION_PAGE + "?"
// + ContentSectionPage.SET_FOLDER + "="
// + folder.getID();
// //label.setLabel("Go to home folder: <a href=\"" + url + "\">" + folder.getLabel() + "</a>");
// String[] parts = new String[3];
// parts[0] = "";
// parts[1] = url;
// parts[2] = folder.getLabel();
// // label.setLabel(String.format("%s: <a href=\"%s\">%s</a>",
// // (String) globalize("cms.ui.go_to_home_folder").localize(),
// // url,
// // folder.getLabel()));
// label.setLabel(globalize("cms.ui.go_to_home_folder", parts));
// } else {
// //label.setLabel("<font color=\"red\">No home folder selected</font>");
// String[] parts = new String[3];
// parts[0] = "";
// parts[1] = "";
// //label.setLabel(String.format("<span style=\"color: red\">%s</span>",
// // (String)globalize("cms.ui.no_home_folder_selected").localize()));
// label.setLabel(globalize("cms.ui.no_home_folder_selected",
// parts));
// }
// label.setOutputEscaping(false);
// }
//
// });
// browseActions.addAction(m_homeFolderLabel);
// m_removeHomeFolderAction = new ActionLink(new Label(globalize(
// "cms.ui.remove_home_folder")));
// m_removeHomeFolderAction.addActionListener(this);
// browseActions.addAction(m_removeHomeFolderAction);
/* */
newItemForm = new SectionNewItemForm("newItem");
newItemForm.addProcessListener(this);
browseActions.addAction(newItemForm);
/* permission */
permissionsSegment = addSegment();
permissionsSegment.setIdAttr("folder-permissions");
final ActionGroup permissionActions = new ActionGroup();
permissionsSegment.add(permissionActions);
// The permissions segment
permissionsSegment.addHeader(new Label(new GlobalizedMessage(
"cms.ui.permissions", CmsConstants.CMS_BUNDLE)));
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final PermissionManager permissionManager = cdiUtil.findBean(
PermissionManager.class);
final List<String> privileges = permissionManager
.listDefiniedPrivileges(ItemPrivileges.class);
final Map<String, String> privNameMap = new HashMap<>();
privileges.forEach(privilege -> privNameMap.put(privilege, privilege));
permissionsPane = new CMSPermissionsPane(
privileges.toArray(new String[]{}),
privNameMap,
(CcmObjectSelectionModel) folderSelectionModel);
permissionActions.setSubject(permissionsPane);
// An action
togglePrivateAction = new ActionLink(new Label(new PrintListener() {
@Override
public void prepare(final PrintEvent event) {
final PageState state = event.getPageState();
final Label target = (Label) event.getTarget();
final Folder currentFolder = folderRequestLocal.getFolder(state);
// ACSObject parent = currentFolder.getParent();
// if (context == null) {
target.setLabel(new GlobalizedMessage(
"cms.ui.restore_default_permissions",
CmsConstants.CMS_BUNDLE));
// } else {
// target.setLabel(GlobalizationUtil
// .globalize("cms.ui.use_custom_permissions"));
// }
}
}));
togglePrivateAction.addActionListener(this);
permissionActions.addAction(togglePrivateAction);
// The 'new item' segment
newItemSegment.addHeader(new Label(globalize("cms.ui.new_item")));
typeSelectionModel = new ParameterSingleSelectionModel<>(
new LongParameter(CONTENT_TYPE_ID));
typeSelectionModel.addChangeListener(this);
creationSelector = new CreationSelector(typeSelectionModel,
folderSelectionModel);
newItemSegment.add(creationSelector);
//m_newItemSeg.add(new Label("<br/>", false));
// The 'new folder' segment
newFolderSegment.addHeader(new Label(globalize("cms.ui.new_folder")));
Form folderCreate = new Form("fcreat");
folderCreator = new FolderCreator("fcreat", folderSelectionModel);
folderCreator.addSubmissionListener(this);
folderCreator.addProcessListener(this);
folderCreate.add(folderCreator);
newFolderSegment.add(folderCreate);
newFolderSegment.add(new Label("<br/>", false));
editFolderSegment.addHeader(new Label(globalize("cms.ui.edit_folder")));
folderEditor = new FolderEditor("fedit", folderSelectionModel);
folderEditor.addSubmissionListener(this);
folderEditor.addProcessListener(this);
Form folderEditorForm = new Form("fedit_form");
folderEditorForm.add(folderEditor);
editFolderSegment.add(folderEditorForm);
editFolderSegment.add(new Label("<br/>", false));
}
@Override
public void register(final Page page) {
super.register(page);
page.setVisibleDefault(chooseLabel, false);
page.setVisibleDefault(newItemSegment, false);
page.setVisibleDefault(newFolderSegment, false);
page.setVisibleDefault(editFolderSegment, false);
page
.addComponentStateParam(this, typeSelectionModel.getStateParameter());
page.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent event) {
final PageState state = event.getPageState();
if (state.isVisibleOnPage(FlatItemList.this)) {
showHideSegments(state);
}
}
});
}
/**
* Show/hide segments based on access checks.
*
* @param state The page state
*
* @pre ( state != null )
*/
private void showHideSegments(final PageState state) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final PermissionChecker permissionChecker = cdiUtil.findBean(
PermissionChecker.class);
final Folder folder = folderRequestLocal.getFolder(state);
// MP: This should be checked on the current folder instead of just
// the content section.
final boolean newItem = permissionChecker.isPermitted(
ItemPrivileges.CREATE_NEW, folder);
if (!newItem) {
browseMode(state);
}
createFolderAction.setVisible(state, newItem);
newItemForm.setVisible(state, newItem);
final boolean editItem = permissionChecker.isPermitted(
ItemPrivileges.EDIT, folder);
editFolderAction.setVisible(state, editItem);
if (permissionChecker.isPermitted(ItemPrivileges.ADMINISTER, folder)) {
permissionsSegment.setVisible(state, true);
} else {
permissionsSegment.setVisible(state, false);
}
}
private void browseMode(final PageState state) {
browseSegment.setVisible(state, true);
permissionsSegment.setVisible(state, true);
chooseLabel.setVisible(state, false);
contentLabel.setVisible(state, true);
folderPath.setVisible(state, true);
newItemSegment.setVisible(state, false);
newFolderSegment.setVisible(state, false);
editFolderSegment.setVisible(state, false);
typeSelectionModel.clearSelection(state);
}
private void newItemMode(final PageState state) {
permissionsSegment.setVisible(state, false);
newItemSegment.setVisible(state, true);
}
private void newFolderMode(final PageState state) {
permissionsSegment.setVisible(state, false);
newFolderSegment.setVisible(state, true);
}
@Override
public void submitted(final FormSectionEvent event)
throws FormProcessException {
final PageState state = event.getPageState();
if (event.getSource() == folderCreator
&& folderCreator.isCancelled(state)) {
browseMode(state);
throw new FormProcessException(new GlobalizedMessage(
"cms.ui.cancelled", CmsConstants.CMS_BUNDLE));
} else if (event.getSource() == folderEditor && folderEditor
.isCancelled(state)) {
browseMode(state);
throw new FormProcessException(new GlobalizedMessage(
"cms.ui.cancelled", CmsConstants.CMS_BUNDLE));
} else if (event.getSource() == folderManipulator.getTargetSelector()) {
// This only works if this submission listener is run
// after the target selector's one
if (!folderManipulator.getTargetSelector().isVisible(state)) {
browseMode(state);
}
}
}
@Override
public void process(final FormSectionEvent event) {
final PageState state = event.getPageState();
final Object source = event.getSource();
if (source == newItemForm) {
final Long typeID = newItemForm.getTypeID(state);
typeSelectionModel.setSelectedKey(state, typeID);
newItemMode(state);
} else if (source == folderCreator || source == folderEditor) {
browseMode(state);
} else if (source == folderManipulator.getItemView()) {
// Hide everything except for the browseSeg
permissionsSegment.setVisible(state, false);
chooseLabel.setVisible(state, true);
contentLabel.setVisible(state, false);
folderPath.setVisible(state, false);
} else if (source == folderManipulator.getTargetSelector()) {
browseMode(state);
}
}
@Override
public void stateChanged(final ChangeEvent event) {
final PageState state = event.getPageState();
if (event.getSource().equals(typeSelectionModel)) {
if (!typeSelectionModel.isSelected(state)) {
browseMode(state);
}
}
}
@Override
public void actionPerformed(final ActionEvent event) {
final PageState state = event.getPageState();
final Object source = event.getSource();
if (source == createFolderAction) {
newFolderMode(state);
} else if (source == editFolderAction) {
permissionsSegment.setVisible(state, false);
editFolderSegment.setVisible(state, true);
} else if (source == togglePrivateAction) {
togglePermissions(state);
}
// } else if (source == m_setHomeFolderAction) {
// User user = Web.getWebContext().getUser();
// Folder folder = m_folder.getFolder(state);
// user = (User) DomainObjectFactory.newInstance(user.getOID());
// Folder.setUserHomeFolder(user, folder);
// } else if (source == m_removeHomeFolderAction) {
// User user = Web.getWebContext().getUser();
// ContentSection section = CMS.getContext().getContentSection();
// UserHomeFolderMap map = UserHomeFolderMap
// .findUserHomeFolderMap(user, section);
// if (map != null) {
// map.delete();
// }
// }
}
private void togglePermissions(final PageState state) {
final Folder currentFolder = folderRequestLocal.getFolder(state);
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final PermissionChecker permissionChecker = cdiUtil.findBean(
PermissionChecker.class);
permissionChecker.checkPermission(ItemPrivileges.ADMINISTER,
currentFolder);
permissionsPane.reset(state);
}
@Override
public void reset(final PageState state) {
browseMode(state);
folderManipulator.reset(state);
// switching between folders used to keep showing the permission pane
// in the same perm mode (direct or inherited) regardless
// of the folder status
permissionsPane.reset(state);
}
public final FolderManipulator getManipulator() {
return folderManipulator;
}
public final CMSPermissionsPane getPermissionsPane() {
return permissionsPane;
}
public void setPermissionLinkVis(PageState state) {
final Folder currentFolder = folderRequestLocal.getFolder(state);
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final PermissionChecker permissionChecker = cdiUtil.findBean(
PermissionChecker.class);
if (!permissionChecker.isPermitted(ItemPrivileges.ADMINISTER,
currentFolder)) {
togglePrivateAction.setVisible(state, false);
}
}
private static class SectionNewItemForm extends NewItemForm {
public SectionNewItemForm(final String name) {
super(name);
}
@Override
public ContentSection getContentSection(final PageState state) {
return CMS.getContext().getContentSection();
}
}
/**
* Getting the GlobalizedMessage using a CMS Class targetBundle.
*
* @param key The resource key
*
* @pre ( key != null )
*/
private static GlobalizedMessage globalize(final String key) {
return ContentSectionPage.globalize(key);
}
}

View File

@ -1,604 +0,0 @@
/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui;
import com.arsdigita.bebop.ActionLink;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.ParameterSingleSelectionModel;
import com.arsdigita.bebop.Resettable;
import com.arsdigita.bebop.SegmentedPanel;
import com.arsdigita.bebop.SingleSelectionModel;
import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener;
import com.arsdigita.bebop.event.ChangeEvent;
import com.arsdigita.bebop.event.ChangeListener;
import com.arsdigita.bebop.event.FormProcessListener;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.event.FormSubmissionListener;
import com.arsdigita.bebop.event.PrintEvent;
import com.arsdigita.bebop.event.PrintListener;
import com.arsdigita.bebop.parameters.BigDecimalParameter;
import com.arsdigita.cms.CMS;
import org.librecms.contentsection.ContentSection;
import com.arsdigita.cms.dispatcher.Utilities;
import com.arsdigita.cms.ui.authoring.CreationSelector;
import com.arsdigita.cms.ui.authoring.NewItemForm;
import com.arsdigita.cms.ui.folder.FolderCreator;
import com.arsdigita.cms.ui.folder.FolderEditor;
import com.arsdigita.cms.ui.folder.FolderManipulator;
import com.arsdigita.cms.ui.folder.FolderRequestLocal;
import com.arsdigita.cms.ui.folder.FolderSelectionModel;
import com.arsdigita.cms.ui.folder.ItemPath;
import com.arsdigita.cms.ui.permissions.CMSPermissionsPane;
import com.arsdigita.cms.util.GlobalizationUtil;
import com.arsdigita.domain.DomainObjectFactory;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.kernel.ACSObject;
import com.arsdigita.kernel.Kernel;
import com.arsdigita.kernel.User;
import com.arsdigita.kernel.permissions.ObjectPermissionCollection;
import com.arsdigita.kernel.permissions.PermissionDescriptor;
import com.arsdigita.kernel.permissions.PermissionService;
import com.arsdigita.kernel.permissions.PrivilegeDescriptor;
import com.arsdigita.persistence.DataObject;
import com.arsdigita.persistence.DataQuery;
import com.arsdigita.persistence.SessionManager;
import com.arsdigita.toolbox.ui.ActionGroup;
import com.arsdigita.util.Assert;
import com.arsdigita.web.Web;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Encapsulates a {@link FolderManipulator} in order to create a flat item
* listing. Also contains a new item form.
*
* @author <a href="mailto:sfreidin@arsdigita.com">Stanislav Freidin</a>
* @version $Id: FlatItemList.java 1538 2007-03-23 16:26:36Z apevec $
*/
public class FlatItemList extends SegmentedPanel
implements FormProcessListener, ChangeListener, FormSubmissionListener,
Resettable, ActionListener {
private static final String CONTENT_TYPE_ID = "ct";
private static final String CMS_PRIVILEGES = "com.arsdigita.cms.getPrivileges";
private static final String PRIVILEGE = "privilege";
private static final String PRIVILEGE_NAME = "prettyName";
// The folder selectors
private final FolderSelectionModel m_folderSel;
private FolderRequestLocal m_folder;
private final NewItemForm m_newItem;
private final SingleSelectionModel m_typeSel;
private final CreationSelector m_selector;
private final FolderManipulator m_folderManip;
private final FolderCreator m_folderCreator;
private final ActionLink m_setHomeFolderAction;
private final ActionLink m_removeHomeFolderAction;
private final ActionLink m_createFolderAction;
private final ActionLink m_togglePrivateAction;
private final Label m_homeFolderLabel;
private final Segment m_browseSeg;
private final Segment m_newItemSeg;
private final Segment m_newFolderSeg;
private final Segment m_editFolderSeg;
private final Segment m_permissionsSeg;
private final CMSPermissionsPane m_permPane;
// Folder edit/rename functionality.
private final ActionLink m_editFolderAction;
private final FolderEditor m_folderEditor;
private final Label m_contentLabel;
private final ItemPath m_itemPath;
private final Label m_chooseLabel;
/**
* Construct a new item listing pane. The provided folder selection model
* is used to keep track of the currently displayed folder.
*
* @param folder
* @param model maintains the currently displayed folder.
*/
public FlatItemList(final FolderRequestLocal folder,
final FolderSelectionModel model) {
m_folder = folder;
m_folderSel = model;
m_folderSel.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
PageState s = e.getPageState();
reset(s);
}
});
setIdAttr("flat-item-list");
m_newItemSeg = addSegment();
m_newItemSeg.setIdAttr("folder-new-item");
m_newFolderSeg = addSegment();
m_newFolderSeg.setIdAttr("folder-new-folder");
m_editFolderSeg = addSegment();
m_editFolderSeg.setIdAttr("folder-edit-folder");
m_browseSeg = addSegment();
m_browseSeg.setIdAttr("folder-browse");
final ActionGroup browseActions = new ActionGroup();
m_browseSeg.add(browseActions);
// The top 'browse' segment
m_contentLabel = new Label(globalize("cms.ui.contents_of"), false);
m_browseSeg.addHeader(m_contentLabel);
m_chooseLabel = new Label(globalize("cms.ui.choose_target_folder"), false);
m_browseSeg.addHeader(m_chooseLabel);
m_itemPath = new ItemPath(m_folderSel);
//m_itemPath = new Label(new PrintListener() {
// public final void prepare(final PrintEvent e) {
// final Folder f = m_folder.getFolder(e.getPageState());
// ((Label) e.getTarget()).setLabel(f.getDisplayName());
// }
// });
m_browseSeg.addHeader(m_itemPath);
m_folderManip = new FolderManipulator(m_folderSel);
m_folderManip.getItemView().addProcessListener(this);
m_folderManip.getTargetSelector().addProcessListener(this);
m_folderManip.getTargetSelector().addSubmissionListener(this);
browseActions.setSubject(m_folderManip);
// The actions
m_createFolderAction = new ActionLink(new Label(globalize("cms.ui.new_folder")));
m_createFolderAction.addActionListener(this);
browseActions.addAction(m_createFolderAction);
m_editFolderAction = new ActionLink(new Label(globalize("cms.ui.edit_folder")));
m_editFolderAction.addActionListener(this);
browseActions.addAction(m_editFolderAction);
m_setHomeFolderAction = new ActionLink(new Label(globalize("cms.ui.set_home_folder")));
m_setHomeFolderAction.addActionListener(this);
browseActions.addAction(m_setHomeFolderAction);
m_homeFolderLabel = new Label(new PrintListener() {
@Override
public final void prepare(final PrintEvent e) {
Label label = (Label) e.getTarget();
User user = Web.getWebContext().getUser();
Folder folder = Folder.getUserHomeFolder(user, CMS.getContext().getContentSection());
if (folder != null) {
String url = folder.getContentSection().getURL() + PageLocations.SECTION_PAGE + "?"
+ ContentSectionPage.SET_FOLDER + "=" + folder.getID();
//label.setLabel("Go to home folder: <a href=\"" + url + "\">" + folder.getLabel() + "</a>");
String[] parts = new String[3];
parts[0] = "";
parts[1] = url;
parts[2] = folder.getLabel();
// label.setLabel(String.format("%s: <a href=\"%s\">%s</a>",
// (String) globalize("cms.ui.go_to_home_folder").localize(),
// url,
// folder.getLabel()));
label.setLabel( globalize("cms.ui.go_to_home_folder",parts) );
} else {
//label.setLabel("<font color=\"red\">No home folder selected</font>");
String[] parts = new String[3];
parts[0] = "";
parts[1] = "";
//label.setLabel(String.format("<span style=\"color: red\">%s</span>",
// (String)globalize("cms.ui.no_home_folder_selected").localize()));
label.setLabel( globalize("cms.ui.no_home_folder_selected",parts) );
}
label.setOutputEscaping(false);
}
});
browseActions.addAction(m_homeFolderLabel);
m_removeHomeFolderAction = new ActionLink(new Label(globalize("cms.ui.remove_home_folder")));
m_removeHomeFolderAction.addActionListener(this);
browseActions.addAction(m_removeHomeFolderAction);
/* */
m_newItem = new SectionNewItemForm("newItem");
m_newItem.addProcessListener(this);
browseActions.addAction(m_newItem);
/* permission */
m_permissionsSeg = addSegment();
m_permissionsSeg.setIdAttr("folder-permissions");
final ActionGroup permActions = new ActionGroup();
m_permissionsSeg.add(permActions);
// The permissions segment
m_permissionsSeg.addHeader(new Label(GlobalizationUtil.globalize("cms.ui.permissions")));
List privs = new ArrayList();
Map privNameMap = new HashMap();
DataQuery query = SessionManager.getSession().retrieveQuery(CMS_PRIVILEGES);
query.addFilter("scope != 'section'");
query.addOrder("sortOrder");
while (query.next()) {
String privilege = (String) query.get(PRIVILEGE);
String privilegeName = (String) query.get(PRIVILEGE_NAME);
privs.add(PrivilegeDescriptor.get(privilege));
privNameMap.put(privilege, privilegeName);
}
query.close();
m_permPane =
new CMSPermissionsPane((PrivilegeDescriptor[]) privs.toArray(new PrivilegeDescriptor[privs.size()]),
privNameMap,
m_folderSel);
permActions.setSubject(m_permPane);
// An action
m_togglePrivateAction = new ActionLink(new Label(new PrintListener() {
public void prepare(PrintEvent e) {
PageState state = e.getPageState();
Label target = (Label) e.getTarget();
Folder currentFolder = m_folder.getFolder(state);
// ACSObject parent = currentFolder.getParent();
DataObject context = PermissionService.getContext(currentFolder);
if (context == null) {
target.setLabel(GlobalizationUtil
.globalize("cms.ui.restore_default_permissions"));
} else {
target.setLabel(GlobalizationUtil
.globalize("cms.ui.use_custom_permissions"));
}
}
}));
m_togglePrivateAction.addActionListener(this);
permActions.addAction(m_togglePrivateAction);
// The 'new item' segment
m_newItemSeg.addHeader(new Label(globalize("cms.ui.new_item")));
m_typeSel = new ParameterSingleSelectionModel(new BigDecimalParameter(CONTENT_TYPE_ID));
m_typeSel.addChangeListener(this);
m_selector = new CreationSelector(m_typeSel, m_folderSel);
m_newItemSeg.add(m_selector);
//m_newItemSeg.add(new Label("<br/>", false));
// The 'new folder' segment
m_newFolderSeg.addHeader(new Label(globalize("cms.ui.new_folder")));
Form folderCreate = new Form("fcreat");
m_folderCreator = new FolderCreator("fcreat", m_folderSel);
m_folderCreator.addSubmissionListener(this);
m_folderCreator.addProcessListener(this);
folderCreate.add(m_folderCreator);
m_newFolderSeg.add(folderCreate);
m_newFolderSeg.add(new Label("<br/>", false));
m_editFolderSeg.addHeader(new Label(globalize("cms.ui.edit_folder")));
m_folderEditor = new FolderEditor("fedit", m_folderSel);
m_folderEditor.addSubmissionListener(this);
m_folderEditor.addProcessListener(this);
Form folderEditorForm = new Form("fedit_form");
folderEditorForm.add(m_folderEditor);
m_editFolderSeg.add(folderEditorForm);
m_editFolderSeg.add(new Label("<br/>", false));
}
@Override
public void register(Page p) {
super.register(p);
p.setVisibleDefault(m_chooseLabel, false);
p.setVisibleDefault(m_newItemSeg, false);
p.setVisibleDefault(m_newFolderSeg, false);
p.setVisibleDefault(m_editFolderSeg, false);
p.addComponentStateParam(this, m_typeSel.getStateParameter());
p.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
final PageState state = e.getPageState();
if (state.isVisibleOnPage(FlatItemList.this)) {
showHideSegments(state);
}
}
});
}
/**
* Show/hide segments based on access checks.
*
* @param state The page state
* @pre ( state != null )
*/
private void showHideSegments(PageState state) {
SecurityManager sm = Utilities.getSecurityManager(state);
Folder folder = m_folder.getFolder(state);
Assert.exists(folder);
// MP: This should be checked on the current folder instead of just
// the content section.
boolean newItem =
sm.canAccess(state.getRequest(),
SecurityManager.NEW_ITEM,
folder);
if (!newItem) {
browseMode(state);
}
m_createFolderAction.setVisible(state, newItem);
m_newItem.setVisible(state, newItem);
final boolean editItem = sm.canAccess(state.getRequest(),
SecurityManager.EDIT_ITEM,
folder);
m_editFolderAction.setVisible(state, editItem);
User user = (User) Kernel.getContext().getParty();
PermissionDescriptor perm =
new PermissionDescriptor(PrivilegeDescriptor.ADMIN,
folder,
user);
if (PermissionService.checkPermission(perm)) {
m_permissionsSeg.setVisible(state, true);
} else {
m_permissionsSeg.setVisible(state, false);
}
}
private void browseMode(PageState s) {
m_browseSeg.setVisible(s, true);
m_permissionsSeg.setVisible(s, true);
m_chooseLabel.setVisible(s, false);
m_contentLabel.setVisible(s, true);
m_itemPath.setVisible(s, true);
m_newItemSeg.setVisible(s, false);
m_newFolderSeg.setVisible(s, false);
m_editFolderSeg.setVisible(s, false);
m_typeSel.clearSelection(s);
}
private void newItemMode(PageState s) {
m_permissionsSeg.setVisible(s, false);
m_newItemSeg.setVisible(s, true);
}
private void newFolderMode(PageState s) {
m_permissionsSeg.setVisible(s, false);
m_newFolderSeg.setVisible(s, true);
}
@Override
public void submitted(FormSectionEvent e)
throws FormProcessException {
PageState s = e.getPageState();
if (e.getSource() == m_folderCreator
&& m_folderCreator.isCancelled(s)) {
browseMode(s);
throw new FormProcessException(GlobalizationUtil.globalize("cms.ui.cancelled"));
} else if (e.getSource() == m_folderEditor && m_folderEditor.isCancelled(s)) {
browseMode(s);
throw new FormProcessException(GlobalizationUtil.globalize("cms.ui.cancelled"));
} else if (e.getSource() == m_folderManip.getTargetSelector()) {
// This only works if this submission listener is run
// after the target selector's one
if (!m_folderManip.getTargetSelector().isVisible(s)) {
browseMode(s);
}
}
}
@Override
public void process(FormSectionEvent e) {
PageState s = e.getPageState();
final Object source = e.getSource();
if (source == m_newItem) {
BigDecimal typeID = m_newItem.getTypeID(s);
m_typeSel.setSelectedKey(s, typeID);
newItemMode(s);
} else if (source == m_folderCreator || source == m_folderEditor) {
browseMode(s);
} else if (source == m_folderManip.getItemView()) {
// Hide everything except for the browseSeg
m_permissionsSeg.setVisible(s, false);
m_chooseLabel.setVisible(s, true);
m_contentLabel.setVisible(s, false);
m_itemPath.setVisible(s, false);
} else if (source == m_folderManip.getTargetSelector()) {
browseMode(s);
}
}
@Override
public void stateChanged(ChangeEvent e) {
PageState s = e.getPageState();
if (e.getSource().equals(m_typeSel)) {
if (!m_typeSel.isSelected(s)) {
browseMode(s);
}
}
}
@Override
public void actionPerformed(ActionEvent e) {
PageState s = e.getPageState();
Object source = e.getSource();
if (source == m_createFolderAction) {
newFolderMode(s);
} else if (source == m_editFolderAction) {
m_permissionsSeg.setVisible(s, false);
m_editFolderSeg.setVisible(s, true);
} else if (source == m_togglePrivateAction) {
togglePermissions(s);
} else if (source == m_setHomeFolderAction) {
User user = Web.getWebContext().getUser();
Folder folder = m_folder.getFolder(s);
user = (User) DomainObjectFactory.newInstance(user.getOID());
Folder.setUserHomeFolder(user, folder);
} else if( source == m_removeHomeFolderAction) {
User user = Web.getWebContext().getUser();
ContentSection section = CMS.getContext().getContentSection();
UserHomeFolderMap map = UserHomeFolderMap.findUserHomeFolderMap(user, section);
if (map != null) {
map.delete();
}
}
}
private void togglePermissions(PageState state) {
Folder currentFolder = m_folder.getFolder(state);
if (!Utilities.getSecurityManager(state).canAccess(state.getRequest(), SecurityManager.STAFF_ADMIN)) {
throw new com.arsdigita.cms.dispatcher.AccessDeniedException();
}
DataObject context = PermissionService.getContext(currentFolder);
if (context != null) {
PermissionService.clonePermissions(currentFolder);
Folder liveFolder = (Folder) currentFolder.getLiveVersion();
if (liveFolder != null) {
PermissionService.setContext(liveFolder, currentFolder);
}
} else {
ACSObject parent = currentFolder.getParent();
if (parent != null) {
PermissionService.setContext(currentFolder, parent);
} else {
// if the folder has no parent, it must be a root folder or template folder
// in this case, set it's context to the ContentSection
ContentSection section = currentFolder.getContentSection();
if (section != null) {
PermissionService.setContext(currentFolder, section);
} else {
throw new IllegalStateException("Cannot set the context for a folder with "
+ "no parent and no Content Section");
}
}
Folder liveVersion = (Folder) currentFolder.getLiveVersion();
if (liveVersion != null) {
ACSObject liveParent = liveVersion.getParent();
if (liveParent != null) {
PermissionService.setContext(liveVersion, liveParent);
} else {
ContentSection liveSection = liveVersion.getContentSection();
if (liveSection != null) {
PermissionService.setContext(liveVersion, liveSection);
} else {
throw new IllegalStateException("Cannot set the context for a folder with "
+ "no parent and no Content Section");
}
}
}
// revoke all direct permissions so folder will only have inherited permissions
ObjectPermissionCollection perms = PermissionService.getGrantedPermissions(currentFolder.getOID());
while (perms.next()) {
if (!perms.isInherited() && !perms.getPrivilege().equals(PrivilegeDescriptor.ADMIN)) {
PermissionDescriptor desc = new PermissionDescriptor(perms.getPrivilege(), currentFolder.getOID(),
perms.getGranteeOID());
PermissionService.revokePermission(desc);
}
}
if (liveVersion != null) {
ObjectPermissionCollection livePerms = PermissionService.getGrantedPermissions(liveVersion.getOID());
while (livePerms.next()) {
if (!livePerms.isInherited()) {
PermissionDescriptor desc2 = new PermissionDescriptor(livePerms.getPrivilege(), liveVersion.
getOID(),
livePerms.getGranteeOID());
PermissionService.revokePermission(desc2);
}
}
}
}
m_permPane.reset(state);
}
@Override
public void reset(PageState s) {
browseMode(s);
m_folderManip.reset(s);
// switching between folders used to keep showing the permission pane
// in the same perm mode (direct or inherited) regardless
// of the folder status
m_permPane.reset(s);
}
public final FolderManipulator getManipulator() {
return m_folderManip;
}
public final CMSPermissionsPane getPermissionsPane() {
return m_permPane;
}
public void setPermissionLinkVis(PageState state) {
if (!Utilities.getSecurityManager(state).
canAccess(state.getRequest(), SecurityManager.STAFF_ADMIN)) {
m_togglePrivateAction.setVisible(state, false);
}
}
private static class SectionNewItemForm extends NewItemForm {
public SectionNewItemForm(String name) {
super(name);
}
@Override
public ContentSection getContentSection(PageState s) {
return CMS.getContext().getContentSection();
}
}
/**
* Getting the GlobalizedMessage using a CMS Class targetBundle.
*
* @param key The resource key
* @pre ( key != null )
*/
private static GlobalizedMessage globalize(String key) {
return ContentSectionPage.globalize(key);
}
private static GlobalizedMessage globalize(final String key,
final Object[] args) {
return ContentSectionPage.globalize(key, args);
}
}

View File

@ -113,11 +113,11 @@ public abstract class UserAddForm extends SimpleContainer
m_form = makeForm(name); m_form = makeForm(name);
Label title = new Label(new GlobalizedMessage("cms.ui.matches", final Label title = new Label(new GlobalizedMessage("cms.ui.matches",
CmsConstants.CMS_BUNDLE)); CmsConstants.CMS_BUNDLE));
title.setFontWeight(Label.BOLD); title.setFontWeight(Label.BOLD);
Label label = new Label(new GlobalizedMessage( final Label label = new Label(new GlobalizedMessage(
"cms.ui.there_was_no_one_matching_the_search_criteria", "cms.ui.there_was_no_one_matching_the_search_criteria",
CmsConstants.CMS_BUNDLE)); CmsConstants.CMS_BUNDLE));
label.setFontWeight("em"); label.setFontWeight("em");

View File

@ -0,0 +1,285 @@
/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.authoring;
import com.arsdigita.bebop.ColumnPanel;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.MetaForm;
import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.SingleSelectionModel;
import com.arsdigita.bebop.form.FormErrorDisplay;
import com.arsdigita.bebop.parameters.BigDecimalParameter;
import com.arsdigita.bebop.parameters.LongParameter;
import com.arsdigita.cms.ItemSelectionModel;
import com.arsdigita.cms.ui.ContentItemPage;
import com.arsdigita.cms.ui.folder.FolderSelectionModel;
import com.arsdigita.cms.ui.item.ItemCreateForm;
import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.web.RedirectSignal;
import com.arsdigita.web.URL;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.libreccm.cdi.utils.CdiUtil;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentType;
import org.librecms.contentsection.ContentTypeManager;
import org.librecms.contentsection.ContentTypeRepository;
import org.librecms.contentsection.Folder;
import org.librecms.contenttypes.AuthoringKit;
import org.librecms.contenttypes.AuthoringKitInfo;
import org.librecms.contenttypes.ContentTypeInfo;
import org.librecms.contenttypes.ContentTypesManager;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
/**
* An invisible component which contains all the possible creation components.
* The components are loaded from the database at construction time. The
* selector uses a {@link SingleSelectionModel} in order to get the ID of the
* current content type.
*
* <strong>Important:</strong> This component is passed in the constructor to
* every authoring kit creation component (such as {@link PageCreate}). The
* creation component is supposed to follow the following pattern:
*
* <blockquote><pre>
* // The member variable m_parent points to the CreationSelector
* SomeContentItem item = somehowCreateTheItem(state);
* item.setParent(m_parent.getFolder(state));
* m_parent.editItem(state, item);
* </pre></blockquote>
*
* If the creation component wishes to cancel the creation process, it should
* call
*
* <blockquote><pre>m_parent.redirectBack(state);</pre></blockquote>
*
* The component may also call
*
* <blockquote><pre>m_parent.getContentSection(state);</pre></blockquote>
*
* in order to get the current content section.
*
* @author unknown
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class CreationSelector extends MetaForm {
private static final Logger LOGGER = LogManager.getLogger(
CreationSelector.class);
private final FolderSelectionModel folderSelectionModel;
private final SingleSelectionModel<Long> typeSelectionModel;
private static Class[] arguments = new Class[]{
ItemSelectionModel.class,
CreationSelector.class
};
private Object[] values;
private final ItemSelectionModel itemSelectionModel;
private final LongParameter itemIdParameter;
public static final String ITEM_ID = "iid";
/**
* Constructs a new <code>CreationSelector</code>. Load all the possible
* creation components from the database and stick them in the Map.
*
* @param typeSelectionModel the {@link SingleSelectionModel} which will
* supply a BigDecimal ID of the content type to
* instantiate
*
* @param folderSelectionModel the {@link FolderSelectionModel} containing
* the folder in which new items are to be
* created
*/
public CreationSelector(final SingleSelectionModel<Long> typeSelectionModel,
final FolderSelectionModel folderSelectionModel) {
super("pageCreate");
this.typeSelectionModel = typeSelectionModel;
this.folderSelectionModel = folderSelectionModel;
itemIdParameter = new LongParameter(ITEM_ID);
itemSelectionModel = new ItemSelectionModel(itemIdParameter);
}
/**
*
* @param state
*
* @return
*/
@Override
public Form buildForm(final PageState state) {
final Long typeId = typeSelectionModel.getSelectedKey(state);
final Component component;
final Form returnForm = new Form("pageCreate");
final FormErrorDisplay formErrorDisplay = new FormErrorDisplay(this);
formErrorDisplay.setStateParamsAreRegistered(false);
returnForm.add(formErrorDisplay, ColumnPanel.FULL_WIDTH
| ColumnPanel.LEFT);
if (typeId != null) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentTypeRepository typeRepo = cdiUtil.findBean(
ContentTypeRepository.class);
final ContentTypeManager typeManager = cdiUtil.findBean(
ContentTypeManager.class);
final ContentTypesManager typesManager = cdiUtil.findBean(
ContentTypesManager.class);
final ContentType type = typeRepo.findById(typeId);
if (type == null) {
throw new UncheckedWrapperException(String.format(
"Type with id %d not found.", typeId));
}
final ContentTypeInfo typeInfo = typesManager.getContentTypeInfo(
type);
final AuthoringKitInfo kit = typeInfo.getAuthoringKit();
component = instantiateKitComponent(kit, type);
if (component != null) {
returnForm.add(component);
returnForm.setMethod(Form.POST);
returnForm.setEncType("multipart/form-data");
}
}
return returnForm;
}
/**
* Add the item_id parameter.
*
* @param page
*/
@Override
public void register(final Page page) {
super.register(page);
page.addComponentStateParam(this, itemIdParameter);
}
/**
* Get the creation component.
*
* @param kit
* @param type
*
* @return
*/
protected Component instantiateKitComponent(final AuthoringKitInfo kit,
final ContentType type) {
final Class<? extends ItemCreateForm> createClass = kit
.getCreateComponent();
final Object[] vals;
try {
final ItemSelectionModel itemModel = new ItemSelectionModel(type,
itemIdParameter);
vals = new Object[]{itemModel, this};
final Constructor<? extends ItemCreateForm> constructor
= createClass
.getConstructor(arguments);
final Component component = (Component) constructor
.newInstance(vals);
return component;
} catch (IllegalAccessException
| IllegalArgumentException
| InstantiationException
| NoSuchMethodException
| SecurityException
| InvocationTargetException ex) {
LOGGER.error("\"Failed to instantiate creation component \"{}\".",
kit.getCreateComponent().getName());
LOGGER.error(ex);
throw new UncheckedWrapperException(String.format(
"Failed to instantiate creation component \"%s\".",
kit.getCreateComponent().getName()),
ex);
}
}
/**
* Return the currently selected folder. Creation components will place new
* items in this folder.
*
* @param state represents the current request
*
* @return the currently selected folder, in which new items should be
* placed.
*/
public final Folder getFolder(final PageState state) {
return (Folder) folderSelectionModel.getSelectedObject(state);
}
/**
* Return the currently selected content section. New items created by
* creation components will belong to this section. This is the content
* section to which the folder returned by {@link #getFolder getFolder}
* belongs.
*
* @param state represents the current request
*
* @return the currently selected content section.
*/
public final ContentSection getContentSection(final PageState state) {
final ContentSection section = getFolder(state).getSection();
return section;
}
/**
* Forward to the item editing UI. The creation component of an authoring
* kit may call this method to indicate that the creation process is
* complete.
*
* @param state the page state
* @param item the newly created item
*/
public void editItem(final PageState state, final ContentItem item) {
final ContentSection section = getContentSection(state);
final String nodeUrl = String.join("", URL.getDispatcherPath(),
section.getPrimaryUrl(),
"/");
final String target = ContentItemPage.getItemURL(
nodeUrl, item.getObjectId(), ContentItemPage.AUTHORING_TAB, true);
throw new RedirectSignal(target, true);
}
/**
* Cancel item editing and go back to where the user came from
*
* @param state the page state
*/
public void redirectBack(final PageState state) {
typeSelectionModel.clearSelection(state);
}
}

View File

@ -1,258 +0,0 @@
/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.authoring;
import com.arsdigita.bebop.ColumnPanel;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.MetaForm;
import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.SingleSelectionModel;
import com.arsdigita.bebop.form.FormErrorDisplay;
import com.arsdigita.bebop.parameters.BigDecimalParameter;
import com.arsdigita.cms.AuthoringKit;
import com.arsdigita.cms.ContentBundle;
import com.arsdigita.cms.ContentItem;
import com.arsdigita.cms.ContentSection;
import com.arsdigita.cms.ContentType;
import com.arsdigita.cms.Folder;
import com.arsdigita.cms.ItemSelectionModel;
import com.arsdigita.cms.ui.ContentItemPage;
import com.arsdigita.cms.ui.folder.FolderSelectionModel;
import com.arsdigita.domain.DataObjectNotFoundException;
import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.web.RedirectSignal;
import com.arsdigita.web.URL;
import org.apache.log4j.Logger;
import java.lang.reflect.Constructor;
import java.math.BigDecimal;
/**
* An invisible component which contains all the possible creation
* components. The components are loaded from the database at
* construction time. The selector uses a {@link SingleSelectionModel}
* in order to get the ID of the current content type.
*
* <strong>Important:</strong> This component is passed in the
* constructor to every authoring kit creation component (such as
* {@link PageCreate}). The creation component is supposed to follow
* the following pattern:
*
* <blockquote><pre>
* // The member variable m_parent points to the CreationSelector
* SomeContentItem item = somehowCreateTheItem(state);
* item.setParent(m_parent.getFolder(state));
* m_parent.editItem(state, item);
* </pre></blockquote>
*
* If the creation component wishes to cancel the creation process,
* it should call
*
* <blockquote><pre>m_parent.redirectBack(state);</pre></blockquote>
*
* The component may also call
*
* <blockquote><pre>m_parent.getContentSection(state);</pre></blockquote>
*
* in order to get the current content section.
*
* @version $Id: CreationSelector.java 2185 2011-06-20 21:16:02Z pboy $
*/
public class CreationSelector extends MetaForm {
private static Logger s_log = Logger.getLogger(CreationSelector.class);
private final FolderSelectionModel m_folderSel;
private final SingleSelectionModel m_typeSel;
private static Class[] s_args = new Class[] {
ItemSelectionModel.class,
CreationSelector.class
};
private Object[] m_vals;
private ItemSelectionModel m_itemSel;
private BigDecimalParameter m_itemId;
private ItemSelectionModel m_bundleSel;
private BigDecimalParameter m_bundleId;
public static final String ITEM_ID = "iid";
public static final String BUNDLE_ID = "bid";
/**
* Constructs a new <code>CreationSelector</code>. Load all the
* possible creation components from the database and stick them
* in the Map.
*
* @param typeModel the {@link SingleSelectionModel} which will
* supply a BigDecimal ID of the content type to instantiate
*
* @param folderModel the {@link FolderSelectionModel} containing
* the folder in which new items are to be created
*/
public CreationSelector(final SingleSelectionModel typeModel,
final FolderSelectionModel folderModel) {
super("pageCreate");
m_typeSel = typeModel;
m_folderSel = folderModel;
m_itemId = new BigDecimalParameter(ITEM_ID);
m_bundleId = new BigDecimalParameter(BUNDLE_ID);
m_bundleSel = new ItemSelectionModel(ContentBundle.class.getName(),
ContentBundle.BASE_DATA_OBJECT_TYPE, m_bundleId);
}
/**
*
* @param state
* @return
*/
@Override
public Form buildForm(PageState state) {
BigDecimal typeID = (BigDecimal)m_typeSel.getSelectedKey(state);
Component c = null;
Form returnForm = new Form("pageCreate");
FormErrorDisplay fed = new FormErrorDisplay(this);
fed.setStateParamsAreRegistered(false);
returnForm.add(fed , ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT);
if (typeID != null) {
try {
ContentType type = new ContentType(typeID);
AuthoringKit kit = type.getAuthoringKit();
if(kit != null) {
c = instantiateKitComponent(kit, type);
if(c != null) {
returnForm.add(c);
returnForm.setMethod(Form.POST);
returnForm.setEncType("multipart/form-data");
}
}
} catch (DataObjectNotFoundException e) {
// content type not found
}
}
return returnForm;
}
/**
* Add the item_id parameter.
*
* @param p
*/
@Override
public void register(Page p) {
super.register(p);
p.addComponentStateParam(this, m_itemId);
p.addComponentStateParam(this, m_bundleId);
}
/**
* Get the creation component.
*
* @param kit
* @param type
* @return
*/
protected Component instantiateKitComponent
(final AuthoringKit kit, final ContentType type) {
String creatorName = kit.getCreateComponent();
Object[] vals;
if(creatorName == null) {
return null;
}
try {
Class createClass = Class.forName(creatorName);
ItemSelectionModel itemModel = new ItemSelectionModel(type, m_itemId);
vals = new Object[]{itemModel, this};
Constructor constr = createClass.getConstructor(s_args);
Component c = (Component)constr.newInstance(vals);
return c;
} catch (Exception e) {
s_log.error("Instantiation failure", e);
throw new UncheckedWrapperException (
"Failed to instantiate creation component " +
kit.getCreateComponent() + ": " + e.getMessage(),
e);
}
}
/**
* Return the currently selected folder. Creation components will place
* new items in this folder.
*
* @param s represents the current request
* @return the currently selected folder, in which new items should be
* placed.
*/
public final Folder getFolder(PageState s) {
return (Folder) m_folderSel.getSelectedObject(s);
}
/**
* Return the currently selected content section. New items created by
* creation components will belong to this section. This is the content
* section to which the folder returned by {@link #getFolder getFolder}
* belongs.
*
* @param s represents the current request
* @return the currently selected content section.
*/
public final ContentSection getContentSection(PageState s) {
final ContentSection section = (ContentSection)
getFolder(s).getContentSection();
return section;
}
/**
* Forward to the item editing UI. The creation component of an authoring
* kit may call this method to indicate that the creation process is
* complete.
*
* @param s the page state
* @param item the newly created item
*/
public void editItem(PageState s, ContentItem item) {
ContentSection sec = getContentSection(s);
String nodeURL = URL.getDispatcherPath() + sec.getPath() + "/";
String target = ContentItemPage.getItemURL
(nodeURL, item.getID(), ContentItemPage.AUTHORING_TAB,true);
throw new RedirectSignal(target, true);
}
/**
* Cancel item editing and go back to where the user came from
*
* @param s the page state
*/
public void redirectBack(PageState state) {
m_typeSel.clearSelection(state);
}
}

View File

@ -0,0 +1,201 @@
/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.authoring;
import com.arsdigita.bebop.BoxPanel;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.event.PrintEvent;
import com.arsdigita.bebop.event.PrintListener;
import com.arsdigita.bebop.form.OptionGroup;
import com.arsdigita.bebop.form.SingleSelect;
import com.arsdigita.bebop.form.Submit;
import com.arsdigita.bebop.parameters.BigDecimalParameter;
import com.arsdigita.bebop.parameters.LongParameter;
import com.arsdigita.cms.ui.ItemSearch;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.xml.Element;
import java.math.BigDecimal;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.security.PermissionChecker;
import org.librecms.CmsConstants;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentType;
import org.librecms.contentsection.ContentTypeRepository;
import org.librecms.contentsection.privileges.TypePrivileges;
import java.util.List;
import java.util.TooManyListenersException;
import java.util.stream.Collectors;
/**
* A form element which displays a select box of all content types available
* under the given content section, and forwards to the item creation UI when
* the user selects a content type to instantiate.
*
* @author Stanislav Freidin (sfreidin@arsdigtia.com)
* @author <a href="jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public abstract class NewItemForm extends Form {
public static final String TYPE_ID = "tid";
private final SingleSelect typeSelect;
private final Submit submit;
private final Label emptyLabel;
private final Label createLabel;
public NewItemForm(final String name) {
this(name, BoxPanel.HORIZONTAL);
}
/**
* Construct a new NewItemForm. It sets a vertical BoxPanel as the component
* container.
*
* @param name the name attribute of the form.
* @param orientation
*/
public NewItemForm(final String name, final int orientation) {
super(name, new BoxPanel(BoxPanel.VERTICAL));
setIdAttr("new_item_form");
final BoxPanel panel = new BoxPanel(orientation);
panel.setWidth("2%");
panel.setBorder(0);
// create and add an "empty" component
emptyLabel = new Label(
new GlobalizedMessage("cms.ui.authoring.no_types_registered",
CmsConstants.CMS_BUNDLE),
false);
emptyLabel.setIdAttr("empty_label");
panel.add(emptyLabel);
createLabel = new Label(
new GlobalizedMessage("cms.ui.authoring.create_new",
CmsConstants.CMS_BUNDLE),
false);
createLabel.setIdAttr("create_label");
panel.add(createLabel);
typeSelect = new SingleSelect(new BigDecimalParameter(TYPE_ID),
OptionGroup.SortMode.ALPHABETICAL_ASCENDING);
try {
typeSelect.addPrintListener(new PrintListener() {
// Read the content section's content types and add them as options
@Override
public void prepare(final PrintEvent event) {
final OptionGroup optionGroup = (OptionGroup) event
.getTarget();
optionGroup.clearOptions();
final PageState state = event.getPageState();
// gather the content types of this section into a list
final ContentSection section = getContentSection(state);
final ContentType parentType;
final List<ContentType> typesCollection;
final Long singleTypeID = (Long) state.getValue(
new LongParameter(ItemSearch.SINGLE_TYPE_PARAM));
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final ContentTypeRepository typeRepo = cdiUtil.findBean(
ContentTypeRepository.class);
final PermissionChecker permissionChecker = cdiUtil
.findBean(PermissionChecker.class);
if (singleTypeID == null) {
parentType = null;
} else {
parentType = typeRepo.findById(singleTypeID);
}
typesCollection = section.getContentTypes().stream()
.filter(type -> permissionChecker.isPermitted(
TypePrivileges.USE_TYPE,
type))
.collect(Collectors.toList());
}
});
} catch (TooManyListenersException ex) {
throw new UncheckedWrapperException("Too many listeners.", ex);
}
panel.add(typeSelect);
submit = new Submit("new",
new GlobalizedMessage("cms.ui.authoring.go",
CmsConstants.CMS_BUNDLE));
panel.add(submit);
add(panel);
}
public abstract ContentSection getContentSection(PageState state);
/**
*
* @param state
*
* @return
*/
public Long getTypeID(final PageState state) {
return (Long) typeSelect.getValue(state);
}
/**
*
* @return
*/
public final SingleSelect getTypeSelect() {
return typeSelect;
}
/**
* Generate XML - show/hide labels/widgets
*
* @param state
* @param parent
*/
@Override
public void generateXML(final PageState state, final Element parent) {
if (isVisible(state)) {
final ContentSection section = getContentSection(state);
final List<ContentType> types = section.getContentTypes();
boolean isEmpty = types.isEmpty();
createLabel.setVisible(state, !isEmpty);
typeSelect.setVisible(state, !isEmpty);
submit.setVisible(state, !isEmpty);
emptyLabel.setVisible(state, isEmpty);
super.generateXML(state, parent);
}
}
}

View File

@ -1,247 +0,0 @@
/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.authoring;
import com.arsdigita.bebop.BoxPanel;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.event.PrintEvent;
import com.arsdigita.bebop.event.PrintListener;
import com.arsdigita.bebop.form.Option;
import com.arsdigita.bebop.form.OptionGroup;
import com.arsdigita.bebop.form.SingleSelect;
import com.arsdigita.bebop.form.Submit;
import com.arsdigita.bebop.parameters.BigDecimalParameter;
import com.arsdigita.cms.ui.ItemSearch;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.ui.admin.GlobalizationUtil;
import com.arsdigita.util.UncheckedWrapperException;
import com.arsdigita.xml.Element;
import java.math.BigDecimal;
import org.apache.log4j.Logger;
import org.libreccm.security.Party;
import org.librecms.CmsConstants;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentType;
import java.awt.image.Kernel;
import java.util.List;
/**
* A form element which displays a select box of all content types available
* under the given content section, and forwards to the item creation UI when
* the user selects a content type to instantiate.
*
* @author Stanislav Freidin (sfreidin@arsdigtia.com)
* @version $Revision: #12 $ $DateTime: 2004/08/17 23:15:09 $
* @version $Id: NewItemForm.java 2161 2011-02-02 00:16:13Z pboy $
*/
public abstract class NewItemForm extends Form {
/**
* Internal logger instance to faciliate debugging. Enable logging output by
* editing /WEB-INF/conf/log4j.properties int hte runtime environment and
* set com.arsdigita.cms.ui.authoring.NewItemForm=DEBUG by uncommenting or
* adding the line.
*/
private static final Logger s_log = Logger.getLogger(NewItemForm.class);
private final SingleSelect m_typeWidget;
private final Submit m_submit;
private final Label m_emptyLabel;
private final Label m_createLabel;
public static final String TYPE_ID = "tid";
public NewItemForm(String name) {
this(name, BoxPanel.HORIZONTAL);
}
/**
* Construct a new NewItemForm. It sets a vertical BoxPanel as the component
* container.
*
* @param name the name attribute of the form.
*/
public NewItemForm(String name, int orientation) {
super(name, new BoxPanel(BoxPanel.VERTICAL));
setIdAttr("new_item_form");
//BoxPanel panel = new BoxPanel(BoxPanel.HORIZONTAL);
BoxPanel panel = new BoxPanel(orientation);
panel.setWidth("2%");
panel.setBorder(0);
// create and add an "empty" component
m_emptyLabel = new Label(new GlobalizedMessage(
"cms.ui.authoring.no_types_registered", CmsConstants.CMS_BUNDLE),
false);
m_emptyLabel.setIdAttr("empty_label");
panel.add(m_emptyLabel);
m_createLabel = new Label(new GlobalizedMessage(
"cms.ui.authoring.create_new", CmsConstants.CMS_BUNDLE),
false);
m_createLabel.setIdAttr("create_label");
panel.add(m_createLabel);
m_typeWidget = new SingleSelect(new BigDecimalParameter(TYPE_ID),
OptionGroup.SortMode.ALPHABETICAL_ASCENDING);
try {
m_typeWidget.addPrintListener(new PrintListener() {
// Read the content section's content types and add them as options
@Override
public void prepare(PrintEvent e) {
OptionGroup o = (OptionGroup) e.getTarget();
o.clearOptions();
PageState state = e.getPageState();
// gather the content types of this section into a list
ContentSection section = getContentSection(state);
ContentType parentType = null;
List<ContentType> typesCollection = null;
BigDecimal singleTypeID = (BigDecimal) state.getValue(
new BigDecimalParameter(
ItemSearch.SINGLE_TYPE_PARAM));
if (singleTypeID != null) {
try {
parentType = new ContentType(singleTypeID);
} catch (DataObjectNotFoundException ex) {
parentType = null;
}
}
if (parentType == null) {
typesCollection = section.getCreatableContentTypes();
} else {
typesCollection = section.getDescendantsOfContentType(
parentType);
}
typesCollection.addOrder(ContentType.LABEL);
if (!typesCollection.isEmpty()) {
// Add content types
while (typesCollection.next()) {
boolean list = true;
ContentType type = typesCollection.getContentType();
if (PermissionService
.getDirectGrantedPermissions(type.getOID())
.size() > 0) {
// chris gilbert - allow restriction of some types
// to certain users/groups. No interface to do
// this, but group could be created and permission
// granted in a content type loader
//
// can't permission filter the collection because
// most types will have no permissions granted.
// This approach involves a small overhead getting
// the count of granted permissions for each type
// (mitigated by only checking DIRECT permissions)
Party party = Kernel.getContext().getParty();
if (party == null) {
party = Kernel.getPublicUser();
}
PermissionDescriptor create
= new PermissionDescriptor(
PrivilegeDescriptor
.get(SecurityManager.CMS_NEW_ITEM),
type,
party);
list = PermissionService.checkPermission(create);
}
if (list) {
// o.addOption(new Option(type.getID().toString(), type.getName()));
o.addOption(new Option(type.getID().toString(),
new Label(type.getLabel())));
}
}
typesCollection.reset();
}
}
});
} catch (java.util.TooManyListenersException e) {
throw new UncheckedWrapperException("Too many listeners: " + e
.getMessage(), e);
}
panel.add(m_typeWidget);
m_submit = new Submit("new", GlobalizationUtil.globalize(
"cms.ui.authoring.go"));
panel.add(m_submit);
add(panel);
}
public abstract ContentSection getContentSection(PageState state);
/**
*
* @param state
*
* @return
*/
public BigDecimal getTypeID(PageState state) {
return (BigDecimal) m_typeWidget.getValue(state);
}
/**
*
* @return
*/
public final SingleSelect getTypeSelect() {
return m_typeWidget;
}
/**
* Generate XML - show/hide labels/widgets
*
* @param state
* @param parent
*/
@Override
public void generateXML(PageState state, Element parent) {
if (isVisible(state)) {
ContentSection section = getContentSection(state);
ContentTypeCollection c = section.getCreatableContentTypes();
boolean isEmpty = c.isEmpty();
c.close();
m_createLabel.setVisible(state, !isEmpty);
m_typeWidget.setVisible(state, !isEmpty);
m_submit.setVisible(state, !isEmpty);
m_emptyLabel.setVisible(state, isEmpty);
super.generateXML(state, parent);
}
}
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (C) 2017 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package com.arsdigita.cms.ui.folder;
import com.arsdigita.bebop.List;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class FolderPath extends List {
public FolderPath(final FolderSelectionModel folderSelectionModel) {
super(new FolderPathListModelBuilder(folderSelectionModel));
setAttribute("type", "item-path");
setSelectionModel(folderSelectionModel);
}
}

View File

@ -0,0 +1,63 @@
/*
* Copyright (C) 2017 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package com.arsdigita.cms.ui.folder;
import com.arsdigita.bebop.list.ListModel;
import org.libreccm.cdi.utils.CdiUtil;
import org.librecms.contentsection.Folder;
import org.librecms.contentsection.FolderManager;
import java.util.Iterator;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
class FolderPathListModel implements ListModel {
private final Iterator<Folder> pathFolders;
private Folder currentFolder;
public FolderPathListModel(final Folder folder) {
pathFolders = CdiUtil.createCdiUtil().findBean(FolderManager.class)
.getParentFolders(folder).iterator();
}
@Override
public boolean next() {
if (pathFolders.hasNext()) {
currentFolder = pathFolders.next();
return true;
} else {
return false;
}
}
@Override
public Object getElement() {
return currentFolder.getName();
}
@Override
public String getKey() {
return Long.toString(currentFolder.getObjectId());
}
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (C) 2017 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package com.arsdigita.cms.ui.folder;
import com.arsdigita.bebop.List;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.list.ListModel;
import com.arsdigita.bebop.list.ListModelBuilder;
import com.arsdigita.util.LockableImpl;
import org.librecms.contentsection.Folder;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class FolderPathListModelBuilder extends LockableImpl
implements ListModelBuilder {
private final FolderSelectionModel folderSelectionModel;
public FolderPathListModelBuilder(
final FolderSelectionModel folderSelectionModel) {
this.folderSelectionModel = folderSelectionModel;
}
@Override
public ListModel makeModel(final List list, final PageState state) {
return new FolderPathListModel(folderSelectionModel
.getSelectedObject(state));
}
}

View File

@ -26,6 +26,7 @@ import org.apache.log4j.Logger;
import org.libreccm.categorization.Category; import org.libreccm.categorization.Category;
import org.libreccm.categorization.CategoryRepository; import org.libreccm.categorization.CategoryRepository;
import org.libreccm.cdi.utils.CdiUtil; import org.libreccm.cdi.utils.CdiUtil;
import org.librecms.contentsection.Folder;
public class FolderRequestLocal extends CcmObjectRequestLocal { public class FolderRequestLocal extends CcmObjectRequestLocal {
@ -55,8 +56,8 @@ public class FolderRequestLocal extends CcmObjectRequestLocal {
} }
} }
public final Category getFolder(final PageState state) { public final Folder getFolder(final PageState state) {
return (Category) get(state); return (Folder) get(state);
} }
} }

View File

@ -26,6 +26,7 @@ import com.arsdigita.ui.CcmObjectSelectionModel;
import org.apache.log4j.Category; import org.apache.log4j.Category;
import org.librecms.contentsection.ContentSection; import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.Folder;
/** /**
@ -34,15 +35,15 @@ import org.librecms.contentsection.ContentSection;
* com.arsdigita.cms.Folder}. * com.arsdigita.cms.Folder}.
* *
* @author <a href="mailto:lutter@arsdigita.com">David Lutterkort</a> * @author <a href="mailto:lutter@arsdigita.com">David Lutterkort</a>
* @version $Id$ * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */
public class FolderSelectionModel extends CcmObjectSelectionModel { public class FolderSelectionModel extends CcmObjectSelectionModel<Folder> {
public FolderSelectionModel(String name) { public FolderSelectionModel(String name) {
super(Category.class.getName(), name); super(Category.class.getName(), name);
} }
public FolderSelectionModel(final SingleSelectionModel model) { public FolderSelectionModel(final SingleSelectionModel<Long> model) {
super(Category.class.getName(), model); super(Category.class.getName(), model);
} }
@ -60,10 +61,11 @@ public class FolderSelectionModel extends CcmObjectSelectionModel {
/** /**
* Clear the selection by resetting it to the root folder id. * Clear the selection by resetting it to the root folder id.
* *
* @param s represents the curent request. * @param state represents the cuerent request.
*/ */
public void clearSelection(PageState s) { @Override
setSelectedKey(s, getRootFolderID(s)); public void clearSelection(final PageState state) {
setSelectedKey(state, getRootFolderID(state));
} }
/** /**
@ -72,13 +74,13 @@ public class FolderSelectionModel extends CcmObjectSelectionModel {
* is to be used outside a content section, this method has to be overriden * is to be used outside a content section, this method has to be overriden
* appropriately. * appropriately.
* *
* @param s represents the current request * @param state represents the current request
* @return the ID of the root folder * @return the ID of the root folder
* *
* @pre s != null * @pre s != null
* @post return != null * @post return != null
*/ */
protected Long getRootFolderID(PageState s) { protected Long getRootFolderID(final PageState state) {
ContentSection sec = CMS.getContext().getContentSection(); ContentSection sec = CMS.getContext().getContentSection();
return sec.getRootDocumentsFolder().getObjectId(); return sec.getRootDocumentsFolder().getObjectId();
} }
@ -86,8 +88,11 @@ public class FolderSelectionModel extends CcmObjectSelectionModel {
/** /**
* Return true, since this selection model will always have a folder * Return true, since this selection model will always have a folder
* selected in it * selected in it
* @param state
* @return
*/ */
public boolean isSelected(PageState s) { @Override
public boolean isSelected(final PageState state) {
return true; return true;
} }

View File

@ -19,70 +19,21 @@
package com.arsdigita.cms.ui.folder; package com.arsdigita.cms.ui.folder;
import com.arsdigita.bebop.List; import com.arsdigita.bebop.List;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.list.ListModel;
import com.arsdigita.bebop.list.ListModelBuilder;
import com.arsdigita.cms.ItemSelectionModel; import com.arsdigita.cms.ItemSelectionModel;
import com.arsdigita.util.LockableImpl;
import org.libreccm.categorization.Category;
import org.libreccm.cdi.utils.CdiUtil;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentItemManager;
import org.librecms.contentsection.Folder;
/** /**
* Produce a list of the items starting from the selected item's root down to * Produce a list of the items starting from the selected item's root down to
* the item itself. * the item itself.
* *
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
* @author <a href="mailto:lutter@arsdigita.com">David Lutterkort</a> * @author <a href="mailto:lutter@arsdigita.com">David Lutterkort</a>
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */
public class ItemPath extends List { public class ItemPath extends List {
public ItemPath(ItemSelectionModel folderSel) { public ItemPath(final ItemSelectionModel itemSelectionModel) {
super(new ItemPathListModelBuilder(folderSel)); super(new ItemPathListModelBuilder(itemSelectionModel));
setAttribute("type", "item-path"); setAttribute("type", "item-path");
setSelectionModel(folderSel); setSelectionModel(itemSelectionModel);
} }
public static class ItemPathListModel implements ListModel {
private final java.util.List<Folder> pathFolders;
private int index = -1;
public ItemPathListModel(final ContentItem item) {
pathFolders = CdiUtil.createCdiUtil().findBean(ContentItemManager.class).getItemFolders(item);
}
@Override
public boolean next() {
index++;
return index < pathFolders.size();
}
public Object getElement() {
return pathFolders.get(index).getName();
}
public String getKey() {
return Long.toString(pathFolders.get(index).getObjectId());
}
}
public static class ItemPathListModelBuilder extends LockableImpl
implements ListModelBuilder {
ItemSelectionModel m_itemSel;
public ItemPathListModelBuilder(ItemSelectionModel itemSel) {
m_itemSel = itemSel;
}
public com.arsdigita.bebop.list.ListModel makeModel(List l,
final PageState s) {
return new ItemPathListModel((ContentItem) m_itemSel.
getSelectedObject(s));
}
}
} }

View File

@ -0,0 +1,66 @@
/*
* Copyright (C) 2017 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package com.arsdigita.cms.ui.folder;
import com.arsdigita.bebop.list.ListModel;
import org.libreccm.cdi.utils.CdiUtil;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentItemManager;
import org.librecms.contentsection.Folder;
import java.util.Iterator;
/**
* Model for {@link ItemPath}. This was originally a inner class.
*
* @author <a href="mailto:lutter@arsdigita.com">David Lutterkort</a>
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
class ItemPathListModel implements ListModel {
private final Iterator<Folder> pathFolders;
private Folder currentFolder;
public ItemPathListModel(final ContentItem item) {
pathFolders = CdiUtil.createCdiUtil().findBean(
ContentItemManager.class).getItemFolders(item).iterator();
}
@Override
public boolean next() {
if (pathFolders.hasNext()) {
currentFolder = pathFolders.next();
return true;
} else {
return false;
}
}
@Override
public Object getElement() {
return currentFolder.getName();
}
@Override
public String getKey() {
return Long.toString(currentFolder.getObjectId());
}
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (C) 2017 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package com.arsdigita.cms.ui.folder;
import com.arsdigita.bebop.List;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.list.ListModelBuilder;
import com.arsdigita.cms.ItemSelectionModel;
import com.arsdigita.util.LockableImpl;
/**
* ModelBuilder for {@link ItemPath}. This was originally an inner class.
*
* @author <a href="mailto:lutter@arsdigita.com">David Lutterkort</a>
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
class ItemPathListModelBuilder extends LockableImpl implements ListModelBuilder {
private final ItemSelectionModel itemSelectionModel;
public ItemPathListModelBuilder(
final ItemSelectionModel itemSelectionModel) {
this.itemSelectionModel = itemSelectionModel;
}
@Override
public com.arsdigita.bebop.list.ListModel makeModel(
final List list, final PageState state) {
return new ItemPathListModel(itemSelectionModel.getSelectedObject(
state));
}
}

View File

@ -0,0 +1,167 @@
/*
* Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.permissions;
import com.arsdigita.globalization.GlobalizedMessage;
import org.librecms.contentsection.privileges.ItemPrivileges;
/**
* This interface is used to centralise constants and labels used in the
* Permissions UI package.
*
* @author Stefan Deusch (stefan@arsdigita.com)
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
class CMSPermissionsConstants {
private CMSPermissionsConstants() {
//Nothing
}
/**
* These are our five default privileges.
*/
public static final String[] DEFAULT_PRIVILEGES = new String[]{
ItemPrivileges.VIEW_PUBLISHED,
ItemPrivileges.EDIT,
ItemPrivileges.CREATE_NEW,
ItemPrivileges.DELETE,};
public static final String BUNDLE_NAME
= "com.arsdigita.ui.permissions.PermissionsResources";
public static final GlobalizedMessage SEARCH_LABEL = new GlobalizedMessage(
"permissions.userSearchForm.label", BUNDLE_NAME);
public static final GlobalizedMessage SEARCH_BUTTON = new GlobalizedMessage(
"permissions.button.search", BUNDLE_NAME);
public static final GlobalizedMessage SAVE_BUTTON = new GlobalizedMessage(
"permissions.button.save", BUNDLE_NAME);
public static final GlobalizedMessage NO_RESULTS = new GlobalizedMessage(
"permissions.userSearchForm.noResults", BUNDLE_NAME);
// Direct / Indirect permissions
public static final GlobalizedMessage PERM_TABLE_DIRECT_HEADING
= new GlobalizedMessage(
"permissions.directPermissions.heading", BUNDLE_NAME);
public static final GlobalizedMessage PERM_TABLE_DIRECT_EXPLANATION
= new GlobalizedMessage(
"permissions.directPermissions.explanation", BUNDLE_NAME);
public static final GlobalizedMessage PERM_TABLE_INDIRECT_HEADING
= new GlobalizedMessage(
"permissions.indirectPermissions.heading", BUNDLE_NAME);
public static final GlobalizedMessage PERM_TABLE_INDIRECT_EXPLANATION
= new GlobalizedMessage(
"permissions.indirectPermissions.explanation", BUNDLE_NAME);
public static final GlobalizedMessage PERM_TABLE_INDIRECT_CONTEXT
= new GlobalizedMessage(
"permissions.indirectPermissions.context", BUNDLE_NAME);
public static final GlobalizedMessage PERM_TABLE_GRANTEE
= new GlobalizedMessage(
"permissions.table.grantee", BUNDLE_NAME);
public static final GlobalizedMessage PERM_TABLE_ACTIONS
= new GlobalizedMessage(
"permissions.table.actions", BUNDLE_NAME);
public static final GlobalizedMessage REMOVE_ALL_CONFIRM
= new GlobalizedMessage(
"permissions.table.actions.removeAll", BUNDLE_NAME);
public static final GlobalizedMessage PERM_TABLE_INHERITED
= new GlobalizedMessage(
"permissions.table.inherited", BUNDLE_NAME);
public static final GlobalizedMessage PERM_TABLE_NO_PARENT_CONTEXT
= new GlobalizedMessage(
"permissions.table.parent.context.null", BUNDLE_NAME);
// Permissions header
public static final GlobalizedMessage PAGE_TITLE = new GlobalizedMessage(
"permissions.one.title", BUNDLE_NAME);
public static final GlobalizedMessage MAIN_SITE = new GlobalizedMessage(
"permissions.main.site", BUNDLE_NAME);
public static final GlobalizedMessage PERSONAL_SITE = new GlobalizedMessage(
"permissions.personal.site", BUNDLE_NAME);
public static final GlobalizedMessage PERMISSIONS_INDEX
= new GlobalizedMessage(
"permissions.index.title", BUNDLE_NAME);
public static final GlobalizedMessage PERMISSIONS_INDEX_NAVBAR
= new GlobalizedMessage(
"permissions.index.navbarItem", BUNDLE_NAME);
// Permissions grant form
public static final GlobalizedMessage PAGE_GRANT_TITLE
= new GlobalizedMessage(
"permissions.one.grant.title", BUNDLE_NAME);
public static final GlobalizedMessage PAGE_GRANT_LEFT
= new GlobalizedMessage(
"permissions.one.grant.explanation.left", BUNDLE_NAME);
public static final GlobalizedMessage PAGE_GRANT_RIGHT
= new GlobalizedMessage(
"permissions.one.grant.explanation.right", BUNDLE_NAME);
// Access denied page
public static final GlobalizedMessage PAGE_DENIED_TITLE
= new GlobalizedMessage(
"permissions.denied.title", BUNDLE_NAME);
// Index page
public static final GlobalizedMessage PAGE_OBJECT_INDEX
= new GlobalizedMessage(
"permissions.index.adminObjects", BUNDLE_NAME);
public static final GlobalizedMessage PAGE_OBJECT_PANEL_TITLE
= new GlobalizedMessage(
"permissions.index.panelTitle", BUNDLE_NAME);
public static final GlobalizedMessage PAGE_OBJECT_NONE
= new GlobalizedMessage(
"permissions.index.noAdminObjects", BUNDLE_NAME);
// Flats for permission types
public static final int DIRECT = 0;
public static final int INHERITED = 1;
// Form constants
public static final String OBJECT_ID = "po_id";
public static final String DIRECT_PERMISSIONS = "direct";
public static final String INDIRECT_PERMISSIONS = "indirect";
public static final String SEARCH_QUERY = "query";
public static final String PRIV_SET = "privs_set";
// shared query
public static final String RETRIEVE_USERS
= "com.arsdigita.kernel.RetrieveUsers";
}

View File

@ -0,0 +1,212 @@
/*
* Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.permissions;
import com.arsdigita.bebop.BoxPanel;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.FormData;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.SegmentedPanel;
import com.arsdigita.bebop.Text;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.event.FormSubmissionListener;
import com.arsdigita.bebop.event.PrintEvent;
import com.arsdigita.bebop.event.PrintListener;
import com.arsdigita.bebop.form.CheckboxGroup;
import com.arsdigita.bebop.form.Option;
import com.arsdigita.bebop.form.OptionGroup;
import com.arsdigita.bebop.form.Submit;
import com.arsdigita.bebop.parameters.ArrayParameter;
import com.arsdigita.bebop.parameters.StringParameter;
import com.arsdigita.util.StringUtils;
import com.arsdigita.util.UncheckedWrapperException;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.security.PermissionManager;
import org.libreccm.security.Role;
import org.libreccm.security.RoleRepository;
import java.util.List;
import java.util.TooManyListenersException;
import static com.arsdigita.cms.ui.permissions.CMSPermissionsConstants.*;
/**
* Permissions Grant container for permissions assignment. Widgets are currently
* organised on a bebop SegmentedPanel.
*
* @author Stefan Deusch (sdeusch@arsdigita.com)
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
class CMSPermissionsGrant {
private final static String PARTIES_CBG = "parties_cbg";
private final static String PRIVILEGES_CBG = "privs_cbg";
// data keys
private static final String USER_ID = "userID";
private static final String SCREEN_NAME = "screenName";
private static final String FIRST_NAME = "firstName";
private static final String LAST_NAME = "lastName";
private final CMSPermissionsPane parent;
private final SegmentedPanel grantPanel;
private CheckboxGroup partiesCheckboxGroup;
private CheckboxGroup privilegesCheckboxGroup;
private Form form;
private Submit saveSubmit;
/**
* Creates a PermissionsGrant object that will be contained with another
* component. This is currently used inside the permissions pane.
*
* @param parent the enclosing container
*/
public CMSPermissionsGrant(final CMSPermissionsPane parent) {
this.parent = parent;
makeForm();
grantPanel = new SegmentedPanel();
grantPanel.addSegment(new Label(PAGE_GRANT_TITLE), form);
}
/**
* Builds the form used to grant pivileges to users and groups.
*/
private void makeForm() {
form = new Form("GrantPrivileges", new BoxPanel());
form.setMethod(Form.POST);
form.addSubmissionListener(new GrantFormSubmissionListener());
form.add(new Label(PAGE_GRANT_LEFT));
partiesCheckboxGroup = new CheckboxGroup(PARTIES_CBG);
try {
partiesCheckboxGroup.addPrintListener(new UserSearchPrintListener());
} catch (TooManyListenersException e) {
throw new UncheckedWrapperException("TooManyListeners: " + e
.getMessage(), e);
}
form.add(partiesCheckboxGroup);
form.add(new Label(PAGE_GRANT_RIGHT));
privilegesCheckboxGroup = new CheckboxGroup(PRIVILEGES_CBG);
try {
privilegesCheckboxGroup.addPrintListener(
new PrivilegePrintListener());
} catch (TooManyListenersException e) {
throw new UncheckedWrapperException("TooManyListeners: " + e
.getMessage(), e);
}
form.add(privilegesCheckboxGroup);
saveSubmit = new Submit("save", SAVE_BUTTON);
form.add(saveSubmit);
}
/**
* Returns the SegmentedPanel with the permissions grant Form
*
* @return the SegmentedPanel with the permissions grant form
*/
public SegmentedPanel getPanel() {
return grantPanel;
}
private class GrantFormSubmissionListener
implements FormSubmissionListener {
@Override
public void submitted(FormSectionEvent event) throws
FormProcessException {
final PageState state = event.getPageState();
final FormData data = event.getFormData();
final String[] gids = (String[]) data.get(PARTIES_CBG);
final String[] privs = (String[]) data.get(PRIVILEGES_CBG);
if (privs != null && gids != null) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final PermissionManager permissionManager = cdiUtil.findBean(
PermissionManager.class);
final Long oID = parent.getObject(state).getObjectId();
for (String gid : gids) {
final Long gID = Long.parseLong(gid);
final CMSUserObjectStruct userObjectStruct
= new CMSUserObjectStruct(gID,
oID);
for (String priv : privs) {
permissionManager.grantPrivilege(
priv,
userObjectStruct.getRole(),
userObjectStruct.getObject());
}
}
}
parent.showAdmin(state);
}
}
private class UserSearchPrintListener implements PrintListener {
@Override
public void prepare(final PrintEvent event) {
final PageState state = event.getPageState();
final OptionGroup target = (OptionGroup) event.getTarget();
// get query string
final String search = StringUtils.stripWhiteSpace((String) state.
getValue(new StringParameter(SEARCH_QUERY)));
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final RoleRepository roleRepo = cdiUtil.findBean(
RoleRepository.class);
final List<Role> roles = roleRepo.searchByName(search);
roles.forEach(role -> target.addOption(new Option(
Long.toString(role.getRoleId()),
new Text(role.getName()))));
}
}
private class PrivilegePrintListener implements PrintListener {
@Override
public void prepare(final PrintEvent event) {
final PageState state = event.getPageState();
final OptionGroup target = (OptionGroup) event.getTarget();
// get privileges from page state
final Object[] privileges = (Object[]) state.getValue(
new ArrayParameter(
PRIV_SET));
// print ceckbox group with privileges
for (Object privilege : privileges) {
target.addOption(new Option((String) privilege,
new Text(parent.getPrivilegeName(
(String) privilege))));
}
}
}
}

View File

@ -0,0 +1,99 @@
/*
* Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.permissions;
import com.arsdigita.bebop.BoxPanel;
import com.arsdigita.bebop.DimensionalNavbar;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Link;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.event.PrintEvent;
import com.arsdigita.bebop.event.PrintListener;
import org.libreccm.core.CcmObject;
import static com.arsdigita.cms.ui.permissions.CMSPermissionsConstants.*;
/**
*
* Component that Renders the Header of the Permissions Admin pages
*
* @author sdeusch@arsdigita.com
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
class CMSPermissionsHeader extends BoxPanel {
private final CMSPermissionsPane parent;
private final Label title;
/**
* Constructor
*/
CMSPermissionsHeader(final CMSPermissionsPane parent) {
this.parent = parent;
title = new Label();
title.addPrintListener(new PrintListener() {
@Override
public void prepare(final PrintEvent event) {
final Label target = (Label) event.getTarget();
target.setLabel(PAGE_TITLE);
}
});
title.setClassAttr("heading");
add(title);
// Used to render the object name in the navbar
final Label objectName = new Label();
objectName.addPrintListener(new PrintListener() {
public void prepare(final PrintEvent event) {
final Label target = (Label) event.getTarget();
target.setLabel(getObjectName(event));
}
});
final DimensionalNavbar navbar = new DimensionalNavbar();
navbar.add(new Link(new Label(PERSONAL_SITE), "/pvt/home"));
navbar.add(new Link(new Label(MAIN_SITE), "/"));
navbar.add(new Link(new Label(PERMISSIONS_INDEX), "/permissions/"));
navbar.add(objectName);
navbar.setClassAttr("permNavBar");
add(navbar);
}
private String getObjectName(final PrintEvent event) {
final PageState state = event.getPageState();
final CcmObject object = parent.getObject(state);
final String objectName = String.format("%s (ID %d)",
object.getDisplayName(),
object.getObjectId());
return objectName;
}
/**
* Returns the object used to render the title of the panel.
*/
Label getTitle() {
return title;
}
}

View File

@ -0,0 +1,501 @@
/*
* Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.permissions;
import com.arsdigita.bebop.BoxPanel;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.RequestLocal;
import com.arsdigita.bebop.Resettable;
import com.arsdigita.bebop.SegmentedPanel;
import com.arsdigita.bebop.SimpleComponent;
import com.arsdigita.bebop.SimpleContainer;
import com.arsdigita.bebop.Text;
import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener;
import com.arsdigita.bebop.event.RequestEvent;
import com.arsdigita.bebop.event.RequestListener;
import com.arsdigita.bebop.parameters.ArrayParameter;
import com.arsdigita.bebop.parameters.ParameterModel;
import com.arsdigita.bebop.parameters.StringParameter;
import com.arsdigita.dispatcher.DispatcherHelper;
import com.arsdigita.ui.CcmObjectSelectionModel;
import com.arsdigita.util.UncheckedWrapperException;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.core.CcmObject;
import org.libreccm.security.PermissionChecker;
import org.libreccm.security.Role;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.Folder;
import org.librecms.contentsection.privileges.ItemPrivileges;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* A pane used to administer the permissions of one {@link
* ACSObject}. This is a reusable component that can be embedded into a page to
* provide a generic UI. The page must have the "?po_id=" parameter to supply to
* ACSObject id of the item one is managing permissions for.
*
* @author sdeusch@arsdigita.com
* @authro <a href="jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class CMSPermissionsPane extends SimpleContainer
implements Resettable,
ActionListener,
RequestListener {
// non-shared parameter models; leave package scope for access from its members.
private ParameterModel searchString = new StringParameter(
CMSPermissionsConstants.SEARCH_QUERY);
private ParameterModel privilegeArray = new ArrayParameter(
CMSPermissionsConstants.PRIV_SET);
private String[] privileges;
private Map<String, String> privilegeNameMap;
private CMSPermissionsTables allPermissions;
private CMSPermissionsHeader PermissionsHeader;
private SimpleContainer directPermissions;
private Form roleSearchForm;
private SimpleContainer inheritedPermissions;
private SimpleComponent contextPanel;
private SimpleContainer permissionsGrantPanel;
private SimpleContainer noResultsPanel;
private ObjectAdminListing adminListing;
private CcmObjectSelectionModel<CcmObject> selectionModel;
private RequestLocal userObjectInfo;
/**
* Default constructor creates components that show the default privileges
* as defined in PermissionsConstants interface
*
* @param model
*/
public CMSPermissionsPane(final CcmObjectSelectionModel<CcmObject> model) {
this(CMSPermissionsConstants.DEFAULT_PRIVILEGES, new HashMap<>(), model);
privilegeNameMap.put("read", "Read");
privilegeNameMap.put("write", "Write");
privilegeNameMap.put("create", "Create");
privilegeNameMap.put("delete", "Delete");
privilegeNameMap.put("admin", "Admin");
}
/**
* Creates a PermissionsPane with components showing the privileges that are
* passed in as argument.
*
* @param privileges
* @param privilegeNameMap
* @param selectionModel
*/
public CMSPermissionsPane(
final String[] privileges,
final Map<String, String> privilegeNameMap,
final CcmObjectSelectionModel<CcmObject> selectionModel) {
userObjectInfo = new RequestLocal() {
@Override
protected Object initialValue(final PageState state) {
return new CMSUserObjectStruct(state, selectionModel);
}
};
this.privileges = privileges;
this.selectionModel = selectionModel;
this.privilegeNameMap = privilegeNameMap;
}
/**
* Overwrite this method to construct your default Permissions Pane with the
* components you need. You can subclass anonymously overwriting just the
* register method. Note: the getXXX methods are lazy instantiators, i.e.
* they produce the components only if not already there. (You can even
* overwrite the getXXX components with your own implementation, e.g., if
* you want to show a List instead of a Table for the direct permissions,
* but still use a Table for the inherited permissions.
*
* @param page
*/
@Override
public void register(final Page page) {
super.register(page);
// add permissions components to this specific implementation
// add(getPermissionsHeader());
add(getContextPanel());
add(getDirectPermissionsPanel());
add(getUserSearchForm());
add(getInheritedPermissionsPanel());
add(getPermissionGrantPanel());
add(getNoSearchResultPanel());
add(getAdminListingPanel());
// set initial visibility of components
// p.setVisibleDefault(getPermissionsHeader(), true);
page.setVisibleDefault(getDirectPermissionsPanel(), true);
page.setVisibleDefault(getUserSearchForm(), true);
page.setVisibleDefault(getInheritedPermissionsPanel(), true);
page.setVisibleDefault(getContextPanel(), true);
page.setVisibleDefault(getPermissionGrantPanel(), false);
page.setVisibleDefault(getNoSearchResultPanel(), false);
page.setVisibleDefault(getAdminListingPanel(), false);
// p.addActionListener(this);
// p.addRequestListener(this);
// add state parameters
page.addGlobalStateParam(searchString);
page.addGlobalStateParam(privilegeArray);
}
/**
* Implementation of interface bebop.Resettable. Use {@code reset} to reset
* permissions component to initial state, e.g. if you embed it into another
* container.
*/
@Override
public void reset(final PageState state) {
showAdmin(state);
}
/**
* Utility method to get the authenticated user or group
*
* @param state
*
* @return
*/
public Role getRequestingRole(final PageState state) {
return ((CMSUserObjectStruct) userObjectInfo.get(state)).getRole();
}
/**
* Utility method to get the ACSObject from the page state
*
* @param state
*
* @return
*/
public CcmObject getObject(final PageState state) {
return ((CMSUserObjectStruct) userObjectInfo.get(state)).getObject();
}
/**
* Returns the title "Permissions on object articles", e.g.
*
* @return
*/
public Label getTitle() {
return ((CMSPermissionsHeader) getPermissionsHeader()).getTitle();
}
/**
* Returns a string array of privilege names as defined in the constructor
*
* @return
*/
public String[] getPrivileges() {
return Arrays.copyOf(privileges, privileges.length);
}
/**
* Produces the direct and inherited permission tables to the privileges
* defined in the constructor.
*
* @see #getDirectPermissionsPanel(), getInheritedPermissionsPanel()
*/
private CMSPermissionsTables getPermissionsTables() {
if (allPermissions == null) {
allPermissions = new CMSPermissionsTables(privileges, this);
}
return allPermissions;
}
/**
* Returns the bebop component with a table for the direct permission on the
* privileges defined in the constructor
*
* @return
*
* @see #getInheritedPermissionsPanel()
*/
public SimpleContainer getDirectPermissionsPanel() {
directPermissions = getPermissionsTables().getPermissions(
CMSPermissionsConstants.DIRECT);
return directPermissions;
}
/**
* Returns the bebop component with a table for the inherited permission on
* the privileges defined in the constructor. The table is non-editable.
*
* @return
*
* @see #getDirectPermissionsPanel()
*/
public SimpleContainer getInheritedPermissionsPanel() {
inheritedPermissions = getPermissionsTables()
.getPermissions(CMSPermissionsConstants.INHERITED);
return inheritedPermissions;
}
public SimpleContainer getAdminListingPanel() {
if (adminListing == null) {
adminListing = new ObjectAdminListing(selectionModel);
}
return adminListing;
}
/**
* This is an outstanding item.
*
* @return
*/
public SegmentedPanel getUniversalPermissionsPanel() {
throw new UnsupportedOperationException();
}
/**
* Returns a bebop form for user and group search.
*
* @return
*/
public Form getUserSearchForm() {
if (roleSearchForm == null) {
roleSearchForm = new CMSUserSearchForm(this);
}
return roleSearchForm;
}
/**
* Returns a panel with a form with 2 checkbox groups, one for parties to
* choose, one for privileges to assign.
*
* @return
*/
public SimpleContainer getPermissionGrantPanel() {
if (permissionsGrantPanel == null) {
CMSPermissionsGrant permGrant = new CMSPermissionsGrant(this);
permissionsGrantPanel = permGrant.getPanel();
}
return permissionsGrantPanel;
}
/**
* Returns a bebop container with the title to this object and a navigation
* bar, specific for the UI at /permissions/.
*
* @return
*/
public SimpleContainer getPermissionsHeader() {
if (PermissionsHeader == null) {
PermissionsHeader = new CMSPermissionsHeader(this);
}
return PermissionsHeader;
}
/**
* Returns a bebop panel indicating that the user search yielded no results.
* It is customised in the xsl stylesheet.
*
* @return
*/
public SimpleContainer getNoSearchResultPanel() {
if (noResultsPanel == null) {
final Label errorMsg = new Label(CMSPermissionsConstants.NO_RESULTS);
errorMsg.setClassAttr("errorBullet");
final BoxPanel panel = new BoxPanel();
panel.add(errorMsg);
panel.add(new CMSUserSearchForm(this));
noResultsPanel = new SegmentedPanel().addSegment(new Text(" "),
panel);
}
return noResultsPanel;
}
/**
* Returns a bebop panel with a link to the permissions administration page
* of the object's direct ancestor (parent).
*
* @return
*/
public SimpleComponent getContextPanel() {
if (contextPanel == null) {
contextPanel = getPermissionsTables().makeContextPanel();
}
return contextPanel;
}
ParameterModel getSearchString() {
return searchString;
}
ParameterModel getPrivilegeParam() {
return privilegeArray;
}
CcmObjectSelectionModel<CcmObject> getSelectionModel() {
return selectionModel;
}
/**
* Shows panel with no results to user search.
*
* @param state
*/
public void showNoResults(final PageState state) {
getDirectPermissionsPanel().setVisible(state, false);
getInheritedPermissionsPanel().setVisible(state, false);
getContextPanel().setVisible(state, false);
getUserSearchForm().setVisible(state, false);
getPermissionGrantPanel().setVisible(state, false);
getNoSearchResultPanel().setVisible(state, true);
}
/**
* Show the Grant privileges panel
*
* @param state
*/
public void showGrant(final PageState state) {
getDirectPermissionsPanel().setVisible(state, false);
getInheritedPermissionsPanel().setVisible(state, false);
getContextPanel().setVisible(state, false);
getUserSearchForm().setVisible(state, false);
getNoSearchResultPanel().setVisible(state, false);
getPermissionGrantPanel().setVisible(state, true);
}
/**
* Shows the administration page of permissions to one object.
*
* @param state
*/
public void showAdmin(final PageState state) {
final CcmObject object = getObject(state);
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final PermissionChecker permissionChecker = cdiUtil.findBean(
PermissionChecker.class);
final boolean canAccess;
if (object == null) {
throw new UncheckedWrapperException(
"Unexpected null value for object.");
} else if (object instanceof ContentItem) {
canAccess = permissionChecker.isPermitted(ItemPrivileges.ADMINISTER,
object);
} else if (object instanceof Folder) {
canAccess = permissionChecker.isPermitted(ItemPrivileges.ADMINISTER,
object);
} else {
throw new UncheckedWrapperException(String.format(
"The object is of type \"%s\" which is not supported here.",
object.getClass().getName()));
}
if (canAccess) {
showCustom(state, true);
// showCustom(state, false);
getContextPanel().setVisible(state, true);
} else {
// do not have permission to set permissions, so don't show them
getDirectPermissionsPanel().setVisible(state, false);
getInheritedPermissionsPanel().setVisible(state, false);
getUserSearchForm().setVisible(state, false);
getContextPanel().setVisible(state, false);
}
getPermissionGrantPanel().setVisible(state, false);
}
@Override
public void actionPerformed(final ActionEvent event) {
final PageState state = event.getPageState();
/**
* check if viewing user has admin privilege on this Object, after
* Action Event fires everytime the component is visible.
*
*/
if (this.isVisible(state)) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final PermissionChecker permissionChecker = cdiUtil.findBean(
PermissionChecker.class);
if (!permissionChecker.isPermitted(ItemPrivileges.ADMINISTER,
getObject(state))) {
try {
DispatcherHelper.sendRedirect(state.getRequest(),
state.getResponse(),
"/permissions/denied");
} catch (IOException ex) {
throw new UncheckedWrapperException(ex);
}
}
}
}
public void showCustom(final PageState state, final boolean custom) {
if (custom) {
getDirectPermissionsPanel().setVisible(state, true);
getInheritedPermissionsPanel().setVisible(state, false);
getUserSearchForm().setVisible(state, true);
getAdminListingPanel().setVisible(state, true);
} else {
getDirectPermissionsPanel().setVisible(state, false);
getInheritedPermissionsPanel().setVisible(state, true);
getUserSearchForm().setVisible(state, false);
getAdminListingPanel().setVisible(state, false);
}
}
public String getPrivilegeName(final String privilege) {
return privilegeNameMap.get(privilege);
}
@Override
public void pageRequested(final RequestEvent event) {
// PageState s = e.getPageState();
// ACSObject object = getObject(s);
// if (object != null) {
// DataObject context = PermissionService.getContext(object);
// if (context != null) {
// showCustom(s, false);
// } else {
// showCustom(s, true);
// }
// } else {
// throw new IllegalStateException( (String) GlobalizationUtil.globalize("cms.ui.permissions.current_object_is_null").localize());
// }
}
}

View File

@ -0,0 +1,652 @@
/*
* Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.permissions;
import com.arsdigita.bebop.ActionLink;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.ControlLink;
import com.arsdigita.bebop.GridPanel;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.SimpleComponent;
import com.arsdigita.bebop.SimpleContainer;
import com.arsdigita.bebop.Table;
import com.arsdigita.bebop.event.PrintEvent;
import com.arsdigita.bebop.event.PrintListener;
import com.arsdigita.bebop.event.TableActionEvent;
import com.arsdigita.bebop.event.TableActionListener;
import com.arsdigita.bebop.table.TableCellRenderer;
import com.arsdigita.bebop.table.TableModel;
import com.arsdigita.bebop.table.TableModelBuilder;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.util.LockableImpl;
import com.arsdigita.util.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.core.CcmObject;
import org.libreccm.security.Permission;
import org.libreccm.security.PermissionManager;
import org.libreccm.security.Role;
import org.librecms.CmsConstants;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import static com.arsdigita.cms.ui.permissions.CMSPermissionsConstants.*;
/**
* Class to represent direct and inherited permissions of an CcmObject. This
* class provides two SegmentPanels with the direct and the inherited
* permissions tables, respectively. The expected pageState contains a variable
* "id=123" of which the permissions are rendered. The viewing user must be
* authenticated. The permissions representations can be swapped , e.g. with a
* List, if scalability warrants.
*
* @author Stefan Deusch
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
class CMSPermissionsTables {
private static Logger LOGGER = LogManager.getLogger(
CMSPermissionsTables.class);
private CMSPermissionsPane parent;
private String[] privileges;
private final GridPanel permissionsPanel[] = new GridPanel[2];
private final int[] tableColumns = new int[2];
/**
* Default constructor uses the DEFAULT_PRIVILEGES as defined in
* PermissionsConstants.
*/
CMSPermissionsTables(final CMSPermissionsPane parent) {
this(DEFAULT_PRIVILEGES, parent);
}
/**
* Constructor that takes an array of PrivilegeDescriptors and builds the
* grantee - privilege matrix. <strong>The permissions tables contain the
* set of privileges that are passed into this constructor.</strong>
*
* @param privileges the array of PrivilegeDesrciptors with which go into
* table
* @param parent the Bebop parent container
*/
CMSPermissionsTables(final String[] privileges,
final CMSPermissionsPane parent) {
this.parent = parent;
// fixed table information
this.privileges = privileges;
tableColumns[DIRECT] = privileges.length + 2;
tableColumns[INHERITED] = privileges.length + 1;
// Construct Direct Permissions Panel
permissionsPanel[DIRECT] = new GridPanel(1);
final Table directTable = new Table(
new PermissionsTableModelBuilder(DIRECT),
getHeaders(DIRECT));
directTable.setClassAttr("dataTable");
setCellRenderers(directTable, DIRECT);
directTable.addTableActionListener(
new DirectPermissionsTableActionListener());
permissionsPanel[DIRECT].add(new Label(new GlobalizedMessage(
"cms.ui.permissions.these_are_the_custom_permissions"
+ "_that_have_been_granted_on_this_object",
CmsConstants.CMS_BUNDLE)));
permissionsPanel[DIRECT].add(directTable);
// Construct Inherited Permissions Panel
permissionsPanel[INHERITED] = new GridPanel(1);
final Table inheritedTable = new Table(
new PermissionsTableModelBuilder(INHERITED),
getHeaders(INHERITED));
inheritedTable.setClassAttr("dataTable");
setCellRenderers(inheritedTable, INHERITED);
permissionsPanel[INHERITED].add(new Label(new GlobalizedMessage(
"cms.ui.permissions.these_are_the_current_permissions_for_this_folder",
CmsConstants.CMS_BUNDLE)));
permissionsPanel[INHERITED].add(inheritedTable);
//m_permPanel[INHERITED].addSegment(new Label(PERM_TABLE_INDIRECT_HEADING),
// boxpanel);
}
/**
* Returns the SegmentedPanel with either the direct or the indirect
* permissions table.
*
* @param use PermissionsContants.DIRECT or PermissionsContants.INHERITED
*/
GridPanel getPermissions(int type) {
return permissionsPanel[type];
}
/**
* Returns the set of privileges of the permission tables as a String array.
*/
String[] getPrivileges() {
return Arrays.copyOf(privileges, privileges.length);
}
SimpleComponent makeContextPanel() {
final SimpleContainer contextPanel = new SimpleContainer();
final Label contextLabel1 = new Label();
contextLabel1.addPrintListener(new PrintListener() {
@Override
public void prepare(final PrintEvent event) {
final PageState state = event.getPageState();
final Label label = (Label) event.getTarget();
final CcmObject context = getContext(state);
if (context != null) {
label.setLabel(PERM_TABLE_INDIRECT_CONTEXT);
contextLabel1.setVisible(state, true);
} else {
label.setLabel(PERM_TABLE_NO_PARENT_CONTEXT);
contextLabel1.setVisible(state, false);
}
}
});
final Label contextLabel2 = new Label();
contextLabel2.addPrintListener(new PrintListener() {
@Override
public void prepare(final PrintEvent event) {
final PageState state = event.getPageState();
final Label label = (Label) event.getTarget();
final CcmObject context = getContext(state);
if (context != null) {
label.setLabel(context.getDisplayName());
}
}
});
contextLabel2.setFontWeight(Label.BOLD);
contextPanel.add(contextLabel1);
contextPanel.add(contextLabel2);
return contextPanel;
}
CcmObject getContext(final PageState state) {
return null;
}
private String[] getHeaders(final int type) {
String[] headers = new String[tableColumns[type]];
headers[0] = PERM_TABLE_GRANTEE.localize() + "";
for (int j = 0; j < privileges.length; j++) {
headers[j + 1] = parent.getPrivilegeName(privileges[j]);
}
if (type == DIRECT) {
headers[privileges.length + 1] = PERM_TABLE_ACTIONS.localize()
+ "";
}
return headers;
}
private void setCellRenderers(final Table table, final int type) {
int j;
if (type == DIRECT) {
for (j = 1; j < table.getColumnModel().size() - 1; j++) {
table.getColumn(j).setCellRenderer(
new PermissionToggleRenderer());
}
table.getColumn(j).setCellRenderer(new LinkRenderer());
} else {
for (j = 1; j < table.getColumnModel().size(); j++) {
table.getColumn(j).setCellRenderer(
new PermissionStatusRenderer());
}
}
}
private class DirectPermissionsTableActionListener
implements TableActionListener {
@Override
public void cellSelected(TableActionEvent event) {
final PageState state = event.getPageState();
final int col = event.getColumn();
final String rowkey = (String) event.getRowKey();
if (rowkey == null) {
return;
}
final Table table = (Table) event.getSource();
final int no_cols = table.getColumnModel().size();
final int lastCol = no_cols - 1;
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final PermissionManager permissionManager = cdiUtil.findBean(
PermissionManager.class);
if (col > 0 && col < lastCol) {
final PermissionStatus pmds = UserPrivilegeKey
.undescribe(rowkey);
LOGGER.debug("Do perm toggle on {} for {} of {}",
pmds.getObject().getObjectId(),
pmds.getRole().getName(),
pmds.getPrivilege());
if (pmds.isGranted()) {
LOGGER.debug("Do revoke permission");
permissionManager.revokePrivilege(pmds.getPrivilege(),
pmds.getRole(),
pmds.getObject());
} else {
LOGGER.debug("Do grant permission");
permissionManager.grantPrivilege(pmds.getPrivilege(),
pmds.getRole(),
pmds.getObject());
}
} else if (col == lastCol) {
// Process Remove All Link
final String[] tokens = StringUtils.split(rowkey, '.');
final Long pID = Long.parseLong(tokens[0]);
/*
* Remove all indicated privileges from user
* enumerated in tokens array
*/
final CcmObject obj = parent.getObject(state);
final Role role = CMSUserObjectStruct.loadRole(pID);
LOGGER.debug("Revoke all on {} for {}.",
obj.getObjectId(),
role.getName());
for (final String token : tokens) {
permissionManager.revokePrivilege(token, role, obj);
}
}
}
@Override
public void headSelected(final TableActionEvent event) {
throw new UnsupportedOperationException();
}
}
private final class PermissionsTableModelBuilder
extends LockableImpl implements TableModelBuilder {
private final int m_type;
PermissionsTableModelBuilder(final int type) {
m_type = type;
}
/*
* this can be optimized to run the query only
* once for both tables
*/
@Override
public TableModel makeModel(final Table table,
final PageState state) {
final CcmObject object = parent.getObject(state);
final List<Permission> permissions = object.getPermissions();
switch (m_type) {
case DIRECT:
return new DirectPermissionsTableModel(permissions,
object);
case INHERITED:
return new DirectPermissionsTableModel(permissions,
object);
default:
return null;
}
}
}
private class DirectPermissionsTableModel implements TableModel {
private final List<String> userPrivileges = new ArrayList<>();
private final Iterator<Permission> iterator;
private Permission currentPermission;
public DirectPermissionsTableModel(final List<Permission> permissions,
final CcmObject object) {
this.iterator = permissions.iterator();
}
@Override
public int getColumnCount() {
return tableColumns[DIRECT];
}
@Override
public Object getElementAt(final int columnIndex) {
if (columnIndex == 0) {
// the Grantee column
return currentPermission.getGrantee().getName();
} else if (columnIndex == getColumnCount() - 1) {
// the Action column
return "Remove All";
} else {
if (userHasPermission(columnIndex - 1)) {
return Boolean.TRUE;
} else {
return Boolean.FALSE;
}
}
}
@Override
public Object getKeyAt(final int columnIndex) {
if (columnIndex == 0) {
// the key for the grantee
return currentPermission.getGrantee().getRoleId();
} else if (columnIndex == getColumnCount() - 1) {
// key for 'Remove All' link
return makeRemoveAllKey();
} else {
// key for a user privilege
return (new UserPrivilegeKey(
currentPermission.getObject().getObjectId(),
currentPermission.getGrantee().getRoleId(),
privileges[columnIndex - 1],
userHasPermission(columnIndex - 1)))
.toString();
}
}
@Override
public boolean nextRow() {
if (iterator.hasNext()) {
currentPermission = iterator.next();
return true;
} else {
return false;
}
}
boolean userHasPermission(final int idx) {
return userPrivileges.contains(privileges[idx]);
}
private String makeRemoveAllKey() {
final StringBuffer buffer = new StringBuffer();
buffer.append(Long.toString(currentPermission.getGrantee()
.getRoleId()));
for (int i = 0; i < privileges.length; i++) {
if (userHasPermission(i)) {
buffer.append(".").append(privileges[i]);
}
}
return buffer.toString();
}
void addPrivilege(final String privilege) {
for (String current : privileges) {
if (current.equals(current)) {
userPrivileges.add(current);
break;
}
}
}
protected Permission getCurrentPermission() {
return currentPermission;
}
}
/**
* Extension of DirectPermissionsTableModel to accomodate Inherited
* permissions table model.
*/
private final class InheritedPermissionsTableModel
extends DirectPermissionsTableModel {
public InheritedPermissionsTableModel(final List<Permission> permissions,
final CcmObject object) {
super(permissions, object);
}
@Override
public int getColumnCount() {
return tableColumns[INHERITED];
}
@Override
public Object getElementAt(final int columnIndex) {
if (columnIndex == 0) {
// the Grantee column
return getCurrentPermission().getGrantee().getName();
} else {
if (userHasPermission(columnIndex - 1)) {
return Boolean.TRUE;
} else {
return Boolean.FALSE;
}
}
}
@Override
public Object getKeyAt(final int columnIndex) {
if (columnIndex == 0) {
// the key for the grantee
return getCurrentPermission().getGrantee().getRoleId();
}
// no keys for inherited permissions
return null;
}
}
private final class PermissionToggleRenderer implements TableCellRenderer {
@Override
public Component getComponent(final Table table,
final PageState state,
final Object value,
final boolean isSelected,
final Object key,
final int row,
final int column) {
final ControlLink link = new ControlLink("");
if (((Boolean) value)) {
link.setClassAttr("checkBoxChecked");
} else {
link.setClassAttr("checkBoxUnchecked");
}
return link;
}
}
private final class PermissionStatusRenderer implements TableCellRenderer {
@Override
public Component getComponent(final Table table,
final PageState state,
final Object value,
final boolean isSelected,
final Object key,
final int row,
final int column) {
final Label link = new Label();
if (((Boolean) value)) {
link.setClassAttr("checkBoxGreyChecked");
} else {
link.setClassAttr("checkBoxGreyUnchecked");
}
return link;
}
}
private final class LinkRenderer implements TableCellRenderer {
@Override
public Component getComponent(final Table table,
final PageState state,
final Object value,
final boolean isSelected,
final Object key,
final int row,
final int column) {
final ControlLink link = new ControlLink((String) value);
link.setConfirmation(REMOVE_ALL_CONFIRM);
return link;
}
}
}
/**
* Utility class to encode a user privilege in the bebop table
*/
final class UserPrivilegeKey {
private final String objectId;
private final String granteeId;
private final String privilege;
private final boolean granted;
public UserPrivilegeKey(final Long objectId,
final Long granteeId,
final String privilege,
final boolean granted) {
this.objectId = objectId.toString();
this.granteeId = granteeId.toString();
this.privilege = privilege;
this.granted = granted;
}
@Override
public String toString() {
return String.format("%s{ %s }",
super.toString(),
String.join(".", privilege,
objectId,
granteeId,
Boolean.toString(granted)));
}
/**
* Decodes the information in a key into the helper class
*
* @see PermissionStatus
*/
static PermissionStatus undescribe(final String key) {
final int i = key.indexOf(".");
final int j = key.indexOf(".", i + 1);
final int k = key.lastIndexOf(".");
final String privilege = key.substring(0, i);
final Long oID = Long.parseLong(key.substring(i + 1, j));
final Long gID = Long.parseLong(key.substring(j + 1, k));
boolean granted = false;
final CMSUserObjectStruct uos;
try {
granted = Boolean.parseBoolean(key.substring(k + 1, k + 2));
uos = new CMSUserObjectStruct(gID, oID);
} catch (NumberFormatException ex) {
// cannot decode
throw new IllegalArgumentException(ex.getMessage());
}
return new PermissionStatus(privilege,
uos.getObject(),
uos.getRole(),
granted);
}
}
/**
* Structure to hold a permission and its current grant state
*/
final class PermissionStatus {
private final boolean granted;
private final CcmObject object;
private final Role role;
private final String privilege;
PermissionStatus(final String privilege,
final CcmObject object,
final Role role,
final boolean granted) {
this.granted = granted;
this.object = object;
this.role = role;
this.privilege = privilege;
}
boolean isGranted() {
return granted;
}
CcmObject getObject() {
return object;
}
Role getRole() {
return role;
}
String getPrivilege() {
return privilege;
}
}

View File

@ -0,0 +1,112 @@
/*
* Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.permissions;
import com.arsdigita.bebop.PageState;
import com.arsdigita.ui.CcmObjectSelectionModel;
import com.arsdigita.util.UncheckedWrapperException;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.core.CcmObject;
import org.libreccm.core.CcmObjectRepository;
import org.libreccm.security.Role;
import org.libreccm.security.RoleRepository;
/**
* This class is mainly instantiated from a PageState It is very context
* specific for permissions. It tries to read the object_id and load the
* corresponding ACSObject, as well as the party_id and the corresponding
* entity.
*
* @author Stefan Deusch (sdeusch@arsdigita.com)
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
class CMSUserObjectStruct {
private final Role role;
private final CcmObject object;
CMSUserObjectStruct(final PageState state,
final CcmObjectSelectionModel selectionModel) {
this(getRole(state), getObject(state, selectionModel));
}
CMSUserObjectStruct(final Long partyId,
final Long objectId) {
this(loadRole(partyId), loadObject(objectId));
}
CMSUserObjectStruct(final Role role, final CcmObject object) {
this.role = role;
this.object = object;
}
Role getRole() {
return role;
}
CcmObject getObject() {
return object;
}
// Utility factory methods
static CcmObject loadObject(final Long objectId) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final CcmObjectRepository objectRepo = cdiUtil.findBean(
CcmObjectRepository.class);
final CcmObject ccmObject = objectRepo.findById(objectId);
if (ccmObject == null) {
throw new UncheckedWrapperException(String.format(
"Failed to find object with ID %d.", objectId));
}
return ccmObject;
}
// use in package
static Role loadRole(final Long roleId) {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final RoleRepository roleRepo = cdiUtil
.findBean(RoleRepository.class);
final Role role = roleRepo.findById(roleId);
if (role == null) {
throw new UncheckedWrapperException(String.format(
"Failed to find party with ID %d.", roleId));
}
return role;
}
public static Role getRole(final PageState state) {
// final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
// final Shiro shiro = cdiUtil.findBean(Shiro.class);
//
// return shiro.getUser();
return null;
}
public static CcmObject getObject(
final PageState state, final CcmObjectSelectionModel selectionModel) {
return selectionModel.getSelectedObject(state);
}
}

View File

@ -0,0 +1,136 @@
/*
* Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.permissions;
import com.arsdigita.bebop.ColumnPanel;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.FormData;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.SimpleContainer;
import com.arsdigita.bebop.event.FormProcessListener;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.form.Submit;
import com.arsdigita.bebop.form.TextField;
import com.arsdigita.bebop.parameters.NotEmptyValidationListener;
import com.arsdigita.bebop.parameters.ParameterModel;
import com.arsdigita.bebop.parameters.StringParameter;
import com.arsdigita.util.StringUtils;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.security.Party;
import org.libreccm.security.Role;
import org.libreccm.security.RoleRepository;
import java.util.List;
import static com.arsdigita.cms.ui.permissions.CMSPermissionsConstants.*;
/**
* User Search Form for permissions.
*
* @author Stefan Deusch (stefan@arsdigita.com)
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class CMSUserSearchForm extends Form implements FormProcessListener {
private CMSPermissionsPane parent;
private TextField searchField;
public CMSUserSearchForm(CMSPermissionsPane parent) {
this(DEFAULT_PRIVILEGES, parent);
}
public CMSUserSearchForm(final String[] privileges,
final CMSPermissionsPane parent) {
super("RoleSearchUsers", new SimpleContainer());
this.parent = parent;
setMethod(Form.POST);
addProcessListener(this);
add(new Label(SEARCH_LABEL));
add(new Label("&nbsp;", false));
final StringParameter searchParam = new StringParameter(SEARCH_QUERY);
searchField = new TextField(searchParam);
searchField.addValidationListener(new NotEmptyValidationListener());
searchField.setSize(20);
add(searchField, ColumnPanel.RIGHT);
final Submit submit = new Submit(SEARCH_BUTTON);
add(submit, ColumnPanel.LEFT);
}
@Override
public void process(final FormSectionEvent event) throws
FormProcessException {
final PageState state = event.getPageState();
final FormData data = event.getFormData();
final String search = StringUtils.stripWhiteSpace((String) data.get(
SEARCH_QUERY));
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final RoleRepository roleRepo = cdiUtil.findBean(RoleRepository.class);
final List<Role> roles = roleRepo.searchByName(search);
if (roles.isEmpty()) {
parent.showNoResults(state);
} else {
// put search string into Page
state.setValue(getSearchString(), data.get(SEARCH_QUERY));
// put privileges into Page
state.setValue(getPrivilegeModel(), getPrivileges());
parent.showGrant(state);
}
}
/**
* Hide Delegate pattern, if parent's implementation changes.
*/
private ParameterModel getSearchString() {
return parent.getSearchString();
}
/**
* Detto
*/
private ParameterModel getPrivilegeModel() {
return parent.getPrivilegeParam();
}
/**
* Detto
*/
private Object[] getPrivileges() {
return parent.getPrivileges();
}
public TextField getSearchWidget() {
return searchField;
}
}

View File

@ -0,0 +1,286 @@
/*
* Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.permissions;
import com.arsdigita.bebop.ColumnPanel;
import com.arsdigita.bebop.Form;
import com.arsdigita.bebop.FormData;
import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.RequestLocal;
import com.arsdigita.bebop.SimpleContainer;
import com.arsdigita.bebop.Text;
import com.arsdigita.bebop.event.FormProcessListener;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.event.PrintEvent;
import com.arsdigita.bebop.event.PrintListener;
import com.arsdigita.bebop.form.CheckboxGroup;
import com.arsdigita.bebop.form.Hidden;
import com.arsdigita.bebop.form.Option;
import com.arsdigita.bebop.form.OptionGroup;
import com.arsdigita.bebop.form.Submit;
import com.arsdigita.bebop.form.TextField;
import com.arsdigita.bebop.form.Widget;
import com.arsdigita.bebop.parameters.NotNullValidationListener;
import com.arsdigita.cms.ui.CMSContainer;
import com.arsdigita.cms.ui.CMSForm;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.ui.CcmObjectSelectionModel;
import org.libreccm.core.CcmObject;
import org.libreccm.security.User;
import com.arsdigita.util.Assert;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.security.PermissionChecker;
import org.libreccm.security.PermissionManager;
import org.libreccm.security.Role;
import org.libreccm.security.RoleRepository;
import org.libreccm.security.UserRepository;
import org.librecms.CmsConstants;
import org.librecms.contentsection.privileges.ItemPrivileges;
import java.util.List;
import java.util.TooManyListenersException;
/**
* <p>
* This component is a form for adding object administrators
*
* @author Michael Pih (pihman@arsdigita.com)
* @author Uday Mathur (umathur@arsdigita.com)
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class ObjectAddAdmin extends SimpleContainer
implements FormProcessListener {
private final static String SEARCH_QUERY = "searchQuery";
private final static String USERS = "roles";
private final static String SUBMIT = "addSubmit";
private final static String CANCEL = "addCancel";
private Widget searchWidget;
private final RequestLocal queryRequestLocal;
private String labelText;
private String m_submitText;
private final CMSContainer noMatchesContainer;
private final CMSContainer matchesContainer;
private final Form form;
private Hidden searchQuery;
private CheckboxGroup rolesCheckboxGroup;
private Submit submit;
private Submit cancel;
private final CcmObjectSelectionModel<CcmObject> objectSelectionModel;
public ObjectAddAdmin(
final CcmObjectSelectionModel<CcmObject> objectSelectionModel,
final TextField search) {
// super(search, "ObjectAddAdmin");
labelText = "Check the box next to the name of the person(s) to assign.";
m_submitText = "Add Members";
searchWidget = search;
queryRequestLocal = new RequestLocal() {
@Override
protected Object initialValue(final PageState state) {
return makeQuery(state);
}
};
this.objectSelectionModel = objectSelectionModel;
form = makeForm("ObjectAddAdmin");
final Label title = new Label(new GlobalizedMessage("cms.ui.matches",
CmsConstants.CMS_BUNDLE));
title.setFontWeight(Label.BOLD);
final Label label = new Label(new GlobalizedMessage(
"cms.ui.there_was_no_one_matching_the_search_criteria",
CmsConstants.CMS_BUNDLE));
label.setFontWeight("em");
noMatchesContainer = new CMSContainer();
noMatchesContainer.add(title);
noMatchesContainer.add(label);
add(noMatchesContainer);
matchesContainer = new CMSContainer();
matchesContainer.add(title);
matchesContainer.add(form);
add(matchesContainer);
}
/**
* Build the form used to add roles.
*
* @param name
*
* @return The form
*/
protected Form makeForm(final String name) {
final CMSForm form = new CMSForm(name) {
public final boolean isCancelled(final PageState state) {
return cancel.isSelected(state);
}
};
// This hidden field will store the search query. A hidden widget is
// used instead of a request local variable because the search query
// should only be updated when the search form is submitted.
searchQuery = new Hidden(SEARCH_QUERY);
form.add(searchQuery, ColumnPanel.FULL_WIDTH);
final Text label = new Text(labelText);
form.add(label, ColumnPanel.FULL_WIDTH);
// Add the list of roles that can be added.
rolesCheckboxGroup = new CheckboxGroup(USERS);
rolesCheckboxGroup
.addValidationListener(new NotNullValidationListener());
try {
rolesCheckboxGroup.addPrintListener(new PrintListener() {
@Override
public void prepare(PrintEvent event) {
final CheckboxGroup target = (CheckboxGroup) event
.getTarget();
final PageState state = event.getPageState();
// Ensures that the init listener gets fired before the
// print listeners.
addRoles(state, target);
}
});
} catch (TooManyListenersException ex) {
throw new RuntimeException(ex);
}
form.add(rolesCheckboxGroup, ColumnPanel.FULL_WIDTH);
// Submit and Cancel buttons.
final SimpleContainer container = new SimpleContainer();
submit = new Submit(SUBMIT, m_submitText);
container.add(submit);
cancel = new Submit(CANCEL, "Cancel");
container.add(cancel);
form.add(container, ColumnPanel.FULL_WIDTH | ColumnPanel.CENTER);
form.addProcessListener(this);
return form;
}
/**
* Fetches the form for adding users.
*
* @return The "add user" form
*/
public Form getForm() {
return form;
}
/**
* Fetches the widget that contains the search string.
*
* @return The widget that contains the search string
*/
protected Widget getSearchWidget() {
return searchQuery;
}
/**
* Adds roles to the option group.
*
* @param state The page state
* @param target The option group
*
* @pre ( state != null && target != null )
*/
protected void addRoles(final PageState state, final OptionGroup target) {
@SuppressWarnings("unchecked")
final List<Role> roles = (List<Role>) queryRequestLocal.get(state);
roles.forEach(role -> target.addOption(
new Option(Long.toString(role.getRoleId()), role.getName())));
}
protected List<User> makeQuery(final PageState state) {
Assert.isTrue(objectSelectionModel.isSelected(state));
final CcmObject object = (CcmObject) objectSelectionModel
.getSelectedObject(state);
final String searchQuery = (String) getSearchWidget().getValue(state);
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final UserRepository userRepo = cdiUtil.findBean(UserRepository.class);
return userRepo.filtered(searchQuery);
}
@Override
public void process(final FormSectionEvent event) throws
FormProcessException {
final FormData data = event.getFormData();
final PageState state = event.getPageState();
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final PermissionChecker permissionChecker = cdiUtil.findBean(
PermissionChecker.class);
final PermissionManager permissionManager = cdiUtil.findBean(
PermissionManager.class);
final RoleRepository roleRepo = cdiUtil.findBean(RoleRepository.class);
final CcmObject object = objectSelectionModel.getSelectedObject(state);
permissionChecker.checkPermission(ItemPrivileges.ADMINISTER, object);
final String[] roleIds = (String[]) data.get("roles");
if (roleIds != null) {
// Add each checked user to the object
for (final String roleId : roleIds) {
final Role role = roleRepo.findById(Long.parseLong(roleId));
if (role == null) {
throw new FormProcessException(new GlobalizedMessage(
"cms.ui.permissions.cannot_add_user",
CmsConstants.CMS_BUNDLE));
}
permissionManager.grantPrivilege(ItemPrivileges.ADMINISTER,
role,
object);
}
} else {
throw new FormProcessException(new GlobalizedMessage(
"cms.ui.permissions.no_roles_were_selected",
CmsConstants.CMS_BUNDLE));
}
fireCompletionEvent(state);
}
}

View File

@ -0,0 +1,118 @@
/*
* Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.permissions;
import com.arsdigita.bebop.ActionLink;
import com.arsdigita.bebop.FormData;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.SimpleContainer;
import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener;
import com.arsdigita.cms.ui.UserSearchForm;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.ui.CcmObjectSelectionModel;
import com.arsdigita.xml.Element;
import org.libreccm.core.CcmObject;
import org.librecms.CmsConstants;
/**
* <p>
* This panel allows a staff administrator to search for users and add them to a
* staff role for the content section.</p>
*
* @author Michael Pih (pihman@arsdigita.com)
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class ObjectAddSearchAdmin extends SimpleContainer {
private final CcmObjectSelectionModel<CcmObject> objectSelectionModel;
private final UserSearchForm searchForm;
private final ObjectAddAdmin addPanel;
private final ActionLink returnLink;
public ObjectAddSearchAdmin(
final CcmObjectSelectionModel<CcmObject> objectSelectionModel) {
super();
this.objectSelectionModel = objectSelectionModel;
searchForm = new UserSearchForm("ObjectAdminSearch");
add(searchForm);
addPanel = getObjectAddAdmin(objectSelectionModel, searchForm);
add(addPanel);
addPanel.addCompletionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent event) {
fireCompletionEvent(event.getPageState());
}
});
returnLink = new ActionLink(new GlobalizedMessage(
"cms.ui.permissions.return_to_object_info", CmsConstants.CMS_BUNDLE));
returnLink.setClassAttr("actionLink");
returnLink.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent event) {
fireCompletionEvent(event.getPageState());
}
});
add(returnLink);
}
/**
* Displays the appropriate form(s).
*
* @param parent
*/
@Override
public void generateXML(final PageState state, final Element parent) {
final FormData data = searchForm.getFormData(state);
final FormData data2 = addPanel.getForm().getFormData(state);
if (data != null && (data.isSubmission() || data2.isSubmission())) {
addPanel.setVisible(state, true);
} else {
addPanel.setVisible(state, false);
}
super.generateXML(state, parent);
}
/**
* This returns the form for adding object administrators
*
* @param model
* @param searchForm
* @return
*/
protected ObjectAddAdmin getObjectAddAdmin(
final CcmObjectSelectionModel<CcmObject> model,
final UserSearchForm searchForm) {
return new ObjectAddAdmin(model, searchForm.getSearchWidget());
}
}

View File

@ -0,0 +1,259 @@
/*
* Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.cms.ui.permissions;
import com.arsdigita.bebop.ActionLink;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.ControlLink;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.SimpleContainer;
import com.arsdigita.bebop.Table;
import com.arsdigita.bebop.Text;
import com.arsdigita.bebop.event.ActionEvent;
import com.arsdigita.bebop.event.ActionListener;
import com.arsdigita.bebop.event.TableActionEvent;
import com.arsdigita.bebop.event.TableActionListener;
import com.arsdigita.bebop.table.TableCellRenderer;
import com.arsdigita.bebop.table.TableModel;
import com.arsdigita.bebop.table.TableModelBuilder;
import com.arsdigita.cms.CMS;
import com.arsdigita.cms.dispatcher.Utilities;
import com.arsdigita.dispatcher.AccessDeniedException;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.ui.CcmObjectSelectionModel;
import com.arsdigita.util.LockableImpl;
import com.arsdigita.util.UncheckedWrapperException;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.core.CcmObject;
import org.libreccm.security.Party;
import org.libreccm.security.PermissionChecker;
import org.libreccm.security.PermissionManager;
import org.libreccm.security.Role;
import org.libreccm.security.RoleRepository;
import org.librecms.CmsConstants;
import org.librecms.contentsection.privileges.ItemPrivileges;
import java.math.BigDecimal;
import java.util.Iterator;
import java.util.List;
import java.util.stream.Collectors;
public class ObjectAdminListing extends SimpleContainer {
private final Table adminTable;
private ActionLink addUserLink;
private final CcmObjectSelectionModel<CcmObject> objectSelectionModel;
private ObjectAddSearchAdmin objectAddSearchAdmin;
public ObjectAdminListing(
final CcmObjectSelectionModel<CcmObject> objectSelectionModel) {
super("cms:roleAdmin", CMS.CMS_XML_NS);
this.objectSelectionModel = objectSelectionModel;
adminTable = new Table(getTableModelBuilder(objectSelectionModel),
new String[]{"Member", "Action"});
adminTable.setDefaultCellRenderer(new ObjectAdminTableRenderer());
adminTable.setEmptyView(new Label(
"There are no administrators for this object"));
adminTable.setClassAttr("dataTable");
adminTable.addTableActionListener(new ObjectAdminActionListener());
addUserLink = new ActionLink(new GlobalizedMessage(
"cms.ui.permissions.add_administrator", CmsConstants.CMS_BUNDLE));
addUserLink.setClassAttr("actionLink");
objectAddSearchAdmin = getObjectAddSearchAdmin(objectSelectionModel);
addUserLink.addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent event) {
objectAddSearchAdmin.setVisible(event.getPageState(), true);
addUserLink.setVisible(event.getPageState(), false);
}
});
objectAddSearchAdmin.addCompletionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent event) {
objectAddSearchAdmin.setVisible(event.getPageState(), false);
addUserLink.setVisible(event.getPageState(), true);
}
});
add(adminTable);
add(addUserLink);
add(objectAddSearchAdmin);
}
@Override
public void register(final Page page) {
super.register(page);
page.setVisibleDefault(objectAddSearchAdmin, false);
}
// This returns the add search admin form to use for this object
protected ObjectAddSearchAdmin getObjectAddSearchAdmin(
CcmObjectSelectionModel<CcmObject> model) {
return new ObjectAddSearchAdmin(model);
}
private class ObjectAdminActionListener implements TableActionListener {
@Override
public void cellSelected(final TableActionEvent event) {
if (event.getColumn() == 1) {
final PageState state = event.getPageState();
final CcmObject object = objectSelectionModel.getSelectedObject(
state);
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final PermissionChecker permissionChecker = cdiUtil.findBean(
PermissionChecker.class);
final PermissionManager permissionManager = cdiUtil.findBean(
PermissionManager.class);
final RoleRepository roleRepo = cdiUtil.findBean(
RoleRepository.class);
permissionChecker.checkPermission(
ItemPrivileges.ADMINISTER, object);
final String roleId = (String) event.getRowKey();
final Role role = roleRepo.findById(Long.parseLong(roleId));
if (role == null) {
throw new UncheckedWrapperException(String.format(
"No role with id %s found.", roleId));
}
permissionManager.revokePrivilege(ItemPrivileges.ADMINISTER,
role,
object);
}
}
@Override
public void headSelected(final TableActionEvent event) {
}
}
protected TableModelBuilder getTableModelBuilder(
final CcmObjectSelectionModel<CcmObject> model) {
return new ObjectTableModelBuilder(model);
}
private class ObjectTableModelBuilder extends LockableImpl
implements TableModelBuilder {
private final CcmObjectSelectionModel<CcmObject> model;
ObjectTableModelBuilder(final CcmObjectSelectionModel<CcmObject> model) {
this.model = model;
}
@Override
public TableModel makeModel(final Table table, final PageState state) {
final CcmObject object = model.getSelectedObject(state);
final List<Role> roles = object.getPermissions().stream()
.filter(permission -> ItemPrivileges.ADMINISTER.equals(
permission.getGrantedPrivilege()))
.map(permission -> permission.getGrantee())
.collect(Collectors.toList());
return new ObjectAdminTableModel(roles);
}
}
private class ObjectAdminTableModel implements TableModel {
private final Iterator<Role> roles;
private Role currentRole;
public ObjectAdminTableModel(final List<Role> roles) {
this.roles = roles.iterator();
}
@Override
public int getColumnCount() {
return 2;
}
@Override
public boolean nextRow() {
if (roles.hasNext()) {
currentRole = roles.next();
return true;
} else {
return false;
}
}
@Override
public Object getElementAt(final int column) {
return currentRole;
}
@Override
public Object getKeyAt(final int column) {
return currentRole.getRoleId();
}
}
private class ObjectAdminTableRenderer implements TableCellRenderer {
@Override
public Component getComponent(final Table list,
final PageState state,
final Object value,
final boolean isSelected,
final Object key,
final int row,
final int column) {
final Role role = (Role) value;
switch (column) {
case 0:
return new Text(role.getName());
case 1:
return new ControlLink(new Text("remove"));
default:
throw new IllegalArgumentException("Column index " + column
+ " out of bounds 0..1");
}
}
}
}

View File

@ -169,6 +169,7 @@ public class ContentSectionSetup extends AbstractCcmApplicationSetup {
grantPermissions(manager, grantPermissions(manager,
rootFolder, rootFolder,
ItemPrivileges.ADMINISTER,
ItemPrivileges.CATEGORIZE, ItemPrivileges.CATEGORIZE,
ItemPrivileges.CREATE_NEW, ItemPrivileges.CREATE_NEW,
ItemPrivileges.EDIT, ItemPrivileges.EDIT,

View File

@ -20,6 +20,7 @@ package org.librecms.contentsection;
import com.arsdigita.kernel.KernelConfig; import com.arsdigita.kernel.KernelConfig;
import org.libreccm.categorization.Categorization;
import org.libreccm.categorization.CategoryManager; import org.libreccm.categorization.CategoryManager;
import org.libreccm.configuration.ConfigurationManager; import org.libreccm.configuration.ConfigurationManager;
@ -111,7 +112,7 @@ public class FolderManager {
* and the content section to which the folder belongs are the same as for * and the content section to which the folder belongs are the same as for
* the provided parent folder. * the provided parent folder.
* *
* @param name The name of the new folder. * @param name The name of the new folder.
* @param parent The folder in which the new folder is generated. * @param parent The folder in which the new folder is generated.
* *
* @return The new folder. * @return The new folder.
@ -120,16 +121,16 @@ public class FolderManager {
public Folder createFolder(final String name, final Folder parent) { public Folder createFolder(final String name, final Folder parent) {
if (parent == null) { if (parent == null) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Can't create a folder without a parent folder."); "Can't create a folder without a parent folder.");
} }
if (name == null || name.trim().isEmpty()) { if (name == null || name.trim().isEmpty()) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Can't create a folder with an empty name"); "Can't create a folder with an empty name");
} }
final KernelConfig kernelConfig = confManager.findConfiguration( final KernelConfig kernelConfig = confManager.findConfiguration(
KernelConfig.class); KernelConfig.class);
final Folder folder = new Folder(); final Folder folder = new Folder();
folder.setName(name); folder.setName(name);
@ -147,7 +148,7 @@ public class FolderManager {
public FolderIsDeletable folderIsDeletable(final Folder folder) { public FolderIsDeletable folderIsDeletable(final Folder folder) {
if (folder == null) { if (folder == null) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Can't check if null is deletable."); "Can't check if null is deletable.");
} }
if (!folder.getSubCategories().isEmpty()) { if (!folder.getSubCategories().isEmpty()) {
@ -183,20 +184,20 @@ public class FolderManager {
break; break;
case HAS_SUBCATEGORIES: case HAS_SUBCATEGORIES:
throw new IllegalArgumentException(String.format( throw new IllegalArgumentException(String.format(
"Can't delete folder \"%s\" because the folder is not empty", "Can't delete folder \"%s\" because the folder is not empty",
getFolderPath(folder, true))); getFolderPath(folder, true)));
case IS_NOT_EMPTY: case IS_NOT_EMPTY:
throw new IllegalArgumentException(String.format( throw new IllegalArgumentException(String.format(
"Can't delete folder \"%s\" because the folder is not empty.", "Can't delete folder \"%s\" because the folder is not empty.",
getFolderPath(folder))); getFolderPath(folder)));
case IS_ROOT_FOLDER: case IS_ROOT_FOLDER:
throw new IllegalArgumentException( throw new IllegalArgumentException(
"The folder to delete is a root folder can can't be deleted."); "The folder to delete is a root folder can can't be deleted.");
default: default:
throw new IllegalArgumentException(String.format( throw new IllegalArgumentException(String.format(
"Unexpected return value from #folderIsDeletable: " "Unexpected return value from #folderIsDeletable: "
+ "\"%s\".", + "\"%s\".",
status.toString())); status.toString()));
} }
} }
@ -213,13 +214,13 @@ public class FolderManager {
public void moveFolder(final Folder folder, final Folder target) { public void moveFolder(final Folder folder, final Folder target) {
if (folder if (folder
== null) { == null) {
throw new IllegalArgumentException("Can't move folder null"); throw new IllegalArgumentException("Can't move folder null");
} }
if (target == null) { if (target == null) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Can't move a folder to folder null"); "Can't move a folder to folder null");
} }
final FolderIsMovable status = folderIsMovable(folder, target); final FolderIsMovable status = folderIsMovable(folder, target);
@ -228,18 +229,18 @@ public class FolderManager {
final Folder source = folder.getParentFolder(); final Folder source = folder.getParentFolder();
categoryManager.removeSubCategoryFromCategory(folder, source); categoryManager.removeSubCategoryFromCategory(folder, source);
final boolean sameName = target.getSubCategories() final boolean sameName = target.getSubCategories()
.stream() .stream()
.anyMatch(subCategory -> folder.getName().equals( .anyMatch(subCategory -> folder.getName().equals(
subCategory subCategory
.getName())); .getName()));
if (sameName) { if (sameName) {
final String name = String.format("%s_1", folder.getName()); final String name = String.format("%s_1", folder.getName());
folder.setName(name); folder.setName(name);
folder.setDisplayName(name); folder.setDisplayName(name);
final KernelConfig kernelConfig = confManager. final KernelConfig kernelConfig = confManager.
findConfiguration( findConfiguration(
KernelConfig.class); KernelConfig.class);
folder.getTitle().addValue(kernelConfig.getDefaultLocale(), folder.getTitle().addValue(kernelConfig.getDefaultLocale(),
name); name);
} }
@ -248,36 +249,36 @@ public class FolderManager {
} }
case IS_ROOT_FOLDER: case IS_ROOT_FOLDER:
throw new IllegalArgumentException(String.format( throw new IllegalArgumentException(String.format(
"The folder \"%s\" to move is a root folder can can't " "The folder \"%s\" to move is a root folder can can't "
+ "be moved.", + "be moved.",
getFolderPath(folder))); getFolderPath(folder)));
case SAME_FOLDER: case SAME_FOLDER:
throw new IllegalArgumentException( throw new IllegalArgumentException(
"The folder to move and the target folder are the same " "The folder to move and the target folder are the same "
+ "folder."); + "folder.");
case DIFFERENT_SECTIONS: case DIFFERENT_SECTIONS:
throw new IllegalArgumentException(String.format( throw new IllegalArgumentException(String.format(
"Folders can't be moved between content section. The " "Folders can't be moved between content section. The "
+ "folder \"%s\" to move belongs to section " + "folder \"%s\" to move belongs to section "
+ "\"%s\", the target folder \"%s\" belongs to " + "\"%s\", the target folder \"%s\" belongs to "
+ "section \"%s\".", + "section \"%s\".",
getFolderPath(folder), getFolderPath(folder),
folder.getSection().getDisplayName(), folder.getSection().getDisplayName(),
getFolderPath(target), getFolderPath(target),
target.getSection().getDisplayName())); target.getSection().getDisplayName()));
case DIFFERENT_TYPES: case DIFFERENT_TYPES:
throw new IllegalArgumentException( throw new IllegalArgumentException(
"The folder to move is a \"%s\"," "The folder to move is a \"%s\","
+ "but the target folder is a \"%s\" folder."); + "but the target folder is a \"%s\" folder.");
case HAS_LIVE_ITEMS: case HAS_LIVE_ITEMS:
throw new IllegalArgumentException(String.format( throw new IllegalArgumentException(String.format(
"Can't move folder \"%s\" because some items in the " "Can't move folder \"%s\" because some items in the "
+ "folder or its sub folder are live.", + "folder or its sub folder are live.",
getFolderPath(folder, true))); getFolderPath(folder, true)));
default: default:
throw new IllegalArgumentException(String.format( throw new IllegalArgumentException(String.format(
"Unexpected return value from #folderIsMovable: %s", "Unexpected return value from #folderIsMovable: %s",
status.toString())); status.toString()));
} }
// if (folder.getParentFolder() // if (folder.getParentFolder()
@ -345,7 +346,7 @@ public class FolderManager {
if (target == null) { if (target == null) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Can't check if a server can be moved to null."); "Can't check if a server can be moved to null.");
} }
if (folder.getParentFolder() == null) { if (folder.getParentFolder() == null) {
@ -378,19 +379,19 @@ public class FolderManager {
* @param folder The folder to check for live items. * @param folder The folder to check for live items.
* *
* @return {@code true} if there any live items in the folder or its sub * @return {@code true} if there any live items in the folder or its sub
* folders, {@code false} if not. * folders, {@code false} if not.
*/ */
private boolean liveItemsInFolder(final Folder folder) { private boolean liveItemsInFolder(final Folder folder) {
final boolean liveItemsInFolder = folder.getObjects() final boolean liveItemsInFolder = folder.getObjects()
.stream() .stream()
.map(categorization -> categorization.getCategorizedObject()) .map(categorization -> categorization.getCategorizedObject())
.filter(object -> object instanceof ContentItem) .filter(object -> object instanceof ContentItem)
.map(object -> (ContentItem) object) .map(object -> (ContentItem) object)
.anyMatch(item -> itemManager.isLive(item)); .anyMatch(item -> itemManager.isLive(item));
final boolean liveItemsInSubFolders = folder.getSubFolders() final boolean liveItemsInSubFolders = folder.getSubFolders()
.stream() .stream()
.anyMatch(subFolder -> liveItemsInFolder(subFolder)); .anyMatch(subFolder -> liveItemsInFolder(subFolder));
return liveItemsInFolder || liveItemsInSubFolders; return liveItemsInFolder || liveItemsInSubFolders;
} }
@ -401,7 +402,7 @@ public class FolderManager {
* @param folder The folder. * @param folder The folder.
* *
* @return The path of the folder as a UNIX-like path, but without the * @return The path of the folder as a UNIX-like path, but without the
* content section as prefix. * content section as prefix.
*/ */
public String getFolderPath(final Folder folder) { public String getFolderPath(final Folder folder) {
return getFolderPath(folder, false); return getFolderPath(folder, false);
@ -410,12 +411,12 @@ public class FolderManager {
/** /**
* Returns the path of folder. * Returns the path of folder.
* *
* @param folder The folder. * @param folder The folder.
* @param withContentSection Whether to include the content section in the * @param withContentSection Whether to include the content section in the
* path. * path.
* *
* @return The path of the folder as a UNIX-like path, optionally with the * @return The path of the folder as a UNIX-like path, optionally with the
* content section the folder belongs to as prefix.. * content section the folder belongs to as prefix..
*/ */
public String getFolderPath(final Folder folder, public String getFolderPath(final Folder folder,
final boolean withContentSection) { final boolean withContentSection) {
@ -443,4 +444,31 @@ public class FolderManager {
} }
} }
/**
* Creates list with a parent folders of the provided folder.
*
* @param folder The folder.
*
* @return
*/
public List<Folder> getParentFolders(final Folder folder) {
if (folder == null) {
throw new IllegalArgumentException(
"Can't create a list of parent folder for folder null.");
}
final List<Folder> folders = new ArrayList<>();
if (folder.getParentFolder() != null) {
Folder currentFolder = folder.getParentFolder();
while(currentFolder != null) {
folders.add(currentFolder);
currentFolder = folder.getParentFolder();
}
}
Collections.reverse(folders);
return folders;
}
} }

View File

@ -29,6 +29,11 @@ import org.librecms.contentsection.ContentItem;
*/ */
public final class ItemPrivileges { public final class ItemPrivileges {
/**
* Allows the user to edit the permissions for items.
*/
public static final String ADMINISTER = "administer_items";
/** /**
* Allows the user to approve {@link ContentItem}s. * Allows the user to approve {@link ContentItem}s.
*/ */

View File

@ -18,7 +18,6 @@
*/ */
package org.librecms.contenttypes; package org.librecms.contenttypes;
import com.arsdigita.util.UncheckedWrapperException;
import org.libreccm.modules.CcmModule; import org.libreccm.modules.CcmModule;
import org.librecms.contentsection.ContentItem; import org.librecms.contentsection.ContentItem;

View File

@ -0,0 +1,188 @@
/*
* Copyright (C) 2001-2004 Red Hat Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.arsdigita.bebop;
import com.arsdigita.bebop.util.Traversal;
import com.arsdigita.xml.Element;
/**
* A form that is instantiated on a per-request basis. This class
* functions as a placeholder and decorator of the request-specific form
* in a Bebop {@link Page}.
*
* <p> Subclasses only need to override {@link #buildForm buildForm} to
* return the request-specific form. The meta form takes care of
* interfacing that form with the normal control flow of serving a Bebop
* <code>Page</code>. The meta form will fool the request-specific forms
* into thinking that they are part of a static Bebop <code>Page</code>.
* The properties of the meta form should be used to initialize the
* correspoding properties of the request-specific form whenever
* possible. These properties include <code>name</code>,
* <code>method</code>, and <code>encType</code>.
*
* <p> Listeners can be added directly to the meta form and are run
* whenever the corresponding listeners would be run on an ordinary
* form. The source of the <code>FormSectionEvent</code> will be the meta
* form.
*
* @author Stas Freidin
* @author David Lutterkort
*/
public abstract class MetaForm extends Form {
private RequestLocal m_dynamicForm;
/**
* Constructs a new meta form.
*
* @param name the name of the form
*/
public MetaForm(String name) {
super(name);
m_dynamicForm = new RequestLocal() {
protected Object initialValue(PageState s) {
Form result = buildForm(s);
result.getModel().mergeModel(getModel());
// form isn't part of the page, so it is invisible
// on the page (vacuously). We should consider it
// visible iff the static container MetaForm is visible.
result.setProcessInvisible(
MetaForm.this.getProcessInvisible() ||
s.isVisibleOnPage(MetaForm.this));
result.traverse();
Traversal t = new Traversal() {
public void act(Component c) {
c.lock();
}
};
t.preorder(result);
return result;
}
};
}
/**
* Retrieves the form for the request represented by
* <code>state</code>. If the form hasn't been built
* yet, calls {@link #buildForm buildForm} to build the
* form.
*
* @param state describes the current request
* @return a custom-built form for this request.
* @pre state != null
* @post return != null
*/
protected Form getDynamicForm(PageState state) {
return (Form) m_dynamicForm.get(state);
}
/**
* Builds the dynamic form. Subclasses should override this method to
* build the form based on the request represented by <code>state</code>.
*
* @param state describes the current request
* @return the form to be used for this request.
* @pre state != null
* @post return != null
*/
public abstract Form buildForm(PageState state);
/**
* Force a rebuilding and updating of the dynamic form. Calls
* <code>buildForm</code> again and sets the dynamic form to the form
* returned by it.
*
* @param s describes the current request
*/
public void rebuildForm(PageState s) {
m_dynamicForm.set(s, m_dynamicForm.initialValue(s));
}
/**
* Returns the form data constructed by {@link #process process} for the
* request described by <code>state</code>. If the form for this request
* hasn't been built yet, calls {@link #buildForm buildForm}.
*
* @param state describes the current request
* @return the values extracted from the HTTP request contained
* in <code>state</code>, or <code>null</code> if the form has not
* yet been processed.
* @pre state != null
*/
public FormData getFormData(PageState state) {
return getDynamicForm(state).getFormData(state);
}
/**
* Generates the XML representing the form and its widgets, but not
* the state information, from <code>s</code>. The XML generation is
* delegated to the request-specific form by calling {@link
* #generateXMLSansState generateXMLSansState} on it.
*
* @param s represents the curent request
* @return the top-level element for the form.
*/
protected Element generateXMLSansState(PageState s, Element parent) {
return getDynamicForm(s).generateXMLSansState(s, parent);
}
/**
* Processes the request-specific form for the request represented by
* <code>state</code>.
*
* @param state describes the current request
* @return the form data extracted from the current request.
* @pre state != null
* @post return != null
* @see Form#process Form.process(...)
* @see FormModel#process FormModel.process(...)
*/
public FormData process(PageState state)
throws FormProcessException {
if (state.isVisibleOnPage(this))
return getDynamicForm(state).process(state);
return null; // XXX is this ok ?
}
/**
* Do nothing; the dynamic form will take care of the tag.
*/
protected void addMagicTag() {
return;
}
/**
* Not implemented because meta forms currently don't support mixing static and
* dynamic widgets.
* @throws UnsupportedOperationException
*/
public void add(Component pc, int constraints) {
throw new UnsupportedOperationException("Not implemented");
}
/**
* Not implemented.
* @throws UnsupportedOperationException
*/
public Container getPanel() {
throw new UnsupportedOperationException("Not implemented");
}
}