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