package edu.gatech.oad.rocket.findmythings.server.security; import com.google.common.base.Preconditions; import edu.gatech.oad.rocket.findmythings.server.db.DatabaseService; import edu.gatech.oad.rocket.findmythings.server.db.MemcacheManager; import edu.gatech.oad.rocket.findmythings.server.db.model.DBMember; import edu.gatech.oad.rocket.findmythings.server.model.AppMember; import edu.gatech.oad.rocket.findmythings.server.util.HashHelper; import org.apache.shiro.authc.*; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.subject.SimplePrincipalCollection; import org.apache.shiro.util.SimpleByteSource; import java.util.HashSet; import java.util.logging.Logger; public class DatabaseRealm extends AuthorizingRealm implements ProfileRealm { private static final Logger LOG = Logger.getLogger(DatabaseRealm.class.getName()); public DatabaseRealm() { super(new MemcacheManager(), HashHelper.getCredentialsMatcher()); setAuthenticationTokenClass(UsernamePasswordToken.class); LOG.fine("Creating a new instance of DatabaseRealm"); } public void clearCachedAuthorizationInfo(String principal) { SimplePrincipalCollection principals = new SimplePrincipalCollection(principal, getName()); clearCachedAuthorizationInfo(principals); } @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { Preconditions.checkNotNull(principals, "You can't have a null collection of principals. No really, how did you do that"); String userEmail = (String)getAvailablePrincipal(principals); if (userEmail == null) { throw new NullPointerException("Can't find a principal in the collection"); } LOG.fine("Finding authorization info for " + userEmail + " in DB"); DBMember member = DatabaseService.ofy().memberWithEmail(userEmail); if (memberCannotLogIn(member)) { LOG.info("Rejecting user " + userEmail); return null; } LOG.fine("Found " + userEmail + " in DB"); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.addRoles(member.getRoles()); info.addStringPermissions(member.getStringPermissions()); return info; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { if (token instanceof UsernamePasswordToken) { String userEmail = ((UsernamePasswordToken) token).getUsername(); return doGetAuthenticationInfo(userEmail); } throw new UnsupportedOperationException("Implement another method of getting user email."); } AuthenticationInfo doGetAuthenticationInfo(String email) throws AuthenticationException { Preconditions.checkNotNull(email, "Email can't be null"); LOG.info("Finding authentication info for " + email + " in DB"); DBMember member = DatabaseService.ofy().memberWithEmail(email); if (memberCannotLogIn(member)) { LOG.info("Rejecting user " + email); return null; } SimpleAccount account = new SimpleAccount(member.getEmail(), member.getHashedPassword(), new SimpleByteSource(member.getSalt()), getName()); account.setRoles(new HashSet<>(member.getRoles())); account.setStringPermissions(new HashSet<>(member.getStringPermissions())); return account; } private static boolean memberCannotLogIn(AppMember member) { return member == null || !member.isRegistered() || member.isLocked(); } @Override public boolean accountExists(String email) { return email != null && DatabaseService.ofy().load().type(DBMember.class).id(email) != null; } @Override public AppMember getAccount(String email) { if (email == null) return null; return DatabaseService.ofy().load().type(DBMember.class).id(email).get(); } }