package restx.jongo; import com.google.common.base.Optional; import org.bson.types.ObjectId; import org.joda.time.DateTime; import restx.security.CredentialsStrategy; import restx.security.RestxPrincipal; import restx.security.UserRepository; /** */ public class JongoUserRepository<U extends RestxPrincipal> implements UserRepository<U> { private final JongoCollection users; private final JongoCollection usersCredentials; private final UserRefStrategy<U> userRefStrategy; private final CredentialsStrategy credentialsStrategy; private final Class<U> userClass; private final U defaultAdminUser; public JongoUserRepository(JongoCollection users, JongoCollection usersCredentials, UserRefStrategy<U> userRefStrategy, CredentialsStrategy credentialsStrategy, Class<U> userClass, U defaultAdminUser) { this.users = users; this.usersCredentials = usersCredentials; this.userRefStrategy = userRefStrategy; this.credentialsStrategy = credentialsStrategy; this.userClass = userClass; this.defaultAdminUser = defaultAdminUser; } @Override public Optional<U> findUserByName(String name) { return Optional.fromNullable(users.get().findOne("{" + userRefStrategy.getNameProperty() + ": #}", name).as(userClass)); } @Override public Optional<String> findCredentialByUserName(String name) { Optional<U> userByName = findUserByName(name); if (!userByName.isPresent()) { return Optional.absent(); } UserCredentials c = findCredentialsForUserRef(userRefStrategy.getUserRef(userByName.get())); if (c == null) { return Optional.absent(); } return Optional.fromNullable(c.getPasswordHash()); } @Override public boolean isAdminDefined() { try { return users.get().count("{roles: {$all: [ # ]}}", getAdminRole()) > 0; } catch (Exception e) { return false; } } protected String getAdminRole() { return "restx-admin"; } @Override public U defaultAdmin() { return defaultAdminUser; } private UserCredentials findCredentialsForUserRef(String userRef) { return usersCredentials.get() .findOne("{ _id: # }", userRefStrategy.toId(userRef)).as(UserCredentials.class); } ///////////////////////////////////////////////////////// // repo update methods ///////////////////////////////////////////////////////// public U createUser(U user) { users.get().save(user); return user; } public U updateUser(U user) { users.get().save(user); return user; } public Iterable<U> findAllUsers() { return users.get().find().as(userClass); } public void deleteUser(String userRef) { Object id = userRefStrategy.toId(userRef); users.get().remove("{ _id: # }", id); usersCredentials.get().remove("{ _id: # }", id); } public void setCredentials(String userRef, String passwordHash) { UserCredentials userCredentials = findCredentialsForUserRef(userRef); if (userCredentials == null) { userCredentials = new UserCredentials().setUserRef(userRef); } String hashed = credentialsStrategy.cryptCredentialsForStorage(userRef, passwordHash); usersCredentials.get().save( userCredentials .setPasswordHash(hashed) .setLastUpdated(DateTime.now())); } public Optional<U> findUserByKey(String key) { return Optional.fromNullable(users.get().findOne("{ _id: # }", userRefStrategy.toId(key)).as(userClass)); } public static interface UserRefStrategy<U extends RestxPrincipal> { String getNameProperty(); String getUserRef(U user); Object toId(String userRef); } public static class RefUserByNameStrategy<U extends RestxPrincipal> implements UserRefStrategy<U> { public String getNameProperty() { return "_id"; } public String getUserRef(U user) { return user.getName(); } public Object toId(String userRef) { return userRef; } } public static abstract class RefUserByKeyStrategy<U extends RestxPrincipal> implements UserRefStrategy<U> { public String getNameProperty() { return "name"; } public String getUserRef(U user) { return getId(user); } protected abstract String getId(U user); public Object toId(String userRef) { return new ObjectId(userRef); } } }