Compare commits

..

5 Commits

Author SHA1 Message Date
ec03919c78 Merge remote-tracking branch 'origin/main_app权限适配' into dyf-app
# Conflicts:
#	fys-system/src/main/java/com/fuyuanshen/modules/security/security/app/AppTokenProvider.java
2025-06-25 08:40:02 +08:00
c61f2a7265 app登录响应状态码修改 2025-06-24 18:35:30 +08:00
ae88cc16cc 修改app用户信息 2025-06-24 17:43:45 +08:00
a7bb1d8e84 app端忘记密码redis缓存key字段优化 2025-06-24 13:58:00 +08:00
1f7f4bf537 app端忘记密码功能实现 2025-06-24 13:38:36 +08:00
12 changed files with 260 additions and 37 deletions

View File

@ -0,0 +1,8 @@
package com.fuyuanshen.constants;
public class RedisConstants {
public static final String APP_FORGOT_PASSWORD_SMS_TOKEN = "app_sms_forgotPassword:";
public static final String APP_REGISTER_SMS_TOKEN = "app_sms_register:";
}

View File

@ -146,7 +146,7 @@ public class AuthController {
@Log("app用户登录")
@ApiOperation("app用户登录")
@AnonymousPostMapping(value = "/app/login")
public ResponseEntity<Object> APPLogin(@Validated @RequestBody AppAuthUserDto authUser, HttpServletRequest request) throws Exception {
public ResponseVO<Object> APPLogin(@Validated @RequestBody AppAuthUserDto authUser, HttpServletRequest request) throws Exception {
// 1. 构建查询参数
APPUserQuery appUserQuery = new APPUserQuery();
@ -196,7 +196,7 @@ public class AuthController {
onlineUserService.saveAppOnlineUser(jwtUser, token, request);
// 11. 返回结果
return ResponseEntity.ok(authInfo);
return ResponseVO.success(authInfo);
}

View File

@ -133,4 +133,8 @@ public class APPUser extends BaseEntity implements Serializable {
@ApiModelProperty(hidden = true)
private Integer userType;
/**
* 地区
*/
private String region;
}

View File

@ -0,0 +1,27 @@
package com.fuyuanshen.modules.system.domain.dto.app;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* @author: 默苍璃
* @date: 2025-06-1818:36
*/
@Data
public class APPForgotPasswordDTO {
@NotBlank(message = "手机号不能为空")
@ApiModelProperty(value = "手机号APP登录")
private String phoneNumber;
@NotBlank(message = "密码不能为空")
@ApiModelProperty(value = "密码")
private String password;
@ApiModelProperty(value = "验证码")
@NotBlank(message = "验证码不能为空")
private String verificationCode;
}

View File

@ -0,0 +1,32 @@
package com.fuyuanshen.modules.system.domain.dto.app;
import com.fuyuanshen.modules.system.domain.app.APPUser;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;
import javax.validation.constraints.NotBlank;
/**
* @author: 默苍璃
* @date: 2025-06-1818:36
*/
@Data
public class APPUpdateUserDTO {
@ApiModelProperty(value = "ID", hidden = true)
private Long id;
@ApiModelProperty(value = "用户昵称")
private String nickName;
@ApiModelProperty(value = "地区")
private String region;
@ApiModelProperty(value = "用户性别")
private String gender;
@ApiModelProperty(value = "头像图片")
private MultipartFile file;
}

View File

@ -0,0 +1,25 @@
package com.fuyuanshen.modules.system.domain.vo;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author: 默苍璃
* @date: 2025-06-1211:34
*/
@Data
public class APPUserVo {
@ApiModelProperty(value = "ID")
private Long id;
@ApiModelProperty(value = "用户昵称")
private String nickName;
@ApiModelProperty(value = "用户性别")
private String gender;
@ApiModelProperty(value = "电话号码")
private Long phone;
}

View File

@ -15,54 +15,30 @@
*/
package com.fuyuanshen.modules.system.rest.app;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fuyuanshen.annotation.Log;
import com.fuyuanshen.annotation.rest.AnonymousPostMapping;
import com.fuyuanshen.exception.BadRequestException;
import com.fuyuanshen.modules.security.service.UserCacheManager;
import com.fuyuanshen.modules.security.service.dto.JwtUserDto;
import com.fuyuanshen.modules.system.constant.UserConstants;
import com.fuyuanshen.modules.system.domain.Dept;
import com.fuyuanshen.modules.system.domain.Role;
import com.fuyuanshen.modules.system.domain.User;
import com.fuyuanshen.modules.system.domain.app.APPUser;
import com.fuyuanshen.modules.system.domain.dto.UserPassVo;
import com.fuyuanshen.modules.system.domain.dto.DeviceForm;
import com.fuyuanshen.modules.system.domain.dto.UserQueryCriteria;
import com.fuyuanshen.modules.system.domain.dto.app.APPForgotPasswordDTO;
import com.fuyuanshen.modules.system.domain.dto.app.APPUpdateUserDTO;
import com.fuyuanshen.modules.system.domain.dto.app.APPUserDTO;
import com.fuyuanshen.modules.system.domain.query.APPUserQuery;
import com.fuyuanshen.modules.system.domain.vo.ConsumerVo;
import com.fuyuanshen.modules.system.domain.vo.APPUserVo;
import com.fuyuanshen.modules.system.enums.UserType;
import com.fuyuanshen.modules.system.mapper.UserMapper;
import com.fuyuanshen.modules.system.service.*;
import com.fuyuanshen.modules.system.service.app.APPUserService;
import com.fuyuanshen.modules.utils.ResponseVO;
import com.fuyuanshen.utils.PageResult;
import com.fuyuanshen.utils.SecurityUtils;
import com.fuyuanshen.utils.StringUtils;
import com.fuyuanshen.utils.enums.CodeEnum;
import io.netty.util.internal.StringUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.formula.functions.T;
import org.apache.ibatis.annotations.Param;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author Zheng Jie
@ -91,10 +67,17 @@ public class APPUserController {
@ApiOperation("用户中心")
@GetMapping(value = "/get")
@PreAuthorize("@el.check('appUser:get')")
public ResponseVO<APPUser> getAPPUser(UserQueryCriteria criteria) {
public ResponseVO<APPUserVo> getAPPUser() {
String userName = SecurityUtils.getCurrentUsername();
return null;
// return ResponseVO.success(appUserService.getAPPUser(criteria));
APPUser appUser = appUserService.getLoginData(userName);
APPUserVo appUserVo = new APPUserVo();
appUserVo.setId(appUser.getId());
appUserVo.setNickName(appUser.getNickName());
appUserVo.setGender(appUser.getGender());
appUserVo.setPhone(appUser.getPhone());
return ResponseVO.success(appUserVo);
}
@Log("app用户注册")
@ -103,21 +86,52 @@ public class APPUserController {
public ResponseVO<String> APPRegister(@Validated @RequestBody APPUserDTO user) throws Exception {
//暫定0000
if (user.getVerificationCode() == null || !"0000".equals(user.getVerificationCode())) {
if (!"0000".equals(user.getVerificationCode())) {
throw new BadRequestException("验证码错误");
}
appUserService.addUser(user);
return ResponseVO.success("success");
}
@Log("发送用户注册验证码")
@ApiOperation("发送用户注册验证码")
@AnonymousPostMapping(value = "/sendRegisterSms")
public ResponseVO<String> sendRegisterSms(@Param("phoneNumber") String phoneNumber) throws Exception {
// appUserService.sendSms(phoneNumber);
return ResponseVO.success("success");
}
@Log("修改APP用户")
@ApiOperation("修改APP用户")
@PutMapping
@PreAuthorize("@el.check('appUser:edit')")
public ResponseVO<String> updateUser(@Validated(APPUser.Update.class) @RequestBody APPUser appUser) throws Exception {
appUserService.updateById(appUser);
public ResponseVO<String> updateUser(@Validated @ModelAttribute APPUpdateUserDTO appUser) throws Exception {
Long userId = SecurityUtils.getCurrentUserId();
if(!userId.equals(appUser.getId())){
throw new BadRequestException("不能修改他人资料");
}
appUserService.updateUser(appUser);
return ResponseVO.success("success");
}
@Log("忘记密码")
@ApiOperation("忘记密码")
@AnonymousPostMapping(value = "/forgotPassword")
public ResponseVO<String> forgotPassword(@RequestBody APPForgotPasswordDTO appForgotPasswordDTO) throws Exception {
if (!"0000".equals(appForgotPasswordDTO.getVerificationCode())) {
throw new BadRequestException("验证码错误");
}
appUserService.forgotPassword(appForgotPasswordDTO);
return ResponseVO.success("success");
}
@Log("发送忘记密码验证码")
@ApiOperation("发送忘记密码验证码")
@AnonymousPostMapping(value = "/sendForgotPasswordSms")
public ResponseVO<String> sendForgotPasswordSms(@Param("phoneNumber") String phoneNumber) throws Exception {
// appUserService.sendSms(phoneNumber);
return ResponseVO.success("success");
}
}

View File

@ -21,6 +21,8 @@ import com.fuyuanshen.modules.security.service.dto.app.AppRoleDto;
import com.fuyuanshen.modules.system.domain.Role;
import com.fuyuanshen.modules.system.domain.app.APPUser;
import com.fuyuanshen.modules.system.domain.dto.UserQueryCriteria;
import com.fuyuanshen.modules.system.domain.dto.app.APPForgotPasswordDTO;
import com.fuyuanshen.modules.system.domain.dto.app.APPUpdateUserDTO;
import com.fuyuanshen.modules.system.domain.dto.app.APPUserDTO;
import com.fuyuanshen.modules.utils.ResponseVO;
import com.fuyuanshen.utils.PageResult;
@ -54,4 +56,10 @@ public interface APPUserService extends IService<APPUser> {
ResponseVO<Object> addUser(APPUserDTO user);
Integer selectRoleByUserLevel(Set<Role> roles);
void forgotPassword(APPForgotPasswordDTO appForgotPasswordDTO);
void sendSms(String phoneNumber);
void updateUser(APPUpdateUserDTO appUser);
}

View File

@ -15,24 +15,35 @@
*/
package com.fuyuanshen.modules.system.service.impl.app;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.crypto.digest.MD5;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fuyuanshen.constants.DeviceConstants;
import com.fuyuanshen.exception.BadRequestException;
import com.fuyuanshen.modules.system.domain.Role;
import com.fuyuanshen.modules.system.domain.app.APPUser;
import com.fuyuanshen.modules.system.domain.dto.UserQueryCriteria;
import com.fuyuanshen.modules.system.domain.dto.app.APPForgotPasswordDTO;
import com.fuyuanshen.modules.system.domain.dto.app.APPUpdateUserDTO;
import com.fuyuanshen.modules.system.domain.dto.app.APPUserDTO;
import com.fuyuanshen.modules.system.mapper.app.APPUserMapper;
import com.fuyuanshen.modules.system.service.app.APPUserService;
import com.fuyuanshen.modules.utils.ResponseVO;
import com.fuyuanshen.utils.*;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.Set;
import static com.fuyuanshen.constants.RedisConstants.*;
/**
* @author Zheng Jie
* @date 2018-11-23
@ -45,6 +56,19 @@ public class APPUserServiceImpl extends ServiceImpl<APPUserMapper, APPUser> impl
private final PasswordEncoder passwordEncoder;
@Autowired
private final RedisUtils redisUtils;
@Value("${file.app_avatar.pic}")
private String filePath;
@Value("${file.app_avatar.ip}")
private String ip;
/**
* 文件访问路径前缀
*/
public static final String FILE_ACCESS_PREFIX = "images";
public static final String FILE_AVATAR_PREFIX = "avatar";
/**
* 查询APP/小程序用户
*
@ -73,6 +97,14 @@ public class APPUserServiceImpl extends ServiceImpl<APPUserMapper, APPUser> impl
if (appUserMapper.getByUsername(username) != null) {
throw new BadRequestException("该手机号已被注册");
}
/* Object verificationCode = redisUtils.get(APP_REGISTER_SMS_TOKEN + username);
if (verificationCode == null) {
throw new BadRequestException("验证码已过期");
}
if(!user.getVerificationCode().equals(verificationCode.toString())){
throw new BadRequestException("验证码错误");
}*/
APPUser appUser = new APPUser();
appUser.setUsername(user.getPhoneNumber());
@ -96,4 +128,67 @@ public class APPUserServiceImpl extends ServiceImpl<APPUserMapper, APPUser> impl
return 0;
}
@Override
public void forgotPassword(APPForgotPasswordDTO appForgotPasswordDTO) {
String phoneNumber = appForgotPasswordDTO.getPhoneNumber();
APPUser appUser = appUserMapper.appFindByUsername(phoneNumber);
if (appUser == null) {
throw new BadRequestException("手机号不存在");
}
/*Object verificationCode = redisUtils.get(APP_FORGOT_PASSWORD_SMS_TOKEN + phoneNumber);
if (verificationCode == null) {
throw new BadRequestException("验证码已过期");
}
if(!appForgotPasswordDTO.getVerificationCode().equals(verificationCode.toString())){
throw new BadRequestException("验证码错误");
}*/
appUser.setPassword(appForgotPasswordDTO.getPassword());
appUserMapper.updateById(appUser);
}
@Override
public void sendSms(String phoneNumber) {
if (appUserMapper.appFindByUsername(phoneNumber) == null) {
throw new BadRequestException("手机号不存在");
}
// todo 发送验证码
redisUtils.set(APP_FORGOT_PASSWORD_SMS_TOKEN + phoneNumber, RandomUtil.randomNumbers(4), 5 * 60);
}
@Override
public void updateUser(APPUpdateUserDTO appUser) {
APPUser updUser= new APPUser();
updUser.setId(appUser.getId());
updUser.setNickName(appUser.getNickName());
try {
updUser.setAvatarPath(saveUserAvatarImage(appUser.getFile()));
}catch (IOException e){
throw new BadRequestException("上传头像失败");
}
updUser.setRegion(appUser.getRegion());
updUser.setGender(appUser.getGender());
appUserMapper.updateById(updUser);
}
private String saveUserAvatarImage(MultipartFile file) throws IOException {
if (file == null || file.isEmpty()) {
return null;
}
String originalFileName = file.getOriginalFilename();
String fileExtension = originalFileName.substring(originalFileName.lastIndexOf(".") + 1);
String newFileName = "PS_" + RandomUtil.randomNumbers(8) + "." + fileExtension;
File newFile = new File(filePath + FILE_AVATAR_PREFIX + File.separator + newFileName);
if (!newFile.getParentFile().exists()) {
newFile.getParentFile().mkdirs();
}
file.transferTo(newFile);
return ip + DeviceConstants.FILE_ACCESS_PREFIX + "/" + FILE_AVATAR_PREFIX + "/" + newFileName;
}
}

View File

@ -141,6 +141,10 @@ file:
device:
pic: C:\eladmin\file\ #设备图片存储路径
ip: http://fuyuanshen.com:81/ #服务器地址
app_avatar:
pic: C:\eladmin\file\ #设备图片存储路径
#ip: http://fuyuanshen.com:81/ #服务器地址
ip: https://fuyuanshen.com/ #服务器地址
logging:
level:

View File

@ -151,3 +151,7 @@ file:
pic: /home/eladmin/file/ #设备图片存储路径
#ip: http://fuyuanshen.com:81/ #服务器地址
ip: https://fuyuanshen.com/ #服务器地址
app_avatar:
pic: /home/eladmin/app_avatar/ #设备图片存储路径
#ip: http://fuyuanshen.com:81/ #服务器地址
ip: https://fuyuanshen.com/ #服务器地址

View File

@ -43,6 +43,8 @@ spring:
multipart:
max-file-size: 5MB # 设置单个上传文件的最大大小为10MB
max-request-size: 5MB
jackson:
default-property-inclusion: non_null
# pid:
# file: /自行指定位置/eladmin.pid