Why don't you answer the question, Scott, in stead of circumventing that by
replying with another question?



Pierre Smits

*ORRTIZ.COM <http://www.orrtiz.com>*
Services & Solutions for Cloud-
Based Manufacturing, Professional
Services and Retail & Trade
http://www.orrtiz.com

On Thu, Jul 2, 2015 at 12:06 AM, Scott Gray <scott.g...@hotwaxsystems.com>
wrote:

> Seems like it's been in jira for a few months.  When exactly were you
> planning on reviewing it Pierre?
> Why is this being dumped in the repository without some kind of apparent
> consensus about having it in? It seems to me that there was consensus
> regarding these kind of big improvements would go through a process of
> Review Than Commit in stead of having it in trunk and then review it.
> Meaning having it as patches of JIRA issue...
>
> Best regards,
>
> Pierre Smits
>
> *ORRTIZ.COM <http://www.orrtiz.com>*
> Services & Solutions for Cloud-
> Based Manufacturing, Professional
> Services and Retail & Trade
> http://www.orrtiz.com
>
> On Tue, Jun 30, 2015 at 9:38 PM, <sh...@apache.org> wrote:
>
> > Author: shijh
> > Date: Tue Jun 30 18:38:16 2015
> > New Revision: 1688503
> >
> > URL: http://svn.apache.org/r1688503
> > Log:
> > Refs OFBIZ-6135.
> >
> > The oauth2 login icons will appear in /ecomseo/checkLogin page if the
> seed
> > data files are properly configured and imported into database.
> >
> > Added:
> >     ofbiz/trunk/specialpurpose/passport/
> >     ofbiz/trunk/specialpurpose/passport/README   (with props)
> >     ofbiz/trunk/specialpurpose/passport/build.xml   (with props)
> >     ofbiz/trunk/specialpurpose/passport/config/
> >     ofbiz/trunk/specialpurpose/passport/config/PassportUiLabels.xml
> >  (with props)
> >     ofbiz/trunk/specialpurpose/passport/config/gitHubAuth.properties
> >  (with props)
> >     ofbiz/trunk/specialpurpose/passport/config/linkedInAuth.properties
> >  (with props)
> >     ofbiz/trunk/specialpurpose/passport/data/
> >     ofbiz/trunk/specialpurpose/passport/data/OAuth2CommonSeedData.xml
> >  (with props)
> >     ofbiz/trunk/specialpurpose/passport/data/OAuth2GitHubSeedData.xml
> >  (with props)
> >     ofbiz/trunk/specialpurpose/passport/data/OAuth2LinkedInSeedData.xml
> >  (with props)
> >     ofbiz/trunk/specialpurpose/passport/entitydef/
> >     ofbiz/trunk/specialpurpose/passport/entitydef/entitymodel.xml   (with
> > props)
> >     ofbiz/trunk/specialpurpose/passport/ofbiz-component.xml   (with
> props)
> >     ofbiz/trunk/specialpurpose/passport/src/
> >     ofbiz/trunk/specialpurpose/passport/src/org/
> >     ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/
> >     ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/
> >     ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/
> >
> >
>
> ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/GitHubEvents.java
> >  (with props)
> >
> >
>
> ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/LinkedInEvents.java
> >  (with props)
> >     ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/
> >
> >
>
> ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/GitHubAuthenticator.java
> >  (with props)
> >
> >
>
> ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/GitHubUserGroupMapper.java
> >  (with props)
> >
> >
>
> ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/LinkedInAuthenticator.java
> >  (with props)
> >
> >
>
> ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/user/LinkedInUserGroupMapper.java
> >  (with props)
> >     ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/util/
> >
> >
>
> ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/util/PassportUtil.java
> >  (with props)
> >     ofbiz/trunk/specialpurpose/passport/webapp/
> >     ofbiz/trunk/specialpurpose/passport/webapp/passport/
> >     ofbiz/trunk/specialpurpose/passport/webapp/passport/WEB-INF/
> >     ofbiz/trunk/specialpurpose/passport/webapp/passport/WEB-INF/actions/
> >
> >
> ofbiz/trunk/specialpurpose/passport/webapp/passport/WEB-INF/actions/login/
> >
> >
>
> ofbiz/trunk/specialpurpose/passport/webapp/passport/WEB-INF/actions/login/getThirdPartyLogins.groovy
> >  (with props)
> >
> >
>
> ofbiz/trunk/specialpurpose/passport/webapp/passport/WEB-INF/controller-passport.xml
> >  (with props)
> >     ofbiz/trunk/specialpurpose/passport/webapp/passport/images/
> >     ofbiz/trunk/specialpurpose/passport/webapp/passport/images/alipay.png
> >  (with props)
> >     ofbiz/trunk/specialpurpose/passport/webapp/passport/images/github.png
> >  (with props)
> >
> > ofbiz/trunk/specialpurpose/passport/webapp/passport/images/linkedin.png
> >  (with props)
> >     ofbiz/trunk/specialpurpose/passport/webapp/passport/images/paypal.png
> >  (with props)
> >     ofbiz/trunk/specialpurpose/passport/webapp/passport/images/qq.png
> >  (with props)
> >     ofbiz/trunk/specialpurpose/passport/webapp/passport/images/renren.png
> >  (with props)
> >     ofbiz/trunk/specialpurpose/passport/webapp/passport/images/taobao.png
> >  (with props)
> >     ofbiz/trunk/specialpurpose/passport/webapp/passport/images/weibo.png
> >  (with props)
> >     ofbiz/trunk/specialpurpose/passport/webapp/passport/images/weixin.png
> >  (with props)
> >     ofbiz/trunk/specialpurpose/passport/webapp/passport/login/
> >
> >
>
> ofbiz/trunk/specialpurpose/passport/webapp/passport/login/thirdPartyLogins.ftl
> >  (with props)
> >     ofbiz/trunk/specialpurpose/passport/widget/
> >     ofbiz/trunk/specialpurpose/passport/widget/PassportScreens.xml
>  (with
> > props)
> > Modified:
> >     ofbiz/trunk/.classpath
> >     ofbiz/trunk/specialpurpose/build.xml
> >     ofbiz/trunk/specialpurpose/component-load.xml
> >
> >
>
> ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/customer/newcustomer.ftl
> >
> >
> ofbiz/trunk/specialpurpose/ecommerce/webapp/ecomseo/WEB-INF/controller.xml
> >     ofbiz/trunk/specialpurpose/ecommerce/widget/CommonScreens.xml
> >
> > Modified: ofbiz/trunk/.classpath
> > URL:
> >
>
> http://svn.apache.org/viewvc/ofbiz/trunk/.classpath?rev=1688503&r1=1688502&r2=1688503&view=diff
> >
> >
>
> ==============================================================================
> > --- ofbiz/trunk/.classpath (original)
> > +++ ofbiz/trunk/.classpath Tue Jun 30 18:38:16 2015
> > @@ -179,6 +179,7 @@
> >      <classpathentry kind="src" path="specialpurpose/projectmgr/src"/>
> >      <classpathentry kind="src" path="specialpurpose/scrum/src"/>
> >      <classpathentry kind="src" path="specialpurpose/webpos/src"/>
> > +    <classpathentry kind="src" path="specialpurpose/passport/src"/>
> >      <classpathentry kind="con" path="GROOVY_SUPPORT" exported="true"/>
> >      <classpathentry kind="con" path="GROOVY_DSL_SUPPORT"
> exported="true"/>
> >      <classpathentry kind="output" path="bin"/>
> >
> > Modified: ofbiz/trunk/specialpurpose/build.xml
> > URL:
> >
>
> http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/build.xml?rev=1688503&r1=1688502&r2=1688503&view=diff
> >
> >
>
> ==============================================================================
> > --- ofbiz/trunk/specialpurpose/build.xml (original)
> > +++ ofbiz/trunk/specialpurpose/build.xml Tue Jun 30 18:38:16 2015
> > @@ -37,6 +37,7 @@
> >          projectmgr/build.xml,
> >          scrum/build.xml,
> >          bi/build.xml,
> > -        webpos/build.xml
> > +        webpos/build.xml,
> > +        passport/build.xml
> >      "/>
> >  </project>
> >
> > Modified: ofbiz/trunk/specialpurpose/component-load.xml
> > URL:
> >
>
> http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/component-load.xml?rev=1688503&r1=1688502&r2=1688503&view=diff
> >
> >
>
> ==============================================================================
> > --- ofbiz/trunk/specialpurpose/component-load.xml (original)
> > +++ ofbiz/trunk/specialpurpose/component-load.xml Tue Jun 30 18:38:16
> 2015
> > @@ -40,4 +40,5 @@ under the License.
> >      <load-component component-location="bi"/>
> >      <load-component component-location="example"/>
> >      <load-component component-location="exampleext"/>
> > +    <load-component component-location="passport"/>
> >  </component-loader>
> >
> > Modified:
> >
>
> ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/customer/newcustomer.ftl
> > URL:
> >
>
> http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/customer/newcustomer.ftl?rev=1688503&r1=1688502&r2=1688503&view=diff
> >
> >
>
> ==============================================================================
> > ---
> >
>
> ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/customer/newcustomer.ftl
> > (original)
> > +++
> >
>
> ofbiz/trunk/specialpurpose/ecommerce/webapp/ecommerce/customer/newcustomer.ftl
> > Tue Jun 30 18:38:16 2015
> > @@ -51,8 +51,8 @@ under the License.
> >           }
> >       }
> >       function hideShowUsaStates() {
> > -                var customerStateElement =
> > document.getElementById('newuserform_stateProvinceGeoId');
> > -        var customerCountryElement =
> > document.getElementById('newuserform_countryGeoId');
> > +         var customerStateElement =
> > document.getElementById('newuserform_stateProvinceGeoId');
> > +          var customerCountryElement =
> > document.getElementById('newuserform_countryGeoId');
> >           if (customerCountryElement.value == "USA" ||
> > customerCountryElement.value == "UMI") {
> >               customerStateElement.style.display = "block";
> >           } else {
> >
> > Modified:
> >
> ofbiz/trunk/specialpurpose/ecommerce/webapp/ecomseo/WEB-INF/controller.xml
> > URL:
> >
>
> http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/ecommerce/webapp/ecomseo/WEB-INF/controller.xml?rev=1688503&r1=1688502&r2=1688503&view=diff
> >
> >
>
> ==============================================================================
> > ---
> >
> ofbiz/trunk/specialpurpose/ecommerce/webapp/ecomseo/WEB-INF/controller.xml
> > (original)
> > +++
> >
> ofbiz/trunk/specialpurpose/ecommerce/webapp/ecomseo/WEB-INF/controller.xml
> > Tue Jun 30 18:38:16 2015
> > @@ -21,6 +21,7 @@ under the License.
> >  <site-conf xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
> >          xsi:noNamespaceSchemaLocation="
> > http://ofbiz.apache.org/dtds/site-conf.xsd";>
> >      <include
> >
> location="component://ecommerce/webapp/ecommerce/WEB-INF/controller.xml"/>
> > +    <include
> >
>
> location="component://passport/webapp/passport/WEB-INF/controller-passport.xml"/>
> >      <description>OFBiz: eCommerce SEO Controller Configuration
> > File</description>
> >
> >      <handler name="jsp" type="view"
> > class="org.ofbiz.ecommerce.webapp.view.JspViewHandler"/>
> >
> > Modified: ofbiz/trunk/specialpurpose/ecommerce/widget/CommonScreens.xml
> > URL:
> >
>
> http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/ecommerce/widget/CommonScreens.xml?rev=1688503&r1=1688502&r2=1688503&view=diff
> >
> >
>
> ==============================================================================
> > --- ofbiz/trunk/specialpurpose/ecommerce/widget/CommonScreens.xml
> > (original)
> > +++ ofbiz/trunk/specialpurpose/ecommerce/widget/CommonScreens.xml Tue Jun
> > 30 18:38:16 2015
> > @@ -336,6 +336,7 @@ under the License.
> >                          <platform-specific>
> >                              <html><html-template
> > location="component://ecommerce/webapp/ecommerce/login.ftl"/></html>
> >                          </platform-specific>
> > +                        <include-screen name="ListThirdPartyLogins"
> > location="component://passport/widget/PassportScreens.xml"/>
> >                          <platform-specific>
> >                              <html><html-template
> >
>
> location="component://ecommerce/webapp/ecommerce/order/startanoncheckout.ftl"/></html>
> >                          </platform-specific>
> >
> > Added: ofbiz/trunk/specialpurpose/passport/README
> > URL:
> >
>
> http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/README?rev=1688503&view=auto
> >
> >
>
> ==============================================================================
> > --- ofbiz/trunk/specialpurpose/passport/README (added)
> > +++ ofbiz/trunk/specialpurpose/passport/README Tue Jun 30 18:38:16 2015
> > @@ -0,0 +1,4 @@
> > +OFBiz Passport Component
> > +
> > +To support users to login with a third party OAuth2 authentication such
> > as Github, LinkedIn and etc.
> > +
> >
> > Propchange: ofbiz/trunk/specialpurpose/passport/README
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:eol-style = native
> >
> > Propchange: ofbiz/trunk/specialpurpose/passport/README
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:mime-type = text/plain
> >
> > Added: ofbiz/trunk/specialpurpose/passport/build.xml
> > URL:
> >
>
> http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/build.xml?rev=1688503&view=auto
> >
> >
>
> ==============================================================================
> > --- ofbiz/trunk/specialpurpose/passport/build.xml (added)
> > +++ ofbiz/trunk/specialpurpose/passport/build.xml Tue Jun 30 18:38:16
> 2015
> > @@ -0,0 +1,51 @@
> > +<?xml version="1.0"?>
> > +<!--
> > +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.
> > +-->
> > +
> > +<project name="OFBiz - Passport Component" default="jar" basedir=".">
> > +    <import file="../../common.xml"/>
> > +
> > +    <!--
> > ================================================================== -->
> > +    <!-- Initialization of all property settings
> >   -->
> > +    <!--
> > ================================================================== -->
> > +
> > +    <property name="desc" value="Ecommerce Passport"/>
> > +    <property name="name" value="ofbiz-passport"/>
> > +    <property name="ofbiz.home.dir" value="../.."/>
> > +
> > +    <path id="local.class.path">
> > +        <fileset dir="../../framework/base/lib" includes="*.jar"/>
> > +        <fileset dir="../../framework/base/lib/j2eespecs"
> > includes="*.jar"/>
> > +        <fileset dir="../../framework/base/build/lib" includes="*.jar"/>
> > +        <fileset dir="../../framework/entity/lib" includes="*.jar"/>
> > +        <fileset dir="../../framework/entity/build/lib"
> includes="*.jar"/>
> > +        <fileset dir="../../framework/security/build/lib"
> > includes="*.jar"/>
> > +        <fileset dir="../../framework/service/lib" includes="*.jar"/>
> > +        <fileset dir="../../framework/service/build/lib"
> > includes="*.jar"/>
> > +        <fileset dir="../../framework/minilang/build/lib"
> > includes="*.jar"/>
> > +        <fileset dir="../../framework/common/build/lib"
> includes="*.jar"/>
> > +        <fileset dir="../../framework/webapp/build/lib"
> includes="*.jar"/>
> > +        <fileset dir="../../applications/party/build/lib"
> > includes="*.jar"/>
> > +        <fileset dir="../../applications/product/build/lib"
> > includes="*.jar"/>
> > +        <fileset dir="../../applications/marketing/build/lib"
> > includes="*.jar"/>
> > +        <fileset dir="../../applications/order/build/lib"
> > includes="*.jar"/>
> > +        <fileset dir="../../applications/accounting/build/lib"
> > includes="*.jar"/>
> > +        <fileset dir="../../applications/securityext/build/lib"
> > includes="*.jar"/>
> > +    </path>
> > +</project>
> > \ No newline at end of file
> >
> > Propchange: ofbiz/trunk/specialpurpose/passport/build.xml
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:eol-style = native
> >
> > Propchange: ofbiz/trunk/specialpurpose/passport/build.xml
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:keywords = Date Rev Author URL Id
> >
> > Propchange: ofbiz/trunk/specialpurpose/passport/build.xml
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:mime-type = text/xml
> >
> > Added: ofbiz/trunk/specialpurpose/passport/config/PassportUiLabels.xml
> > URL:
> >
>
> http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/config/PassportUiLabels.xml?rev=1688503&view=auto
> >
> >
>
> ==============================================================================
> > --- ofbiz/trunk/specialpurpose/passport/config/PassportUiLabels.xml
> (added)
> > +++ ofbiz/trunk/specialpurpose/passport/config/PassportUiLabels.xml Tue
> > Jun 30 18:38:16 2015
> > @@ -0,0 +1,98 @@
> > +<?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.
> > +-->
> > +
> > +<resource xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>
> > +    <property key="PassportApplication">
> > +        <value xml:lang="en">Passport Third Party Auth
> Application</value>
> > +        <value xml:lang="zh">ç¬¬ä¸‰æ–¹è®¤è¯ åº”ç”¨ç¨‹åº </value>
> > +    </property>
> > +    <property key="ThirdPartyLogin">
> > +        <value xml:lang="en">Third Party Login</value>
> > +        <value xml:lang="zh">第三方登录</value>
> > +    </property>
> > +
> > +    <!-- LinkedIn labels -->
> > +    <property key="LinkedInFailedToMatchState">
> > +        <value xml:lang="en">Failed to match the state parameter in
> > LinkedIn response. Just try to login again.</value>
> > +        <value xml:lang="zh">é¢†è‹±å“ åº”ä¸­çš„stateå ‚æ•°ä¸ ä¸€è‡´ã€‚é‡
> > è¯•ç™»å½•å ³å ¯ã€‚</value>
> > +    </property>
> > +    <property key="RedirectToLinkedInOAuth2NullException">
> > +        <value xml:lang="en">Error while redirecting to LinkedIn
> > authorization URL. Please use other login method for now.</value>
> > +        <value xml:lang="zh">è½¬åˆ°é¢†è‹±è®¤è¯ ç½‘å
> > €æ—¶å‡ºé”™ã€‚è¯·å…ˆä½¿ç”¨å…¶å®ƒç™»å½•æ–¹å¼ ã€‚</value>
> > +    </property>
> > +    <property key="RedirectToLinkedInOAuth2Error">
> > +        <value xml:lang="en">Error while redirecting to LinkedIn
> > authorization URL: ${errorMessage}</value>
> > +        <value xml:lang="zh">è½¬åˆ°é¢†è‹±è®¤è¯ ç½‘å
> > €æ—¶å‡ºé”™ï¼š${errorMessage}。</value>
> > +    </property>
> > +    <property key="FailedToGetLinkedInAuthorizationCode">
> > +        <value xml:lang="en">Failed to get LinkedIn authorization
> > code.&lt;br&gt;Error: ${error}&lt;br&gt;Error description:
> > ${error_description}</value>
> > +        <value xml:lang="zh">èŽ·å –é¢†è‹±æŽˆæ ƒç
> > 时出错。&lt;br&gt;错误: ${error}&lt;br&gt;é”™è¯¯æ  è¿°:
> > ${error_description}</value>
> > +    </property>
> > +    <property key="GetLinkedInAuthorizationCodeError">
> > +        <value xml:lang="en">Failed to get LinkedIn authorization
> > code.</value>
> > +        <value xml:lang="zh">èŽ·å –é¢†è‹±æŽˆæ ƒç  æ—¶å‡ºé”™ã€‚</value>
> > +    </property>
> > +    <property key="GetOAuth2LinkedInConfigError">
> > +        <value xml:lang="en">Failed to get LinkedIn configuration.
> Please
> > check whether OAuth2LinkedIn entity has your productStoreId
> > configured.</value>
> > +        <value xml:lang="zh">èŽ·å –é¢†è‹±é…
> > 置时出错。请检查OAuth2LinkedInå®žä½“ä¸­æ˜¯å ¦é…
> > ç½®äº†ä½ çš„åº—é“ºæ ‡è¯†(productStoreId)。</value>
> > +    </property>
> > +    <property key="GetOAuth2LinkedInAccessTokenError">
> > +        <value xml:lang="en">Failed to get LinkedIn access
> token.</value>
> > +        <value xml:lang="zh">获å
> –领英访问令牌时出错。</value>
> > +    </property>
> > +    <property key="GetOAuth2LinkedInError">
> > +        <value xml:lang="en">Failed to get OAuth2LinkedIn entity:
> > ${errorMessage}</value>
> > +        <value xml:lang="zh">获å
> > –OAuth2LinkedIn实体时出错:${errorMessage}</value>
> > +    </property>
> > +
> > +    <!-- GitHub labels -->
> > +    <property key="RedirectToGitHubOAuth2NullException">
> > +        <value xml:lang="en">Error while redirecting to GitHub
> > authorization URL. Please use other login method for now.</value>
> > +        <value xml:lang="zh">转到GitHubè®¤è¯ ç½‘å
> > €æ—¶å‡ºé”™ã€‚è¯·å…ˆä½¿ç”¨å…¶å®ƒç™»å½•æ–¹å¼ ã€‚</value>
> > +    </property>
> > +    <property key="RedirectToGitHubOAuth2Error">
> > +        <value xml:lang="en">Error while redirecting to GitHub
> > authorization URL: ${errorMessage}</value>
> > +        <value xml:lang="zh">转到GitHubè®¤è¯ ç½‘å
> > €æ—¶å‡ºé”™ï¼š${errorMessage}。</value>
> > +    </property>
> > +    <property key="GitHubFailedToMatchState">
> > +        <value xml:lang="en">Failed to match the state parameter in
> > GitHub response. Just try to login again.</value>
> > +        <value xml:lang="zh">GitHubå“ åº”ä¸­çš„stateå ‚æ•°ä¸ ä¸€è‡´ã€‚é‡
> > è¯•ç™»å½•å ³å ¯ã€‚</value>
> > +    </property>
> > +    <property key="FailedToGetLinkedInAuthorizationCode">
> > +        <value xml:lang="en">Failed to get LinkedIn authorization
> > code.&lt;br&gt;Error: ${error}&lt;br&gt;Error description:
> > ${error_description}</value>
> > +        <value xml:lang="zh">èŽ·å –é¢†è‹±æŽˆæ ƒç
> > 时出错。&lt;br&gt;错误: ${error}&lt;br&gt;é”™è¯¯æ  è¿°:
> > ${error_description}</value>
> > +    </property>
> > +    <property key="GetGitHubAuthorizationCodeError">
> > +        <value xml:lang="en">Failed to get GitHub authorization
> > code.</value>
> > +        <value xml:lang="zh">èŽ·å –GitHubæŽˆæ ƒç  æ—¶å‡ºé”™ã€‚</value>
> > +    </property>
> > +    <property key="GetOAuth2GitHubConfigError">
> > +        <value xml:lang="en">Failed to get GitHub configuration. Please
> > check whether OAuth2GitHub entity has your productStoreId
> > configured.</value>
> > +        <value xml:lang="zh">èŽ·å –GitHubé…
> > 置时出错。请检查OAuth2GitHubå®žä½“ä¸­æ˜¯å ¦é…
> > ç½®äº†ä½ çš„åº—é“ºæ ‡è¯†(productStoreId)。</value>
> > +    </property>
> > +    <property key="GetOAuth2GitHubAccessTokenError">
> > +        <value xml:lang="en">Failed to get GitHub access token:
> > ${error}</value>
> > +        <value xml:lang="zh">获å
> > –GitHub访问令牌时出错:${error}</value>
> > +    </property>
> > +    <property key="GetOAuth2GitHubError">
> > +        <value xml:lang="en">Failed to get OAuth2GitHub entity:
> > ${errorMessage}</value>
> > +        <value xml:lang="zh">获å
> > –OAuth2GitHub实体时出错:${errorMessage}</value>
> > +    </property>
> > +</resource>
> >
> > Propchange:
> ofbiz/trunk/specialpurpose/passport/config/PassportUiLabels.xml
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:eol-style = native
> >
> > Propchange:
> ofbiz/trunk/specialpurpose/passport/config/PassportUiLabels.xml
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:keywords = Date Rev Author URL Id
> >
> > Propchange:
> ofbiz/trunk/specialpurpose/passport/config/PassportUiLabels.xml
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:mime-type = text/xml
> >
> > Added: ofbiz/trunk/specialpurpose/passport/config/gitHubAuth.properties
> > URL:
> >
>
> http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/config/gitHubAuth.properties?rev=1688503&view=auto
> >
> >
>
> ==============================================================================
> > --- ofbiz/trunk/specialpurpose/passport/config/gitHubAuth.properties
> > (added)
> > +++ ofbiz/trunk/specialpurpose/passport/config/gitHubAuth.properties Tue
> > Jun 30 18:38:16 2015
> > @@ -0,0 +1,24 @@
> >
> >
>
> +###############################################################################
> > +# 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.
> >
> >
>
> +###############################################################################
> > +
> > +github.env.prefix=test
> > +
> > +github.authenticator.enabled=true
> > +
> > +# github.group.map.1=github-user=FULLADMIN
> >
> > Propchange:
> > ofbiz/trunk/specialpurpose/passport/config/gitHubAuth.properties
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:eol-style = native
> >
> > Propchange:
> > ofbiz/trunk/specialpurpose/passport/config/gitHubAuth.properties
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:keywords = Date Rev Author URL Id
> >
> > Propchange:
> > ofbiz/trunk/specialpurpose/passport/config/gitHubAuth.properties
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:mime-type = text/plain
> >
> > Added: ofbiz/trunk/specialpurpose/passport/config/linkedInAuth.properties
> > URL:
> >
>
> http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/config/linkedInAuth.properties?rev=1688503&view=auto
> >
> >
>
> ==============================================================================
> > --- ofbiz/trunk/specialpurpose/passport/config/linkedInAuth.properties
> > (added)
> > +++ ofbiz/trunk/specialpurpose/passport/config/linkedInAuth.properties
> Tue
> > Jun 30 18:38:16 2015
> > @@ -0,0 +1,24 @@
> >
> >
>
> +###############################################################################
> > +# 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.
> >
> >
>
> +###############################################################################
> > +
> > +linkedin.env.prefix=test
> > +
> > +linkedin.authenticator.enabled=true
> > +
> > +# linkedin.group.map.1=linkedin-user=FULLADMIN
> >
> > Propchange:
> > ofbiz/trunk/specialpurpose/passport/config/linkedInAuth.properties
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:eol-style = native
> >
> > Propchange:
> > ofbiz/trunk/specialpurpose/passport/config/linkedInAuth.properties
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:keywords = Date Rev Author URL Id
> >
> > Propchange:
> > ofbiz/trunk/specialpurpose/passport/config/linkedInAuth.properties
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:mime-type = text/plain
> >
> > Added: ofbiz/trunk/specialpurpose/passport/data/OAuth2CommonSeedData.xml
> > URL:
> >
>
> http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/data/OAuth2CommonSeedData.xml?rev=1688503&view=auto
> >
> >
>
> ==============================================================================
> > --- ofbiz/trunk/specialpurpose/passport/data/OAuth2CommonSeedData.xml
> > (added)
> > +++ ofbiz/trunk/specialpurpose/passport/data/OAuth2CommonSeedData.xml Tue
> > Jun 30 18:38:16 2015
> > @@ -0,0 +1,28 @@
> > +<?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.
> > +-->
> > +
> > +<entity-engine-xml>
> > +
> > +    <EnumerationType description="Passport Login Method Type"
> > enumTypeId="ppLoginMethType" hasTable="N" parentTypeId=""/>
> > +    <EnumerationType description="Passport Login Provider"
> > enumTypeId="ppLoginProvider" hasTable="N" parentTypeId=""/>
> > +
> > +    <EnumerationType description="OAuth2 Login Method Type"
> > enumTypeId="OAuth2" hasTable="N" parentTypeId="ppLoginMethType"/>
> > +
> > +</entity-engine-xml>
> > \ No newline at end of file
> >
> > Propchange:
> > ofbiz/trunk/specialpurpose/passport/data/OAuth2CommonSeedData.xml
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:eol-style = native
> >
> > Propchange:
> > ofbiz/trunk/specialpurpose/passport/data/OAuth2CommonSeedData.xml
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:keywords = Date Rev Author URL Id
> >
> > Propchange:
> > ofbiz/trunk/specialpurpose/passport/data/OAuth2CommonSeedData.xml
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:mime-type = text/xml
> >
> > Added: ofbiz/trunk/specialpurpose/passport/data/OAuth2GitHubSeedData.xml
> > URL:
> >
>
> http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/data/OAuth2GitHubSeedData.xml?rev=1688503&view=auto
> >
> >
>
> ==============================================================================
> > --- ofbiz/trunk/specialpurpose/passport/data/OAuth2GitHubSeedData.xml
> > (added)
> > +++ ofbiz/trunk/specialpurpose/passport/data/OAuth2GitHubSeedData.xml Tue
> > Jun 30 18:38:16 2015
> > @@ -0,0 +1,34 @@
> > +<?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.
> > +-->
> > +
> > +<entity-engine-xml>
> > +
> > +    <EnumerationType description="GitHub Login" enumTypeId="GitHub"
> > hasTable="N" parentTypeId="ppLoginProvider"/>
> > +
> > +    <ThirdPartyLogin productStoreId="9000" loginMethTypeId="OAuth2"
> > loginProviderId="GitHub" fromDate="2011-01-01 00:00:00.0" thruDate=""
> > sequenceNum=""/>
> > +
> > +    <OAuth2GitHub productStoreId="9000"
> > +                    clientId="" clientSecret=""
> > +                    returnUrl=""
> > +                    localRedirectUri="/ecomseo/gitHubRedirect"
> > +                    iconUrl="/passport/images/github.png"
> > fromDate="2011-01-01 00:00:00.0" thruDate=""/>
> > +    <!-- The returnUrl, i.e.
> > https://yourWebSiteOrIp:8443/ecomseo/githubResponse -->
> > +
> > +</entity-engine-xml>
> > \ No newline at end of file
> >
> > Propchange:
> > ofbiz/trunk/specialpurpose/passport/data/OAuth2GitHubSeedData.xml
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:eol-style = native
> >
> > Propchange:
> > ofbiz/trunk/specialpurpose/passport/data/OAuth2GitHubSeedData.xml
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:keywords = Date Rev Author URL Id
> >
> > Propchange:
> > ofbiz/trunk/specialpurpose/passport/data/OAuth2GitHubSeedData.xml
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:mime-type = text/xml
> >
> > Added:
> ofbiz/trunk/specialpurpose/passport/data/OAuth2LinkedInSeedData.xml
> > URL:
> >
>
> http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/data/OAuth2LinkedInSeedData.xml?rev=1688503&view=auto
> >
> >
>
> ==============================================================================
> > --- ofbiz/trunk/specialpurpose/passport/data/OAuth2LinkedInSeedData.xml
> > (added)
> > +++ ofbiz/trunk/specialpurpose/passport/data/OAuth2LinkedInSeedData.xml
> > Tue Jun 30 18:38:16 2015
> > @@ -0,0 +1,36 @@
> > +<?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.
> > +-->
> > +
> > +<entity-engine-xml>
> > +
> > +    <EnumerationType description="LinkedIn Login" enumTypeId="LinkedIn"
> > hasTable="N" parentTypeId="ppLoginProvider"/>
> > +
> > +    <ThirdPartyLogin productStoreId="9000" loginMethTypeId="OAuth2"
> > loginProviderId="LinkedIn" fromDate="2011-01-01 00:00:00.0" thruDate=""
> > sequenceNum=""/>
> > +
> > +    <OAuth2LinkedIn productStoreId="9000"
> > +                    apiKey="" secretKey=""
> > +                    testReturnUrl=""
> > +                    liveReturnUrl=""
> > +                    localRedirectUri="/ecomseo/linkedInRedirect"
> > +                    iconUrl="/passport/images/linkedin.png"
> > fromDate="2011-01-01 00:00:00.0" thruDate=""/>
> > +    <!-- The testReturnUrl, i.e.
> > https://yourTestWebSiteOrIp:8443/ecomseo/linkedInResponse -->
> > +    <!-- The liveReturnUrl, i.e.
> > https://yourLiveWebSiteOrIp:8443/ecomseo/linkedInResponse -->
> > +
> > +</entity-engine-xml>
> > \ No newline at end of file
> >
> > Propchange:
> > ofbiz/trunk/specialpurpose/passport/data/OAuth2LinkedInSeedData.xml
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:eol-style = native
> >
> > Propchange:
> > ofbiz/trunk/specialpurpose/passport/data/OAuth2LinkedInSeedData.xml
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:keywords = Date Rev Author URL Id
> >
> > Propchange:
> > ofbiz/trunk/specialpurpose/passport/data/OAuth2LinkedInSeedData.xml
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:mime-type = text/xml
> >
> > Added: ofbiz/trunk/specialpurpose/passport/entitydef/entitymodel.xml
> > URL:
> >
>
> http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/entitydef/entitymodel.xml?rev=1688503&view=auto
> >
> >
>
> ==============================================================================
> > --- ofbiz/trunk/specialpurpose/passport/entitydef/entitymodel.xml (added)
> > +++ ofbiz/trunk/specialpurpose/passport/entitydef/entitymodel.xml Tue Jun
> > 30 18:38:16 2015
> > @@ -0,0 +1,121 @@
> > +<?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.
> > +-->
> > +
> > +<entitymodel xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
> > xsi:noNamespaceSchemaLocation="
> > http://ofbiz.apache.org/dtds/entitymodel.xsd";>
> > +    <title>Entity of Passport Component</title>
> > +    <description>Data Model Enhancements For Passport</description>
> > +    <version>1.0</version>
> > +
> > +    <entity entity-name="ThirdPartyLogin"
> > +            package-name="org.ofbiz.passport"
> > +            title="Third party logins for a specific product store"
> > +            default-resource-name="PassportEntityLabels">
> > +        <field name="productStoreId" type="id-ne"></field>
> > +        <field name="loginMethTypeId" type="id-ne"></field><!-- i.e.
> > OAuth2 -->
> > +        <field name="loginProviderId" type="id-ne"></field><!-- i.e.
> > GitHub -->
> > +        <field name="fromDate" type="date-time"></field>
> > +        <field name="thruDate" type="date-time"></field>
> > +        <field name="sequenceNum" type="numeric"></field>
> > +        <prim-key field="productStoreId"/>
> > +        <prim-key field="loginMethTypeId"/>
> > +        <prim-key field="loginProviderId"/>
> > +        <prim-key field="fromDate"/>
> > +        <relation type="one" fk-name="PROD_STORE_LOGINS"
> > rel-entity-name="ProductStore">
> > +            <key-map field-name="productStoreId"/>
> > +        </relation>
> > +        <relation type="one" fk-name="LOGIN_METH_TYPE_ID"
> > rel-entity-name="EnumerationType">
> > +            <key-map field-name="loginMethTypeId"
> > rel-field-name="enumTypeId"/>
> > +        </relation>
> > +        <relation type="one" fk-name="LOGIN_PROVIDER_ID"
> > rel-entity-name="EnumerationType">
> > +            <key-map field-name="loginProviderId"
> > rel-field-name="enumTypeId"/>
> > +        </relation>
> > +    </entity>
> > +
> > +    <!-- GitHub OAuth -->
> > +    <entity entity-name="OAuth2GitHub"
> > +            package-name="org.ofbiz.passport"
> > +            title="GitHub OAuth Login Config"
> > +            default-resource-name="PassportEntityLabels">
> > +        <field name="productStoreId" type="id-ne"></field>
> > +        <field name="clientId" type="short-varchar"></field>
> > +        <field name="clientSecret" type="short-varchar"></field>
> > +        <field name="returnUrl" type="value"></field>
> > +        <field name="localRedirectUri" type="short-varchar"></field>
> > +        <field name="iconUrl" type="url"></field>
> > +        <field name="fromDate" type="date-time"></field>
> > +        <field name="thruDate" type="date-time"></field>
> > +        <prim-key field="productStoreId"/>
> > +        <prim-key field="fromDate"/>
> > +        <relation type="one" fk-name="STORE_OAUTH_GITHUB"
> > rel-entity-name="ProductStore">
> > +            <key-map field-name="productStoreId"/>
> > +        </relation>
> > +    </entity>
> > +
> > +    <entity entity-name="GitHubUser"
> > +            package-name="org.ofbiz.passport"
> > +            title="Store GitHub access token for user"
> > +            default-resource-name="PassportEntityLabels">
> > +        <field name="gitHubUserId" type="id-vlong-ne"></field>
> > +        <field name="productStoreId" type="id-ne"></field>
> > +        <field name="envPrefix" type="short-varchar"></field>
> > +        <field name="tokenType" type="short-varchar"></field>
> > +        <field name="accessToken" type="value"></field>
> > +        <prim-key field="gitHubUserId"/>
> > +        <relation type="one" fk-name="GITHUB_USER_STORE"
> > rel-entity-name="ProductStore">
> > +            <key-map field-name="productStoreId"/>
> > +        </relation>
> > +    </entity>
> > +
> > +    <!-- LinkedIn OAuth -->
> > +    <entity entity-name="OAuth2LinkedIn"
> > +            package-name="org.ofbiz.passport"
> > +            title="LinkedIn OAuth Login Config"
> > +            default-resource-name="PassportEntityLabels">
> > +        <field name="productStoreId" type="id-ne"></field>
> > +        <field name="apiKey" type="short-varchar"></field>
> > +        <field name="secretKey" type="short-varchar"></field>
> > +        <field name="liveReturnUrl" type="value"></field>
> > +        <field name="testReturnUrl" type="value"></field>
> > +        <field name="localRedirectUri" type="short-varchar"></field>
> > +        <field name="iconUrl" type="url"></field>
> > +        <field name="fromDate" type="date-time"></field>
> > +        <field name="thruDate" type="date-time"></field>
> > +        <prim-key field="productStoreId"/>
> > +        <prim-key field="fromDate"/>
> > +        <relation type="one" fk-name="STORE_OAUTH_LINKEDIN"
> > rel-entity-name="ProductStore">
> > +            <key-map field-name="productStoreId"/>
> > +        </relation>
> > +    </entity>
> > +
> > +    <entity entity-name="LinkedInUser"
> > +            package-name="org.ofbiz.passport"
> > +            title="Store LinkedIn access token for user"
> > +            default-resource-name="PassportEntityLabels">
> > +        <field name="linkedInUserId" type="id-vlong-ne"></field>
> > +        <field name="productStoreId" type="id-ne"></field>
> > +        <field name="envPrefix" type="short-varchar"></field>
> > +        <field name="accessToken" type="value"></field>
> > +        <prim-key field="linkedInUserId"/>
> > +        <relation type="one" fk-name="LINKEDIN_USER_STORE"
> > rel-entity-name="ProductStore">
> > +            <key-map field-name="productStoreId"/>
> > +        </relation>
> > +    </entity>
> > +
> > +</entitymodel>
> > \ No newline at end of file
> >
> > Propchange: ofbiz/trunk/specialpurpose/passport/entitydef/entitymodel.xml
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:eol-style = native
> >
> > Propchange: ofbiz/trunk/specialpurpose/passport/entitydef/entitymodel.xml
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:keywords = Date Rev Author URL Id
> >
> > Propchange: ofbiz/trunk/specialpurpose/passport/entitydef/entitymodel.xml
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:mime-type = text/xml
> >
> > Added: ofbiz/trunk/specialpurpose/passport/ofbiz-component.xml
> > URL:
> >
>
> http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/ofbiz-component.xml?rev=1688503&view=auto
> >
> >
>
> ==============================================================================
> > --- ofbiz/trunk/specialpurpose/passport/ofbiz-component.xml (added)
> > +++ ofbiz/trunk/specialpurpose/passport/ofbiz-component.xml Tue Jun 30
> > 18:38:16 2015
> > @@ -0,0 +1,35 @@
> > +<?xml version="1.0" encoding="UTF-8"?>
> > +<ofbiz-component name="passport"
> > +        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
> > +        xsi:noNamespaceSchemaLocation="
> > http://ofbiz.apache.org/dtds/ofbiz-component.xsd";>
> > +    <!-- define resource loaders; most common is to use the component
> > resource loader -->
> > +    <resource-loader name="main" type="component"/>
> > +
> > +    <!-- place the config directory on the classpath to access
> > configuration files -->
> > +    <classpath type="dir" location="config"/>
> > +
> > +    <!-- load single or multiple external libraries -->
> > +    <classpath type="jar" location="build/lib/*"/>
> > +    <classpath type="jar" location="lib/*"/>
> > +
> > +    <!-- entity resources: model(s), eca(s), group, and data definitions
> > -->
> > +    <entity-resource type="model" reader-name="main" loader="main"
> > location="entitydef/entitymodel.xml"/>
> > +
> > +    <!-- Seed Data -->
> > +    <entity-resource type="data" reader-name="seed" loader="main"
> > location="data/OAuth2CommonSeedData.xml"/>
> > +    <entity-resource type="data" reader-name="seed" loader="main"
> > location="data/OAuth2LinkedInSeedData.xml"/>
> > +    <entity-resource type="data" reader-name="seed" loader="main"
> > location="data/OAuth2GitHubSeedData.xml"/>
> > +
> > +    <!-- service resources: model(s), eca(s) and group definitions -->
> > +    <!--
> > +    <service-resource type="model" loader="main"
> > location="servicedef/services.xml"/>
> > +     -->
> > +
> > +    <!-- web applications; will be mounted when using the embedded
> > container -->
> > +    <webapp name="passport"
> > +            title="OFBiz Passport"
> > +            server="default-server"
> > +            location="webapp/passport"
> > +            mount-point="/passport"
> > +            app-bar-display="false" />
> > +</ofbiz-component>
> > \ No newline at end of file
> >
> > Propchange: ofbiz/trunk/specialpurpose/passport/ofbiz-component.xml
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:eol-style = native
> >
> > Propchange: ofbiz/trunk/specialpurpose/passport/ofbiz-component.xml
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:keywords = Date Rev Author URL Id
> >
> > Propchange: ofbiz/trunk/specialpurpose/passport/ofbiz-component.xml
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:mime-type = text/xml
> >
> > Added:
> >
>
> ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/GitHubEvents.java
> > URL:
> >
>
> http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/GitHubEvents.java?rev=1688503&view=auto
> >
> >
>
> ==============================================================================
> > ---
> >
>
> ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/GitHubEvents.java
> > (added)
> > +++
> >
>
> ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/GitHubEvents.java
> > Tue Jun 30 18:38:16 2015
> > @@ -0,0 +1,322 @@
> >
> >
>
> +/*******************************************************************************
> > + * 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.event;
> > +
> > +import java.io.IOException;
> > +import java.io.UnsupportedEncodingException;
> > +import java.net.URLDecoder;
> > +import java.net.URLEncoder;
> > +import java.util.Map;
> > +import java.util.Random;
> > +
> > +import javax.servlet.http.HttpServletRequest;
> > +import javax.servlet.http.HttpServletResponse;
> > +
> > +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.methods.PostMethod;
> > +import org.apache.commons.httpclient.params.HttpMethodParams;
> > +import org.ofbiz.passport.user.GitHubAuthenticator;
> > +import org.ofbiz.passport.util.PassportUtil;
> > +import org.ofbiz.base.conversion.ConversionException;
> > +import org.ofbiz.base.conversion.JSONConverters.JSONToMap;
> > +import org.ofbiz.base.crypto.HashCrypt;
> > +import org.ofbiz.base.lang.JSON;
> > +import org.ofbiz.base.util.Debug;
> > +import org.ofbiz.base.util.UtilHttp;
> > +import org.ofbiz.base.util.UtilMisc;
> > +import org.ofbiz.base.util.UtilProperties;
> > +import org.ofbiz.base.util.UtilValidate;
> > +import org.ofbiz.common.authentication.api.AuthenticatorException;
> > +import org.ofbiz.common.login.LoginServices;
> > +import org.ofbiz.entity.Delegator;
> > +import org.ofbiz.entity.GenericEntityException;
> > +import org.ofbiz.entity.GenericValue;
> > +import org.ofbiz.entity.util.EntityUtil;
> > +import org.ofbiz.product.store.ProductStoreWorker;
> > +import org.ofbiz.service.LocalDispatcher;
> > +
> > +/**
> > + * GitHubEvents - Events for GitHub login.
> > + *
> > + * Refs: https://developer.github.com/v3/oauth/
> > + *
> > + */
> > +public class GitHubEvents {
> > +
> > +    public static final String module = GitHubEvents.class.getName();
> > +
> > +    public static final String resource = "PassportUiLabels";
> > +
> > +    public static final String AuthorizeUri = "/login/oauth/authorize";
> > +
> > +    public static final String TokenServiceUri =
> > "/login/oauth/access_token";
> > +
> > +    public static final String UserApiUri = "/user";
> > +
> > +    public static final String DEFAULT_SCOPE = "user,gist";
> > +
> > +    public static final String ApiEndpoint = "https://api.github.com";;
> > +
> > +    public static final String TokenEndpoint = "https://github.com";;
> > +
> > +    public static final String SESSION_GITHUB_STATE = "_GITHUB_STATE_";
> > +
> > +    public static final String envPrefix =
> > UtilProperties.getPropertyValue(GitHubAuthenticator.props,
> > "github.env.prefix", "test");
> > +
> > +    /**
> > +     * Redirect to GitHub login page.
> > +     *
> > +     * @return
> > +     */
> > +    public static String gitHubRedirect(HttpServletRequest request,
> > HttpServletResponse response) {
> > +        GenericValue oauth2GitHub = getOAuth2GitHubConfig(request);
> > +        if (UtilValidate.isEmpty(oauth2GitHub)) {
> > +            return "error";
> > +        }
> > +
> > +        String clientId =
> > oauth2GitHub.getString(PassportUtil.COMMON_CLIENT_ID);
> > +        String returnURI =
> > oauth2GitHub.getString(PassportUtil.COMMON_RETURN_RUL);
> > +
> > +        // Get user authorization code
> > +        try {
> > +            String state = System.currentTimeMillis() +
> > String.valueOf((new Random(10)).nextLong());
> > +            request.getSession().setAttribute(SESSION_GITHUB_STATE,
> > state);
> > +            String redirectUrl = TokenEndpoint + AuthorizeUri
> > +                    + "?client_id=" + clientId
> > +                    + "&scope=" + DEFAULT_SCOPE
> > +                    + "&redirect_uri=" + URLEncoder.encode(returnURI,
> > "UTF-8")
> > +                    + "&state=" + state;
> > +            Debug.logInfo("Request to GitHub: " + redirectUrl, module);
> > +            response.sendRedirect(redirectUrl);
> > +        } catch (NullPointerException e) {
> > +            String errMsg = UtilProperties.getMessage(resource,
> > "RedirectToGitHubOAuth2NullException", UtilHttp.getLocale(request));
> > +            request.setAttribute("_ERROR_MESSAGE_", errMsg);
> > +            return "error";
> > +        } catch (IOException e) {
> > +            Map<String, String> messageMap =
> > UtilMisc.toMap("errorMessage", e.toString());
> > +            String errMsg = UtilProperties.getMessage(resource,
> > "RedirectToGitHubOAuth2Error", messageMap, UtilHttp.getLocale(request));
> > +            request.setAttribute("_ERROR_MESSAGE_", errMsg);
> > +            return "error";
> > +        }
> > +
> > +        return "success";
> > +    }
> > +
> > +    /**
> > +     * Parse GitHub login response and login the user if possible.
> > +     *
> > +     * @return
> > +     */
> > +    public static String parseGitHubResponse(HttpServletRequest request,
> > HttpServletResponse response) {
> > +        String authorizationCode =
> > request.getParameter(PassportUtil.COMMON_CODE);
> > +        String state = request.getParameter(PassportUtil.COMMON_STATE);
> > +        if
> > (!state.equals(request.getSession().getAttribute(SESSION_GITHUB_STATE)))
> {
> > +            String errMsg = UtilProperties.getMessage(resource,
> > "GitHubFailedToMatchState", UtilHttp.getLocale(request));
> > +            request.setAttribute("_ERROR_MESSAGE_", errMsg);
> > +            return "error";
> > +        }
> > +        if (UtilValidate.isEmpty(authorizationCode)) {
> > +            String error =
> > request.getParameter(PassportUtil.COMMON_ERROR);
> > +            String errorDescpriton =
> > request.getParameter(PassportUtil.COMMON_ERROR_DESCRIPTION);
> > +            String errMsg = null;
> > +            try {
> > +                errMsg = UtilProperties.getMessage(resource,
> > "FailedToGetGitHubAuthorizationCode",
> > UtilMisc.toMap(PassportUtil.COMMON_ERROR, error,
> > PassportUtil.COMMON_ERROR_DESCRIPTION, URLDecoder.decode(errorDescpriton,
> > "UTF-8")), UtilHttp.getLocale(request));
> > +            } catch (UnsupportedEncodingException e) {
> > +                errMsg = UtilProperties.getMessage(resource,
> > "GetGitHubAuthorizationCodeError", UtilHttp.getLocale(request));
> > +            }
> > +            request.setAttribute("_ERROR_MESSAGE_", errMsg);
> > +            return "error";
> > +        }
> > +        Debug.logInfo("GitHub authorization code: " + authorizationCode,
> > module);
> > +
> > +        GenericValue oauth2GitHub = getOAuth2GitHubConfig(request);
> > +        if (UtilValidate.isEmpty(oauth2GitHub)) {
> > +            String errMsg = UtilProperties.getMessage(resource,
> > "GetOAuth2GitHubConfigError", UtilHttp.getLocale(request));
> > +            request.setAttribute("_ERROR_MESSAGE_", errMsg);
> > +            return "error";
> > +        }
> > +        String clientId =
> > oauth2GitHub.getString(PassportUtil.COMMON_CLIENT_ID);
> > +        String secret =
> > oauth2GitHub.getString(PassportUtil.COMMON_CLIENT_SECRET);
> > +        String returnURI =
> > oauth2GitHub.getString(PassportUtil.COMMON_RETURN_RUL);
> > +
> > +        // Grant token from authorization code and oauth2 token
> > +        // Use the authorization code to obtain an access token
> > +        String accessToken = null;
> > +        String tokenType = null;
> > +
> > +        HttpClient jsonClient = new HttpClient();
> > +        PostMethod postMethod = new PostMethod(TokenEndpoint +
> > TokenServiceUri);
> > +        try {
> > +            HttpMethodParams params = new HttpMethodParams();
> > +            String queryString = "client_id=" + clientId
> > +                    + "&client_secret=" + secret
> > +                    + "&code=" + authorizationCode
> > +                    + "&redirect_uri=" + URLEncoder.encode(returnURI,
> > "UTF-8");
> > +            // Debug.logInfo("GitHub get access token query string: " +
> > queryString, module);
> > +            postMethod.setQueryString(queryString);
> > +            params.setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
> > +            postMethod.setParams(params);
> > +            postMethod.setRequestHeader(PassportUtil.ACCEPT_HEADER,
> > "application/json");
> > +            jsonClient.executeMethod(postMethod);
> > +            // Debug.logInfo("GitHub get access token response code: " +
> > postMethod.getStatusCode(), module);
> > +            // Debug.logInfo("GitHub get access token response content:
> "
> > + postMethod.getResponseBodyAsString(1024), module);
> > +            if (postMethod.getStatusCode() == HttpStatus.SC_OK) {
> > +                // Debug.logInfo("Json Response from GitHub: " +
> > postMethod.getResponseBodyAsString(1024), module);
> > +                JSON jsonObject =
> > JSON.from(postMethod.getResponseBodyAsString(1024));
> > +                JSONToMap jsonMap = new JSONToMap();
> > +                Map<String, Object> userMap =
> jsonMap.convert(jsonObject);
> > +                accessToken = (String) userMap.get("access_token");
> > +                tokenType = (String) userMap.get("token_type");
> > +                // Debug.logInfo("Generated Access Token : " +
> > accessToken, module);
> > +                // Debug.logInfo("Token Type: " + tokenType, module);
> > +            } else {
> > +                String errMsg = UtilProperties.getMessage(resource,
> > "GetOAuth2GitHubAccessTokenError", UtilMisc.toMap("error",
> > postMethod.getResponseBodyAsString()), UtilHttp.getLocale(request));
> > +                request.setAttribute("_ERROR_MESSAGE_", errMsg);
> > +                return "error";
> > +            }
> > +        } catch (UnsupportedEncodingException e) {
> > +            request.setAttribute("_ERROR_MESSAGE_", e.toString());
> > +            return "error";
> > +        } catch (HttpException e) {
> > +            request.setAttribute("_ERROR_MESSAGE_", e.toString());
> > +            return "error";
> > +        } catch (IOException e) {
> > +            request.setAttribute("_ERROR_MESSAGE_", e.toString());
> > +            return "error";
> > +        } catch (ConversionException e) {
> > +            request.setAttribute("_ERROR_MESSAGE_", e.toString());
> > +            return "error";
> > +        } finally {
> > +            postMethod.releaseConnection();
> > +        }
> > +
> > +        // Get User Profile
> > +        GetMethod getMethod = new GetMethod(ApiEndpoint + UserApiUri);
> > +        Map<String, Object> userInfo = null;
> > +        try {
> > +            userInfo = GitHubAuthenticator.getUserInfo(getMethod,
> > accessToken, tokenType, UtilHttp.getLocale(request));
> > +        } catch (HttpException e) {
> > +            request.setAttribute("_ERROR_MESSAGE_", e.toString());
> > +            return "error";
> > +        } catch (IOException e) {
> > +            request.setAttribute("_ERROR_MESSAGE_", e.toString());
> > +            return "error";
> > +        } catch (AuthenticatorException e) {
> > +            request.setAttribute("_ERROR_MESSAGE_", e.toString());
> > +            return "error";
> > +        } finally {
> > +            getMethod.releaseConnection();
> > +        }
> > +        // Debug.logInfo("GitHub User Info:" + userInfo, module);
> > +
> > +        // Store the user info and check login the user
> > +        return checkLoginGitHubUser(request, userInfo, accessToken);
> > +    }
> > +
> > +    private static String checkLoginGitHubUser(HttpServletRequest
> > request, Map<String, Object> userInfo, String accessToken) {
> > +        Delegator delegator = (Delegator)
> > request.getAttribute("delegator");
> > +        LocalDispatcher dispatcher = (LocalDispatcher)
> > request.getAttribute("dispatcher");
> > +        String productStoreId =
> > ProductStoreWorker.getProductStoreId(request);
> > +        String gitHubUserId = (String) userInfo.get("login");
> > +        GenericValue gitHubUser = null;
> > +        try {
> > +            gitHubUser = delegator.findOne("GitHubUser",
> > UtilMisc.toMap("gitHubUserId", gitHubUserId), false);
> > +        } catch (GenericEntityException e) {
> > +            request.setAttribute("_ERROR_MESSAGE_", e.getMessage());
> > +            return "error";
> > +        }
> > +        if (UtilValidate.isNotEmpty(gitHubUser)) {
> > +            boolean dataChanged = false;
> > +            if
> (!accessToken.equals(gitHubUser.getString("accessToken")))
> > {
> > +                gitHubUser.set("accessToken", accessToken);
> > +                dataChanged = true;
> > +            }
> > +            if (!envPrefix.equals(gitHubUser.getString("envPrefix"))) {
> > +                gitHubUser.set("envPrefix", envPrefix);
> > +                dataChanged = true;
> > +            }
> > +            if
> > (!productStoreId.equals(gitHubUser.getString("productStoreId"))) {
> > +                gitHubUser.set("productStoreId", productStoreId);
> > +                dataChanged = true;
> > +            }
> > +            if (dataChanged) {
> > +                try {
> > +                    gitHubUser.store();
> > +                } catch (GenericEntityException e) {
> > +                    Debug.logError(e.getMessage(), module);
> > +                }
> > +            }
> > +        } else {
> > +            gitHubUser = delegator.makeValue("GitHubUser",
> > UtilMisc.toMap("accessToken", accessToken,
> > +
> > "productStoreId", productStoreId,
> > +
> > "envPrefix", envPrefix,
> > +
> > "gitHubUserId", gitHubUserId));
> > +            try {
> > +                gitHubUser.create();
> > +            } catch (GenericEntityException e) {
> > +                Debug.logError(e.getMessage(), module);
> > +            }
> > +        }
> > +        try {
> > +            GenericValue userLogin =
> > EntityUtil.getFirst(delegator.findByAnd("UserLogin",
> > UtilMisc.toMap("externalAuthId", gitHubUserId), null, false));
> > +            GitHubAuthenticator authn = new GitHubAuthenticator();
> > +            authn.initialize(dispatcher);
> > +            if (UtilValidate.isEmpty(userLogin)) {
> > +                String userLoginId = authn.createUser(userInfo);
> > +                userLogin = delegator.findOne("UserLogin",
> > UtilMisc.toMap("userLoginId", userLoginId), false);
> > +            }
> > +            String password = PassportUtil.randomString();
> > +            boolean useEncryption =
> > "true".equals(UtilProperties.getPropertyValue("security.properties",
> > "password.encrypt"));
> > +            userLogin.set("currentPassword", useEncryption ?
> > HashCrypt.digestHash(LoginServices.getHashType(), null, password) :
> > password);
> > +            userLogin.store();
> > +            request.setAttribute("USERNAME",
> > userLogin.getString("userLoginId"));
> > +            request.setAttribute("PASSWORD", password);
> > +        } catch (GenericEntityException e) {
> > +            Debug.logError(e.getMessage(), module);
> > +            request.setAttribute("_ERROR_MESSAGE_", e.toString());
> > +            return "error";
> > +        } catch (AuthenticatorException e) {
> > +            Debug.logError(e.getMessage(), module);
> > +            request.setAttribute("_ERROR_MESSAGE_", e.toString());
> > +            return "error";
> > +        }
> > +        return "success";
> > +    }
> > +
> > +    public static GenericValue getOAuth2GitHubConfig(HttpServletRequest
> > request) {
> > +        Delegator delegator = (Delegator)
> > request.getAttribute("delegator");
> > +        String productStoreId =
> > ProductStoreWorker.getProductStoreId(request);
> > +        try {
> > +            return getOAuth2GitHubConfig(delegator, productStoreId);
> > +        } catch (GenericEntityException e) {
> > +            Map<String, String> messageMap =
> > UtilMisc.toMap("errorMessage", e.toString());
> > +            String errMsg = UtilProperties.getMessage(resource,
> > "GetOAuth2GitHubError", messageMap, UtilHttp.getLocale(request));
> > +            request.setAttribute("_ERROR_MESSAGE_", errMsg);
> > +        }
> > +        return null;
> > +    }
> > +
> > +    public static GenericValue getOAuth2GitHubConfig(Delegator
> delegator,
> > String productStoreId) throws GenericEntityException {
> > +        return
> >
>
> EntityUtil.getFirst(EntityUtil.filterByDate(delegator.findByAnd("OAuth2GitHub",
> > UtilMisc.toMap("productStoreId", productStoreId), null, false)));
> > +    }
> > +}
> >
> > Propchange:
> >
>
> ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/GitHubEvents.java
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:eol-style = native
> >
> > Propchange:
> >
>
> ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/GitHubEvents.java
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:keywords = Date Rev Author URL Id
> >
> > Propchange:
> >
>
> ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/GitHubEvents.java
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:mime-type = text/plain
> >
> > Added:
> >
>
> ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/LinkedInEvents.java
> > URL:
> >
>
> http://svn.apache.org/viewvc/ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/LinkedInEvents.java?rev=1688503&view=auto
> >
> >
>
> ==============================================================================
> > ---
> >
>
> ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/LinkedInEvents.java
> > (added)
> > +++
> >
>
> ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/LinkedInEvents.java
> > Tue Jun 30 18:38:16 2015
> > @@ -0,0 +1,326 @@
> >
> >
>
> +/*******************************************************************************
> > + * 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.event;
> > +
> > +import java.io.IOException;
> > +import java.io.UnsupportedEncodingException;
> > +import java.net.URLDecoder;
> > +import java.net.URLEncoder;
> > +import java.util.Map;
> > +import java.util.Random;
> > +
> > +import javax.servlet.http.HttpServletRequest;
> > +import javax.servlet.http.HttpServletResponse;
> > +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.methods.PostMethod;
> > +import org.apache.commons.httpclient.params.HttpMethodParams;
> > +import org.ofbiz.passport.user.LinkedInAuthenticator;
> > +import org.ofbiz.passport.util.PassportUtil;
> > +import org.ofbiz.base.conversion.ConversionException;
> > +import org.ofbiz.base.conversion.JSONConverters.JSONToMap;
> > +import org.ofbiz.base.crypto.HashCrypt;
> > +import org.ofbiz.base.lang.JSON;
> > +import org.ofbiz.base.util.Debug;
> > +import org.ofbiz.base.util.UtilHttp;
> > +import org.ofbiz.base.util.UtilMisc;
> > +import org.ofbiz.base.util.UtilProperties;
> > +import org.ofbiz.base.util.UtilValidate;
> > +import org.ofbiz.common.authentication.api.AuthenticatorException;
> > +import org.ofbiz.common.login.LoginServices;
> > +import org.ofbiz.entity.Delegator;
> > +import org.ofbiz.entity.GenericEntityException;
> > +import org.ofbiz.entity.GenericValue;
> > +import org.ofbiz.entity.util.EntityUtil;
> > +import org.ofbiz.product.store.ProductStoreWorker;
> > +import org.ofbiz.service.LocalDispatcher;
> > +import org.w3c.dom.Document;
> > +import org.xml.sax.SAXException;
> > +
> > +/**
> > + * LinkedEvents - Events for LinkedIn login.
> > + *
> > + * Refs: https://developer.linkedin.com/documents/authentication
> > + *
> > + */
> > +public class LinkedInEvents {
> > +
> > +    public static final String module = LinkedInEvents.class.getName();
> > +
> > +    public static final String resource = "PassportUiLabels";
> > +
> > +    public static final String AuthorizeUri =
> "/uas/oauth2/authorization";
> > +
> > +    public static final String TokenServiceUri =
> > "/uas/oauth2/accessToken";
> > +
> > +    public static final String UserApiUri = "/v1/people/~";
> > +
> > +    public static final String DEFAULT_SCOPE =
> > "r_basicprofile%20r_emailaddress";
> > +
> > +    public static final String TokenEndpoint = "
> https://www.linkedin.com
> > ";
> > +
> > +    public static final String SESSION_LINKEDIN_STATE =
> > "_LINKEDIN_STATE_";
> > +
> > +    public static final String envPrefix =
> > UtilProperties.getPropertyValue(LinkedInAuthenticator.props,
> > "linkedin.env.prefix", "test");
> > +
> > +    /**
> > +     * Redirect to LinkedIn login page.
> > +     *
> > +     * @return
> > +     */
> > +    public static String linkedInRedirect(HttpServletRequest request,
> > HttpServletResponse response) {
> > +        GenericValue oauth2LinkedIn = getOAuth2LinkedInConfig(request);
> > +        if (UtilValidate.isEmpty(oauth2LinkedIn)) {
> > +            return "error";
> > +        }
> > +
> > +        String clientId =
> > oauth2LinkedIn.getString(PassportUtil.ApiKeyLabel);
> > +        String returnURI = oauth2LinkedIn.getString(envPrefix +
> > PassportUtil.ReturnUrlLabel);
> > +
> > +        // Get user authorization code
> > +        try {
> > +            String state = System.currentTimeMillis() +
> > String.valueOf((new Random(10)).nextLong());
> > +            request.getSession().setAttribute(SESSION_LINKEDIN_STATE,
> > state);
> > +            String redirectUrl = TokenEndpoint + AuthorizeUri
> > +                    + "?client_id=" + clientId
> > +                    + "&response_type=code"
> > +                    + "&scope=" + DEFAULT_SCOPE
> > +                    + "&redirect_uri=" + URLEncoder.encode(returnURI,
> > "UTF-8")
> > +                    + "&state=" + state;
> > +            response.sendRedirect(redirectUrl);
> > +        } catch (NullPointerException e) {
> > +            String errMsg = UtilProperties.getMessage(resource,
> > "RedirectToLinkedInOAuth2NullException", UtilHttp.getLocale(request));
> > +            request.setAttribute("_ERROR_MESSAGE_", errMsg);
> > +            return "error";
> > +        } catch (IOException e) {
> > +            Map<String, String> messageMap =
> > UtilMisc.toMap("errorMessage", e.toString());
> > +            String errMsg = UtilProperties.getMessage(resource,
> > "RedirectToLinkedInOAuth2Error", messageMap,
> UtilHttp.getLocale(request));
> > +            request.setAttribute("_ERROR_MESSAGE_", errMsg);
> > +            return "error";
> > +        }
> > +
> > +        return "success";
> > +    }
> > +
> > +    /**
> > +     * Parse LinkedIn login response and login the user if possible.
> > +     *
> > +     * @return
> > +     */
> > +    public static String parseLinkedInResponse(HttpServletRequest
> > request, HttpServletResponse response) {
> > +        String authorizationCode =
> > request.getParameter(PassportUtil.COMMON_CODE);
> > +        String state = request.getParameter(PassportUtil.COMMON_STATE);
> > +        if
> >
> (!state.equals(request.getSession().getAttribute(SESSION_LINKEDIN_STATE)))
> {
> > +            String errMsg = UtilProperties.getMessage(resource,
> > "LinkedInFailedToMatchState", UtilHttp.getLocale(request));
> > +            request.setAttribute("_ERROR_MESSAGE_", errMsg);
> > +            return "error";
> > +        }
> > +        if (UtilValidate.isEmpty(authorizationCode)) {
> > +            String error =
> > request.getParameter(PassportUtil.COMMON_ERROR);
> > +            String errorDescpriton =
> > request.getParameter(PassportUtil.COMMON_ERROR_DESCRIPTION);
> > +            String errMsg = null;
> > +            try {
> > +                errMsg = UtilProperties.getMessage(resource,
> > "FailedToGetLinkedInAuthorizationCode",
> > UtilMisc.toMap(PassportUtil.COMMON_ERROR, error,
> > PassportUtil.COMMON_ERROR_DESCRIPTION, URLDecoder.decode(errorDescpriton,
> > "UTF-8")), UtilHttp.getLocale(request));
> > +            } catch (UnsupportedEncodingException e) {
> > +                errMsg = UtilProperties.getMessage(resource,
> > "GetLinkedInAuthorizationCodeError", UtilHttp.getLocale(request));
> > +            }
> > +            request.setAttribute("_ERROR_MESSAGE_", errMsg);
> > +            return "error";
> > +        }
> > +        // Debug.logInfo("LinkedIn authorization code: " +
> > authorizationCode, module);
> > +
> > +        GenericValue oauth2LinkedIn = getOAuth2LinkedInConfig(request);
> > +        if (UtilValidate.isEmpty(oauth2LinkedIn)) {
> > +            String errMsg = UtilProperties.getMessage(resource,
> > "GetOAuth2LinkedInConfigError", UtilHttp.getLocale(request));
> > +            request.setAttribute("_ERROR_MESSAGE_", errMsg);
> > +            return "error";
> > +        }
> > +        String clientId =
> > oauth2LinkedIn.getString(PassportUtil.ApiKeyLabel);
> > +        String secret =
> > oauth2LinkedIn.getString(PassportUtil.SecretKeyLabel);
> > +        String returnURI = oauth2LinkedIn.getString(envPrefix +
> > PassportUtil.ReturnUrlLabel);
> > +
> > +        // Grant token from authorization code and oauth2 token
> > +        // Use the authorization code to obtain an access token
> > +        String accessToken = null;
> > +
> > +        HttpClient jsonClient = new HttpClient();
> > +        PostMethod postMethod = new PostMethod(TokenEndpoint +
> > TokenServiceUri);
> > +        try {
> > +            HttpMethodParams params = new HttpMethodParams();
> > +            String queryString = "client_id=" + clientId
> > +                    + "&client_secret=" + secret
> > +                    + "&grant_type=authorization_code"
> > +                    + "&code=" + authorizationCode
> > +                    + "&redirect_uri=" + URLEncoder.encode(returnURI,
> > "UTF-8");
> > +            // Debug.logInfo("LinkedIn get access token query string: "
> +
> > queryString, module);
> > +            postMethod.setQueryString(queryString);
> > +            params.setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
> > +            postMethod.setParams(params);
> > +            jsonClient.executeMethod(postMethod);
> > +            // Debug.logInfo("LinkedIn get access token response code: "
> > + postMethod.getStatusCode(), module);
> > +            // Debug.logInfo("LinkedIn get access token response
> content:
> > " + postMethod.getResponseBodyAsString(1024), module);
> > +            if (postMethod.getStatusCode() == HttpStatus.SC_OK) {
> > +                // Debug.logInfo("Json Response from LinkedIn: " +
> > postMethod.getResponseBodyAsString(1024), module);
> > +                JSON jsonObject =
> > JSON.from(postMethod.getResponseBodyAsString(1024));
> > +                JSONToMap jsonMap = new JSONToMap();
> > +                Map<String, Object> userMap =
> jsonMap.convert(jsonObject);
> > +                accessToken = (String) userMap.get("access_token");
> > +                // Debug.logInfo("Generated Access Token : " +
> > accessToken, module);
> > +            } else {
> > +                String errMsg = UtilProperties.getMessage(resource,
> > "GetOAuth2LinkedInAccessTokenError", UtilMisc.toMap("error",
> > postMethod.getResponseBodyAsString()), UtilHttp.getLocale(request));
> > +                request.setAttribute("_ERROR_MESSAGE_", errMsg);
> > +                return "error";
> > +            }
> > +        } catch (UnsupportedEncodingException e) {
> > +            request.setAttribute("_ERROR_MESSAGE_", e.toString());
> > +            return "error";
> > +        } catch (HttpException e) {
> > +            request.setAttribute("_ERROR_MESSAGE_", e.toString());
> > +            return "error";
> > +        } catch (IOException e) {
> > +            request.setAttribute("_ERROR_MESSAGE_", e.toString());
> > +            return "error";
> > +        } catch (ConversionException e) {
> > +            request.setAttribute("_ERROR_MESSAGE_", e.toString());
> > +            return "error";
> > +        } finally {
> > +            postMethod.releaseConnection();
> > +        }
> > +
> > +        // Get User Profile
> > +        GetMethod getMethod = new GetMethod(TokenEndpoint + UserApiUri +
> > "?oauth2_access_token=" + accessToken);
> > +        Document userInfo = null;
> > +        try {
> > +            userInfo = LinkedInAuthenticator.getUserInfo(getMethod,
> > UtilHttp.getLocale(request));
> > +        } catch (HttpException e) {
> > +            request.setAttribute("_ERROR_MESSAGE_", e.toString());
> > +            return "error";
> > +        } catch (IOException e) {
> > +            request.setAttribute("_ERROR_MESSAGE_", e.toString());
> > +            return "error";
> > +        } catch (AuthenticatorException e) {
> > +            request.setAttribute("_ERROR_MESSAGE_", e.toString());
> > +            return "error";
> > +        } catch (SAXException e) {
> > +            request.setAttribute("_ERROR_MESSAGE_", e.toString());
> > +            return "error";
> > +        } catch (ParserConfigurationException e) {
> > +            request.setAttribute("_ERROR_MESSAGE_", e.toString());
> > +            return "error";
> > +        } finally {
> > +            getMethod.releaseConnection();
> > +        }
> > +        // Debug.logInfo("LinkedIn User Info:" + userInfo, module);
> > +
> > +        // Store the user info and check login the user
> > +        return checkLoginLinkedInUser(request, userInfo, accessToken);
> > +    }
> > +
> > +    private static String checkLoginLinkedInUser(HttpServletRequest
> > request, Document userInfo, String accessToken) {
> > +        Delegator delegator = (Delegator)
> > request.getAttribute("delegator");
> > +        LocalDispatcher dispatcher = (LocalDispatcher)
> > request.getAttribute("dispatcher");
> > +        String productStoreId =
> > ProductStoreWorker.getProductStoreId(request);
> > +        String linkedInUserId =
> > LinkedInAuthenticator.getLinkedInUserId(userInfo);
> > +        GenericValue linkedInUser = null;
> > +        try {
> > +            linkedInUser = delegator.findOne("LinkedInUser",
> > UtilMisc.toMap("linkedInUserId", linkedInUserId), false);
> > +        } catch (GenericEntityException e) {
> > +            request.setAttribute("_ERROR_MESSAGE_", e.getMessage());
> > +            return "error";
> > +        }
> > +        if (UtilValidate.isNotEmpty(linkedInUser)) {
> > +            boolean dataChanged = false;
> > +            if
> > (!accessToken.equals(linkedInUser.getString("accessToken"))) {
> > +                linkedInUser.set("accessToken", accessToken);
> > +                dataChanged = true;
> > +            }
> > +            if (!envPrefix.equals(linkedInUser.getString("envPrefix")))
> {
> > +                linkedInUser.set("envPrefix", envPrefix);
> > +                dataChanged = true;
> > +            }
> > +            if
> > (!productStoreId.equals(linkedInUser.getString("productStoreId"))) {
> > +                linkedInUser.set("productStoreId", productStoreId);
> > +                dataChanged = true;
> > +            }
> > +            if (dataChanged) {
> > +                try {
> > +                    linkedInUser.store();
> > +                } catch (GenericEntityException e) {
> > +                    Debug.logError(e.getMessage(), module);
> > +                }
> > +            }
> > +        } else {
> > +            linkedInUser = delegator.makeValue("LinkedInUser",
> > UtilMisc.toMap("accessToken", accessToken,
> > +
> > "productStoreId", productStoreId,
> > +
> > "envPrefix", envPrefix,
> > +
> > "linkedInUserId", linkedInUserId));
> > +            try {
> > +                linkedInUser.create();
> > +            } catch (GenericEntityException e) {
> > +                Debug.logError(e.getMessage(), module);
> > +            }
> > +        }
> > +        try {
> > +            GenericValue userLogin =
> > EntityUtil.getFirst(delegator.findByAnd("UserLogin",
> > UtilMisc.toMap("externalAuthId", linkedInUserId), null, false));
> > +            LinkedInAuthenticator authn = new LinkedInAuthenticator();
> > +            authn.initialize(dispatcher);
> > +            if (UtilValidate.isEmpty(userLogin)) {
> > +                String userLoginId = authn.createUser(userInfo);
> > +                userLogin = delegator.findOne("UserLogin",
> > UtilMisc.toMap("userLoginId", userLoginId), false);
> > +            }
> > +            String password = PassportUtil.randomString();
> > +            boolean useEncryption =
> > "true".equals(UtilProperties.getPropertyValue("security.properties",
> > "password.encrypt"));
> > +            userLogin.set("currentPassword", useEncryption ?
> > HashCrypt.digestHash(LoginServices.getHashType(), null, password) :
> > password);
> > +            userLogin.store();
> > +            request.setAttribute("USERNAME",
> > userLogin.getString("userLoginId"));
> > +            request.setAttribute("PASSWORD", password);
> > +        } catch (GenericEntityException e) {
> > +            Debug.logError(e.getMessage(), module);
> > +            request.setAttribute("_ERROR_MESSAGE_", e.toString());
> > +            return "error";
> > +        } catch (AuthenticatorException e) {
> > +            Debug.logError(e.getMessage(), module);
> > +            request.setAttribute("_ERROR_MESSAGE_", e.toString());
> > +            return "error";
> > +        }
> > +        return "success";
> > +    }
> > +
> > +    public static GenericValue
> getOAuth2LinkedInConfig(HttpServletRequest
> > request) {
> > +        Delegator delegator = (Delegator)
> > request.getAttribute("delegator");
> > +        String productStoreId =
> > ProductStoreWorker.getProductStoreId(request);
> > +        try {
> > +            return getOAuth2LinkedInConfig(delegator, productStoreId);
> > +        } catch (GenericEntityException e) {
> > +            Map<String, String> messageMap =
> > UtilMisc.toMap("errorMessage", e.toString());
> > +            String errMsg = UtilProperties.getMessage(resource,
> > "GetOAuth2LinkedInError", messageMap, UtilHttp.getLocale(request));
> > +            request.setAttribute("_ERROR_MESSAGE_", errMsg);
> > +        }
> > +        return null;
> > +    }
> > +
> > +    public static GenericValue getOAuth2LinkedInConfig(Delegator
> > delegator, String productStoreId) throws GenericEntityException {
> > +        return
> >
>
> EntityUtil.getFirst(EntityUtil.filterByDate(delegator.findByAnd("OAuth2LinkedIn",
> > UtilMisc.toMap("productStoreId", productStoreId), null, false)));
> > +    }
> > +}
> >
> > Propchange:
> >
>
> ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/LinkedInEvents.java
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:eol-style = native
> >
> > Propchange:
> >
>
> ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/LinkedInEvents.java
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:keywords = Date Rev Author URL Id
> >
> > Propchange:
> >
>
> ofbiz/trunk/specialpurpose/passport/src/org/ofbiz/passport/event/LinkedInEvents.java
> >
> >
>
> ------------------------------------------------------------------------------
> >     svn:mime-type = text/plain
> >
> >
> >
>

Reply via email to