You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by sh...@apache.org on 2015/06/30 20:38:17 UTC
svn commit: r1688503 [2/2] - in /ofbiz/trunk: ./ specialpurpose/
specialpurpose/ecommerce/webapp/ecommerce/customer/
specialpurpose/ecommerce/webapp/ecomseo/WEB-INF/
specialpurpose/ecommerce/widget/ specialpurpose/passport/
specialpurpose/passport/conf...
Added: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/GitHubAuthenticator.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/GitHubAuthenticator.java?rev=1688503&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/GitHubAuthenticator.java (added)
+++ ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/GitHubAuthenticator.java Tue Jun 30 18:38:16 2015
@@ -0,0 +1,416 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.passport.user;
+
+import java.util.Locale;
+import java.util.Map;
+import java.io.IOException;
+import java.io.Serializable;
+import java.sql.Timestamp;
+
+import javax.transaction.Transaction;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.cookie.CookiePolicy;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.params.HttpMethodParams;
+import org.ofbiz.passport.event.GitHubEvents;
+import org.ofbiz.passport.user.GitHubUserGroupMapper;
+import org.ofbiz.passport.util.PassportUtil;
+import org.ofbiz.common.authentication.api.Authenticator;
+import org.ofbiz.common.authentication.api.AuthenticatorException;
+import org.ofbiz.service.LocalDispatcher;
+import org.ofbiz.service.GenericServiceException;
+import org.ofbiz.service.ServiceUtil;
+import org.ofbiz.entity.Delegator;
+import org.ofbiz.entity.GenericValue;
+import org.ofbiz.entity.GenericEntityException;
+import org.ofbiz.entity.transaction.TransactionUtil;
+import org.ofbiz.entity.transaction.GenericTransactionException;
+import org.ofbiz.entity.util.EntityUtil;
+import org.ofbiz.base.conversion.ConversionException;
+import org.ofbiz.base.conversion.JSONConverters.JSONToMap;
+import org.ofbiz.base.lang.JSON;
+import org.ofbiz.base.util.UtilProperties;
+import org.ofbiz.base.util.Debug;
+import org.ofbiz.base.util.UtilMisc;
+import org.ofbiz.base.util.UtilDateTime;
+import org.ofbiz.base.util.UtilValidate;
+
+import javolution.util.FastMap;
+
+/**
+ * GitHub OFBiz Authenticator
+ */
+public class GitHubAuthenticator implements Authenticator {
+
+ private static final String module = GitHubAuthenticator.class.getName();
+
+ public static final String props = "gitHubAuth.properties";
+
+ public static final String resource = "PassportUiLabels";
+
+ protected LocalDispatcher dispatcher;
+
+ protected Delegator delegator;
+
+ /**
+ * Method called when authenticator is first initialized (the delegator
+ * object can be obtained from the LocalDispatcher)
+ *
+ * @param dispatcher The ServiceDispatcher to use for this Authenticator
+ */
+ public void initialize(LocalDispatcher dispatcher) {
+ this.dispatcher = dispatcher;
+ this.delegator = dispatcher.getDelegator();
+ }
+
+ /**
+ * Method to authenticate a user.
+ *
+ * For GitHub users, we only check if the username(userLoginId) exists an
+ * externalAuthId, and the externalAuthId has a valid accessToken in
+ * GitHubUser entity.
+ *
+ * @param username User's username
+ * @param password User's password
+ * @param isServiceAuth true if authentication is for a service call
+ * @return true if the user is authenticated
+ * @throws org.ofbiz.common.authentication.api.AuthenticatorException
+ * when a fatal error occurs during authentication
+ */
+ public boolean authenticate(String userLoginId, String password, boolean isServiceAuth) throws AuthenticatorException {
+ Map<String, Object> user = null;
+ GetMethod getMethod = null;
+ try {
+ GenericValue userLogin = delegator.findOne("UserLogin", UtilMisc.toMap("userLoginId", userLoginId), false);
+ String externalAuthId = userLogin.getString("externalAuthId");
+ GenericValue gitHubUser = delegator.findOne("GitHubUser", UtilMisc.toMap("gitHubUserId", externalAuthId), false);
+ if (UtilValidate.isNotEmpty(gitHubUser)) {
+ String accessToken = gitHubUser.getString("accessToken");
+ String tokenType = gitHubUser.getString("tokenType");
+ if (UtilValidate.isNotEmpty(accessToken)) {
+ getMethod = new GetMethod(GitHubEvents.ApiEndpoint + GitHubEvents.UserApiUri);
+ user = GitHubAuthenticator.getUserInfo(getMethod, accessToken, tokenType, Locale.getDefault());
+ }
+ }
+ } catch (GenericEntityException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ } catch (HttpException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ } catch (IOException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ } catch (AuthenticatorException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ } finally {
+ if (getMethod != null) {
+ getMethod.releaseConnection();
+ }
+ }
+
+ Debug.logInfo("GitHub auth called; returned user info: " + user, module);
+ return user != null;
+ }
+
+ /**
+ * Logs a user out
+ *
+ * @param username User's username
+ * @throws org.ofbiz.common.authentication.api.AuthenticatorException
+ * when logout fails
+ */
+ public void logout(String username) throws AuthenticatorException {
+ }
+
+ /**
+ * Reads user information and syncs it to OFBiz (i.e. UserLogin, Person, etc)
+ *
+ * @param userLoginId
+ * @throws org.ofbiz.common.authentication.api.AuthenticatorException
+ * user synchronization fails
+ */
+ public void syncUser(String userLoginId) throws AuthenticatorException {
+ Map<String, Object> userMap = getGitHubUserinfo(userLoginId);
+ GenericValue system;
+ try {
+ system = delegator.findOne("UserLogin", UtilMisc.toMap("userLoginId", "system"), true);
+ } catch (GenericEntityException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ }
+
+ GenericValue userLogin;
+ try {
+ userLogin = EntityUtil.getFirst(delegator.findByAnd("UserLogin", UtilMisc.toMap("externalAuthId", (String) userMap.get("id")), null, false));
+ } catch (GenericEntityException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ }
+
+ // suspend the current transaction and load the user
+ Transaction parentTx = null;
+ boolean beganTransaction = false;
+
+ try {
+ try {
+ parentTx = TransactionUtil.suspend();
+ } catch (GenericTransactionException e) {
+ Debug.logError(e, "Could not suspend transaction: " + e.getMessage(), module);
+ }
+
+ try {
+ beganTransaction = TransactionUtil.begin();
+
+ if (userLogin == null) {
+ // create the user
+ createUser(userMap, system);
+ } else {
+ // update the user information
+ updateUser(userMap, system, userLogin);
+ }
+
+ } catch (GenericTransactionException e) {
+ Debug.logError(e, "Could not suspend transaction: " + e.getMessage(), module);
+ } finally {
+ try {
+ TransactionUtil.commit(beganTransaction);
+ } catch (GenericTransactionException e) {
+ Debug.logError(e, "Could not commit nested transaction: " + e.getMessage(), module);
+ }
+ }
+ } finally {
+ // resume/restore parent transaction
+ if (parentTx != null) {
+ try {
+ TransactionUtil.resume(parentTx);
+ Debug.logVerbose("Resumed the parent transaction.", module);
+ } catch (GenericTransactionException e) {
+ Debug.logError(e, "Could not resume parent nested transaction: " + e.getMessage(), module);
+ }
+ }
+ }
+ }
+
+ private Map<String, Object> getGitHubUserinfo(String userLoginId) throws AuthenticatorException {
+ Map<String, Object> user = null;
+ GetMethod getMethod = null;
+ try {
+ GenericValue userLogin = delegator.findOne("UserLogin", UtilMisc.toMap("userLoginId", userLoginId), false);
+ String externalAuthId = userLogin.getString("externalAuthId");
+ GenericValue gitHubUser = delegator.findOne("GitHubUser", UtilMisc.toMap("gitHubUserId", externalAuthId), false);
+ if (UtilValidate.isNotEmpty(gitHubUser)) {
+ String accessToken = gitHubUser.getString("accessToken");
+ String tokenType = gitHubUser.getString("tokenType");
+ if (UtilValidate.isNotEmpty(accessToken)) {
+ getMethod = new GetMethod(GitHubEvents.ApiEndpoint + GitHubEvents.UserApiUri);
+ user = getUserInfo(getMethod, accessToken, tokenType, Locale.getDefault());
+ }
+ }
+ } catch (GenericEntityException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ } catch (HttpException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ } catch (IOException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ } catch (AuthenticatorException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ } finally {
+ if (getMethod != null) {
+ getMethod.releaseConnection();
+ }
+ }
+ return user;
+ }
+
+ public String createUser(Map<String, Object> userMap) throws AuthenticatorException {
+ GenericValue system;
+ try {
+ system = delegator.findOne("UserLogin", UtilMisc.toMap("userLoginId", "system"), true);
+ } catch (GenericEntityException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ }
+ return createUser(userMap, system);
+ }
+
+ private String createUser(Map<String, Object> userMap, GenericValue system) throws AuthenticatorException {
+ // create person + userLogin
+ Map<String, Serializable> createPersonUlMap = FastMap.newInstance();
+ String userLoginId = delegator.getNextSeqId("UserLogin");
+ if (userMap.containsKey("name")) {
+ // use github's name as OFBiz's lastName
+ createPersonUlMap.put("lastName", (String) userMap.get("name"));
+ }
+ if (userMap.containsKey("login")) {
+ createPersonUlMap.put("externalAuthId", (String) userMap.get("login"));
+ }
+ // createPersonUlMap.put("externalId", user.getUserId());
+ createPersonUlMap.put("userLoginId", userLoginId);
+ createPersonUlMap.put("currentPassword", "[EXTERNAL]");
+ createPersonUlMap.put("currentPasswordVerify", "[EXTERNAL]");
+ createPersonUlMap.put("userLogin", system);
+ Map<String, Object> createPersonResult;
+ try {
+ createPersonResult = dispatcher.runSync("createPersonAndUserLogin", createPersonUlMap);
+ } catch (GenericServiceException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ }
+ if (ServiceUtil.isError(createPersonResult)) {
+ throw new AuthenticatorException(ServiceUtil.getErrorMessage(createPersonResult));
+ }
+ String partyId = (String) createPersonResult.get("partyId");
+
+ // give this person a role of CUSTOMER
+ GenericValue partyRole = delegator.makeValue("PartyRole", UtilMisc.toMap("partyId", partyId, "roleTypeId", "CUSTOMER"));
+ try {
+ delegator.create(partyRole);
+ } catch (GenericEntityException e) {
+ Debug.logError(e, module);
+ throw new AuthenticatorException(e.getMessage(), e);
+ }
+
+ // create email
+ if (userMap.containsKey("email")) {
+ Map<String, Serializable> createEmailMap = FastMap.newInstance();
+ createEmailMap.put("emailAddress", (String) userMap.get("email"));
+ createEmailMap.put("contactMechPurposeTypeId", "PRIMARY_EMAIL");
+ createEmailMap.put("partyId", partyId);
+ createEmailMap.put("userLogin", system);
+ Map<String, Object> createEmailResult;
+ try {
+ createEmailResult = dispatcher.runSync("createPartyEmailAddress", createEmailMap);
+ } catch (GenericServiceException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ }
+ if (ServiceUtil.isError(createEmailResult)) {
+ throw new AuthenticatorException(ServiceUtil.getErrorMessage(createEmailResult));
+ }
+ }
+
+ // create security group(s)
+ Timestamp now = UtilDateTime.nowTimestamp();
+ for (String securityGroup : (new GitHubUserGroupMapper(new String[] {(String) userMap.get("type")}).getSecurityGroups())) {
+ // check and make sure the security group exists
+ GenericValue secGroup = null;
+ try {
+ secGroup = delegator.findOne("SecurityGroup", UtilMisc.toMap("groupId", securityGroup), true);
+ } catch (GenericEntityException e) {
+ Debug.logError(e, e.getMessage(), module);
+ }
+
+ // add it to the user if it exists
+ if (secGroup != null) {
+ Map<String, Serializable> createSecGrpMap = FastMap.newInstance();
+ createSecGrpMap.put("userLoginId", userLoginId);
+ createSecGrpMap.put("groupId", securityGroup);
+ createSecGrpMap.put("fromDate", now);
+ createSecGrpMap.put("userLogin", system);
+
+ Map<String, Object> createSecGrpResult;
+ try {
+ createSecGrpResult = dispatcher.runSync("addUserLoginToSecurityGroup", createSecGrpMap);
+ } catch (GenericServiceException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ }
+ if (ServiceUtil.isError(createSecGrpResult)) {
+ throw new AuthenticatorException(ServiceUtil.getErrorMessage(createSecGrpResult));
+ }
+ }
+ }
+ return userLoginId;
+ }
+
+ private void updateUser(Map<String, Object> userMap, GenericValue system, GenericValue userLogin) throws AuthenticatorException {
+ // TODO implement me
+ }
+
+ /**
+ * Updates a user's password.
+ *
+ * @param username User's username
+ * @param password User's current password
+ * @param newPassword User's new password
+ * @throws org.ofbiz.common.authentication.api.AuthenticatorException
+ * when update password fails
+ */
+ public void updatePassword(String username, String password, String newPassword) throws AuthenticatorException {
+ Debug.logInfo("Calling GitHub:updatePassword() - ignored!!!", module);
+ }
+
+ /**
+ * Weight of this authenticator (lower weights are run first)
+ *
+ * @return the weight of this Authenicator
+ */
+ public float getWeight() {
+ return 1;
+ }
+
+ /**
+ * Is the user synchronzied back to OFBiz
+ *
+ * @return true if the user record is copied to the OFB database
+ */
+ public boolean isUserSynchronized() {
+ return true;
+ }
+
+ /**
+ * Is this expected to be the only authenticator, if so errors will be thrown when users cannot be found
+ *
+ * @return true if this is expected to be the only Authenticator
+ */
+ public boolean isSingleAuthenticator() {
+ return false;
+ }
+
+ /**
+ * Flag to test if this Authenticator is enabled
+ *
+ * @return true if the Authenticator is enabled
+ */
+ public boolean isEnabled() {
+ return "true".equalsIgnoreCase(UtilProperties.getPropertyValue(props, "github.authenticator.enabled", "true"));
+ }
+
+ public static Map<String, Object> getUserInfo(GetMethod getMethod, String accessToken, String tokenType, Locale locale) throws HttpException, IOException, AuthenticatorException {
+ JSON userInfo = null;
+ HttpClient jsonClient = new HttpClient();
+ HttpMethodParams params = new HttpMethodParams();
+ params.setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
+ getMethod.setParams(params);
+ getMethod.setRequestHeader(PassportUtil.AUTHORIZATION_HEADER, tokenType + " " + accessToken);
+ getMethod.setRequestHeader(PassportUtil.ACCEPT_HEADER, "application/json");
+ jsonClient.executeMethod(getMethod);
+ if (getMethod.getStatusCode() == HttpStatus.SC_OK) {
+ Debug.logInfo("Json Response from GitHub: " + getMethod.getResponseBodyAsString(), module);
+ userInfo = JSON.from(getMethod.getResponseBodyAsString());
+ } else {
+ String errMsg = UtilProperties.getMessage(resource, "GetOAuth2AccessTokenError", UtilMisc.toMap("error", getMethod.getResponseBodyAsString()), locale);
+ throw new AuthenticatorException(errMsg);
+ }
+ JSONToMap jsonMap = new JSONToMap();
+ Map<String, Object> userMap;
+ try {
+ userMap = jsonMap.convert(userInfo);
+ } catch (ConversionException e) {
+ throw new AuthenticatorException(e.getMessage());
+ }
+ return userMap;
+ }
+}
Propchange: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/GitHubAuthenticator.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/GitHubAuthenticator.java
------------------------------------------------------------------------------
svn:keywords = Date Rev Author URL Id
Propchange: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/GitHubAuthenticator.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/GitHubUserGroupMapper.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/GitHubUserGroupMapper.java?rev=1688503&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/GitHubUserGroupMapper.java (added)
+++ ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/GitHubUserGroupMapper.java Tue Jun 30 18:38:16 2015
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.passport.user;
+
+import java.util.List;
+import java.util.Properties;
+import java.util.Arrays;
+import java.util.Set;
+
+import org.ofbiz.base.util.UtilProperties;
+
+import javolution.util.FastList;
+import javolution.util.FastSet;
+
+/**
+ * GitHub UserGroupMapper
+ */
+public class GitHubUserGroupMapper {
+
+ protected List<String> groups;
+
+ public GitHubUserGroupMapper(String[] groups) {
+ this.groups = Arrays.asList(groups);
+ }
+
+ public GitHubUserGroupMapper(String group) {
+ if (groups == null) {
+ groups = FastList.newInstance();
+ }
+ groups.add(group);
+ }
+
+ public Set<String> getSecurityGroups() {
+ Properties props = UtilProperties.getProperties(GitHubAuthenticator.props);
+
+ Set<String> secGroups = FastSet.newInstance();
+ boolean running = true;
+ int index = 1;
+
+ while (running) {
+ String groupStr = (String) props.get("github.group.map." + index);
+ if (groupStr == null) {
+ running = false;
+ } else {
+ String[] groupSplit = groupStr.split("=");
+ if (groupSplit.length == 2) {
+ if (groups.contains(groupSplit[0])) {
+ secGroups.add(groupSplit[1]);
+ }
+ }
+ }
+ index++;
+ }
+ return secGroups;
+ }
+}
Propchange: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/GitHubUserGroupMapper.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/GitHubUserGroupMapper.java
------------------------------------------------------------------------------
svn:keywords = Date Rev Author URL Id
Propchange: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/GitHubUserGroupMapper.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/LinkedInAuthenticator.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/LinkedInAuthenticator.java?rev=1688503&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/LinkedInAuthenticator.java (added)
+++ ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/LinkedInAuthenticator.java Tue Jun 30 18:38:16 2015
@@ -0,0 +1,471 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.passport.user;
+
+import java.util.Locale;
+import java.util.Map;
+import java.io.IOException;
+import java.io.Serializable;
+import java.sql.Timestamp;
+
+import javax.transaction.Transaction;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.cookie.CookiePolicy;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.params.HttpMethodParams;
+import org.ofbiz.passport.event.LinkedInEvents;
+import org.ofbiz.common.authentication.api.Authenticator;
+import org.ofbiz.common.authentication.api.AuthenticatorException;
+import org.ofbiz.service.LocalDispatcher;
+import org.ofbiz.service.GenericServiceException;
+import org.ofbiz.service.ServiceUtil;
+import org.ofbiz.entity.Delegator;
+import org.ofbiz.entity.GenericValue;
+import org.ofbiz.entity.GenericEntityException;
+import org.ofbiz.entity.transaction.TransactionUtil;
+import org.ofbiz.entity.transaction.GenericTransactionException;
+import org.ofbiz.entity.util.EntityUtil;
+import org.ofbiz.base.util.UtilProperties;
+import org.ofbiz.base.util.Debug;
+import org.ofbiz.base.util.UtilMisc;
+import org.ofbiz.base.util.UtilDateTime;
+import org.ofbiz.base.util.UtilValidate;
+import org.ofbiz.base.util.UtilXml;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+import javolution.util.FastMap;
+
+/**
+ * LinkedIn OFBiz Authenticator
+ */
+public class LinkedInAuthenticator implements Authenticator {
+
+ private static final String module = LinkedInAuthenticator.class.getName();
+
+ public static final String props = "linkedInAuth.properties";
+
+ public static final String resource = "PassportUiLabels";
+
+ protected LocalDispatcher dispatcher;
+
+ protected Delegator delegator;
+
+ /**
+ * Method called when authenticator is first initialized (the delegator
+ * object can be obtained from the LocalDispatcher)
+ *
+ * @param dispatcher The ServiceDispatcher to use for this Authenticator
+ */
+ public void initialize(LocalDispatcher dispatcher) {
+ this.dispatcher = dispatcher;
+ this.delegator = dispatcher.getDelegator();
+ }
+
+ /**
+ * Method to authenticate a user.
+ *
+ * For LinkedIn users, we only check if the username(userLoginId) exists an
+ * externalAuthId, and the externalAuthId has a valid accessToken in
+ * LinkedInUser entity.
+ *
+ * @param username User's username
+ * @param password User's password
+ * @param isServiceAuth true if authentication is for a service call
+ * @return true if the user is authenticated
+ * @throws org.ofbiz.common.authentication.api.AuthenticatorException
+ * when a fatal error occurs during authentication
+ */
+ public boolean authenticate(String userLoginId, String password, boolean isServiceAuth) throws AuthenticatorException {
+ Document user = null;
+ GetMethod getMethod = null;
+ try {
+ GenericValue userLogin = delegator.findOne("UserLogin", UtilMisc.toMap("userLoginId", userLoginId), false);
+ String externalAuthId = userLogin.getString("externalAuthId");
+ GenericValue linkedInUser = delegator.findOne("LinkedInUser", UtilMisc.toMap("linedInUserId", externalAuthId), false);
+ if (UtilValidate.isNotEmpty(linkedInUser)) {
+ String accessToken = linkedInUser.getString("accessToken");
+ if (UtilValidate.isNotEmpty(accessToken)) {
+ getMethod = new GetMethod(LinkedInEvents.TokenEndpoint + LinkedInEvents.UserApiUri + "?oauth2_access_token=" + accessToken);
+ user = LinkedInAuthenticator.getUserInfo(getMethod, Locale.getDefault());
+ }
+ }
+ } catch (GenericEntityException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ } catch (HttpException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ } catch (IOException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ } catch (AuthenticatorException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ } catch (SAXException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ } catch (ParserConfigurationException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ } finally {
+ if (getMethod != null) {
+ getMethod.releaseConnection();
+ }
+ }
+
+ Debug.logInfo("LinkedIn auth called; returned user info: " + user, module);
+ return user != null;
+ }
+
+ /**
+ * Logs a user out
+ *
+ * @param username User's username
+ * @throws org.ofbiz.common.authentication.api.AuthenticatorException
+ * when logout fails
+ */
+ public void logout(String username) throws AuthenticatorException {
+ }
+
+ /**
+ * Reads user information and syncs it to OFBiz (i.e. UserLogin, Person, etc)
+ *
+ * @param userLoginId
+ * @throws org.ofbiz.common.authentication.api.AuthenticatorException
+ * user synchronization fails
+ */
+ public void syncUser(String userLoginId) throws AuthenticatorException {
+ Document user = getLinkedInUserinfo(userLoginId);
+
+ GenericValue system;
+ try {
+ system = delegator.findOne("UserLogin", UtilMisc.toMap("userLoginId", "system"), true);
+ } catch (GenericEntityException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ }
+
+ GenericValue userLogin;
+ try {
+ userLogin = EntityUtil.getFirst(delegator.findByAnd("UserLogin", UtilMisc.toMap("externalAuthId", getLinkedInUserId(user)), null, false));
+ } catch (GenericEntityException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ }
+
+ // suspend the current transaction and load the user
+ Transaction parentTx = null;
+ boolean beganTransaction = false;
+
+ try {
+ try {
+ parentTx = TransactionUtil.suspend();
+ } catch (GenericTransactionException e) {
+ Debug.logError(e, "Could not suspend transaction: " + e.getMessage(), module);
+ }
+
+ try {
+ beganTransaction = TransactionUtil.begin();
+
+ if (userLogin == null) {
+ // create the user
+ createUser(user, system);
+ } else {
+ // update the user information
+ updateUser(user, system, userLogin);
+ }
+
+ } catch (GenericTransactionException e) {
+ Debug.logError(e, "Could not suspend transaction: " + e.getMessage(), module);
+ } finally {
+ try {
+ TransactionUtil.commit(beganTransaction);
+ } catch (GenericTransactionException e) {
+ Debug.logError(e, "Could not commit nested transaction: " + e.getMessage(), module);
+ }
+ }
+ } finally {
+ // resume/restore parent transaction
+ if (parentTx != null) {
+ try {
+ TransactionUtil.resume(parentTx);
+ Debug.logVerbose("Resumed the parent transaction.", module);
+ } catch (GenericTransactionException e) {
+ Debug.logError(e, "Could not resume parent nested transaction: " + e.getMessage(), module);
+ }
+ }
+ }
+ }
+
+ private Document getLinkedInUserinfo(String userLoginId) throws AuthenticatorException {
+ Document user = null;
+ GetMethod getMethod = null;
+ try {
+ GenericValue userLogin = delegator.findOne("UserLogin", UtilMisc.toMap("userLoginId", userLoginId), false);
+ String externalAuthId = userLogin.getString("externalAuthId");
+ GenericValue linkedInUser = delegator.findOne("LinkedInUser", UtilMisc.toMap("linkedInUserId", externalAuthId), false);
+ if (UtilValidate.isNotEmpty(linkedInUser)) {
+ String accessToken = linkedInUser.getString("accessToken");
+ if (UtilValidate.isNotEmpty(accessToken)) {
+ getMethod = new GetMethod(LinkedInEvents.TokenEndpoint + LinkedInEvents.UserApiUri + "?oauth2_access_token=" + accessToken);
+ user = getUserInfo(getMethod, Locale.getDefault());
+ }
+ }
+ } catch (GenericEntityException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ } catch (HttpException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ } catch (IOException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ } catch (AuthenticatorException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ } catch (SAXException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ } catch (ParserConfigurationException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ } finally {
+ if (getMethod != null) {
+ getMethod.releaseConnection();
+ }
+ }
+ return user;
+ }
+
+ public String createUser(Document user) throws AuthenticatorException {
+ GenericValue system;
+ try {
+ system = delegator.findOne("UserLogin", UtilMisc.toMap("userLoginId", "system"), true);
+ } catch (GenericEntityException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ }
+ return createUser(user, system);
+ }
+
+ private String createUser(Document user, GenericValue system) throws AuthenticatorException {
+ Map<String, String> userInfo = parseLinkedInUserInfo(user);
+
+ // create person + userLogin
+ Map<String, Serializable> createPersonUlMap = FastMap.newInstance();
+ String userLoginId = delegator.getNextSeqId("UserLogin");
+ if (userInfo.containsKey("firstName")) {
+ createPersonUlMap.put("firstName", userInfo.get("firstName"));
+ }
+ if (userInfo.containsKey("lastName")) {
+ createPersonUlMap.put("lastName", userInfo.get("lastName"));
+ }
+ if (userInfo.containsKey("userId")) {
+ createPersonUlMap.put("externalAuthId", userInfo.get("userId"));
+ }
+ // createPersonUlMap.put("externalId", user.getUserId());
+ createPersonUlMap.put("userLoginId", userLoginId);
+ createPersonUlMap.put("currentPassword", "[EXTERNAL]");
+ createPersonUlMap.put("currentPasswordVerify", "[EXTERNAL]");
+ createPersonUlMap.put("userLogin", system);
+ Map<String, Object> createPersonResult;
+ try {
+ createPersonResult = dispatcher.runSync("createPersonAndUserLogin", createPersonUlMap);
+ } catch (GenericServiceException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ }
+ if (ServiceUtil.isError(createPersonResult)) {
+ throw new AuthenticatorException(ServiceUtil.getErrorMessage(createPersonResult));
+ }
+ String partyId = (String) createPersonResult.get("partyId");
+
+ // give this person a role of CUSTOMER
+ GenericValue partyRole = delegator.makeValue("PartyRole", UtilMisc.toMap("partyId", partyId, "roleTypeId", "CUSTOMER"));
+ try {
+ delegator.create(partyRole);
+ } catch (GenericEntityException e) {
+ Debug.logError(e, module);
+ throw new AuthenticatorException(e.getMessage(), e);
+ }
+
+ // create email
+ if (userInfo.containsKey("emailAddress")) {
+ Map<String, Serializable> createEmailMap = FastMap.newInstance();
+ createEmailMap.put("emailAddress", userInfo.get("emailAddress"));
+ createEmailMap.put("contactMechPurposeTypeId", "PRIMARY_EMAIL");
+ createEmailMap.put("partyId", partyId);
+ createEmailMap.put("userLogin", system);
+ Map<String, Object> createEmailResult;
+ try {
+ createEmailResult = dispatcher.runSync("createPartyEmailAddress", createEmailMap);
+ } catch (GenericServiceException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ }
+ if (ServiceUtil.isError(createEmailResult)) {
+ throw new AuthenticatorException(ServiceUtil.getErrorMessage(createEmailResult));
+ }
+ }
+
+ // create security group(s)
+ Timestamp now = UtilDateTime.nowTimestamp();
+ for (String securityGroup : (new LinkedInUserGroupMapper(new String[] {"person"}).getSecurityGroups())) {
+ // check and make sure the security group exists
+ GenericValue secGroup = null;
+ try {
+ secGroup = delegator.findOne("SecurityGroup", UtilMisc.toMap("groupId", securityGroup), true);
+ } catch (GenericEntityException e) {
+ Debug.logError(e, e.getMessage(), module);
+ }
+
+ // add it to the user if it exists
+ if (secGroup != null) {
+ Map<String, Serializable> createSecGrpMap = FastMap.newInstance();
+ createSecGrpMap.put("userLoginId", userLoginId);
+ createSecGrpMap.put("groupId", securityGroup);
+ createSecGrpMap.put("fromDate", now);
+ createSecGrpMap.put("userLogin", system);
+
+ Map<String, Object> createSecGrpResult;
+ try {
+ createSecGrpResult = dispatcher.runSync("addUserLoginToSecurityGroup", createSecGrpMap);
+ } catch (GenericServiceException e) {
+ throw new AuthenticatorException(e.getMessage(), e);
+ }
+ if (ServiceUtil.isError(createSecGrpResult)) {
+ throw new AuthenticatorException(ServiceUtil.getErrorMessage(createSecGrpResult));
+ }
+ }
+ }
+ return userLoginId;
+ }
+
+ private void updateUser(Document user, GenericValue system, GenericValue userLogin) throws AuthenticatorException {
+ // TODO implement me
+ }
+
+ /**
+ * Updates a user's password.
+ *
+ * @param username User's username
+ * @param password User's current password
+ * @param newPassword User's new password
+ * @throws org.ofbiz.common.authentication.api.AuthenticatorException
+ * when update password fails
+ */
+ public void updatePassword(String username, String password, String newPassword) throws AuthenticatorException {
+ Debug.logInfo("Calling LinkedIn:updatePassword() - ignored!!!", module);
+ }
+
+ /**
+ * Weight of this authenticator (lower weights are run first)
+ *
+ * @return the weight of this Authenicator
+ */
+ public float getWeight() {
+ return 1;
+ }
+
+ /**
+ * Is the user synchronzied back to OFBiz
+ *
+ * @return true if the user record is copied to the OFB database
+ */
+ public boolean isUserSynchronized() {
+ return true;
+ }
+
+ /**
+ * Is this expected to be the only authenticator, if so errors will be thrown when users cannot be found
+ *
+ * @return true if this is expected to be the only Authenticator
+ */
+ public boolean isSingleAuthenticator() {
+ return false;
+ }
+
+ /**
+ * Flag to test if this Authenticator is enabled
+ *
+ * @return true if the Authenticator is enabled
+ */
+ public boolean isEnabled() {
+ return "true".equalsIgnoreCase(UtilProperties.getPropertyValue(props, "linked.authenticator.enabled", "true"));
+ }
+
+ public static Document getUserInfo(GetMethod getMethod, Locale locale) throws HttpException, IOException, AuthenticatorException, SAXException, ParserConfigurationException {
+ Document userInfo = null;
+ HttpClient jsonClient = new HttpClient();
+ HttpMethodParams params = new HttpMethodParams();
+ params.setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
+ getMethod.setParams(params);
+ jsonClient.executeMethod(getMethod);
+ if (getMethod.getStatusCode() == HttpStatus.SC_OK) {
+ Debug.logInfo("Json Response from LinkedIn: " + getMethod.getResponseBodyAsString(), module);
+ userInfo = UtilXml.readXmlDocument(getMethod.getResponseBodyAsString());
+ } else {
+ String errMsg = UtilProperties.getMessage(resource, "GetOAuth2AccessTokenError", UtilMisc.toMap("error", getMethod.getResponseBodyAsString()), locale);
+ throw new AuthenticatorException(errMsg);
+ }
+ return userInfo;
+ }
+
+ public static String getLinkedInUserId(Document userInfo) {
+ NodeList persons = userInfo.getElementsByTagName("person");
+ if (UtilValidate.isEmpty(persons) || persons.getLength() <= 0) {
+ return null;
+ }
+ Element standardProfileRequest = UtilXml.firstChildElement((Element) persons.item(0), "site-standard-profile-request");
+ Element url = UtilXml.firstChildElement(standardProfileRequest, "url");
+ if (UtilValidate.isNotEmpty(url)) {
+ String urlContent = url.getTextContent();
+ if (UtilValidate.isNotEmpty(urlContent)) {
+ String id = urlContent.substring(urlContent.indexOf("?id="));
+ id = id.substring(0, id.indexOf("&"));
+ Debug.logInfo("LinkedIn user id: " + id, module);
+ return id;
+ }
+ }
+ return null;
+ }
+
+ public static Map<String, String> parseLinkedInUserInfo(Document userInfo) {
+ Map<String, String> results = FastMap.newInstance();
+ NodeList persons = userInfo.getElementsByTagName("person");
+ if (UtilValidate.isEmpty(persons) || persons.getLength() <= 0) {
+ return results;
+ }
+ Element person = (Element) persons.item(0);
+ Element standardProfileRequest = UtilXml.firstChildElement(person, "site-standard-profile-request");
+ Element url = UtilXml.firstChildElement(standardProfileRequest, "url");
+ if (UtilValidate.isNotEmpty(url)) {
+ String urlContent = url.getTextContent();
+ if (UtilValidate.isNotEmpty(urlContent)) {
+ String id = urlContent.substring(urlContent.indexOf("?id="));
+ id = id.substring(0, id.indexOf("&"));
+ Debug.logInfo("LinkedIn user id: " + id, module);
+ results.put("userId", id);
+ }
+ }
+ Element firstNameElement = UtilXml.firstChildElement(person, "first-name");
+ if (UtilValidate.isNotEmpty(firstNameElement) && UtilValidate.isNotEmpty(firstNameElement.getTextContent())) {
+ results.put("firstName", firstNameElement.getTextContent());
+ }
+ Element lastNameElement = UtilXml.firstChildElement(person, "last-name");
+ if (UtilValidate.isNotEmpty(lastNameElement) && UtilValidate.isNotEmpty(lastNameElement.getTextContent())) {
+ results.put("lastName", lastNameElement.getTextContent());
+ }
+ Element emailElement = UtilXml.firstChildElement(person, "email-address");
+ if (UtilValidate.isNotEmpty(emailElement) && UtilValidate.isNotEmpty(emailElement.getTextContent())) {
+ results.put("emailAddress", emailElement.getTextContent());
+ }
+ return results;
+ }
+}
Propchange: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/LinkedInAuthenticator.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/LinkedInAuthenticator.java
------------------------------------------------------------------------------
svn:keywords = Date Rev Author URL Id
Propchange: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/LinkedInAuthenticator.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/LinkedInUserGroupMapper.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/LinkedInUserGroupMapper.java?rev=1688503&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/LinkedInUserGroupMapper.java (added)
+++ ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/LinkedInUserGroupMapper.java Tue Jun 30 18:38:16 2015
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.passport.user;
+
+import java.util.List;
+import java.util.Properties;
+import java.util.Arrays;
+import java.util.Set;
+
+import org.ofbiz.base.util.UtilProperties;
+
+import javolution.util.FastList;
+import javolution.util.FastSet;
+
+/**
+ * LinkedIn UserGroupMapper
+ */
+public class LinkedInUserGroupMapper {
+
+ protected List<String> groups;
+
+ public LinkedInUserGroupMapper(String[] groups) {
+ this.groups = Arrays.asList(groups);
+ }
+
+ public LinkedInUserGroupMapper(String group) {
+ if (groups == null) {
+ groups = FastList.newInstance();
+ }
+ groups.add(group);
+ }
+
+ public Set<String> getSecurityGroups() {
+ Properties props = UtilProperties.getProperties(LinkedInAuthenticator.props);
+
+ Set<String> secGroups = FastSet.newInstance();
+ boolean running = true;
+ int index = 1;
+
+ while (running) {
+ String groupStr = (String) props.get("linkedin.group.map." + index);
+ if (groupStr == null) {
+ running = false;
+ } else {
+ String[] groupSplit = groupStr.split("=");
+ if (groupSplit.length == 2) {
+ if (groups.contains(groupSplit[0])) {
+ secGroups.add(groupSplit[1]);
+ }
+ }
+ }
+ index++;
+ }
+ return secGroups;
+ }
+}
Propchange: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/LinkedInUserGroupMapper.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/LinkedInUserGroupMapper.java
------------------------------------------------------------------------------
svn:keywords = Date Rev Author URL Id
Propchange: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/LinkedInUserGroupMapper.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/util/PassportUtil.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/util/PassportUtil.java?rev=1688503&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/util/PassportUtil.java (added)
+++ ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/util/PassportUtil.java Tue Jun 30 18:38:16 2015
@@ -0,0 +1,196 @@
+/*******************************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *******************************************************************************/
+package org.ofbiz.passport.util;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.UnrecoverableKeyException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLContextBuilder;
+import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.ofbiz.base.util.Debug;
+
+public class PassportUtil {
+
+ public static final String module = PassportUtil.class.getName();
+
+ public static final String ClientIdLabel = "ClientId";
+
+ public static final String SecretLabel = "Secret";
+
+ public static final String ReturnUrlLabel = "ReturnUrl";
+
+ public static final String TokenEndpointLabel = "TokenEndpoint";
+
+ public static final String GrantTypeLabel = "grantType";
+
+ public static final String ContentTypeLabel = "contentType";
+
+ public static final String AUTHORIZATION_HEADER = "Authorization";
+
+ public static final String UserProfileUrlLabel = "UserProfileUrl";
+
+ public static final String GrantTypeParam = "grant_type";
+
+ public static final String ContentTypeParam = "Content-Type";
+
+ public static final String ACCEPT_HEADER = "Accept";
+
+ public static final String APPLICATION_JSON = "application/json";
+
+ public static final String RESTApiEndpointLabel = "RESTApiEndpoint";
+
+ public static final String COMMON_CODE = "code";
+
+ public static final String COMMON_SCOPE = "scope";
+
+ public static final String AuthorizationCodeGrantType = "authorization_code";
+
+ public static final String COMMON_STATE = "state";
+
+ public static final String COMMON_ERROR = "error";
+
+ public static final String COMMON_ERROR_DESCRIPTION = "error_description";
+
+ public static final String ApiKeyLabel = "apiKey";
+
+ public static final String SecretKeyLabel = "secretKey";
+
+ public static final String COMMON_CLIENT_ID = "clientId";
+
+ public static final String COMMON_RETURN_RUL = "returnUrl";
+
+ public static final String COMMON_CLIENT_SECRET = "clientSecret";
+
+ public static final String ApiIdLabel = "apiId";
+
+ public static final String AppKeyLabel = "appKey";
+
+ public static final String AppSecretLabel = "appSecret";
+
+ public static final String AppIdLabel = "appId";
+
+ public static final String COMMON_APP_KEY = "AppKey";
+
+ public static final String COMMON_APP_SECRET = "AppSecret";
+
+ protected PassportUtil() {
+ // empty constructor
+ }
+
+ public static PassportUtil getInstance() {
+ return new PassportUtil();
+ }
+
+ public static String getEnvPrefixByHost(HttpServletRequest request) {
+ String prefix ="test";
+ try {
+ InetAddress[] addresses = InetAddress.getAllByName(request.getServerName());
+ for (InetAddress address : addresses) {
+ if (address.isAnyLocalAddress() || address.isLinkLocalAddress() || address.isLoopbackAddress()) {
+ return prefix;
+ }
+ }
+ prefix = "live";
+ } catch (UnknownHostException e) {
+ Debug.logError(e.getMessage(), module);
+ }
+ return prefix;
+ }
+
+ private static String randomString(int lo, int hi) {
+ int n = rand(lo, hi);
+ byte b[] = new byte[n];
+ for (int i = 0; i < n; i++) {
+ b[i] = (byte)rand('a', 'z');
+ }
+ return new String(b);
+ }
+
+ private static int rand(int lo, int hi) {
+ java.util.Random rn = new java.util.Random();
+ int n = hi - lo + 1;
+ int i = rn.nextInt() % n;
+ if (i < 0)
+ i = -i;
+ return lo + i;
+ }
+
+ public static String randomString() {
+ return randomString(8, 15);
+ }
+
+ public CloseableHttpClient getAllowAllHttpClient() {
+ try {
+ SSLContextBuilder builder = new SSLContextBuilder();
+ builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
+ SSLConnectionSocketFactory sf = new AllowAllSSLSocketFactory(builder.build());
+ CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sf).build();
+ return httpclient;
+ } catch (Exception e) {
+ return HttpClients.createDefault();
+ }
+ }
+
+ public class AllowAllSSLSocketFactory extends SSLConnectionSocketFactory {
+ SSLContext sslContext = SSLContext.getInstance("TLS");
+
+ public AllowAllSSLSocketFactory(SSLContext sslContext) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {
+ super(sslContext);
+
+ TrustManager tm = new X509TrustManager() {
+ public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+ }
+
+ public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
+ }
+
+ public X509Certificate[] getAcceptedIssuers() {
+ return null;
+ }
+ };
+
+ sslContext.init(null, new TrustManager[] { tm }, null);
+ }
+
+ public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
+ return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
+ }
+
+ public Socket createSocket() throws IOException {
+ return sslContext.getSocketFactory().createSocket();
+ }
+ }
+
+}
\ No newline at end of file
Propchange: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/util/PassportUtil.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/util/PassportUtil.java
------------------------------------------------------------------------------
svn:keywords = Date Rev Author URL Id
Propchange: ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/util/PassportUtil.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: ofbiz/trunk/specialpurpose/passport/webapp/passport/WEB-INF/actions/login/getThirdPartyLogins.groovy
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/webapp/passport/WEB-INF/actions/login/getThirdPartyLogins.groovy?rev=1688503&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/passport/webapp/passport/WEB-INF/actions/login/getThirdPartyLogins.groovy (added)
+++ ofbiz/trunk/specialpurpose/passport/webapp/passport/WEB-INF/actions/login/getThirdPartyLogins.groovy Tue Jun 30 18:38:16 2015
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.ofbiz.passport;
+
+import org.ofbiz.entity.GenericValue;
+import org.ofbiz.entity.util.EntityUtil;
+import org.ofbiz.base.util.Debug;
+import org.ofbiz.product.store.ProductStoreWorker;
+
+final String module = "getThirdPartyLogins.groovy"
+
+adminErrorInfo = context.adminErrorInfo;
+productStoreId = context.productStoreId;
+if (!productStoreId) {
+ productStore = ProductStoreWorker.getProductStore(request);
+ productStoreId = productStore.productStoreId;
+}
+
+if (!adminErrorInfo || !adminErrorInfo.hasError()) {
+ storePassportLoginMethList = null;
+ // Get lists of passport login methods
+ if (productStoreId) {
+ storePassportLoginMethList = delegator.findByAnd("ThirdPartyLogin", ["productStoreId": productStoreId], ["sequenceNum ASC"], false);
+ storePassportLoginMethList = EntityUtil.filterByDate(storePassportLoginMethList);
+ }
+
+ // Extra data preparation for each login method.
+ if (storePassportLoginMethList) {
+ storeLoginMethList = []
+ for (storeLoginMeth in storePassportLoginMethList) {
+ storeLoginMethDetail = EntityUtil.getFirst(EntityUtil.filterByDate(delegator.findByAnd(storeLoginMeth.loginMethTypeId + storeLoginMeth.loginProviderId, ["productStoreId": productStoreId], null, false)));
+ storeLoginMethList.add(storeLoginMethDetail)
+ }
+ context.storeLoginMethList = storeLoginMethList
+ }
+}
Propchange: ofbiz/trunk/specialpurpose/passport/webapp/passport/WEB-INF/actions/login/getThirdPartyLogins.groovy
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: ofbiz/trunk/specialpurpose/passport/webapp/passport/WEB-INF/actions/login/getThirdPartyLogins.groovy
------------------------------------------------------------------------------
svn:keywords = Date Rev Author URL Id
Propchange: ofbiz/trunk/specialpurpose/passport/webapp/passport/WEB-INF/actions/login/getThirdPartyLogins.groovy
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: ofbiz/trunk/specialpurpose/passport/webapp/passport/WEB-INF/controller-passport.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/webapp/passport/WEB-INF/controller-passport.xml?rev=1688503&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/passport/webapp/passport/WEB-INF/controller-passport.xml (added)
+++ ofbiz/trunk/specialpurpose/passport/webapp/passport/WEB-INF/controller-passport.xml Tue Jun 30 18:38:16 2015
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<site-conf xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/site-conf.xsd">
+
+ <!-- GitHub requests -->
+ <request-map uri="gitHubRedirect">
+ <security https="true" auth="false"/>
+ <event type="java" path="org.ofbiz.passport.event.GitHubEvents" invoke="gitHubRedirect"/>
+ <response name="success" type="view" value="main"/>
+ <response name="error" type="view" value="login"/>
+ </request-map>
+
+ <request-map uri="githubResponse">
+ <security https="true" auth="false"/>
+ <event type="java" path="org.ofbiz.passport.event.GitHubEvents" invoke="parseGitHubResponse"/>
+ <response name="success" type="request" value="login">
+ <redirect-parameter name="USERNAME"/>
+ <redirect-parameter name="PASSWORD"/>
+ </response>
+ <response name="error" type="view" value="login"/>
+ </request-map>
+
+ <!-- LinkedIn requests -->
+ <request-map uri="linkedInRedirect">
+ <security https="true" auth="false"/>
+ <event type="java" path="org.ofbiz.passport.event.LinkedInEvents" invoke="linkedInRedirect"/>
+ <response name="success" type="view" value="main"/>
+ <response name="error" type="view" value="login"/>
+ </request-map>
+
+ <request-map uri="linkedInResponse">
+ <security https="true" auth="false"/>
+ <event type="java" path="org.ofbiz.passport.event.LinkedInEvents" invoke="parseLinkedInResponse"/>
+ <response name="success" type="request" value="login">
+ <redirect-parameter name="USERNAME"/>
+ <redirect-parameter name="PASSWORD"/>
+ </response>
+ <response name="error" type="view" value="login"/>
+ </request-map>
+
+</site-conf>
Propchange: ofbiz/trunk/specialpurpose/passport/webapp/passport/WEB-INF/controller-passport.xml
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: ofbiz/trunk/specialpurpose/passport/webapp/passport/WEB-INF/controller-passport.xml
------------------------------------------------------------------------------
svn:keywords = Date Rev Author URL Id
Propchange: ofbiz/trunk/specialpurpose/passport/webapp/passport/WEB-INF/controller-passport.xml
------------------------------------------------------------------------------
svn:mime-type = text/xml
Added: ofbiz/trunk/specialpurpose/passport/webapp/passport/images/alipay.png
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/webapp/passport/images/alipay.png?rev=1688503&view=auto
==============================================================================
Binary file - no diff available.
Propchange: ofbiz/trunk/specialpurpose/passport/webapp/passport/images/alipay.png
------------------------------------------------------------------------------
svn:mime-type = image/png
Added: ofbiz/trunk/specialpurpose/passport/webapp/passport/images/github.png
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/webapp/passport/images/github.png?rev=1688503&view=auto
==============================================================================
Binary file - no diff available.
Propchange: ofbiz/trunk/specialpurpose/passport/webapp/passport/images/github.png
------------------------------------------------------------------------------
svn:mime-type = image/png
Added: ofbiz/trunk/specialpurpose/passport/webapp/passport/images/linkedin.png
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/webapp/passport/images/linkedin.png?rev=1688503&view=auto
==============================================================================
Binary file - no diff available.
Propchange: ofbiz/trunk/specialpurpose/passport/webapp/passport/images/linkedin.png
------------------------------------------------------------------------------
svn:mime-type = image/png
Added: ofbiz/trunk/specialpurpose/passport/webapp/passport/images/paypal.png
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/webapp/passport/images/paypal.png?rev=1688503&view=auto
==============================================================================
Binary file - no diff available.
Propchange: ofbiz/trunk/specialpurpose/passport/webapp/passport/images/paypal.png
------------------------------------------------------------------------------
svn:mime-type = image/png
Added: ofbiz/trunk/specialpurpose/passport/webapp/passport/images/qq.png
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/webapp/passport/images/qq.png?rev=1688503&view=auto
==============================================================================
Binary file - no diff available.
Propchange: ofbiz/trunk/specialpurpose/passport/webapp/passport/images/qq.png
------------------------------------------------------------------------------
svn:mime-type = image/png
Added: ofbiz/trunk/specialpurpose/passport/webapp/passport/images/renren.png
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/webapp/passport/images/renren.png?rev=1688503&view=auto
==============================================================================
Binary file - no diff available.
Propchange: ofbiz/trunk/specialpurpose/passport/webapp/passport/images/renren.png
------------------------------------------------------------------------------
svn:mime-type = image/png
Added: ofbiz/trunk/specialpurpose/passport/webapp/passport/images/taobao.png
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/webapp/passport/images/taobao.png?rev=1688503&view=auto
==============================================================================
Binary file - no diff available.
Propchange: ofbiz/trunk/specialpurpose/passport/webapp/passport/images/taobao.png
------------------------------------------------------------------------------
svn:mime-type = image/png
Added: ofbiz/trunk/specialpurpose/passport/webapp/passport/images/weibo.png
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/webapp/passport/images/weibo.png?rev=1688503&view=auto
==============================================================================
Binary file - no diff available.
Propchange: ofbiz/trunk/specialpurpose/passport/webapp/passport/images/weibo.png
------------------------------------------------------------------------------
svn:mime-type = image/png
Added: ofbiz/trunk/specialpurpose/passport/webapp/passport/images/weixin.png
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/webapp/passport/images/weixin.png?rev=1688503&view=auto
==============================================================================
Binary file - no diff available.
Propchange: ofbiz/trunk/specialpurpose/passport/webapp/passport/images/weixin.png
------------------------------------------------------------------------------
svn:mime-type = image/png
Added: ofbiz/trunk/specialpurpose/passport/webapp/passport/login/thirdPartyLogins.ftl
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/webapp/passport/login/thirdPartyLogins.ftl?rev=1688503&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/passport/webapp/passport/login/thirdPartyLogins.ftl (added)
+++ ofbiz/trunk/specialpurpose/passport/webapp/passport/login/thirdPartyLogins.ftl Tue Jun 30 18:38:16 2015
@@ -0,0 +1,29 @@
+<#--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<#if storeLoginMethList?exists && storeLoginMethList?has_content>
+<div class="screenlet">
+ <div class="screenlet-title-bar"><h3>${uiLabelMap.ThirdPartyLogin}</h3></div>
+ <div class="screenlet-body">
+ <#list storeLoginMethList as storeLoginMeth>
+ <span><a href="${storeLoginMeth.localRedirectUri!}"><img src="${storeLoginMeth.iconUrl!}"></a></span>
+ </#list>
+ </div>
+</div>
+</#if>
Propchange: ofbiz/trunk/specialpurpose/passport/webapp/passport/login/thirdPartyLogins.ftl
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: ofbiz/trunk/specialpurpose/passport/webapp/passport/login/thirdPartyLogins.ftl
------------------------------------------------------------------------------
svn:keywords = Date Rev Author URL Id
Propchange: ofbiz/trunk/specialpurpose/passport/webapp/passport/login/thirdPartyLogins.ftl
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: ofbiz/trunk/specialpurpose/passport/widget/PassportScreens.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/widget/PassportScreens.xml?rev=1688503&view=auto
==============================================================================
--- ofbiz/trunk/specialpurpose/passport/widget/PassportScreens.xml (added)
+++ ofbiz/trunk/specialpurpose/passport/widget/PassportScreens.xml Tue Jun 30 18:38:16 2015
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+
+<screens xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="http://ofbiz.apache.org/dtds/widget-screen.xsd">
+
+
+ <!-- ++++++ Third Party Logins ++++++ -->
+ <screen name="ListThirdPartyLogins">
+ <section>
+ <actions>
+ <property-map resource="PassportUiLabels" map-name="uiLabelMap" global="true"/>
+ <script location="component://passport/webapp/passport/WEB-INF/actions/login/getThirdPartyLogins.groovy"/>
+ </actions>
+ <widgets>
+ <platform-specific>
+ <html>
+ <html-template location="component://passport/webapp/passport/login/thirdPartyLogins.ftl"/>
+ </html>
+ </platform-specific>
+ </widgets>
+ </section>
+ </screen>
+
+</screens>
\ No newline at end of file
Propchange: ofbiz/trunk/specialpurpose/passport/widget/PassportScreens.xml
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: ofbiz/trunk/specialpurpose/passport/widget/PassportScreens.xml
------------------------------------------------------------------------------
svn:keywords = Date Rev Author URL Id
Propchange: ofbiz/trunk/specialpurpose/passport/widget/PassportScreens.xml
------------------------------------------------------------------------------
svn:mime-type = text/xml