r6942 - in dumbhippo/trunk/server: src/com/dumbhippo/persistence src/com/dumbhippo/server src/com/dumbhippo/server/impl src/com/dumbhippo/web/servlets web web/jsp3



Author: marinaz
Date: 2007-11-30 18:03:48 -0600 (Fri, 30 Nov 2007)
New Revision: 6942

Added:
   dumbhippo/trunk/server/src/com/dumbhippo/web/servlets/FacebookServlet.java
   dumbhippo/trunk/server/web/jsp3/facebook-application-page.jsp
Removed:
   dumbhippo/trunk/server/web/jsp3/facebook.jsp
Modified:
   dumbhippo/trunk/server/src/com/dumbhippo/persistence/FacebookResource.java
   dumbhippo/trunk/server/src/com/dumbhippo/server/IdentitySpider.java
   dumbhippo/trunk/server/src/com/dumbhippo/server/impl/FacebookTrackerBean.java
   dumbhippo/trunk/server/src/com/dumbhippo/server/impl/IdentitySpiderBean.java
   dumbhippo/trunk/server/web/jsp3/facebook-welcome.jsp
   dumbhippo/trunk/server/web/servlet-info.xml
Log:
Check if we know who the person is on Mugshot when they visit our application page on Facebook. 

Modified: dumbhippo/trunk/server/src/com/dumbhippo/persistence/FacebookResource.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/persistence/FacebookResource.java	2007-11-29 21:57:44 UTC (rev 6941)
+++ dumbhippo/trunk/server/src/com/dumbhippo/persistence/FacebookResource.java	2007-12-01 00:03:48 UTC (rev 6942)
@@ -4,6 +4,8 @@
 import javax.persistence.Entity;
 import javax.persistence.Transient;
 
+import com.dumbhippo.StringUtils;
+
 @Entity
 public class FacebookResource extends Resource {
 	
@@ -11,6 +13,16 @@
 	
 	private String facebookUserId;
 	
+	public static String canonicalize(String str) throws ValidationException {
+		if (str == null)
+			return null;		
+		str = str.trim(); // gets tabs and stuff not just spaces
+	    if (!StringUtils.isAllNumbers(str))
+	        throw new ValidationException("Possibly invalid Facebook user id: '" + str + "')");
+	    
+	    return str;
+	}
+	
 	protected FacebookResource() {}
 	
 	public FacebookResource(String facebookUserId) {

Modified: dumbhippo/trunk/server/src/com/dumbhippo/server/IdentitySpider.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/server/IdentitySpider.java	2007-11-29 21:57:44 UTC (rev 6941)
+++ dumbhippo/trunk/server/src/com/dumbhippo/server/IdentitySpider.java	2007-12-01 00:03:48 UTC (rev 6942)
@@ -14,6 +14,7 @@
 import com.dumbhippo.persistence.Contact;
 import com.dumbhippo.persistence.ContactStatus;
 import com.dumbhippo.persistence.EmailResource;
+import com.dumbhippo.persistence.FacebookResource;
 import com.dumbhippo.persistence.GuidPersistable;
 import com.dumbhippo.persistence.LinkResource;
 import com.dumbhippo.persistence.Person;
@@ -101,6 +102,15 @@
 	 * @throws RetryException 
 	 */
 	public XmppResource getXmpp(String screenName) throws ValidationException, RetryException;
+
+	/**
+	 * Returns the FacebookResource for a given Facebook user id, or null if there is none.
+	 * Does not create a new FacebookResource if it's not there already.
+	 * 
+	 * @param facebookUserId
+	 * @return FacebookResource object
+	 */
+	public FacebookResource lookupFacebook(String facebookUserId) throws NotFoundException;
 	
 	/**
 	 * Returns the XmppResource for a given screen name, or null if there is none.
@@ -144,6 +154,8 @@
 
 	public User lookupUserByAim(Viewpoint viewpoint, String aim) throws NotFoundException;
 
+	public User lookupUserByFacebookUserId(Viewpoint viewpoint, String facebookUserId) throws NotFoundException;
+	
 	/**
 	 * Finds the unique person which owns a resource
 	 * according to our system. i.e. this person has proved

Modified: dumbhippo/trunk/server/src/com/dumbhippo/server/impl/FacebookTrackerBean.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/server/impl/FacebookTrackerBean.java	2007-11-29 21:57:44 UTC (rev 6941)
+++ dumbhippo/trunk/server/src/com/dumbhippo/server/impl/FacebookTrackerBean.java	2007-12-01 00:03:48 UTC (rev 6942)
@@ -118,7 +118,12 @@
 		
 		FacebookAccount facebookAccount;
 		if (externalAccount.getExtra() == null) {
-			FacebookResource res = getFacebookResource(facebookUserId);
+			FacebookResource res = null;
+			try {
+			    res = identitySpider.lookupFacebook(facebookUserId);
+			} catch (NotFoundException e) {
+				// nothing to do
+			}
 			facebookAccount = getFacebookAccount(facebookUserId);
 			if (res == null && facebookAccount == null) {
 				res = new FacebookResource(facebookUserId);
@@ -154,10 +159,10 @@
 			}
 		    Query resourceQuery = em.createQuery("from FacebookResource f where f.facebookUserId = :facebookUserId");
 			resourceQuery.setParameter("facebookUserId", facebookUserId);
-			FacebookResource res = getFacebookResource(facebookUserId);
-			if (res != null) {
+			try {
+				FacebookResource res = identitySpider.lookupFacebook(facebookUserId);
 				assert(res.getAccountClaim().equals(viewpoint.getViewer()));
-			} else {
+			} catch (NotFoundException e) {
 				throw new RuntimeException("No FacebookResource found for " + facebookUserId + ", while there exists a corresponding FacebookAccount");
 			}			
 		}
@@ -184,16 +189,6 @@
 		}
 	}
 	
-	private FacebookResource getFacebookResource(String facebookUserId) {
-	    Query resourceQuery = em.createQuery("from FacebookResource f where f.facebookUserId = :facebookUserId");
-		resourceQuery.setParameter("facebookUserId", facebookUserId);
-		try {
-			return (FacebookResource)resourceQuery.getSingleResult();
-		} catch (NoResultException e) {
-			return null;
-		}
-	}
-	
 	private FacebookAccount getFacebookAccount(String facebookUserId) {
 		Query accountQuery = em.createQuery("from FacebookAccount f where f.facebookUserId = :facebookUserId");
 		accountQuery.setParameter("facebookUserId", facebookUserId);

Modified: dumbhippo/trunk/server/src/com/dumbhippo/server/impl/IdentitySpiderBean.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/server/impl/IdentitySpiderBean.java	2007-11-29 21:57:44 UTC (rev 6941)
+++ dumbhippo/trunk/server/src/com/dumbhippo/server/impl/IdentitySpiderBean.java	2007-12-01 00:03:48 UTC (rev 6942)
@@ -123,6 +123,13 @@
 		return lookupUserByResource(viewpoint, res);
 	}
 
+	public User lookupUserByFacebookUserId(Viewpoint viewpoint, String facebookUserId) throws NotFoundException {
+		FacebookResource res = lookupFacebook(facebookUserId);
+		if (res == null)
+			return null;
+		return lookupUserByResource(viewpoint, res);
+	}
+	
 	public User lookupUserByResource(Viewpoint viewpoint, Resource resource) {
 		return getUser(resource);
 	}
@@ -203,8 +210,7 @@
 			public AimResource call() {
 				Query q;
 
-				q = em
-						.createQuery("from AimResource a where a.screenName = :name");
+				q = em.createQuery("from AimResource a where a.screenName = :name");
 				q.setParameter("name", screenName);
 
 				AimResource res;
@@ -249,7 +255,7 @@
 			}
 		});
 	}
-
+	
 	private <T extends Resource> T lookupResourceByName(Class<T> klass,	String identifier, String name) throws NotFoundException {
 		Query q;
 		String className = klass.getName();
@@ -289,11 +295,20 @@
 		try {
 			jid = XmppResource.canonicalize(jid);
 		} catch (ValidationException e) {
-			throw new NotFoundException("Not a valid AIM address", e);
+			throw new NotFoundException("Not a valid XMPP address", e);
 		}
 		return lookupResourceByName(XmppResource.class, "jid", jid);
 	}
 
+	public FacebookResource lookupFacebook(String facebookUserId) throws NotFoundException {
+		try {
+			facebookUserId = FacebookResource.canonicalize(facebookUserId);
+		} catch (ValidationException e) {
+			throw new NotFoundException("Not a valid Facebook user id", e);
+		}
+		return lookupResourceByName(FacebookResource.class, "facebookUserId", facebookUserId);
+	}
+	
 	public LinkResource lookupLink(final URL url) throws NotFoundException {
 		return lookupResourceByName(LinkResource.class, "url", url.toExternalForm());
 	}

Added: dumbhippo/trunk/server/src/com/dumbhippo/web/servlets/FacebookServlet.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/web/servlets/FacebookServlet.java	2007-11-29 21:57:44 UTC (rev 6941)
+++ dumbhippo/trunk/server/src/com/dumbhippo/web/servlets/FacebookServlet.java	2007-12-01 00:03:48 UTC (rev 6942)
@@ -0,0 +1,137 @@
+package com.dumbhippo.web.servlets;
+
+import java.io.IOException;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+
+import com.dumbhippo.GlobalSetup;
+import com.dumbhippo.Site;
+import com.dumbhippo.XmlBuilder;
+import com.dumbhippo.persistence.User;
+import com.dumbhippo.server.Configuration;
+import com.dumbhippo.server.FacebookSystemException;
+import com.dumbhippo.server.FacebookTracker;
+import com.dumbhippo.server.HippoProperty;
+import com.dumbhippo.server.HumanVisibleException;
+import com.dumbhippo.server.IdentitySpider;
+import com.dumbhippo.server.NotFoundException;
+import com.dumbhippo.server.Configuration.PropertyNotFoundException;
+import com.dumbhippo.server.views.SystemViewpoint;
+import com.dumbhippo.server.views.UserViewpoint;
+import com.dumbhippo.tx.RetryException;
+import com.dumbhippo.web.WebEJBUtil;
+import com.facebook.api.FacebookParam;
+import com.facebook.api.FacebookSignatureUtil;
+
+public class FacebookServlet extends AbstractServlet {
+
+	@SuppressWarnings("unused")
+	private static final Logger logger = GlobalSetup.getLogger(FacebookAddServlet.class);
+	
+	static final long serialVersionUID = 1;
+	
+	private Configuration config;
+	
+	@Override
+	public void init() {
+		config = WebEJBUtil.defaultLookup(Configuration.class);
+	}	
+	
+	@Override
+	protected String wrappedDoGet(HttpServletRequest request, HttpServletResponse response) throws IOException, HumanVisibleException, HttpException, ServletException, RetryException {
+		logger.debug("full request is: {}", request.toString());
+		logger.debug("context params are:");
+        for (Object o : request.getParameterMap().entrySet()) {
+        	@SuppressWarnings("unchecked")
+            Map.Entry<String, String[]> mapEntry = (Map.Entry<String, String[]>)o;
+            logger.debug("{} = {}", mapEntry.getKey(), mapEntry.getValue()[0]);
+        }
+      
+        @SuppressWarnings("unchecked")
+        Map<String, CharSequence> facebookParams = FacebookSignatureUtil.extractFacebookParamsFromArray(request.getParameterMap());
+        String secret = null;
+        try {
+        	secret = config.getPropertyNoDefault(HippoProperty.FACEBOOK_SECRET).trim();
+			if (secret.length() == 0)
+				secret = null;				
+		} catch (PropertyNotFoundException e) {
+			secret = null;
+		}
+		
+		String errorMessage = null;
+		User user = null;
+		if (secret == null) {
+			errorMessage = "We could not verify Facebook information due to a missing secret key we should share with Facebook.";   
+			logger.warn("Facebook secret is not set, can't verify requests from Facebook.");
+		} else {        
+	        boolean signatureValid = FacebookSignatureUtil.verifySignature(facebookParams, secret);
+	        if (!signatureValid) {
+				errorMessage = "We could not verify Facebook information because the signature supplied for Facebook parameters was not valid.";           	
+	        } else if (facebookParams.get(FacebookParam.ADDED.toString()).toString().equals("1")) {
+	        	// get the user who owns the related FacebookResource
+	            String sessionKey = facebookParams.get(FacebookParam.SESSION_KEY.toString()).toString();
+	            String facebookUserId = facebookParams.get(FacebookParam.USER.toString()).toString(); 
+	        	IdentitySpider identitySpider = WebEJBUtil.defaultLookup(IdentitySpider.class);
+	        	try {
+	        	    user = identitySpider.lookupUserByFacebookUserId(SystemViewpoint.getInstance(), facebookUserId);
+			        if (user != null) {
+	    	            try {
+	    	            FacebookTracker facebookTracker = WebEJBUtil.defaultLookup(FacebookTracker.class);
+	    	        	// TODO: can change this into updateExistingFacebookAccount
+	    	            facebookTracker.updateOrCreateFacebookAccount(new UserViewpoint(user, Site.MUGSHOT), sessionKey, facebookUserId, true);
+	    	            } catch (FacebookSystemException e) {
+	                        errorMessage = e.getMessage();		
+	    	            }
+			        }
+		        } catch (NotFoundException e) {
+		        	//nothing to do
+		        }
+	        }
+		}
+
+		// this returns some code in FBML we'll return for our app page on Facebook
+		// it intentionally points to my test server for now
+		XmlBuilder xml = new XmlBuilder();		
+		xml.openElement("p");
+		if (user != null && errorMessage == null) {
+			xml.append("We already know that you are ");
+		    xml.appendTextNode("a", user.getNickname(), "href",
+				               "http://dogfood.mugshot.org/person?who="; + user.getId(), "target", "_blank");
+		    xml.append(" on Mugshot!");
+		} else {
+		    xml.append("You need to be ");
+		    xml.appendTextNode("a", "logged in to Mugshot", "href",
+				    "http://dogfood.mugshot.org/account";, "target", "_blank");
+	    	xml.append(" to be able to verify your Mugshot account.");
+		    xml.openElement("form", "action", "http://dogfood.mugshot.org/facebook-add";, "target", "_blank", "method", "GET");
+		    xml.appendEmptyNode("input", "type", "submit", "value", "Verify My Mugshot Account");
+		    xml.closeElement();
+		}
+		xml.closeElement();
+		
+		response.setContentType("text/html");
+		response.getOutputStream().write(xml.getBytes());
+		
+		return null;
+	}	
+		
+	@Override
+	protected boolean isReadWrite(HttpServletRequest request) {
+		// The method is GET, since we need links that the user can just click upon,
+		// but they have side effects. This is OK since the links are unique, so 
+		// caching won't happen.
+		
+		return true;
+	}
+	
+
+	@Override
+	protected boolean requiresTransaction(HttpServletRequest request) {
+		return true;
+	}
+}

Copied: dumbhippo/trunk/server/web/jsp3/facebook-application-page.jsp (from rev 6940, dumbhippo/trunk/server/web/jsp3/facebook.jsp)

Modified: dumbhippo/trunk/server/web/jsp3/facebook-welcome.jsp
===================================================================
--- dumbhippo/trunk/server/web/jsp3/facebook-welcome.jsp	2007-11-29 21:57:44 UTC (rev 6941)
+++ dumbhippo/trunk/server/web/jsp3/facebook-welcome.jsp	2007-12-01 00:03:48 UTC (rev 6942)
@@ -12,7 +12,7 @@
 	<dht3:stylesheet name="site" iefixes="true"/>			
 	<dht:faviconIncludes/>
 </head>
-<dht3:page currentPageLink="facebook-add">
+<dht3:page currentPageLink="facebook-welcome">
     <dht3:shinyBox color="grey">
         <div class="dh-page-shinybox-title-large">Thank you for trying out Mugshot application for Facebook!</div>
         <c:choose>

Deleted: dumbhippo/trunk/server/web/jsp3/facebook.jsp
===================================================================
--- dumbhippo/trunk/server/web/jsp3/facebook.jsp	2007-11-29 21:57:44 UTC (rev 6941)
+++ dumbhippo/trunk/server/web/jsp3/facebook.jsp	2007-12-01 00:03:48 UTC (rev 6942)
@@ -1,8 +0,0 @@
-<!-- this is some code in FBML we'll return for our app page on Facebook -->
-<!-- it intentionally points to my test server for now -->
-<p>
-You need to be <a href="http://test.marinaz.dumbhippo.com:8080/account"; target="_blank">logged in to Mugshot</a> to be able to verify your Mugshot account.
-<form action="http://test.marinaz.dumbhippo.com:8080/facebook-add"; target="_blank" method="GET">
-<input type="submit" value="Verify My Mugshot Account"/>
-</form>
-</p>
\ No newline at end of file

Modified: dumbhippo/trunk/server/web/servlet-info.xml
===================================================================
--- dumbhippo/trunk/server/web/servlet-info.xml	2007-11-29 21:57:44 UTC (rev 6941)
+++ dumbhippo/trunk/server/web/servlet-info.xml	2007-12-01 00:03:48 UTC (rev 6942)
@@ -278,8 +278,18 @@
       <servlet-name>FacebookAddServlet</servlet-name>
       <url-pattern>/facebook-add</url-pattern>
    </servlet-mapping>   
+
+    <servlet>
+      <servlet-name>FacebookServlet</servlet-name>
+      <servlet-class>com.dumbhippo.web.servlets.FacebookServlet</servlet-class>
+    </servlet> 
    
    <servlet-mapping>
+      <servlet-name>FacebookServlet</servlet-name>
+      <url-pattern>/facebook</url-pattern>
+   </servlet-mapping>   
+      
+   <servlet-mapping>
       <servlet-name>AbnormalErrorServlet</servlet-name>
       <url-pattern>/abnormalerror</url-pattern>
    </servlet-mapping>
@@ -309,7 +319,7 @@
            they are listed below for completeness -->
       <init-param>
           <param-name>noSignin</param-name>
-          <param-value>apple-dashboard-content,application,applications,applications-learnmore,badges,busy,buttons,comingsoon,error,facebook,facebook-welcome,files,flash,google-stacker,google-stacker-spec,google-stacker-content,group-files,licenses,mugshot-eula,public-groups,radar-theme,sharelink,sharelink-inactive,signup,summit,tour,unknownlink,upgrade,user-summary,who-are-you,robots.txt,trademark</param-value>
+          <param-value>apple-dashboard-content,application,applications,applications-learnmore,badges,busy,buttons,comingsoon,error,facebook-application-page,facebook-welcome,files,flash,google-stacker,google-stacker-spec,google-stacker-content,group-files,licenses,mugshot-eula,public-groups,radar-theme,sharelink,sharelink-inactive,signup,summit,tour,unknownlink,upgrade,user-summary,who-are-you,robots.txt,trademark</param-value>
       </init-param>
       <init-param>
           <param-name>requiresSigninStealth</param-name>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]