Saturday, September 28, 2013

SecureSocial Database persistence service for users and tokens

/**

 * Copyright 2012 Jorge Aliss (jaliss at gmail dot com) - twitter: @jaliss
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package service;

import play.Application;
import play.Logger;
import scala.Option;
import scala.Some;
import securesocial.core.AuthenticationMethod;
import securesocial.core.Identity;
import securesocial.core.IdentityId;
import securesocial.core.PasswordInfo;
import securesocial.core.SocialUser;
import securesocial.core.java.BaseUserService;

import securesocial.core.java.Token;

import java.net.UnknownHostException;

import org.joda.time.DateTime;

import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.MongoClient;

/**
 * A Sample In Memory user service in Java
 *
 * Note: This is NOT suitable for a production environment and is provided only as a guide.
 * A real implementation would persist things in a database
 */
public class CopyOfInMemoryUserService extends BaseUserService {

    private static final String IS_SIGN_UP = "isSignUp";
    private static final String BCRYPT = "bcrypt";
    private static final String PASSWORD = "password";
    private static final String AUTH_METHOD = "authMethod";
    private static final String LAST_NAME = "lastName";
    private static final String FIRST_NAME = "firstName";
    private static final String USER_ID = "userId";
    private static final String PROVIDER_ID = "providerId";
    private static final String USERS = "users";
    private static final String EXPIRATION_TIME = "expirationTime";
    private static final String CREATION_TIME = "creationTime";
    private static final String EMAIL = "email";
    private static final String UUID = "uuid";
    private static final String USER_TOKENS = "userTokens";
 
 
    public CopyOfInMemoryUserService(Application application) {
        super(application);
    }

    @Override
    public Identity doSave(Identity user) {
        Logger.debug("doSave(user)***"+user);
        // this sample returns the same user object, but you could return an instance of your own class
        // here as long as it implements the Identity interface. This will allow you to use your own class in the
        // protected actions and event callbacks. The same goes for the doFind(UserId userId) method.
        DB db = getMongoClient();          
        DBCollection userCollection = db.getCollection(USERS);
        BasicDBObject doc = new BasicDBObject(USER_ID, user.identityId().userId())
                            .append("userId:providerId", user.identityId().userId() + ":" + user.identityId().providerId())
                            .append(PROVIDER_ID, user.identityId().providerId())
                            .append(AUTH_METHOD,user.authMethod().method())
                            //.append("avatarUrl",user.avatarUrl().get())
                            .append(EMAIL,user.email().get())
                            .append(FIRST_NAME,user.firstName())
                            .append(LAST_NAME,user.lastName())
                            .append("fullName",user.fullName())
                            .append(PASSWORD,user.passwordInfo().get().password());

        Logger.debug("saving user:"+doc);
        userCollection.insert(doc);
     
        return user;
    }

    @Override
    public void doSave(Token token) {
        Logger.debug("***doSave(token):"+token);
        DB db = getMongoClient();          
        DBCollection userCollection = db.getCollection(USER_TOKENS);
     
        BasicDBObject doc = new BasicDBObject(UUID, token.getUuid())
                            .append(EMAIL, token.getEmail())
                            .append(IS_SIGN_UP, token.getIsSignUp())
                            .append(CREATION_TIME, Long.toString(token.getCreationTime().toDate().getTime()))
                            .append(EXPIRATION_TIME, Long.toString(token.getExpirationTime().toDate().getTime()));
        Logger.debug("Saving token:" + doc);
        userCollection.insert(doc);
    }

    @Override
    public Identity doFind(IdentityId identityId) {
        Logger.debug("****doFind(identityId):"+identityId);
        DB db = getMongoClient();          
        DBCollection userCollection = db.getCollection(USERS);
        BasicDBObject query = new BasicDBObject("userId:providerId", identityId.userId() + ":" + identityId.providerId());
        DBCursor cursor = userCollection.find(query);
     
        Identity identity = null;
        if( cursor.hasNext() ) {
            DBObject dbUser = cursor.next();
            Logger.debug("Found user (with identityId):"+dbUser);
            identity = new SocialUser(identityId,        
                    dbUser.get(FIRST_NAME).toString(),
                    dbUser.get(LAST_NAME).toString(),
                    dbUser.get(FIRST_NAME).toString() + " " + dbUser.get(LAST_NAME).toString(),
                    Option.apply(dbUser.get(EMAIL).toString()),
                    null,
                    new AuthenticationMethod( dbUser.get(AUTH_METHOD).toString() ),
                    null,
                    null,
                    Some.apply(new PasswordInfo(BCRYPT, dbUser.get(PASSWORD).toString(), null))
                );
         
        }
        return identity;
    }

    @Override
    public Token doFindToken(String tokenId) {
        Logger.debug("doFindToken(tokenId):"+tokenId);
        DB db = getMongoClient();          
        DBCollection userCollection = db.getCollection(USER_TOKENS);
        BasicDBObject query = new BasicDBObject(UUID, tokenId);
        DBCursor cursor = userCollection.find(query);
     
        Token token = null;
        if( cursor.hasNext() ) {
            token = new Token();
            DBObject dbToken = cursor.next();
            Logger.debug("Found token with tokenId:"+dbToken);
         
            token.setUuid(dbToken.get(UUID).toString());
            token.setEmail(dbToken.get(EMAIL).toString());
            token.setIsSignUp( new Boolean( dbToken.get(IS_SIGN_UP).toString() ) );      
            token.setCreationTime( new DateTime(new Long( dbToken.get(CREATION_TIME).toString() ) ));    
            token.setExpirationTime( new DateTime( new Long( dbToken.get(EXPIRATION_TIME).toString()) ));
            token.setIsSignUp( new Boolean(dbToken.get(IS_SIGN_UP).toString()));
        }      
        return token;
    }

    @Override
    public Identity doFindByEmailAndProvider(String email, String providerId) {
        Logger.debug("finding user with email:"+email + " and providerId:"+providerId);
     
        Identity result = null;
        DB db = getMongoClient();          
        DBCollection userCollection = db.getCollection(USERS);
        BasicDBObject query = new BasicDBObject(EMAIL, email).append(PROVIDER_ID, providerId);
        DBCursor cursor = userCollection.find(query);
     
        if( cursor.hasNext() ) {
            DBObject dbUser = cursor.next();
            Logger.debug("found user(with email and providerId:"+dbUser);
            if( dbUser != null ) {
                IdentityId userId = new IdentityId(dbUser.get(USER_ID).toString(), providerId);
                result = new SocialUser(userId ,        
                        dbUser.get(FIRST_NAME).toString(),
                        dbUser.get(LAST_NAME).toString(),
                        dbUser.get(FIRST_NAME).toString() + " " + dbUser.get(LAST_NAME).toString(),
                        Option.apply(dbUser.get(EMAIL).toString()),
                        null,
                        new AuthenticationMethod( dbUser.get(AUTH_METHOD).toString() ),
                        null,
                        null,
                        Some.apply(new PasswordInfo(BCRYPT, dbUser.get(PASSWORD).toString(), null))
                    );
            }
        }
        Logger.debug("found user with email and provider:"+result);
        return result;
    }

    @Override
    public void doDeleteToken(String uuid) {
        Logger.debug("********* doDeleteToken() called ****");
        DB db = getMongoClient();          
        DBCollection userCollection = db.getCollection(USER_TOKENS);
        BasicDBObject query = new BasicDBObject(UUID, uuid);
        DBCursor cursor = userCollection.find(query);
     
        if( cursor.hasNext() ) {
            DBObject dbToken = cursor.next();
            Logger.debug("Deleting token with uuid:"+uuid);
            userCollection.remove(dbToken);
        }      
    }

    @Override
    public void doDeleteExpiredTokens() {
        Logger.debug("***deleteExpiredTokens()");
        DB db = getMongoClient();          
        DBCollection userCollection = db.getCollection(USER_TOKENS);
        DBCursor cursor = userCollection.find();
     
        Token token = null;
        if( cursor.hasNext() ) {
            token = new Token();
            DBObject dbToken = cursor.next();

            Logger.debug("Got token:" + dbToken);
            token.setUuid(dbToken.get(UUID).toString());
            token.setEmail(dbToken.get(EMAIL).toString());

            DateTime d1 = new DateTime( new Long(dbToken.get(CREATION_TIME).toString()) );
            token.setCreationTime(d1);
         
            DateTime d2 = new DateTime( new Long(dbToken.get(EXPIRATION_TIME).toString()) );
            token.setExpirationTime(d2);        
            if( token.isExpired() ) {
                Logger.debug("Expired, deleting token:"+dbToken);
                userCollection.remove(dbToken);
            }
        }
    }
 
    private static DB getMongoClient() {
        MongoClient client = null;
        DB db = null;
        try {
            client = new MongoClient("localhost", 27017);

            db = client.getDB("UserDB");
        } catch(UnknownHostException e) {
            e.printStackTrace();
        }
     
        return db;
    }
}

No comments: