package in.partake.controller.action.auth; import in.partake.app.PartakeApp; import in.partake.app.PartakeConfiguration; import in.partake.base.PartakeException; import in.partake.model.IPartakeDAOs; import in.partake.model.UserEx; import in.partake.model.access.DBAccess; import in.partake.model.access.Transaction; import in.partake.model.dao.DAOException; import in.partake.model.dao.PartakeConnection; import in.partake.model.daofacade.UserDAOFacade; import in.partake.model.dto.User; import in.partake.model.dto.UserOpenIDLink; import in.partake.resource.Constants; import in.partake.resource.MessageCode; import in.partake.resource.ServerErrorCode; import in.partake.resource.UserErrorCode; import in.partake.session.OpenIDLoginInformation; import java.util.HashMap; import java.util.Map; import java.util.UUID; import org.openid4java.OpenIDException; import org.openid4java.discovery.DiscoveryInformation; import play.cache.Cache; import play.mvc.Result; public class VerifyForOpenIDAction extends AbstractOpenIDAction { public static Result get() throws DAOException, PartakeException { return new VerifyForOpenIDAction().execute(); } // なんでかしらないけど、login と connect の openID の URL を一緒にしないと残念なことになる。 public Result doExecute() throws DAOException, PartakeException { String sessionId = session().get(Constants.Session.ID_KEY); assert sessionId != null; if (sessionId == null) return renderInvalid(UserErrorCode.INVALID_OPENID_PURPOSE); String receivingURL = receivingURL(); Map<String, Object> params = new HashMap<String, Object>(); for (Map.Entry<String, String[]> entry : request().queryString().entrySet()) params.put(entry.getKey(), entry.getValue()); OpenIDLoginInformation info = (OpenIDLoginInformation) Cache.get(Constants.Cache.OPENID_LOGIN_KEY_PREFIX + sessionId); String purpose = info.takeLoginPurpose(); try { if ("login".equals(purpose)) return verifyOpenIDForLogin(receivingURL, params, info.getDiscoveryInformation()); if ("connect".equals(purpose)) return verifyOpenIDForConnection(receivingURL, params, info.getDiscoveryInformation()); return renderInvalid(UserErrorCode.INVALID_OPENID_PURPOSE); } catch (OpenIDException e) { return renderError(ServerErrorCode.OPENID_ERROR, e); } } private Result verifyOpenIDForLogin(String receivingURL, Map<String, Object> params, DiscoveryInformation discoveryInformation) throws DAOException, OpenIDException, PartakeException { String identity = PartakeApp.getOpenIDService().getIdentifier(receivingURL, params, discoveryInformation); if (identity == null) return renderRedirect("/", MessageCode.MESSAGE_OPENID_LOGIN_FAILURE); // TODO: UserEx が identifier から取れるべき UserEx user = new GetUserFromOpenIDIdentifierTransaction(identity).execute(); if (user != null) { session().put(Constants.Session.USER_ID_KEY, user.getId()); if (getRedirectURL() == null) return renderRedirect("/"); else return renderRedirect(getRedirectURL()); } else { return renderRedirect("/", MessageCode.MESSAGE_OPENID_LOGIN_NOLINKAGE); } } private Result verifyOpenIDForConnection(String receivingURL, Map<String, Object> params, DiscoveryInformation discoveryInformation) throws DAOException, PartakeException, OpenIDException { User user = getLoginUser(); if (user == null) return renderLoginRequired(); String identity = PartakeApp.getOpenIDService().getIdentifier(receivingURL, params, discoveryInformation); if (identity == null) return renderInvalid(UserErrorCode.INVALID_OPENID_IDENTIFIER); new AddOpenIDTransaction(user.getId(), identity).execute(); return renderRedirect("/mypage#account", MessageCode.MESSAGE_OPENID_CONNECTION_SUCCESS); } private String receivingURL() { return PartakeConfiguration.toppath() + request().uri(); } } class GetUserFromOpenIDIdentifierTransaction extends DBAccess<UserEx> { private String identifier; GetUserFromOpenIDIdentifierTransaction(String identifier) { this.identifier = identifier; } @Override protected UserEx doExecute(PartakeConnection con, IPartakeDAOs daos) throws DAOException, PartakeException { UserOpenIDLink linkage = daos.getOpenIDLinkageAccess().findByOpenId(con, identifier); if (linkage == null) return null; return UserDAOFacade.getUserEx(con, daos, linkage.getUserId()); } } class AddOpenIDTransaction extends Transaction<Void> { private String userId; private String identifier; public AddOpenIDTransaction(String userId, String identifier) { this.userId = userId; this.identifier = identifier; } @Override protected Void doExecute(PartakeConnection con, IPartakeDAOs daos) throws DAOException, PartakeException { UUID id = daos.getOpenIDLinkageAccess().getFreshId(con); daos.getOpenIDLinkageAccess().put(con, new UserOpenIDLink(id, userId, identifier)); return null; } }