package org.waterforpeople.mapping.app.web.rest.security; import java.util.EnumSet; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import javax.inject.Inject; import org.springframework.context.MessageSource; import org.springframework.context.MessageSourceAware; import org.springframework.context.support.MessageSourceAccessor; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.DisabledException; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.SpringSecurityMessageSource; import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; import org.waterforpeople.mapping.app.web.rest.security.user.GaeUser; import com.gallatinsystems.user.dao.UserDao; import com.google.appengine.api.users.User; /** * A simple authentication provider which interacts with {@code User} returned by the GAE * {@code UserService}, and also the local persistent {@code UserRegistry} to build an application * user principal. * <p> * If the user has been authenticated through google accounts, it will check if they are already * registered and either load the existing user information or assign them a temporary identity with * limited access until they have registered. * <p> * If the account has been disabled, a {@code DisabledException} will be raised. * * @author Luke Taylor */ public class GoogleAccountsAuthenticationProvider implements AuthenticationProvider, MessageSourceAware { protected MessageSourceAccessor messages = SpringSecurityMessageSource.getAccessor(); private static final Logger log = Logger.getLogger(GoogleAccountsAuthenticationProvider.class .getName()); @Inject UserDao userDao; @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { User googleUser = (User) authentication.getPrincipal(); GaeUser user = findUser(googleUser.getEmail()); if (user == null) { // User not in registry. Needs to register user = new GaeUser(googleUser.getNickname(), googleUser.getEmail()); } if (!user.isEnabled()) { throw new DisabledException("Account is disabled"); } return new GaeUserAuthentication(user, authentication.getDetails()); } private GaeUser findUser(String email) { final com.gallatinsystems.user.domain.User user = userDao.findUserByEmail(email); if (user == null) { return null; } final int authority = getAuthorityLevel(user); final Set<AppRole> roles = EnumSet.noneOf(AppRole.class); if (authority == AppRole.NEW_USER.getLevel()) { roles.add(AppRole.NEW_USER); } else { for (AppRole r : AppRole.values()) { if (authority <= r.getLevel()) { roles.add(r); } } } return new GaeUser(user.getUserName(), user.getEmailAddress(), user.getKey().getId(), roles, true); } private int getAuthorityLevel(com.gallatinsystems.user.domain.User user) { if (user.isSuperAdmin()) { return AppRole.SUPER_ADMIN.getLevel(); } try { final int level = Integer.parseInt(user.getPermissionList()); return level; } catch (Exception e) { log.log(Level.WARNING, "Error getting role level, setting USER role", e); } return AppRole.USER.getLevel(); } /** * Indicate that this provider only supports PreAuthenticatedAuthenticationToken (sub)classes. */ @Override public final boolean supports(Class<?> authentication) { return PreAuthenticatedAuthenticationToken.class.isAssignableFrom(authentication); } @Override public void setMessageSource(MessageSource messageSource) { this.messages = new MessageSourceAccessor(messageSource); } }