update m2pool 新增注销账号功能

This commit is contained in:
yyb
2025-12-30 09:53:41 +08:00
parent b210b114d5
commit 1e7c2099bf
29 changed files with 418 additions and 43 deletions

View File

@@ -92,4 +92,12 @@ public interface RemoteUserService {
@GetMapping("/user/getCSList") @GetMapping("/user/getCSList")
public R<List<SysUser>> getCSList(); public R<List<SysUser>> getCSList();
/**
* 关闭
*
* @return 结果
*/
@PostMapping("/user/closeAccount")
R<Boolean> closeAccount(@RequestBody SysUser sysUser);
} }

View File

@@ -0,0 +1,32 @@
package com.m2pool.system.api.entity;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotBlank;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class CloseAccountVo {
@Email
private String userEmail;
/**
* 谷歌验证器验证码
*/
@ApiModelProperty(value = "谷歌验证码",required = true)
public long gCode;
/**
* 邮箱验证码
*/
@NotBlank
@ApiModelProperty(value = "邮箱验证码",required = true)
public String eCode;
}

View File

@@ -0,0 +1,31 @@
package com.m2pool.system.api.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.Map;
/**
* @Description 用户矿机在离线的数量
* @Date 2024/6/12 16:13
* @Author dy
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class EmailTemplateEntity implements Serializable {
/** 邮箱 */
private String email;
/** 主题 */
private String subject;
/** 模版名称 */
private String templateName;
/** 填充到模版的数据 */
private Map<String,Object> data;
}

View File

@@ -69,6 +69,11 @@ public class RemoteUserFallbackFactory implements FallbackFactory<RemoteUserServ
return R.fail("客服列表获取失败:" + cause.getMessage()); return R.fail("客服列表获取失败:" + cause.getMessage());
} }
@Override
public R<Boolean> closeAccount(SysUser sysUser) {
return R.fail("注销用户失败:" + cause.getMessage());
}
}; };
} }
} }

View File

@@ -12,7 +12,6 @@
<artifactId>m2pool-auth</artifactId> <artifactId>m2pool-auth</artifactId>
<description>认证模块:登录认证、权限鉴定等</description> <description>认证模块:登录认证、权限鉴定等</description>
<dependencies> <dependencies>
<!-- SpringCloud Alibaba Nacos --> <!-- SpringCloud Alibaba Nacos -->
@@ -71,6 +70,19 @@
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>com.m2pool</groupId>
<artifactId>common-swagger</artifactId>
</dependency>
<!-- Swagger UI -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${swagger.fox.version}</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@@ -1,10 +1,14 @@
package com.m2pool.auth; package com.m2pool.auth;
import com.m2pool.common.security.annotation.EnableCustomConfig;
import com.m2pool.common.security.annotation.EnableM2PoolFeignClients; import com.m2pool.common.security.annotation.EnableM2PoolFeignClients;
import com.m2pool.common.swagger.annotation.EnableCustomSwagger2;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@EnableCustomConfig
@EnableCustomSwagger2
@EnableM2PoolFeignClients @EnableM2PoolFeignClients
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) @SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class M2PoolAuthApplication{ public class M2PoolAuthApplication{

View File

@@ -10,6 +10,7 @@ import com.m2pool.common.security.annotation.RequiresLogin;
import com.m2pool.common.security.auth.AuthUtil; import com.m2pool.common.security.auth.AuthUtil;
import com.m2pool.common.security.service.TokenService; import com.m2pool.common.security.service.TokenService;
import com.m2pool.common.security.utils.SecurityUtils; import com.m2pool.common.security.utils.SecurityUtils;
import com.m2pool.system.api.entity.CloseAccountVo;
import com.m2pool.system.api.entity.EmailTemplateEntity; import com.m2pool.system.api.entity.EmailTemplateEntity;
import com.m2pool.system.api.model.LoginUser; import com.m2pool.system.api.model.LoginUser;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
@@ -86,6 +87,10 @@ public class TokenController {
return maliService.resetPwdCode(entity); return maliService.resetPwdCode(entity);
} }
@PostMapping("updatePwdCode") @PostMapping("updatePwdCode")
public R<?> updatePwdCode() public R<?> updatePwdCode()
{ {
@@ -93,6 +98,30 @@ public class TokenController {
} }
/**
* 关闭注销账户
* @param closeAccountVo
* @return
*/
@PostMapping("/closeAccount")
@RequiresLogin
@ApiOperation(value = "用户注销")
public R<?> closeAccount(@RequestBody @Valid CloseAccountVo closeAccountVo){
return sysLoginService.closeAccount(closeAccountVo);
}
/**
* 发送注销账户邮件
* @param emailCodeVo
* @return
*/
@PostMapping("/sendCloseAccount")
@ApiOperation(value = "发送注销用户邮箱验证码")
public R<?> sendCloseAccount(@RequestBody @Valid GetLoginEmailCodeEntity emailCodeVo){
return maliService.sendCloseAccount(emailCodeVo);
}
@GetMapping("hello") @GetMapping("hello")
public R<?> hello() public R<?> hello()
{ {

View File

@@ -4,6 +4,9 @@ import com.m2pool.auth.entity.GetEmailCodeEntity;
import com.m2pool.auth.entity.GetLoginEmailCodeEntity; import com.m2pool.auth.entity.GetLoginEmailCodeEntity;
import com.m2pool.common.core.Result.R; import com.m2pool.common.core.Result.R;
import com.m2pool.system.api.entity.EmailTemplateEntity; import com.m2pool.system.api.entity.EmailTemplateEntity;
import org.springframework.web.bind.annotation.RequestBody;
import javax.validation.Valid;
/** /**
* @Description TODO * @Description TODO
@@ -73,4 +76,19 @@ public interface MailService {
public R<?> updatePwdCode(); public R<?> updatePwdCode();
/**
* 账号注销验证码
* @param emailCodeVo
* @return
*/
R<?> sendCloseAccount(GetLoginEmailCodeEntity emailCodeVo);
/**
* 账号注销邮箱验证码 消息格式设置
* @param to
* @param code
*/
void sendCloseAccountMailMessage(String to, String code);
} }

View File

@@ -1,7 +1,6 @@
package com.m2pool.auth.service; package com.m2pool.auth.service;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.shaded.org.checkerframework.checker.units.qual.A;
import com.m2pool.auth.entity.*; import com.m2pool.auth.entity.*;
import com.m2pool.common.core.RedisTransKey; import com.m2pool.common.core.RedisTransKey;
import com.m2pool.common.core.Result.R; import com.m2pool.common.core.Result.R;
@@ -12,6 +11,7 @@ import com.m2pool.common.core.enums.UserStatus;
import com.m2pool.common.core.exception.ServiceException; import com.m2pool.common.core.exception.ServiceException;
import com.m2pool.common.core.text.Convert; import com.m2pool.common.core.text.Convert;
import com.m2pool.common.core.utils.DateUtils; import com.m2pool.common.core.utils.DateUtils;
import com.m2pool.common.core.utils.GoogleAuthenticator;
import com.m2pool.common.core.utils.ServletUtils; import com.m2pool.common.core.utils.ServletUtils;
import com.m2pool.common.core.utils.StringUtils; import com.m2pool.common.core.utils.StringUtils;
import com.m2pool.common.core.utils.ip.IpUtils; import com.m2pool.common.core.utils.ip.IpUtils;
@@ -22,16 +22,14 @@ import com.m2pool.common.security.service.TokenService;
import com.m2pool.common.security.utils.SecurityUtils; import com.m2pool.common.security.utils.SecurityUtils;
import com.m2pool.system.api.RemoteLogService; import com.m2pool.system.api.RemoteLogService;
import com.m2pool.system.api.RemoteUserService; import com.m2pool.system.api.RemoteUserService;
import com.m2pool.system.api.entity.CloseAccountVo;
import com.m2pool.system.api.entity.SysLogininfor; import com.m2pool.system.api.entity.SysLogininfor;
import com.m2pool.system.api.entity.SysUser; import com.m2pool.system.api.entity.SysUser;
import com.m2pool.system.api.model.LoginUser; import com.m2pool.system.api.model.LoginUser;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.annotations.Update;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestBody;
import javax.validation.Valid;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -563,4 +561,53 @@ public class SysLoginService {
} }
public R<?> closeAccount(CloseAccountVo closeAccountVo){
String email = closeAccountVo.getUserEmail();
String emailCode = closeAccountVo.getECode();
// 用户名或密码为空 错误
if (StringUtils.isBlank(email))
{
recordLogininfor(email, Constants.LOGIN_FAIL, "邮箱必须填写");
throw new ServiceException("邮箱必须填写");
}
if(!StringUtils.isBlank(email)){
if(!email.matches(EMAIL_REGEX)){
throw new ServiceException("邮箱格式错误");
}
}else {
throw new ServiceException("邮箱为必填项");
}
String closeAccountKey = RedisTransKey.getCloseAccountKey(email);
//校验谷歌验证码和邮箱验证码
if(redisService.hasKey(closeAccountKey)){
Object o = redisService.getCacheObject(closeAccountKey);//user:emailCode:email
EmailCodeEntity emailCodeEntity = JSON.parseObject(JSON.toJSONString(o), EmailCodeEntity.class);
//验证验证码
if(emailCode.equals(emailCodeEntity.getEmailCode())){
//不做处理 进入后续登录流程
}else {
throw new ServiceException("验证码错误");
}
}else {
throw new ServiceException("验证码未获取或已过期,请重新获取验证码");
}
R<Boolean> booleanR1 = remoteUserService.checkGoogleCode(closeAccountVo.getGCode(), SecurityConstants.INNER);
if(!booleanR1.getData()){
throw new ServiceException("谷歌验证码错误");
}
R<LoginUser> userInfo = remoteUserService.getUserInfo(SecurityUtils.getUsername(), SecurityConstants.INNER);
if (R.FAIL == userInfo.getCode()) {
throw new ServiceException("服务器请求失败请稍后再试");
}
SysUser sysUser = userInfo.getData().getSysUser();
sysUser.setDelFlag("2");
R<Boolean> booleanR = remoteUserService.closeAccount(sysUser);
if (R.FAIL == booleanR.getCode()) {
throw new ServiceException("服务器请求失败请稍后再试");
}
return booleanR;
}
} }

View File

@@ -556,4 +556,61 @@ public class MaliServiceImpl implements MailService {
} }
@Override
public R<?> sendCloseAccount(GetLoginEmailCodeEntity emailCodeVo) {
String email = SecurityUtils.getUsername();
if(StringUtils.isBlank(email)){
return R.fail("token解析失败");
}
//通过邮箱获取用户
R<LoginUser> userByEmail = remoteUserService.getUserInfo(email, SecurityConstants.INNER);
if(StringUtils.isNull(userByEmail.getData())){
return R.fail("token解析异常");
}
//判断用户是不是恶意刷邮箱,在规定时间内进行的
String closeAccountKey = RedisTransKey.getCloseAccountKey(email);
if (redisService.hasKey(closeAccountKey)) {
Object o = redisService.getCacheObject(closeAccountKey);//user:updatePwdCode:email
EmailCodeEntity emailCodeEntity = JSON.parseObject(JSON.toJSONString(o), EmailCodeEntity.class);
if (emailCodeEntity.getTimes() >= 5) {
return R.fail("请求次数过多请10分钟后再试");
} else {
//这里就不去判断两次绑定的邮箱是不是一样的了,不排除第一次输入错了邮箱的情况
String emailCode = CodeUtils.creatCode(6);
emailCodeEntity.setEmailCode(emailCode);
emailCodeEntity.setTimes(emailCodeEntity.getTimes() + 1);
long overTime = redisService.getExpire(closeAccountKey);
redisService.setCacheObject(closeAccountKey, emailCodeEntity, overTime, TimeUnit.SECONDS
);
sendCloseAccountMailMessage(email, emailCodeEntity.getEmailCode());
}
} else {
String emailCode = CodeUtils.creatCode(6);
// 最多允许用户在10分钟内发送2次的邮箱验证
// 0s倒计时后用户可以再发送验证码但是间隔在10分钟内只能再发送1次
EmailCodeEntity emailCodeEntity = new EmailCodeEntity(
email, emailCode,1
);
//设置失效时间10分钟
redisService.setCacheObject(closeAccountKey, emailCodeEntity,
10L, TimeUnit.MINUTES
);
sendCloseAccountMailMessage(email, emailCodeEntity.getEmailCode());
}
return R.success("请求成功,修改密码验证码已经发送至用户邮箱");
}
@Override
public void sendCloseAccountMailMessage(String to, String code) {
Map<String, Object> content = new HashMap<>();
content.put("code",code);
content.put("text","You are logging out of the user account. If this is not done by you, please ignore it. The verification code is valid for 10 minutes.");
EmailTemplateEntity entity = new EmailTemplateEntity(to,"Change password, email verification code","emailCode-en",content);
sendHtmlMailMessage(entity);
}
} }

View File

@@ -3,6 +3,9 @@ server:
# Spring # Spring
spring: spring:
mvc:
pathmatch:
matching-strategy: ant-path-matcher
#邮箱基本配置 #邮箱基本配置
mail: mail:
# 配置在limit_time内用户可以发送limit次验证码 # 配置在limit_time内用户可以发送limit次验证码

View File

@@ -15,6 +15,7 @@ public class RedisTransKey {
public static final String RedisAddCreditEmailCodeName="addCreditEmailCode"; public static final String RedisAddCreditEmailCodeName="addCreditEmailCode";
public static final String RedisResetPwdCodeName="restPwdCode"; public static final String RedisResetPwdCodeName="restPwdCode";
public static final String RedisUpdatePwdCodeName="updatePwdCode"; public static final String RedisUpdatePwdCodeName="updatePwdCode";
public static final String RedisCloseAccountName="closeAccount";
public static String setEmailKey(String key){ public static String setEmailKey(String key){
return RedisNameSpace+":"+RedisEmailCodeName+":"+key; return RedisNameSpace+":"+RedisEmailCodeName+":"+key;
@@ -39,6 +40,10 @@ public class RedisTransKey {
return RedisNameSpace+":"+RedisAddCreditEmailCodeName+":"+key; return RedisNameSpace+":"+RedisAddCreditEmailCodeName+":"+key;
} }
public static String setCloseAccountKey(String key){
return RedisNameSpace+":"+RedisCloseAccountName+":"+key;
}
public static String getEmailKey(String key){return setEmailKey(key);} public static String getEmailKey(String key){return setEmailKey(key);}
public static String getRootKey(String key){return setRootKey(key);} public static String getRootKey(String key){return setRootKey(key);}
public static String getTokenKey(String key){return setTokenKey(key);} public static String getTokenKey(String key){return setTokenKey(key);}
@@ -47,4 +52,8 @@ public class RedisTransKey {
public static String getUpdatePwdKey(String key){return setUpdatePwdKey(key);} public static String getUpdatePwdKey(String key){return setUpdatePwdKey(key);}
public static String getAddCreditEmailKey(String key){return setAddCreditEmailKey(key);} public static String getAddCreditEmailKey(String key){return setAddCreditEmailKey(key);}
public static String getCloseAccountKey(String key){return setCloseAccountKey(key);}
} }

View File

@@ -5,11 +5,19 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.annotation.PropertyAccessor; import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CachingConfigurerSupport; import org.springframework.cache.annotation.CachingConfigurerSupport;
import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript; import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer;
@@ -19,13 +27,21 @@ import org.springframework.data.redis.serializer.StringRedisSerializer;
* @Date 2024/6/13 09:58 * @Date 2024/6/13 09:58
* @Author dy * @Author dy
*/ */
@RefreshScope
@Configuration @Configuration
@EnableCaching @EnableCaching
public class RedisConfig extends CachingConfigurerSupport { public class RedisConfig extends CachingConfigurerSupport {
@Value("${spring.redis.host}")
private String host;
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.database:0}")
private int database = 0;
@Bean @Bean
@SuppressWarnings(value = { "unchecked", "rawtypes" }) @SuppressWarnings(value = { "unchecked", "rawtypes" })
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory) public RedisTemplate<Object, Object> redisTemplate(@Qualifier("redisConnectionFactory0") RedisConnectionFactory connectionFactory)
{ {
RedisTemplate<Object, Object> template = new RedisTemplate<>(); RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory); template.setConnectionFactory(connectionFactory);
@@ -50,6 +66,45 @@ public class RedisConfig extends CachingConfigurerSupport {
return template; return template;
} }
@Bean(name = "redisTemplate7")
public RedisTemplate<Object, Object> redisTemplate7(@Qualifier("redisConnectionFactory7") RedisConnectionFactory redisConnectionFactory0) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory0);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new StringRedisSerializer());
return template;
}
/**
* 7号 数据库 - >
* @return
*/
@Bean
public RedisConnectionFactory redisConnectionFactory7() {
LettuceConnectionFactory factory = new LettuceConnectionFactory();
factory.setHostName(host);
factory.setPort(port);
factory.setDatabase(7);
return factory;
}
/**
* 默认 数据库
* @return
*/
@Bean
@Primary //添加@Primary默认使用的库
public RedisConnectionFactory redisConnectionFactory0() {
LettuceConnectionFactory factory = new LettuceConnectionFactory();
factory.setHostName(host);
factory.setPort(port);
factory.setDatabase(database);
return factory;
}
@Bean @Bean
public DefaultRedisScript<Long> limitScript() public DefaultRedisScript<Long> limitScript()
{ {
@@ -62,6 +117,8 @@ public class RedisConfig extends CachingConfigurerSupport {
return redisScript; return redisScript;
} }
/** /**
* 限流脚本 * 限流脚本
*/ */

View File

@@ -1,6 +1,7 @@
package com.m2pool.common.redis.service; package com.m2pool.common.redis.service;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.BoundSetOperations; import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.HashOperations; import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
@@ -21,8 +22,14 @@ import java.util.concurrent.TimeUnit;
public class RedisService { public class RedisService {
@Autowired @Autowired
@Qualifier("redisTemplate")
private RedisTemplate redisTemplate; private RedisTemplate redisTemplate;
@Autowired
@Qualifier("redisTemplate7")
private RedisTemplate redisTemplate7;
/** /**
* 缓存基本的对象Integer、String、实体类等 * 缓存基本的对象Integer、String、实体类等
* *
@@ -34,6 +41,7 @@ public class RedisService {
redisTemplate.opsForValue().set(key, value); redisTemplate.opsForValue().set(key, value);
} }
/** /**
* 缓存基本的对象Integer、String、实体类等 * 缓存基本的对象Integer、String、实体类等
* *
@@ -47,6 +55,12 @@ public class RedisService {
redisTemplate.opsForValue().set(key, value, timeout, timeUnit); redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
} }
public <T> void setCacheObject7(final String key, final T value, final Long timeout, final TimeUnit timeUnit)
{
redisTemplate7.opsForValue().set(key, value, timeout, timeUnit);
}
/** /**
* 设置有效时间 * 设置有效时间
* *
@@ -118,6 +132,12 @@ public class RedisService {
return operation.get(key); return operation.get(key);
} }
public <T> T getCacheObject7(final String key)
{
ValueOperations<String, T> operation = redisTemplate7.opsForValue();
return operation.get(key);
}
/** /**
* 所有数字类型转换为BigDecimal * 所有数字类型转换为BigDecimal
* @param key 缓存键值 * @param key 缓存键值
@@ -153,6 +173,7 @@ public class RedisService {
return redisTemplate.delete(key); return redisTemplate.delete(key);
} }
/** /**
* 删除集合对象 * 删除集合对象
* *

View File

@@ -179,5 +179,5 @@ public class GlobalExceptionHandler {
log.error("请求地址'{}',发生SQL异常.", requestURI, e); log.error("请求地址'{}',发生SQL异常.", requestURI, e);
return AjaxResult.error(HttpStatus.ERROR, "数据库异常!"); return AjaxResult.error(HttpStatus.ERROR, "数据库异常!");
} }
//todo 根据业务需求增加异常 //todo 根据业务需求增加异常
} }

View File

@@ -39,9 +39,9 @@ public class HeaderInterceptor implements AsyncHandlerInterceptor {
SecurityContextHolder.setUserKey(ServletUtils.getHeader(request,SecurityConstants.USER_KEY)); SecurityContextHolder.setUserKey(ServletUtils.getHeader(request,SecurityConstants.USER_KEY));
//开发环境 //开发环境
String authorization = request.getHeader("Authorization"); //String authorization = request.getHeader("Authorization");
String userName = JwtUtils.getUserName(authorization); //String userName = JwtUtils.getUserName(authorization);
SecurityContextHolder.setUserName(userName); //SecurityContextHolder.setUserName(userName);
String token = SecurityUtils.getToken(); String token = SecurityUtils.getToken();
if(StringUtils.isNotEmpty(token)){ if(StringUtils.isNotEmpty(token)){

View File

@@ -78,7 +78,7 @@ public class WebsocketChannelInterceptor implements ChannelInterceptor {
//获取链接建立时的请求头信息 //获取链接建立时的请求头信息
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message); StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
if (accessor.getCommand() == StompCommand.CONNECT ) { if (accessor.getCommand() == StompCommand.CONNECT ) {
System.out.println("yyb-开始链接"+new Date()); System.out.println("开始链接"+new Date());
StompHeaderAccessor mha = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class); StompHeaderAccessor mha = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
if(mha == null){ if(mha == null){
throw new MessageDeliveryException(ExceptionEnum.fromCode(ExceptionEnum.SET_PRINCIPAL_FAIL)); throw new MessageDeliveryException(ExceptionEnum.fromCode(ExceptionEnum.SET_PRINCIPAL_FAIL));
@@ -92,7 +92,7 @@ public class WebsocketChannelInterceptor implements ChannelInterceptor {
ipLimit(accessor,type,email); ipLimit(accessor,type,email);
//链接请求头中用户信息存入stomp中 //链接请求头中用户信息存入stomp中
mha.setUser(new StompPrincipal(email,type,true)); mha.setUser(new StompPrincipal(email,type,true));
System.out.println("yyb-链接成功"+new Date()); System.out.println("链接成功"+new Date());
} }
if (accessor.getCommand() == StompCommand.SUBSCRIBE) { if (accessor.getCommand() == StompCommand.SUBSCRIBE) {
LOGGER.info("------------websocket subscribe message"); LOGGER.info("------------websocket subscribe message");

View File

@@ -3,7 +3,7 @@ package com.m2pool.file.service;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
/** /**
* 文件上传接口 * 接口
* *
* @author dy * @author dy
*/ */

View File

@@ -39,6 +39,8 @@ public interface PoolMapper {
public List<PowerLineDto> getHourPoolPowerList(@Param("table") String table); public List<PowerLineDto> getHourPoolPowerList(@Param("table") String table);
public List<PowerLineDto> getHourNetPowerList(@Param("table") String table); public List<PowerLineDto> getHourNetPowerList(@Param("table") String table);
BigDecimal getCurrentCoinPrice(@Param("table") String table);
public List<BlockInfoDto> getGRSBlockInfoList(); public List<BlockInfoDto> getGRSBlockInfoList();
public List<BlockInfoDto> getMonaBlockInfoList(); public List<BlockInfoDto> getMonaBlockInfoList();

View File

@@ -22,6 +22,9 @@ import com.m2pool.pool.utils.EnumUtils;
import com.m2pool.pool.utils.NodeRpc; import com.m2pool.pool.utils.NodeRpc;
import com.m2pool.pool.utils.PowerUnitUtils; import com.m2pool.pool.utils.PowerUnitUtils;
import com.m2pool.pool.vo.*; import com.m2pool.pool.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.session.SqlSession;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@@ -33,7 +36,6 @@ import java.time.LocalDateTime;
import java.time.ZoneId; import java.time.ZoneId;
import java.util.*; import java.util.*;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/** /**
@@ -41,6 +43,7 @@ import java.util.stream.Collectors;
* @Date 2024/6/14 14:29 * @Date 2024/6/14 14:29
* @Author dy * @Author dy
*/ */
@Slf4j
@Service @Service
public class PoolServiceImpl implements PoolService { public class PoolServiceImpl implements PoolService {
@@ -182,6 +185,7 @@ public class PoolServiceImpl implements PoolService {
public AjaxResult getPoolPower(CoinVo vo) { public AjaxResult getPoolPower(CoinVo vo) {
Pools pool = (Pools) EnumUtils.get(Pools.class, vo.getCoin()); Pools pool = (Pools) EnumUtils.get(Pools.class, vo.getCoin());
if(StringUtils.isNull(pool)){ if(StringUtils.isNull(pool)){
return AjaxResult.error("参数错误,未能根据当前参数获取到数据"); return AjaxResult.error("参数错误,未能根据当前参数获取到数据");
} }
@@ -189,13 +193,12 @@ public class PoolServiceImpl implements PoolService {
if(StringUtils.isBlank(vo.getInterval())){ if(StringUtils.isBlank(vo.getInterval())){
return AjaxResult.error("缺失参数:interval"); return AjaxResult.error("缺失参数:interval");
} }
PageHelper.clearPage();
List<PowerLineDto> priceList = poolMapper.getHourPoolPowerList(pool.getCoin()); List<PowerLineDto> priceList = poolMapper.getHourPoolPowerList(pool.getCoin());
int scale = PoolProfitScale.getScaleByCoin(pool.getCoin()); int scale = PoolProfitScale.getScaleByCoin(pool.getCoin());
PowerLineDto powerLineDto = priceList.stream()
.filter(e -> e.getDate().after(DateUtils.toDate(LocalDateTime.now().toLocalDate().atStartOfDay()))) BigDecimal currentCoinPrice = poolMapper.getCurrentCoinPrice(pool.getCoin());
.max(Comparator.comparing(PowerLineDto::getPrice)).orElse(new PowerLineDto());
if("1h".equals(vo.getInterval()) || "rt".equals(vo.getInterval())){ if("1h".equals(vo.getInterval()) || "rt".equals(vo.getInterval())){
// 获取当前日期 // 获取当前日期
@@ -221,19 +224,17 @@ public class PoolServiceImpl implements PoolService {
//数据补零 //数据补零
list = fillMissingOnlineData(list,oneDayAgo,currentDate,powerUnit.getUnit(),30); list = fillMissingOnlineData(list,oneDayAgo,currentDate,powerUnit.getUnit(),30);
//通过全网算力接口 获取到的时间段价格补充到矿池算力接口的价格中 //通过全网算力接口 获取到的时间段价格补充到矿池算力接口的价格中
list.stream().forEach(e -> priceList.stream().anyMatch(p ->{ list.forEach(e -> priceList.stream().anyMatch(p ->{
if( p.getDate().equals(e.getDate())){ if( p.getDate().equals(e.getDate())){
e.setPrice(p.getPrice()); e.setPrice(p.getPrice());
} }
return false; return false;
})); }));
List<PowerLineDto> collect = list.stream().peek(e -> { List<PowerLineDto> collect = list.stream().peek(e -> {
if (e.getPrice() == 0) { if (e.getPrice() == 0) {
e.setPrice(powerLineDto.getPrice()); e.setPrice(currentCoinPrice.doubleValue());
} }
}).collect(Collectors.toList()); }).collect(Collectors.toList());
return AjaxResult.success(collect); return AjaxResult.success(collect);
}else if ("1d".equals(vo.getInterval())){ }else if ("1d".equals(vo.getInterval())){
@@ -268,7 +269,7 @@ public class PoolServiceImpl implements PoolService {
list = changeUnit(powerUnit, list, pool,BigDecimal.valueOf(1000 * 1000)); list = changeUnit(powerUnit, list, pool,BigDecimal.valueOf(1000 * 1000));
list = fillMissingOnlineData(list,oneMonthAgo,currentDate,powerUnit.getUnit(),24*60); list = fillMissingOnlineData(list,oneMonthAgo,currentDate,powerUnit.getUnit(),24*60);
list.stream().forEach(e -> priceList.stream().anyMatch(p ->{ list.forEach(e -> priceList.stream().anyMatch(p ->{
if( p.getDate().equals(e.getDate())){ if( p.getDate().equals(e.getDate())){
e.setPrice(p.getPrice()); e.setPrice(p.getPrice());
} }
@@ -276,7 +277,7 @@ public class PoolServiceImpl implements PoolService {
})); }));
List<PowerLineDto> collect = list.stream().peek(e -> { List<PowerLineDto> collect = list.stream().peek(e -> {
if (e.getPrice() == 0) { if (e.getPrice() == 0) {
e.setPrice(powerLineDto.getPrice()); e.setPrice(currentCoinPrice.doubleValue());
} }
}).collect(Collectors.toList()); }).collect(Collectors.toList());
return AjaxResult.success(collect); return AjaxResult.success(collect);
@@ -423,7 +424,7 @@ public class PoolServiceImpl implements PoolService {
List<PowerLineDto> list = poolMapper.getHourNetPowerList(pool.getCoin()); List<PowerLineDto> list = poolMapper.getHourNetPowerList(pool.getCoin());
PowerLineDto powerLineDto = list.stream() PowerLineDto powerLineDto = list.stream()
.max(Comparator.comparing(PowerLineDto::getPrice)).orElse(new PowerLineDto()); .max(Comparator.comparing(PowerLineDto::getDate)).orElse(new PowerLineDto());
list = list.stream().peek(e -> { list = list.stream().peek(e -> {
if (e.getPrice() == 0) { if (e.getPrice() == 0) {
@@ -541,7 +542,7 @@ public class PoolServiceImpl implements PoolService {
} }
else { else {
BlockInfo info = redisService.getCacheObject(pool.getCoin() + "_block"); BlockInfo info = redisService.getCacheObject(pool.getCoin() + "_block");
System.out.println("yyb-redis key"+ pool.getCoin() + "_block" +"查询结果"+ info); System.out.println("redis key"+ pool.getCoin() + "_block" +"查询结果"+ info);
if(StringUtils.isNull(info)){ if(StringUtils.isNull(info)){
if(!"enx".equals(pool.getCoin()) && !"alph".equals(pool.getCoin())){ if(!"enx".equals(pool.getCoin()) && !"alph".equals(pool.getCoin())){
// //
@@ -736,7 +737,7 @@ public class PoolServiceImpl implements PoolService {
List<MinerDataDto> list = poolMapper.getHourMinerDataList(vo.getCoin()+"_mhsv2",nowStr); List<MinerDataDto> list = poolMapper.getHourMinerDataList(vo.getCoin()+"_mhsv2",nowStr);
if(list.size() > 0){ if(!list.isEmpty()){
List<MinerDataDto> offlineList = new ArrayList<>(); List<MinerDataDto> offlineList = new ArrayList<>();
list.stream().forEach(e -> { list.stream().forEach(e -> {
if(StringUtils.isNotNull(e.getMhs())){ if(StringUtils.isNotNull(e.getMhs())){

View File

@@ -504,7 +504,7 @@ public class NodeRpc{
JSONObject jsonObject = JSON.parseObject(result); JSONObject jsonObject = JSON.parseObject(result);
JSONObject jsonObject1 = JSON.parseObject(result1); JSONObject jsonObject1 = JSON.parseObject(result1);
BigDecimal netPower = jsonObject1.getBigDecimal("networkhashps"); BigDecimal netPower = jsonObject1.getBigDecimal("networkhashps");
System.out.println("yyb-全网算力grs"+netPower); System.out.println("全网算力grs"+netPower);
long height = jsonObject.getLongValue("height"); long height = jsonObject.getLongValue("height");
blockInfo.setHeight(height); blockInfo.setHeight(height);
@@ -589,7 +589,7 @@ public class NodeRpc{
BigDecimal difficulty = jsonObject.getBigDecimal("difficulty"); BigDecimal difficulty = jsonObject.getBigDecimal("difficulty");
BigDecimal netPower = jsonObject1.getBigDecimal("networkhashps"); BigDecimal netPower = jsonObject1.getBigDecimal("networkhashps");
System.out.println("yyb-全网算力mona"+netPower); System.out.println("全网算力mona"+netPower);
if(StringUtils.isNotNull(difficulty)){ if(StringUtils.isNotNull(difficulty)){
blockInfo.setDifficulty(difficulty.setScale(2,BigDecimal.ROUND_HALF_UP)); blockInfo.setDifficulty(difficulty.setScale(2,BigDecimal.ROUND_HALF_UP));
//NodeConstant constant = (NodeConstant) EnumUtils.get(NodeConstant.class, coin); //NodeConstant constant = (NodeConstant) EnumUtils.get(NodeConstant.class, coin);
@@ -669,7 +669,7 @@ public class NodeRpc{
BigDecimal difficulty = jsonObject.getBigDecimal("difficulty"); BigDecimal difficulty = jsonObject.getBigDecimal("difficulty");
BigDecimal netPower = jsonObject1.getBigDecimal("networkhashps"); BigDecimal netPower = jsonObject1.getBigDecimal("networkhashps");
System.out.println("yyb-全网算力rxd"+netPower); System.out.println("全网算力rxd"+netPower);
if(StringUtils.isNotNull(difficulty)){ if(StringUtils.isNotNull(difficulty)){
blockInfo.setDifficulty(difficulty.setScale(2,BigDecimal.ROUND_HALF_UP)); blockInfo.setDifficulty(difficulty.setScale(2,BigDecimal.ROUND_HALF_UP));
//NodeConstant constant = (NodeConstant) EnumUtils.get(NodeConstant.class, coin); //NodeConstant constant = (NodeConstant) EnumUtils.get(NodeConstant.class, coin);
@@ -1039,7 +1039,6 @@ public class NodeRpc{
qBlockInfo.setPower(qNetwork); qBlockInfo.setPower(qNetwork);
map.put("dgbq",qBlockInfo); map.put("dgbq",qBlockInfo);
} }
System.out.println("存储的数据"+map);
return map; return map;
} }

View File

@@ -75,3 +75,8 @@ myenv:
path: /var/www/html/web_test path: /var/www/html/web_test
img: /img img: /img
filepath: /home/ubuntu/web filepath: /home/ubuntu/web
#mybatis:
# configuration:
# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

View File

@@ -62,13 +62,13 @@
<!-- Spring日志级别控制 --> <!-- Spring日志级别控制 -->
<logger name="org.springframework" level="warn" /> <logger name="org.springframework" level="warn" />
<root level="info">
<appender-ref ref="console" />
</root>
<!--系统操作日志--> <!--系统操作日志-->
<root level="info"> <root level="info">
<appender-ref ref="file_info" /> <appender-ref ref="file_info" />
<appender-ref ref="file_error" /> <appender-ref ref="file_error" />
</root> </root>
</configuration> </configuration>

View File

@@ -375,11 +375,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="getHourPoolPowerList" resultType="com.m2pool.pool.dto.PowerLineDto"> <select id="getHourPoolPowerList" resultType="com.m2pool.pool.dto.PowerLineDto">
select select
p.date `date`, p.date `date`,
COALESCE(p.value,0) price, COALESCE(p.value,0) price
COALESCE(np.value,0) pv
from from
${table}_price p ${table}_price p
left join ${table}_net_power np on p.date = np.date where p.date >= DATE_SUB(NOW(), INTERVAL 35 DAY)
</select> </select>
<select id="getHourNetPowerList" resultType="com.m2pool.pool.dto.PowerLineDto"> <select id="getHourNetPowerList" resultType="com.m2pool.pool.dto.PowerLineDto">
@@ -1048,6 +1047,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{i.user} #{i.user}
</foreach> </foreach>
</select> </select>
<select id="getCurrentCoinPrice" resultType="java.math.BigDecimal">
select `value` from ${table}_price order by id DESC LIMIT 1;
</select>
</mapper> </mapper>

View File

@@ -2,13 +2,13 @@ package com.m2pool.system.controller;
import com.m2pool.common.core.Result.R; import com.m2pool.common.core.Result.R;
import com.m2pool.common.core.constant.UserConstants; import com.m2pool.common.core.constant.UserConstants;
import com.m2pool.common.core.utils.DateUtils;
import com.m2pool.common.core.utils.StringUtils; import com.m2pool.common.core.utils.StringUtils;
import com.m2pool.common.core.web.Result.AjaxResult; import com.m2pool.common.core.web.Result.AjaxResult;
import com.m2pool.common.core.web.controller.BaseController; import com.m2pool.common.core.web.controller.BaseController;
import com.m2pool.common.log.annotation.Log; import com.m2pool.common.log.annotation.Log;
import com.m2pool.common.log.enums.BusinessType; import com.m2pool.common.log.enums.BusinessType;
import com.m2pool.common.security.annotation.InnerAuth; import com.m2pool.common.security.annotation.InnerAuth;
import com.m2pool.common.security.annotation.RequiresLogin;
import com.m2pool.common.security.annotation.RequiresPermissions; import com.m2pool.common.security.annotation.RequiresPermissions;
import com.m2pool.common.security.utils.SecurityUtils; import com.m2pool.common.security.utils.SecurityUtils;
import com.m2pool.system.api.entity.SysRole; import com.m2pool.system.api.entity.SysRole;
@@ -237,4 +237,11 @@ public class SysUserController extends BaseController {
} }
return R.success(list); return R.success(list);
} }
@RequiresLogin
@PostMapping("/closeAccount")
@ApiOperation(value = "用户注销")
public AjaxResult closeAccount(@RequestBody SysUser sysUser){
return toAjax(userService.closeAccount(sysUser));
}
} }

View File

@@ -135,4 +135,12 @@ public interface SysUserMapper {
* @return 用户信息集合信息 * @return 用户信息集合信息
*/ */
public List<SysUser> getCSList(); public List<SysUser> getCSList();
/**
* 关闭用户
* @param closeAccountVo
* @return
*/
boolean closeUser(SysUser sysUser);
} }

View File

@@ -173,4 +173,11 @@ public interface SysUserService {
* @return 结果 * @return 结果
*/ */
public List<SysUser> getCSList(); public List<SysUser> getCSList();
/**
* 注销用户
* @return 结果
*/
boolean closeAccount(SysUser sysUser);
} }

View File

@@ -8,9 +8,7 @@ import com.m2pool.common.core.utils.StringUtils;
import com.m2pool.common.core.web.Result.AjaxResult; import com.m2pool.common.core.web.Result.AjaxResult;
import com.m2pool.common.datascope.annotation.DataScope; import com.m2pool.common.datascope.annotation.DataScope;
import com.m2pool.common.security.utils.SecurityUtils; import com.m2pool.common.security.utils.SecurityUtils;
import com.m2pool.system.api.entity.SysRole; import com.m2pool.system.api.entity.*;
import com.m2pool.system.api.entity.SysUser;
import com.m2pool.system.api.entity.SysUserLeveDate;
import com.m2pool.system.entity.GoogleInfo; import com.m2pool.system.entity.GoogleInfo;
import com.m2pool.system.entity.SysUserRole; import com.m2pool.system.entity.SysUserRole;
import com.m2pool.system.mapper.SysRoleMapper; import com.m2pool.system.mapper.SysRoleMapper;
@@ -444,5 +442,8 @@ public class SysUserServiceImpl implements SysUserService {
} }
} }
@Override
public boolean closeAccount(SysUser sysUser) {
return userMapper.closeUser(sysUser);
}
} }

View File

@@ -207,5 +207,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<update id="resetPwdByEmail" parameterType="com.m2pool.system.api.entity.SysUser"> <update id="resetPwdByEmail" parameterType="com.m2pool.system.api.entity.SysUser">
update sys_user set password = #{password} where email = #{email} update sys_user set password = #{password} where email = #{email}
</update> </update>
<update id="closeUser">
update sys_user
<set>
<if test="delFlag != null">delFlag = #{delFlag},</if>
update_time = sysdate()
</set>
where user_id = #{userId}
</update>
</mapper> </mapper>