Subversion Repositories general

Rev

Rev 1018 | Rev 1041 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
924 dev 1
package ak.hostadmiral.core.model;
919 dev 2
 
3
import java.util.*;
4
import net.sf.hibernate.*;
5
import net.sf.hibernate.type.Type;
1028 dev 6
import ak.hostadmiral.util.CollectionInfo;
924 dev 7
import ak.hostadmiral.util.HibernateUtil;
8
import ak.hostadmiral.util.ModelException;
9
import ak.hostadmiral.util.ModelSecurityException;
919 dev 10
 
11
public class UserManager
1014 dev 12
	implements
13
		UserBeforeDeleteListener,
14
		UserDeletingListener
919 dev 15
{
946 dev 16
	private static UserManager userManager = null;
919 dev 17
	private static boolean registered = false;
946 dev 18
 
19
	public static UserManager getInstance()
20
	{
21
		return userManager;
22
	}
23
 
919 dev 24
	protected static void register()
25
	{
1012 dev 26
		synchronized(UserManager.class) {
919 dev 27
			if(registered) return;
28
 
29
			registered = true;
30
			try {
31
				HibernateUtil.getConfiguration().addResource(
950 dev 32
					"ak/hostadmiral/core/model/User.hbm.xml");
949 dev 33
				HibernateUtil.getConfiguration().addResource(
950 dev 34
					"ak/hostadmiral/core/model/UserLogin.hbm.xml");
1018 dev 35
				HibernateUtil.getConfiguration().addResource(
36
					"ak/hostadmiral/core/model/PasswordStoreAbstract.hbm.xml");
946 dev 37
				userManager = new UserManager();
919 dev 38
			}
39
			catch(Exception ex) {
40
				ex.printStackTrace();
41
				throw new RuntimeException(ex.getMessage());
42
			}
43
		}
44
	}
45
 
46
	static {
47
		register();
48
	}
49
 
1010 dev 50
	private Collection createdListeners      = new ArrayList();
51
	private Collection modifiedListeners     = new ArrayList();
946 dev 52
	private Collection beforeDeleteListeners = new ArrayList();
1014 dev 53
	private Collection deletingListeners     = new ArrayList();
1010 dev 54
	private Collection deletedListeners      = new ArrayList();
950 dev 55
	private Map loggedinUsers = new WeakHashMap();
946 dev 56
 
919 dev 57
	private UserManager()
58
	{
946 dev 59
		addBeforeDeleteListener(this);
1014 dev 60
		addDeletingListener(this);
919 dev 61
	}
62
 
63
	public User create(User editor)
64
		throws ModelException
65
	{
66
		if(!allowedToCreate(editor)) throw new ModelSecurityException();
67
 
1010 dev 68
		User user = new User();
69
 
70
		if(!user.mayChangeBoss(editor)) { // ordinal user can create only own "subusers"
71
			user.setBoss(editor);
72
		}
73
 
1015 dev 74
        // FIXME: make this configurable
75
		user.addPasswordStore(new PasswordStoreMd5());
76
		user.addPasswordStore(new PasswordStoreCrypt());
77
		user.addPasswordStore(new PasswordStorePlain());
78
 
1010 dev 79
		return user;
919 dev 80
	}
81
 
82
	public boolean allowedToCreate(User editor)
83
		throws ModelException
84
	{
85
		return User.allowedToCreate(this, editor);
86
	}
87
 
88
	public User get(User editor, Long id)
89
		throws ModelException
90
	{
91
		User user;
92
 
93
		try {
94
			user = (User)HibernateUtil.currentSession().load(User.class, id);
95
		}
1010 dev 96
		catch(HibernateException ex) {
919 dev 97
			throw new ModelException(ex);
98
		}
99
 
100
		if(!user.viewableBy(editor))
101
			throw new ModelSecurityException();
102
 
103
		return user;
104
	}
105
 
923 dev 106
	public boolean loginExists(User editor, User user, String login)
107
		throws ModelException
108
	{
109
		try {
110
			if(user.getId() == null)
111
				return ((Integer)HibernateUtil.currentSession().iterate(
112
					"select count(*) from User u where login = ?",
113
					login, Hibernate.STRING)
114
					.next()).intValue() > 0;
115
			else
116
				return ((Integer)HibernateUtil.currentSession().iterate(
117
					"select count(*) from User u where login = ? and u != ?",
118
					new Object[] { login, user },
119
					new Type[] { Hibernate.STRING, Hibernate.entity(User.class) } )
120
					.next()).intValue() > 0;
121
		}
1010 dev 122
		catch(HibernateException ex) {
923 dev 123
			throw new ModelException(ex);
124
		}
125
	}
126
 
919 dev 127
	public User findForLogin(String login)
128
		throws ModelException
129
	{
130
		try {
131
			List list = HibernateUtil.currentSession().find(
1018 dev 132
				"select u from User u left join fetch u.boss where u.login = ? and u.enabled = ?",
951 dev 133
				new Object[] { login, Boolean.TRUE },
949 dev 134
				new Type[] { Hibernate.STRING, Hibernate.BOOLEAN } );
919 dev 135
 
136
			if(list.size() == 0)
137
				return null;
138
			else
139
				return (User)list.get(0);
140
		}
1010 dev 141
		catch(HibernateException ex) {
919 dev 142
			throw new ModelException(ex);
143
		}
144
	}
145
 
146
	public void save(User editor, User user)
147
		throws ModelException
148
	{
950 dev 149
		if(!user.editableBy(editor) && !user.partEditableBy(editor)
919 dev 150
			&& !user.mayChangeSuperuser(editor))
151
		{
152
			throw new ModelSecurityException();
153
        }
154
 
1010 dev 155
        boolean isNew = user.isNew();
919 dev 156
 
1010 dev 157
		//user.setModUser(editor); // FIXME: disabled because hb throws exception
158
		                           // if user edits itself
159
 
919 dev 160
		try {
161
			HibernateUtil.currentSession().saveOrUpdate(user);
162
		}
1010 dev 163
		catch(HibernateException ex) {
919 dev 164
			throw new ModelException(ex);
165
		}
950 dev 166
 
167
		// update user if he is logged in
168
		for(Iterator i = loggedinUsers.keySet().iterator(); i.hasNext(); ) {
169
			User u = (User)i.next();
170
			if(u.equals(user))
171
				u.update(user);
172
		}
1010 dev 173
 
174
        // inform listeners
175
        if(isNew) {
176
        	for(Iterator i = createdListeners.iterator(); i.hasNext(); ) {
177
        		UserCreatedListener listener = (UserCreatedListener)i.next();
178
    			listener.userCreated(editor, user);
179
        	}
180
        }
181
        else {
182
            User oldUser = user.getOrigin();
183
            if(oldUser == null) oldUser = user;
184
        	for(Iterator i = modifiedListeners.iterator(); i.hasNext(); ) {
185
        		UserModifiedListener listener = (UserModifiedListener)i.next();
186
    			listener.userModified(editor, user, oldUser);
187
        	}
188
        }
919 dev 189
	}
190
 
1010 dev 191
    public void addCreatedListener(UserCreatedListener listener)
192
    {
193
    	createdListeners.add(listener);
194
    }
195
 
196
    public void removeCreatedListener(UserCreatedListener listener)
197
    {
198
    	createdListeners.remove(listener);
199
    }
200
 
201
    public void addModifiedListener(UserModifiedListener listener)
202
    {
203
    	modifiedListeners.add(listener);
204
    }
205
 
206
    public void removeModifiedListener(UserModifiedListener listener)
207
    {
208
    	modifiedListeners.remove(listener);
209
    }
210
 
946 dev 211
    public void addBeforeDeleteListener(UserBeforeDeleteListener listener)
212
    {
213
    	beforeDeleteListeners.add(listener);
214
    }
215
 
216
    public void removeBeforeDeleteListener(UserBeforeDeleteListener listener)
217
    {
218
    	beforeDeleteListeners.remove(listener);
219
    }
220
 
1010 dev 221
    public void addDeletedListener(UserDeletedListener listener)
222
    {
223
    	deletedListeners.add(listener);
224
    }
225
 
226
    public void removeDeletedListener(UserDeletedListener listener)
227
    {
228
    	deletedListeners.remove(listener);
229
    }
230
 
1014 dev 231
    public void addDeletingListener(UserDeletingListener listener)
232
    {
233
    	deletingListeners.add(listener);
234
    }
235
 
236
    public void removeDeletingListener(UserDeletingListener listener)
237
    {
238
    	deletingListeners.remove(listener);
239
    }
240
 
949 dev 241
    public Collection beforeDelete(User editor, User user, Collection known)
946 dev 242
		throws ModelException
243
    {
244
    	Collection cascade = new ArrayList();
245
 
246
    	for(Iterator i = beforeDeleteListeners.iterator(); i.hasNext(); ) {
247
    		UserBeforeDeleteListener listener = (UserBeforeDeleteListener)i.next();
949 dev 248
			Collection subcascade = listener.userBeforeDelete(editor, user, known);
946 dev 249
    		if(subcascade != null)
250
    			cascade.addAll(subcascade);
251
    	}
252
 
253
    	return cascade;
254
    }
255
 
919 dev 256
	public void delete(User editor, User user)
257
		throws ModelException
258
	{
1011 dev 259
	    // check rights
919 dev 260
		if(!user.deleteableBy(editor))
261
			throw new ModelSecurityException();
262
 
1014 dev 263
        // inform deleting listeners
264
    	for(Iterator i = deletingListeners.iterator(); i.hasNext(); ) {
265
    		UserDeletingListener listener = (UserDeletingListener)i.next();
266
			listener.userDeleting(editor, user);
267
    	}
268
 
1010 dev 269
        // backup copy
270
        User oldUser = new User(user);
271
 
272
        // delete it
919 dev 273
		try {
274
			HibernateUtil.currentSession().delete(user);
275
		}
1010 dev 276
		catch(HibernateException ex) {
919 dev 277
			throw new ModelException(ex);
278
		}
1010 dev 279
 
1014 dev 280
        // inform delete listeners
1010 dev 281
    	for(Iterator i = deletedListeners.iterator(); i.hasNext(); ) {
282
    		UserDeletedListener listener = (UserDeletedListener)i.next();
283
			listener.userDeleted(editor, oldUser);
284
    	}
919 dev 285
	}
286
 
287
	public Collection listUsers(User editor)
288
		throws ModelException
289
	{
1028 dev 290
		return listUsers(null, 0, 0, null, editor);
291
	}
292
 
293
	public Collection listUsers(CollectionInfo info, int rowsPerPage, int pageNumber,
294
			Integer[] sortingKeys, User editor)
295
		throws ModelException
296
	{
919 dev 297
		try {
298
			if(editor.isSuperuser()) {
1028 dev 299
				if(info != null) {
300
					info.init(((Integer)HibernateUtil.currentSession().iterate(
301
						"select count(*) from User").next()).intValue(),
302
						pageNumber, rowsPerPage);
303
				}
304
 
305
				return HibernateUtil.pageableList(rowsPerPage, pageNumber,
306
					"select u from User u left join fetch u.boss"
307
					+ HibernateUtil.formOrderClause(sortingKeys, sortKeys), null, null);
919 dev 308
			}
309
			else {
1028 dev 310
				if(info != null) {
311
					info.init(((Integer)HibernateUtil.currentSession().iterate(
312
						"select count(*) from User u where u = ? or u.boss = ?",
313
						new Object[] { editor, editor},
314
						new Type[] { Hibernate.entity(User.class), Hibernate.entity(User.class) }
315
						).next()).intValue(),
316
						pageNumber, rowsPerPage);
317
				}
318
 
319
				return HibernateUtil.pageableList(rowsPerPage, pageNumber,
320
					"select u from User u left join fetch u.boss where u = ? or u.boss = ?"
321
					+ HibernateUtil.formOrderClause(sortingKeys, sortKeys),
919 dev 322
					new Object[] { editor, editor},
323
					new Type[] { Hibernate.entity(User.class), Hibernate.entity(User.class) } );
324
			}
325
		}
1010 dev 326
		catch(HibernateException ex) {
919 dev 327
			throw new ModelException(ex);
328
		}
329
	}
330
 
923 dev 331
	public boolean areUsersAvailable(User editor)
919 dev 332
		throws ModelException
333
	{
334
		try {
335
			if(editor.isSuperuser()) {
336
				return true;
337
			}
338
			else {
1018 dev 339
				// FIXME: always true?
919 dev 340
				return ((Integer)HibernateUtil.currentSession().iterate(
923 dev 341
					"select count(*) from User u where u = ? or u.boss = ?",
919 dev 342
					new Object[] { editor, editor},
343
					new Type[] { Hibernate.entity(User.class), Hibernate.entity(User.class) } )
344
					.next()).intValue() > 0;
345
			}
346
		}
1010 dev 347
		catch(HibernateException ex) {
919 dev 348
			throw new ModelException(ex);
349
		}
350
	}
351
 
949 dev 352
	public User loginUser(String login, String password, String ip)
919 dev 353
		throws ModelException
354
	{
949 dev 355
		User      user      = (login == null || password == null) ? null : findForLogin(login);
356
		boolean   success   = (user == null) ? false : user.checkPassword(password);
951 dev 357
		UserLogin userLogin = new UserLogin(user, login, new Date(), Boolean.valueOf(success), ip);
919 dev 358
 
949 dev 359
		// save login information
360
		try {
361
			HibernateUtil.currentSession().saveOrUpdate(userLogin);
919 dev 362
		}
1010 dev 363
		catch(HibernateException ex) {
949 dev 364
			throw new ModelException(ex);
365
		}
919 dev 366
 
950 dev 367
		if(success) {
1010 dev 368
			user = new User(user);   // unbind the user from hibernate
950 dev 369
			loggedinUsers.put(user, Boolean.TRUE);
949 dev 370
			return user;
950 dev 371
		}
372
		else {
949 dev 373
			return null; // wrong login or password
950 dev 374
		}
919 dev 375
	}
376
 
949 dev 377
	public Collection listFailedLogins(User editor)
946 dev 378
		throws ModelException
919 dev 379
	{
949 dev 380
		if(!editor.mayViewAllLogins())
381
		{
382
			throw new ModelSecurityException();
383
        }
384
 
385
		try {
386
			return HibernateUtil.currentSession().find(
1018 dev 387
				"select l from UserLogin l left join fetch l.user where l.success = ?",
951 dev 388
				Boolean.FALSE, Hibernate.BOOLEAN);
949 dev 389
		}
1010 dev 390
		catch(HibernateException ex) {
391
            throw new ModelException(ex);
949 dev 392
		}
393
	}
394
 
395
	public Collection userBeforeDelete(User editor, User user, Collection known)
396
		throws ModelException
397
	{
946 dev 398
        Collection subusers;
919 dev 399
 
946 dev 400
		try {
401
			subusers = HibernateUtil.currentSession().find(
1018 dev 402
				"select u from User u where u.boss = ?",
946 dev 403
				user, Hibernate.entity(User.class) );
404
		}
1010 dev 405
		catch(HibernateException ex) {
946 dev 406
			throw new ModelException(ex);
407
		}
408
 
409
    	Collection cascade = new ArrayList();
410
		for(Iterator i = subusers.iterator(); i.hasNext(); ) {
411
			User u = (User)i.next();
412
            if(u.viewableBy(editor)) {
413
				if(u.deleteableBy(editor))
414
					cascade.add(new CascadeDeleteElement(u, CascadeDeleteElement.DELETE,
949 dev 415
						this.beforeDelete(editor, u, known)));
946 dev 416
				else
417
					cascade.add(new CascadeDeleteElement(u, CascadeDeleteElement.FORBIDDEN, null));
418
			}
419
			else {
420
				cascade.add(new CascadeDeleteElement(User.createLimitedCopy(u),
421
					CascadeDeleteElement.FORBIDDEN, null));
422
			}
423
		}
424
 
425
    	return cascade;
919 dev 426
	}
427
 
1014 dev 428
	public void userDeleting(User editor, User user)
429
		throws ModelException
430
	{
431
        Collection subusers;
432
 
433
		try {
434
			subusers = HibernateUtil.currentSession().find(
1018 dev 435
				"select u from User u where u.boss = ?",
1014 dev 436
				user, Hibernate.entity(User.class) );
437
		}
438
		catch(HibernateException ex) {
439
			throw new ModelException(ex);
440
		}
441
 
442
		for(Iterator i = subusers.iterator(); i.hasNext(); ) {
443
			delete(editor, (User)i.next());
444
		}
445
	}
446
 
1028 dev 447
	public static final Integer SORT_LOGIN = new Integer(1);
448
 
449
	protected static Map sortKeys = new HashMap();
450
 
451
	static {
452
		sortKeys.put(SORT_LOGIN, "u.login");
453
	}
454
 
919 dev 455
	public static final Comparator LOGIN_COMPARATOR = new LoginComparator();
949 dev 456
	public static final Comparator LOGINS_TIME_COMPARATOR = new LoginsTimeComparator();
919 dev 457
 
458
	private static class LoginComparator
459
		implements Comparator
460
	{
461
		public int compare(Object o1, Object o2)
462
		{
463
			if(!(o1 instanceof User) || !(o2 instanceof User))
464
				throw new ClassCastException("not a User");
465
 
466
		    User a1 = (User)o1;
467
		    User a2 = (User)o2;
468
 
469
		    if(a1 == null && a2 == null)
470
		    	return 0;
471
		    else if(a1 == null && a2 != null)
472
		    	return -1;
473
		    else if(a1 != null && a2 == null)
474
		    	return 1;
475
		    else
476
		    	return a1.getLogin().compareToIgnoreCase(a2.getLogin());
477
		}
478
 
479
		public boolean equals(Object obj)
480
		{
481
			return (obj instanceof LoginComparator);
482
		}
483
	}
949 dev 484
 
485
	private static class LoginsTimeComparator
486
		implements Comparator
487
	{
488
		public int compare(Object o1, Object o2)
489
		{
490
			if(!(o1 instanceof UserLogin) || !(o2 instanceof UserLogin))
491
				throw new ClassCastException("not a UserLogin");
492
 
493
		    UserLogin a1 = (UserLogin)o1;
494
		    UserLogin a2 = (UserLogin)o2;
495
 
496
		    if(a1 == null && a2 == null)
497
		    	return 0;
498
		    else if(a1 == null && a2 != null)
499
		    	return -1;
500
		    else if(a1 != null && a2 == null)
501
		    	return 1;
502
		    else
503
		    	return a1.getLoginTime().compareTo(a2.getLoginTime());
504
		}
505
 
506
		public boolean equals(Object obj)
507
		{
508
			return (obj instanceof LoginComparator);
509
		}
510
	}
919 dev 511
}