Subversion Repositories general

Rev

Rev 1058 | Rev 1072 | 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
 
1041 dev 3
import java.util.Collection;
4
import java.util.ArrayList;
5
import java.util.Iterator;
6
import java.util.Map;
7
import java.util.WeakHashMap;
8
import java.util.Comparator;
9
import java.util.Date;
10
 
11
import ak.hostadmiral.util.ConfigInit;
1028 dev 12
import ak.hostadmiral.util.CollectionInfo;
924 dev 13
import ak.hostadmiral.util.ModelException;
14
import ak.hostadmiral.util.ModelSecurityException;
1041 dev 15
import ak.hostadmiral.core.model.store.UserStore;
919 dev 16
 
17
public class UserManager
1014 dev 18
	implements
1041 dev 19
		ConfigInit,
1014 dev 20
		UserBeforeDeleteListener,
21
		UserDeletingListener
919 dev 22
{
1062 dev 23
	private UserStore store;
24
	private Class[]   passwordStores;
946 dev 25
 
1062 dev 26
	private Collection validateListeners     = new ArrayList();
1010 dev 27
	private Collection createdListeners      = new ArrayList();
28
	private Collection modifiedListeners     = new ArrayList();
946 dev 29
	private Collection beforeDeleteListeners = new ArrayList();
1014 dev 30
	private Collection deletingListeners     = new ArrayList();
1010 dev 31
	private Collection deletedListeners      = new ArrayList();
1041 dev 32
 
1056 dev 33
	// FIMXE: check that it works
950 dev 34
	private Map loggedinUsers = new WeakHashMap();
946 dev 35
 
1041 dev 36
	public UserManager()
37
		throws ModelException
919 dev 38
	{
946 dev 39
		addBeforeDeleteListener(this);
1014 dev 40
		addDeletingListener(this);
919 dev 41
	}
42
 
43
	public User create(User editor)
44
		throws ModelException
45
	{
46
		if(!allowedToCreate(editor)) throw new ModelSecurityException();
47
 
1010 dev 48
		User user = new User();
49
 
1046 dev 50
		if(!user.mayChangeBoss(editor)) // ordinal user can create only own "subusers"
1010 dev 51
			user.setBoss(editor);
52
 
1046 dev 53
        setUserPasswordStores(user);
1015 dev 54
 
1010 dev 55
		return user;
919 dev 56
	}
57
 
58
	public boolean allowedToCreate(User editor)
59
		throws ModelException
60
	{
61
		return User.allowedToCreate(this, editor);
62
	}
63
 
64
	public User get(User editor, Long id)
65
		throws ModelException
66
	{
1041 dev 67
		User user = store.get(id);
919 dev 68
 
69
		if(!user.viewableBy(editor))
70
			throw new ModelSecurityException();
71
 
72
		return user;
73
	}
74
 
923 dev 75
	public boolean loginExists(User editor, User user, String login)
76
		throws ModelException
77
	{
1041 dev 78
		return store.loginExists(user, login);
923 dev 79
	}
80
 
1041 dev 81
	public User findForLogin(User editor, String login)
919 dev 82
		throws ModelException
83
	{
1041 dev 84
		User user = store.findForLogin(login);
919 dev 85
 
1041 dev 86
		if(user != null && !user.viewableBy(editor))
87
			throw new ModelSecurityException();
88
 
89
		return user;
919 dev 90
	}
91
 
92
	public void save(User editor, User user)
93
		throws ModelException
94
	{
1062 dev 95
		// security check
950 dev 96
		if(!user.editableBy(editor) && !user.partEditableBy(editor)
919 dev 97
			&& !user.mayChangeSuperuser(editor))
98
		{
99
			throw new ModelSecurityException();
100
        }
101
 
1062 dev 102
		//user.setModUser(editor); // FIXME: disabled because hb throws exception
103
		                           // if user edits itself
1044 dev 104
 
1010 dev 105
        boolean isNew = user.isNew();
1062 dev 106
        User oldUser = user.getOrigin();
107
        if(oldUser == null) oldUser = user;
919 dev 108
 
1062 dev 109
		// validate
110
    	for(Iterator i = validateListeners.iterator(); i.hasNext(); ) {
111
    		UserValidateListener listener = (UserValidateListener)i.next();
112
			listener.userValidate(editor, user, oldUser);
113
    	}
1010 dev 114
 
1041 dev 115
		store.save(user);
950 dev 116
 
117
		// update user if he is logged in
118
		for(Iterator i = loggedinUsers.keySet().iterator(); i.hasNext(); ) {
119
			User u = (User)i.next();
120
			if(u.equals(user))
121
				u.update(user);
122
		}
1010 dev 123
 
124
        // inform listeners
125
        if(isNew) {
126
        	for(Iterator i = createdListeners.iterator(); i.hasNext(); ) {
127
        		UserCreatedListener listener = (UserCreatedListener)i.next();
128
    			listener.userCreated(editor, user);
129
        	}
130
        }
131
        else {
132
        	for(Iterator i = modifiedListeners.iterator(); i.hasNext(); ) {
133
        		UserModifiedListener listener = (UserModifiedListener)i.next();
134
    			listener.userModified(editor, user, oldUser);
135
        	}
136
        }
1045 dev 137
 
138
        // reset backup
139
        user.resetOrigin();
919 dev 140
	}
141
 
1062 dev 142
    public void addValidateListener(UserValidateListener listener)
143
    {
144
    	validateListeners.add(listener);
145
    }
146
 
147
    public void removeValidateListener(UserValidateListener listener)
148
    {
149
    	validateListeners.remove(listener);
150
    }
151
 
1010 dev 152
    public void addCreatedListener(UserCreatedListener listener)
153
    {
154
    	createdListeners.add(listener);
155
    }
156
 
157
    public void removeCreatedListener(UserCreatedListener listener)
158
    {
159
    	createdListeners.remove(listener);
160
    }
161
 
162
    public void addModifiedListener(UserModifiedListener listener)
163
    {
164
    	modifiedListeners.add(listener);
165
    }
166
 
167
    public void removeModifiedListener(UserModifiedListener listener)
168
    {
169
    	modifiedListeners.remove(listener);
170
    }
171
 
946 dev 172
    public void addBeforeDeleteListener(UserBeforeDeleteListener listener)
173
    {
174
    	beforeDeleteListeners.add(listener);
175
    }
176
 
177
    public void removeBeforeDeleteListener(UserBeforeDeleteListener listener)
178
    {
179
    	beforeDeleteListeners.remove(listener);
180
    }
181
 
1010 dev 182
    public void addDeletedListener(UserDeletedListener listener)
183
    {
184
    	deletedListeners.add(listener);
185
    }
186
 
187
    public void removeDeletedListener(UserDeletedListener listener)
188
    {
189
    	deletedListeners.remove(listener);
190
    }
191
 
1014 dev 192
    public void addDeletingListener(UserDeletingListener listener)
193
    {
194
    	deletingListeners.add(listener);
195
    }
196
 
197
    public void removeDeletingListener(UserDeletingListener listener)
198
    {
199
    	deletingListeners.remove(listener);
200
    }
201
 
949 dev 202
    public Collection beforeDelete(User editor, User user, Collection known)
946 dev 203
		throws ModelException
204
    {
205
    	Collection cascade = new ArrayList();
206
 
207
    	for(Iterator i = beforeDeleteListeners.iterator(); i.hasNext(); ) {
208
    		UserBeforeDeleteListener listener = (UserBeforeDeleteListener)i.next();
949 dev 209
			Collection subcascade = listener.userBeforeDelete(editor, user, known);
946 dev 210
    		if(subcascade != null)
211
    			cascade.addAll(subcascade);
212
    	}
213
 
214
    	return cascade;
215
    }
216
 
919 dev 217
	public void delete(User editor, User user)
218
		throws ModelException
219
	{
1011 dev 220
	    // check rights
919 dev 221
		if(!user.deleteableBy(editor))
222
			throw new ModelSecurityException();
223
 
1014 dev 224
        // inform deleting listeners
225
    	for(Iterator i = deletingListeners.iterator(); i.hasNext(); ) {
226
    		UserDeletingListener listener = (UserDeletingListener)i.next();
227
			listener.userDeleting(editor, user);
228
    	}
229
 
1010 dev 230
        // backup copy
231
        User oldUser = new User(user);
232
 
233
        // delete it
1041 dev 234
		store.delete(user);
1010 dev 235
 
1014 dev 236
        // inform delete listeners
1010 dev 237
    	for(Iterator i = deletedListeners.iterator(); i.hasNext(); ) {
238
    		UserDeletedListener listener = (UserDeletedListener)i.next();
239
			listener.userDeleted(editor, oldUser);
240
    	}
919 dev 241
	}
242
 
243
	public Collection listUsers(User editor)
244
		throws ModelException
245
	{
1028 dev 246
		return listUsers(null, 0, 0, null, editor);
247
	}
248
 
249
	public Collection listUsers(CollectionInfo info, int rowsPerPage, int pageNumber,
250
			Integer[] sortingKeys, User editor)
251
		throws ModelException
252
	{
1041 dev 253
		if(editor.isSuperuser())
254
			return store.listAllUsers(info, rowsPerPage, pageNumber, sortingKeys);
255
		else
256
			return store.listUsers(info, rowsPerPage, pageNumber, sortingKeys, editor);
919 dev 257
	}
258
 
923 dev 259
	public boolean areUsersAvailable(User editor)
919 dev 260
		throws ModelException
261
	{
1041 dev 262
		return true;
919 dev 263
	}
264
 
949 dev 265
	public User loginUser(String login, String password, String ip)
919 dev 266
		throws ModelException
267
	{
1041 dev 268
		User      user      = (login == null || password == null)
269
			? null : store.findForLogin(login);
270
 
949 dev 271
		boolean   success   = (user == null) ? false : user.checkPassword(password);
951 dev 272
		UserLogin userLogin = new UserLogin(user, login, new Date(), Boolean.valueOf(success), ip);
919 dev 273
 
949 dev 274
		// save login information
1041 dev 275
		store.saveUserLogin(userLogin);
919 dev 276
 
950 dev 277
		if(success) {
1041 dev 278
			user = new User(user);   // unbind the user from store
950 dev 279
			loggedinUsers.put(user, Boolean.TRUE);
949 dev 280
			return user;
950 dev 281
		}
282
		else {
949 dev 283
			return null; // wrong login or password
950 dev 284
		}
919 dev 285
	}
286
 
949 dev 287
	public Collection listFailedLogins(User editor)
946 dev 288
		throws ModelException
919 dev 289
	{
949 dev 290
		if(!editor.mayViewAllLogins())
291
			throw new ModelSecurityException();
292
 
1041 dev 293
		return store.listFailedLogins();
949 dev 294
	}
295
 
296
	public Collection userBeforeDelete(User editor, User user, Collection known)
297
		throws ModelException
298
	{
1041 dev 299
        Collection subusers = store.listSubusers(user);
919 dev 300
 
946 dev 301
    	Collection cascade = new ArrayList();
302
		for(Iterator i = subusers.iterator(); i.hasNext(); ) {
303
			User u = (User)i.next();
1058 dev 304
			if(known.contains(u)) continue;
305
 
306
			known.add(u);
946 dev 307
            if(u.viewableBy(editor)) {
308
				if(u.deleteableBy(editor))
309
					cascade.add(new CascadeDeleteElement(u, CascadeDeleteElement.DELETE,
949 dev 310
						this.beforeDelete(editor, u, known)));
946 dev 311
				else
312
					cascade.add(new CascadeDeleteElement(u, CascadeDeleteElement.FORBIDDEN, null));
313
			}
314
			else {
315
				cascade.add(new CascadeDeleteElement(User.createLimitedCopy(u),
316
					CascadeDeleteElement.FORBIDDEN, null));
317
			}
318
		}
319
 
320
    	return cascade;
919 dev 321
	}
322
 
1014 dev 323
	public void userDeleting(User editor, User user)
324
		throws ModelException
325
	{
1041 dev 326
        Collection subusers = store.listSubusers(user);
1014 dev 327
 
328
		for(Iterator i = subusers.iterator(); i.hasNext(); ) {
329
			delete(editor, (User)i.next());
330
		}
331
	}
332
 
1046 dev 333
	protected void setUserPasswordStores(User user)
334
		throws ModelException
335
	{
336
		if(passwordStores == null) return;
337
 
338
        try {
339
			for(int i = 0; i < passwordStores.length; i++)
340
				user.addPasswordStore((PasswordStore)passwordStores[i].newInstance());
341
        }
342
        catch(Exception ex) {
343
        	throw new ModelException(ex);
344
        }
345
	}
346
 
1055 dev 347
	public Collection listUserLogins(CollectionInfo info, int rowsPerPage, int pageNumber,
348
			Integer[] sortingKeys, User editor, User user)
349
		throws ModelException
350
	{
351
		return store.listUserLogins(info, rowsPerPage, pageNumber, sortingKeys, user);
352
	}
1028 dev 353
 
1055 dev 354
	public static final Integer SORT_LOGIN               = new Integer(1);
355
	public static final Integer SORT_LOGINS_TIME         = new Integer(2);
356
	public static final Integer SORT_LOGINS_TIME_REVERSE = new Integer(3);
357
 
919 dev 358
	public static final Comparator LOGIN_COMPARATOR = new LoginComparator();
949 dev 359
	public static final Comparator LOGINS_TIME_COMPARATOR = new LoginsTimeComparator();
919 dev 360
 
361
	private static class LoginComparator
362
		implements Comparator
363
	{
364
		public int compare(Object o1, Object o2)
365
		{
366
			if(!(o1 instanceof User) || !(o2 instanceof User))
367
				throw new ClassCastException("not a User");
368
 
369
		    User a1 = (User)o1;
370
		    User a2 = (User)o2;
371
 
372
		    if(a1 == null && a2 == null)
373
		    	return 0;
374
		    else if(a1 == null && a2 != null)
375
		    	return -1;
376
		    else if(a1 != null && a2 == null)
377
		    	return 1;
378
		    else
379
		    	return a1.getLogin().compareToIgnoreCase(a2.getLogin());
380
		}
381
 
382
		public boolean equals(Object obj)
383
		{
384
			return (obj instanceof LoginComparator);
385
		}
386
	}
949 dev 387
 
388
	private static class LoginsTimeComparator
389
		implements Comparator
390
	{
391
		public int compare(Object o1, Object o2)
392
		{
393
			if(!(o1 instanceof UserLogin) || !(o2 instanceof UserLogin))
394
				throw new ClassCastException("not a UserLogin");
395
 
396
		    UserLogin a1 = (UserLogin)o1;
397
		    UserLogin a2 = (UserLogin)o2;
398
 
399
		    if(a1 == null && a2 == null)
400
		    	return 0;
401
		    else if(a1 == null && a2 != null)
402
		    	return -1;
403
		    else if(a1 != null && a2 == null)
404
		    	return 1;
405
		    else
406
		    	return a1.getLoginTime().compareTo(a2.getLoginTime());
407
		}
408
 
409
		public boolean equals(Object obj)
410
		{
411
			return (obj instanceof LoginComparator);
412
		}
413
	}
1041 dev 414
 
415
	public void init(Map params)
416
		throws ModelException
417
	{
418
		try {
419
    		userManager = this;
420
 
1046 dev 421
			Class c = Class.forName(((String[])params.get("store"))[0]);
1041 dev 422
			store = (UserStore)c.newInstance();
1044 dev 423
 
1046 dev 424
			String[] passwordStoreNames = (String[])params.get("passwordStore");
425
			if(passwordStoreNames != null) {
426
				passwordStores = new Class[passwordStoreNames.length];
427
				for(int i = 0; i < passwordStoreNames.length; i++) {
428
					passwordStores[i] = Class.forName(passwordStoreNames[i]);
429
				}
430
			}
1041 dev 431
        }
432
        catch(Exception ex) {
433
        	throw new ModelException(ex);
434
        }
435
	}
436
 
437
	private static UserManager userManager = null;
438
 
439
	public static UserManager getInstance()
440
	{
441
		return userManager;
442
	}
919 dev 443
}