001 /*
002 *
003 * $Revision: 14994 $ $Date: 2009-03-24 13:01:57 +0100 (Tue, 24 Mar 2009) $
004 *
005 * This file is part of *** M y C o R e ***
006 * See http://www.mycore.de/ for details.
007 *
008 * This program is free software; you can use it, redistribute it
009 * and / or modify it under the terms of the GNU General Public License
010 * (GPL) as published by the Free Software Foundation; either version 2
011 * of the License or (at your option) any later version.
012 *
013 * This program is distributed in the hope that it will be useful, but
014 * WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program, in a file called gpl.txt or license.txt.
020 * If not, write to the Free Software Foundation Inc.,
021 * 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA
022 */
023
024 package org.mycore.user;
025
026 import static org.mycore.common.MCRConstants.XLINK_NAMESPACE;
027 import static org.mycore.common.MCRConstants.XSI_NAMESPACE;
028
029 import java.util.ArrayList;
030 import java.util.HashSet;
031 import java.util.Iterator;
032 import java.util.List;
033 import java.util.Set;
034
035 import org.apache.log4j.Logger;
036 import org.jdom.Element;
037 import org.mycore.access.MCRAccessManager;
038 import org.mycore.common.MCRCache;
039 import org.mycore.common.MCRConfiguration;
040 import org.mycore.common.MCRException;
041 import org.mycore.common.MCRSession;
042 import org.mycore.common.MCRSessionMgr;
043
044 /**
045 * This class is the user (and group) manager of the MyCoRe system. It is
046 * implemented using the singleton design pattern in order to ensure that there
047 * is only one instance of this class, i.e. one user manager, running. The user
048 * manager has several responsibilities. First it serves as a facade for client
049 * classes such as MyCoRe-Servlets to retrieve objects from the persistent
050 * datastore. Then the manager is used by the user and group objects themselves
051 * to manage their existence in the underlying datastore.
052 *
053 * @author Detlev Degenhardt
054 * @author Jens Kupferschmidt
055 * @version $Revision: 14994 $ $Date: 2009-01-29 09:42:52 +0100 (Do, 29. Jan
056 * 2009) $
057 */
058 public class MCRUserMgr {
059 /** The LOGGER and the configuration */
060 private static Logger LOGGER = Logger.getLogger(MCRUserMgr.class.getName());
061
062 private static MCRConfiguration CONFIG = null;
063
064 // private static MCRAccessInterface AI;
065
066 /**
067 * flag that determines whether write access to the data is denied (true) or
068 * allowed
069 */
070 private boolean locked = false;
071
072 /** flag that determines whether we use password encryption */
073 private boolean useEncryption = false;
074
075 /** the user cache */
076 private MCRCache userCache;
077
078 /** the group cache */
079 private MCRCache groupCache;
080
081 /** the class responsible for persistent datastore (configurable ) */
082 private MCRUserStore mcrUserStore;
083
084 /** The one and only instance of this class */
085 private static MCRUserMgr theInstance = null;
086
087 /**
088 * private constructor to create the singleton instance.
089 */
090 private MCRUserMgr() throws MCRException {
091 CONFIG = MCRConfiguration.instance();
092
093 String userStoreName = CONFIG.getString("MCR.Persistence.User.Store.Class");
094 useEncryption = CONFIG.getBoolean("MCR.Users.UsePasswordEncryption", false);
095
096 try {
097 mcrUserStore = (MCRUserStore) Class.forName(userStoreName).newInstance();
098 } catch (Exception e) {
099 throw new MCRException("MCRUserStore error", e);
100 }
101
102 userCache = new MCRCache(20, "UserMgr users"); // resonable values?
103 // This might also be
104 groupCache = new MCRCache(10, "UserMgr groups"); // read from
105 // mycore.properties....
106 }
107
108 /**
109 * This method is the only way to get an instance of this class. It calls
110 * the private constructor to create the singleton.
111 *
112 * @return returns the one and only instance of <CODE>MCRUserMgr</CODE>
113 */
114 public final static synchronized MCRUserMgr instance() throws MCRException {
115 if (theInstance == null) {
116 theInstance = new MCRUserMgr();
117 }
118
119 return theInstance;
120 }
121
122 /**
123 * This method checks the consistency of the user and group data. It should
124 * be executed after importing data from xml files, e.g.
125 */
126 public final void checkConsistency() throws MCRException {
127 locked = true; // we now run in the read only mode
128
129 // Get the MCRSession object for the current thread from the session
130 // manager.
131 MCRSession session = MCRSessionMgr.getCurrentSession();
132
133 if (session == null) {
134 return;
135 }
136 // For this action you must have list rights.
137 if (!MCRAccessManager.checkPermission("administrate-user") && !session.getCurrentUserID().equals("administrator")) {
138 locked = false;
139 throw new MCRException("The session does not have the permission \"administrate-user\"!");
140 }
141
142 // For all users in the system get their groups and check if the groups
143 // really exist at all.
144 // We do not need to check if the user is a member of the groups listed
145 // in his or her groups
146 // list since the user object is constructed from the data - so he or
147 // she *must* be a member
148 // by definition. However, since the primary group of the user is added
149 // automatically to the
150 // group list in MCRUser, we have to check if this group has the user as
151 // one of its members.
152 LOGGER.info("Consistency check is started.");
153
154 List<String> allUserIDs = mcrUserStore.getAllUserIDs();
155
156 for (String userID : allUserIDs) {
157 MCRUser currentUser = retrieveUser(userID, true);
158 List<String> currentGroupIDs = currentUser.getGroupIDs();
159
160 for (String gid : currentGroupIDs) {
161 if (!mcrUserStore.existsGroup(gid)) {
162 LOGGER.error("user : '" + currentUser.getID() + "' error: unknown group '" + gid + "'!");
163 }
164 }
165
166 MCRGroup primaryGroup = retrieveGroup(currentUser.getPrimaryGroupID(), true);
167 ArrayList<String> mbrUserIDs = primaryGroup.getMemberUserIDs();
168
169 if (!mbrUserIDs.contains(currentUser.getID())) {
170 LOGGER.error("user : '" + currentUser.getID() + "' error: is not member of" + " primary group '"
171 + currentUser.getPrimaryGroupID() + "'!");
172 }
173 }
174
175 // For all groups get the admins and members (user and group lists,
176 // respectively) and check
177 // if they have unknown users as admins or members, unknown groups as
178 // admins or members etc.
179 List<String> allGroupIDs = mcrUserStore.getAllGroupIDs();
180
181 for (String gid : allGroupIDs) {
182 MCRGroup currentGroup = retrieveGroup(gid, true);
183
184 // check the admin users
185 ArrayList<String> admUserIDs = currentGroup.getAdminUserIDs();
186
187 for (int j = 0; j < admUserIDs.size(); j++) {
188 if (!mcrUserStore.existsUser((String) admUserIDs.get(j))) {
189 LOGGER.error("group: '" + currentGroup.getID() + "' error: unknown admin" + " user '" + (String) admUserIDs.get(j)
190 + "'!");
191 }
192 }
193
194 // check the admin groups
195 ArrayList<String> admGroupIDs = currentGroup.getAdminGroupIDs();
196
197 for (int j = 0; j < admGroupIDs.size(); j++) {
198 if (!mcrUserStore.existsGroup((String) admGroupIDs.get(j))) {
199 LOGGER.error("group: '" + currentGroup.getID() + "' error: unknown admin" + " group '" + (String) admGroupIDs.get(j)
200 + "'!");
201 }
202 }
203
204 // check the users (members)
205 ArrayList<String> mbrUserIDs = currentGroup.getMemberUserIDs();
206
207 for (int j = 0; j < mbrUserIDs.size(); j++) {
208 if (!mcrUserStore.existsUser((String) mbrUserIDs.get(j))) {
209 LOGGER.error("group: '" + currentGroup.getID() + "' error: unknown user '" + (String) mbrUserIDs.get(j) + "'!");
210 }
211 }
212 }
213
214 LOGGER.info("done.");
215 locked = false; // write access is allowed again
216 }
217
218 /**
219 * This method creates a group in the datastore (and the group cache as
220 * well). The logical correctness of the data is checked.
221 *
222 * @param group
223 * The group object to be created
224 */
225 public final void createGroup(MCRGroup group) throws MCRException {
226 if (locked) {
227 throw new MCRException("The user component is locked. At the moment write access is denied.");
228 }
229 // Check the permissions
230 if ((!MCRAccessManager.checkPermission("create-group"))) {
231 throw new MCRException("The current user does not have the permission to create a group!");
232 }
233 createGroupInternal(group);
234 }
235
236 /**
237 * This method is internal to create a group.
238 *
239 * @param group
240 * The group object to be created
241 */
242 private final synchronized void createGroupInternal(MCRGroup group) throws MCRException {
243 // Check if there really is a non-null group object provided
244 if (group == null) {
245 throw new MCRException("The given group object is null.");
246 }
247 // Check if the given group object is valid.
248 if (!group.isValid()) {
249 throw new MCRException("The given group object is not valid.");
250 }
251 // Check if the group already exists.
252 if (mcrUserStore.existsGroup(group.getID())) {
253 throw new MCRException("The group '" + group.getID() + "' already exists!");
254 }
255 // set the current user ID as administration user
256 MCRSession session = MCRSessionMgr.getCurrentSession();
257 MCRUser admin = retrieveUser(session.getCurrentUserID(), false);
258 if (admin != null) {
259 group.addAdminUserID(admin.getID());
260 group.addAdminGroupID(admin.getPrimaryGroupID());
261 }
262 // add other administration user
263 ArrayList<String> admUserIDs = group.getAdminUserIDs();
264 for (int j = 0; j < admUserIDs.size(); j++) {
265 if (!mcrUserStore.existsUser((String) admUserIDs.get(j))) {
266 throw new MCRException("Unknown admin userID: " + (String) admUserIDs.get(j));
267 }
268 }
269 // add other primary groups
270 ArrayList<String> admGroupIDs = group.getAdminGroupIDs();
271 for (int j = 0; j < admGroupIDs.size(); j++) {
272 if (((String) admGroupIDs.get(j)).equals(group.getID())) {
273 continue;
274 }
275 if (!mcrUserStore.existsGroup((String) admGroupIDs.get(j))) {
276 throw new MCRException("Unknown admin groupID: " + (String) admGroupIDs.get(j));
277 }
278 }
279
280 try {
281 // Set some data by the manager
282 group.setCreationDate();
283 group.setModifiedDate();
284 group.setCreator(session.getCurrentUserID());
285
286 // Just create the group. The group must be created before updating
287 // the groups this
288 // group is a member of because the existence of the group will be
289 // checked while
290 // updating the groups.
291 mcrUserStore.createGroup(group);
292 } catch (Exception ex) {
293 // Since something went wrong we delete the previously created
294 // group. We do this
295 // using this.deleteGroup() in order to ensure that already updated
296 // groups will
297 // be resetted to the original state as well.
298 try {
299 deleteGroup(group.getID());
300 } catch (MCRException e) {
301 }
302
303 LOGGER.error("Can't create MCRGroup", ex);
304 throw new MCRException("Can't create MCRGroup.", ex);
305 }
306 }
307
308 /**
309 * This method creates a user in the datastore (and the user cache as well).
310 * The logical correctness of the data is checked.
311 *
312 * @param user
313 * The user object which will be created
314 */
315 public final void createUser(MCRUser user) throws MCRException {
316 if (locked) {
317 throw new MCRException("The user component is locked. At the moment write access is denied.");
318 }
319 // Check the permissions
320 if (!MCRAccessManager.checkPermission("create-user")) {
321 throw new MCRException("The current user does not have the permission to create a user!");
322 }
323 createUserInternal(user);
324 }
325
326 /**
327 * This is the internal method to create a user.
328 *
329 * @param user
330 * The user object which will be created
331 */
332 private final synchronized void createUserInternal(MCRUser user) throws MCRException {
333 // Check if there really is a non-null object provided
334 if (user == null) {
335 throw new MCRException("The given user object is null.");
336 }
337 // Check if the given user object is valid.
338 if (!user.isValid()) {
339 throw new MCRException("The given user object is not valid.");
340 }
341 // Check if the user already exists.
342 if (mcrUserStore.existsUser(user.getNumID(), user.getID())) {
343 throw new MCRException("The user '" + user.getID() + "' or numerical ID '" + user.getNumID() + "' already exists!");
344 }
345 // Check if the primary group exists and if so, whether the current user
346 // may modify the group
347 if (!mcrUserStore.existsGroup(user.getPrimaryGroupID())) {
348 throw new MCRException("The primary group of the user '" + user.getID() + "' does not exist.");
349 }
350 MCRGroup primGroup = retrieveGroup(user.getPrimaryGroupID());
351 // Check if the groups the user will be a member of really exist
352 List<String> groupIDs = user.getGroupIDs();
353 for (String gid : groupIDs) {
354 if (!mcrUserStore.existsGroup(gid)) {
355 throw new MCRException("The user '" + user.getID() + "' is linked to the unknown group '" + gid + "'.");
356 }
357 }
358 try {
359 // Set some data by the manager
360 user.setCreationDate();
361 user.setModifiedDate();
362 MCRSession session = MCRSessionMgr.getCurrentSession();
363 user.setCreator(session.getCurrentUserID());
364
365 // At first create the user. The user must be created before
366 // updating the groups
367 // because the existence of the user will be checked while updating
368 // the groups.
369 mcrUserStore.createUser(user);
370
371 // now we update the primary group
372 primGroup.addMemberUserID(user.getID());
373 groupCache.remove(primGroup.getID());
374 mcrUserStore.updateGroup(primGroup);
375
376 // now update the other groups
377 for (int i = 0; i < groupIDs.size(); i++) {
378 if (!primGroup.getID().equals(groupIDs.get(i))) {
379 MCRGroup otherGroup = retrieveGroup((String) groupIDs.get(i), true);
380 otherGroup.addMemberUserID(user.getID());
381 groupCache.remove(otherGroup.getID());
382 mcrUserStore.updateGroup(otherGroup);
383 }
384 }
385 } catch (MCRException ex) {
386 // Since something went wrong we delete the previously created user.
387 // We do this
388 // using this.deleteUser() in order to ensure that already updated
389 // groups will
390 // be resetted to the original state as well.
391 try {
392 deleteUser(user.getID());
393 } catch (Exception e) {
394 }
395
396 throw new MCRException("Can't create user.", ex);
397 }
398 }
399
400 /**
401 * This method deletes a group from the datastore (and the group cache as
402 * well).
403 *
404 * @param groupID
405 * The group ID which will be deleted
406 */
407 public final void deleteGroup(String groupID) throws MCRException {
408 if (locked) {
409 throw new MCRException("The user component is locked. At the moment write" + " access is denied.");
410 }
411 // Check the permissions
412 if (!MCRAccessManager.checkPermission("delete-group")) {
413 throw new MCRException("The current user does not have the permission to delete a group!");
414 }
415 deleteGroupInternal(groupID);
416 }
417
418 /**
419 * This is the internal method to delete groups.
420 *
421 * @param groupID
422 * The group ID which will be deleted
423 */
424 private final synchronized void deleteGroupInternal(String groupID) throws MCRException {
425 // Check if the group exists at all
426 if (!mcrUserStore.existsGroup(groupID)) {
427 throw new MCRException("The group '" + groupID + "' is unknown!");
428 }
429
430 // Now we check if there are users in the system which have this group
431 // as their primary
432 // group. If so, this group cannot be deleted. First the users must be
433 // updated.
434 List<String> primUserIDs = mcrUserStore.getUserIDsWithPrimaryGroup(groupID);
435
436 if (primUserIDs.iterator().hasNext()) {
437 throw new MCRException("Group '" + groupID + "' can't be deleted since there" + " are users with '" + groupID
438 + "' as their primary group. First update or" + " delete the users!");
439 }
440
441 try {
442 // It is sufficient to remove the members from the
443 // caches. The next time they will be used they will be rebuild from
444 // the datastore and
445 // hence no longer have this group in their group lists.
446 MCRGroup delGroup = retrieveGroup(groupID);
447
448 for (int i = 0; i < delGroup.getMemberUserIDs().size(); i++) {
449 userCache.remove(delGroup.getMemberUserIDs().get(i));
450
451 MCRUser uuser = retrieveUser((String) delGroup.getMemberUserIDs().get(i), false);
452 uuser.removeGroupID(groupID);
453 mcrUserStore.updateUser(uuser);
454 }
455
456 // Remove all admin items from other groups
457 List<String> ogroups = mcrUserStore.getGroupIDsWithAdminUser(groupID);
458
459 for (String gid : ogroups) {
460 groupCache.remove(gid);
461
462 MCRGroup agroup = retrieveGroup(gid);
463 agroup.removeAdminGroupID(groupID);
464 mcrUserStore.updateGroup(agroup);
465 }
466 } catch (Exception ex) {
467 throw new MCRException("Can't delete group " + groupID, ex);
468 } finally {
469 groupCache.remove(groupID);
470 mcrUserStore.deleteGroup(groupID);
471 }
472 LOGGER.info("Group with ID " + groupID + " deleted.");
473 }
474
475 /**
476 * This method deletes a user from the datastore (and the user cache as
477 * well).
478 *
479 * @param userID
480 * The user ID which will be deleted
481 */
482 public final void deleteUser(String userID) throws MCRException {
483 if (locked) {
484 throw new MCRException("The user component is locked. At the moment write" + " access is denied.");
485 }
486 // Check the permission
487 if (!MCRAccessManager.checkPermission("delete-user")) {
488 throw new MCRException("The current user does not have the permission to delete a user!");
489 }
490 deleteUserInternal(userID);
491 }
492
493 /**
494 * This is the internal method for delete a user.
495 *
496 * @param userID
497 * The user ID which will be deleted
498 */
499 private final synchronized void deleteUserInternal(String userID) throws MCRException {
500 // Check if the user exists at all
501 if (!mcrUserStore.existsUser(userID)) {
502 throw new MCRException("User '" + userID + "' is unknown!");
503 }
504 MCRUser user = retrieveUser(userID, false);
505 if (!user.isUpdateAllowed()) {
506 throw new MCRException("Delete for user '" + userID + "' is not allowed!");
507 }
508 // We have to notify the groups where this user is an administrative
509 // user
510 List<String> adminGroups = mcrUserStore.getGroupIDsWithAdminUser(userID);
511 for (String gid : adminGroups) {
512 try {
513 MCRGroup adminGroup = retrieveGroup(gid);
514 adminGroup.removeAdminUserID(userID);
515 groupCache.remove(adminGroup.getID());
516 mcrUserStore.updateGroup(adminGroup);
517 } catch (Exception ex) {
518 LOGGER.warn("Can't remove " + userID + "from group " + gid);
519 }
520 }
521
522 // We have to notify the groups this user is a member of
523 for (int i = 0; i < user.getGroupIDs().size(); i++) {
524 try {
525 MCRGroup currentGroup = retrieveGroup((String) user.getGroupIDs().get(i));
526 currentGroup.removeMemberUserID(userID);
527 groupCache.remove(currentGroup.getID());
528 mcrUserStore.updateGroup(currentGroup);
529 } catch (Exception ex) {
530 LOGGER.warn("Can't remove " + userID + "from group " + adminGroups.get(i));
531 }
532 }
533 userCache.remove(userID);
534 mcrUserStore.deleteUser(userID);
535 LOGGER.info("User with ID " + userID + " deleted.");
536 }
537
538 /**
539 * This method disables the user.
540 *
541 * @param userID
542 * The user object which will be disabled
543 */
544 public final void disableUser(String userID) throws MCRException {
545 enable(userID, false);
546 LOGGER.info("User with ID " + userID + " disabled!");
547 }
548
549 /**
550 * This method enables the user.
551 *
552 * @param userID
553 * The user object which will be enabled
554 */
555 public final void enableUser(String userID) throws MCRException {
556 enable(userID, true);
557 LOGGER.info("User with ID " + userID + " enabled!");
558 }
559
560 /**
561 * This method gets all group IDs from the persistent datastore and returns
562 * them as a ArrayList of strings.
563 *
564 * @return ArrayList of strings containing the group IDs of the system.
565 */
566 public final List<String> getAllGroupIDs() throws MCRException {
567 return mcrUserStore.getAllGroupIDs();
568 }
569
570 /**
571 * This method returns a JDOM presentation of all groups of the system
572 *
573 * @return JDOM document presentation of all groups of the system
574 */
575 public final org.jdom.Document getAllGroups() throws MCRException {
576 // Build the DOM
577 MCRGroup currentGroup = null;
578 org.jdom.Element root = new org.jdom.Element("mycoregroup");
579 root.addNamespaceDeclaration(XSI_NAMESPACE);
580 root.addNamespaceDeclaration(XLINK_NAMESPACE);
581 root.setAttribute("noNamespaceSchemaLocation", "MCRGroup.xsd", XSI_NAMESPACE);
582
583 List<String> allGroupIDs = mcrUserStore.getAllGroupIDs();
584
585 for (String gid : allGroupIDs) {
586 currentGroup = mcrUserStore.retrieveGroup(gid);
587 root.addContent(currentGroup.toJDOMElement());
588 }
589
590 org.jdom.Document jdomDoc = new org.jdom.Document(root);
591
592 return jdomDoc;
593 }
594
595 /**
596 * This method gets all user IDs from the persistent datastore and returns
597 * them as an ArrayList of strings.
598 *
599 * @return ArrayList of strings containing the user IDs of the system.
600 */
601 public final List<String> getAllUserIDs() throws MCRException {
602 return mcrUserStore.getAllUserIDs();
603 }
604
605 /**
606 * This method returns a JDOM presentation of all users of the system
607 *
608 * @return JDOM document presentation of all users of the system
609 */
610 public final org.jdom.Document getAllUsers() throws MCRException {
611 // Build the DOM
612 MCRUser currentUser;
613 org.jdom.Element root = new org.jdom.Element("mycoreuser");
614 root.addNamespaceDeclaration(XSI_NAMESPACE);
615 root.addNamespaceDeclaration(XLINK_NAMESPACE);
616 root.setAttribute("noNamespaceSchemaLocation", "MCRUser.xsd", XSI_NAMESPACE);
617
618 List<String> allUserIDs = mcrUserStore.getAllUserIDs();
619
620 for (String uid : allUserIDs) {
621 currentUser = mcrUserStore.retrieveUser(uid);
622 root.addContent(currentUser.toJDOMElement());
623 }
624
625 org.jdom.Document jdomDoc = new org.jdom.Document(root);
626
627 return jdomDoc;
628 }
629
630 /**
631 * The access control subsystem needs to know the current working user. This
632 * information is held in the session, so we just ask the session about it.
633 *
634 * @return the current user
635 */
636 public final MCRUser getCurrentUser() {
637 // Get the MCRSession object for the current thread from the session
638 // manager.
639 MCRSession mcrSession = MCRSessionMgr.getCurrentSession();
640
641 return retrieveUser(mcrSession.getCurrentUserID(), false);
642 }
643
644 /**
645 * This method determines in which groups of a given set of groups a given
646 * user is a member of.
647 *
648 * @return set of groups the given user is a member of
649 */
650 public final Set<MCRGroup> getGroupsContainingUser(MCRUser user, Set<MCRGroup> groups) {
651 Set<MCRGroup> set = new HashSet<MCRGroup>();
652 Iterator<MCRGroup> iterator = groups.iterator();
653
654 while (iterator.hasNext()) {
655 Object element = iterator.next();
656
657 if (element instanceof MCRGroup) {
658 MCRGroup group = (MCRGroup) element;
659
660 if (group.hasUserMember(user)) {
661 set.add(group);
662 }
663 }
664 }
665
666 return set;
667 }
668
669 /**
670 * This method determines in which groups is the user member.
671 *
672 * @return an ArrayList of groups where the given user is a member of
673 */
674 public final List<String> getGroupsContainingUser(String user) {
675 MCRUser u = retrieveUser(user);
676 List<String> a = getAllGroupIDs();
677 List<String> o = new ArrayList<String>(a.size());
678 for (String aa : a) {
679 if (retrieveGroup(aa).hasUserMember(u)) {
680 if (!o.contains(aa)) {
681 o.add(aa);
682 }
683 }
684 }
685 return o;
686 }
687
688 /**
689 * This method returns the maximum value of the numerical user IDs
690 *
691 * @return maximum value of the numerical user IDs
692 */
693 public final int getMaxUserNumID() throws MCRException {
694 // without checking a permission, because we only want to see it
695 return mcrUserStore.getMaxUserNumID();
696 }
697
698 /**
699 * This method returns the ID of the primary group for a given userID.
700 *
701 * @param userID
702 * the userID for which the primary group ID is requested
703 * @return groupID the ID of the primary group of the user
704 */
705 public final String getPrimaryGroupIDOfUser(String userID) {
706 try {
707 MCRUser u = retrieveUser(userID);
708
709 return u.getPrimaryGroupID();
710 } catch (MCRException e) {
711 }
712
713 return null;
714 }
715
716 /**
717 * This method is used by the initialization process of the user/group
718 * system to create a starting configuration without checking the
719 * consistency of the data. It is also used when importing groups into the
720 * system.
721 *
722 * @param group
723 * The group object which should be created
724 * @param creator
725 * the creator
726 */
727 public final synchronized void initializeGroup(MCRGroup group, String creator) throws MCRException {
728 if (locked) { // This is very unlikely to happen since we are just
729
730 // initializing the system.
731 throw new MCRException("The user component is locked. At the moment write access is denied.");
732 }
733
734 if (group == null) {
735 throw new MCRException("The provided group object is null.");
736 }
737
738 if ((creator == null) || ((creator = creator.trim()).length() == 0)) {
739 throw new MCRException("The value for creator is null or empty.");
740 }
741
742 if (!group.isValid()) {
743 throw new MCRException("The data of the provided group object is not valid.");
744 }
745
746 if (mcrUserStore.existsGroup(group.getID())) {
747 throw new MCRException("The group '" + group.getID() + "' already exists!");
748 }
749
750 try {
751 mcrUserStore.createGroup(group);
752 } catch (Exception ex) {
753 throw new MCRException("Can't initalize group system.", ex);
754 }
755 }
756
757 /**
758 * This method is used by the initialization process of the user/group
759 * system to create a starting configuration without checking the
760 * consistency of the data. It is also used when importing users into the
761 * system.
762 *
763 * @param user
764 * The user object which should be created
765 * @param creator
766 * The creator
767 */
768 public final synchronized void initializeUser(MCRUser user, String creator) throws MCRException {
769 if (locked) { // This is very unlikely to happen since we are just
770
771 // initialising the system.
772 throw new MCRException("The user component is locked. At the moment write access is denied.");
773 }
774
775 if (user == null) {
776 throw new MCRException("The provided user object is null.");
777 }
778
779 if ((creator == null) || ((creator = creator.trim()).length() == 0)) {
780 throw new MCRException("The value for creator is null or empty.");
781 }
782
783 if (!user.isValid()) {
784 throw new MCRException("The data of the provided user object is not valid.");
785 }
786
787 if (mcrUserStore.existsUser(user.getNumID(), user.getID())) {
788 throw new MCRException("The user '" + user.getID() + "' or numerical ID '" + user.getNumID() + "' already exists!");
789 }
790
791 try {
792 mcrUserStore.createUser(user);
793 } catch (MCRException ex) {
794 throw new MCRException("Can't initialize user system.", ex);
795 }
796 }
797
798 /**
799 * This method imports groups and user data from XML JDOM trees. It clean
800 * the old existing user and group entries. Only the administrator of from
801 * the property file is authorized to do this command.
802 *
803 * @param groupfile
804 * the JDOM tree of the MCRGroups data input
805 * @param userfile
806 * the JDOM tree of the MCRUsers data input
807 */
808 @SuppressWarnings("unchecked")
809 public final void importUserSystemFromFiles(org.jdom.Element groups, org.jdom.Element users) throws MCRException {
810 // check authorization
811 MCRSession mcrSession = MCRSessionMgr.getCurrentSession();
812 String sessionUser = mcrSession.getCurrentUserID();
813 String propertyUser = CONFIG.getString("MCR.Users.Superuser.UserName", "administrator");
814 if (!sessionUser.equals(propertyUser)) {
815 throw new MCRException("The user " + sessionUser + " is not authorized for import the user system.");
816 }
817 // the user system should not locked
818 if (locked) {
819 throw new MCRException("The user component is locked. At the moment write access is denied.");
820 }
821 // check input for null
822 if (groups == null || users == null) {
823 throw new MCRException("The input JDOM tree is null.");
824 }
825 // clean user system
826 List<String> uids = mcrUserStore.getAllUserIDs();
827 List<String> gids = mcrUserStore.getAllGroupIDs();
828 for (int i = 0; i < uids.size(); i++) {
829 deleteUserInternal(uids.get(i));
830 }
831 for (int i = 0; i < gids.size(); i++) {
832 deleteGroupInternal(gids.get(i));
833 }
834 LOGGER.info("The user system is clean now.");
835 // load elementary group entries
836 List<Element> grouplistelm = groups.getChildren();
837 for (Element groupElement : grouplistelm) {
838 MCRGroup gin = new MCRGroup(groupElement);
839 if (!gin.isValid()) {
840 throw new MCRException("The data of the provided group object is not valid.");
841 }
842 // Check exist group
843 if (existGroup(gin.getID())) {
844 throw new MCRException("The group '" + gin.getID() + "' already exists!");
845 }
846 gin.removeAllAdminGroupID();
847 gin.removeAllAdminUserID();
848 gin.removeAllMemberUserID();
849 createGroupInternal(gin);
850 LOGGER.info("Elementary data of group " + gin.getID() + " are imported.");
851 }
852 // load user entries without encryption password
853 List<Element> listelm = users.getChildren();
854 for (Element userElement : listelm) {
855 MCRUser u = new MCRUser(userElement, false);
856 if (!u.isValid()) {
857 throw new MCRException("The data of the provided user object is not valid.");
858 }
859 // check exist group
860 if (existUser(u.getID())) {
861 throw new MCRException("The user '" + u.getID() + "' already exists!");
862 }
863 // Check if the primary group exists
864 String primarygroup = u.getPrimaryGroupID();
865 if (!existGroup(primarygroup)) {
866 throw new MCRException("The primary group of the user '" + u.getID() + "' does not exist.");
867 }
868 // Check if the groups the user will be a member of really exist
869 List<String> groupIDs = u.getGroupIDs();
870 for (int j = 0; j < groupIDs.size(); j++) {
871 if (!existGroup((String) groupIDs.get(j))) {
872 throw new MCRException("The user '" + u.getID() + "' is linked to the unknown group '" + groupIDs.get(j) + "'.");
873 }
874 }
875 // At first create the user. The user must be created before
876 // updating the groups because the existence of the user will
877 // be checked while updating the groups.
878 createUserInternal(u);
879 // now we update the primary group
880 MCRGroup primGroup = retrieveGroup(primarygroup);
881 primGroup.addMemberUserID(u.getID());
882 updateGroupInternal(primGroup);
883 // now update the other groups
884 for (int j = 0; j < groupIDs.size(); j++) {
885 MCRGroup otherGroup = retrieveGroup((String) groupIDs.get(j));
886 otherGroup.addMemberUserID(u.getID());
887 updateGroupInternal(otherGroup);
888 }
889 LOGGER.info("All data of user " + u.getID() + " are imported.");
890 }
891 // complete groups
892 for (int i = 0; i < grouplistelm.size(); i++) {
893 MCRGroup gin = new MCRGroup((org.jdom.Element) grouplistelm.get(i));
894 MCRGroup g = MCRUserMgr.instance().retrieveGroup(gin.getID());
895 // backup up creator and dates
896 g.setAdminGroupIDs(gin.getAdminGroupIDs());
897 g.setAdminUserIDs(gin.getAdminUserIDs());
898 g.setCreator(gin.getCreator());
899 g.setCreationDate(gin.getCreationDate());
900 g.setModifiedDate(gin.getModifiedDate());
901 updateGroupInternal(g);
902 LOGGER.info("All data of group " + gin.getID() + " are imported.");
903 }
904 }
905
906 /**
907 * This method checks if the user is authenticated, i.e. if he or she is in
908 * the current session.
909 *
910 * @return returns true if the user is authenticated
911 */
912 public final static boolean isAuthenticated(MCRUser user) {
913 // Get the MCRSession object for the current thread from the session
914 // manager.
915 MCRSession mcrSession = MCRSessionMgr.getCurrentSession();
916
917 String sessionUser = mcrSession.getCurrentUserID();
918
919 return (sessionUser.equals(user.getID())) ? true : false;
920 }
921
922 /**
923 * return This method returns true is if the user manager is in the locked
924 * state
925 */
926 public final boolean isLocked() {
927 return locked;
928 }
929
930 /**
931 * login to the system. This method just checks the password for a given
932 * user.
933 *
934 * @param userID
935 * user ID for the login
936 * @param passwd
937 * password for the user
938 * @return true if the password matches the password stored, false otherwise
939 */
940 public boolean login(String userID, String passwd) throws MCRException {
941 MCRUser loginUser = retrieveUser(userID, false);
942
943 if (loginUser == null) {
944 throw new MCRException("Login denied. User does not exist: " + userID);
945 }
946
947 if (loginUser.isEnabled()) {
948 if (useEncryption) {
949 String salt = loginUser.getPassword().substring(0, 3);
950 String newCrypt = MCRCrypt.crypt(salt, passwd);
951
952 return (loginUser.getPassword().equals(newCrypt));
953 }
954
955 return (loginUser.getPassword().equals(passwd));
956 }
957
958 throw new MCRException("Login denied. User is disabled.");
959 }
960
961 /**
962 * This method retrieves the group object with the given group ID.
963 *
964 * @param groupID
965 * string representing the requested group object
966 * @return MCRGroup group object (if available)
967 * @exception MCRException
968 * if group object is not known
969 */
970 public MCRGroup retrieveGroup(String groupID) throws MCRException {
971 return this.retrieveGroup(groupID, false);
972 }
973
974 /**
975 * This method first looks for a given groupID in the group cache and
976 * returns this group object. In case that the group object is not in the
977 * cache, the group will be retrieved from the database. Then the group
978 * object is put into the cache.
979 *
980 * @param groupID
981 * string representing the requested group object
982 * @param bFromDataStore
983 * boolean value, if true the group must be retrieved directly
984 * from the data store
985 * @return MCRGroup group object (if available)
986 * @exception MCRException
987 * if group object is not known
988 */
989 protected MCRGroup retrieveGroup(String groupID, boolean bFromDataStore) throws MCRException {
990 // In order to compare a modified group object with the persistent one
991 // we must
992 // be able to force this method to get the group from the store
993 MCRGroup reqGroup = bFromDataStore ? null : (MCRGroup) groupCache.get(groupID);
994
995 if (reqGroup == null) { // We do not have this group in the cache.
996 try {
997 reqGroup = mcrUserStore.retrieveGroup(groupID);
998 } catch (MCRException e) {
999 throw new MCRException("MCRUserMgr.retrieveGroup(): Unknown group '" + groupID + "'!");
1000 }
1001
1002 if (reqGroup == null) {
1003 throw new MCRException("MCRUserMgr.retrieveGroup(): Unknown group '" + groupID + "'!");
1004 }
1005
1006 groupCache.put(groupID, reqGroup);
1007 }
1008
1009 return reqGroup;
1010 }
1011
1012 /**
1013 * In the access control subsystem only IDs are stored, not references to
1014 * user or group objects. Therefore the user system must provide a method to
1015 * retrieve a set of groups according to a set of given group IDs.
1016 *
1017 * @param groupIDs
1018 * A set of group IDs for which the group objects are to be
1019 * retrieved
1020 * @return set of groups according to the given set of group IDs
1021 * @throws MCRException
1022 */
1023 public final Set<MCRGroup> retrieveGroups(Set<String> groupIDs) throws MCRException {
1024 Set<MCRGroup> groups = new HashSet<MCRGroup>();
1025 Iterator<String> iterator = groupIDs.iterator();
1026
1027 while (iterator.hasNext()) {
1028 Object object = iterator.next();
1029
1030 if (object instanceof String) {
1031 String groupid = (String) object;
1032 MCRGroup group = retrieveGroup(groupid);
1033
1034 if (group != null) {
1035 groups.add(group);
1036 }
1037 }
1038 }
1039
1040 return groups;
1041 }
1042
1043 /**
1044 * This method first retrieves the user object with the given userID.
1045 *
1046 * @param userID
1047 * string representing the requested user object
1048 * @return MCRUser user object (if available), otherwise null
1049 * @exception MCRException
1050 * if user object is not known
1051 */
1052 public MCRUser retrieveUser(String userID) throws MCRException {
1053 return this.retrieveUser(userID, false);
1054 }
1055
1056 /**
1057 * This method first looks for a given userID in the user cache and returns
1058 * this user object. In case that the user object is not in the cache, the
1059 * user will be retrieved from the database. Then the user object is put
1060 * into the cache.
1061 *
1062 * @param userID
1063 * string representing the requested user object
1064 * @param bFromDataStore
1065 * boolean value, if true the user must be retrieved directly
1066 * from the data store
1067 * @return MCRUser user object (if available), otherwise null
1068 * @exception MCRException
1069 * if user object is not known
1070 */
1071 protected MCRUser retrieveUser(String userID, boolean bFromDataStore) throws MCRException {
1072 // In order to compare a modified user object with the persistent one we
1073 // must
1074 // be able to force this method to get the user from the store
1075 MCRUser reqUser = bFromDataStore ? null : (MCRUser) userCache.get(userID);
1076
1077 if (reqUser == null) { // We do not have this user in the cache
1078
1079 try {
1080 reqUser = mcrUserStore.retrieveUser(userID);
1081 } catch (MCRException e) {
1082 LOGGER.warn(e.getMessage());
1083 throw new MCRException("user can't be found in the database");
1084 }
1085
1086 if (reqUser != null) {
1087 userCache.put(userID, reqUser);
1088 }
1089 }
1090
1091 return reqUser;
1092 }
1093
1094 /**
1095 * In the access control subsystem only IDs are stored, not references to
1096 * user or group objects. Therefore the user system must provide a method to
1097 * retrieve a set of users according to a set of given user IDs.
1098 *
1099 * @param userIDs
1100 * A set of user IDs for which the user objects are to be
1101 * retrieved
1102 * @return set of users according to the given set of user IDs
1103 * @throws MCRException
1104 */
1105 public final Set<MCRUser> retrieveUsers(Set<String> userIDs) {
1106 Set<MCRUser> users = new HashSet<MCRUser>();
1107 Iterator<String> iterator = userIDs.iterator();
1108
1109 while (iterator.hasNext()) {
1110 Object object = iterator.next();
1111
1112 if (object instanceof String) {
1113 String userid = (String) object;
1114 MCRUser user = retrieveUser(userid, false);
1115
1116 if (user != null) {
1117 users.add(user);
1118 }
1119 }
1120 }
1121
1122 return users;
1123 }
1124
1125 /**
1126 * This method sets the lock-status of the user manager.
1127 *
1128 * @param locked
1129 * flag that determines whether write access to the data is
1130 * denied (true) or allowed
1131 */
1132 public final synchronized void setLock(boolean locked) {
1133 // Check the permissions
1134 if (!MCRAccessManager.checkPermission("administrate-user")) {
1135 throw new MCRException("The current user does not have the permission to 'administrate-user'!");
1136 }
1137
1138 this.locked = locked;
1139 if (locked)
1140 LOGGER.info("Write access to the user component persistent database now is denied.");
1141 else
1142 LOGGER.info("Write access to the user component persistent database now is allowed.");
1143 }
1144
1145 /**
1146 * This method sets a new password for the given user.
1147 *
1148 * @param userID
1149 * the userID
1150 * @param password
1151 * the user password
1152 */
1153 public final void setPassword(String userID, String password) throws MCRException {
1154 // check for empty strings
1155 if ((userID == null) || ((userID = userID.trim()).length() == 0)) {
1156 throw new MCRException("The userID is null or empty!");
1157 }
1158
1159 if ((password == null) || ((password = password.trim()).length() == 0)) {
1160 throw new MCRException("The password is null or empty!");
1161 }
1162
1163 // Check permissions
1164 MCRSession session = MCRSessionMgr.getCurrentSession();
1165 MCRUser user = retrieveUser(userID, false);
1166 if (user == null) {
1167 throw new MCRException("Cant find user with ID " + userID + "!");
1168 }
1169
1170 if (!user.isUpdateAllowed()) {
1171 throw new MCRException("The update for the user " + userID + " is not allowed!");
1172 }
1173
1174 boolean test = false;
1175
1176 if (session.getCurrentUserID().equals(userID)) {
1177 test = true;
1178 } else {
1179 if (MCRAccessManager.checkPermission("administrate-user")) {
1180 test = true;
1181 }
1182 }
1183
1184 if (!test) {
1185 throw new MCRException("You have no rights to change the users password!");
1186 }
1187
1188 if (useEncryption) {
1189 user.setPassword(MCRCrypt.crypt(password));
1190 } else {
1191 user.setPassword(password);
1192 }
1193
1194 userCache.remove(userID);
1195 mcrUserStore.updateUser(user);
1196 LOGGER.info("The new password was set.");
1197 }
1198
1199 /**
1200 * This method updates a group in the datastore (and the cache as well).
1201 *
1202 * @param updGroup
1203 * The group object which will be updated
1204 */
1205 public final void updateGroup(MCRGroup updGroup) throws MCRException {
1206 if (locked) {
1207 throw new MCRException("The user component is locked. At the moment write access is denied.");
1208 }
1209 // Check the permission
1210 if (!MCRAccessManager.checkPermission("modify-group")) {
1211 throw new MCRException("The current user does not have the permission to modify this group!");
1212 }
1213 updateGroupInternal(updGroup);
1214 }
1215
1216 /**
1217 * This method is internal for update groups.
1218 *
1219 * @param updGroup
1220 * The group object which will be updated
1221 */
1222 private final synchronized void updateGroupInternal(MCRGroup updGroup) throws MCRException {
1223 // check that the updGroup is valid
1224 if (updGroup == null) {
1225 throw new MCRException("The provided group object is null!");
1226 }
1227
1228 if (!updGroup.isValid()) {
1229 throw new MCRException("The provided group object is not valid.");
1230 }
1231
1232 // check that the group which shall be updated really exists
1233 String groupID = updGroup.getID();
1234
1235 if (!mcrUserStore.existsGroup(groupID)) {
1236 throw new MCRException("You tried to update the unknown group '" + groupID + "'.");
1237 }
1238
1239 try {
1240 // get the group directly from the datastore
1241 MCRGroup oldGroup = retrieveGroup(groupID, true);
1242
1243 // At first we check that admins or members or permissions which may
1244 // be added to this
1245 // group really exist at all. Because this is not a performance
1246 // issue, we simply
1247 // check that all members etc. exist. This should be improved later.
1248 // We look for newly
1249 // added admin users in this group:
1250 for (int i = 0; i < updGroup.getAdminUserIDs().size(); i++) {
1251 String userID = (String) updGroup.getAdminUserIDs().get(i);
1252 if (!mcrUserStore.existsUser(userID)) {
1253 throw new MCRException("You tried to add the unknown admin user '" + userID + "' to the group '" + groupID + "'.");
1254 }
1255 }
1256
1257 // We look for newly added admin groups in this group:
1258 for (int i = 0; i < updGroup.getAdminGroupIDs().size(); i++) {
1259 String gid = (String) updGroup.getAdminGroupIDs().get(i);
1260 if (!mcrUserStore.existsGroup(gid)) {
1261 throw new MCRException("You tried to add the unknown admin group '" + gid + "' to the group '" + groupID + "'.");
1262 }
1263 }
1264
1265 // We look for newly added member users in this group:
1266 for (int i = 0; i < updGroup.getMemberUserIDs().size(); i++) {
1267 String userID = (String) updGroup.getMemberUserIDs().get(i);
1268 if (!mcrUserStore.existsUser(userID)) {
1269 throw new MCRException("You tried to add the unknown member user '" + userID + "' to the group '" + groupID + "'.");
1270 }
1271 }
1272
1273 // Some values are taken from the old version, they cannot be
1274 // updated. Then we
1275 // really update the object in the datastore.
1276 updGroup.setCreationDate(oldGroup.getCreationDate());
1277 updGroup.setCreator(oldGroup.getCreator());
1278 mcrUserStore.updateGroup(updGroup);
1279 groupCache.remove(groupID);
1280 groupCache.put(groupID, updGroup);
1281
1282 // We finally look again for recently added and deleted members
1283 // (users). If
1284 // so, we do not have to notify them, since the users and groups get
1285 // their membership
1286 // information when they are constructed from the datastore.
1287 // However, we have to remove
1288 // them from the user or group cache so that they will be retrieved
1289 // from the datastore.
1290 for (int i = 0; i < oldGroup.getMemberUserIDs().size(); i++) {
1291 if (!updGroup.getMemberUserIDs().contains(oldGroup.getMemberUserIDs().get(i))) {
1292 userCache.remove(oldGroup.getMemberUserIDs().get(i));
1293 }
1294 }
1295
1296 for (int i = 0; i < updGroup.getMemberUserIDs().size(); i++) {
1297 if (!oldGroup.getMemberUserIDs().contains(updGroup.getMemberUserIDs().get(i))) {
1298 userCache.remove(updGroup.getMemberUserIDs().get(i));
1299 }
1300 }
1301 } catch (MCRException ex) {
1302 throw new MCRException("Error while updating group " + updGroup.getID(), ex);
1303 }
1304 }
1305
1306 /**
1307 * This method updates a user in the datastore (and the cache as well).
1308 *
1309 * @param updUser
1310 * The user object which will be updated
1311 */
1312 public final synchronized void updateUser(MCRUser updUser) throws MCRException {
1313 if (locked) {
1314 throw new MCRException("The user component is locked. At the moment write access is denied.");
1315 }
1316
1317 // Check the permissions
1318 if (!MCRAccessManager.checkPermission("modify-user") && !MCRAccessManager.checkPermission("modify-contact")) {
1319 throw new MCRException("The current user does not have the permission to modify this user!");
1320 }
1321
1322 // Check that the provided user object is valid
1323 if (updUser == null) {
1324 throw new MCRException("The provided user object is null!");
1325 }
1326
1327 if (!updUser.isValid()) {
1328 throw new MCRException("The provided user object is not valid.");
1329 }
1330
1331 // Check that the user exists
1332 if (!mcrUserStore.existsUser(updUser.getID())) {
1333 throw new MCRException("You tried to update the unknown user '" + updUser.getID() + "'.");
1334 }
1335
1336 try {
1337 // get the user directly from the datastore
1338 MCRUser oldUser = mcrUserStore.retrieveUser(updUser.getID());
1339
1340 // We have to check whether the membership to some of the groups of
1341 // this user changed.
1342 // For example, the user might be removed from one of the groups he
1343 // or she was
1344 // a member of. This group must be notified! To get information
1345 // about which groups
1346 // have been added or removed, we compare the current (updated) user
1347 // object with
1348 // the one from the datastore before the update process takes place.
1349 update(updUser, oldUser);
1350
1351 // Now we come back to the primary group.
1352 if (!updUser.getPrimaryGroupID().equals(oldUser.getPrimaryGroupID())) {
1353 MCRGroup primGroup = retrieveGroup(oldUser.getPrimaryGroupID());
1354 primGroup.removeMemberUserID(oldUser.getID());
1355 this.updateGroup(primGroup);
1356 primGroup = retrieveGroup(updUser.getPrimaryGroupID());
1357 primGroup.addMemberUserID(updUser.getID());
1358 this.updateGroup(primGroup);
1359 }
1360
1361 // Some values are taken from the old version, they cannot be
1362 // updated. Then we
1363 // really update the object in the datastore.
1364 updUser.setCreationDate(oldUser.getCreationDate());
1365 updUser.setCreator(oldUser.getCreator());
1366 mcrUserStore.updateUser(updUser);
1367 userCache.remove(updUser.getID());
1368 userCache.put(updUser.getID(), updUser);
1369 } catch (MCRException ex) {
1370 try {
1371 deleteUser(updUser.getID());
1372 } catch (MCRException e) {
1373 }
1374
1375 throw new MCRException("Error while updating user " + updUser.getID() + ", the user has been deleted.");
1376 }
1377 }
1378
1379 /**
1380 * This method updates groups where a given user is a new member of or is no
1381 * longer a member of, respectively. The groups are determined by comparing
1382 * the user to be updated with the version out of the datastore, i.e. before
1383 * the update request.
1384 *
1385 * @param updObject
1386 * The user object which is to be updated
1387 * @param oldObject
1388 * The same user object as it was before the update request.
1389 */
1390 private final void update(MCRUser updUser, MCRUser oldUser) throws MCRException {
1391 // It is important to first check whether *all* groups where the current
1392 // object is a new member of
1393 // exist at all. Furthermore it is very important that the current user
1394 // (session) has the right
1395 // to update the groups. Hence we must check this, too. If something
1396 // goes wrong here an exception
1397 // will be thrown and we do not have to care about a rollback of data
1398 // already modified. Hence do
1399 // not combine the following two loops!
1400 String ID = updUser.getID();
1401
1402 for (int i = 0; i < updUser.getGroupIDs().size(); i++) {
1403 String gid = (String) updUser.getGroupIDs().get(i);
1404
1405 if (!mcrUserStore.existsGroup(gid)) {
1406 StringBuffer msg = new StringBuffer("You tried to update ");
1407 msg.append((updUser instanceof MCRUser) ? "user '" : "group '").append(ID).append("' with the unknown group '").append(gid)
1408 .append("'.");
1409 throw new MCRException(msg.toString());
1410 }
1411 }
1412
1413 // update groups where this User is a new member of
1414 for (int i = 0; i < updUser.getGroupIDs().size(); i++) {
1415 MCRGroup updGroup = retrieveGroup((String) updUser.getGroupIDs().get(i));
1416
1417 if (!oldUser.getGroupIDs().contains(updGroup.getID())) {
1418 updGroup.addMemberUserID(ID);
1419 this.updateGroup(updGroup);
1420 }
1421 }
1422
1423 // update groups where this object is no longer a member of
1424 for (int i = 0; i < oldUser.getGroupIDs().size(); i++) {
1425 MCRGroup updGroup = retrieveGroup((String) oldUser.getGroupIDs().get(i));
1426
1427 if (!updUser.getGroupIDs().contains(updGroup.getID())) {
1428 // The object is no longer member of this group
1429 updGroup.removeMemberUserID(ID);
1430 this.updateGroup(updGroup);
1431 }
1432 }
1433 }
1434
1435 /**
1436 * This method enables the user.
1437 *
1438 * @param userID
1439 * The user object which will be enabled
1440 * @param flag
1441 * the enable/disable flag
1442 */
1443 private final void enable(String userID, boolean flag) throws MCRException {
1444 if (locked) {
1445 throw new MCRException("The user component is locked. At the moment write access is denied.");
1446 }
1447
1448 // Check the permissions
1449 if (!MCRAccessManager.checkPermission("administrate-user")) {
1450 throw new MCRException("The session does not have the permission 'administrate-user'!");
1451 }
1452
1453 if (userID == null) {
1454 throw new MCRException("The userID String is null!");
1455 }
1456
1457 // check that the user exists
1458 if (!mcrUserStore.existsUser(userID)) {
1459 throw new MCRException("You tried to update the unknown user '" + userID + "'.");
1460 }
1461
1462 try {
1463 MCRUser olduser = mcrUserStore.retrieveUser(userID);
1464 olduser.setEnabled(flag);
1465 olduser.setModifiedDate();
1466 userCache.remove(olduser.getID());
1467 mcrUserStore.updateUser(olduser);
1468 } catch (MCRException ex) {
1469 throw new MCRException("Error while updating user " + userID);
1470 }
1471 }
1472
1473 /**
1474 * The method check that a group entry exists.
1475 *
1476 * @param group
1477 * the group name as String
1478 * @return true if the group exists, else return false
1479 */
1480 public final boolean existGroup(String group) {
1481 if (group == null)
1482 return false;
1483 return mcrUserStore.existsGroup(group);
1484 }
1485
1486 /**
1487 * The method check that an user entry exists.
1488 *
1489 * @param user
1490 * the user name as String
1491 * @return true if the user exists, else return false
1492 */
1493 public final boolean existUser(String user) {
1494 if (user == null)
1495 return false;
1496 return mcrUserStore.existsUser(user);
1497 }
1498 }