View Javadoc
1   /**
2    * This file Copyright (c) 2003-2018 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.cms.security;
35  
36  import info.magnolia.cms.util.DeprecationUtil;
37  
38  import java.io.Serializable;
39  import java.util.Calendar;
40  import java.util.Collection;
41  import java.util.Collections;
42  import java.util.Map;
43  
44  import org.apache.jackrabbit.util.ISO8601;
45  
46  /**
47   * A read-only snapshot of a Magnolia user as found in JCR at the moment of creation (e.g. upon login).
48   * Any changes to the underlying properties, roles and groups will be reflected here only upon first logging out
49   * and then logging in again.
50   * To get a "real-time" view of a user's status, use {@link MgnlUserManager#getUser(String)} or similar methods instead.
51   */
52  public class MgnlUser extends AbstractUser implements User, Serializable {
53      private final Map<String, String> properties;
54      private final Collection<String> directGroups;
55      private final Collection<String> directRoles;
56      private final Collection<String> allGroups;
57      private final Collection<String> allRoles;
58  
59      private final String name;
60      private final String language;
61      private final String encodedPassword;
62      private boolean enabled = true;
63      private String path;
64      private String uuid;
65      private final String realm;
66  
67      /**
68       * This constructor is mainly used by {@link MgnlUserManager} or by custom extensions of this object.
69       * If you extend MgnlUser, chances are you need to provide your own {@link MgnlUserManager} as well.
70       *
71       * @see MgnlUserManager#getUser(String)
72       * @see MgnlUserManager#newUserInstance(javax.jcr.Node)
73       *
74       */
75      public MgnlUser(String name, String realm, Collection<String> directGroups, Collection<String> directRoles, Map<String, String> properties, String path, String uuid, Collection<String> allGroups, Collection<String> allRoles) {
76          this.name = name;
77          this.directRoles = directRoles;
78          this.directGroups = directGroups;
79          this.allRoles = allRoles;
80          this.allGroups = allGroups;
81          this.properties = properties;
82          this.realm = realm;
83  
84          //shortcut some often accessed props so we don't have to search hashmap for them.
85          this.language = properties.get(MgnlUserManager.PROPERTY_LANGUAGE);
86  
87          final String enabledByDefault = properties.get(MgnlUserManager.PROPERTY_ENABLED);
88          // all accounts are enabled by default and prop doesn't exist if the account was not disabled before
89          this.enabled = enabledByDefault == null ? true : Boolean.parseBoolean(properties.get(MgnlUserManager.PROPERTY_ENABLED));
90  
91          this.encodedPassword = properties.get(MgnlUserManager.PROPERTY_PASSWORD);
92          this.path = path;
93          this.uuid = uuid;
94      }
95  
96      /**
97       * @deprecated since 5.5.5. Please use {@link #MgnlUser(String, String, Collection, Collection, Map, String, String, Collection, Collection)} instead.
98       */
99      @Deprecated
100     public MgnlUser(String name, String realm, Collection<String> directGroups, Collection<String> directRoles, Map<String, String> properties, String path, String uuid) {
101         this(name, realm, directGroups, directRoles, properties, path, uuid, Collections.emptySet(), Collections.emptySet());
102         final String reason = "This constructor is deprecated since Magnolia 5.5.5.\n" +
103                 "Be warned that instantiating directly MgnlUser with this constructor will result in an inconsistent object missing all roles and groups.\n" +
104                 "Please use new public constructor instead.";
105         DeprecationUtil.isDeprecated(reason);
106     }
107 
108     /**
109      * @deprecated since 5.5.5. Please use {@link #MgnlUser(String, String, Collection, Collection, Map, String, String, Collection, Collection)} instead.
110      */
111     @Deprecated
112     public MgnlUser(String name, String realm, Collection<String> directGroups, Collection<String> directRoles, Map<String, String> properties) {
113         this(name, realm, directGroups, directRoles, properties, null, null);
114     }
115 
116     @Override
117     public boolean inGroup(String groupName) {
118         return allGroups.contains(groupName);
119     }
120 
121     @Override
122     public boolean isEnabled() {
123         return enabled;
124     }
125 
126     @Override
127     public boolean hasRole(String roleName) {
128         return allRoles.contains(roleName);
129     }
130 
131     public int getFailedLoginAttempts() {
132         try {
133             return Integer.valueOf(this.properties.get("failedLoginAttempts"));
134         } catch (Exception e) {
135             return 0;
136         }
137     }
138 
139     public Calendar getReleaseTime() {
140         try {
141             return ISO8601.parse(this.properties.get("releaseTime"));
142         } catch (Exception e) {
143             return null;
144         }
145     }
146 
147     @Override
148     public String getName() {
149         return name;
150     }
151 
152     @Override
153     public String getPassword() {
154         return encodedPassword;
155     }
156 
157     /**
158      * @deprecated Since 4.5.8. Password is now encoded by BCrypt and therefore cannot be decoded.
159      */
160     @Deprecated
161     protected String decodePassword(String encodedPassword) {
162         throw new UnsupportedOperationException();
163     }
164 
165     @Override
166     public String getLanguage() {
167         return this.language;
168     }
169 
170     @Override
171     public String getProperty(String propertyName) {
172         return properties.get(propertyName);
173     }
174 
175     @Override
176     public Collection<String> getGroups() {
177         return Collections.unmodifiableCollection(directGroups);
178     }
179 
180     @Override
181     public Collection<String> getAllGroups() {
182         return Collections.unmodifiableCollection(allGroups);
183     }
184 
185     @Override
186     public Collection<String> getRoles() {
187         return Collections.unmodifiableCollection(directRoles);
188     }
189 
190     @Override
191     public Collection<String> getAllRoles() {
192         return Collections.unmodifiableCollection(allRoles);
193     }
194 
195     public String getPath() {
196         return this.path;
197     }
198 
199     @Deprecated
200     public void setPath(String path) {
201         this.path = path;
202     }
203 
204 
205     public String getRealm() {
206         return realm;
207     }
208 
209     /**
210      * Update the "last access" timestamp.
211      *
212      * @deprecated since 4.5, use {@link UserManager#updateLastAccessTimestamp(User)} instead
213      */
214     @Deprecated
215     public void setLastAccess() {
216         throw new UnsupportedOperationException("Use manager to update user details.");
217     }
218 
219     /**
220      * @deprecated since 4.5, use {@link UserManager} instead
221      */
222     @Override
223     @Deprecated
224     public void setProperty(String propertyName, String value) {
225         throw new UnsupportedOperationException("Use manager to modify properties of the user.");
226     }
227 
228     @Override
229     public String getIdentifier() {
230         return uuid;
231     }
232 
233     /**
234      * @deprecated since 4.5.1, use {@link MgnlUser#getIdentifier()} instead
235      */
236     @Deprecated
237     public String getUuid() {
238         return uuid;
239     }
240 
241     @Override
242     public String toString() {
243         return "MgnlUser - " + name + " [" + uuid + "]";
244     }
245 }