package in.partake.controller.action.auth; import in.partake.app.PartakeApp; import in.partake.app.PartakeConfiguration; import in.partake.base.PartakeException; import in.partake.base.TimeUtil; import in.partake.controller.action.AbstractPartakeAction; import in.partake.model.IPartakeDAOs; import in.partake.model.UserEx; import in.partake.model.access.Transaction; import in.partake.model.dao.DAOException; import in.partake.model.dao.PartakeConnection; import in.partake.model.dto.User; import in.partake.model.dto.UserTwitterLink; import in.partake.resource.Constants; import in.partake.resource.MessageCode; import in.partake.resource.ServerErrorCode; import in.partake.resource.UserErrorCode; import in.partake.service.ITwitterService; import in.partake.session.TwitterLoginInformation; import java.util.UUID; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.StringUtils; import play.cache.Cache; import play.mvc.Result; import twitter4j.TwitterException; public class VerifyForTwitterAction extends AbstractPartakeAction { public static Result get() throws DAOException, PartakeException { return new VerifyForTwitterAction().execute(); } public Result doExecute() throws DAOException, PartakeException { String verifier = getParameter("oauth_verifier"); if (StringUtils.isBlank(verifier)) return renderInvalid(UserErrorCode.INVALID_OAUTH_VERIFIER); String sessionId = session().get(Constants.Session.ID_KEY); assert sessionId != null; TwitterLoginInformation loginInformation = (TwitterLoginInformation) Cache.get(Constants.Cache.TWITTER_LOGIN_KEY_PREFIX + sessionId); if (loginInformation == null) return renderInvalid(UserErrorCode.UNEXPECTED_REQUEST); Cache.set(Constants.Cache.TWITTER_LOGIN_KEY_PREFIX + sessionId, null); MessageCode messageCode = null; try { ITwitterService twitterService = PartakeApp.getTwitterService(); UserTwitterLink linkage = twitterService.createTwitterLinkageFromLoginInformation(loginInformation, verifier); UserEx user = new VerifyForTwitterActionTransaction(linkage).execute(); session().put(Constants.Session.USER_ID_KEY, user.getId()); messageCode = MessageCode.MESSAGE_AUTH_LOGIN; } catch (TwitterException e) { return renderError(ServerErrorCode.TWITTER_OAUTH_ERROR, e); } String redirectURL = loginInformation.getRedirectURL(); if (StringUtils.isEmpty(redirectURL)) return renderRedirect("/", messageCode); // If the redirect page is the error page, we do not want to show it. Showing the top page is better. // TODO(mayah): We should not put these values here. String errorPagePaths[] = new String[] { "/error", "/notfound", "/invalid", "/prohibited", "/forbidden", "/loginRequired" }; for (String errorPagePath : errorPagePaths) { String errorPageURL = PartakeConfiguration.toppath() + errorPagePath; if (redirectURL.startsWith(errorPageURL)) return renderRedirect("/", messageCode); } return renderRedirect(redirectURL, messageCode); } } class VerifyForTwitterActionTransaction extends Transaction<UserEx> { private UserTwitterLink twitterLinkageEmbryo; public VerifyForTwitterActionTransaction(UserTwitterLink linkage) { this.twitterLinkageEmbryo = linkage; } @Override protected UserEx doExecute(PartakeConnection con, IPartakeDAOs daos) throws DAOException, PartakeException { // Twitter Linkage から User を引いてくる。 // 対応する user がいない場合は、user を作成して Twitter Linkage を付与する try { // 1. まず TwitterLinkage をアップデート UserTwitterLink twitterLinkage = updateTwitterLinkage(con, daos, twitterLinkageEmbryo); // 2. 対応するユーザーを生成 UserEx user = getUserFromTwitterLinkage(con, daos, twitterLinkage); return user; } catch (TwitterException e) { throw new PartakeException(ServerErrorCode.TWITTER_OAUTH_ERROR, e); } } private UserTwitterLink updateTwitterLinkage(PartakeConnection con, IPartakeDAOs daos, UserTwitterLink twitterLinkageEmbryo) throws DAOException, TwitterException { UserTwitterLink twitterLinkage = daos.getTwitterLinkageAccess().findByTwitterId(con, twitterLinkageEmbryo.getTwitterId()); if (twitterLinkage == null || twitterLinkage.getUserId() == null) { String userId = daos.getUserAccess().getFreshId(con); UUID id = daos.getTwitterLinkageAccess().getFreshId(con); twitterLinkageEmbryo.setId(id); twitterLinkageEmbryo.setUserId(userId); } else { twitterLinkageEmbryo.setId(twitterLinkage.getId()); twitterLinkageEmbryo.setUserId(twitterLinkage.getUserId()); } daos.getTwitterLinkageAccess().put(con, twitterLinkageEmbryo); return twitterLinkageEmbryo; } private UserEx getUserFromTwitterLinkage(PartakeConnection con, IPartakeDAOs daos, UserTwitterLink twitterLinkage) throws DAOException, TwitterException { String userId = twitterLinkage.getUserId(); User user = daos.getUserAccess().find(con, userId); if (user == null) { user = new User(userId, twitterLinkage.getScreenName(), twitterLinkage.getProfileImageURL(), TimeUtil.getCurrentDateTime(), null, false); daos.getUserAccess().put(con, user); user.freeze(); } else { if (!verifyUserProfiles(user, twitterLinkage)) { user = new User(user); user.setScreenName(twitterLinkage.getScreenName()); user.setProfileImageURL(twitterLinkage.getProfileImageURL()); daos.getUserAccess().put(con, user); user.freeze(); } } return new UserEx(user, twitterLinkage); } /** * Verifies whether the screenName & profileImageURL of the user are the same<br> * with the original twitterLinkage ones. * @param user * @param twitterLinkage * @return true when the data are the same. */ private boolean verifyUserProfiles(User user, UserTwitterLink twitterLinkage) { return ObjectUtils.equals(user.getScreenName(), twitterLinkage.getScreenName()) && ObjectUtils.equals(user.getProfileImageURL(), twitterLinkage.getProfileImageURL()); } }