Commit 34317a70 authored by igoshin's avatar igoshin Committed by Matija Obreza
Browse files

Finish google account integration (+2 squashed commits)

Squashed commits:
[0dcbc98] First version of user story "Login with google"
[66df377] First version of user story "Login with google"
parent 0940539f
...@@ -43,6 +43,8 @@ ...@@ -43,6 +43,8 @@
<spring.security.oauth2.version>1.0.5.RELEASE</spring.security.oauth2.version> <spring.security.oauth2.version>1.0.5.RELEASE</spring.security.oauth2.version>
<spring.data.core.version>1.5.1.RELEASE</spring.data.core.version> <spring.data.core.version>1.5.1.RELEASE</spring.data.core.version>
<spring.data.jpa.version>1.3.5.RELEASE</spring.data.jpa.version> <spring.data.jpa.version>1.3.5.RELEASE</spring.data.jpa.version>
<org.springframework.social-version>1.0.3.RELEASE</org.springframework.social-version>
<org.springframework.social-google-version>1.0.0.M3</org.springframework.social-google-version>
<mysql.version>5.1.25</mysql.version> <mysql.version>5.1.25</mysql.version>
...@@ -67,10 +69,25 @@ ...@@ -67,10 +69,25 @@
<name>ibiblio.mirrors</name> <name>ibiblio.mirrors</name>
<url>http://mirrors.ibiblio.org/pub/mirrors/maven2</url> <url>http://mirrors.ibiblio.org/pub/mirrors/maven2</url>
</repository> </repository>
<!-- <repository> <repository>
<id>sonatype mirror</id> <id>spring-social-google</id>
<url>http://search.maven.org/remotecontent?filepath=</url> <name>Spring Social Google</name>
</repository> --> <url>http://gabiaxel.github.io/maven/</url>
</repository>
<repository>
<id>sonatype-oss</id>
<url>https://oss.sonatype.org/content/groups/public</url>
</repository>
<repository>
<id>releases</id>
<name>Releases</name>
<url>https://oss.sonatype.org/content/repositories/releases</url>
</repository>
<!-- <repository>
<id>sonatype mirror</id>
<url>http://search.maven.org/remotecontent?filepath=</url>
</repository> -->
</repositories> </repositories>
<dependencies> <dependencies>
...@@ -242,7 +259,61 @@ ...@@ -242,7 +259,61 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!-- Hibernate dependencies --> <dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-google</artifactId>
<version>${org.springframework.social-google-version}</version>
</dependency>
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-web</artifactId>
<version>${org.springframework.social-version}</version>
</dependency>
<dependency>
<groupId>org.springframework.social</groupId>
<artifactId>spring-social-core</artifactId>
<version>${org.springframework.social-version}</version>
</dependency>
<dependency>
<groupId>com.google.oauth-client</groupId>
<artifactId>google-oauth-client-servlet</artifactId>
<version>1.17.0-rc</version>
</dependency>
<dependency>
<groupId>com.googlecode.googleplus</groupId>
<artifactId>google-plus-java-api</artifactId>
<exclusions>
<exclusion>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
</exclusion>
<exclusion>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
</exclusion>
</exclusions>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.google.api.client</groupId>
<artifactId>google-api-client</artifactId>
<exclusions>
<exclusion>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
</exclusion>
</exclusions>
<version>1.3.1-alpha</version>
</dependency>
<!-- Hibernate dependencies -->
<dependency> <dependency>
<groupId>org.hibernate</groupId> <groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId> <artifactId>hibernate-core</artifactId>
...@@ -286,11 +357,11 @@ ...@@ -286,11 +357,11 @@
<version>${oval.version}</version> <version>${oval.version}</version>
</dependency> </dependency>
<dependency> <!--<dependency>-->
<groupId>com.fasterxml.jackson.core</groupId> <!--<groupId>com.fasterxml.jackson.core</groupId>-->
<artifactId>jackson-databind</artifactId> <!--<artifactId>jackson-databind</artifactId>-->
<version>${jackson.version}</version> <!--<version>${jackson.version}</version>-->
</dependency> <!--</dependency>-->
<!--Jetty --> <!--Jetty -->
...@@ -357,6 +428,16 @@ ...@@ -357,6 +428,16 @@
<artifactId>mail</artifactId> <artifactId>mail</artifactId>
<version>1.5.0-b01</version> <version>1.5.0-b01</version>
</dependency> </dependency>
<dependency>
<groupId>com.github.fernandospr</groupId>
<artifactId>javapns-jdk16</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>com.google.api-client</groupId>
<artifactId>google-api-client</artifactId>
<version>1.17.0-rc</version>
</dependency>
</dependencies> </dependencies>
<build> <build>
......
...@@ -22,6 +22,7 @@ import org.genesys2.server.model.wrapper.UserWrapper; ...@@ -22,6 +22,7 @@ import org.genesys2.server.model.wrapper.UserWrapper;
import org.springframework.data.domain.Page; import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.social.google.api.userinfo.GoogleUserInfo;
public interface UserService { public interface UserService {
...@@ -71,4 +72,6 @@ public interface UserService { ...@@ -71,4 +72,6 @@ public interface UserService {
void setAccountLockLocal(String uuid, boolean locked); void setAccountLockLocal(String uuid, boolean locked);
void userEmailValidated(String uuid) throws UserException; void userEmailValidated(String uuid) throws UserException;
void googleAuthentication(GoogleUserInfo userInfo) throws UserException;
} }
...@@ -16,12 +16,6 @@ ...@@ -16,12 +16,6 @@
package org.genesys2.server.service.impl; package org.genesys2.server.service.impl;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.genesys2.server.exception.NoUserFoundException; import org.genesys2.server.exception.NoUserFoundException;
...@@ -49,9 +43,12 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority; ...@@ -49,9 +43,12 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.social.google.api.userinfo.GoogleUserInfo;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import java.util.*;
@Service @Service
@Transactional(readOnly = true) @Transactional(readOnly = true)
public class UserServiceImpl implements UserService { public class UserServiceImpl implements UserService {
...@@ -350,7 +347,24 @@ public class UserServiceImpl implements UserService { ...@@ -350,7 +347,24 @@ public class UserServiceImpl implements UserService {
LOG.info("Ensured VALIDATEDUSER role for user " + user); LOG.info("Ensured VALIDATEDUSER role for user " + user);
} }
private void addRoleToCurrentUser(User user, String role) { @Override
public void googleAuthentication(GoogleUserInfo userInfo) throws UserException {
User user=getUserByEmail(userInfo.getEmail());
userEmailValidated(user.getUuid());
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
grantedAuthorities.add(new SimpleGrantedAuthority("USER"));
grantedAuthorities.add(new SimpleGrantedAuthority("VALIDATEDUSER"));
AuthUserDetails userDetails = new AuthUserDetails(user.getUuid(), user.getPassword() , grantedAuthorities);
userDetails.setUser(user);
Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
}
private void addRoleToCurrentUser(User user, String role) {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal(); Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof AuthUserDetails) { if (principal instanceof AuthUserDetails) {
......
package org.genesys2.server.servlet.controller;
import org.apache.commons.lang.RandomStringUtils;
import org.genesys2.server.exception.UserException;
import org.genesys2.server.model.impl.User;
import org.genesys2.server.service.EMailVerificationService;
import org.genesys2.server.service.UserService;
import org.genesys2.server.servlet.util.GoogleOAuthUtil;
import org.json.JSONException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.social.google.api.Google;
import org.springframework.social.google.api.impl.GoogleTemplate;
import org.springframework.social.google.api.userinfo.GoogleUserInfo;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Controller
@RequestMapping("/g")
public class GoogleSocialController extends BaseController {
@Value("${google.auth.url}")
private String url;
@Autowired
private UserService userService;
@Autowired
private EMailVerificationService emailService;
@Autowired
private GoogleOAuthUtil oAuth;
@RequestMapping("/login")
public void redirectToGoogle(HttpServletResponse response) throws IOException {
response.sendRedirect(url);
}
@RequestMapping("/auth")
public String googleAuth(Model model, HttpServletRequest request) throws IOException, JSONException, UserException {
String accessToken = oAuth.exchangeForAccessToken(request);
if (accessToken == null) {
model.addAttribute("error", true);
return "/login";
}
Google google = new GoogleTemplate(accessToken);
GoogleUserInfo userInfo = google.userOperations().getUserInfo();
if (!userService.exists(userInfo.getEmail())) {
String pwd = RandomStringUtils.randomAlphanumeric(10);
User user = userService.createAccount(userInfo.getEmail(), pwd, userInfo.getName());
emailService.sendPasswordForGenesysAccount(user, pwd);
}
userService.googleAuthentication(userInfo);
return "redirect:/profile";
}
}
/** /**
* Copyright 2013 Global Crop Diversity Trust * Copyright 2013 Global Crop Diversity Trust
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
...@@ -19,6 +19,7 @@ package org.genesys2.server.servlet.controller; ...@@ -19,6 +19,7 @@ package org.genesys2.server.servlet.controller;
import org.genesys2.server.model.Permissions; import org.genesys2.server.model.Permissions;
import org.genesys2.server.model.UserRole; import org.genesys2.server.model.UserRole;
import org.genesys2.server.model.impl.User; import org.genesys2.server.model.impl.User;
import org.genesys2.server.security.lockout.AccountLockoutManager;
import org.genesys2.server.service.ContentService; import org.genesys2.server.service.ContentService;
import org.genesys2.server.service.CropService; import org.genesys2.server.service.CropService;
import org.genesys2.server.service.EMailVerificationService; import org.genesys2.server.service.EMailVerificationService;
...@@ -26,7 +27,6 @@ import org.genesys2.server.service.UserService; ...@@ -26,7 +27,6 @@ import org.genesys2.server.service.UserService;
import org.genesys2.util.ReCaptchaUtil; import org.genesys2.util.ReCaptchaUtil;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap; import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult; import org.springframework.validation.BindingResult;
...@@ -40,6 +40,10 @@ import javax.servlet.http.HttpServletRequest; ...@@ -40,6 +40,10 @@ import javax.servlet.http.HttpServletRequest;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.List;
/** /**
* Controller which simply handles *.html requests * Controller which simply handles *.html requests
*/ */
...@@ -64,6 +68,9 @@ public class HtmlController extends BaseController { ...@@ -64,6 +68,9 @@ public class HtmlController extends BaseController {
@Autowired @Autowired
private ContentService contentService; private ContentService contentService;
@Autowired
private AccountLockoutManager lockoutManager;
@Value("${captcha.privateKey}") @Value("${captcha.privateKey}")
private String captchaPrivateKey; private String captchaPrivateKey;
...@@ -97,7 +104,7 @@ public class HtmlController extends BaseController { ...@@ -97,7 +104,7 @@ public class HtmlController extends BaseController {
return "/registration"; return "/registration";
} }
@RequestMapping(value = "new-user") @RequestMapping(value = "new-user")
public String addUser(@ModelAttribute User user, BindingResult bindingResult, HttpServletRequest req, public String addUser(@ModelAttribute User user, BindingResult bindingResult, HttpServletRequest req,
@RequestParam(value = "recaptcha_challenge_field", required = false) String challenge, @RequestParam(value = "recaptcha_challenge_field", required = false) String challenge,
@RequestParam(value = "recaptcha_response_field", required = false) String response) { @RequestParam(value = "recaptcha_response_field", required = false) String response) {
......
package org.genesys2.server.servlet.util;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.json.JSONObject;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class GoogleOAuthUtil {
private String clientId;
private String secret;
private String redirectUrl;
public String exchangeForAccessToken(HttpServletRequest request) throws IOException, JSONException {
HttpClient httpclient = new DefaultHttpClient();
HttpPost httppost = new HttpPost("https://accounts.google.com/o/oauth2/token");
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("code", request.getParameter("code")));
params.add(new BasicNameValuePair("client_id", clientId));
params.add(new BasicNameValuePair("client_secret", secret));
params.add(new BasicNameValuePair("redirect_uri", redirectUrl));
params.add(new BasicNameValuePair("grant_type", "authorization_code"));
params.add(new BasicNameValuePair("scope", ""));
httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
HttpResponse response = httpclient.execute(httppost);
BufferedReader reader = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"));
StringBuilder builder = new StringBuilder();
for (String line = null; (line = reader.readLine()) != null; ) {
builder.append(line).append("\n");
}
JSONObject jsonObject = new JSONObject(builder.toString());
return jsonObject.getString("access_token") != null ? jsonObject.getString("access_token") : null;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public void setSecret(String secret) {
this.secret = secret;
}
public void setRedirectUrl(String redirectUrl) {
this.redirectUrl = redirectUrl;
}
}
...@@ -428,3 +428,4 @@ userprofile.email.send=Send email ...@@ -428,3 +428,4 @@ userprofile.email.send=Send email
verification.invalid-key=Token key is not valid. verification.invalid-key=Token key is not valid.
verification.token-key=Validation key verification.token-key=Validation key
login.invalid-token=Invalid access token
{
"en": {
"title": "Password for genesys account",
"body": "<h2><small>Genesys account</small><br/>Password for you genesys account</h2><p></p><h2>New password: {0}</h2><p>Thanks,<br/ >Genesys team</p>"
}
}
\ No newline at end of file
...@@ -31,5 +31,6 @@ ...@@ -31,5 +31,6 @@
<import resource="spring-security-acl.xml" /> <import resource="spring-security-acl.xml" />
<import resource="spring-security.xml" /> <import resource="spring-security.xml" />
<import resource="spring-mail.xml" /> <import resource="spring-mail.xml" />
<import resource="spring-social.xml" />
</beans> </beans>
...@@ -29,7 +29,7 @@ ...@@ -29,7 +29,7 @@
<aop:aspectj-autoproxy /> <aop:aspectj-autoproxy />
<context:property-placeholder ignore-resource-not-found="true" location="classpath:/application.properties,classpath:/spring/spring.properties,classpath:/genesys.properties"/> <context:property-placeholder ignore-resource-not-found="true" location="classpath:/*.properties,classpath:/spring/*.properties"/>
<context:component-scan base-package="org.genesys2.server"> <context:component-scan base-package="org.genesys2.server">
<!--Include @Entity for scanning of Acl Classes purposes--> <!--Include @Entity for scanning of Acl Classes purposes-->
......
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
<property name="validationQuery" value="SELECT 1" /> <property name="validationQuery" value="SELECT 1" />
<property name="testWhileIdle" value="true" /> <property name="testWhileIdle" value="true" />
<property name="testOnBorrow" value="true" /> <property name="testOnBorrow" value="true" />
<!-- <!--
<property name="timeBetweenEvictionRunsMillis" value="5000" /> <property name="timeBetweenEvictionRunsMillis" value="5000" />
<property name="minEvictableIdleTimeMillis" value="5000" /> <property name="minEvictableIdleTimeMillis" value="5000" />
<property name="minIdle" value="0" /> <property name="minIdle" value="0" />
...@@ -54,6 +54,9 @@ ...@@ -54,6 +54,9 @@
<prop key="hibernate.hbm2ddl.auto">${db.hbm2ddl}</prop> <prop key="hibernate.hbm2ddl.auto">${db.hbm2ddl}</prop>
<prop key="hibernate.search.default.indexBase">${lucene.indexDir}</prop> <prop key="hibernate.search.default.indexBase">${lucene.indexDir}</prop>
<prop key="hibernate.search.default.exclusive_index_use">false</prop> <prop key="hibernate.search.default.exclusive_index_use">false</prop>
<prop key="hibernate.connection.CharSet">utf8</prop>
<prop key="hibernate.connection.characterEncoding">utf8</prop>
<prop key="hibernate.connection.useUnicode">true</prop>
</props> </props>
</property> </property>
<property name="packagesToScan"> <property name="packagesToScan">
......
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright 2013 Global Crop Diversity Trust
Licensed 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.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd"
default-autowire="no">
<context:component-scan base-package="org.genesys2.server"/>
<context:property-placeholder ignore-resource-not-found="true" location="classpath:/spring/spring.properties"/>
<bean name="googleOAuthUtil" class="org.genesys2.server.servlet.util.GoogleOAuthUtil">
<property name="clientId" value="${google.consumerKey}"/>
<property name="secret" value="${google.consumerSecret}"/>
<property name="redirectUrl" value="${google.redirect.url}"/>
</bean>
</beans>
\ No newline at end of file
...@@ -16,12 +16,12 @@ ...@@ -16,12 +16,12 @@
base.url=http://localhost:8080 base.url=http://localhost:8080
db.url=jdbc:mysql://localhost/genesys4?useUnicode=true&characterEncoding=UTF-8&useFastDateParsing=false db.url=jdbc:mysql://localhost/genesys2
db.driverClassName = com.mysql.jdbc.Driver db.driverClassName = com.mysql.jdbc.Driver
db.username = root db.username = root
db.password = 1 db.password = 1
db.showSql=false db.showSql=false
db.hbm2ddl=do-nothing db.hbm2ddl=update
c3p0.acquireIncrement=1 c3p0.acquireIncrement=1
c3p0.minPoolSize=1 c3p0.minPoolSize=1
...@@ -60,7 +60,6 @@ mail.user.from=test@example.com ...@@ -60,7 +60,6 @@ mail.user.from=test@example.com
mail.user.password=