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.action;
35
36 import static info.magnolia.cms.security.MgnlUserManager.*;
37 import static info.magnolia.cms.security.SecurityConstants.*;
38
39 import info.magnolia.cms.security.SecuritySupport;
40 import info.magnolia.cms.security.SilentSessionOp;
41 import info.magnolia.cms.security.User;
42 import info.magnolia.cms.security.UserManager;
43 import info.magnolia.context.MgnlContext;
44 import info.magnolia.jcr.util.NodeUtil;
45 import info.magnolia.jcr.util.PropertyUtil;
46 import info.magnolia.repository.RepositoryConstants;
47 import info.magnolia.security.app.util.UsersWorkspaceUtil;
48 import info.magnolia.ui.admincentral.dialog.action.SaveDialogAction;
49 import info.magnolia.ui.api.action.ActionExecutionException;
50 import info.magnolia.ui.form.EditorCallback;
51 import info.magnolia.ui.form.EditorValidator;
52 import info.magnolia.ui.vaadin.integration.jcr.JcrNewNodeAdapter;
53 import info.magnolia.ui.vaadin.integration.jcr.JcrNodeAdapter;
54 import info.magnolia.ui.vaadin.integration.jcr.ModelConstants;
55
56 import java.util.ArrayList;
57 import java.util.Arrays;
58 import java.util.Collection;
59 import java.util.List;
60
61 import javax.jcr.Node;
62 import javax.jcr.RepositoryException;
63 import javax.jcr.Session;
64 import javax.jcr.Value;
65 import javax.jcr.ValueFactory;
66
67 import org.apache.commons.lang3.StringUtils;
68 import org.slf4j.Logger;
69 import org.slf4j.LoggerFactory;
70
71 import com.vaadin.data.Item;
72
73
74
75
76 public class SaveUserDialogAction extends SaveDialogAction<SaveUserDialogActionDefinition> {
77
78 private static final Logger log = LoggerFactory.getLogger(SaveUserDialogAction.class);
79
80 private SecuritySupport securitySupport;
81 private final List<String> protectedProperties = Arrays.asList(PROPERTY_PASSWORD, "name", NODE_GROUPS, NODE_ROLES);
82
83 public SaveUserDialogAction(SaveUserDialogActionDefinition definition, Item item, EditorValidator validator, EditorCallback callback, SecuritySupport securitySupport) {
84 super(definition, item, validator, callback);
85 this.securitySupport = securitySupport;
86 }
87
88 @Override
89 public void execute() throws ActionExecutionException {
90
91 validator.showValidation(true);
92 if (validator.isValid()) {
93
94 final JcrNodeAdapter nodeAdapter = (JcrNodeAdapter) item;
95 createOrUpdateUser(nodeAdapter);
96 callback.onSuccess(getDefinition().getName());
97
98 } else {
99
100 }
101 }
102
103 private void createOrUpdateUser(final JcrNodeAdapter userItem) throws ActionExecutionException {
104 try {
105 String userManagerRealm = getDefinition().getUserManagerRealm();
106 if (StringUtils.isBlank(userManagerRealm)){
107 log.debug("userManagerRealm property is not defined -> will try to get realm from node path");
108 userManagerRealm = resolveUserManagerRealm(userItem);
109 }
110 UserManager userManager = securitySupport.getUserManager(userManagerRealm);
111 if (userManager == null){
112 throw new ActionExecutionException("User cannot be created. No user manager with realm name " + userManagerRealm + " is defined.");
113 }
114
115 String newUserName = (String) userItem.getItemProperty(ModelConstants.JCR_NAME).getValue();
116 String newPassword = (String) userItem.getItemProperty(PROPERTY_PASSWORD).getValue();
117
118 User user;
119 Session session = userItem.getJcrItem().getSession();
120 if (userItem instanceof JcrNewNodeAdapter) {
121
122
123 Node parentNode = userItem.getJcrItem();
124 String parentPath = parentNode.getPath();
125
126 if ("/".equals(parentPath)) {
127 throw new ActionExecutionException("Users cannot be created directly under root");
128 }
129
130
131 parentNode.getSession().checkPermission(parentNode.getPath(), Session.ACTION_ADD_NODE);
132
133 user = userManager.createUser(parentPath, newUserName, newPassword);
134 } else {
135 Node userNode = userItem.getJcrItem();
136 String existingUserName = userNode.getName();
137 user = userManager.getUser(existingUserName);
138
139 if (!StringUtils.equals(existingUserName, newUserName)) {
140 String pathBefore = userNode.getPath();
141 NodeUtil.renameNode(userNode, newUserName);
142 userNode.setProperty("name", newUserName);
143 UsersWorkspaceUtil.updateAcls(userNode, pathBefore);
144 }
145
146 String existingPasswordHash = user.getProperty(PROPERTY_PASSWORD);
147 if (!StringUtils.equals(newPassword, existingPasswordHash)) {
148 userManager.setProperty(user, PROPERTY_PASSWORD, newPassword);
149 }
150 }
151
152 final Collection<String> groups = resolveItemsNamesFromIdentifiers((Collection<String>) userItem.getItemProperty(NODE_GROUPS).getValue(), RepositoryConstants.USER_GROUPS);
153 log.debug("Assigning user the following groups [{}]", groups);
154 storeGroupsCollection(userManager, user, groups);
155
156 final Collection<String> roles = resolveItemsNamesFromIdentifiers((Collection<String>) userItem.getItemProperty(NODE_ROLES).getValue(), RepositoryConstants.USER_ROLES);
157 log.debug("Assigning user the following roles [{}]", roles);
158 storeRolesCollection(userManager, user, roles);
159
160 Collection<?> userProperties = userItem.getItemPropertyIds();
161 ValueFactory valueFactory = session.getValueFactory();
162 for (Object propertyName : userProperties) {
163 if (!protectedProperties.contains(propertyName)) {
164 Value propertyValue = PropertyUtil.createValue(userItem.getItemProperty(propertyName).getValue(), valueFactory);
165 userManager.setProperty(user, propertyName.toString(), propertyValue);
166 }
167 }
168
169 session.save();
170
171 } catch (final RepositoryException e) {
172 throw new ActionExecutionException(e);
173 }
174 }
175
176 private String resolveUserManagerRealm(final JcrNodeAdapter userItem) throws RepositoryException{
177 String userPath = userItem.getJcrItem().getPath();
178 if (userItem instanceof JcrNewNodeAdapter && !"/".equals(userPath)) {
179
180 userPath += "/";
181 }
182 return StringUtils.substringBetween(userPath, "/");
183 }
184
185 private void storeGroupsCollection(UserManager userManager, User user, Collection<String> newGroups){
186 Collection<String> oldGroups = new ArrayList<String>();
187 for (String group : user.getGroups()) {
188 oldGroups.add(group);
189 }
190 for(String newGroup : newGroups) {
191 userManager.addGroup(user, newGroup);
192 oldGroups.remove(newGroup);
193 }
194 for(String oldGroup : oldGroups) {
195 userManager.removeGroup(user, oldGroup);
196 }
197 }
198
199 private void storeRolesCollection(UserManager userManager, User user, Collection<String> newRoles){
200 Collection<String> oldRoles = new ArrayList<String>();
201 for (String role : user.getRoles()) {
202 oldRoles.add(role);
203 }
204 for(String newRole : newRoles) {
205 userManager.addRole(user, newRole);
206 oldRoles.remove(newRole);
207 }
208 for(String oldRole : oldRoles) {
209 userManager.removeRole(user, oldRole);
210 }
211 }
212
213 private Collection<String> resolveItemsNamesFromIdentifiers(Collection<String> itemsIdentifiers, String repository){
214 final Collection<String> itemsNames = new ArrayList<String>();
215 for (final String itemIdentifier : itemsIdentifiers) {
216 MgnlContext.doInSystemContext(new SilentSessionOp<Void>(repository) {
217
218 @Override
219 public Void doExec(Session session) {
220 try {
221 final String itemName = session.getNodeByIdentifier(itemIdentifier).getName();
222 itemsNames.add(itemName);
223 } catch (RepositoryException e) {
224 log.error("Can't resolve group/role with uuid: " + itemIdentifier);
225 log.debug(e.getMessage());
226 }
227 return null;
228 }
229 });
230 }
231 return itemsNames;
232 }
233
234 }