Package ca.carleton.gcrc.couch.user

Source Code of ca.carleton.gcrc.couch.user.UserServletActions

package ca.carleton.gcrc.couch.user;

import java.io.ByteArrayOutputStream;
import java.io.OutputStreamWriter;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.Date;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Formatter;
import java.util.List;
import java.util.Vector;

import org.apache.commons.codec.binary.Base64;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ca.carleton.gcrc.couch.client.CouchDb;
import ca.carleton.gcrc.couch.client.CouchDesignDocument;
import ca.carleton.gcrc.couch.client.CouchQuery;
import ca.carleton.gcrc.couch.client.CouchQueryResults;
import ca.carleton.gcrc.couch.user.mail.UserMailNotification;
import ca.carleton.gcrc.couch.user.token.CreationToken;
import ca.carleton.gcrc.couch.user.token.TokenEncryptor;
import ca.carleton.gcrc.security.rng.RngFactory;

public class UserServletActions {

  static final private byte[] SECRET_KEY = {
    (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04, (byte)0x05, (byte)0x06, (byte)0x07, (byte)0x08
    ,(byte)0x11, (byte)0x12, (byte)0x13, (byte)0x14, (byte)0x15, (byte)0x16, (byte)0x17, (byte)0x18
  };
 
  final protected Logger logger = LoggerFactory.getLogger(this.getClass());

  private CouchDb userDb;
  private CouchDesignDocument nunaliitUserDesignDocument;
  private UserMailNotification userMailNotification;
  private byte[] serverKey = null;
  private JSONObject cached_welcome = null;
  private SecureRandom rng = null;

  public UserServletActions(
      CouchDb userDb
      ,CouchDesignDocument nunaliitUserDesignDocument
      ,UserMailNotification userMailNotification
    ){
    this.userDb = userDb;
    this.nunaliitUserDesignDocument = nunaliitUserDesignDocument;
    this.userMailNotification = userMailNotification;
   
    rng = (new RngFactory()).createRng();
   
    // Hard coded key
   
  }
 
  public void setServerKey(byte[] serverKey){
    this.serverKey = serverKey;
  }
 
  synchronized public JSONObject getWelcome() throws Exception{
    if( null == cached_welcome ){
      cached_welcome = new JSONObject();
      cached_welcome.put("UserServlet", true);
    }
   
    return cached_welcome;
  }

  public JSONObject getUser(String name) throws Exception {
    String id = "org.couchdb.user:"+name;
    JSONObject userDoc = userDb.getDocument(id);
   
    JSONObject result = getPublicUserFromUser(userDoc);
   
    return result;
  }

  public JSONObject getUsers(List<String> names) throws Exception {
    List<String> docIds = new ArrayList<String>(names.size());
    for(String n : names){
      String id = "org.couchdb.user:"+n;
      docIds.add(id);
    }
   
    Collection<JSONObject> userDocs = userDb.getDocuments(docIds);
   
    // Work around for bug in CouchDb 1.4.0
    if( userDocs.size() > 0 ) {
      JSONObject firstUser = userDocs.iterator().next();
      Object returnedId = firstUser.opt("_id");
      if( null == returnedId ){
        // Perform request, one at a time
        List<JSONObject> tempUserDocs = new Vector<JSONObject>();
        for(String id : docIds){
          try {
            JSONObject userDoc = userDb.getDocument(id);
            if( null != userDoc ){
              tempUserDocs.add(userDoc);
            }
          } catch(Exception e) {
            // Ignore error. User is not in database
          }
        }
       
        // Continue with this list, instead
        userDocs = tempUserDocs;
      }
    }
   
    JSONObject result = new JSONObject();
   
    JSONArray userArray = new JSONArray();
    result.put("users", userArray);
   
    for(JSONObject userDoc : userDocs) {
      JSONObject pubUser = getPublicUserFromUser(userDoc);
      userArray.put(pubUser);
    }
   
    return result;
  }

  public JSONObject getUserFromEmailAddress(String emailAddress) throws Exception {
    try {
      CouchQuery query = new CouchQuery();
      query.setViewName("emails");
      query.setStartKey(emailAddress);
      query.setEndKey(emailAddress);
      query.setIncludeDocs(true);

      CouchQueryResults results = nunaliitUserDesignDocument.performQuery(query);
      List<JSONObject> rows = results.getRows();
      for(JSONObject row : rows){
        JSONObject doc = row.optJSONObject("doc");
        if( null != doc ){
          JSONObject result = getPublicUserFromUser(doc);
          return result;
        }
      }

      throw new Exception("Unable to find user with e-mail address: "+emailAddress);
     
    } catch (Exception e) {
      throw new Exception("Error while searching user with e-mail address: "+emailAddress,e);
    }
  }
 
  public JSONObject initUserCreation(String emailAddr) throws Exception {
    JSONObject result = new JSONObject();
    result.put("message", "User creation email was sent to the given address");

    // Create token
    CreationToken creationToken = new CreationToken();
    {
      creationToken.setEmailAddress(emailAddr);
      Date now = new Date();
      long thirtyDaysMs = now.getTime() + (30 * 24 * 60 * 60 * 1000);
      creationToken.setExpiry( new Date(thirtyDaysMs) );
    }
   
    // Encrypt token
    if( null == serverKey ){
      throw new Exception("Server key was not installed. Configuration must be adjusted.");
    }
    byte[] context = new byte[8];
    rng.nextBytes(context);
    byte[] encryptedToken = TokenEncryptor.encryptToken(SECRET_KEY, context, creationToken);
   
    // Base 64 encode token
    String b64Token = null;
    try {
      b64Token = Base64.encodeBase64String(encryptedToken);
    } catch( Exception e ) {
      throw new Exception("Error while encoding token (b64)", e);
    }   
   
    userMailNotification.sendUserCreationNotice(emailAddr,b64Token);
   
    return result;
  }

  private JSONObject getPublicUserFromUser(JSONObject userDoc) throws Exception {
    JSONObject result = new JSONObject();

    result.put("_id", userDoc.opt("_id"));
    result.put("_rev", userDoc.opt("_rev"));
    result.put("name", userDoc.opt("name"));
    result.put("display", userDoc.opt("display"));
   
    JSONArray emailArray = userDoc.optJSONArray("nunaliit_emails");
    if( null != emailArray ){
      JSONArray emailDigest = new JSONArray();
     
      for(int i=0,e=emailArray.length();i<e;++i){
        Object emailObj = emailArray.get(i);
        if( emailObj instanceof String ){
          String email = (String)emailObj;
         
          ByteArrayOutputStream baos = new ByteArrayOutputStream();
          OutputStreamWriter osw = new OutputStreamWriter(baos,"UTF-8");
          osw.write(email);
          osw.flush();
         
          MessageDigest md = MessageDigest.getInstance("MD5");
          md.update(baos.toByteArray());
          byte[] digest = md.digest();

          StringBuilder sb = new StringBuilder(digest.length * 2);
          Formatter formatter = new Formatter(sb);
          for (byte b : digest) {
            formatter.format("%02x", b)
          }
          formatter.close();
          emailDigest.put( sb.toString() )
        }
      }
     
      result.put("emailDigests", emailDigest);
    }
   
    return result;
  }
}
TOP

Related Classes of ca.carleton.gcrc.couch.user.UserServletActions

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.