1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.security.app.dialog.field;
35
36 import info.magnolia.cms.security.Permission;
37 import info.magnolia.i18nsystem.SimpleTranslator;
38 import info.magnolia.jcr.RuntimeRepositoryException;
39 import info.magnolia.ui.api.ModelConstants;
40 import info.magnolia.ui.api.app.ChooseDialogCallback;
41 import info.magnolia.ui.api.context.UiContext;
42 import info.magnolia.ui.contentapp.field.WorkbenchFieldDefinition;
43 import info.magnolia.ui.dialog.choosedialog.ChooseDialogPresenter;
44 import info.magnolia.ui.dialog.choosedialog.ChooseDialogView;
45 import info.magnolia.ui.dialog.definition.ConfiguredChooseDialogDefinition;
46 import info.magnolia.ui.vaadin.integration.jcr.AbstractJcrNodeAdapter;
47 import info.magnolia.ui.vaadin.integration.jcr.DefaultProperty;
48 import info.magnolia.ui.vaadin.integration.jcr.JcrItemAdapter;
49 import info.magnolia.ui.vaadin.integration.jcr.JcrNewNodeAdapter;
50 import info.magnolia.ui.vaadin.integration.jcr.JcrNodeAdapter;
51 import info.magnolia.ui.workbench.column.definition.ColumnDefinition;
52 import info.magnolia.ui.workbench.column.definition.PropertyColumnDefinition;
53 import info.magnolia.ui.workbench.definition.ConfiguredNodeTypeDefinition;
54 import info.magnolia.ui.workbench.definition.ConfiguredWorkbenchDefinition;
55 import info.magnolia.ui.workbench.definition.ContentPresenterDefinition;
56 import info.magnolia.ui.workbench.definition.NodeTypeDefinition;
57 import info.magnolia.ui.workbench.definition.WorkbenchDefinition;
58 import info.magnolia.ui.workbench.tree.TreePresenterDefinition;
59
60 import java.util.ArrayList;
61 import java.util.List;
62
63 import javax.jcr.Node;
64 import javax.jcr.RepositoryException;
65
66 import org.apache.commons.lang.StringUtils;
67 import org.apache.jackrabbit.JcrConstants;
68 import org.slf4j.Logger;
69 import org.slf4j.LoggerFactory;
70
71 import com.vaadin.data.Item;
72 import com.vaadin.data.Property;
73 import com.vaadin.ui.AbstractOrderedLayout;
74 import com.vaadin.ui.Button;
75 import com.vaadin.ui.Component;
76 import com.vaadin.ui.CustomField;
77 import com.vaadin.ui.Field;
78 import com.vaadin.ui.HorizontalLayout;
79 import com.vaadin.ui.Label;
80 import com.vaadin.ui.NativeSelect;
81 import com.vaadin.ui.TextField;
82 import com.vaadin.ui.VerticalLayout;
83
84
85
86
87
88
89
90
91
92 public class WorkspaceAccessFieldFactory<D extends WorkspaceAccessFieldDefinition> extends AbstractAccessFieldFactory<D> {
93
94 private static final Logger log = LoggerFactory.getLogger(WorkspaceAccessFieldFactory.class);
95
96 public static final String INTERMEDIARY_FORMAT_PROPERTY_NAME = "__intermediary_format";
97 public static final String ACCESS_TYPE_PROPERTY_NAME = "accessType";
98
99 private final UiContext uiContext;
100 private final SimpleTranslator i18n;
101
102 private ChooseDialogPresenter workbenchChooseDialogPresenter;
103
104
105 public WorkspaceAccessFieldFactory(D definition, Item relatedFieldItem, UiContext uiContext,
106 ChooseDialogPresenter workbenchChooseDialogPresenter, SimpleTranslator i18n) {
107 super(definition, relatedFieldItem);
108 this.uiContext = uiContext;
109 this.workbenchChooseDialogPresenter = workbenchChooseDialogPresenter;
110 this.i18n = i18n;
111 }
112
113 @Override
114 protected Field<Object> createFieldComponent() {
115
116 final String aclName = "acl_" + getFieldDefinition().getWorkspace();
117
118 final VerticalLayout layout = new VerticalLayout();
119 layout.setSpacing(true);
120
121 try {
122
123 final JcrNodeAdapter roleItem = (JcrNodeAdapter) item;
124
125 final VerticalLayout aclLayout = new VerticalLayout();
126
127 final Label emptyLabel = new Label(i18n.translate("security.workspace.field.noAccess"));
128
129
130 if (!(roleItem instanceof JcrNewNodeAdapter)) {
131 Node roleNode = roleItem.getJcrItem();
132 if (roleNode.hasNode(aclName)) {
133
134 final Node aclNode = roleNode.getNode(aclName);
135
136 AccessControlList acl = new AccessControlList();
137 acl.readEntries(aclNode);
138
139 AbstractJcrNodeAdapter aclItem = new JcrNodeAdapter(aclNode);
140 roleItem.addChild(aclItem);
141
142 aclItem.addItemProperty(INTERMEDIARY_FORMAT_PROPERTY_NAME, new DefaultProperty<String>(String.class, "true"));
143
144 for (AccessControlList.Entry entry : acl.getEntries()) {
145
146 long permissions = entry.getPermissions();
147 long accessType = entry.getAccessType();
148 String path = entry.getPath();
149
150 JcrNewNodeAdapter entryItem = addAclEntryItem(aclItem);
151 entryItem.addItemProperty(INTERMEDIARY_FORMAT_PROPERTY_NAME, new DefaultProperty<String>(String.class, "true"));
152 entryItem.addItemProperty(AccessControlList.PERMISSIONS_PROPERTY_NAME, new DefaultProperty<Long>(Long.class, permissions));
153 entryItem.addItemProperty(ACCESS_TYPE_PROPERTY_NAME, new DefaultProperty<Long>(Long.class, accessType));
154 entryItem.addItemProperty(AccessControlList.PATH_PROPERTY_NAME, new DefaultProperty<String>(String.class, path));
155
156 Component ruleRow = createRuleRow(aclLayout, entryItem, emptyLabel);
157 aclLayout.addComponent(ruleRow);
158 }
159 }
160 }
161
162 if (aclLayout.getComponentCount() == 0) {
163 aclLayout.addComponent(emptyLabel);
164 }
165
166 final HorizontalLayout buttons = new HorizontalLayout();
167 final Button addButton = new Button(i18n.translate("security.workspace.field.addButton"));
168 addButton.addClickListener(new Button.ClickListener() {
169
170 @Override
171 public void buttonClick(Button.ClickEvent event) {
172 try {
173
174 AbstractJcrNodeAdapter aclItem = getOrAddAclItem(roleItem, aclName);
175 if (aclItem.getItemProperty(INTERMEDIARY_FORMAT_PROPERTY_NAME) == null) {
176 aclItem.addItemProperty(INTERMEDIARY_FORMAT_PROPERTY_NAME, new DefaultProperty<String>(String.class, "true"));
177 }
178
179 JcrNewNodeAdapter entryItem = addAclEntryItem(aclItem);
180 entryItem.addItemProperty(INTERMEDIARY_FORMAT_PROPERTY_NAME, new DefaultProperty<String>(String.class, "true"));
181 entryItem.addItemProperty(AccessControlList.PERMISSIONS_PROPERTY_NAME, new DefaultProperty<Long>(Long.class, Permission.ALL));
182 entryItem.addItemProperty(ACCESS_TYPE_PROPERTY_NAME, new DefaultProperty<Long>(Long.class, AccessControlList.ACCESS_TYPE_NODE_AND_CHILDREN));
183 entryItem.addItemProperty(AccessControlList.PATH_PROPERTY_NAME, new DefaultProperty<String>(String.class, ""));
184
185 Component ruleRow = createRuleRow(aclLayout, entryItem, emptyLabel);
186 aclLayout.removeComponent(emptyLabel);
187 aclLayout.addComponent(ruleRow, aclLayout.getComponentCount() - 1);
188 } catch (RepositoryException e) {
189 throw new RuntimeRepositoryException(e);
190 }
191 }
192 });
193 buttons.addComponent(addButton);
194 aclLayout.addComponent(buttons);
195
196 layout.addComponent(aclLayout);
197
198 } catch (RepositoryException e) {
199 throw new RuntimeRepositoryException(e);
200 }
201
202 return new CustomField<Object>() {
203
204 @Override
205 protected Component initContent() {
206 return layout;
207 }
208
209 @Override
210 public Class<?> getType() {
211 return Object.class;
212 }
213 };
214 }
215
216 protected Component createRuleRow(final AbstractOrderedLayout parentContainer, final AbstractJcrNodeAdapter ruleItem, final Label emptyLabel) {
217
218 final HorizontalLayout ruleLayout = new HorizontalLayout();
219 ruleLayout.setSpacing(true);
220
221 NativeSelect accessRights = new NativeSelect();
222 accessRights.setNullSelectionAllowed(false);
223 accessRights.setImmediate(true);
224 accessRights.setInvalidAllowed(false);
225 accessRights.setNewItemsAllowed(false);
226 accessRights.addItem(Permission.ALL);
227 accessRights.setItemCaption(Permission.ALL, i18n.translate("security.workspace.field.readWrite"));
228 accessRights.addItem(Permission.READ);
229 accessRights.setItemCaption(Permission.READ, i18n.translate("security.workspace.field.readOnly"));
230 accessRights.addItem(Permission.NONE);
231 accessRights.setItemCaption(Permission.NONE, i18n.translate("security.workspace.field.denyAccess"));
232 accessRights.setPropertyDataSource(ruleItem.getItemProperty(AccessControlList.PERMISSIONS_PROPERTY_NAME));
233 ruleLayout.addComponent(accessRights);
234
235 NativeSelect accessType = new NativeSelect();
236 accessType.setNullSelectionAllowed(false);
237 accessType.setImmediate(true);
238 accessType.setInvalidAllowed(false);
239 accessType.setNewItemsAllowed(false);
240 accessType.setWidth("150px");
241 accessType.addItem(AccessControlList.ACCESS_TYPE_NODE);
242 accessType.setItemCaption(AccessControlList.ACCESS_TYPE_NODE, i18n.translate("security.workspace.field.selected"));
243 accessType.addItem(AccessControlList.ACCESS_TYPE_CHILDREN);
244 accessType.setItemCaption(AccessControlList.ACCESS_TYPE_CHILDREN, i18n.translate("security.workspace.field.subnodes"));
245 accessType.addItem(AccessControlList.ACCESS_TYPE_NODE_AND_CHILDREN);
246 accessType.setItemCaption(AccessControlList.ACCESS_TYPE_NODE_AND_CHILDREN, i18n.translate("security.workspace.field.selectedSubnodes"));
247 Property accessTypeProperty = ruleItem.getItemProperty(ACCESS_TYPE_PROPERTY_NAME);
248 accessType.setPropertyDataSource(accessTypeProperty);
249 ruleLayout.addComponent(accessType);
250
251 final TextField path = new TextField();
252 path.setWidth("125px");
253 path.setPropertyDataSource(ruleItem.getItemProperty(AccessControlList.PATH_PROPERTY_NAME));
254 ruleLayout.addComponent(path);
255
256 Button chooseButton = new Button(i18n.translate("security.workspace.field.choose"));
257 chooseButton.addClickListener(new Button.ClickListener() {
258
259 @Override
260 public void buttonClick(Button.ClickEvent event) {
261 openChooseDialog(path);
262 }
263 });
264 ruleLayout.addComponent(chooseButton);
265
266 Button deleteButton = new Button();
267 deleteButton.setHtmlContentAllowed(true);
268 deleteButton.setCaption("<span class=\"" + "icon-trash" + "\"></span>");
269 deleteButton.addStyleName("inline");
270 deleteButton.setDescription(i18n.translate("security.workspace.field.delete"));
271 deleteButton.addClickListener(new Button.ClickListener() {
272
273 @Override
274 public void buttonClick(Button.ClickEvent event) {
275 parentContainer.removeComponent(ruleLayout);
276 ruleItem.getParent().removeChild(ruleItem);
277 if (parentContainer.getComponentCount() == 1) {
278 parentContainer.addComponent(emptyLabel, 0);
279 }
280 }
281 });
282 ruleLayout.addComponent(deleteButton);
283
284 return ruleLayout;
285 }
286
287 protected void openChooseDialog(final TextField textField) {
288 final ConfiguredChooseDialogDefinition def = new ConfiguredChooseDialogDefinition();
289 final WorkbenchDefinition wbDef = resolveWorkbenchDefinition();
290 final WorkbenchFieldDefinition fieldDef = new WorkbenchFieldDefinition();
291 fieldDef.setWorkbench(wbDef);
292 def.setField(fieldDef);
293 ChooseDialogView chooseDialogView = workbenchChooseDialogPresenter.start(new ChooseDialogCallback() {
294 @Override
295 public void onItemChosen(String actionName, Item item) {
296 try {
297 if (item instanceof JcrItemAdapter) {
298 textField.setValue(((JcrItemAdapter) item).getJcrItem().getPath());
299 } else {
300 textField.setValue("/");
301 }
302 } catch (RepositoryException e) {
303 log.error("Failed to read chosen node", e);
304 }
305 }
306
307 @Override
308 public void onCancel() {
309 }
310 }, def, uiContext, null);
311 chooseDialogView.setCaption(StringUtils.capitalize(getFieldDefinition().getWorkspace()));
312 }
313
314 protected WorkbenchDefinition resolveWorkbenchDefinition() {
315
316 if (getFieldDefinition().getWorkbench() != null) {
317 return getFieldDefinition().getWorkbench();
318 }
319
320 ConfiguredWorkbenchDefinition workbenchDefinition = new ConfiguredWorkbenchDefinition();
321 workbenchDefinition.setWorkspace(getFieldDefinition().getWorkspace());
322 workbenchDefinition.setPath("/");
323 workbenchDefinition.setDialogWorkbench(true);
324 workbenchDefinition.setEditable(false);
325 workbenchDefinition.setDefaultOrder(ModelConstants.JCR_NAME);
326
327
328 workbenchDefinition.setNodeTypes(resolveNodeTypes());
329
330
331 ArrayList<ContentPresenterDefinition> contentViews = new ArrayList<ContentPresenterDefinition>();
332 TreePresenterDefinition treeView = new TreePresenterDefinition();
333 ArrayList<ColumnDefinition> columns = new ArrayList<ColumnDefinition>();
334 PropertyColumnDefinition column = new PropertyColumnDefinition();
335 column.setEditable(false);
336 column.setDisplayInChooseDialog(true);
337 column.setLabel(i18n.translate("security.workspace.field.nodeName"));
338 column.setPropertyName(ModelConstants.JCR_NAME);
339 column.setName(ModelConstants.JCR_NAME);
340 columns.add(column);
341 treeView.setColumns(columns);
342 contentViews.add(treeView);
343 workbenchDefinition.setContentViews(contentViews);
344
345 return workbenchDefinition;
346 }
347
348 private List<NodeTypeDefinition> resolveNodeTypes() {
349
350 if (getFieldDefinition().getNodeTypes() != null) {
351 return getFieldDefinition().getNodeTypes();
352 }
353
354 ArrayList<NodeTypeDefinition> nodeTypes = new ArrayList<NodeTypeDefinition>();
355 ConfiguredNodeTypeDefinition nodeType = new ConfiguredNodeTypeDefinition();
356 nodeType.setName(JcrConstants.NT_BASE);
357 nodeType.setIcon("icon-folder");
358 nodeTypes.add(nodeType);
359
360 return nodeTypes;
361 }
362 }