1
18 package org.torweg.pulse.accesscontrol;
19
20 import java.io.File;
21 import java.io.FileNotFoundException;
22 import java.math.BigInteger;
23 import java.security.NoSuchAlgorithmException;
24 import java.security.SecureRandom;
25 import java.util.HashSet;
26 import java.util.Random;
27 import java.util.Set;
28
29 import javax.persistence.Transient;
30 import javax.xml.bind.annotation.XmlAccessOrder;
31 import javax.xml.bind.annotation.XmlAccessType;
32 import javax.xml.bind.annotation.XmlAccessorOrder;
33 import javax.xml.bind.annotation.XmlAccessorType;
34 import javax.xml.bind.annotation.XmlElement;
35 import javax.xml.bind.annotation.XmlElementWrapper;
36 import javax.xml.bind.annotation.XmlRootElement;
37
38 import org.hibernate.LazyInitializationException;
39 import org.hibernate.Session;
40 import org.hibernate.Transaction;
41 import org.hibernate.criterion.Restrictions;
42 import org.jdom.Element;
43 import org.slf4j.Logger;
44 import org.slf4j.LoggerFactory;
45 import org.torweg.pulse.configuration.PoorMansCache;
46 import org.torweg.pulse.invocation.lifecycle.Lifecycle;
47 import org.torweg.pulse.service.PulseException;
48 import org.torweg.pulse.service.request.ServiceSession;
49 import org.torweg.pulse.util.HibernateDataSource;
50 import org.torweg.pulse.util.StringUtils;
51
52
58 @XmlRootElement(name = "abstract-user-base")
59 @XmlAccessorOrder(XmlAccessOrder.UNDEFINED)
60 @XmlAccessorType(XmlAccessType.FIELD)
61 public abstract class AbstractUserBase extends AbstractAccessControlObject {
62
63
66 private static final long serialVersionUID = -7020963404983358073L;
67
68
71 private static final Logger LOGGER = LoggerFactory
72 .getLogger(AbstractUserBase.class);
73
74
77 protected static final String PASSWORD_CHARACTERS = "0123456789"
78 + "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
79 + "~+*#'?/\\{}[]()!$%&=-_.,;:";
80
81
84 @XmlElement(name = "everybody-id")
85 private static Long everybodyId;
86
87
90 @Transient
91 private final Set<CommandMatcher> commandMatchers = new HashSet<CommandMatcher>();
93
94
97 public static final String EVERYBODY = "~Everybody";
98
99
106 private static void initUserCommandMatchers(final User user) {
107 for (Role r : user.getRoles()) {
108 processGroups(user, r.getGroups());
109 processPermissions(user, r.getPermissions());
110 }
111 processGroups(user, user.getGroups());
112 processPermissions(user, user.getPermissions());
113 }
114
115
125 private static void processGroups(final User user, final Set<Group> gs) {
126 for (Group g : gs) {
127 for (Permission p : g.getPermissions()) {
128 user.getCommandMatchers().addAll(p.getCommandMatchers());
129 }
130 }
131 }
132
133
144 private static void processPermissions(final User user,
145 final Set<Permission> ps) {
146 for (Permission p : ps) {
147 user.getCommandMatchers().addAll(p.getCommandMatchers());
148 }
149 }
150
151
160 private static void parseUserAttributes(final User user) {
161 try {
162 Element userAttributes = PoorMansCache.getJDOMResource(
163 new File("WEB-INF" + System.getProperty("file.separator")
164 + "conf" + System.getProperty("file.separator")
165 + "user-attributes.xml")).getRootElement();
166 for (Object o : userAttributes.getChildren("user")) {
167 Element userElement = (Element) o;
168 if (!userElement.getAttributeValue("name").equals(
169 user.getName())) {
170 continue;
171 }
172 for (Object attr : userElement.getChildren("attribute")) {
173 user.addAttribute(parseAttribute((Element) attr));
174 }
175 }
176 } catch (FileNotFoundException e) {
177 LOGGER.warn("no user-attributes.xml found!");
178 }
179 }
180
181
188 private static UserAttribute parseAttribute(final Element attr) {
189 UserAttribute attribute = new UserAttribute(
190 attr.getAttributeValue("name"));
191 for (Object v : attr.getChildren("value")) {
192 Element value = (Element) v;
193 attribute.addValue(value.getTextNormalize());
194 }
195 for (Object a : attr.getChildren("attribute")) {
196 attribute.addAttribute(parseAttribute((Element) a));
197 }
198 return attribute;
199 }
200
201
209 private static void addSessionRoles(final User user,
210 final ServiceSession session) {
211 if (session != null && session.getSessionRoles() != null
212 && !session.getSessionRoles().isEmpty()) {
213 for (Role role : session.getSessionRoles()) {
214 if (!user.addSessionRole(role)) {
215 LOGGER.warn(
216 "Could not add session based role {}@{} to current user.",
217 role.getName(), role.getId());
218 }
219
220 }
221 }
222 }
223
224
227 protected final Set<CommandMatcher> getCommandMatchers() {
228 return this.commandMatchers;
229 }
230
231
236 @XmlElementWrapper(name = "command-matchers")
237 @XmlElement(name = "command-matcher")
238 @SuppressWarnings("unused")
239 @Deprecated
240 private HashSet<CommandMatcher> getCommandMatchersJAXB() { try {
242 return new HashSet<CommandMatcher>(getCommandMatchers());
243 } catch (LazyInitializationException e) {
244 LOGGER.debug("ignored: {}", e.getLocalizedMessage());
245 return null;
246 }
247 }
248
249
254 protected final Long getEveryBodyId() {
255 return Long.valueOf(everybodyId.longValue());
256 }
257
258
267 public static final User getUser(final ServiceSession session) {
268 Long id = null;
269 if (session != null) {
270 id = (Long) session.getAttribute(User.class.getCanonicalName());
271 }
272 User user = null;
273 Session sess = null;
274 Transaction trans = null;
275 try {
276 sess = Lifecycle.getHibernateDataSource().createNewSession();
277 trans = sess.beginTransaction();
278
279
280 Role everybody = getEverybodyRole(sess);
281
282
283 if (id != null) {
284 user = (User) sess.get(User.class, id);
285 if (user != null && user.isActive()) {
286 initUserCommandMatchers(user);
287 } else {
288 session.removeAttribute(User.class.getCanonicalName());
289 }
290 }
291
292
296 if (user == null) {
297 user = new User.Everybody(everybody);
298 }
299
300 processGroups(user, everybody.getGroups());
301 processPermissions(user, everybody.getPermissions());
302
303 trans.commit();
304 } catch (Exception exception) {
305 if (trans != null) {
306 trans.rollback();
307 }
308 throw new PulseException(exception);
309 } finally {
310 sess.close();
311 }
312
313 if (user != null) {
315 parseUserAttributes(user);
316 }
317
318 addSessionRoles(user, session);
320
321 return user;
322 }
323
324
333 public static final User getUser(final String usrName) {
334 Session sess = null;
335 Transaction trans = null;
336 try {
337 sess = Lifecycle.getHibernateDataSource().createNewSession();
338 trans = sess.beginTransaction();
339 User user = (User) sess
340 .createQuery("from User as u where u.name=?")
341 .setString(0, usrName).setCacheable(true).uniqueResult();
342 if (user != null) {
343 initUserCommandMatchers(user);
344 }
345
346
347 Role everybody = getEverybodyRole(sess);
348
349 if ((user == null) || (user.isExpunged())) {
350 user = new User.Everybody(everybody);
351 }
352
353 processGroups(user, everybody.getGroups());
354 processPermissions(user, everybody.getPermissions());
355
356 trans.commit();
357 return user;
358 } catch (Exception exception) {
359 if (trans != null) {
360 trans.rollback();
361 }
362 throw new PulseException(exception);
363 } finally {
364 sess.close();
365 }
366 }
367
368
381 public static final User getSuperUser(final HibernateDataSource dataSrc) {
382 User superUsr = null;
383 String passwd = null;
384 Session sess = null;
385 Transaction trans = null;
386 try {
387 sess = dataSrc.createNewSession();
388 trans = sess.beginTransaction();
389 superUsr = (User) sess
390 .createQuery("from User as u where u.superuser = ?")
391 .setBoolean(0, true).uniqueResult();
392 if (superUsr == null) {
393 passwd = generatePassword();
394 superUsr = new User("root", "user@domain", passwd);
395 superUsr.setSuperuser(true);
396 superUsr.setWebdavEnabled(true);
397 sess.save(superUsr);
398 }
399 trans.commit();
400 } catch (Exception exception) {
401 if (trans != null) {
402 trans.rollback();
403 }
404 throw new PulseException(exception);
405 } finally {
406 sess.close();
407 }
408 if (passwd != null) {
409 LOGGER.info("Created new superuser root identified by {}", passwd);
410 }
411 return superUsr;
412 }
413
414
421 public static final Role getEverybodyRole(final Session sess) {
422 Role everybody;
423 if (everybodyId != null) {
424 everybody = (Role) sess.get(Role.class, everybodyId);
425 } else {
426 everybody = (Role) sess.createCriteria(Group.class)
427 .add(Restrictions.eq("name", User.EVERYBODY))
428 .uniqueResult();
429 }
430 return everybody;
431 }
432
433
442 public static final void initEverybodyRole(final HibernateDataSource ds) {
443 Session s = ds.createNewSession();
444 Transaction tx = s.beginTransaction();
445 try {
446 Role everybody = (Role) s.createCriteria(Role.class)
447 .add(Restrictions.eq("name", User.EVERYBODY))
448 .uniqueResult();
449 if (everybody == null) {
450 everybody = new Role(User.EVERYBODY);
451 s.save(everybody);
452 LOGGER.info("Created Role '{}' as the default role.",
453 User.EVERYBODY);
454 }
455 tx.commit();
456 everybodyId = everybody.getId();
457 } catch (Exception e) {
458 tx.rollback();
459 throw new PulseException("Error: " + e.getLocalizedMessage(), e);
460 } finally {
461 s.close();
462 }
463 }
464
465
470 public static final String generatePassword() {
471 Random random;
472 try {
473 random = SecureRandom.getInstance("SHA1PRNG");
475 } catch (NoSuchAlgorithmException e) {
476 LOGGER.error(
477 "Error creating SecureRandom: " + e.getLocalizedMessage(),
478 e);
479 random = new Random();
480 random.setSeed(System.currentTimeMillis());
481 }
482
483 StringBuilder password = new StringBuilder();
484 for (int i = 0; i < 15; i++) {
485 password.append(User.PASSWORD_CHARACTERS.charAt((int) (random
486 .nextDouble() * User.PASSWORD_CHARACTERS.length())));
487 }
488 return password.toString();
489 }
490
491
497 public static final String generateToken() {
498 byte[] bytes = new byte[16];
499 Lifecycle.getRandom().nextBytes(bytes);
500 BigInteger token = new BigInteger(bytes);
501 StringBuilder tokenBuilder = new StringBuilder(
502 StringUtils.toBase62String(token.abs()));
503 for (int i = tokenBuilder.length(); i < 22; i++) {
504 tokenBuilder.insert(0, '0');
505 }
506 return tokenBuilder.toString();
507 }
508
509 }
510