修复用户登录逻辑
This commit is contained in:
parent
75cb0d2445
commit
d1dee415b2
36
pom.xml
36
pom.xml
|
@ -40,6 +40,24 @@
|
|||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- guava 基础库 -->
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>31.1-jre</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.configcat</groupId>
|
||||
<artifactId>configcat-java-client</artifactId>
|
||||
<version>7.2.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-jpa</artifactId>
|
||||
|
@ -87,6 +105,24 @@
|
|||
<version>0.9.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.mailgun</groupId>
|
||||
<artifactId>mailgun-java</artifactId>
|
||||
<version>1.0.3</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-simple</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<!--Thymeleaf support email template -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
* XMLUtils.java
|
||||
*
|
||||
* Created on December 6, 2001, 1:21 PM
|
||||
*/
|
||||
package com.northtecom.visatrack.api.base.util;
|
||||
|
||||
import com.configcat.ConfigCatClient;
|
||||
import com.configcat.User;
|
||||
import com.mailgun.api.v3.MailgunMessagesApi;
|
||||
import com.mailgun.client.MailgunClient;
|
||||
import com.mailgun.model.message.Message;
|
||||
import com.mailgun.model.message.MessageResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Utilities for Email sending
|
||||
*
|
||||
* @author YuCheng Hu
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class EmailUtils {
|
||||
|
||||
public static final String EMAIL_KEY_NAME = "emailKey";
|
||||
public static final String EMAIL_KEY_SENDER_NAME = "emailSender";
|
||||
public static final String EMAIL_KEY_IDENTIFIER = "MailGun";
|
||||
|
||||
public static final String EMAIL_DOMAIN = "mail.usvisatrack.com";
|
||||
|
||||
private static String emailSenderAddress = "info@usvisatrack.com";
|
||||
|
||||
private final ConfigCatClient configCatClient;
|
||||
private MailgunMessagesApi mailgunMessagesApi;
|
||||
|
||||
@Autowired
|
||||
public EmailUtils(ConfigCatClient configCatClient) {
|
||||
this.configCatClient = configCatClient;
|
||||
User userObject = User.newBuilder().build(EMAIL_KEY_IDENTIFIER);
|
||||
// Unique identifier is required. Could be UserID, Email address or SessionID.
|
||||
String emailKey = configCatClient.getValue(String.class, EMAIL_KEY_NAME, userObject, StringUtils.EMPTY);
|
||||
emailSenderAddress = configCatClient.getValue(String.class, EMAIL_KEY_SENDER_NAME, userObject,
|
||||
emailSenderAddress);
|
||||
mailgunMessagesApi = MailgunClient.config(emailKey).createApi(MailgunMessagesApi.class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send Test Email to check config and email sending API
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public MessageResponse sendTestEmail() {
|
||||
|
||||
Message message =
|
||||
Message.builder().from(emailSenderAddress).to("huyuchengus@gmail.com").subject("TEST").html("<html>\n"
|
||||
+ "<body>\n" + "\t<h1>Sending HTML emails with Mailgun</h1>\n" + "\t<p style=\"color:blue; " +
|
||||
"font-size:30px;\">Hello world</p>\n" + "\t<p style=\"font-size:30px;\">More examples can be " +
|
||||
"found <a href=\"https://www.ossez.com\">here</a></p>\n" + "</body>\n" + "</html>").build();
|
||||
|
||||
MessageResponse messageResponse = mailgunMessagesApi.sendMessage(EMAIL_DOMAIN, message);
|
||||
return messageResponse;
|
||||
|
||||
}
|
||||
|
||||
public MessageResponse sendTestEmail(String toEmail, String subject) {
|
||||
|
||||
Message message = Message.builder().from(emailSenderAddress).to(toEmail).subject(subject).html("<html>\n" +
|
||||
"<body>\n" + "\t<h1>Sending HTML emails with Mailgun</h1>\n" + "\t<p style=\"color:blue; " +
|
||||
"font-size:30px;\">Hello world</p>\n" + "\t<p style=\"font-size:30px;\">More examples can be found <a" +
|
||||
" href=\"https://www.ossez.com\">here</a></p>\n" + "</body>\n" + "</html>").build();
|
||||
|
||||
MessageResponse messageResponse = mailgunMessagesApi.sendMessage(EMAIL_DOMAIN, message);
|
||||
return messageResponse;
|
||||
|
||||
}
|
||||
|
||||
public MessageResponse sendEmail(String toEmail, String subject, String htmlContent) {
|
||||
|
||||
Message message =
|
||||
Message.builder().from(emailSenderAddress).to(toEmail).subject(subject).html(htmlContent).build();
|
||||
MessageResponse messageResponse = mailgunMessagesApi.sendMessage(EMAIL_DOMAIN, message);
|
||||
return messageResponse;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
package com.northtecom.visatrack.api.base.util;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.northtecom.visatrack.api.config.JwtConfig;
|
||||
import io.jsonwebtoken.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
@EnableConfigurationProperties({JwtConfig.class})
|
||||
@Configuration
|
||||
public class JwtUtil {
|
||||
private static final Logger log = LoggerFactory.getLogger(JwtUtil.class);
|
||||
@Autowired
|
||||
private JwtConfig jwtConfig;
|
||||
|
||||
public JwtUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rememberMe 是否记住登录
|
||||
* @param useId 用户id
|
||||
* @param userName 用户名
|
||||
* @param roles 用户角色
|
||||
* @param authorities 用户权限
|
||||
* @return JWT token
|
||||
*/
|
||||
public String createJWT(Boolean rememberMe, Long useId, String userName, List<String> roles, Collection<?
|
||||
extends GrantedAuthority> authorities, Map<String, Object> claims) {
|
||||
Date now = new Date();
|
||||
JwtBuilder jwtBuilder = Jwts.builder()
|
||||
// 将userId放进JWT
|
||||
.setId(useId.toString())
|
||||
// 将userName放进JWT
|
||||
.setSubject(userName)
|
||||
.setIssuedAt(now)
|
||||
.signWith(SignatureAlgorithm.HS256, this.jwtConfig.getKey())
|
||||
.claim("roles", roles)
|
||||
.claim("authorities", authorities);
|
||||
|
||||
// 设置过期时间
|
||||
Long ttl = rememberMe ? this.jwtConfig.getRemember() : this.jwtConfig.getTtl();
|
||||
if (ttl > 0L) {
|
||||
jwtBuilder.setExpiration(DateUtil.offsetMillisecond(now, ttl.intValue()));
|
||||
}
|
||||
|
||||
// 设置附加身份信息
|
||||
for (String key : claims.keySet()) {
|
||||
jwtBuilder.claim(key, claims.get(key));
|
||||
}
|
||||
|
||||
String jwt = jwtBuilder.compact();
|
||||
return jwt;
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析JWT
|
||||
*
|
||||
* @param jwt JWT
|
||||
* @return {@link Claims}
|
||||
*/
|
||||
public Claims parseJWT(String jwt) {
|
||||
try {
|
||||
Claims claims = Jwts.parser().setSigningKey(jwtConfig.getKey()).parseClaimsJws(jwt).getBody();
|
||||
|
||||
return claims;
|
||||
} catch (ExpiredJwtException e) {
|
||||
log.error("Token 已过期");
|
||||
throw e;
|
||||
} catch (UnsupportedJwtException e) {
|
||||
log.error("不支持的 Token");
|
||||
throw e;
|
||||
} catch (MalformedJwtException e) {
|
||||
log.error("Token 无效");
|
||||
throw e;
|
||||
} catch (SignatureException e) {
|
||||
log.error("无效的 Token 签名");
|
||||
throw e;
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.error("Token 参数不存在");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String getUsernameFromJWT(String jwt) throws ExpiredJwtException, UnsupportedJwtException,
|
||||
MalformedJwtException, SignatureException, IllegalArgumentException {
|
||||
Claims claims = this.parseJWT(jwt);
|
||||
return claims.getSubject();
|
||||
}
|
||||
|
||||
public String getJwtFromRequest(HttpServletRequest request) {
|
||||
String bearerToken = request.getHeader("Authorization");
|
||||
return StrUtil.isNotBlank(bearerToken) && bearerToken.startsWith("Bearer ") ? bearerToken.substring(7) : null;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package com.northtecom.visatrack.api.base.web;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.northtecom.visatrack.api.base.util.JwtUtil;
|
||||
import com.northtecom.visatrack.api.service.impl.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Created with IntelliJ IDEA.
|
||||
*
|
||||
* @Author: XieYang
|
||||
* @Date: 2022/10/03/20:29
|
||||
* @Description:
|
||||
*/
|
||||
|
||||
@Component
|
||||
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Autowired
|
||||
private JwtUtil jwtUtil;
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain filterChain) throws ServletException, IOException {
|
||||
|
||||
String jwt = jwtUtil.getJwtFromRequest(request);
|
||||
|
||||
// 没有jwt就放行
|
||||
if (StrUtil.isBlank(jwt)) {
|
||||
filterChain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
String username = jwtUtil.getUsernameFromJWT(jwt);
|
||||
UserDetails userDetails = userService.loadUserByUsername(username);
|
||||
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails,
|
||||
null, userDetails.getAuthorities());
|
||||
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
filterChain.doFilter(request, response);
|
||||
} catch (Exception ex) {
|
||||
//获取用户信息失败也放行
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package com.northtecom.visatrack.api.config;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 自定义配置
|
||||
* </p>
|
||||
*
|
||||
* @date Created in 2018-12-13 10:56
|
||||
*/
|
||||
@Data
|
||||
@ConfigurationProperties(prefix = "custom.config")
|
||||
public class CustomConfig {
|
||||
/**
|
||||
* 不需要拦截的地址
|
||||
*/
|
||||
private IgnoreConfig ignores;
|
||||
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package com.northtecom.visatrack.api.config;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 忽略配置
|
||||
* </p>
|
||||
*
|
||||
* @author yangkai.shen
|
||||
* @date Created in 2018-12-17 17:37
|
||||
*/
|
||||
@Data
|
||||
public class IgnoreConfig {
|
||||
/**
|
||||
* 需要忽略的 URL 格式,不考虑请求方法
|
||||
*/
|
||||
private List<String> pattern = Lists.newArrayList();
|
||||
|
||||
/**
|
||||
* 需要忽略的 GET 请求
|
||||
*/
|
||||
private List<String> get = Lists.newArrayList();
|
||||
|
||||
/**
|
||||
* 需要忽略的 POST 请求
|
||||
*/
|
||||
private List<String> post = Lists.newArrayList();
|
||||
|
||||
/**
|
||||
* 需要忽略的 DELETE 请求
|
||||
*/
|
||||
private List<String> delete = Lists.newArrayList();
|
||||
|
||||
/**
|
||||
* 需要忽略的 PUT 请求
|
||||
*/
|
||||
private List<String> put = Lists.newArrayList();
|
||||
|
||||
/**
|
||||
* 需要忽略的 HEAD 请求
|
||||
*/
|
||||
private List<String> head = Lists.newArrayList();
|
||||
|
||||
/**
|
||||
* 需要忽略的 PATCH 请求
|
||||
*/
|
||||
private List<String> patch = Lists.newArrayList();
|
||||
|
||||
/**
|
||||
* 需要忽略的 OPTIONS 请求
|
||||
*/
|
||||
private List<String> options = Lists.newArrayList();
|
||||
|
||||
/**
|
||||
* 需要忽略的 TRACE 请求
|
||||
*/
|
||||
private List<String> trace = Lists.newArrayList();
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package com.northtecom.visatrack.api.controller.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.Email;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
|
||||
/**
|
||||
* Created with IntelliJ IDEA.
|
||||
*
|
||||
* @Author: XieYang
|
||||
* @Date: 2022/10/01/17:08
|
||||
* @Description:
|
||||
*/
|
||||
@Data
|
||||
public class RegisterUserRequest {
|
||||
@NotBlank(message = "User name can not be empty.")
|
||||
private String userName;
|
||||
@NotBlank(message = "Password can not be empty.")
|
||||
private String password;
|
||||
@NotBlank(message = "Confirm password can not be empty.")
|
||||
private String confirmPassword;
|
||||
@Email(message = "Email format is not correct.")
|
||||
@NotBlank(message = "Email can not be empty.")
|
||||
private String email;
|
||||
private String nationality;
|
||||
private Boolean allowReceiveMessage;
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package com.northtecom.visatrack.api.controller.vo;
|
||||
|
||||
import com.northtecom.visatrack.api.data.entity.User;
|
||||
import com.northtecom.visatrack.api.service.enums.UserStatus;
|
||||
import lombok.Data;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Created with IntelliJ IDEA.
|
||||
*
|
||||
* @Author: XieYang
|
||||
* @Date: 2022/10/03/20:02
|
||||
* @Description:
|
||||
*/
|
||||
@Data
|
||||
public class VisaTrackUserDetail implements UserDetails {
|
||||
|
||||
private User user;
|
||||
|
||||
public VisaTrackUserDetail(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return user.getId();
|
||||
}
|
||||
|
||||
|
||||
public String getSurname() {
|
||||
return user.getUserName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return this.user.getUserPassword();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return this.user.getUserEmail();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonLocked() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCredentialsNonExpired() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return this.user.getUserStatus() == UserStatus.ACTIVATED && this.user.getIsEmailVerified();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package com.northtecom.visatrack.api.data.repository;
|
||||
|
||||
import com.northtecom.visatrack.api.data.entity.Blog;
|
||||
import org.springframework.data.repository.PagingAndSortingRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Repository
|
||||
public interface BlogRepository extends PagingAndSortingRepository<Blog, Long> {
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package com.northtecom.visatrack.api.data.repository;
|
||||
|
||||
import com.northtecom.visatrack.api.data.entity.User;
|
||||
import org.springframework.data.repository.CrudRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public interface UserRepository extends CrudRepository<User, Long> {
|
||||
User findByUserNameEquals(String userName);
|
||||
|
||||
Optional<User> findByUserEmail(String userEmail);
|
||||
|
||||
Optional<User> findByUserName(String userName);
|
||||
|
||||
User findByUserNameEqualsAndUserPasswordEquals(String userName, String userPassword);
|
||||
|
||||
List<User> findByUserNameContaining(String username);
|
||||
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package com.northtecom.visatrack.api.service.impl;
|
||||
|
||||
import com.northtecom.visatrack.api.data.entity.Blog;
|
||||
import com.northtecom.visatrack.api.data.repository.BlogRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* Listing Service.
|
||||
* This Service process listing related.
|
||||
*
|
||||
* @author YuCheng Hu
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ContentService {
|
||||
|
||||
|
||||
private final BlogRepository blogRepository;
|
||||
|
||||
@Autowired
|
||||
public ContentService(BlogRepository blogRepository) {
|
||||
this.blogRepository = blogRepository;
|
||||
}
|
||||
|
||||
public Page<Blog> getNewBlog(Pageable pageable) {
|
||||
return blogRepository.findAll(pageable);
|
||||
}
|
||||
|
||||
public Blog getBlogById(Long blogId) {
|
||||
return blogRepository.findById(blogId).orElse(null);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package com.northtecom.visatrack.api.service.impl;
|
||||
|
||||
import com.northtecom.visatrack.api.base.util.EmailUtils;
|
||||
import com.northtecom.visatrack.api.data.entity.User;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Created with IntelliJ IDEA.
|
||||
*
|
||||
* @Author: XieYang
|
||||
* @Date: 2022/10/02/10:37
|
||||
* @Description:
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class EmailService {
|
||||
|
||||
private final TemplateService templateService;
|
||||
|
||||
|
||||
private final EmailUtils emailUtils;
|
||||
|
||||
@Autowired
|
||||
public EmailService(TemplateService templateService, EmailUtils emailUtils) {
|
||||
this.templateService = templateService;
|
||||
this.emailUtils = emailUtils;
|
||||
}
|
||||
|
||||
public void sendVerifiedEmailToUser(User user) {
|
||||
log.info("Send verified email to user: {}", user);
|
||||
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
map.put("SiteName", "UsVisaTrack");
|
||||
map.put("SiteHost", "www.usvisatrack.com");
|
||||
map.put("UserName", user.getUserName());
|
||||
map.put("ActiveUserId", user.getId());
|
||||
map.put("ActiveCode", user.getEmailVerifiedCode());
|
||||
|
||||
String htmlContent = this.templateService.createHtml("email/VerifiedEmail.html", map);
|
||||
|
||||
String subject = "UsVisaTrack Email Verification";
|
||||
|
||||
emailUtils.sendEmail(user.getUserEmail(), subject, htmlContent);
|
||||
}
|
||||
|
||||
public void sendWelcomeEmailToUser(User user) {
|
||||
log.info("Send welcome email to user: {}", user);
|
||||
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
map.put("SiteName", "UsVisaTrack");
|
||||
map.put("SiteHost", "www.usvisatrack.com");
|
||||
map.put("UserName", user.getUserName());
|
||||
map.put("ActiveUserId", user.getId());
|
||||
|
||||
String htmlContent = this.templateService.createHtml("email/Welcome.html", map);
|
||||
|
||||
String subject = "Welcome to UsVisaTrack";
|
||||
|
||||
emailUtils.sendEmail(user.getUserEmail(), subject, htmlContent);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package com.northtecom.visatrack.api.service.impl;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.thymeleaf.TemplateEngine;
|
||||
import org.thymeleaf.context.Context;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Created with IntelliJ IDEA.
|
||||
*
|
||||
* @Author: XieYang
|
||||
* @Date: 2022/10/01/16:53
|
||||
* @Description:
|
||||
*/
|
||||
@Slf4j
|
||||
@Component
|
||||
public class TemplateService {
|
||||
|
||||
|
||||
@Autowired
|
||||
TemplateEngine templateEngine;
|
||||
|
||||
public String createHtml(String templateName, Map<String, Object> map) {
|
||||
Context context = new Context();
|
||||
if (map.size() > 0) {
|
||||
context.setVariables(map);
|
||||
}
|
||||
String templateContent = templateEngine.process(templateName, context);
|
||||
log.info("template Content: {}", templateContent);
|
||||
return templateContent;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
package com.northtecom.visatrack.api.service.impl;
|
||||
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import com.northtecom.visatrack.api.base.exception.BaseException;
|
||||
import com.northtecom.visatrack.api.base.util.JwtUtil;
|
||||
import com.northtecom.visatrack.api.base.web.Status;
|
||||
import com.northtecom.visatrack.api.controller.vo.RegisterUserRequest;
|
||||
import com.northtecom.visatrack.api.controller.vo.VisaTrackUserDetail;
|
||||
import com.northtecom.visatrack.api.data.entity.User;
|
||||
import com.northtecom.visatrack.api.data.repository.UserRepository;
|
||||
import com.northtecom.visatrack.api.service.enums.UserStatus;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Listing Service.
|
||||
* This Service process listing related.
|
||||
*
|
||||
* @author YuCheng Hu
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class UserService implements UserDetailsService {
|
||||
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private EmailService emailService;
|
||||
|
||||
@Autowired
|
||||
private JwtUtil jwtUtil;
|
||||
|
||||
|
||||
/**
|
||||
* Search Database by userName.
|
||||
* If not in DB, insert to Register user.
|
||||
*
|
||||
* @param user
|
||||
* @return
|
||||
*/
|
||||
public User userRegister(User user) {
|
||||
if (ObjectUtils.isNotEmpty(user)) {
|
||||
user.setUserStatus(UserStatus.NEEDVERIFY);
|
||||
user.setDateRegistered(LocalDateTime.now());
|
||||
return userRepository.save(user);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public User userLogin(String userName, String userPassword) {
|
||||
return userRepository.findByUserNameEqualsAndUserPasswordEquals(userName, userPassword);
|
||||
}
|
||||
|
||||
public User findUserByUserName(String userName) {
|
||||
return userRepository.findByUserNameEquals(userName);
|
||||
}
|
||||
|
||||
public User registerUser(RegisterUserRequest registerUserRequest) {
|
||||
|
||||
if (checkUserNameIsExist(registerUserRequest.getUserName())) {
|
||||
throw new BaseException(Status.BAD_REQUEST, "User Name is already exist");
|
||||
}
|
||||
|
||||
if (checkEmailIsExist(registerUserRequest.getEmail())) {
|
||||
throw new BaseException(Status.BAD_REQUEST, "Email is already exist");
|
||||
}
|
||||
|
||||
User user = new User();
|
||||
user.setUserName(registerUserRequest.getUserName());
|
||||
user.setUserPassword(registerUserRequest.getPassword());
|
||||
user.setUserEmail(registerUserRequest.getEmail());
|
||||
user.setUserStatus(UserStatus.NEEDVERIFY);
|
||||
user.setDateRegistered(LocalDateTime.now());
|
||||
user.setIsEmailVerified(false);
|
||||
user.setEmailVerifiedCode(RandomUtil.randomString(18));
|
||||
User savedUser = userRepository.save(user);
|
||||
|
||||
emailService.sendVerifiedEmailToUser(savedUser);
|
||||
|
||||
return savedUser;
|
||||
}
|
||||
|
||||
private Boolean checkEmailIsExist(String email) {
|
||||
return userRepository.findByUserEmail(email).isPresent();
|
||||
}
|
||||
|
||||
private Boolean checkUserNameIsExist(String userName) {
|
||||
return userRepository.findByUserName(userName).isPresent();
|
||||
}
|
||||
|
||||
public void activeUser(Long userId, String verifiedCode) {
|
||||
User user = userRepository.findById(userId).orElseThrow(() -> new BaseException(Status.BAD_REQUEST, "User is " +
|
||||
"not exist"));
|
||||
|
||||
if (user.getIsEmailVerified()) {
|
||||
throw new BaseException(Status.BAD_REQUEST, "User is already verified");
|
||||
}
|
||||
|
||||
if (!StringUtils.hasText(verifiedCode) || !verifiedCode.equals(user.getEmailVerifiedCode())) {
|
||||
throw new BaseException(Status.BAD_REQUEST, "Verified Code is not correct");
|
||||
}
|
||||
user.setIsEmailVerified(true);
|
||||
user.setEmailVerifiedCode("");
|
||||
user.setUserStatus(UserStatus.ACTIVATED);
|
||||
User savedUser = userRepository.save(user);
|
||||
|
||||
emailService.sendWelcomeEmailToUser(savedUser);
|
||||
}
|
||||
|
||||
public boolean checkPasswordIsMatch(String userPassword, String password) {
|
||||
return userPassword.equals(password);
|
||||
}
|
||||
|
||||
private String generateToken(User user, Boolean rememberMe) {
|
||||
|
||||
VisaTrackUserDetail visaTrackUserDetail = new VisaTrackUserDetail(user);
|
||||
|
||||
return this.generateToken(visaTrackUserDetail, rememberMe);
|
||||
}
|
||||
|
||||
public String generateToken(VisaTrackUserDetail userDetail, Boolean rememberMe) {
|
||||
Map<String, Object> userClaims = new HashMap<String, Object>();
|
||||
userClaims.put("user_id", userDetail.getId());
|
||||
userClaims.put("login_id", userDetail.getUsername());
|
||||
userClaims.put("surname", userDetail.getSurname());
|
||||
userClaims.put("email", userDetail.getUsername());
|
||||
return this.jwtUtil.createJWT(rememberMe, userDetail.getId(), userDetail.getUsername(), Arrays.asList(),
|
||||
Arrays.asList(), userClaims);
|
||||
}
|
||||
|
||||
private String generateToken(Authentication authentication, Boolean rememberMe) {
|
||||
VisaTrackUserDetail userDetail = (VisaTrackUserDetail) authentication.getPrincipal();
|
||||
return this.generateToken(userDetail.getUser(), rememberMe);
|
||||
}
|
||||
|
||||
public User findUserByEmail(String userEmail) {
|
||||
return userRepository.findByUserEmail(userEmail).orElse(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
User user = userRepository.findByUserEmail(username).orElseThrow(() -> new UsernameNotFoundException("User " +
|
||||
"not found"));
|
||||
|
||||
if (user.getUserStatus() == UserStatus.NEEDVERIFY) {
|
||||
throw new BaseException(Status.BAD_REQUEST, "User is not verified");
|
||||
}
|
||||
|
||||
if (!user.getIsEmailVerified()) {
|
||||
throw new BaseException(Status.BAD_REQUEST, "User email is not verified");
|
||||
}
|
||||
|
||||
return new VisaTrackUserDetail(user);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue