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 Node roleNode = roleItem.getJcrItem();
125
126 final VerticalLayout aclLayout = new VerticalLayout();
127
128 final Label emptyLabel = new Label(i18n.translate("security.workspace.field.noAccess"));
129
130 if (roleNode.hasNode(aclName)) {
131
132 final Node aclNode = roleNode.getNode(aclName);
133
134 AccessControlList acl = new AccessControlList();
135 acl.readEntries(aclNode);
136
137 AbstractJcrNodeAdapter aclItem = new JcrNodeAdapter(aclNode);
138 roleItem.addChild(aclItem);
139
140 aclItem.addItemProperty(INTERMEDIARY_FORMAT_PROPERTY_NAME, new DefaultProperty<String>(String.class, "true"));
141
142 for (AccessControlList.Entry entry : acl.getEntries()) {
143
144 long permissions = entry.getPermissions();
145 long accessType = entry.getAccessType();
146 String path = entry.getPath();
147
148 JcrNewNodeAdapter entryItem = addAclEntryItem(aclItem);
149 entryItem.addItemProperty(INTERMEDIARY_FORMAT_PROPERTY_NAME, new DefaultProperty<String>(String.class, "true"));
150 entryItem.addItemProperty(AccessControlList.PERMISSIONS_PROPERTY_NAME, new DefaultProperty<Long>(Long.class, permissions));
151 entryItem.addItemProperty(ACCESS_TYPE_PROPERTY_NAME, new DefaultProperty<Long>(Long.class, accessType));
152 entryItem.addItemProperty(AccessControlList.PATH_PROPERTY_NAME, new DefaultProperty<String>(String.class, path));
153
154 Component ruleRow = createRuleRow(aclLayout, entryItem, emptyLabel);
155 aclLayout.addComponent(ruleRow);
156 }
157 }
158
159 if (aclLayout.getComponentCount() == 0) {
160 aclLayout.addComponent(emptyLabel);
161 }
162
163 final HorizontalLayout buttons = new HorizontalLayout();
164 final Button addButton = new Button(i18n.translate("security.workspace.field.addButton"));
165 addButton.addClickListener(new Button.ClickListener() {
166
167 @Override
168 public void buttonClick(Button.ClickEvent event) {
169 try {
170
171 AbstractJcrNodeAdapter aclItem = getOrAddAclItem(roleItem, aclName);
172 if (aclItem.getItemProperty(INTERMEDIARY_FORMAT_PROPERTY_NAME) == null) {
173 aclItem.addItemProperty(INTERMEDIARY_FORMAT_PROPERTY_NAME, new DefaultProperty<String>(String.class, "true"));
174 }
175
176 JcrNewNodeAdapter entryItem = addAclEntryItem(aclItem);
177 entryItem.addItemProperty(INTERMEDIARY_FORMAT_PROPERTY_NAME, new DefaultProperty<String>(String.class, "true"));
178 entryItem.addItemProperty(AccessControlList.PERMISSIONS_PROPERTY_NAME, new DefaultProperty<Long>(Long.class, Permission.ALL));
179 entryItem.addItemProperty(ACCESS_TYPE_PROPERTY_NAME, new DefaultProperty<Long>(Long.class, AccessControlList.ACCESS_TYPE_NODE_AND_CHILDREN));
180 entryItem.addItemProperty(AccessControlList.PATH_PROPERTY_NAME, new DefaultProperty<String>(String.class, ""));
181
182 Component ruleRow = createRuleRow(aclLayout, entryItem, emptyLabel);
183 aclLayout.removeComponent(emptyLabel);
184 aclLayout.addComponent(ruleRow, aclLayout.getComponentCount() - 1);
185 } catch (RepositoryException e) {
186 throw new RuntimeRepositoryException(e);
187 }
188 }
189 });
190 buttons.addComponent(addButton);
191 aclLayout.addComponent(buttons);
192
193 layout.addComponent(aclLayout);
194
195 } catch (RepositoryException e) {
196 throw new RuntimeRepositoryException(e);
197 }
198
199 return new CustomField<Object>() {
200
201 @Override
202 protected Component initContent() {
203 return layout;
204 }
205
206 @Override
207 public Class<?> getType() {
208 return Object.class;
209 }
210 };
211 }
212
213 protected Component createRuleRow(final AbstractOrderedLayout parentContainer, final AbstractJcrNodeAdapter ruleItem, final Label emptyLabel) {
214
215 final HorizontalLayout ruleLayout = new HorizontalLayout();
216 ruleLayout.setSpacing(true);
217
218 NativeSelect accessRights = new NativeSelect();
219 accessRights.setNullSelectionAllowed(false);
220 accessRights.setImmediate(true);
221 accessRights.setInvalidAllowed(false);
222 accessRights.setNewItemsAllowed(false);
223 accessRights.addItem(Permission.ALL);
224 accessRights.setItemCaption(Permission.ALL, i18n.translate("security.workspace.field.readWrite"));
225 accessRights.addItem(Permission.READ);
226 accessRights.setItemCaption(Permission.READ, i18n.translate("security.workspace.field.readOnly"));
227 accessRights.addItem(Permission.NONE);
228 accessRights.setItemCaption(Permission.NONE, i18n.translate("security.workspace.field.denyAccess"));
229 accessRights.setPropertyDataSource(ruleItem.getItemProperty(AccessControlList.PERMISSIONS_PROPERTY_NAME));
230 ruleLayout.addComponent(accessRights);
231
232 NativeSelect accessType = new NativeSelect();
233 accessType.setNullSelectionAllowed(false);
234 accessType.setImmediate(true);
235 accessType.setInvalidAllowed(false);
236 accessType.setNewItemsAllowed(false);
237 accessType.setWidth("150px");
238 accessType.addItem(AccessControlList.ACCESS_TYPE_NODE);
239 accessType.setItemCaption(AccessControlList.ACCESS_TYPE_NODE, i18n.translate("security.workspace.field.selected"));
240 accessType.addItem(AccessControlList.ACCESS_TYPE_CHILDREN);
241 accessType.setItemCaption(AccessControlList.ACCESS_TYPE_CHILDREN, i18n.translate("security.workspace.field.subnodes"));
242 accessType.addItem(AccessControlList.ACCESS_TYPE_NODE_AND_CHILDREN);
243 accessType.setItemCaption(AccessControlList.ACCESS_TYPE_NODE_AND_CHILDREN, i18n.translate("security.workspace.field.selectedSubnodes"));
244 Property accessTypeProperty = ruleItem.getItemProperty(ACCESS_TYPE_PROPERTY_NAME);
245 accessType.setPropertyDataSource(accessTypeProperty);
246 ruleLayout.addComponent(accessType);
247
248 final TextField path = new TextField();
249 path.setWidth("125px");
250 path.setPropertyDataSource(ruleItem.getItemProperty(AccessControlList.PATH_PROPERTY_NAME));
251 ruleLayout.addComponent(path);
252
253 Button chooseButton = new Button(i18n.translate("security.workspace.field.choose"));
254 chooseButton.addClickListener(new Button.ClickListener() {
255
256 @Override
257 public void buttonClick(Button.ClickEvent event) {
258 openChooseDialog(path);
259 }
260 });
261 ruleLayout.addComponent(chooseButton);
262
263 Button deleteButton = new Button();
264 deleteButton.setHtmlContentAllowed(true);
265 deleteButton.setCaption("<span class=\"" + "icon-trash" + "\"></span>");
266 deleteButton.addStyleName("inline");
267 deleteButton.setDescription(i18n.translate("security.workspace.field.delete"));
268 deleteButton.addClickListener(new Button.ClickListener() {
269
270 @Override
271 public void buttonClick(Button.ClickEvent event) {
272 parentContainer.removeComponent(ruleLayout);
273 ruleItem.getParent().removeChild(ruleItem);
274 if (parentContainer.getComponentCount() == 1) {
275 parentContainer.addComponent(emptyLabel, 0);
276 }
277 }
278 });
279 ruleLayout.addComponent(deleteButton);
280
281 return ruleLayout;
282 }
283
284 protected void openChooseDialog(final TextField textField) {
285 final ConfiguredChooseDialogDefinition def = new ConfiguredChooseDialogDefinition();
286 final WorkbenchDefinition wbDef = resolveWorkbenchDefinition();
287 final WorkbenchFieldDefinition fieldDef = new WorkbenchFieldDefinition();
288 fieldDef.setWorkbench(wbDef);
289 def.setField(fieldDef);
290 ChooseDialogView chooseDialogView = workbenchChooseDialogPresenter.start(new ChooseDialogCallback() {
291 @Override
292 public void onItemChosen(String actionName, Item item) {
293 try {
294 if (item instanceof JcrItemAdapter) {
295 textField.setValue(((JcrItemAdapter) item).getJcrItem().getPath());
296 } else {
297 textField.setValue("/");
298 }
299 } catch (RepositoryException e) {
300 log.error("Failed to read chosen node", e);
301 }
302 }
303
304 @Override
305 public void onCancel() {
306 }
307 }, def, uiContext, null);
308 chooseDialogView.setCaption(StringUtils.capitalize(getFieldDefinition().getWorkspace()));
309 }
310
311 protected WorkbenchDefinition resolveWorkbenchDefinition() {
312
313 if (getFieldDefinition().getWorkbench() != null) {
314 return getFieldDefinition().getWorkbench();
315 }
316
317 ConfiguredWorkbenchDefinition workbenchDefinition = new ConfiguredWorkbenchDefinition();
318 workbenchDefinition.setWorkspace(getFieldDefinition().getWorkspace());
319 workbenchDefinition.setPath("/");
320 workbenchDefinition.setDialogWorkbench(true);
321 workbenchDefinition.setEditable(false);
322 workbenchDefinition.setDefaultOrder(ModelConstants.JCR_NAME);
323
324
325 workbenchDefinition.setNodeTypes(resolveNodeTypes());
326
327
328 ArrayList<ContentPresenterDefinition> contentViews = new ArrayList<ContentPresenterDefinition>();
329 TreePresenterDefinition treeView = new TreePresenterDefinition();
330 ArrayList<ColumnDefinition> columns = new ArrayList<ColumnDefinition>();
331 PropertyColumnDefinition column = new PropertyColumnDefinition();
332 column.setEditable(false);
333 column.setDisplayInChooseDialog(true);
334 column.setLabel(i18n.translate("security.workspace.field.nodeName"));
335 column.setPropertyName(ModelConstants.JCR_NAME);
336 column.setName(ModelConstants.JCR_NAME);
337 columns.add(column);
338 treeView.setColumns(columns);
339 contentViews.add(treeView);
340 workbenchDefinition.setContentViews(contentViews);
341
342 return workbenchDefinition;
343 }
344
345 private List<NodeTypeDefinition> resolveNodeTypes() {
346
347 if (getFieldDefinition().getNodeTypes() != null) {
348 return getFieldDefinition().getNodeTypes();
349 }
350
351 ArrayList<NodeTypeDefinition> nodeTypes = new ArrayList<NodeTypeDefinition>();
352 ConfiguredNodeTypeDefinition nodeType = new ConfiguredNodeTypeDefinition();
353 nodeType.setName(JcrConstants.NT_BASE);
354 nodeType.setIcon("icon-folder");
355 nodeTypes.add(nodeType);
356
357 return nodeTypes;
358 }
359 }