001: /**
002: * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, version 2.1, dated February 1999.
003: *
004: * This program is free software; you can redistribute it and/or modify
005: * it under the terms of the latest version of the GNU Lesser General
006: * Public License as published by the Free Software Foundation;
007: *
008: * This program is distributed in the hope that it will be useful,
009: * but WITHOUT ANY WARRANTY; without even the implied warranty of
010: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
011: * GNU Lesser General Public License for more details.
012: *
013: * You should have received a copy of the GNU Lesser General Public License
014: * along with this program (LICENSE.txt); if not, write to the Free Software
015: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
016: */package org.jamwiki.authentication;
017:
018: import java.util.Arrays;
019: import java.util.HashSet;
020: import java.util.Set;
021: import org.acegisecurity.Authentication;
022: import org.acegisecurity.AuthenticationCredentialsNotFoundException;
023: import org.acegisecurity.GrantedAuthority;
024: import org.acegisecurity.userdetails.UserDetails;
025: import org.apache.commons.lang.StringUtils;
026: import org.jamwiki.WikiBase;
027: import org.jamwiki.model.Role;
028: import org.jamwiki.model.WikiGroup;
029: import org.jamwiki.model.WikiUser;
030: import org.jamwiki.utils.WikiLogger;
031: import org.jamwiki.utils.WikiUtil;
032:
033: /**
034: *
035: */
036: public class WikiUserAuth extends WikiUser implements UserDetails {
037:
038: private static final WikiLogger logger = WikiLogger
039: .getLogger(WikiUserAuth.class.getName());
040: private static final long serialVersionUID = -2818435399240684581L;
041: /** Default roles for logged-in users */
042: private static Role[] defaultGroupRoles = null;
043: /**
044: * GrantedAuthority is used by Acegi Security to support several authorities
045: * (roles). A logged user always has ROLE_USER and may have other roles,
046: * e.g. ROLE_ADMIN.
047: */
048: private GrantedAuthority[] authorities = { Role.ROLE_USER };
049:
050: /**
051: *
052: */
053: private WikiUserAuth() {
054: super ();
055: }
056:
057: /**
058: *
059: */
060: public WikiUserAuth(WikiUser wikiUser) throws Exception {
061: super (wikiUser.getUsername());
062: this .init();
063: this .setCreateDate(wikiUser.getCreateDate());
064: this .setCreateIpAddress(wikiUser.getCreateIpAddress());
065: this .setDefaultLocale(wikiUser.getDefaultLocale());
066: this .setDisplayName(wikiUser.getDisplayName());
067: this .setLastLoginDate(wikiUser.getLastLoginDate());
068: this .setLastLoginIpAddress(wikiUser.getLastLoginIpAddress());
069: this .setUserId(wikiUser.getUserId());
070: this .setPassword(wikiUser.getPassword());
071: }
072:
073: /**
074: *
075: */
076: public WikiUserAuth(String username) throws Exception {
077: super (username);
078: this .init();
079: }
080:
081: /**
082: * Construct the <code>User</code> with the details required by
083: * {@link org.acegisecurity.providers.dao.DaoAuthenticationProvider}. This
084: * method should be used by systems that do NOT use the default JAMWiki
085: * user and group roles. This method will NOT assign default roles to the
086: * user, and as a result the Special:Roles functionality will be ignored.
087: *
088: * @param username the username presented to the
089: * <code>DaoAuthenticationProvider</code>
090: * @param password the password that should be presented to the
091: * <code>DaoAuthenticationProvider</code>
092: * @param enabled set to <code>true</code> if the user is enabled
093: * @param accountNonExpired set to <code>true</code> if the account has not
094: * expired
095: * @param credentialsNonExpired set to <code>true</code> if the credentials
096: * have not expired
097: * @param accountNonLocked set to <code>true</code> if the account is not
098: * locked
099: * @param authorities the authorities that should be granted to the caller
100: * if they presented the correct username and password and the user
101: * is enabled
102: * @throws IllegalArgumentException if a <code>null</code> value was passed
103: * either as a parameter or as an element in the
104: * <code>GrantedAuthority[]</code> array.
105: */
106: public WikiUserAuth(String username, String password,
107: boolean enabled, boolean accountNonExpired,
108: boolean credentialsNonExpired, boolean accountNonLocked,
109: GrantedAuthority[] authorities) {
110: super (username);
111: if (StringUtils.isBlank(username) || password == null) {
112: throw new IllegalArgumentException(
113: "Cannot pass null or empty values to constructor");
114: }
115: this .setPassword(password);
116: // this.enabled = enabled;
117: // this.accountNonExpired = accountNonExpired;
118: // this.credentialsNonExpired = credentialsNonExpired;
119: // this.accountNonLocked = accountNonLocked;
120: if (authorities == null) {
121: authorities = new GrantedAuthority[0];
122: }
123: this .addRoles(authorities);
124: }
125:
126: // Acegi Security: UserDetails contract
127:
128: /**
129: * Returns granted authorites.
130: *
131: * @return authorites, never null.
132: */
133: public GrantedAuthority[] getAuthorities() {
134: return authorities;
135: }
136:
137: protected void setAuthorities(GrantedAuthority[] authorities) {
138: if (authorities == null) {
139: throw new IllegalArgumentException(
140: "Cannot pass a null GrantedAuthority array");
141: }
142: for (int i = 0; i < authorities.length; i++) {
143: if (authorities[i] == null) {
144: throw new IllegalArgumentException(
145: "Granted authority element "
146: + i
147: + " is null - GrantedAuthority[] cannot contain any null elements");
148: }
149: }
150: this .authorities = authorities;
151: }
152:
153: /**
154: *
155: */
156: private void init() throws Exception {
157: if (WikiUtil.isFirstUse() || WikiUtil.isUpgrade()) {
158: return;
159: }
160: this .addDefaultGroupRoles();
161: this .addUserRoles();
162: }
163:
164: /**
165: *
166: */
167: public boolean isAccountNonExpired() {
168: // TODO Not yet implemented
169: return true;
170: }
171:
172: /**
173: *
174: */
175: public boolean isAccountNonLocked() {
176: // TODO Not yet implemented
177: return true;
178: }
179:
180: /**
181: *
182: */
183: public boolean isCredentialsNonExpired() {
184: // TODO Not yet implemented
185: return true;
186: }
187:
188: /**
189: *
190: */
191: public boolean isEnabled() {
192: // TODO Not yet implemented
193: return true;
194: }
195:
196: /**
197: *
198: */
199: private void addRoles(GrantedAuthority[] roles) {
200: if (this .authorities == null) {
201: this .authorities = new GrantedAuthority[0];
202: }
203: Set authoritiesSet = new HashSet(Arrays
204: .asList(this .authorities));
205: for (int i = 0; i < roles.length; i++) {
206: if (!authoritiesSet.contains(roles[i])) {
207: authoritiesSet.add(roles[i]);
208: }
209: }
210: this .setAuthorities((GrantedAuthority[]) authoritiesSet
211: .toArray(authorities));
212: }
213:
214: /**
215: *
216: */
217: private void addDefaultGroupRoles() {
218: if (WikiUserAuth.defaultGroupRoles == null) {
219: try {
220: WikiUserAuth.defaultGroupRoles = WikiBase
221: .getDataHandler().getRoleMapGroup(
222: WikiGroup.GROUP_REGISTERED_USER);
223: } catch (Exception e) {
224: // FIXME - without default roles bad things happen, so should this throw the
225: // error to the calling method?
226: logger.severe("Unable to retrieve default roles for "
227: + WikiGroup.GROUP_REGISTERED_USER, e);
228: return;
229: }
230: }
231: this .addRoles(WikiUserAuth.defaultGroupRoles);
232: }
233:
234: /**
235: *
236: */
237: private void addUserRoles() {
238: if (StringUtils.isBlank(this .getUsername())) {
239: // FIXME - log error? RegisterServlet will trigger this.
240: return;
241: }
242: Role[] userRoles = new Role[0];
243: try {
244: userRoles = WikiBase.getDataHandler().getRoleMapUser(
245: this .getUsername());
246: } catch (Exception e) {
247: // FIXME - without default roles bad things happen, so should this throw the
248: // error to the calling method?
249: logger.severe("Unable to retrieve default roles for "
250: + this .getUsername(), e);
251: }
252: this .addRoles(userRoles);
253: }
254:
255: /**
256: * Convenience method for determining if a user has been assigned a role
257: * without the need to examine an array of Role objects.
258: *
259: * @param role If the user has been assigned this role then the method will
260: * return <code>true</code>.
261: * @return <code>true</code> if the user has been assigned the specified
262: * role, <code>false</code> otherwise.
263: */
264: public boolean hasRole(Role role) {
265: if (this .authorities == null) {
266: logger.warning("No roles assigned for user "
267: + this .getUsername());
268: return false;
269: }
270: return Arrays.asList(authorities).contains(role);
271: }
272:
273: /**
274: * Utility method for converting an Acegi <code>Authentication</code>
275: * object into a <code>WikiUserAuth</code>. If the user is logged-in then the
276: * <code>Authentication</code> object will have the <code>WikiUserAuth</code>
277: * as its principal. If the user is not logged in then create an empty
278: * <code>WikiUserAuth</code> object and assign it the same authorities as the
279: * <code>Authentication</code> object.
280: *
281: * @param auth The Acegi <code>Authentication</code> object that is being
282: * converted into a <code>WikiUserAuth</code> object.
283: * @return Returns a <code>WikiUserAuth</code> object that corresponds to the
284: * Acegi <code>Authentication</code> object. If the user is not currently
285: * logged-in then an empty <code>WikiUserAuth</code> with the same authorities
286: * as the <code>Authentication</code> object is returned. This method
287: * will never return <code>null</code>.
288: * @throws AuthenticationCredentialsNotFoundException If authentication
289: * credentials are unavailable.
290: */
291: public static WikiUserAuth initWikiUserAuth(Authentication auth)
292: throws AuthenticationCredentialsNotFoundException {
293: if (auth == null) {
294: throw new AuthenticationCredentialsNotFoundException(
295: "No authentication credential available");
296: }
297: if (auth.getPrincipal() instanceof WikiUserAuth) {
298: // logged-in user
299: return (WikiUserAuth) auth.getPrincipal();
300: }
301: WikiUserAuth user = new WikiUserAuth();
302: user.setAuthorities(auth.getAuthorities());
303: return user;
304: }
305:
306: /**
307: * Force a reset of the default logged-in users roles. This method should
308: * be called if the roles allowed to logged-in users are changed.
309: */
310: public static void resetDefaultGroupRoles() {
311: WikiUserAuth.defaultGroupRoles = null;
312: }
313: }
|