|
|
|
@ -8,6 +8,9 @@ import com.unilife.mapper.UserMapper;
|
|
|
|
|
import com.unilife.model.dto.LoginDTO;
|
|
|
|
|
import com.unilife.model.dto.LoginEmailDTO;
|
|
|
|
|
import com.unilife.model.dto.RegisterDTO;
|
|
|
|
|
import com.unilife.model.dto.UpdateEmailDTO;
|
|
|
|
|
import com.unilife.model.dto.UpdatePasswordDTO;
|
|
|
|
|
import com.unilife.model.dto.UpdateProfileDTO;
|
|
|
|
|
import com.unilife.model.entity.User;
|
|
|
|
|
import com.unilife.model.vo.LoginVO;
|
|
|
|
|
import com.unilife.model.vo.RegisterVO;
|
|
|
|
@ -18,7 +21,9 @@ import com.unilife.utils.RegexUtils;
|
|
|
|
|
import jakarta.mail.MessagingException;
|
|
|
|
|
import jakarta.mail.internet.MimeMessage;
|
|
|
|
|
import jakarta.servlet.http.HttpServletRequest;
|
|
|
|
|
import lombok.Data;
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
|
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
|
|
|
@ -26,10 +31,13 @@ import org.springframework.mail.javamail.JavaMailSender;
|
|
|
|
|
import org.springframework.mail.javamail.MimeMessageHelper;
|
|
|
|
|
import org.springframework.stereotype.Component;
|
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
import org.springframework.web.multipart.MultipartFile;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import java.time.Duration;
|
|
|
|
|
import java.time.LocalDateTime;
|
|
|
|
|
import java.util.Date;
|
|
|
|
|
import java.util.HashMap;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
|
@ -69,7 +77,7 @@ public class UserServiceImpl implements UserService {
|
|
|
|
|
if(registerDTO.getPassword().length() < 6) {
|
|
|
|
|
return Result.error(400,"密码长度过短!");
|
|
|
|
|
}
|
|
|
|
|
User getuser = userMapper.FindByOnlyEmail(registerDTO.getEmail());
|
|
|
|
|
User getuser = userMapper.findByEmail(registerDTO.getEmail());
|
|
|
|
|
if(getuser != null) {
|
|
|
|
|
return Result.error(400,"用户已存在!");
|
|
|
|
|
}
|
|
|
|
@ -86,24 +94,36 @@ public class UserServiceImpl implements UserService {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Result login(LoginDTO loginDTO,HttpServletRequest request) {
|
|
|
|
|
User user = new User();
|
|
|
|
|
BeanUtil.copyProperties(loginDTO,user);//将登录的前端传来的消息拷贝给这个user
|
|
|
|
|
User getuser = userMapper.FindByEmail(user.getEmail(),user.getPassword());
|
|
|
|
|
if(getuser == null)
|
|
|
|
|
{
|
|
|
|
|
return Result.error(loginDTO,"用户不存在,登录失败!");
|
|
|
|
|
if(loginDTO==null|| StringUtils.isEmpty(loginDTO.getEmail())||StringUtils.isEmpty(loginDTO.getPassword())){
|
|
|
|
|
return Result.error(400,"邮箱或密码不能为空");
|
|
|
|
|
}
|
|
|
|
|
if(!user.getPassword().equals(getuser.getPassword()))
|
|
|
|
|
{
|
|
|
|
|
return Result.error(loginDTO,"密码错误,登录失败!");
|
|
|
|
|
|
|
|
|
|
User user = userMapper.findByEmail(loginDTO.getEmail());
|
|
|
|
|
if (user == null) {
|
|
|
|
|
return Result.error(400, "账号或密码错误");
|
|
|
|
|
}
|
|
|
|
|
String LastLogIpLocation = getuser.getLoginIp();
|
|
|
|
|
String IPAddress = ipLocationService.getClientIP(request);
|
|
|
|
|
String Location = ipLocationService.getIPLocation(IPAddress);
|
|
|
|
|
getuser.setLoginIp(Location);
|
|
|
|
|
userMapper.UpdateIPLocation(getuser.getEmail(), getuser.getLoginIp());
|
|
|
|
|
|
|
|
|
|
if (!loginDTO.getPassword().equals(user.getPassword())) {
|
|
|
|
|
return Result.error(400, "账号或密码错误");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (user.getStatus() != 1) {
|
|
|
|
|
return Result.error(403, "账号已被禁用,请联系管理员");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
String LastLogIpLocation = user.getLoginIp();
|
|
|
|
|
String currentIp = ipLocationService.getClientIP(request);
|
|
|
|
|
String ipLocation = ipLocationService.getIPLocation(currentIp);
|
|
|
|
|
user.setLoginIp(ipLocation);
|
|
|
|
|
user.setLoginTime(LocalDateTime.now());
|
|
|
|
|
userMapper.updateLoginInfo(user.getId(),ipLocation,new Date());
|
|
|
|
|
|
|
|
|
|
LoginVO loginVO = new LoginVO();
|
|
|
|
|
return Result.success(loginVO,"上次登录IP归属地为" + LastLogIpLocation);
|
|
|
|
|
BeanUtil.copyProperties(user,loginVO);
|
|
|
|
|
String message = StringUtils.isEmpty(LastLogIpLocation) ? "首次登录" : "上次登录IP归属地为" + LastLogIpLocation;
|
|
|
|
|
return Result.success(loginVO, message);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@ -177,39 +197,43 @@ public class UserServiceImpl implements UserService {
|
|
|
|
|
String email=loginEmailDTO.getEmail();
|
|
|
|
|
|
|
|
|
|
if(RegexUtils.isEmailInvalid(email)){
|
|
|
|
|
return Result.error(null,"请输入正确的邮箱");
|
|
|
|
|
return Result.error(400,"请输入正确的邮箱");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String cacheCode = stringRedisTemplate.opsForValue().get(RedisConstant.LOGIN_EMAIL_KEY + email);
|
|
|
|
|
if (cacheCode == null) {
|
|
|
|
|
return Result.error(null, "验证码已过期或未发送,请重新获取");
|
|
|
|
|
return Result.error(400, "验证码已过期或未发送,请重新获取");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 3. 校验验证码是否正确
|
|
|
|
|
String code = loginEmailDTO.getCode();
|
|
|
|
|
if (!cacheCode.equals(code)) {
|
|
|
|
|
return Result.error(null, "验证码错误");
|
|
|
|
|
return Result.error(400, "验证码错误");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 4. 验证通过,删除验证码
|
|
|
|
|
stringRedisTemplate.delete(RedisConstant.LOGIN_EMAIL_KEY + email);
|
|
|
|
|
|
|
|
|
|
// 5. 查询用户是否存在
|
|
|
|
|
User user=userMapper.getUserByEmail(email);
|
|
|
|
|
User user=userMapper.findByEmail(email);
|
|
|
|
|
if(user == null){
|
|
|
|
|
user = createUserWithEmail(email,request);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//6.生成登录凭证
|
|
|
|
|
//TODO
|
|
|
|
|
// 更新登录信息
|
|
|
|
|
String currentIp = ipLocationService.getClientIP(request);
|
|
|
|
|
String ipLocation = ipLocationService.getIPLocation(currentIp);
|
|
|
|
|
user.setLoginIp(ipLocation);
|
|
|
|
|
user.setLoginTime(LocalDateTime.now());
|
|
|
|
|
userMapper.updateLoginInfo(user.getId(), ipLocation, new Date());
|
|
|
|
|
|
|
|
|
|
String token = jwtUtil.generateToken(user.getId());
|
|
|
|
|
// 8. 返回用户信息和登录凭证
|
|
|
|
|
Map<String, Object> userInfo = new HashMap<>();
|
|
|
|
|
userInfo.put("token", token);
|
|
|
|
|
userInfo.put("user", user);
|
|
|
|
|
// 创建LoginVO对象,与普通登录保持一致的返回格式
|
|
|
|
|
LoginVO loginVO = new LoginVO();
|
|
|
|
|
BeanUtil.copyProperties(user, loginVO);
|
|
|
|
|
|
|
|
|
|
return Result.success(userInfo);
|
|
|
|
|
// 返回结果,不在这里生成token,由Controller统一处理
|
|
|
|
|
String message = "邮箱验证码登录成功";
|
|
|
|
|
return Result.success(loginVO, message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -243,4 +267,147 @@ public class UserServiceImpl implements UserService {
|
|
|
|
|
return user;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Result getUserProfile(Long userId) {
|
|
|
|
|
// 根据用户ID获取用户信息
|
|
|
|
|
User user = userMapper.getUserById(userId);
|
|
|
|
|
if (user == null) {
|
|
|
|
|
return Result.error(404, "用户不存在");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 出于安全考虑,不返回密码字段
|
|
|
|
|
user.setPassword(null);
|
|
|
|
|
|
|
|
|
|
return Result.success(user);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Result updateUserProfile(Long userId, UpdateProfileDTO profileDTO) {
|
|
|
|
|
// 检查用户是否存在
|
|
|
|
|
User user = userMapper.getUserById(userId);
|
|
|
|
|
if (user == null) {
|
|
|
|
|
return Result.error(404, "用户不存在");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 更新用户信息
|
|
|
|
|
user.setNickname(profileDTO.getNickname());
|
|
|
|
|
user.setBio(profileDTO.getBio());
|
|
|
|
|
user.setGender(profileDTO.getGender());
|
|
|
|
|
user.setDepartment(profileDTO.getDepartment());
|
|
|
|
|
user.setMajor(profileDTO.getMajor());
|
|
|
|
|
user.setGrade(profileDTO.getGrade());
|
|
|
|
|
|
|
|
|
|
// 保存更新
|
|
|
|
|
userMapper.updateUserProfile(user);
|
|
|
|
|
|
|
|
|
|
return Result.success(null, "个人资料更新成功");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Result updatePassword(Long userId, UpdatePasswordDTO passwordDTO) {
|
|
|
|
|
// 检查用户是否存在
|
|
|
|
|
User user = userMapper.getUserById(userId);
|
|
|
|
|
if (user == null) {
|
|
|
|
|
return Result.error(404, "用户不存在");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 验证验证码
|
|
|
|
|
String cacheCode = stringRedisTemplate.opsForValue().get(RedisConstant.LOGIN_EMAIL_KEY + user.getEmail());
|
|
|
|
|
if (cacheCode == null) {
|
|
|
|
|
return Result.error(400, "验证码已过期或未发送,请重新获取");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!cacheCode.equals(passwordDTO.getCode())) {
|
|
|
|
|
return Result.error(400, "验证码错误");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 验证通过,删除验证码
|
|
|
|
|
stringRedisTemplate.delete(RedisConstant.LOGIN_EMAIL_KEY + user.getEmail());
|
|
|
|
|
|
|
|
|
|
// 更新密码
|
|
|
|
|
userMapper.updatePassword(userId, passwordDTO.getNewPassword());
|
|
|
|
|
|
|
|
|
|
return Result.success(null, "密码修改成功");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Result updateAvatar(Long userId, MultipartFile file) {
|
|
|
|
|
// 检查用户是否存在
|
|
|
|
|
User user = userMapper.getUserById(userId);
|
|
|
|
|
if (user == null) {
|
|
|
|
|
return Result.error(404, "用户不存在");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查文件是否为空
|
|
|
|
|
if (file.isEmpty()) {
|
|
|
|
|
return Result.error(400, "上传文件不能为空");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查文件类型
|
|
|
|
|
String contentType = file.getContentType();
|
|
|
|
|
if (contentType == null || !contentType.startsWith("image/")) {
|
|
|
|
|
return Result.error(400, "只能上传图片文件");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
// 生成文件名
|
|
|
|
|
String originalFilename = file.getOriginalFilename();
|
|
|
|
|
String suffix = originalFilename != null ? originalFilename.substring(originalFilename.lastIndexOf(".")) : ".jpg";
|
|
|
|
|
String filename = "avatar_" + userId + "_" + System.currentTimeMillis() + suffix;
|
|
|
|
|
|
|
|
|
|
// TODO: 实际项目中应该将文件保存到云存储或服务器指定目录
|
|
|
|
|
// 这里简化处理,假设保存成功并返回URL
|
|
|
|
|
String avatarUrl = "https://example.com/avatars/" + filename;
|
|
|
|
|
|
|
|
|
|
// 更新用户头像URL
|
|
|
|
|
userMapper.updateAvatar(userId, avatarUrl);
|
|
|
|
|
|
|
|
|
|
Map<String, String> data = new HashMap<>();
|
|
|
|
|
data.put("avatar", avatarUrl);
|
|
|
|
|
|
|
|
|
|
return Result.success(data, "头像上传成功");
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("头像上传失败", e);
|
|
|
|
|
return Result.error(500, "头像上传失败");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Result updateEmail(Long userId, UpdateEmailDTO emailDTO) {
|
|
|
|
|
// 检查用户是否存在
|
|
|
|
|
User user = userMapper.getUserById(userId);
|
|
|
|
|
if (user == null) {
|
|
|
|
|
return Result.error(404, "用户不存在");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查邮箱格式
|
|
|
|
|
String email = emailDTO.getEmail();
|
|
|
|
|
if (RegexUtils.isEmailInvalid(email)) {
|
|
|
|
|
return Result.error(400, "邮箱格式不正确");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 检查邮箱是否已被使用
|
|
|
|
|
User existingUser = userMapper.findByEmail(email);
|
|
|
|
|
if (existingUser != null && !existingUser.getId().equals(userId)) {
|
|
|
|
|
return Result.error(400, "该邮箱已被其他用户使用");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 验证验证码
|
|
|
|
|
String cacheCode = stringRedisTemplate.opsForValue().get(RedisConstant.LOGIN_EMAIL_KEY + email);
|
|
|
|
|
if (cacheCode == null) {
|
|
|
|
|
return Result.error(400, "验证码已过期或未发送,请重新获取");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!cacheCode.equals(emailDTO.getCode())) {
|
|
|
|
|
return Result.error(400, "验证码错误");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 验证通过,删除验证码
|
|
|
|
|
stringRedisTemplate.delete(RedisConstant.LOGIN_EMAIL_KEY + email);
|
|
|
|
|
|
|
|
|
|
// 更新邮箱
|
|
|
|
|
userMapper.updateEmail(userId, email);
|
|
|
|
|
|
|
|
|
|
return Result.success(null, "邮箱更新成功");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|