package org.pac4j.mongo.profile.service; import com.mongodb.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoCursor; import com.mongodb.client.MongoDatabase; import org.bson.Document; import org.pac4j.core.context.WebContext; import org.pac4j.core.credentials.password.PasswordEncoder; import org.pac4j.core.profile.definition.CommonProfileDefinition; import org.pac4j.core.profile.service.AbstractProfileService; import org.pac4j.core.util.CommonHelper; import org.pac4j.mongo.profile.MongoProfile; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import static com.mongodb.client.model.Filters.*; /** * The MongoDB profile service (which supersedes the Mongo authenticator). * * @author Jerome Leleu * @since 2.0.0 */ public class MongoProfileService extends AbstractProfileService<MongoProfile> { private MongoClient mongoClient; private String usersDatabase = "users"; private String usersCollection = "users"; public MongoProfileService() {} public MongoProfileService(final MongoClient mongoClient) { this.mongoClient = mongoClient; } public MongoProfileService(final MongoClient mongoClient, final String attributes) { this.mongoClient = mongoClient; setAttributes(attributes); } public MongoProfileService(final MongoClient mongoClient, final String attributes, final PasswordEncoder passwordEncoder) { this.mongoClient = mongoClient; setAttributes(attributes); setPasswordEncoder(passwordEncoder); } public MongoProfileService(final MongoClient mongoClient, final PasswordEncoder passwordEncoder) { this.mongoClient = mongoClient; setPasswordEncoder(passwordEncoder); } @Override protected void internalInit(final WebContext context) { CommonHelper.assertNotNull("passwordEncoder", getPasswordEncoder()); CommonHelper.assertNotNull("mongoClient", this.mongoClient); CommonHelper.assertNotBlank("usersDatabase", this.usersDatabase); CommonHelper.assertNotBlank("usersCollection", this.usersCollection); defaultProfileDefinition(new CommonProfileDefinition<>(x -> new MongoProfile())); super.internalInit(context); } @Override protected void insert(final Map<String, Object> attributes) { final Document doc = new Document(); for (final Map.Entry<String, Object> entry : attributes.entrySet()) { doc.append(entry.getKey(), entry.getValue()); } logger.debug("Insert doc: {}", doc); getCollection().insertOne(doc); } @Override protected void update(final Map<String, Object> attributes) { String id = null; final Document doc = new Document(); for (final Map.Entry<String, Object> entry : attributes.entrySet()) { final String name = entry.getKey(); final Object value = entry.getValue(); if (ID.equals(name)) { id = (String) value; } else { doc.append(entry.getKey(), entry.getValue()); } } CommonHelper.assertNotNull(ID, id); logger.debug("Updating id: {} with doc: {}", id, doc); getCollection().updateOne(eq(ID, id), new Document("$set", doc)); } @Override protected void deleteById(final String id) { logger.debug("Delete id: {}", id); getCollection().deleteOne(eq(ID, id)); } @Override protected List<Map<String, Object>> read(final List<String> names, final String key, final String value) { logger.debug("Reading key / value: {} / {}", key, value); final List<Map<String, Object>> listAttributes = new ArrayList<>(); try (final MongoCursor<Document> cursor = getCollection().find(eq(key, value)).iterator()) { int i = 0; while (cursor.hasNext() && i <= 2) { final Document result = cursor.next(); final Map<String, Object> newAttributes = new HashMap<>(); // filter on names for (final Map.Entry<String, Object> entry : result.entrySet()) { final String name = entry.getKey(); if (names == null || names.contains(name)) { newAttributes.put(name, entry.getValue()); } } listAttributes.add(newAttributes); i++; } } logger.debug("Found: ", listAttributes); return listAttributes; } protected MongoCollection<Document> getCollection() { final MongoDatabase db = mongoClient.getDatabase(usersDatabase); return db.getCollection(usersCollection); } public String getUsersDatabase() { return usersDatabase; } public void setUsersDatabase(final String usersDatabase) { this.usersDatabase = usersDatabase; } public String getUsersCollection() { return usersCollection; } public void setUsersCollection(final String usersCollection) { this.usersCollection = usersCollection; } public MongoClient getMongoClient() { return mongoClient; } public void setMongoClient(final MongoClient mongoClient) { this.mongoClient = mongoClient; } @Override public String toString() { return CommonHelper.toString(this.getClass(), "mongoClient", mongoClient, "usersCollection", usersCollection, "passwordEncoder", getPasswordEncoder(), "usersDatabase", usersDatabase, "attributes", getAttributes(), "profileDefinition", getProfileDefinition(), "idAttribute", getIdAttribute(), "usernameAttribute", getUsernameAttribute(), "passwordAttribute", getPasswordAttribute()); } }