Commit 3211dc28 authored by igoshin's avatar igoshin
Browse files

Final version of user story "Email validation"

#10141
parent 12860fb1
......@@ -352,6 +352,13 @@
<artifactId>spring-aspects</artifactId>
<version>3.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.5.0-b01</version>
</dependency>
</dependencies>
<build>
......
......@@ -17,16 +17,94 @@
package org.genesys2.server.service.impl;
import org.genesys2.server.service.EMailService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.mail.javamail.MimeMessagePreparator;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import javax.mail.internet.MimeMessage;
import java.util.Arrays;
@Service
public class EMailServiceImpl implements EMailService {
// TODO get SMTP properties from properties file
private Logger _logger = LoggerFactory.getLogger(getClass());
@Autowired
private JavaMailSender mailSender;
@Autowired
private ThreadPoolTaskExecutor executor;
@Value("${mail.async}")
private boolean async;
@Value("${mail.debug.message}")
private String debugMessage;
@Value("${mail.user.from}")
private String emailFrom;
@Override
public void sendMail(String email, String name, String mailSubject, String mailBody) {
// TODO Auto-generated method stub
sendSimpleEmail(mailSubject, mailBody, emailFrom, email);
}
public void sendSimpleEmail(final String subject, final String text, final String emailFrom, final String... emailTo) {
printDebugInfo(subject, text, emailFrom, emailTo);
final MimeMessagePreparator preparator = new MimeMessagePreparator() {
@SuppressWarnings("unchecked")
@Override
public void prepare(MimeMessage mimeMessage) throws Exception {
MimeMessageHelper message = new MimeMessageHelper(mimeMessage, "UTF-8");
message.setFrom(emailFrom);
message.setTo(emailTo);
message.setSubject(subject);
message.setText(text, true);
}
};
doSend(preparator);
}
protected void doSend(final MimeMessagePreparator preparator) {
//execute sender in separate thread
if (async) {
executor.submit(new Runnable() {
@Override
public void run() {
try {
mailSender.send(preparator);
} catch (Exception e) {
_logger.error(e.getMessage(), e);
}
}
});
} else {
mailSender.send(preparator);
}
}
protected void printDebugInfo(String subject, String text, String emailFrom, String[] emailTo) {
System.out.println(getDebugString(subject, text, emailFrom, emailTo));
}
protected String getDebugString(String subject, String text, String emailFrom, String[] emailTo) {
return String.format(debugMessage,
emailFrom,
Arrays.toString(emailTo),
subject,
text);
}
}
......@@ -16,9 +16,6 @@
package org.genesys2.server.service.impl;
import java.text.MessageFormat;
import java.util.UUID;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
......@@ -33,6 +30,9 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.text.MessageFormat;
import java.util.UUID;
@Service
@Transactional(readOnly = true)
public class EMailVerificationServiceImpl implements EMailVerificationService {
......@@ -53,7 +53,6 @@ public class EMailVerificationServiceImpl implements EMailVerificationService {
// Generate new token
VerificationToken verificationToken = generateToken("email-validation", user.getUuid());
// TODO use content services to generate email body
String mailSubject = "Genesys account verification";
String mailBody = MessageFormat.format("Click http://sandbox.genesys-pgr.org/profile/{0}/validate and enter key {1}", verificationToken.getUuid(),
verificationToken.getKey());
......@@ -67,7 +66,7 @@ public class EMailVerificationServiceImpl implements EMailVerificationService {
// Store data
token.setData(dataUuid);
token.setUuid(UUID.nameUUIDFromBytes(dataUuid.getBytes()).toString());
token.setKey(RandomStringUtils.random(4));
token.setKey(RandomStringUtils.randomAlphanumeric(4));
verificationTokenRepository.save(token);
return token;
}
......@@ -84,7 +83,7 @@ public class EMailVerificationServiceImpl implements EMailVerificationService {
try {
userService.userEmailValidated(verificationToken.getData());
// FIXME Move to finally?
// Remove token
verificationTokenRepository.delete(verificationToken);
return true;
......
......@@ -16,11 +16,6 @@
package org.genesys2.server.service.impl;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.genesys2.server.exception.NoUserFoundException;
......@@ -40,11 +35,21 @@ import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Service
@Transactional(readOnly = true)
public class UserServiceImpl implements UserService {
......@@ -296,7 +301,21 @@ public class UserServiceImpl implements UserService {
}
// Since it's a set, we can just add
userRoles.add(UserRole.VALIDATEDUSER);
addRole(UserRole.VALIDATEDUSER.getName());
updateUser(user);
LOG.info("Ensured VALIDATEDUSER role for user " + user);
}
private void addRole(String role){
List<GrantedAuthority> authorities=new ArrayList<>();
SimpleGrantedAuthority simpleGrantedAuthority=new SimpleGrantedAuthority(role);
authorities.add(simpleGrantedAuthority);
Object principal= SecurityContextHolder.getContext().getAuthentication().getPrincipal();
Authentication authentication=new UsernamePasswordAuthenticationToken(principal,principal,authorities);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
......@@ -27,6 +27,7 @@ import org.genesys2.spring.ResourceNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.Validator;
......@@ -39,6 +40,9 @@ import org.springframework.web.bind.annotation.RequestParam;
@RequestMapping("/profile")
public class UserProfileController extends BaseController {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private UserService userService;
......@@ -90,27 +94,41 @@ public class UserProfileController extends BaseController {
@RequestMapping(value = "/{tokenUuid:.+}/validate", method = RequestMethod.GET)
public String validateEmail(ModelMap model, @PathVariable("tokenUuid") String tokenUuid) {
// TODO Fill model
// TODO Fix /WEB-INF/jsp/user/validateemail.jsp
model.addAttribute("tokenUuid",tokenUuid);
return "/user/validateemail";
}
@RequestMapping(value = "/{uuid}/send", method = RequestMethod.GET)
public String sendEmail(ModelMap model, @PathVariable("uuid") String uuid) {
User user = userService.getUserByUuid(uuid);
emailVerificationService.sendVerificationEmail(user);
model.addAttribute("tokenUuid", uuid);
return "redirect:/profile/" + user.getUuid();
}
@RequestMapping(value = "/{tokenUuid:.+}/validate", method = RequestMethod.POST)
public String validateEmail2(ModelMap model, @PathVariable("tokenUuid") String tokenUuid, @RequestParam("key") String key) {
if (emailVerificationService.validateEMail(tokenUuid, key)) {
// Valid
// TODO Change current security context if user is logged in
// redirect
// Valid
return "redirect:/profile";
} else {
// Not valid
model.addAttribute("tokenUuid", tokenUuid);
model.addAttribute("error", "error");
return "/user/validateemail";
}
}
@PreAuthorize("isAuthenticated()")
@RequestMapping(value = "/update", method = { RequestMethod.POST })
@RequestMapping(value = "/update", method = {RequestMethod.POST})
public String updateMe(ModelMap model, @RequestParam("name") String name, @RequestParam("pwd1") String pwd1, @RequestParam("pwd2") String pwd2) {
User user = userService.getMe();
if (user == null) {
......
......@@ -320,4 +320,7 @@ team.leave-team=Leave team
team.team-members=Team members
team.page.profile.title=Team: {0}
team.page.list.title=All teams
validate.email.key=Enter key
validate.email=Email validation
validate.email.invalid.key=Invalid key
......@@ -317,4 +317,7 @@ team.leave-team=مغادرة الفريق
team.team-members=أعضاء الفريق
team.page.profile.title=فريق\: {0}
team.page.list.title=جميع الفرق
validate.email.key=Enter key
validate.email=Email validation
validate.email.invalid.key=Invalid key
......@@ -317,4 +317,7 @@ team.leave-team=Team verlassen
team.team-members=Teammitglieder
team.page.profile.title=Team\: {0}
team.page.list.title=Alle Teams
validate.email.key=Enter key
validate.email=Email validation
validate.email.invalid.key=Invalid key
......@@ -13,3 +13,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#-------------------------------------------------------------------------------
validate.email.key=Enter key
validate.email=Email validation
validate.email.invalid.key=Invalid key
\ No newline at end of file
......@@ -317,4 +317,7 @@ team.leave-team=Dejar equipo
team.team-members=Miembros del equipo
team.page.profile.title=Equipo\: {0}
team.page.list.title=Todos los equipos
validate.email.key=Enter key
validate.email=Email validation
validate.email.invalid.key=Invalid key
......@@ -240,6 +240,9 @@ article.body=بدنه مقاله
# activitypost.add-new-post=Add new post
activitypost.post-title=تیتر پست
activitypost.post-body=بدنه
validate.email.key=Enter key
validate.email=Email validation
validate.email.invalid.key=Invalid key
# blurp.admin-no-blurp-here=No blurp here.
# blurp.blurp-title=Blurp title
......
......@@ -254,3 +254,6 @@ oauth2.authorization-code-instructions=Copier ce code d'autorisation \:
oauth2.access-denied=Accès refusé
oauth2.access-denied-text=Vous avez refusé l'accès à vos ressources.
validate.email.key=Enter key
validate.email=Email validation
validate.email.invalid.key=Invalid key
......@@ -317,4 +317,7 @@ team.leave-team=Sair da equipa
team.team-members=Membros da equipa
team.page.profile.title=Equipa\: {0}
team.page.list.title=Todas as equipas
validate.email.key=Enter key
validate.email=Email validation
validate.email.invalid.key=Invalid key
......@@ -317,4 +317,7 @@ team.leave-team=Покинуть команду
team.team-members=Члены команды
team.page.profile.title=Команда\: {0}
team.page.list.title=Все команды
validate.email.key=Enter key
validate.email=Email validation
validate.email.invalid.key=Invalid key
......@@ -13,3 +13,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#-------------------------------------------------------------------------------
validate.email.key=Enter key
validate.email=Email validation
validate.email.invalid.key=Invalid key
\ No newline at end of file
......@@ -320,4 +320,7 @@ team.leave-team=离开团队
team.team-members=团队成员
team.page.profile.title=团队:{0}
team.page.list.title=所有团队
validate.email.key=Enter key
validate.email=Email validation
validate.email.invalid.key=Invalid key
......@@ -30,5 +30,6 @@
<import resource="spring-security-oauth.xml" />
<import resource="spring-security-acl.xml" />
<import resource="spring-security.xml" />
<import resource="spring-mail.xml" />
</beans>
<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 id="mailSender" class="org.springframework.mail.javamail.JavaMailSenderImpl">
<property name="host" value="${mail.host}"/>
<property name="port" value="${mail.port}"/>
<property name="username" value="${mail.user.name}"/>
<property name="password" value="${mail.user.password}"/>
<property name="javaMailProperties">
<props>
<prop key="mail.smtp.ssl.enable">${mail.smtp.ssl.enable}</prop>
<prop key="mail.smtp.auth">${mail.smtp.auth}</prop>
<prop key="mail.transport.protocol">${mail.transport.protocol}</prop>
</props>
</property>
</bean>
</beans>
\ No newline at end of file
......@@ -23,7 +23,7 @@
db.url=jdbc:mysql://127.0.0.1/genesys2?useUnicode=true&characterEncoding=UTF-8&useFastDateParsing=false&autoCommit=false
db.driverClassName = com.mysql.jdbc.Driver
db.username = root
db.password =
db.password = 1
db.showSql=false
db.hbm2ddl=do-nothing
......@@ -55,4 +55,27 @@ cdn.flags.url=${cdn.base}/flags
# Content creation on startup
auto.createContent=true
# Mail properties
mail.host=localhost
mail.port=25
mail.user.from=test@example.com
mail.user.password=
mail.user.name=
mail.smtp.ssl.enable=true
mail.smtp.auth=true
mail.transport.protocol=smtp
mail.async=true
mail.debug.message= Email has been sent succesfully\n\
Details:\n\
From:%s\n\
To:%s\n\
Subject: %s\n\
Text: \n==================================\n\n\
%s\
\n\n==================================
......@@ -30,7 +30,7 @@
</div>
<security:authorize access="(not hasRole('VALIDATEDUSER') && principal.user.id == #user.id)">
<div class="">TODO FIXME Display alert and button to send validation email!</div>
<a href="<c:url value="/profile/${user.uuid}/send"/>" class="btn btn-default"/>Send validation email</a>
</security:authorize>
<h3><spring:message code="team.user-teams" /></h3>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment