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.cms.security;
35
36 import info.magnolia.cms.beans.config.ContentRepository;
37 import info.magnolia.cms.core.Content;
38 import info.magnolia.cms.core.HierarchyManager;
39 import info.magnolia.cms.core.ItemType;
40 import info.magnolia.cms.core.NodeData;
41 import info.magnolia.cms.core.Path;
42 import info.magnolia.cms.util.NodeDataUtil;
43 import info.magnolia.cms.util.SystemContentWrapper;
44
45 import org.apache.commons.codec.binary.Base64;
46 import org.apache.commons.lang.StringUtils;
47 import org.apache.commons.lang.exception.ExceptionUtils;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50
51 import javax.jcr.ItemNotFoundException;
52 import javax.jcr.PathNotFoundException;
53 import javax.jcr.PropertyType;
54 import javax.jcr.RepositoryException;
55 import java.io.Serializable;
56 import java.util.Collection;
57 import java.util.GregorianCalendar;
58 import java.util.Set;
59 import java.util.TreeSet;
60
61
62
63
64
65
66 public class MgnlUser extends AbstractUser implements Serializable {
67
68 private static final long serialVersionUID = 222L;
69
70 private static final Logger log = LoggerFactory.getLogger(MgnlUser.class);
71
72
73
74
75 private static final String NODE_ROLES = "roles";
76
77 private static final String NODE_GROUPS = "groups";
78
79
80
81
82 private static final Object mutex = new Object();
83
84
85 private final SystemContentWrapper userNode;
86
87
88
89
90 protected MgnlUser(Content userNode) {
91 this.userNode = new SystemContentWrapper(userNode);
92 }
93
94
95
96
97
98
99 public boolean inGroup(String groupName) {
100 return this.hasAny(groupName, NODE_GROUPS);
101 }
102
103
104
105
106
107 public void removeGroup(String groupName) throws UnsupportedOperationException {
108 this.remove(groupName, NODE_GROUPS);
109 }
110
111
112
113
114
115 public void addGroup(String groupName) throws UnsupportedOperationException {
116 this.add(groupName, NODE_GROUPS);
117 }
118
119 public boolean isEnabled() {
120 return NodeDataUtil.getBoolean(getUserNode(), "enabled", true);
121 }
122
123 public void setEnabled(boolean enabled) {
124 try {
125 NodeDataUtil.getOrCreateAndSet(getUserNode(), "enabled", enabled);
126 getUserNode().save();
127 } catch (RepositoryException e) {
128 throw new RuntimeException(e);
129 }
130 }
131
132
133
134
135
136
137 public boolean hasRole(String roleName) {
138 return this.hasAny(roleName, NODE_ROLES);
139 }
140
141 public void removeRole(String roleName) {
142 this.remove(roleName, NODE_ROLES);
143 }
144
145 public void addRole(String roleName) {
146 this.add(roleName, NODE_ROLES);
147 }
148
149
150
151 private boolean hasAny(String name, String nodeName) {
152 try {
153 HierarchyManager hm;
154 if (StringUtils.equalsIgnoreCase(nodeName, NODE_ROLES)) {
155 hm = MgnlSecurityUtil.getSystemHierarchyManager(ContentRepository.USER_ROLES);
156 }
157 else {
158 hm = MgnlSecurityUtil.getSystemHierarchyManager(ContentRepository.USER_GROUPS);
159 }
160
161 Content node = this.getUserNode().getContent(nodeName);
162 for (NodeData nodeData : node.getNodeDataCollection()) {
163
164 try {
165 if (hm.getContentByUUID(nodeData.getString()).getName().equalsIgnoreCase(name)) {
166 return true;
167 }
168 }
169 catch (ItemNotFoundException e) {
170 log.debug("Role [{}] does not exist in the ROLES repository", name);
171 }
172 catch (IllegalArgumentException e) {
173 log.debug("{} has invalid value", nodeData.getHandle());
174 }
175 }
176 }
177 catch (RepositoryException e) {
178 log.debug(e.getMessage(), e);
179 }
180 return false;
181 }
182
183 private void remove(String name, String nodeName) {
184 try {
185 HierarchyManager hm;
186 if (StringUtils.equalsIgnoreCase(nodeName, NODE_ROLES)) {
187 hm = MgnlSecurityUtil.getContextHierarchyManager(ContentRepository.USER_ROLES);
188 }
189 else {
190 hm = MgnlSecurityUtil.getContextHierarchyManager(ContentRepository.USER_GROUPS);
191 }
192 Content node = this.getUserNode().getContent(nodeName);
193
194 for (NodeData nodeData : node.getNodeDataCollection()) {
195
196 try {
197 if (hm.getContentByUUID(nodeData.getString()).getName().equalsIgnoreCase(name)) {
198 nodeData.delete();
199 }
200 }
201 catch (ItemNotFoundException e) {
202 log.debug("Role [{}] does not exist in the ROLES repository", name);
203 }
204 catch (IllegalArgumentException e) {
205 log.debug("{} has invalid value", nodeData.getHandle());
206 }
207 }
208 this.getUserNode().save();
209 }
210 catch (RepositoryException e) {
211 log.error("failed to remove " + name + " from user [" + this.getName() + "]", e);
212 }
213 }
214
215 private void add(String name, String nodeName) {
216 try {
217 final String hmName;
218 if (StringUtils.equalsIgnoreCase(nodeName, NODE_ROLES)) {
219 hmName = ContentRepository.USER_ROLES;
220 }
221 else {
222 hmName = ContentRepository.USER_GROUPS;
223 }
224 final HierarchyManager hm = MgnlSecurityUtil.getContextHierarchyManager(hmName);
225
226 if (!this.hasAny(name, nodeName)) {
227 if (!this.getUserNode().hasContent(nodeName)) {
228 this.getUserNode().createContent(nodeName, ItemType.CONTENTNODE);
229 }
230 Content node = this.getUserNode().getContent(nodeName);
231
232 try {
233 String value = hm.getContent("/" + name).getUUID();
234
235 HierarchyManager usersHM = MgnlSecurityUtil.getSystemHierarchyManager(ContentRepository.USERS);
236 String newName = Path.getUniqueLabel(usersHM, node.getHandle(), "0");
237 node.createNodeData(newName).setValue(value);
238 this.getUserNode().save();
239 }
240 catch (PathNotFoundException e) {
241 log.debug("[{}] does not exist in the {} repository", name, hmName);
242 }
243 }
244 }
245 catch (RepositoryException e) {
246 log.error("failed to add " + name + " to user [" + this.getName() + "]", e);
247 }
248 }
249
250 public String getName() {
251 return this.getUserNode().getName();
252 }
253
254 public String getPassword() {
255 final String encodedPassword = this.getUserNode().getNodeData("pswd").getString().trim();
256 return decodePassword(encodedPassword);
257 }
258
259 protected String decodePassword(String encodedPassword) {
260 return new String(Base64.decodeBase64(encodedPassword.getBytes()));
261 }
262
263 public String getLanguage() {
264 return this.getUserNode().getNodeData("language").getString();
265 }
266
267 public String getProperty(String propertyName) {
268 return NodeDataUtil.getString(getUserNode(), propertyName, null);
269 }
270
271 public void setProperty(String propertyName, String value) {
272 try {
273 NodeDataUtil.getOrCreateAndSet(getUserNode(), propertyName, value);
274 getUserNode().save();
275 } catch (RepositoryException e) {
276 throw new RuntimeException(e);
277 }
278 }
279
280 public Collection<String> getGroups() {
281 return MgnlSecurityUtil.collectPropertyNames(getUserNode(), "groups", ContentRepository.USER_GROUPS, false);
282 }
283
284 public Collection<String> getAllGroups() {
285 final Set<String> allGroups = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
286 try {
287
288 final Collection<String> groups = getGroups();
289 allGroups.addAll(groups);
290
291
292 final GroupManager gm = SecuritySupport.Factory.getInstance().getGroupManager();
293 for (String groupName : groups) {
294 final Group g = gm.getGroup(groupName);
295 allGroups.addAll(g.getAllGroups());
296 }
297
298 return allGroups;
299 } catch (AccessDeniedException e) {
300 throw new RuntimeException(e);
301 }
302 }
303
304 public Collection<String> getRoles() {
305 return MgnlSecurityUtil.collectPropertyNames(getUserNode(), "roles", ContentRepository.USER_ROLES, false);
306 }
307
308 public Collection<String> getAllRoles() {
309 final Set<String> allRoles = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
310 try {
311
312 allRoles.addAll(getRoles());
313
314
315 final GroupManager gm = SecuritySupport.Factory.getInstance().getGroupManager();
316 final Collection<String> allGroups = getAllGroups();
317 for (String groupName : allGroups) {
318 final Group g = gm.getGroup(groupName);
319 allRoles.addAll(g.getRoles());
320 }
321
322 return allRoles;
323 } catch (AccessDeniedException e) {
324 throw new RuntimeException(e);
325 }
326 }
327
328
329
330
331 public void setLastAccess() {
332 NodeData lastaccess;
333 Exception finalException = null;
334 boolean success = false;
335
336 for(int i= 1; !success && i <=3; i++){
337 finalException = null;
338 try {
339
340 synchronized (mutex) {
341
342 if(i>1){
343 getUserNode().refresh(false);
344 }
345 lastaccess = NodeDataUtil.getOrCreate(this.getUserNode(), "lastaccess", PropertyType.DATE);
346 lastaccess.setValue(new GregorianCalendar());
347 getUserNode().save();
348 success = true;
349 }
350 }
351 catch (RepositoryException e) {
352 finalException = e;
353 log.debug("Unable to set the last access", e);
354 }
355 }
356 if(finalException != null){
357 log.warn("Unable to set the last access date due to a " + ExceptionUtils.getMessage(finalException));
358 }
359 }
360
361 public Content getUserNode() {
362 return userNode;
363 }
364 }