r7517 - in dumbhippo/trunk: openfire/src/plugins/hippo/src/java/com/dumbhippo/jive server/src/com/dumbhippo/server/impl server/src/com/dumbhippo/web/servlets



Author: marinaz
Date: 2008-10-20 16:50:28 -0500 (Mon, 20 Oct 2008)
New Revision: 7517

Added:
   dumbhippo/trunk/openfire/src/plugins/hippo/src/java/com/dumbhippo/jive/AccountsIQHandler.java
Modified:
   dumbhippo/trunk/openfire/src/plugins/hippo/src/java/com/dumbhippo/jive/HippoPlugin.java
   dumbhippo/trunk/server/src/com/dumbhippo/server/impl/ClaimVerifierBean.java
   dumbhippo/trunk/server/src/com/dumbhippo/server/impl/FeedSystemBean.java
   dumbhippo/trunk/server/src/com/dumbhippo/server/impl/IdentitySpiderBean.java
   dumbhippo/trunk/server/src/com/dumbhippo/server/impl/OnlineDesktopSystemBean.java
   dumbhippo/trunk/server/src/com/dumbhippo/web/servlets/FacebookServlet.java
Log:
AccountsIQHandler.java: Create an AccountsIQHandler with an addOnlineAccount method for adding online accounts. Add special handling for Google accounts that need to be verified.

ClaimVerifierBean.java: add an extra check to see if an e-mail is claimed by someone else and return an error to the user immediately instead of sending a verification e-mail.

IdentitySpiderBean.java: signal onGoogleServicedEmailChange if a Google e-mail was removed.

FeedSystemBean.java: fall back to using feed entry link as its guid if syndEntry.getUri() returns null, which can be the case if a feed entry is missing an optional guid element.

FacebookServlet.java: update the signature used when calling online accounts set methods.

Added: dumbhippo/trunk/openfire/src/plugins/hippo/src/java/com/dumbhippo/jive/AccountsIQHandler.java
===================================================================
--- dumbhippo/trunk/openfire/src/plugins/hippo/src/java/com/dumbhippo/jive/AccountsIQHandler.java	2008-09-29 22:17:31 UTC (rev 7516)
+++ dumbhippo/trunk/openfire/src/plugins/hippo/src/java/com/dumbhippo/jive/AccountsIQHandler.java	2008-10-20 21:50:28 UTC (rev 7517)
@@ -0,0 +1,179 @@
+package com.dumbhippo.jive;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+import org.slf4j.Logger;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.xml.sax.SAXException;
+import org.xmpp.packet.IQ;
+
+import com.dumbhippo.GlobalSetup;
+import com.dumbhippo.XmlBuilder;
+import com.dumbhippo.jive.annotations.IQHandler;
+import com.dumbhippo.jive.annotations.IQMethod;
+import com.dumbhippo.persistence.ExternalAccountType;
+import com.dumbhippo.persistence.OnlineAccountType;
+import com.dumbhippo.persistence.ValidationException;
+import com.dumbhippo.server.ClaimVerifier;
+import com.dumbhippo.server.ExternalAccountSystem;
+import com.dumbhippo.server.HttpMethods;
+import com.dumbhippo.server.HumanVisibleException;
+import com.dumbhippo.server.IdentitySpider;
+import com.dumbhippo.server.NotFoundException;
+import com.dumbhippo.server.OnlineDesktopSystem;
+import com.dumbhippo.server.XmlMethodException;
+import com.dumbhippo.server.util.EJBUtil;
+import com.dumbhippo.server.views.SystemViewpoint;
+import com.dumbhippo.server.views.UserViewpoint;
+import com.dumbhippo.tx.RetryException;
+
+
+ IQHandler(namespace=AccountsIQHandler.ACCOUNTS_NAMESPACE)
+public class AccountsIQHandler extends AnnotatedIQHandler {
+	static final String ACCOUNTS_NAMESPACE = "http://mugshot.org/p/accounts";;
+	
+	private static final Logger logger = GlobalSetup.getLogger(AccountsIQHandler.class);	
+	
+	protected AccountsIQHandler() {
+		super("Accounts IQ Handler");
+	}	
+	
+	// TODO: this can return an ExternalAccountDMO, but for that we need to get an ExternalAccount
+	// back from a set method we use from HttpMethods, which would require removing throwing an error
+	// when checking getReturnType() in HttpMethodsServlet2. Another option is to include an ExternalAccount
+	// id in the XmlBuilder. (Though ideally we would move all the logic that happens in set methods in 
+	// HttpMethods to the ExernalAccountSystem and use that.)
+    // We could then add feedback message as a field in ExternalAccount and make it available as part of the
+	// ExternalAccountDMO. (We now omit the feedback messages that can occur when we set Twitter, Reddit,
+	// MySpace or Amazon. In any case, these messages are only relevant when the user has Mugshot enabled.)
+	@IQMethod(name="addOnlineAccount", type=IQ.Type.set)
+	@IQParams({"accountType", "username"})
+	public void addOnlineAccount(UserViewpoint viewpoint, String accountType, String username) throws IQException {
+		logger.debug("inside addOnlineAccount");
+
+		// Because "google" type is an e-mail address, we need to treat it in a completely 
+		// different way from other account types.
+		if (accountType.equals("google")) {
+		    ClaimVerifier claimVerifier = EJBUtil.defaultLookup(ClaimVerifier.class);
+		    OnlineDesktopSystem onlineDesktopSystem = EJBUtil.defaultLookup(OnlineDesktopSystem.class);
+		    IdentitySpider identitySpider = EJBUtil.defaultLookup(IdentitySpider.class);
+		    try {
+			    claimVerifier.sendClaimVerifierLinkEmail(viewpoint, viewpoint.getViewer(), username);
+			    // should pass in null for the user, because otherwise run in into a check
+			    // that it is only possible to set Google state for e-mails the user owns
+			    onlineDesktopSystem.setGoogleServicedEmail(SystemViewpoint.getInstance(), null, identitySpider.getEmail(username), true);
+			    return;
+		    } catch (HumanVisibleException e) {
+		    	throw IQException.createBadRequest(e.getMessage());
+		    } catch (RetryException e) {
+		    	 throw IQException.createBadRequest("Could not save an account on the server.");
+		    } catch (ValidationException e) {
+		    	throw IQException.createBadRequest(e.getMessage());
+		    }
+		}		
+		
+		ExternalAccountSystem externalAccounts = EJBUtil.defaultLookup(ExternalAccountSystem.class);
+		HttpMethods httpMethods = EJBUtil.defaultLookup(HttpMethods.class);
+		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+		factory.setNamespaceAware(true);
+		OnlineAccountType onlineAccountType;		
+		try {
+			onlineAccountType = externalAccounts.lookupOnlineAccountTypeForName(accountType);
+		} catch (NotFoundException e) {
+			throw IQException.createBadRequest("Unknown account type " + accountType);
+		}
+		
+		if (onlineAccountType.getAccountType() != null) {		
+			try {
+				if (onlineAccountType.getAccountType().equals(ExternalAccountType.FLICKR)) {
+		    		XmlBuilder xmlForFlickr = new XmlBuilder();
+		    		xmlForFlickr.openElement("result");
+		    		httpMethods.doFindFlickrAccount(xmlForFlickr, viewpoint, username);
+		    		xmlForFlickr.closeElement(); // result
+		    		Document doc = factory.newDocumentBuilder().parse(new ByteArrayInputStream(xmlForFlickr.getBytes()));
+		    		XPath xpath = XPathFactory.newInstance().newXPath();
+		    		String nsid = ((Node)xpath.evaluate("/result/flickrUser/nsid", doc, XPathConstants.NODE)).getTextContent();
+		    		httpMethods.doSetFlickrAccount(new XmlBuilder(), viewpoint, "", nsid, username);
+		    		// return "";
+		    	} else {
+		    		Method setAccount = httpMethods.getClass().getMethod("doSet" + onlineAccountType.getAccountType().getDomNodeIdName() + "Account",
+		    				                                             new Class[] {XmlBuilder.class, UserViewpoint.class, String.class, String.class});	
+		    		XmlBuilder resultXml = new XmlBuilder();
+		    		resultXml.openElement("result");
+		    		setAccount.invoke(httpMethods, new Object[] {resultXml, viewpoint, "", username});
+		    		resultXml.closeElement(); // result
+		    		// we have messages telling the user about certain limitations of their account
+		    		// for MySpace, Twitter, Reddit, and Amazon
+		    		if (resultXml.getBytes().length > 0) {
+			    		try {
+			    		    Document doc = factory.newDocumentBuilder().parse(new ByteArrayInputStream(resultXml.getBytes()));
+			    		    XPath xpath = XPathFactory.newInstance().newXPath();
+			    		    Node node = (Node)xpath.evaluate("/result/message", doc, XPathConstants.NODE);
+			    		    if (node != null) {
+			    		        String message = node.getTextContent();
+			    		        if (message.trim().length() > 0) {
+			    		    	    // return message;
+			    		        }
+			    		    }
+			    		} catch (XPathExpressionException e) {
+			    			logger.error("Error getting a message about an external account for " + onlineAccountType.getAccountType() + " with value " + username, e);
+				        	// the account must have been set succesfully anyway
+			    			// return "";
+				        }
+		    	    }
+		    		// return "";	    		
+		    	}
+    	    } catch (XmlMethodException e) {
+    		    // in all cases except for the Flickr one, if the XmlMethodException will be thrown, it will be
+    		    // wrapped inside an InvokationTargetException below because of our use of reflection
+    		    logger.warn("Error updating external account for " + onlineAccountType.getAccountType() + " with value " + username, e);
+    		    throw IQException.createBadRequest(e.getMessage());	   
+    	    } catch (IOException e) {
+    		    logger.error("Error updating external account for " + onlineAccountType.getAccountType() + " with value " + username, e);
+    		    throw IQException.createBadRequest("Could not save an account on the server.");    
+    	    } catch (ParserConfigurationException e) {
+    	    	logger.error("Error updating external account for " + onlineAccountType.getAccountType() + " with value " + username, e);
+    		    throw IQException.createBadRequest("Could not save an account on the server.");
+            } catch (SAXException e) {
+    		    logger.error("Error updating external account for " + onlineAccountType.getAccountType() + " with value " + username, e);
+    		    throw IQException.createBadRequest("Could not save an account on the server.");
+            } catch (XPathExpressionException e) {
+    		    logger.error("Error updating external account for " + onlineAccountType.getAccountType() + " with value " + username, e);
+    		    throw IQException.createBadRequest("Could not save an account on the server.");
+            } catch (NoSuchMethodException e) {
+    		    logger.error("Error updating external account for " + onlineAccountType.getAccountType() + " with value " + username, e);
+    		    throw IQException.createBadRequest("Could not save an account on the server.");
+            } catch (InvocationTargetException e) {
+    		    logger.warn("Error updating external account for " + onlineAccountType.getAccountType() + " with value " + username, e);
+    		    if (e.getCause() != null) {
+    			    // this is the error we'll get if the submitted username is invalid
+    		    	throw IQException.createBadRequest(e.getCause().getMessage());
+    		    } else  {
+    		    	throw IQException.createBadRequest("Could not save an account on the server.");
+    		    }
+            } catch (IllegalAccessException e) {
+		        logger.error("Error updating external account for " + onlineAccountType.getAccountType() + " with value " + username, e);
+		        throw IQException.createBadRequest("Could not save an account on the server.");
+            }
+  	    } else {
+  	    	try {
+	    	    httpMethods.doSetOnlineAccountValue(new XmlBuilder(), viewpoint, accountType, "", username);
+	    	    // return "";
+  	    	 } catch (XmlMethodException e) {
+     		    logger.warn("Error updating external account for " + accountType + " with value " + username, e);
+     		    throw IQException.createBadRequest(e.getMessage());	    		
+     	    }    
+	    }
+	}
+}

Modified: dumbhippo/trunk/openfire/src/plugins/hippo/src/java/com/dumbhippo/jive/HippoPlugin.java
===================================================================
--- dumbhippo/trunk/openfire/src/plugins/hippo/src/java/com/dumbhippo/jive/HippoPlugin.java	2008-09-29 22:17:31 UTC (rev 7516)
+++ dumbhippo/trunk/openfire/src/plugins/hippo/src/java/com/dumbhippo/jive/HippoPlugin.java	2008-10-20 21:50:28 UTC (rev 7517)
@@ -102,6 +102,7 @@
 			addIQHandler(new LegacyContactsIQHandler());
 			addIQHandler(new ContactsIQHandler());
 			addIQHandler(new EntityIQHandler());			
+			addIQHandler(new AccountsIQHandler());
 			
 			Log.debug("... done initializing Hippo plugin");
 		} catch (Exception e) {

Modified: dumbhippo/trunk/server/src/com/dumbhippo/server/impl/ClaimVerifierBean.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/server/impl/ClaimVerifierBean.java	2008-09-29 22:17:31 UTC (rev 7516)
+++ dumbhippo/trunk/server/src/com/dumbhippo/server/impl/ClaimVerifierBean.java	2008-10-20 21:50:28 UTC (rev 7517)
@@ -171,6 +171,10 @@
 		} catch (ValidationException e) {
 			throw new HumanVisibleException("That isn't a valid email address (" + e.getMessage() + ")");
 		}
+		
+    	if (resource.getAccountClaim() != null && !resource.getAccountClaim().getOwner().equals(user))
+    		throw new HumanVisibleException("This email address is already claimed by someone else.");
+    	
 		String link = getClaimVerifierLink(viewpoint, user, resource);
 		MimeMessage message = mailer.createMessage(viewpoint, Mailer.SpecialSender.VERIFIER, resource.getEmail());
 		

Modified: dumbhippo/trunk/server/src/com/dumbhippo/server/impl/FeedSystemBean.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/server/impl/FeedSystemBean.java	2008-09-29 22:17:31 UTC (rev 7516)
+++ dumbhippo/trunk/server/src/com/dumbhippo/server/impl/FeedSystemBean.java	2008-10-20 21:50:28 UTC (rev 7517)
@@ -199,8 +199,12 @@
 		String guid = syndEntry.getUri();
 		// Null does occur in practice, if rarely, we just silently such entries
 		// assuming that they won't be interesting things to post in any case. 
-		if (guid == null) 
-			throw new NoEntryGuidException();
+		if (guid == null) {
+			logger.debug("SyndEntry did not have a uri, will try to use the link which is {}", syndEntry.getLink());
+			guid = syndEntry.getLink();
+			if (guid == null)
+			    throw new NoEntryGuidException();
+		}
 		
 		if (guid.length() <= FeedEntry.MAX_ENTRY_GUID_LENGTH)
 			return guid;
@@ -351,7 +355,8 @@
 			try {
 				guid = makeEntryGuid(syndEntry);
 			} catch (NoEntryGuidException e1) {
-				continue; // Silently ignore; its hard to log usefully
+				logger.warn("Could not make entry Guid");
+				continue;
 			}
 			
 			if (foundGuids.contains(guid))
@@ -410,11 +415,13 @@
 			try {
 				guid = makeEntryGuid(syndEntry);
 			} catch (NoEntryGuidException e1) {
+				logger.warn("Could not make entry Guid");
 				continue;
 			}
 			
-			if (foundGuids.contains(guid))
+			if (foundGuids.contains(guid)) {
 				continue;
+			}
 			
 			if (lastEntries.containsKey(guid)) {
 				// We don't try to update old entries, because it is painful and expensive:
@@ -450,7 +457,6 @@
 			try {
 				FeedEntry entry = createEntryFromSyndEntry(feed, syndFeed, syndEntry);
 				em.persist(entry);
-				
 				long age = now - entry.getDate().getTime();
 				
 				// never create/stack blocks for stuff older than 14 days, prevents 

Modified: dumbhippo/trunk/server/src/com/dumbhippo/server/impl/IdentitySpiderBean.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/server/impl/IdentitySpiderBean.java	2008-09-29 22:17:31 UTC (rev 7516)
+++ dumbhippo/trunk/server/src/com/dumbhippo/server/impl/IdentitySpiderBean.java	2008-10-20 21:50:28 UTC (rev 7517)
@@ -618,12 +618,19 @@
 					}
 				}						
 				
+				if (res instanceof EmailResource) {
+				     EmailDetails emailDetails = onlineDesktop.lookupEmailDetails((EmailResource)res);
+				     if (emailDetails != null && emailDetails.getGoogleServicesEnabled()) {
+				    	 // we want to send out a notification for the claimedOwner about a removed Google serviced e-mail
+				    	 onlineDesktop.onGoogleServicedEmailChange(SystemViewpoint.getInstance(), owner, (EmailResource)res);
+				    }						
+				}
 				return;
 			}
 		}
 		
 		logger.warn("No current claims for {} on {}, cancelling pending claims", owner,	res);
-
+		
 		claimVerifier.cancelClaimToken(owner, res);
 	}
 

Modified: dumbhippo/trunk/server/src/com/dumbhippo/server/impl/OnlineDesktopSystemBean.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/server/impl/OnlineDesktopSystemBean.java	2008-09-29 22:17:31 UTC (rev 7516)
+++ dumbhippo/trunk/server/src/com/dumbhippo/server/impl/OnlineDesktopSystemBean.java	2008-10-20 21:50:28 UTC (rev 7517)
@@ -79,9 +79,9 @@
 	}
 
 	public void setGoogleServicedEmail(Viewpoint viewpoint, User user, EmailResource email, boolean enabled) throws RetryException {
-		if (!(viewpoint instanceof SystemViewpoint) && !viewpoint.isOfUser(user))
+		if (!(viewpoint instanceof SystemViewpoint) && (user == null || !viewpoint.isOfUser(user)))
 			throw new RuntimeException("can only get your own enabled emails");
-		if (!(viewpoint instanceof SystemViewpoint) && !email.getAccountClaim().getOwner().equals(user))
+		if (!(viewpoint instanceof SystemViewpoint) && (user == null || !email.getAccountClaim().getOwner().equals(user)))
 			throw new RuntimeException("can only set Google state for emails you own");
 		EmailDetails ed = getEmailDetails(email);
 		ed.setGoogleServicesEnabled(enabled);

Modified: dumbhippo/trunk/server/src/com/dumbhippo/web/servlets/FacebookServlet.java
===================================================================
--- dumbhippo/trunk/server/src/com/dumbhippo/web/servlets/FacebookServlet.java	2008-09-29 22:17:31 UTC (rev 7516)
+++ dumbhippo/trunk/server/src/com/dumbhippo/web/servlets/FacebookServlet.java	2008-10-20 21:50:28 UTC (rev 7517)
@@ -265,7 +265,7 @@
 					    		accountsSetSuccessful.add(ExternalAccountType.FLICKR);
 					    	} else {
 					    		Method setAccount = httpMethods.getClass().getMethod("doSet" + entry.getKey().getDomNodeIdName() + "Account",
-					    				                                             new Class[] {XmlBuilder.class, UserViewpoint.class, String.class});	
+					    				                                             new Class[] {XmlBuilder.class, UserViewpoint.class, String.class, String.class});	
 					    		XmlBuilder resultXml = new XmlBuilder();
 					    		resultXml.openElement("result");
 					    		setAccount.invoke(httpMethods, new Object[] {resultXml, userViewpoint, "mugshot", entryValue});



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