001/*
002 $Id: User.java 4464 2013-05-02 10:40:11Z olle $
003
004 Copyright (C) 2006 Gregory Vincic, Olle Mansson
005 Copyright (C) 2007 Gregory Vincic
006
007 This file is part of Proteios.
008 Available at http://www.proteios.org/
009
010 Proteios is free software; you can redistribute it and/or modify it
011 under the terms of the GNU General Public License as published by
012 the Free Software Foundation; either version 2 of the License, or
013 (at your option) any later version.
014
015 Proteios is distributed in the hope that it will be useful, but
016 WITHOUT ANY WARRANTY; without even the implied warranty of
017 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
018 General Public License for more details.
019
020 You should have received a copy of the GNU General Public License
021 along with this program; if not, write to the Free Software
022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
023 02111-1307, USA.
024 */
025package org.proteios.core;
026
027import org.proteios.core.data.DirectoryData;
028import org.proteios.core.data.OwnableData;
029import org.proteios.core.data.UserData;
030import org.proteios.core.query.EntityQuery;
031import org.proteios.core.query.Hql;
032import org.proteios.core.query.Restrictions;
033import org.proteios.util.MD5;
034import java.security.Principal;
035import java.util.Collections;
036import java.util.Date;
037import java.util.Set;
038
039/**
040 * This class is used to represent a user in Proteios.
041 * 
042 * @author Nicklas
043 * @version 2.0
044 * @base.modified $Date: 2013-05-02 12:40:11 +0200 (Thu, 02 May 2013) $
045 */
046public class User
047                extends BasicItem<UserData>
048                implements Nameable, Removable, SystemItem, Principal
049{
050        /**
051         * The type of item represented by this class.
052         * 
053         * @see Item#USER
054         * @see #getType()
055         */
056        public static final Item TYPE = Item.USER;
057        /**
058         * The system id for the <code>User</code> representing the root account.
059         * The root user has full access to everything in Proteios.
060         */
061        public static final String ROOT = "org.proteios.core.User.ROOT";
062        /**
063         * This filter will limit a query to only return users which are members of
064         * at least one of the groups where thelogged in user is a member unless the
065         * logged in user has generic read permission.
066         */
067        private static final QueryRuntimeFilter RUNTIME_FILTER = new QueryRuntimeFilterImpl();
068
069
070        /**
071         * Get a <code>User</code> item when you know the ID.
072         * 
073         * @param dc The <code>DbControl</code> which will be used for permission
074         *        checking and database access.
075         * @param id The ID of the item to load
076         * @return The <code>User</code> item
077         * @throws ItemNotFoundException If an item with the specified ID is not
078         *         found
079         * @throws PermissionDeniedException If the logged in user doesn't have
080         *         {@link Permission#READ} permission to the item
081         * @throws BaseException If there is another error
082         */
083        public static User getById(DbControl dc, int id)
084                        throws ItemNotFoundException, PermissionDeniedException,
085                        BaseException
086        {
087                User u = dc.loadItem(User.class, id);
088                if (u == null)
089                        throw new ItemNotFoundException("User[id=" + id + "]");
090                return u;
091        }
092
093
094        /**
095         * Get a query configured to retrieve users. If the logged in user doesn't
096         * have generic permission to all users, only users that are members in at
097         * least one group where the logged in user is also a member are returned.
098         * The <code>Everyone</code> group is not considered since all users
099         * automatically are members to that group.
100         * 
101         * @return An {@link ItemQuery} object
102         */
103        public static ItemQuery<User> getQuery()
104        {
105                return new ItemQuery<User>(User.class, RUNTIME_FILTER);
106        }
107
108
109        User(UserData userData)
110        {
111                super(userData);
112        }
113
114
115        /*
116         * From the Identifiable interface
117         * -------------------------------------------
118         */
119        public Item getType()
120        {
121                return TYPE;
122        }
123
124
125        // -------------------------------------------
126        /*
127         * From the Nameable interface -------------------------------------------
128         */
129        public String getName()
130        {
131                return getData().getName();
132        }
133
134
135        public void setName(String name)
136                        throws PermissionDeniedException, InvalidDataException
137        {
138                checkPermission(Permission.WRITE);
139                NameableUtil.setName(getData(), name);
140        }
141
142
143        public String getDescription()
144        {
145                return getData().getDescription();
146        }
147
148
149        public void setDescription(String description)
150                        throws PermissionDeniedException, InvalidDataException
151        {
152                checkPermission(Permission.RESTRICTED_WRITE);
153                NameableUtil.setDescription(getData(), description);
154        }
155
156
157        // -------------------------------------------
158        /*
159         * From the Removable interface -------------------------------------------
160         */
161        public boolean isRemoved()
162        {
163                return getData().isRemoved();
164        }
165
166
167        public void setRemoved(boolean removed)
168                        throws PermissionDeniedException
169        {
170                checkPermission(removed ? Permission.DELETE : Permission.WRITE);
171                getData().setRemoved(removed);
172        }
173
174
175        // -------------------------------------------
176        /*
177         * From the SystemItem interface -------------------------------------------
178         */
179        public String getSystemId()
180        {
181                return getData().getSystemId();
182        }
183
184
185        public boolean isSystemItem()
186        {
187                return getSystemId() != null;
188        }
189
190
191        // -------------------------------------------
192        /*
193         * From the BasicItem class -------------------------------------------
194         */
195        /**
196         * Checks if:
197         * <ul>
198         * <li>any {@link Ownable} item is owned by this user
199         * </ul>
200         * A user can also be referenced from groups, roles, projects, item keys,
201         * sessions and settings, but those references are automatically deleted if
202         * the user is deleted and aren't inclued in this check.
203         */
204        @Override
205        public boolean isUsed()
206                        throws BaseException
207        {
208                org.hibernate.Session session = getDbControl().getHibernateSession();
209                org.hibernate.Query query = HibernateUtil.getPredefinedQuery(session,
210                        "GET_OWNABLE_ITEMS_FOR_USER");
211                /*
212                 * SELECT o FROM org.proteios.core.data.OwnableData o WHERE o.owner =
213                 * :user
214                 */
215                query.setEntity("user", this.getData());
216                return HibernateUtil.loadData(OwnableData.class, query) != null;
217        }
218
219
220        /**
221         * If the logged in user is the same as this user RESTRICTED_WRITE
222         * permissions is granted, unless it is a multiuser account. If this is a
223         * system user, delete and create permissions are revoked. Finally READ
224         * permission is granted to if the user is a member of at least one group
225         * where the logged in user is also a member.
226         */
227        @Override
228        void initPermissions(int granted, int denied)
229                        throws BaseException
230        {
231                if (isSystemItem())
232                {
233                        denied |= Permission.deny(Permission.DELETE, Permission.CREATE);
234                }
235                if (getSessionControl().getLoggedInUserId() == getId())
236                {
237                        granted |= Permission
238                                .grant(isMultiuserAccount() ? Permission.READ : Permission.RESTRICTED_WRITE);
239                }
240                if (getSessionControl().isFriendOf(this))
241                {
242                        granted |= Permission.grant(Permission.READ);
243                }
244                super.initPermissions(granted, denied);
245        }
246
247
248        // -------------------------------------------
249        /**
250         * Checks a string against the stored password.
251         * 
252         * @param testString String The string to test against the stored password.
253         * @return boolean Returns true if the string equals the password, otherwise false.
254         */
255        public boolean checkAgainstStoredPassword(String testString)
256                        throws PermissionDeniedException
257        {
258                checkPermission(Permission.READ);
259                if (testString == null)
260                {
261                        return false;
262                }
263                boolean result = false;
264                String md5PasswordStored = getData().getPassword().getMd5Password();
265                if (md5PasswordStored != null)
266                {
267                        result = md5PasswordStored.equals(MD5.getHashString(testString));
268                }
269                return result;
270        }
271
272
273        /**
274         * Set the password. A null password is not allowed.
275         * 
276         * @throws PermissionDeniedException If the logged in user doesn't have
277         *         restricted_write permission
278         * @throws InvalidDataException If the new password is null
279         */
280        public void setPassword(String password)
281                        throws PermissionDeniedException, InvalidDataException
282        {
283                checkPermission(Permission.RESTRICTED_WRITE);
284                if (password == null)
285                        throw new InvalidUseOfNullException("password");
286                getData().getPassword().setMd5Password(MD5.getHashString(password));
287        }
288
289
290        /**
291         * Set the encrypted password from Proteios 1. This method is only intended
292         * to be used from the migration application, and will throw a
293         * {@link PermissionDeniedException} unless the logged in user is the root
294         * and the user account is a newly created account.
295         * 
296         * @param md5Password The MD5 password from a Proteios 1 installation
297         * @throws PermissionDeniedException If it is not a new user or root isn't
298         *         logged in
299         */
300        public void setBase1Password(String md5Password)
301                        throws PermissionDeniedException, BaseException
302        {
303                if (isInDatabase() || (SystemItems.getId(User.ROOT) != getSessionControl()
304                        .getLoggedInUserId()))
305                {
306                        throw new PermissionDeniedException(Permission.WRITE,
307                                "Password[login=" + getLogin() + "]");
308                }
309                getData().getPassword().setMd5Password(md5Password);
310        }
311
312
313        /**
314         * Get the expire date of the account. When the expiration date have been
315         * passed the user can't login. A null value indicates that the account will
316         * never expire.
317         */
318        public Date getExpirationDate()
319        {
320                return DateUtil.copy(getData().getExpirationDate());
321        }
322
323
324        /**
325         * Sets the expiration date of the account. A null value indicates that the
326         * account will never expire.
327         * 
328         * @throws PermissionDeniedException If the logged in user doesn't have
329         *         write permission
330         */
331        public void setExpirationDate(Date expirationDate)
332                        throws PermissionDeniedException
333        {
334                checkPermission(Permission.WRITE);
335                getData().setExpirationDate(
336                        DateUtil.setNullableDate(expirationDate, "expirationDate"));
337        }
338
339
340        /**
341         * Check if this account has been disabled. It is not possible to login if
342         * the account is disabled.
343         * 
344         * @return TRUE if the account is disabled, FALSE otherwise
345         */
346        public boolean isDisabled()
347        {
348                return getData().isDisabled();
349        }
350
351
352        /**
353         * Disables or enables the account.
354         * 
355         * @param disabled TRUE to disabled the account, FALSE to enabled it
356         * @throws PermissionDeniedException If the logged in user doesn't have
357         *         write permission
358         * @see #isDisabled()
359         */
360        public void setDisabled(boolean disabled)
361                        throws PermissionDeniedException
362        {
363                checkPermission(Permission.WRITE);
364                getData().setDisabled(disabled);
365        }
366
367
368        /**
369         * Check if the user account is a multiuser account or not. Multiuser
370         * accounts don't have write permissions for contact information and
371         * settings.
372         * 
373         * @return TRUE if the user account is a multiuser account, FALSE otherwise
374         */
375        public boolean isMultiuserAccount()
376        {
377                return getData().isMultiuserAccount();
378        }
379
380
381        /**
382         * Sets if the user account is multiuser account.
383         * 
384         * @throws PermissionDeniedException If the logged in user doesn't have
385         *         write permission
386         */
387        public void setMultiuserAccount(boolean multiuserAccount)
388                        throws PermissionDeniedException
389        {
390                checkPermission(Permission.WRITE);
391                getData().setMultiuserAccount(multiuserAccount);
392        }
393
394        /**
395         * The maximum length of the external ID that can be stored in the database.
396         * 
397         * @see #setExternalId(String)
398         */
399        public static final int MAX_EXTERNAL_ID_LENGTH = UserData.MAX_EXTERNAL_ID_LENGTH;
400
401
402        /**
403         * Get the external id for the user account. The external id is intended to
404         * be used by external applications which need to synchronize data between
405         * the Proteios database and some external database. It is not used by the
406         * core.
407         */
408        public String getExternalId()
409        {
410                return getData().getExternalId();
411        }
412
413
414        /**
415         * Set the external id for the user account.
416         * 
417         * @throws PermissionDeniedException If the logged in user doesn't have
418         *         write permission
419         * @throws InvalidDataException If the new value is longer than
420         *         {@link #MAX_EXTERNAL_ID_LENGTH}
421         * @throws BaseException If there is another error
422         */
423        public void setExternalId(String externalId)
424                        throws PermissionDeniedException, InvalidDataException,
425                        BaseException
426        {
427                checkPermission(Permission.WRITE);
428                getData().setExternalId(
429                        StringUtil.setNullableString(externalId, "externalId",
430                                MAX_EXTERNAL_ID_LENGTH));
431        }
432
433        /**
434         * The maximum length of the login that can be stored in the database.
435         * 
436         * @see #setLogin(String)
437         */
438        public static final int MAX_LOGIN_LENGTH = UserData.MAX_LOGIN_LENGTH;
439
440
441        /**
442         * Get the login for the user account.
443         */
444        public String getLogin()
445        {
446                return getData().getLogin();
447        }
448
449
450        /**
451         * Set the login for the user account.
452         * 
453         * @throws PermissionDeniedException If the logged in user doesn't have
454         *         write permission
455         * @throws InvalidDataException If the new value is null or longer than
456         *         {@link #MAX_LOGIN_LENGTH}
457         */
458        public void setLogin(String login)
459                        throws PermissionDeniedException, InvalidDataException
460        {
461                checkPermission(Permission.WRITE);
462                getData().setLogin(
463                        StringUtil.setNotNullString(login, "login", MAX_LOGIN_LENGTH));
464        }
465
466        /**
467         * The maximum length of the organisation that can be stored in the
468         * database.
469         * 
470         * @see #setOrganisation(String)
471         */
472        public static final int MAX_ORGANISATION_LENGTH = UserData.MAX_ORGANISATION_LENGTH;
473
474
475        /**
476         * Get the organisation this user works for, or null if unknown.
477         */
478        public String getOrganisation()
479        {
480                return getData().getOrganisation();
481        }
482
483
484        /**
485         * Set the organisation this user works for, or null if unknown.
486         * 
487         * @throws PermissionDeniedException If the logged in user doesn't have
488         *         restricted write permission
489         * @throws InvalidDataException If the new value is longer than
490         *         {@link #MAX_ORGANISATION_LENGTH}
491         */
492        public void setOrganisation(String organisation)
493                        throws PermissionDeniedException, InvalidDataException
494        {
495                checkPermission(Permission.RESTRICTED_WRITE);
496                getData().setOrganisation(
497                        StringUtil.setNullableString(organisation, "organisation",
498                                MAX_ORGANISATION_LENGTH));
499        }
500
501        /**
502         * The maximum length of the address that can be stored in the database.
503         * 
504         * @see #setAddress(String)
505         */
506        public static final int MAX_ADDRESS_LENGTH = UserData.MAX_ADDRESS_LENGTH;
507
508
509        /**
510         * Get the address for the user, or null if unknown.
511         */
512        public String getAddress()
513        {
514                return getData().getAddress();
515        }
516
517
518        /**
519         * Set the address for the user, or null if unknown.
520         * 
521         * @throws PermissionDeniedException If the logged in user doesn't have
522         *         write permission
523         * @throws InvalidDataException If the new value is longer than
524         *         {@link #MAX_ADDRESS_LENGTH}
525         */
526        public void setAddress(String address)
527                        throws PermissionDeniedException, InvalidDataException
528        {
529                checkPermission(Permission.RESTRICTED_WRITE);
530                getData().setAddress(
531                        StringUtil
532                                .setNullableString(address, "address", MAX_ADDRESS_LENGTH));
533        }
534
535        /**
536         * The maximum length of the phone that can be stored in the database.
537         * 
538         * @see #setPhone(String)
539         */
540        public static final int MAX_PHONE_LENGTH = UserData.MAX_PHONE_LENGTH;
541
542
543        /**
544         * Get the phone number to the user, or null if unknown.
545         */
546        public String getPhone()
547        {
548                return getData().getPhone();
549        }
550
551
552        /**
553         * Set the phone number to the user, or null if unknown.
554         * 
555         * @throws PermissionDeniedException If the logged in user doesn't have
556         *         write permission
557         * @throws InvalidDataException If the new value is longer than
558         *         {@link #MAX_PHONE_LENGTH}
559         */
560        public void setPhone(String phone)
561                        throws PermissionDeniedException, InvalidDataException
562        {
563                checkPermission(Permission.RESTRICTED_WRITE);
564                getData().setPhone(
565                        StringUtil.setNullableString(phone, "phone", MAX_PHONE_LENGTH));
566        }
567
568        /**
569         * The maximum length of the fax that can be stored in the database.
570         * 
571         * @see #setFax(String)
572         */
573        public static final int MAX_FAX_LENGTH = UserData.MAX_FAX_LENGTH;
574
575
576        /**
577         * Get the fax number to the user, or null if unknown.
578         */
579        public String getFax()
580        {
581                return getData().getFax();
582        }
583
584
585        /**
586         * Set the fax number to the user, or null if unknown.
587         * 
588         * @throws PermissionDeniedException If the logged in user doesn't have
589         *         write permission
590         * @throws InvalidDataException If the new value is longer than
591         *         {@link #MAX_FAX_LENGTH}
592         */
593        public void setFax(String fax)
594                        throws PermissionDeniedException, InvalidDataException
595        {
596                checkPermission(Permission.RESTRICTED_WRITE);
597                getData().setFax(
598                        StringUtil.setNullableString(fax, "fax", MAX_FAX_LENGTH));
599        }
600
601        /**
602         * The maximum length of the email address that can be stored in the
603         * database.
604         * 
605         * @see #setEmail(String)
606         */
607        public static final int MAX_EMAIL_LENGTH = UserData.MAX_EMAIL_LENGTH;
608
609
610        /**
611         * Get the email address to the user, or null if unknown.
612         */
613        public String getEmail()
614        {
615                return getData().getEmail();
616        }
617
618
619        /**
620         * Set the email address to the user, or null if unknown.
621         * 
622         * @throws PermissionDeniedException If the logged in user doesn't have
623         *         write permission
624         * @throws InvalidDataException If the new value is longer than
625         *         {@link #MAX_EMAIL_LENGTH}
626         */
627        public void setEmail(String email)
628                        throws PermissionDeniedException, InvalidDataException
629        {
630                checkPermission(Permission.RESTRICTED_WRITE);
631                getData().setEmail(
632                        StringUtil.setNullableString(email, "email", MAX_EMAIL_LENGTH));
633        }
634
635        /**
636         * The maximum length of the url that can be stored in the database.
637         * 
638         * @see #setUrl(String)
639         */
640        public static final int MAX_URL_LENGTH = UserData.MAX_URL_LENGTH;
641
642
643        /**
644         * Get the URL to the user's homepage, or null if unknown.
645         */
646        public String getUrl()
647        {
648                return getData().getUrl();
649        }
650
651
652        /**
653         * Set the URL to the user's homepage, or null if unknown.
654         * 
655         * @throws PermissionDeniedException If the logged in user doesn't have
656         *         write permission
657         * @throws InvalidDataException If the new value is longer than
658         *         {@link #MAX_URL_LENGTH}
659         */
660        public void setUrl(String url)
661                        throws PermissionDeniedException, InvalidDataException
662        {
663                checkPermission(Permission.RESTRICTED_WRITE);
664                getData().setUrl(
665                        StringUtil.setNullableString(url, "url", MAX_URL_LENGTH));
666        }
667
668
669        /**
670         * Get the {@link Quota} that applies to the user.
671         * 
672         * @return A <code>Quota</code> item
673         * @throws PermissionDeniedException If the logged in user doesn't have
674         *         {@link Permission#READ} permission to the item
675         */
676        public Quota getQuota()
677                        throws PermissionDeniedException, BaseException
678        {
679                return getDbControl().getItem(Quota.class, getData().getQuota());
680        }
681
682
683        /**
684         * Set the quota for the user.
685         * 
686         * @param quota The new <code>Quota</code>
687         * @throws InvalidDataException If the quota is null
688         * @throws PermissionDeniedException If the logged in user doesn't have
689         *         {@link Permission#WRITE} permission for the user or
690         *         {@link Permission#USE} permission for the quota
691         */
692        public void setQuota(Quota quota)
693                        throws PermissionDeniedException, InvalidDataException
694        {
695                checkPermission(Permission.WRITE);
696                if (quota == null)
697                        throw new InvalidUseOfNullException("quota");
698                quota.checkPermission(Permission.USE);
699                getData().setQuota(quota.getData());
700        }
701
702
703        /**
704         * Get the {@link Group} whose {@link Quota} also applies to the user.
705         * 
706         * @return A <code>Group</code> item, or null if no group has been
707         *         specified
708         * @throws PermissionDeniedException If the logged in user doesn't have
709         *         {@link Permission#READ} permission to the item
710         */
711        public Group getQuotaGroup()
712                        throws PermissionDeniedException, BaseException
713        {
714                return getDbControl().getItem(Group.class, getData().getQuotaGroup());
715        }
716
717
718        /**
719         * Set the group whose quota should be checked for disk consuming items.
720         * 
721         * @param quotaGroup The new <code>Group</code>
722         * @throws PermissionDeniedException If the logged in user doesn't have
723         *         {@link Permission#WRITE} permission for the user or
724         *         {@link Permission#USE} permission for the group
725         */
726        public void setQuotaGroup(Group quotaGroup)
727                        throws PermissionDeniedException
728        {
729                checkPermission(Permission.WRITE);
730                if (quotaGroup != null)
731                        quotaGroup.checkPermission(Permission.USE);
732                getData().setQuotaGroup(
733                        quotaGroup == null ? null : quotaGroup.getData());
734        }
735
736
737        /**
738         * Get the used number of bytes for the specified quota type and location.
739         * 
740         * @param quotaType The {@link QuotaType}
741         * @param location The location
742         * @return The number of bytes that have been used
743         */
744        public long getDiskUsage(QuotaType quotaType, Location location)
745                        throws BaseException
746        {
747                if (quotaType == null)
748                        throw new InvalidUseOfNullException("quotaType");
749                if (location == null)
750                        throw new InvalidUseOfNullException("location");
751                return getDbControl().getDiskUsage(getData(), quotaType.getData(),
752                        location);
753        }
754
755
756        /**
757         * Get the home {@link Directory} for this user.
758         * 
759         * @return A <code>Directory</code> item, or null if no home directory has
760         *         been specified
761         * @throws PermissionDeniedException If the logged in user doesn't have
762         *         {@link Permission#READ} permission to the directory
763         */
764        public Directory getHomeDirectory()
765                        throws PermissionDeniedException, BaseException
766        {
767                return getDbControl().getItem(Directory.class,
768                        getData().getHomeDirectory());
769        }
770
771
772        /**
773         * Set the home directory for the user.
774         * 
775         * @param homeDirectory The new home <code>Directory</code>
776         * @throws PermissionDeniedException If the logged in user doesn't have
777         *         {@link Permission#WRITE} permission for the user or
778         *         {@link Permission#USE} permission for the directory
779         * @throws InvalidDataException If the home directory is not a subdirectory
780         *         to /root/home
781         */
782        public void setHomeDirectory(Directory homeDirectory)
783                        throws PermissionDeniedException, InvalidDataException
784        {
785                checkPermission(Permission.WRITE);
786                if (homeDirectory != null)
787                {
788                        homeDirectory.checkPermission(Permission.USE);
789                        DirectoryData parent = homeDirectory.getData().getParent();
790                        if (parent == null || parent.getId() != SystemItems
791                                .getId(Directory.HOME))
792                        {
793                                throw new InvalidDataException(
794                                        "homeDirectory is not a subdirectory to /root/home");
795                        }
796                }
797                getData().setHomeDirectory(
798                        homeDirectory == null ? null : homeDirectory.getData());
799        }
800
801
802        /**
803         * Get a query that returns the roles where this user is a member. The query
804         * excludes roles that the logged in user doesn't have permission to read.
805         * 
806         * @see Role#getQuery()
807         */
808        public ItemQuery<Role> getRoles()
809        {
810                ItemQuery<Role> query = Role.getQuery();
811                query.joinPermanent(Hql.innerJoin("users", Item.USER.getAlias()));
812                query.restrictPermanent(Restrictions.eq(
813                        Hql.alias(Item.USER.getAlias()), Hql.entity(this)));
814                return query;
815        }
816
817
818        /**
819         * Get a query that returns the groups where this user is a member. The
820         * query excludes groups that the logged in user doesn't have permission to
821         * read.
822         * 
823         * @see Group#getQuery()
824         */
825        public ItemQuery<Group> getGroups()
826        {
827                ItemQuery<Group> query = Group.getQuery();
828                query.joinPermanent(Hql.innerJoin("users", Item.USER.getAlias()));
829                query.restrictPermanent(Restrictions.eq(
830                        Hql.alias(Item.USER.getAlias()), Hql.entity(this)));
831                return query;
832        }
833
834
835        /**
836         * Get a query that returns the projects where this user is a member. The
837         * query excludes projects that the logged in user doesn't have permission
838         * to read. The query doesn't include projects where this user is the owner.
839         * 
840         * @see Project#getQuery()
841         */
842        public ItemQuery<Project> getProjects()
843        {
844                ItemQuery<Project> query = Project.getQuery();
845                query.joinPermanent(Hql.innerJoin("users", Item.USER.getAlias()));
846                query.restrictPermanent(Restrictions.eq(Hql.index(Item.USER.getAlias(),
847                        null), Hql.entity(this)));
848                return query;
849        }
850
851
852        /**
853         * Get a query that returns all messages for the user.
854         * 
855         * @return An {@link ItemQuery} object
856         * @see Message#getQuery(User)
857         */
858        public ItemQuery<Message> getMessages()
859        {
860                return Message.getQuery(this);
861        }
862
863        /**
864         * A runtime filter implementation that limits a query to only return users
865         * which are members of at least one group where the logged in user is also
866         * a member unless the logged in user has generic read permission.
867         */
868        private static class QueryRuntimeFilterImpl
869                        implements QueryRuntimeFilter
870        {
871                public void enableFilters(QueryRuntimeFilterManager manager,
872                                EntityQuery query, DbControl dc)
873                {
874                        SessionControl sc = dc.getSessionControl();
875                        if (!sc.hasPermission(Permission.READ, Item.USER))
876                        {
877                                if (sc.isLoggedIn())
878                                {
879                                        // Load users that are friends of the logged in user
880                                        org.hibernate.Filter filter = manager
881                                                .enableFilter("memberOf");
882                                        if (filter != null)
883                                        {
884                                                Set<Integer> friends = sc.getFriends();
885                                                if (friends == null || friends.size() == 0)
886                                                        friends = Collections.singleton(0);
887                                                filter.setParameterList("items", friends);
888                                                filter.setParameter("owner", sc.getLoggedInUserId());
889                                        }
890                                }
891                                else
892                                {
893                                        // Do not load any users if not logged in
894                                        manager.enableFilter("denyAll");
895                                }
896                        }
897                }
898        }
899
900
901        static User getByLogin(DbControl dc, String login)
902                        throws ItemNotFoundException, BaseException
903        {
904                org.hibernate.Query query = HibernateUtil.getPredefinedQuery(dc
905                        .getHibernateSession(), "GET_USER_FOR_LOGIN");
906                query.setString("login", login);
907                User u = dc.getItem(User.class, HibernateUtil.loadData(UserData.class,
908                        query));
909                if (u == null)
910                        throw new ItemNotFoundException("User[login=" + login + "]");
911                return u;
912        }
913}