mirror of https://github.com/elunez/eladmin
Merge branch 'master' into master
commit
c5c770e8f9
|
@ -17,11 +17,6 @@
|
|||
|
||||
**账号密码:** `admin / 123456`
|
||||
|
||||
#### 活动福利
|
||||
|
||||
- 七牛云 2021 ECUG Con 全球技术大会内部票:给大家一共搞来五张小一千块钱的内部票。想要的加群【947578238】联系群主
|
||||
- 七牛云 2021 ECUG Con 全球技术大会早鸟特惠票:[点我抢购](http://www.huodongxing.com/event/1573487912300?coupon=EL666)
|
||||
|
||||
#### 项目源码
|
||||
|
||||
| | 后端源码 | 前端源码 |
|
||||
|
|
|
@ -50,7 +50,7 @@ public class BaseEntity implements Serializable {
|
|||
@LastModifiedBy
|
||||
@Column(name = "update_by")
|
||||
@ApiModelProperty(value = "更新人", hidden = true)
|
||||
private String updatedBy;
|
||||
private String updateBy;
|
||||
|
||||
@CreationTimestamp
|
||||
@Column(name = "create_time", updatable = false)
|
||||
|
|
|
@ -26,14 +26,12 @@ import org.springframework.context.annotation.Configuration;
|
|||
import org.springframework.core.Ordered;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import springfox.documentation.builders.ApiInfoBuilder;
|
||||
import springfox.documentation.builders.ParameterBuilder;
|
||||
import springfox.documentation.builders.PathSelectors;
|
||||
import springfox.documentation.schema.AlternateTypeRule;
|
||||
import springfox.documentation.schema.AlternateTypeRuleConvention;
|
||||
import springfox.documentation.schema.ModelRef;
|
||||
import springfox.documentation.service.ApiInfo;
|
||||
import springfox.documentation.service.Parameter;
|
||||
import springfox.documentation.service.*;
|
||||
import springfox.documentation.spi.DocumentationType;
|
||||
import springfox.documentation.spi.service.contexts.SecurityContext;
|
||||
import springfox.documentation.spring.web.plugins.Docket;
|
||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||
import java.util.ArrayList;
|
||||
|
@ -53,41 +51,65 @@ public class SwaggerConfig {
|
|||
@Value("${jwt.header}")
|
||||
private String tokenHeader;
|
||||
|
||||
@Value("${jwt.token-start-with}")
|
||||
private String tokenStartWith;
|
||||
|
||||
@Value("${swagger.enabled}")
|
||||
private Boolean enabled;
|
||||
|
||||
@Bean
|
||||
@SuppressWarnings("all")
|
||||
public Docket createRestApi() {
|
||||
ParameterBuilder ticketPar = new ParameterBuilder();
|
||||
List<Parameter> pars = new ArrayList<>();
|
||||
ticketPar.name(tokenHeader).description("token")
|
||||
.modelRef(new ModelRef("string"))
|
||||
.parameterType("header")
|
||||
.defaultValue(tokenStartWith + " ")
|
||||
.required(true)
|
||||
.build();
|
||||
pars.add(ticketPar.build());
|
||||
return new Docket(DocumentationType.SWAGGER_2)
|
||||
.enable(enabled)
|
||||
.pathMapping("/")
|
||||
.apiInfo(apiInfo())
|
||||
.select()
|
||||
.paths(Predicates.not(PathSelectors.regex("/error.*")))
|
||||
.paths(PathSelectors.any())
|
||||
.build()
|
||||
.globalOperationParameters(pars);
|
||||
//添加登陆认证
|
||||
.securitySchemes(securitySchemes())
|
||||
.securityContexts(securityContexts());
|
||||
}
|
||||
|
||||
private ApiInfo apiInfo() {
|
||||
return new ApiInfoBuilder()
|
||||
.description("一个简单且易上手的 Spring boot 后台管理框架")
|
||||
.title("EL-ADMIN 接口文档")
|
||||
.version("2.4")
|
||||
.version("2.6")
|
||||
.build();
|
||||
}
|
||||
|
||||
private List<SecurityScheme> securitySchemes() {
|
||||
//设置请求头信息
|
||||
List<SecurityScheme> securitySchemes = new ArrayList<>();
|
||||
ApiKey apiKey = new ApiKey(tokenHeader, tokenHeader, "header");
|
||||
securitySchemes.add(apiKey);
|
||||
return securitySchemes;
|
||||
}
|
||||
|
||||
private List<SecurityContext> securityContexts() {
|
||||
//设置需要登录认证的路径
|
||||
List<SecurityContext> securityContexts = new ArrayList<>();
|
||||
// ^(?!auth).*$ 表示所有包含auth的接口不需要使用securitySchemes即不需要带token
|
||||
// ^标识开始 ()里是一子表达式 ?!/auth表示匹配不是/auth的位置,匹配上则添加请求头,注意路径已/开头 .表示任意字符 *表示前面的字符匹配多次 $标识结束
|
||||
securityContexts.add(getContextByPath());
|
||||
return securityContexts;
|
||||
}
|
||||
|
||||
private SecurityContext getContextByPath() {
|
||||
return SecurityContext.builder()
|
||||
.securityReferences(defaultAuth())
|
||||
.forPaths(PathSelectors.regex("^(?!/auth).*$"))
|
||||
.build();
|
||||
}
|
||||
|
||||
private List<SecurityReference> defaultAuth() {
|
||||
List<SecurityReference> securityReferences = new ArrayList<>();
|
||||
AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
|
||||
AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
|
||||
authorizationScopes[0] = authorizationScope;
|
||||
securityReferences.add(new SecurityReference(tokenHeader, authorizationScopes));
|
||||
return securityReferences;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -95,7 +95,7 @@ public class FileUtil extends cn.hutool.core.io.FileUtil {
|
|||
File file = null;
|
||||
try {
|
||||
// 用uuid作为文件名,防止生成的临时文件重复
|
||||
file = File.createTempFile(IdUtil.simpleUUID(), prefix);
|
||||
file = new File(SYS_TEM_DIR + IdUtil.simpleUUID() + prefix);
|
||||
// MultipartFile to File
|
||||
multipartFile.transferTo(file);
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -2,6 +2,7 @@ package me.zhengjie.utils;
|
|||
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import javax.crypto.Cipher;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.security.*;
|
||||
import java.security.interfaces.RSAPrivateKey;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
|
@ -80,7 +81,7 @@ public class RsaUtils {
|
|||
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
|
||||
Cipher cipher = Cipher.getInstance("RSA");
|
||||
cipher.init(Cipher.DECRYPT_MODE, publicKey);
|
||||
byte[] result = cipher.doFinal(Base64.decodeBase64(text));
|
||||
byte[] result = doLongerCipherFinal(cipher, Base64.decodeBase64(text));
|
||||
return new String(result);
|
||||
}
|
||||
|
||||
|
@ -98,7 +99,7 @@ public class RsaUtils {
|
|||
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
|
||||
Cipher cipher = Cipher.getInstance("RSA");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
|
||||
byte[] result = cipher.doFinal(text.getBytes());
|
||||
byte[] result = doLongerCipherFinal(cipher, text.getBytes());
|
||||
return Base64.encodeBase64String(result);
|
||||
}
|
||||
|
||||
|
@ -116,7 +117,7 @@ public class RsaUtils {
|
|||
PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec5);
|
||||
Cipher cipher = Cipher.getInstance("RSA");
|
||||
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||
byte[] result = cipher.doFinal(Base64.decodeBase64(text));
|
||||
byte[] result = doLongerCipherFinal(cipher, Base64.decodeBase64(text));
|
||||
return new String(result);
|
||||
}
|
||||
|
||||
|
@ -133,10 +134,23 @@ public class RsaUtils {
|
|||
PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec2);
|
||||
Cipher cipher = Cipher.getInstance("RSA");
|
||||
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||
byte[] result = cipher.doFinal(text.getBytes());
|
||||
byte[] result = doLongerCipherFinal(cipher, text.getBytes());
|
||||
return Base64.encodeBase64String(result);
|
||||
}
|
||||
|
||||
private static byte[] doLongerCipherFinal(Cipher cipher, byte[] source) throws Exception {
|
||||
int offset = 0;
|
||||
int totalSize = source.length;
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
while (totalSize - offset > 0) {
|
||||
int size = Math.min(1024 / 8 - 11, totalSize - offset);
|
||||
out.write(cipher.doFinal(source, offset, size));
|
||||
offset += size;
|
||||
}
|
||||
out.close();
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建RSA密钥对
|
||||
*
|
||||
|
|
|
@ -42,7 +42,6 @@ import java.util.concurrent.*;
|
|||
* @date 2019-01-07
|
||||
*/
|
||||
@Async
|
||||
@SuppressWarnings({"unchecked","all"})
|
||||
public class ExecutionJob extends QuartzJobBean {
|
||||
|
||||
/** 该处仅供参考 */
|
||||
|
@ -108,9 +107,11 @@ public class ExecutionJob extends QuartzJobBean {
|
|||
if(quartzJob.getEmail() != null){
|
||||
EmailService emailService = SpringContextHolder.getBean(EmailService.class);
|
||||
// 邮箱报警
|
||||
if(StringUtils.isNoneBlank(quartzJob.getEmail())){
|
||||
EmailVo emailVo = taskAlarm(quartzJob, ThrowableUtil.getStackTrace(e));
|
||||
emailService.send(emailVo, emailService.find());
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
quartzLogRepository.save(log);
|
||||
}
|
||||
|
|
|
@ -20,8 +20,8 @@ import lombok.Data;
|
|||
/**
|
||||
* 登录验证码配置信息
|
||||
*
|
||||
* @author: liaojinlong
|
||||
* @date: 2020/6/10 18:53
|
||||
* @author liaojinlong
|
||||
* @date 2020/6/10 18:53
|
||||
*/
|
||||
@Data
|
||||
public class LoginCode {
|
||||
|
|
|
@ -39,6 +39,7 @@ public class LoginProperties {
|
|||
private boolean singleLogin = false;
|
||||
|
||||
private LoginCode loginCode;
|
||||
|
||||
/**
|
||||
* 用户登录信息缓存
|
||||
*/
|
||||
|
|
|
@ -89,7 +89,10 @@ public class AuthorizationController {
|
|||
new UsernamePasswordAuthenticationToken(authUser.getUsername(), password);
|
||||
Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken);
|
||||
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
// 生成令牌
|
||||
// 生成令牌与第三方系统获取令牌方式
|
||||
// UserDetails userDetails = userDetailsService.loadUserByUsername(userInfo.getUsername());
|
||||
// Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
|
||||
// SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||
String token = tokenProvider.createToken(authentication);
|
||||
final JwtUserDto jwtUserDto = (JwtUserDto) authentication.getPrincipal();
|
||||
// 保存在线信息
|
||||
|
|
|
@ -81,12 +81,12 @@ public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificat
|
|||
|
||||
/**
|
||||
* 根据角色中的部门查询
|
||||
* @param id /
|
||||
* @param deptId /
|
||||
* @return /
|
||||
*/
|
||||
@Query(value = "SELECT u.* FROM sys_user u, sys_users_roles r, sys_roles_depts d WHERE " +
|
||||
"u.user_id = r.user_id AND r.role_id = d.role_id AND r.role_id = ?1 group by u.user_id", nativeQuery = true)
|
||||
List<User> findByDeptRoleId(Long id);
|
||||
"u.user_id = r.user_id AND r.role_id = d.role_id AND d.dept_id = ?1 group by u.user_id", nativeQuery = true)
|
||||
List<User> findByRoleDeptId(Long deptId);
|
||||
|
||||
/**
|
||||
* 根据菜单查询
|
||||
|
|
|
@ -21,6 +21,7 @@ import io.swagger.annotations.ApiOperation;
|
|||
import lombok.RequiredArgsConstructor;
|
||||
import me.zhengjie.annotation.Log;
|
||||
import me.zhengjie.config.RsaProperties;
|
||||
import me.zhengjie.modules.system.domain.Dept;
|
||||
import me.zhengjie.modules.system.service.DataService;
|
||||
import me.zhengjie.modules.system.domain.User;
|
||||
import me.zhengjie.exception.BadRequestException;
|
||||
|
@ -79,7 +80,10 @@ public class UserController {
|
|||
public ResponseEntity<Object> query(UserQueryCriteria criteria, Pageable pageable){
|
||||
if (!ObjectUtils.isEmpty(criteria.getDeptId())) {
|
||||
criteria.getDeptIds().add(criteria.getDeptId());
|
||||
criteria.getDeptIds().addAll(deptService.getDeptChildren(deptService.findByPid(criteria.getDeptId())));
|
||||
// 先查找是否存在子节点
|
||||
List<Dept> data = deptService.findByPid(criteria.getDeptId());
|
||||
// 然后把子节点的ID都加入到集合中
|
||||
criteria.getDeptIds().addAll(deptService.getDeptChildren(data));
|
||||
}
|
||||
// 数据权限
|
||||
List<Long> dataScopes = dataService.getDeptIds(userService.findByName(SecurityUtils.getCurrentUsername()));
|
||||
|
|
|
@ -58,7 +58,7 @@ public class DeptServiceImpl implements DeptService {
|
|||
|
||||
@Override
|
||||
public List<DeptDto> queryAll(DeptQueryCriteria criteria, Boolean isQuery) throws Exception {
|
||||
Sort sort = new Sort(Sort.Direction.ASC, "deptSort");
|
||||
Sort sort = Sort.by(Sort.Direction.ASC, "deptSort");
|
||||
String dataScopeType = SecurityUtils.getDataScopeType();
|
||||
if (isQuery) {
|
||||
if(dataScopeType.equals(DataScopeEnum.ALL.getValue())){
|
||||
|
@ -273,7 +273,7 @@ public class DeptServiceImpl implements DeptService {
|
|||
* @param id /
|
||||
*/
|
||||
public void delCaches(Long id){
|
||||
List<User> users = userRepository.findByDeptRoleId(id);
|
||||
List<User> users = userRepository.findByRoleDeptId(id);
|
||||
// 删除数据权限
|
||||
redisUtils.delByKeys(CacheKey.DATA_USER, users.stream().map(User::getId).collect(Collectors.toSet()));
|
||||
redisUtils.del(CacheKey.DEPT_ID + id);
|
||||
|
|
|
@ -61,7 +61,7 @@ public class MenuServiceImpl implements MenuService {
|
|||
|
||||
@Override
|
||||
public List<MenuDto> queryAll(MenuQueryCriteria criteria, Boolean isQuery) throws Exception {
|
||||
Sort sort = new Sort(Sort.Direction.ASC, "menuSort");
|
||||
Sort sort = Sort.by(Sort.Direction.ASC, "menuSort");
|
||||
if(isQuery){
|
||||
criteria.setPidIsNull(true);
|
||||
List<Field> fields = QueryHelp.getAllFields(criteria.getClass(), new ArrayList<>());
|
||||
|
|
|
@ -66,7 +66,7 @@ public class RoleServiceImpl implements RoleService {
|
|||
|
||||
@Override
|
||||
public List<RoleDto> queryAll() {
|
||||
Sort sort = new Sort(Sort.Direction.ASC, "level");
|
||||
Sort sort = Sort.by(Sort.Direction.ASC, "level");
|
||||
return roleMapper.toDto(roleRepository.findAll(sort));
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ redis:
|
|||
port: 6379
|
||||
password: Chushang831
|
||||
|
||||
|
||||
# 登录相关配置
|
||||
login:
|
||||
# 登录缓存
|
||||
|
@ -27,7 +28,7 @@ login:
|
|||
# 验证码高度
|
||||
width: 111
|
||||
# 验证码宽度
|
||||
heigth: 36
|
||||
height: 36
|
||||
# 内容长度
|
||||
length: 2
|
||||
# 字体名称,为空则使用默认字体
|
||||
|
|
|
@ -21,7 +21,7 @@ login:
|
|||
# 验证码高度
|
||||
width: 111
|
||||
# 验证码宽度
|
||||
heigth: 36
|
||||
height: 36
|
||||
# 内容长度
|
||||
length: 2
|
||||
# 字体名称,为空则使用默认字体,如遇到线上乱码,设置其他字体即可
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<configuration scan="true" scanPeriod="30 seconds" debug="false">
|
||||
<contextName>elAdmin</contextName>
|
||||
<property name="log.charset" value="utf-8" />
|
||||
<property name="log.pattern" value="%black(%contextName-) %red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}) - %gray(%msg%n)" />
|
||||
<property name="log.pattern" value="%contextName- %red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta(%logger{36}) - %msg%n" />
|
||||
|
||||
<!--输出到控制台-->
|
||||
<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<name>工具模块</name>
|
||||
|
||||
<properties>
|
||||
<mail.version>1.5.0-b01</mail.version>
|
||||
<mail.version>1.4.7</mail.version>
|
||||
<qiniu.version>[7.2.0, 7.2.99]</qiniu.version>
|
||||
<alipay.version>4.9.153.ALL</alipay.version>
|
||||
</properties>
|
||||
|
|
|
@ -69,7 +69,9 @@ public class EmailServiceImpl implements EmailService {
|
|||
}
|
||||
// 封装
|
||||
MailAccount account = new MailAccount();
|
||||
account.setUser(emailConfig.getUser());
|
||||
// 设置用户
|
||||
String user = emailConfig.getFromUser().split("@")[0];
|
||||
account.setUser(user);
|
||||
account.setHost(emailConfig.getHost());
|
||||
account.setPort(Integer.parseInt(emailConfig.getPort()));
|
||||
account.setAuth(true);
|
||||
|
|
4
pom.xml
4
pom.xml
|
@ -23,7 +23,7 @@
|
|||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.1.0.RELEASE</version>
|
||||
<version>2.2.10.RELEASE</version>
|
||||
</parent>
|
||||
|
||||
<properties>
|
||||
|
@ -33,7 +33,7 @@
|
|||
<log4jdbc.version>1.16</log4jdbc.version>
|
||||
<swagger.version>2.9.2</swagger.version>
|
||||
<fastjson.version>1.2.70</fastjson.version>
|
||||
<druid.version>1.1.22</druid.version>
|
||||
<druid.version>1.1.24</druid.version>
|
||||
<commons-pool2.version>2.5.0</commons-pool2.version>
|
||||
<mapstruct.version>1.3.1.Final</mapstruct.version>
|
||||
</properties>
|
||||
|
|
|
@ -660,7 +660,7 @@ CREATE TABLE `sys_user` (
|
|||
`is_admin` bit(1) DEFAULT b'0' COMMENT '是否为admin账号',
|
||||
`enabled` bigint(20) DEFAULT NULL COMMENT '状态:1启用、0禁用',
|
||||
`create_by` varchar(255) DEFAULT NULL COMMENT '创建者',
|
||||
`update_by` varchar(255) DEFAULT NULL COMMENT '更新着',
|
||||
`update_by` varchar(255) DEFAULT NULL COMMENT '更新者',
|
||||
`pwd_reset_time` datetime DEFAULT NULL COMMENT '修改密码的时间',
|
||||
`create_time` datetime DEFAULT NULL COMMENT '创建日期',
|
||||
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
||||
|
|
Loading…
Reference in New Issue