package edu.gatech.oad.rocket.findmythings.server.security; import com.google.appengine.api.datastore.PhoneNumber; import edu.gatech.oad.rocket.findmythings.server.model.AppMember; import org.apache.shiro.authc.SimpleAccount; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.authc.credential.PasswordMatcher; import org.apache.shiro.authz.SimpleRole; import org.apache.shiro.config.Ini; import org.apache.shiro.realm.text.IniRealm; import org.apache.shiro.util.StringUtils; import java.util.*; import java.util.logging.Logger; public class ProfileIniRealm extends IniRealm implements ProfileRealm { @SuppressWarnings("unused") private static final Logger LOG = Logger.getLogger(ProfileIniRealm.class.getName()); private static final String PROFILES_SECTION_NAME = "profiles"; @com.google.appengine.repackaged.org.codehaus.jackson.annotate.JsonIgnoreProperties({"objectPermissions", "credentialsExpired", "credentials", "principals"}) private class IniAccount extends SimpleAccount implements AppMember { private static final long serialVersionUID = -1836831286248630414L; private String name = null; private PhoneNumber phone = null; private String address = null; private boolean isAdmin = false; IniAccount(String principal, String credentials, String realmName) { super(principal, credentials, realmName); } @Override public boolean isRegistered() { return true; } @Override public boolean isEditable() { return false; } @Override public String getEmail() { return (String)this.getPrincipals().getPrimaryPrincipal(); } @Override public String getName() { return name; } /** * @param name the name to set */ private void setName(String name) { this.name = name; } @Override public PhoneNumber getPhone() { return phone; } /** * @param phone the phone to set */ private void setPhone(PhoneNumber phone) { this.phone = phone; } @Override public String getAddress() { return address; } /** * @param address the address to set */ private void setAddress(String address) { this.address = address; } public boolean isAdmin() { return isAdmin; } private void setIsAdmin(boolean isAdmin) { this.isAdmin = isAdmin; } } public ProfileIniRealm() { super(); setAuthenticationTokenClass(UsernamePasswordToken.class); setCredentialsMatcher(new PasswordMatcher()); } public ProfileIniRealm(Ini ini) { this(); setAuthenticationTokenClass(UsernamePasswordToken.class); setCredentialsMatcher(new PasswordMatcher()); setIni(ini); } @Override protected void processUserDefinitions(Map<String, String> users) { if (users == null || users.isEmpty()) { return; } Ini.Section profilesSection = getIni().getSection(PROFILES_SECTION_NAME); for (String email : users.keySet()) { String value = users.get(email); String[] passwordAndRolesArray = StringUtils.split(value); String password = passwordAndRolesArray[0]; String profileValue = profilesSection.get(email); String[] profileValuesArray; String name = null; PhoneNumber phone = null; String address = null; boolean hasProfile = false; if (profileValue != null) { profileValuesArray = StringUtils.split(profileValue, ',', '"', '"', false, true); if (profileValuesArray.length == 3) { name = profileValuesArray[0]; phone = profileValuesArray[1] == null ? null : new PhoneNumber(profileValuesArray[1]); address = profileValuesArray[2]; } hasProfile = (name != null || phone != null || address != null); } SimpleAccount account = getUser(email); if (hasProfile && !(account instanceof IniAccount)) { this.users.remove(email); account = null; } if (account == null) { account = new IniAccount(email, password, getName()); add(account); } account.setCredentials(password); if (hasProfile) { ((IniAccount) account).setName(name); ((IniAccount) account).setPhone(phone); ((IniAccount) account).setAddress(address); } if (passwordAndRolesArray.length > 1) { for (int i = 1; i < passwordAndRolesArray.length; i++) { String rolename = passwordAndRolesArray[i]; account.addRole(rolename); SimpleRole role = getRole(rolename); if (role != null) { account.addObjectPermissions(role.getPermissions()); } } } else { account.setRoles(null); } if (hasProfile) { ((IniAccount) account).setIsAdmin(account.getRoles().contains("admin")); } } } @Override public boolean accountExists(String email) { return email != null && getUser(email) != null; } @Override public AppMember getAccount(String email) { if (email == null) return null; SimpleAccount account = getUser(email); if (account instanceof AppMember) return (AppMember)account; return null; } public Collection<? extends AppMember> getMembers() { Collection<SimpleAccount> accounts = this.users.values(); Collection<AppMember> ret = new ArrayList<>(accounts.size()); for (SimpleAccount e : accounts) { if (e instanceof AppMember) { ret.add((AppMember)e); } } return ret; } }