View Javadoc
1   /*
2    * Copyright (C) 2007-2012 Argeo GmbH
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *         http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.argeo.cms.ui.workbench.internal.jcr.parts;
17  
18  import java.util.Collections;
19  import java.util.HashMap;
20  import java.util.Map;
21  
22  import javax.jcr.RepositoryException;
23  import javax.jcr.Session;
24  import javax.jcr.security.Privilege;
25  
26  import org.argeo.cms.ui.useradmin.PickUpUserDialog;
27  import org.argeo.cms.util.UserAdminUtils;
28  import org.argeo.eclipse.ui.EclipseUiException;
29  import org.argeo.eclipse.ui.EclipseUiUtils;
30  import org.argeo.jcr.JcrUtils;
31  import org.eclipse.jface.dialogs.MessageDialog;
32  import org.eclipse.jface.window.Window;
33  import org.eclipse.jface.wizard.Wizard;
34  import org.eclipse.jface.wizard.WizardPage;
35  import org.eclipse.swt.SWT;
36  import org.eclipse.swt.events.FocusEvent;
37  import org.eclipse.swt.events.FocusListener;
38  import org.eclipse.swt.events.ModifyEvent;
39  import org.eclipse.swt.events.ModifyListener;
40  import org.eclipse.swt.events.SelectionAdapter;
41  import org.eclipse.swt.events.SelectionEvent;
42  import org.eclipse.swt.layout.GridData;
43  import org.eclipse.swt.layout.GridLayout;
44  import org.eclipse.swt.widgets.Combo;
45  import org.eclipse.swt.widgets.Composite;
46  import org.eclipse.swt.widgets.Label;
47  import org.eclipse.swt.widgets.Link;
48  import org.eclipse.swt.widgets.Text;
49  import org.osgi.service.useradmin.User;
50  import org.osgi.service.useradmin.UserAdmin;
51  
52  /** Add JCR privileges to the chosen user group on a given node */
53  public class AddPrivilegeWizard extends Wizard {
54  
55  	// Context
56  	private UserAdmin userAdmin;
57  	private Session currentSession;
58  	private String targetPath;
59  	// Chosen parameters
60  	private String chosenDn;
61  	private User chosenUser;
62  	private String jcrPrivilege;
63  
64  	// UI Object
65  	private DefinePrivilegePage page;
66  
67  	// TODO enable external definition of possible values and corresponding
68  	// description
69  	protected static final Map<String, String> AUTH_TYPE_LABELS;
70  	static {
71  		Map<String, String> tmpMap = new HashMap<String, String>();
72  		tmpMap.put(Privilege.JCR_READ, "jcr:read");
73  		tmpMap.put(Privilege.JCR_WRITE, "jcr:write");
74  		tmpMap.put(Privilege.JCR_ALL, "jcr:all");
75  		AUTH_TYPE_LABELS = Collections.unmodifiableMap(tmpMap);
76  	}
77  
78  	protected static final Map<String, String> AUTH_TYPE_DESC;
79  	static {
80  		Map<String, String> tmpMap = new HashMap<String, String>();
81  		tmpMap.put(Privilege.JCR_READ, "The privilege to retrieve a node and get its properties and their values.");
82  		tmpMap.put(Privilege.JCR_WRITE, "An aggregate privilege that "
83  				+ "contains: jcr:modifyProperties, jcr:addChildNodes, " + "jcr:removeNode, jcr:removeChildNodes");
84  		tmpMap.put(Privilege.JCR_ALL, "An aggregate privilege that " + "contains all JCR predefined privileges, "
85  				+ "plus all implementation-defined privileges. ");
86  		AUTH_TYPE_DESC = Collections.unmodifiableMap(tmpMap);
87  	}
88  
89  	public AddPrivilegeWizard(Session currentSession, String path, UserAdmin userAdmin) {
90  		super();
91  		this.userAdmin = userAdmin;
92  		this.currentSession = currentSession;
93  		this.targetPath = path;
94  	}
95  
96  	@Override
97  	public void addPages() {
98  		try {
99  			setWindowTitle("Add privilege on " + targetPath);
100 			page = new DefinePrivilegePage(userAdmin, targetPath);
101 			addPage(page);
102 		} catch (Exception e) {
103 			throw new EclipseUiException("Cannot add page to wizard ", e);
104 		}
105 	}
106 
107 	@Override
108 	public boolean performFinish() {
109 		if (!canFinish())
110 			return false;
111 		try {
112 			String username = chosenUser.getName();
113 			if (EclipseUiUtils.notEmpty(chosenDn) && chosenDn.equalsIgnoreCase(username))
114 				// Enable forcing the username case. TODO clean once this issue
115 				// has been generally addressed
116 				username = chosenDn;
117 			JcrUtils.addPrivilege(currentSession, targetPath, username, jcrPrivilege);
118 		} catch (RepositoryException re) {
119 			throw new EclipseUiException(
120 					"Cannot set " + jcrPrivilege + " for " + chosenUser.getName() + " on " + targetPath, re);
121 		}
122 		return true;
123 	}
124 
125 	private class DefinePrivilegePage extends WizardPage implements ModifyListener {
126 		private static final long serialVersionUID = 8084431378762283920L;
127 
128 		// Context
129 		final private UserAdmin userAdmin;
130 
131 		public DefinePrivilegePage(UserAdmin userAdmin, String path) {
132 			super("Main");
133 			this.userAdmin = userAdmin;
134 			setTitle("Define the privilege to apply to " + path);
135 			setMessage("Please choose a user or a group and relevant JCR Privilege.");
136 		}
137 
138 		public void createControl(Composite parent) {
139 			final Composite composite = new Composite(parent, SWT.NONE);
140 			composite.setLayout(new GridLayout(3, false));
141 
142 			// specify subject
143 			createBoldLabel(composite, "User or group name");
144 			final Label userNameLbl = new Label(composite, SWT.LEAD);
145 			userNameLbl.setLayoutData(EclipseUiUtils.fillWidth());
146 
147 			Link pickUpLk = new Link(composite, SWT.LEFT);
148 			pickUpLk.setText(" <a>Change</a> ");
149 
150 			createBoldLabel(composite, "User or group DN");
151 			final Text userNameTxt = new Text(composite, SWT.LEAD | SWT.BORDER);
152 			userNameTxt.setLayoutData(EclipseUiUtils.fillWidth(2));
153 
154 			pickUpLk.addSelectionListener(new SelectionAdapter() {
155 				private static final long serialVersionUID = 1L;
156 
157 				@Override
158 				public void widgetSelected(SelectionEvent e) {
159 					PickUpUserDialog dialog = new PickUpUserDialog(getShell(), "Choose a group or a user", userAdmin);
160 					if (dialog.open() == Window.OK) {
161 						chosenUser = dialog.getSelected();
162 						userNameLbl.setText(UserAdminUtils.getCommonName(chosenUser));
163 						userNameTxt.setText(chosenUser.getName());
164 					}
165 				}
166 			});
167 
168 			userNameTxt.addFocusListener(new FocusListener() {
169 				private static final long serialVersionUID = 1965498600105667738L;
170 
171 				@Override
172 				public void focusLost(FocusEvent event) {
173 					String dn = userNameTxt.getText();
174 					if (EclipseUiUtils.isEmpty(dn))
175 						return;
176 
177 					User newChosen = null;
178 					try {
179 						newChosen = (User) userAdmin.getRole(dn);
180 					} catch (Exception e) {
181 						boolean tryAgain = MessageDialog.openQuestion(getShell(), "Unvalid DN",
182 								"DN " + dn + " is not valid.\nError message: " + e.getMessage()
183 										+ "\n\t\tDo you want to try again?");
184 						if (tryAgain)
185 							userNameTxt.setFocus();
186 						else
187 							resetOnFail();
188 					}
189 
190 					if (userAdmin.getRole(dn) == null) {
191 						boolean tryAgain = MessageDialog.openQuestion(getShell(), "Unexisting role",
192 								"User/group " + dn + " does not exist. " + "Do you want to try again?");
193 						if (tryAgain)
194 							userNameTxt.setFocus();
195 						else
196 							resetOnFail();
197 					} else {
198 						chosenUser = newChosen;
199 						chosenDn = dn;
200 						userNameLbl.setText(UserAdminUtils.getCommonName(chosenUser));
201 					}
202 				}
203 
204 				private void resetOnFail() {
205 					String oldDn = chosenUser == null ? "" : chosenUser.getName();
206 					userNameTxt.setText(oldDn);
207 				}
208 
209 				@Override
210 				public void focusGained(FocusEvent event) {
211 				}
212 			});
213 
214 			// JCR Privileges
215 			createBoldLabel(composite, "Privilege type");
216 			Combo authorizationCmb = new Combo(composite, SWT.BORDER | SWT.READ_ONLY | SWT.V_SCROLL);
217 			authorizationCmb.setItems(AUTH_TYPE_LABELS.values().toArray(new String[0]));
218 			authorizationCmb.setLayoutData(EclipseUiUtils.fillWidth(2));
219 			createBoldLabel(composite, ""); // empty cell
220 			final Label descLbl = new Label(composite, SWT.WRAP);
221 			descLbl.setLayoutData(EclipseUiUtils.fillWidth(2));
222 
223 			authorizationCmb.addSelectionListener(new SelectionAdapter() {
224 				private static final long serialVersionUID = 1L;
225 
226 				@Override
227 				public void widgetSelected(SelectionEvent e) {
228 					String chosenPrivStr = ((Combo) e.getSource()).getText();
229 					if (AUTH_TYPE_LABELS.containsValue(chosenPrivStr)) {
230 						loop: for (String key : AUTH_TYPE_LABELS.keySet()) {
231 							if (AUTH_TYPE_LABELS.get(key).equals(chosenPrivStr)) {
232 								jcrPrivilege = key;
233 								break loop;
234 							}
235 						}
236 					}
237 
238 					if (jcrPrivilege != null) {
239 						descLbl.setText(AUTH_TYPE_DESC.get(jcrPrivilege));
240 						composite.layout(true, true);
241 					}
242 				}
243 			});
244 
245 			// Compulsory
246 			setControl(composite);
247 		}
248 
249 		public void modifyText(ModifyEvent event) {
250 			String message = checkComplete();
251 			if (message != null)
252 				setMessage(message, WizardPage.ERROR);
253 			else {
254 				setMessage("Complete", WizardPage.INFORMATION);
255 				setPageComplete(true);
256 			}
257 		}
258 
259 		/** @return error message or null if complete */
260 		protected String checkComplete() {
261 			if (chosenUser == null)
262 				return "Please choose a relevant group or user";
263 			else if (userAdmin.getRole(chosenUser.getName()) == null)
264 				return "Please choose a relevant group or user";
265 			else if (jcrPrivilege == null)
266 				return "Please choose a relevant JCR privilege";
267 			return null;
268 		}
269 	}
270 
271 	private Label createBoldLabel(Composite parent, String value) {
272 		Label label = new Label(parent, SWT.RIGHT);
273 		label.setText(" " + value);
274 		label.setFont(EclipseUiUtils.getBoldFont(parent));
275 		label.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
276 		return label;
277 	}
278 }