diff --git a/backend-src/pom.xml b/backend-src/pom.xml index ecf99202222db749d12818e03696f3c5f4bbfb93..2f0964d370f502fa5d6f2e57fe7c7a46cb364284 100644 --- a/backend-src/pom.xml +++ b/backend-src/pom.xml @@ -21,6 +21,8 @@ 1.18.24 8.0.28 3.2.13 + 1.30.0 + 2.9.2 @@ -38,7 +40,7 @@ org.springframework.boot - spring-boot-starter-security + spring-boot-starter-validation @@ -49,13 +51,6 @@ - - - io.jsonwebtoken - jjwt - 0.9.0 - - org.projectlombok @@ -76,6 +71,16 @@ com.github.docker-java docker-java 3.2.13 + + + guava + com.google.guava + + + commons-io + commons-io + + @@ -158,6 +163,45 @@ 1.07.00 + + cn.dev33 + sa-token-spring-boot-starter + ${sa-token.version} + + + + com.github.pagehelper + pagehelper-spring-boot-starter + 1.4.3 + + + mybatis-spring + org.mybatis + + + mybatis + org.mybatis + + + jsqlparser + com.github.jsqlparser + + + + + + io.springfox + springfox-swagger2 + ${swagger.version} + + + + io.springfox + springfox-swagger-ui + ${swagger.version} + + + diff --git a/backend-src/src/main/java/com/taoes/simpledocker/SimpleDockerApplication.java b/backend-src/src/main/java/com/taoes/simpledocker/SimpleDockerApplication.java index c3b47e9dd1b83a5e022dd1edf6fc52fc1e095b79..5159db90d02a90cb833b6cb35e173012d227d166 100644 --- a/backend-src/src/main/java/com/taoes/simpledocker/SimpleDockerApplication.java +++ b/backend-src/src/main/java/com/taoes/simpledocker/SimpleDockerApplication.java @@ -2,6 +2,7 @@ package com.taoes.simpledocker; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import springfox.documentation.swagger2.annotations.EnableSwagger2; @SpringBootApplication public class SimpleDockerApplication { diff --git a/backend-src/src/main/java/com/taoes/simpledocker/config/CommandExceptionHandler.java b/backend-src/src/main/java/com/taoes/simpledocker/config/CommandExceptionHandler.java index cd8442098f065c6fd98bcfd86468a8ad6fd2d175..0f977d4dc18d90f02a32a9463707b33cc4d048ec 100644 --- a/backend-src/src/main/java/com/taoes/simpledocker/config/CommandExceptionHandler.java +++ b/backend-src/src/main/java/com/taoes/simpledocker/config/CommandExceptionHandler.java @@ -1,7 +1,12 @@ package com.taoes.simpledocker.config; +import cn.dev33.satoken.exception.NotPermissionException; +import cn.dev33.satoken.exception.SaTokenException; import com.taoes.simpledocker.model.ResponseModel; + import javax.ws.rs.ProcessingException; + +import com.taoes.simpledocker.model.enums.PermissionEnum; import org.springframework.http.HttpEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -16,11 +21,18 @@ import org.springframework.web.bind.annotation.ExceptionHandler; public class CommandExceptionHandler { @ExceptionHandler(RuntimeException.class) - public HttpEntity> corsFilter(RuntimeException e){ - if (e instanceof ProcessingException){ + public HttpEntity> corsFilter(RuntimeException e) { + if (e instanceof ProcessingException) { String msg = "Docker服务连接异常"; return new HttpEntity<>(ResponseModel.fail(msg).setCode(400)); } return new HttpEntity<>(ResponseModel.fail(e.getMessage()).setCode(400)); } + + + @ExceptionHandler(NotPermissionException.class) + public HttpEntity> saPermissionFilter(NotPermissionException e) { + PermissionEnum permissionEnum = PermissionEnum.getPermissionEnum(e.getPermission()); + return new HttpEntity<>(ResponseModel.fail("无" + permissionEnum.getDesc() + "权限").setCode(400)); + } } diff --git a/backend-src/src/main/java/com/taoes/simpledocker/config/SpringConfig.java b/backend-src/src/main/java/com/taoes/simpledocker/config/SpringConfig.java index 43fd9d2dac344d2fa725db4c775b051748fb6f43..7dd11e14bd4fe7de4adb2f737926fedce21e87fa 100644 --- a/backend-src/src/main/java/com/taoes/simpledocker/config/SpringConfig.java +++ b/backend-src/src/main/java/com/taoes/simpledocker/config/SpringConfig.java @@ -3,7 +3,6 @@ package com.taoes.simpledocker.config; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import org.springframework.context.annotation.Bean; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.stereotype.Component; /** @@ -15,15 +14,11 @@ import org.springframework.stereotype.Component; @Component public class SpringConfig { - @Bean - public ObjectMapper objectMapper(){ - ObjectMapper mapper = new ObjectMapper(); - mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS,false); - return mapper; - } + @Bean + public ObjectMapper objectMapper() { + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); + return mapper; + } - @Bean - public BCryptPasswordEncoder bCryptPasswordEncoder() { - return new BCryptPasswordEncoder(); - } } diff --git a/backend-src/src/main/java/com/taoes/simpledocker/config/SpringInterception.java b/backend-src/src/main/java/com/taoes/simpledocker/config/SpringInterception.java index 659ac4e4b2d2d1c07faa725d9370b100828e8ea9..93f346a58dfa041be7ea66d9e0f2689018844675 100644 --- a/backend-src/src/main/java/com/taoes/simpledocker/config/SpringInterception.java +++ b/backend-src/src/main/java/com/taoes/simpledocker/config/SpringInterception.java @@ -1,5 +1,7 @@ package com.taoes.simpledocker.config; +import cn.dev33.satoken.interceptor.SaAnnotationInterceptor; +import com.taoes.simpledocker.config.interceptor.UserLoginInterceptor; import org.springframework.stereotype.Component; import org.springframework.web.servlet.config.annotation.InterceptorRegistration; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; @@ -21,11 +23,17 @@ public class SpringInterception implements WebMvcConfigurer { InterceptorRegistration registration = registry.addInterceptor(new DockerClientInterception()); registration.addPathPatterns("/**"); registration.excludePathPatterns( - "/**/*.html", - "/**/*.js", - "/**/*.css", - "/**/*.woff", - "/**/*.ttf" + "/**/*.html", + "/**/*.js", + "/**/*.css", + "/**/*.woff", + "/**/*.ttf" ); + registry.addInterceptor(new UserLoginInterceptor()) + .addPathPatterns("/api/**") + .excludePathPatterns("/api/auth/login"); + + registry.addInterceptor(new SaAnnotationInterceptor()) + .addPathPatterns("/api/**"); } } diff --git a/backend-src/src/main/java/com/taoes/simpledocker/config/Swagger2Configuration.java b/backend-src/src/main/java/com/taoes/simpledocker/config/Swagger2Configuration.java new file mode 100644 index 0000000000000000000000000000000000000000..95902f3cd44dd78a7053b1d43edff1d6ac3325c9 --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/config/Swagger2Configuration.java @@ -0,0 +1,58 @@ +package com.taoes.simpledocker.config; + +import com.taoes.simpledocker.config.model.SwaggerProperties; +import io.swagger.annotations.ApiOperation; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.service.Contact; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +import static springfox.documentation.builders.RequestHandlerSelectors.withMethodAnnotation; + +/** + * swagger在线文档配置
+ * 项目启动后可通过地址:http://host:ip/swagger-ui.html 查看在线文档 + * + * @author manwang (569258yin) + * @date 2022/7/14 21:16 + */ + +@Configuration +@EnableSwagger2 +public class Swagger2Configuration { + + + @Bean + public Docket system(SwaggerProperties swaggerProperties) { + + return new Docket(DocumentationType.SWAGGER_2) + // 设定Api文档头信息,这个信息会展示在文档UI的头部位置 + .apiInfo(apiInfo(swaggerProperties)) + // 是否开启Swagger(生产环境建议关闭,避免接口暴露) + .enable(swaggerProperties.getEnable()) + .select() + // 添加过滤条件,谓词过滤predicate,这里是自定义注解进行过滤 + .apis(withMethodAnnotation(ApiOperation.class)) + .apis(RequestHandlerSelectors.basePackage("com.taoes.simpledocker.controller")) + // 这里配合@ComponentScan一起使用,又再次细化了匹配规则(当然,我们也可以只选择@ComponentScan、paths()方法当中的一中) + .paths(PathSelectors.any()) + .build(); + } + + private ApiInfo apiInfo(SwaggerProperties swaggerProperties) { + SwaggerProperties.Contact contact = swaggerProperties.getContact(); + return new ApiInfoBuilder() + .title(swaggerProperties.getTitle()) + .description(swaggerProperties.getDescription()) + .termsOfServiceUrl(swaggerProperties.getTermsOfServiceUrl()) + .contact(new Contact(contact.getName(), contact.getUrl(), contact.getEmail())) + .version(swaggerProperties.getVersion()) + .build(); + } +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/config/interceptor/UserLoginInterceptor.java b/backend-src/src/main/java/com/taoes/simpledocker/config/interceptor/UserLoginInterceptor.java new file mode 100644 index 0000000000000000000000000000000000000000..34152cbfbe19b49889d6a80d4cbe5154f99274a4 --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/config/interceptor/UserLoginInterceptor.java @@ -0,0 +1,23 @@ +package com.taoes.simpledocker.config.interceptor; + +import cn.dev33.satoken.stp.StpUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * + */ +@Slf4j +public class UserLoginInterceptor implements HandlerInterceptor { + + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + log.info("url={}",request.getRequestURL().toString()); + StpUtil.checkLogin(); + return HandlerInterceptor.super.preHandle(request, response, handler); + } +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/config/model/JwtUser.java b/backend-src/src/main/java/com/taoes/simpledocker/config/model/JwtUser.java deleted file mode 100644 index ee19261c27e99467715da63b70b0d7abf3a2f58a..0000000000000000000000000000000000000000 --- a/backend-src/src/main/java/com/taoes/simpledocker/config/model/JwtUser.java +++ /dev/null @@ -1,64 +0,0 @@ -package com.taoes.simpledocker.config.model; - -import com.taoes.simpledocker.dao.bean.UserDao; -import java.util.ArrayList; -import java.util.Collection; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.userdetails.UserDetails; - -public class JwtUser implements UserDetails { - - private UserDao user; - - public JwtUser(UserDao user) { - this.user = user; - } - - @Override - public Collection getAuthorities() { - //返回当前用户的权限 - return new ArrayList<>(); - } - - @Override - public String getPassword() { - return user.getPassword(); - } - - @Override - public String getUsername() { - return user.getUsername(); - } - - /** - * 账户是否未过期 - **/ - @Override - public boolean isAccountNonExpired() { - return true; - } - - /** - * 账户是否未锁定 - **/ - @Override - public boolean isAccountNonLocked() { - return true; - } - - /** - * 密码是否未过期 - **/ - @Override - public boolean isCredentialsNonExpired() { - return true; - } - - /** - * 账户是否激活 - **/ - @Override - public boolean isEnabled() { - return user != null; - } -} \ No newline at end of file diff --git a/backend-src/src/main/java/com/taoes/simpledocker/config/model/SwaggerProperties.java b/backend-src/src/main/java/com/taoes/simpledocker/config/model/SwaggerProperties.java new file mode 100644 index 0000000000000000000000000000000000000000..82b90fe4b203a1bdd58c4cee4f1286622f034e6f --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/config/model/SwaggerProperties.java @@ -0,0 +1,75 @@ +package com.taoes.simpledocker.config.model; + +import lombok.Data; +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author manwang (569258yin) + * @date 2022/7/14 21:16 + */ +@Data +@ConfigurationProperties(prefix = "swagger") +@Component +public class SwaggerProperties { + /** + * 是否开启Swagger + */ + private Boolean enable = true; + + /** + * 文档标题 + */ + private String title = "SimpleDocker"; + + /** + * 文档描述 + */ + private String description = "SimpleDocker"; + + /** + * 文档版本 + */ + private String version = "1.0"; + + /** + * 服务条款 + */ + private String termsOfServiceUrl = "服务条款"; + + /** + * 许可证 + */ + private String license; + + /** + * 许可证地址 + */ + private String licenseUrl; + + /** + * 作者信息 + */ + private Contact contact = new Contact(); + + @Setter + @Getter + public static class Contact { + /** + * 作者 + */ + private String name; + + /** + * 个人网站 + */ + private String url; + + /** + * 邮箱 + */ + private String email; + } +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/config/securoty/CustomAccessDeniedHandler.java b/backend-src/src/main/java/com/taoes/simpledocker/config/securoty/CustomAccessDeniedHandler.java deleted file mode 100644 index 8b510475aa67250107efa6bef3f0a89ac7cebd84..0000000000000000000000000000000000000000 --- a/backend-src/src/main/java/com/taoes/simpledocker/config/securoty/CustomAccessDeniedHandler.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.taoes.simpledocker.config.securoty; - -import java.io.IOException; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.springframework.security.access.AccessDeniedException; -import org.springframework.security.web.access.AccessDeniedHandler; -import org.springframework.stereotype.Component; - -@Component -public class CustomAccessDeniedHandler implements AccessDeniedHandler { - - @Override - public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { - response.setCharacterEncoding("UTF-8"); - response.setContentType("application/json"); - response.getWriter().println("ERROR"); - response.getWriter().flush(); - } - -} \ No newline at end of file diff --git a/backend-src/src/main/java/com/taoes/simpledocker/config/securoty/CustomAuthenticationEntryPoint.java b/backend-src/src/main/java/com/taoes/simpledocker/config/securoty/CustomAuthenticationEntryPoint.java deleted file mode 100644 index 2cbb146a89059a0a9f1c579e3458473ed77755b4..0000000000000000000000000000000000000000 --- a/backend-src/src/main/java/com/taoes/simpledocker/config/securoty/CustomAuthenticationEntryPoint.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.taoes.simpledocker.config.securoty; - -import com.taoes.simpledocker.model.ResponseModel; -import com.taoes.simpledocker.utils.JsonUtils; -import java.io.IOException; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.springframework.security.core.AuthenticationException; -import org.springframework.security.web.AuthenticationEntryPoint; -import org.springframework.stereotype.Component; - -@Component -public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint { - - @Override - public void commence(HttpServletRequest httpServletRequest, - HttpServletResponse httpServletResponse, AuthenticationException e) - throws IOException, ServletException { - ResponseModel model = ResponseModel.fail(e.getMessage()); - model.setCode(401); - - httpServletResponse.setCharacterEncoding("UTF-8"); - httpServletResponse.setContentType("application/json"); - httpServletResponse.getWriter().println(JsonUtils.toJsonString(model)); - httpServletResponse.getWriter().flush(); - } -} \ No newline at end of file diff --git a/backend-src/src/main/java/com/taoes/simpledocker/config/securoty/JwtAuthenticationTokenFilter.java b/backend-src/src/main/java/com/taoes/simpledocker/config/securoty/JwtAuthenticationTokenFilter.java deleted file mode 100644 index ebb167d3663702ba458c6e2eb1d109f127c7ab91..0000000000000000000000000000000000000000 --- a/backend-src/src/main/java/com/taoes/simpledocker/config/securoty/JwtAuthenticationTokenFilter.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.taoes.simpledocker.config.securoty; - -import com.baomidou.mybatisplus.core.toolkit.StringUtils; -import java.io.IOException; -import javax.servlet.FilterChain; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import lombok.extern.slf4j.Slf4j; -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.core.userdetails.UserDetailsService; -import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; -import org.springframework.web.filter.OncePerRequestFilter; - -@Slf4j -public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { - - @Autowired - private JwtTokenUtil jwtTokenUtil; - @Autowired - private UserDetailsService userDetailsService; - - @Override - protected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException { - String authHeader = httpServletRequest.getHeader("Token"); - if (StringUtils.isNotBlank(authHeader) && authHeader.startsWith("Bearer ")) { - String authToken = authHeader.substring("Bearer ".length()); - String username = jwtTokenUtil.getUserNameFromToken(authToken); - log.info("checking authentication " + username); - if (StringUtils.isNotBlank(username) && SecurityContextHolder.getContext().getAuthentication() == null) { - UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); - // 校验token - if (jwtTokenUtil.validateToken(authToken, userDetails)) { - UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( - userDetails, null, userDetails.getAuthorities()); - authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails( - httpServletRequest)); - log.info("authenticated user " + username + ", setting security context"); - SecurityContextHolder.getContext().setAuthentication(authentication); - } - } - } - filterChain.doFilter(httpServletRequest, httpServletResponse); - } -} \ No newline at end of file diff --git a/backend-src/src/main/java/com/taoes/simpledocker/config/securoty/JwtTokenUtil.java b/backend-src/src/main/java/com/taoes/simpledocker/config/securoty/JwtTokenUtil.java deleted file mode 100644 index 9536b5d7b9528fa96ed3d3b25cc94e9c5e042f35..0000000000000000000000000000000000000000 --- a/backend-src/src/main/java/com/taoes/simpledocker/config/securoty/JwtTokenUtil.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.taoes.simpledocker.config.securoty; - -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import lombok.extern.slf4j.Slf4j; -import org.springframework.security.core.userdetails.UserDetails; -import org.springframework.stereotype.Component; - -@Slf4j -@Component -public class JwtTokenUtil { - - private static final String CLAIM_KEY_USERNAME = "sub"; - private static final String CLAIM_KEY_CREATED = "created"; - - private String secret = " .signWith(SignatureAlgorithm.HS512, secret)"; - private Long expire = 60_000L; - - - /** - * 从token中获取登录用户名 - */ - public String getUserNameFromToken(String token) { - String username; - try { - Claims claims = getClaimsFromToken(token); - username = claims.getSubject(); - } catch (Exception e) { - username = null; - } - return username; - } - /** - * 校验token - */ - public boolean validateToken(String token, UserDetails userDetails) { - String username = getUserNameFromToken(token); - return username.equals(userDetails.getUsername()) && !isTokenExpired(token); - } - - /** - * 根据用户信息生成token - */ - public String generateToken(UserDetails userDetails) { - Map claims = new HashMap<>(); - claims.put(CLAIM_KEY_USERNAME, userDetails.getUsername()); - claims.put(CLAIM_KEY_CREATED, new Date()); - return generateToken(claims); - } - - /** - * 判断token是否已经失效 - */ - private boolean isTokenExpired(String token) { - Date expiredDate = getClaimsFromToken(token).getExpiration(); - return expiredDate.before(new Date()); - } - - private String generateToken(Map claims) { - return Jwts.builder() - .setClaims(claims) - .setExpiration(generateExpirationDate()) - //签名算法 - .signWith(SignatureAlgorithm.HS512, secret) - .compact(); - } - - /** - * 生成token的过期时间 - */ - private Date generateExpirationDate() { - return new Date(System.currentTimeMillis() + expire * 1000); - } - - private Claims getClaimsFromToken(String token) { - Claims claims = null; - try { - claims = Jwts.parser() - .setSigningKey(secret) - .parseClaimsJws(token) - .getBody(); - } catch (Exception e) { - log.info("JWT格式验证失败:{}",token); - } - return claims; - } -} \ No newline at end of file diff --git a/backend-src/src/main/java/com/taoes/simpledocker/config/securoty/WebSecurityConfig.java b/backend-src/src/main/java/com/taoes/simpledocker/config/securoty/WebSecurityConfig.java deleted file mode 100644 index 9bc113275dff1ae28e041c6078c8d602b81c4914..0000000000000000000000000000000000000000 --- a/backend-src/src/main/java/com/taoes/simpledocker/config/securoty/WebSecurityConfig.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.taoes.simpledocker.config.securoty; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.http.HttpMethod; -import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.core.userdetails.UserDetailsService; -import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; -import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; - -@Configuration -@EnableWebSecurity -@EnableGlobalMethodSecurity(prePostEnabled = true) -public class WebSecurityConfig extends WebSecurityConfigurerAdapter { - - @Autowired - private CustomAccessDeniedHandler customAccessDeniedHandler; - - @Autowired - private CustomAuthenticationEntryPoint customAuthenticationEntryPoint; - - @Autowired - private UserDetailsService userDetailsService; - - @Autowired - private BCryptPasswordEncoder bCryptPasswordEncoder; - - - // 设置 HTTP 验证规则 - @Override - protected void configure(HttpSecurity http) throws Exception { - http.csrf().disable()// 由于使用的是JWT,我们这里不需要csrf - .sessionManagement()// 基于token,所以不需要session - .sessionCreationPolicy(SessionCreationPolicy.STATELESS) - .and() - .authorizeRequests() - // 允许对于网站静态资源的无授权访问 - .antMatchers(HttpMethod.GET, - "/", - "/*.html", - "/favicon.ico", - "/**/*.html", - "/**/*.css", - "/**/*.js", - "/swagger-resources/**", - "/v2/api-docs/**" - ) - .permitAll() - // 对登录注册要允许匿名访问 - .antMatchers("/api/auth/login") - .permitAll() - //跨域请求会先进行一次options请求 - .antMatchers(HttpMethod.OPTIONS) - .permitAll() - //对于WS请求全部放过 - .antMatchers("/api/ws/**") - .permitAll() - .anyRequest()// 除上面外的所有请求全部需要鉴权认证 - .authenticated(); - // 禁用缓存 - http.headers().cacheControl(); - // 添加JWT filter - http.addFilterBefore(jwtAuthenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class); - //添加自定义未授权和未登录结果返回 - http.exceptionHandling() - .accessDeniedHandler(customAccessDeniedHandler) - .authenticationEntryPoint(customAuthenticationEntryPoint); - } - - // 该方法是登录的时候会进入 - @Override - public void configure(AuthenticationManagerBuilder auth) throws Exception { - auth - .userDetailsService(userDetailsService)// 设置UserDetailsService - .passwordEncoder(bCryptPasswordEncoder);// 使用BCrypt进行密码的hash - } - - /** - * JWT filter - */ - @Bean - public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter(){ - return new JwtAuthenticationTokenFilter(); - } - -} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/controller/AuthController.java b/backend-src/src/main/java/com/taoes/simpledocker/controller/AuthController.java index bfc30446b3ec6006fdf944b7f293bbb000ca3d16..812e44c065d78948655034a0acc7f009086f8fe6 100644 --- a/backend-src/src/main/java/com/taoes/simpledocker/controller/AuthController.java +++ b/backend-src/src/main/java/com/taoes/simpledocker/controller/AuthController.java @@ -4,6 +4,8 @@ import com.taoes.simpledocker.controller.auth.UserLoginRequest; import com.taoes.simpledocker.controller.auth.UserResetRequest; import com.taoes.simpledocker.model.ResponseModel; import com.taoes.simpledocker.service.AuthService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -16,6 +18,7 @@ import org.springframework.web.bind.annotation.RestController; * @author 枕上江南 zhoutao925638@vip.qq.com * @date 2021/12/4 11:35 下午 */ +@Api(tags = "认证") @RestController @RequestMapping("/api/auth") public class AuthController { @@ -23,6 +26,7 @@ public class AuthController { @Autowired private AuthService authService; + @ApiOperation("登录") @PostMapping("/login") public ResponseModel login(@RequestBody UserLoginRequest loginRequest) { final String username = loginRequest.getUsername(); @@ -32,9 +36,17 @@ public class AuthController { return ResponseModel.ok(token); } + @ApiOperation("登出") + @PostMapping("/logout") + public ResponseModel logout() { + this.authService.logout(); + return ResponseModel.ok(Boolean.TRUE); + } + /** * 重置密码 */ + @ApiOperation("重置密码") @PostMapping("/reset") public ResponseModel resetPassword(@RequestBody UserResetRequest request) { request.checkParam(); diff --git a/backend-src/src/main/java/com/taoes/simpledocker/controller/BaseController.java b/backend-src/src/main/java/com/taoes/simpledocker/controller/BaseController.java index 73c0f600ef6d3abe384e988b59bd906e8fd94ae4..c65b44923232ff1e8b91252d6fc90c74f72c2c99 100644 --- a/backend-src/src/main/java/com/taoes/simpledocker/controller/BaseController.java +++ b/backend-src/src/main/java/com/taoes/simpledocker/controller/BaseController.java @@ -1,26 +1,16 @@ package com.taoes.simpledocker.controller; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; import lombok.extern.slf4j.Slf4j; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.context.SecurityContextHolder; + +import java.util.Collections; +import java.util.List; @Slf4j public abstract class BaseController { - public List getAuthentication() { - Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); - Collection authorities = authentication.getAuthorities(); - List list = new ArrayList<>(); - for (GrantedAuthority grantedAuthority : authorities) { - log.info("权限列表:{}", grantedAuthority.getAuthority()); - list.add(grantedAuthority.getAuthority()); + public List getAuthentication() { + return Collections.emptyList(); } - return list; - } } diff --git a/backend-src/src/main/java/com/taoes/simpledocker/controller/RoleController.java b/backend-src/src/main/java/com/taoes/simpledocker/controller/RoleController.java new file mode 100644 index 0000000000000000000000000000000000000000..eea9a1d531cc5a2b97763dfa30a8db23510303c6 --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/controller/RoleController.java @@ -0,0 +1,133 @@ +package com.taoes.simpledocker.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.core.collection.CollUtil; +import com.google.common.collect.Lists; +import com.taoes.simpledocker.controller.request.role.RoleAddRequest; +import com.taoes.simpledocker.controller.request.role.RolePermissionSaveRequest; +import com.taoes.simpledocker.controller.request.role.RoleUpdateRequest; +import com.taoes.simpledocker.controller.response.role.PermissionGroupResponse; +import com.taoes.simpledocker.controller.response.role.PermissionResponse; +import com.taoes.simpledocker.controller.response.role.RoleResponse; +import com.taoes.simpledocker.model.PageModel; +import com.taoes.simpledocker.model.ResponseModel; +import com.taoes.simpledocker.model.Role; +import com.taoes.simpledocker.model.enums.PermissionEnum; +import com.taoes.simpledocker.model.enums.PermissionGroupEnum; +import com.taoes.simpledocker.model.exception.DataNotFoundException; +import com.taoes.simpledocker.service.RoleService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.constraints.Max; +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author manwang (569258yin) + * @date 2022/7/13 22:38 + */ +@Api(tags = "角色管理") +@RestController +@RequestMapping("api/role") +public class RoleController { + + @Autowired + private RoleService roleService; + + @ApiOperation("分页查询角色信息") + @SaCheckPermission(value = "role:query", orRole = Role.ADMIN_ROLE_NAME) + @GetMapping("list") + public ResponseModel> list(@Validated @NotNull @Min(1) @RequestParam("pageNum") Integer pageNum, + @NotNull @Min(1) @Max(100) @RequestParam("pageSize") Integer pageSize) { + PageModel pageModel = roleService.pageList(pageNum, pageSize); + PageModel pageResponse = PageModel.convertResultObj(pageModel, RoleResponse::factory); + return ResponseModel.ok(pageResponse); + } + + @ApiOperation("新增角色") + @SaCheckPermission(value = "role:add", orRole = Role.ADMIN_ROLE_NAME) + @PostMapping() + public ResponseModel addRole(@Validated @RequestBody RoleAddRequest request) { + Role role = new Role(); + role.setName(request.getName()); + role.setComment(request.getComment()); + roleService.addRole(role); + return ResponseModel.ok(true); + } + + @ApiOperation("修改角色信息") + @SaCheckPermission(value = "role:update", orRole = Role.ADMIN_ROLE_NAME) + @PutMapping() + public ResponseModel updateRole(@Validated @RequestBody RoleUpdateRequest request) { + Role role = new Role(); + role.setId(request.getId()); + role.setName(request.getName()); + role.setComment(request.getComment()); + roleService.updateRole(role); + return ResponseModel.ok(true); + } + + @ApiOperation("删除角色信息") + @SaCheckPermission(value = "role:delete", orRole = Role.ADMIN_ROLE_NAME) + @DeleteMapping + public ResponseModel deleteRole(@Validated @NotNull @Min(1) @RequestParam("id") Integer id) { + roleService.deleteRole(id); + return ResponseModel.ok(true); + } + + @ApiOperation("获取权限配置列表") + @GetMapping("/permission/config") + public ResponseModel> getPermissionConfig() { + Map> groupPermissionMap = PermissionEnum.getGroupPermission(); + List responses = Lists.newArrayListWithCapacity(groupPermissionMap.size()); + groupPermissionMap.forEach((groupId, list) -> { + PermissionGroupEnum groupEnum = PermissionGroupEnum.getPermissionGroup(groupId); + if (groupEnum != PermissionGroupEnum.ADMIN) { + responses.add(PermissionGroupResponse.valueOf(groupEnum, list)); + } + }); + return ResponseModel.ok(responses); + } + + + @ApiOperation("获取当前角色下已配置的权限") + @SaCheckPermission(value = "role:permission:query", orRole = Role.ADMIN_ROLE_NAME) + @GetMapping("/permission/{id}") + public ResponseModel> getPermissionByRoleId(@PathVariable("id") Integer id) { + Role role = roleService.getById(id); + if (role == null) { + throw new DataNotFoundException("角色不存在或已删除"); + } + if (CollUtil.isEmpty(role.getPermissions())) { + return ResponseModel.ok(Collections.emptyList()); + } + return ResponseModel.ok( + role.getPermissions().stream().map(PermissionResponse::valueOf).collect(Collectors.toList()) + ); + } + + @ApiOperation("变更角色权限") + @SaCheckPermission(value = "role:permission:save", orRole = Role.ADMIN_ROLE_NAME) + @PostMapping("/permission") + public ResponseModel savePermission(@Validated @RequestBody RolePermissionSaveRequest request) { + roleService.savePermission(request.getRoleId(), request.getPermissions()); + return ResponseModel.ok(true); + } + +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/controller/UserController.java b/backend-src/src/main/java/com/taoes/simpledocker/controller/UserController.java index d54c72921cc9992b31f703cb5115c7db3136cc3f..a02e40122fa76ea96f986737153276ebf8ace70a 100644 --- a/backend-src/src/main/java/com/taoes/simpledocker/controller/UserController.java +++ b/backend-src/src/main/java/com/taoes/simpledocker/controller/UserController.java @@ -1,31 +1,50 @@ package com.taoes.simpledocker.controller; +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.taoes.simpledocker.controller.request.user.UserAuthRoleRequest; import com.taoes.simpledocker.model.ResponseModel; +import com.taoes.simpledocker.model.Role; import com.taoes.simpledocker.model.User; import com.taoes.simpledocker.service.UserService; -import java.util.List; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.List; + /** * TODO: please input file info * * @author 枕上江南 zhoutao925638@vip.qq.com * @date 2021/12/4 11:35 下午 */ +@Api(tags = "用户管理") @RestController @RequestMapping("/api/user") public class UserController { - @Autowired - private UserService userService; + @Autowired + private UserService userService; + + @GetMapping + public ResponseModel> list() { + final List list = userService.list(); + return ResponseModel.ok(list); + } + + @ApiOperation("配置用户角色") + @SaCheckPermission(value = "user:authRole", orRole = Role.ADMIN_ROLE_NAME) + @PostMapping("auth_role") + public ResponseModel authRole(@Validated @RequestBody UserAuthRoleRequest request) { + userService.authRole(request.getUserId(), request.getRoleIds()); + return ResponseModel.ok(true); + } - @GetMapping - public ResponseModel> list() { - final List list = userService.list(); - return ResponseModel.ok(list); - } } diff --git a/backend-src/src/main/java/com/taoes/simpledocker/controller/request/package-info.java b/backend-src/src/main/java/com/taoes/simpledocker/controller/request/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..4db6e8644a5426ecf1a887f7d22def3616d85fc3 --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/controller/request/package-info.java @@ -0,0 +1,5 @@ +/** + * @author manwang (569258yin) + * @date 2022/7/13 22:46 + */ +package com.taoes.simpledocker.controller.request; \ No newline at end of file diff --git a/backend-src/src/main/java/com/taoes/simpledocker/controller/request/role/RoleAddRequest.java b/backend-src/src/main/java/com/taoes/simpledocker/controller/request/role/RoleAddRequest.java new file mode 100644 index 0000000000000000000000000000000000000000..12878f01fba0fed980588ff82b618a811138f248 --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/controller/request/role/RoleAddRequest.java @@ -0,0 +1,18 @@ +package com.taoes.simpledocker.controller.request.role; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +/** + * @author manwang (569258yin) + * @date 2022/7/13 22:40 + */ +@Data +public class RoleAddRequest { + + @NotBlank + private String name; + @NotBlank + private String comment; +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/controller/request/role/RolePermissionSaveRequest.java b/backend-src/src/main/java/com/taoes/simpledocker/controller/request/role/RolePermissionSaveRequest.java new file mode 100644 index 0000000000000000000000000000000000000000..869ade103286114d15c1c7155f3f83aa7aad074b --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/controller/request/role/RolePermissionSaveRequest.java @@ -0,0 +1,21 @@ +package com.taoes.simpledocker.controller.request.role; + +import lombok.Data; + +import javax.validation.constraints.Min; +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author manwang (569258yin) + * @date 2022/7/16 8:59 + */ +@Data +public class RolePermissionSaveRequest { + + @NotNull + @Min(1) + private Integer roleId; + @NotNull + private List permissions; +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/controller/request/role/RoleUpdateRequest.java b/backend-src/src/main/java/com/taoes/simpledocker/controller/request/role/RoleUpdateRequest.java new file mode 100644 index 0000000000000000000000000000000000000000..ae1404fff75907b747eedfdd73aaa1cb3f81a0c3 --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/controller/request/role/RoleUpdateRequest.java @@ -0,0 +1,21 @@ +package com.taoes.simpledocker.controller.request.role; + +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * @author manwang (569258yin) + * @date 2022/7/13 22:40 + */ +@Data +public class RoleUpdateRequest { + + @NotNull + private Integer id; + @NotBlank + private String name; + @NotBlank + private String comment; +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/controller/request/user/UserAuthRoleRequest.java b/backend-src/src/main/java/com/taoes/simpledocker/controller/request/user/UserAuthRoleRequest.java new file mode 100644 index 0000000000000000000000000000000000000000..a00f8bd125a241abc0fdb77414d57f66b0fac7bd --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/controller/request/user/UserAuthRoleRequest.java @@ -0,0 +1,18 @@ +package com.taoes.simpledocker.controller.request.user; + +import lombok.Data; + +import javax.validation.constraints.NotNull; +import java.util.List; + +/** + * @author manwang (569258yin) + * @date 2022/7/16 16:56 + */ +@Data +public class UserAuthRoleRequest { + @NotNull + private Long userId; + @NotNull + private List roleIds; +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/controller/response/package-info.java b/backend-src/src/main/java/com/taoes/simpledocker/controller/response/package-info.java new file mode 100644 index 0000000000000000000000000000000000000000..fa36d10a548039495bcdee9a14d0d0b01a19b2a5 --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/controller/response/package-info.java @@ -0,0 +1,5 @@ +/** + * @author manwang (569258yin) + * @date 2022/7/13 22:46 + */ +package com.taoes.simpledocker.controller.response; \ No newline at end of file diff --git a/backend-src/src/main/java/com/taoes/simpledocker/controller/response/role/PermissionGroupResponse.java b/backend-src/src/main/java/com/taoes/simpledocker/controller/response/role/PermissionGroupResponse.java new file mode 100644 index 0000000000000000000000000000000000000000..76b6c55c621514ef8861342d554e22ab115682d8 --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/controller/response/role/PermissionGroupResponse.java @@ -0,0 +1,29 @@ +package com.taoes.simpledocker.controller.response.role; + +import com.taoes.simpledocker.model.enums.PermissionEnum; +import com.taoes.simpledocker.model.enums.PermissionGroupEnum; +import lombok.Data; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author manwang (569258yin) + * @date 2022/7/16 8:38 + */ +@Data +public class PermissionGroupResponse { + + private Integer groupId; + private String groupName; + private List permissions; + + + public static PermissionGroupResponse valueOf(PermissionGroupEnum permissionGroup, List permissions) { + PermissionGroupResponse permissionGroupResponse = new PermissionGroupResponse(); + permissionGroupResponse.setGroupId(permissionGroup.getId()); + permissionGroupResponse.setGroupName(permissionGroup.getDesc()); + permissionGroupResponse.setPermissions(permissions.stream().map(PermissionResponse::valueOf).collect(Collectors.toList())); + return permissionGroupResponse; + } +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/controller/response/role/PermissionResponse.java b/backend-src/src/main/java/com/taoes/simpledocker/controller/response/role/PermissionResponse.java new file mode 100644 index 0000000000000000000000000000000000000000..c02807b2aeaf82152283e697ddf3b0866f689d85 --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/controller/response/role/PermissionResponse.java @@ -0,0 +1,29 @@ +package com.taoes.simpledocker.controller.response.role; + +import com.taoes.simpledocker.model.enums.PermissionEnum; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author manwang (569258yin) + * @date 2022/7/16 8:25 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class PermissionResponse { + + private Integer groupId; + private String permission; + private String permissionName; + + + public static PermissionResponse valueOf(PermissionEnum permissionEnum) { + PermissionResponse permissionResponse = new PermissionResponse(); + permissionResponse.setGroupId(permissionEnum.getGroupId()); + permissionResponse.setPermission(permissionEnum.getPermission()); + permissionResponse.setPermissionName(permissionEnum.getDesc()); + return permissionResponse; + } +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/controller/response/role/RoleResponse.java b/backend-src/src/main/java/com/taoes/simpledocker/controller/response/role/RoleResponse.java new file mode 100644 index 0000000000000000000000000000000000000000..8dd39c123cb2432b9b67138b69403eea2f2d07c3 --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/controller/response/role/RoleResponse.java @@ -0,0 +1,30 @@ +package com.taoes.simpledocker.controller.response.role; + +import com.taoes.simpledocker.model.Role; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author manwang (569258yin) + * @date 2022/7/13 22:46 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class RoleResponse { + + private Integer id; + private String name; + private String comment; + + public static RoleResponse factory(Role role) { + RoleResponse roleResponse = new RoleResponse(); + roleResponse.setId(role.getId()); + roleResponse.setName(role.getName()); + roleResponse.setComment(role.getComment()); + return roleResponse; + } +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/converter/UserConverter.java b/backend-src/src/main/java/com/taoes/simpledocker/converter/UserConverter.java index f840b1aef81ef33ff4d6933d74a9aa97598aa8c3..df0270765b62037518c0e290337c92b0f32debde 100644 --- a/backend-src/src/main/java/com/taoes/simpledocker/converter/UserConverter.java +++ b/backend-src/src/main/java/com/taoes/simpledocker/converter/UserConverter.java @@ -19,7 +19,7 @@ public class UserConverter extends AbstractConverter { public User from(UserDao userDao) { return new User() .setId(userDao.getId()) - .setUsername(userDao.getUsername()) + .setAccount(userDao.getAccount()) .setCreatedAt(TimeUtils.format(userDao.getCreatedAt())) .setUpdatedAt(TimeUtils.format(userDao.getUpdatedAt())); } diff --git a/backend-src/src/main/java/com/taoes/simpledocker/dao/bean/BaseDao.java b/backend-src/src/main/java/com/taoes/simpledocker/dao/bean/BaseDao.java new file mode 100644 index 0000000000000000000000000000000000000000..68cf381938a792457962f872a001735f0d309dff --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/dao/bean/BaseDao.java @@ -0,0 +1,19 @@ +package com.taoes.simpledocker.dao.bean; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import lombok.Data; + +/** + * @author manwang (569258yin) + * @date 2022/7/16 11:51 + */ +@Data +public class BaseDao { + + @TableId(type = IdType.AUTO) + protected Integer id; + @TableLogic + protected Integer deleted; +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/dao/bean/PermissionDao.java b/backend-src/src/main/java/com/taoes/simpledocker/dao/bean/PermissionDao.java new file mode 100644 index 0000000000000000000000000000000000000000..136f4f99cada0faff08d2fea1b7c8721f86a2918 --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/dao/bean/PermissionDao.java @@ -0,0 +1,28 @@ +package com.taoes.simpledocker.dao.bean; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @author manwang (569258yin) + * @date 2022/7/13 21:36 + */ +@Data +@TableName("permission") +public class PermissionDao extends BaseDao { + + private Integer roleId; + private String permission; + + public PermissionDao() { + } + + public PermissionDao(Integer roleId, String permission) { + this.roleId = roleId; + this.permission = permission; + } + + +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/dao/bean/RoleDao.java b/backend-src/src/main/java/com/taoes/simpledocker/dao/bean/RoleDao.java new file mode 100644 index 0000000000000000000000000000000000000000..5ddcc18d72f5ff667edd7eeaa75b0ac577f54cc5 --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/dao/bean/RoleDao.java @@ -0,0 +1,16 @@ +package com.taoes.simpledocker.dao.bean; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @author manwang (569258yin) + * @date 2022/7/13 21:36 + */ +@Data +@TableName("role") +public class RoleDao extends BaseDao { + + private String comment; + private String name; +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/dao/bean/UserDao.java b/backend-src/src/main/java/com/taoes/simpledocker/dao/bean/UserDao.java index 1f89275feb334a4b692edbf86ace5d1304cbadb2..11f64cb33f9e469bb074e1cdc137a1dcea9bb01c 100644 --- a/backend-src/src/main/java/com/taoes/simpledocker/dao/bean/UserDao.java +++ b/backend-src/src/main/java/com/taoes/simpledocker/dao/bean/UserDao.java @@ -1,11 +1,16 @@ package com.taoes.simpledocker.dao.bean; +import cn.hutool.core.collection.CollUtil; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; +import com.taoes.simpledocker.utils.JsonUtils; import lombok.Data; +import org.apache.commons.lang3.StringUtils; import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; /** * 用户DAO对象 @@ -23,7 +28,9 @@ public class UserDao { /** * 用户名 */ - private String username; + private String account; + + private String name; /** * 密文密码 @@ -35,6 +42,11 @@ public class UserDao { */ private String saltValue; + /** + * 权限数组 + */ + private String roleIds; + /** * 创建时间 */ @@ -44,4 +56,21 @@ public class UserDao { * 更新时间 */ private LocalDateTime updatedAt; + + + private static final String EMPTY_ARRAY = "[]"; + + public static List convertRoleStr2List(String roleIds) { + if (StringUtils.isBlank(roleIds)) { + return Collections.emptyList(); + } + return JsonUtils.jsonToList(roleIds, Integer.class); + } + + public static String convertRoleList2Str(List roleIds) { + if (CollUtil.isEmpty(roleIds)) { + return EMPTY_ARRAY; + } + return JsonUtils.toJsonString(roleIds); + } } diff --git a/backend-src/src/main/java/com/taoes/simpledocker/dao/mapper/PermissionMapper.java b/backend-src/src/main/java/com/taoes/simpledocker/dao/mapper/PermissionMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..37cd6d7bfba42adfdc6310d3979ca8857db36b23 --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/dao/mapper/PermissionMapper.java @@ -0,0 +1,15 @@ +package com.taoes.simpledocker.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.taoes.simpledocker.dao.bean.PermissionDao; +import org.apache.ibatis.annotations.Mapper; + +/** + * @author manwang (569258yin) + * @date 2022/7/13 21:36 + */ +@Mapper +public interface PermissionMapper extends BaseMapper { + + +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/dao/mapper/RoleMapper.java b/backend-src/src/main/java/com/taoes/simpledocker/dao/mapper/RoleMapper.java new file mode 100644 index 0000000000000000000000000000000000000000..18523a5df6469477889e94202c5bd93055cf013d --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/dao/mapper/RoleMapper.java @@ -0,0 +1,14 @@ +package com.taoes.simpledocker.dao.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.taoes.simpledocker.dao.bean.RoleDao; +import org.apache.ibatis.annotations.Mapper; + +/** + * @author manwang (569258yin) + * @date 2022/7/13 21:36 + */ +@Mapper +public interface RoleMapper extends BaseMapper { + +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/dao/responsity/PermissionRepository.java b/backend-src/src/main/java/com/taoes/simpledocker/dao/responsity/PermissionRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..da666fdff8a6ec9977e511316a1431c3155cc054 --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/dao/responsity/PermissionRepository.java @@ -0,0 +1,58 @@ +package com.taoes.simpledocker.dao.responsity; + +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.taoes.simpledocker.dao.bean.PermissionDao; +import com.taoes.simpledocker.dao.mapper.PermissionMapper; +import org.springframework.stereotype.Repository; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +/** + * @author manwang (569258yin) + * @date 2022/7/13 21:43 + */ +@Repository +public class PermissionRepository extends ServiceImpl { + + + public List getByIds(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return this.baseMapper.selectBatchIds(ids); + } + + public List getByRoleId(Integer roleId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(PermissionDao::getRoleId, roleId); + return this.baseMapper.selectList(wrapper); + } + + public List getByRoleIds(Collection roleIds) { + if (CollUtil.isEmpty(roleIds)) { + return Collections.emptyList(); + } + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.in(PermissionDao::getRoleId, roleIds); + return this.baseMapper.selectList(wrapper); + } + + public boolean savePermission(Integer roleId, List permissions) { + deleteByRoleId(roleId); + if (CollUtil.isEmpty(permissions)) { + return true; + } + return this.saveBatch(permissions); + } + + public void deleteByRoleId(Integer roleId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(PermissionDao::getRoleId, roleId); + this.baseMapper.delete(wrapper); + } + +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/dao/responsity/RoleRepository.java b/backend-src/src/main/java/com/taoes/simpledocker/dao/responsity/RoleRepository.java new file mode 100644 index 0000000000000000000000000000000000000000..c5c862d3800c743c0e3936db57d8217c82f52fef --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/dao/responsity/RoleRepository.java @@ -0,0 +1,48 @@ +package com.taoes.simpledocker.dao.responsity; + +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.taoes.simpledocker.dao.bean.RoleDao; +import com.taoes.simpledocker.dao.mapper.RoleMapper; +import org.springframework.stereotype.Repository; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +/** + * @author manwang (569258yin) + * @date 2022/7/13 21:41 + */ +@Repository +public class RoleRepository extends ServiceImpl { + + + public List getAll() { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + return this.baseMapper.selectList(wrapper); + } + + public boolean insertRole(RoleDao roleDao) { + return this.baseMapper.insert(roleDao) > 0; + } + + public boolean updateRole(RoleDao roleDao) { + return this.baseMapper.updateById(roleDao) > 0; + } + + public boolean deleteRole(Integer id) { + return this.baseMapper.deleteById(id) > 0; + } + + + public List getByIds(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.in(RoleDao::getId, ids); + return this.baseMapper.selectList(wrapper); + } +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/dao/responsity/UserRepository.java b/backend-src/src/main/java/com/taoes/simpledocker/dao/responsity/UserRepository.java index 7365b3c66c68a375cf4f72579579e972122d0681..8bd3af5525570838225460c32e5be7aea0d57833 100644 --- a/backend-src/src/main/java/com/taoes/simpledocker/dao/responsity/UserRepository.java +++ b/backend-src/src/main/java/com/taoes/simpledocker/dao/responsity/UserRepository.java @@ -1,13 +1,15 @@ package com.taoes.simpledocker.dao.responsity; -import java.util.Optional; - +import cn.hutool.core.lang.Assert; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.taoes.simpledocker.dao.bean.UserDao; import com.taoes.simpledocker.dao.mapper.UserMapper; import org.springframework.stereotype.Repository; +import java.util.List; +import java.util.Optional; + /** * UserRepository 对象¬ * @@ -25,8 +27,20 @@ public class UserRepository extends ServiceImpl { */ public Optional findByName(String username) { LambdaQueryWrapper wrapper = new LambdaQueryWrapper(); - wrapper.eq(UserDao::getUsername, username); + wrapper.eq(UserDao::getAccount, username); wrapper.orderByDesc(UserDao::getId); return Optional.ofNullable(this.getOne(wrapper)); } + + public boolean updatePasswd(UserDao user) { + Assert.notNull(user.getId()); + return this.updateById(user); + } + + public boolean updateRole(Long userId, List roleIds) { + UserDao userDao = new UserDao(); + userDao.setId(userId); + userDao.setRoleIds(UserDao.convertRoleList2Str(roleIds)); + return this.updateById(userDao); + } } diff --git a/backend-src/src/main/java/com/taoes/simpledocker/model/PageModel.java b/backend-src/src/main/java/com/taoes/simpledocker/model/PageModel.java new file mode 100644 index 0000000000000000000000000000000000000000..367a35225748cf417945d20030d95d73f6a9dc2d --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/model/PageModel.java @@ -0,0 +1,57 @@ +package com.taoes.simpledocker.model; + +import cn.hutool.core.collection.CollUtil; +import com.github.pagehelper.PageInfo; +import lombok.Data; + +import java.util.Collections; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * @author manwang (569258yin) + * @date 2022/7/14 21:16 + */ +@Data +public class PageModel { + + private Integer pages; + private Long total; + private boolean hasNext; + private boolean hasPrevious; + private Integer currentPage; + private List results; + + + public static PageModel valueOfByPageInfo(PageInfo

pageInfo, Function function) { + PageModel pageModel = new PageModel(); + pageModel.setPages(pageInfo.getPages()); + pageModel.setTotal(pageInfo.getTotal()); + pageModel.setHasNext(pageInfo.isHasNextPage()); + pageModel.setHasPrevious(pageInfo.isHasPreviousPage()); + pageModel.setCurrentPage(pageInfo.getPageNum()); + if (CollUtil.isEmpty(pageInfo.getList())) { + pageModel.setResults(Collections.emptyList()); + } else { + pageModel.setResults(pageInfo.getList().stream().map(function).collect(Collectors.toList())); + } + return pageModel; + } + + public static PageModel convertResultObj(PageModel

pageInfo, Function function) { + PageModel pageModel = new PageModel(); + pageModel.setPages(pageInfo.getPages()); + pageModel.setTotal(pageInfo.getTotal()); + pageModel.setHasNext(pageInfo.isHasNext()); + pageModel.setHasPrevious(pageInfo.isHasPrevious()); + pageModel.setCurrentPage(pageInfo.getCurrentPage()); + if (CollUtil.isEmpty(pageInfo.getResults())) { + pageModel.setResults(Collections.emptyList()); + } else { + pageModel.setResults(pageInfo.getResults().stream().map(function).collect(Collectors.toList())); + } + return pageModel; + } + +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/model/Role.java b/backend-src/src/main/java/com/taoes/simpledocker/model/Role.java new file mode 100644 index 0000000000000000000000000000000000000000..0e8c13748ef77b7454904c389bdf08bb3b784b26 --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/model/Role.java @@ -0,0 +1,77 @@ +package com.taoes.simpledocker.model; + +import cn.hutool.core.collection.CollUtil; +import com.taoes.simpledocker.dao.bean.PermissionDao; +import com.taoes.simpledocker.dao.bean.RoleDao; +import com.taoes.simpledocker.model.enums.PermissionEnum; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 角色领域模型 + * + * @author manwang (569258yin) + * @date 2022/7/13 21:55 + */ +@Data +@NoArgsConstructor +public class Role { + + public static final String ADMIN_ROLE_NAME = "admin"; + + private Integer id; + private String name; + private String comment; + private List permissions; + + + public RoleDao convertRoleDao() { + RoleDao roleDao = new RoleDao(); + roleDao.setId(this.id); + roleDao.setComment(this.comment); + roleDao.setName(this.name); + return roleDao; + } + + public static Role factoryRole(RoleDao roleDao) { + Role role = new Role(); + role.setId(roleDao.getId()); + role.setName(roleDao.getName()); + role.setComment(roleDao.getComment()); + role.setPermissions(Collections.emptyList()); + return role; + } + + public static Role factoryRole(RoleDao roleDao, List permissions) { + Role role = new Role(); + role.setId(roleDao.getId()); + role.setName(roleDao.getName()); + role.setComment(roleDao.getComment()); + role.setPermissions(convertPermission2Enum(permissions)); + return role; + } + + public static List factoryRoles(List roleDaoList, List permissionDaoList) { + Map> groupByRoleIdMap = permissionDaoList.stream().collect(Collectors.groupingBy(PermissionDao::getRoleId)); + return roleDaoList.stream().map(r -> factoryRole(r, groupByRoleIdMap.get(r))).collect(Collectors.toList()); + } + + public static List convertPermission2Enum(List permissions) { + if (CollUtil.isEmpty(permissions)) { + return Collections.emptyList(); + } + return permissions.stream().map(r -> PermissionEnum.getPermissionEnum(r.getPermission())).collect(Collectors.toList()); + } + + public static List getAllPermissions(List roles) { + if (CollUtil.isEmpty(roles)) { + return Collections.emptyList(); + } + return roles.stream().flatMap(r -> r.getPermissions().stream().map(PermissionEnum::getPermission)).distinct().collect(Collectors.toList()); + } +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/model/User.java b/backend-src/src/main/java/com/taoes/simpledocker/model/User.java index cbe4917a6bd69d4b231a385cdff0ef331058ba23..4447b9e8035aee5c296340bdc7dfeb50a3e8aaa1 100644 --- a/backend-src/src/main/java/com/taoes/simpledocker/model/User.java +++ b/backend-src/src/main/java/com/taoes/simpledocker/model/User.java @@ -12,22 +12,27 @@ import lombok.Data; public class User { - private Long id; + private Long id; - /** - * 用户名 - */ - private String username; + /** + * 用户账号 + */ + private String account; + /** + * 用户名 + */ + private String name; - /** - * 创建时间 - */ - private String createdAt; - /** - * 更新时间 - */ - private String updatedAt; + /** + * 创建时间 + */ + private String createdAt; + + /** + * 更新时间 + */ + private String updatedAt; } diff --git a/backend-src/src/main/java/com/taoes/simpledocker/model/enums/PermissionEnum.java b/backend-src/src/main/java/com/taoes/simpledocker/model/enums/PermissionEnum.java new file mode 100644 index 0000000000000000000000000000000000000000..2f5a70d73283db6e985c8ed773f1cfed7e85edff --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/model/enums/PermissionEnum.java @@ -0,0 +1,70 @@ +package com.taoes.simpledocker.model.enums; + +import com.taoes.simpledocker.model.exception.ParamCheckException; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @author manwang (569258yin) + * @date 2022/7/13 21:57 + */ +@AllArgsConstructor +@Getter +public enum PermissionEnum { + + ADMIN(PermissionGroupEnum.ADMIN.getId(), "*", "超级管理员"), + + DOCKER_ENDPOINT_ADD(PermissionGroupEnum.DOCKER_ENDPOINT.getId(), "docker:endpoint:create", "新增docker节点"), + DOCKER_ENDPOINT_UPDATE(PermissionGroupEnum.DOCKER_ENDPOINT.getId(), "docker:endpoint:update", "修改docker节点"), + DOCKER_ENDPOINT_DELETE(PermissionGroupEnum.DOCKER_ENDPOINT.getId(), "docker:endpoint:delete", "删除docker节点"), + DOCKER_ENDPOINT_QUERY(PermissionGroupEnum.DOCKER_ENDPOINT.getId(), "docker:endpoint:query", "查看docker节点"), + + USER_ADD(PermissionGroupEnum.USER.getId(), "user:add", "新增用户"), + USER_UPDATE(PermissionGroupEnum.USER.getId(), "user:update", "修改用户"), + USER_DELETE(PermissionGroupEnum.USER.getId(), "user:delete", "删除用户"), + USER_QUERY(PermissionGroupEnum.USER.getId(), "user:query", "查看用户"), + USER_AUTH_ROLE(PermissionGroupEnum.USER.getId(), "user:authRole", "编辑用户角色"), + + ROLE_ADD(PermissionGroupEnum.ROLE.getId(), "role:add", "新增角色信息"), + ROLE_UPDATE(PermissionGroupEnum.ROLE.getId(), "role:update", "修改角色信息"), + ROLE_DELETE(PermissionGroupEnum.ROLE.getId(), "role:delete", "删除角色信息"), + ROLE_QUERY(PermissionGroupEnum.ROLE.getId(), "role:query", "查看角色信息"), + ROLE_PERMISSION_QUERY(PermissionGroupEnum.ROLE.getId(), "role:permission:query", "查看角色权限"), + ROLE_PERMISSION_SAVE(PermissionGroupEnum.ROLE.getId(), "role:permission:save", "修改角色权限"), + ; + + private static final Map INNER_MAP = new HashMap<>(); + + static { + for (PermissionEnum value : PermissionEnum.values()) { + INNER_MAP.put(value.permission, value); + } + } + + private final Integer groupId; + private final String permission; + private final String desc; + + + public static PermissionEnum getPermissionEnum(String permission) { + PermissionEnum permissionEnum = INNER_MAP.get(permission); + if (permissionEnum == null) { + throw new ParamCheckException("权限不正确"); + } + return permissionEnum; + } + + public static Map> getGroupPermission() { + return INNER_MAP.values().stream().collect(Collectors.groupingBy(PermissionEnum::getGroupId)); + } + + @Override + public String toString() { + return this.permission; + } +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/model/enums/PermissionGroupEnum.java b/backend-src/src/main/java/com/taoes/simpledocker/model/enums/PermissionGroupEnum.java new file mode 100644 index 0000000000000000000000000000000000000000..0c922b28b1bf8af7e113c3a1807f1394d09a7f31 --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/model/enums/PermissionGroupEnum.java @@ -0,0 +1,44 @@ +package com.taoes.simpledocker.model.enums; + +import com.taoes.simpledocker.model.exception.ParamCheckException; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author manwang (569258yin) + * @date 2022/7/13 21:57 + */ +@AllArgsConstructor +@Getter +public enum PermissionGroupEnum { + + ADMIN(0, "超级管理员"), + DOCKER_ENDPOINT(1, "容器资源"), + USER(21, "用户"), + ROLE(22, "角色"), + ; + + private static final Map INNER_MAP = new HashMap<>(); + + static { + for (PermissionGroupEnum value : PermissionGroupEnum.values()) { + INNER_MAP.put(value.id, value); + } + } + + private final Integer id; + private final String desc; + + + public static PermissionGroupEnum getPermissionGroup(Integer groupId) { + PermissionGroupEnum permissionEnum = INNER_MAP.get(groupId); + if (permissionEnum == null) { + throw new ParamCheckException("权限分组不正确"); + } + return permissionEnum; + } + +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/model/exception/AuthFailException.java b/backend-src/src/main/java/com/taoes/simpledocker/model/exception/AuthFailException.java new file mode 100644 index 0000000000000000000000000000000000000000..26f1830948092fee651a0ea7b5be4d14c53e9502 --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/model/exception/AuthFailException.java @@ -0,0 +1,19 @@ +package com.taoes.simpledocker.model.exception; + +import com.taoes.simpledocker.model.exception.BaseBizException; +import lombok.Data; + +@Data +public class AuthFailException extends BaseBizException { + + public AuthFailException() { + } + + public AuthFailException(String message) { + super(message); + } + + public AuthFailException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/model/exception/BaseBizException.java b/backend-src/src/main/java/com/taoes/simpledocker/model/exception/BaseBizException.java index 043ff61ec7e8ca862fe5aca97d87e17534d158a9..f5e38c60b3fefdcdafde1abe53829e502df7e6d2 100644 --- a/backend-src/src/main/java/com/taoes/simpledocker/model/exception/BaseBizException.java +++ b/backend-src/src/main/java/com/taoes/simpledocker/model/exception/BaseBizException.java @@ -12,4 +12,8 @@ public abstract class BaseBizException extends RuntimeException { public BaseBizException(String message) { super(message); } + + public BaseBizException(String message, Throwable cause) { + super(message, cause); + } } diff --git a/backend-src/src/main/java/com/taoes/simpledocker/model/exception/DataNotFoundException.java b/backend-src/src/main/java/com/taoes/simpledocker/model/exception/DataNotFoundException.java new file mode 100644 index 0000000000000000000000000000000000000000..3f41cdd618b6224d0dc0c5996a8c6c4f9cfde1cd --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/model/exception/DataNotFoundException.java @@ -0,0 +1,14 @@ +package com.taoes.simpledocker.model.exception; + +/** + * 数据未查到错误 + */ +public class DataNotFoundException extends BaseBizException { + + public DataNotFoundException() { + } + + public DataNotFoundException(String message) { + super(message); + } +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/model/exception/OperateFailException.java b/backend-src/src/main/java/com/taoes/simpledocker/model/exception/OperateFailException.java new file mode 100644 index 0000000000000000000000000000000000000000..ae5568888a9a561d48fc28f5ced6f0b1cd5293e9 --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/model/exception/OperateFailException.java @@ -0,0 +1,14 @@ +package com.taoes.simpledocker.model.exception; + +/** + * 操作失败异常 + */ +public class OperateFailException extends BaseBizException { + + public OperateFailException() { + } + + public OperateFailException(String message) { + super(message); + } +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/service/AuthService.java b/backend-src/src/main/java/com/taoes/simpledocker/service/AuthService.java index a0d530c1a35e4096dadabf9286e4fa6362b459f6..0e8b7e5c900a3cc5e09d7b3e9ab8a320915c10cd 100644 --- a/backend-src/src/main/java/com/taoes/simpledocker/service/AuthService.java +++ b/backend-src/src/main/java/com/taoes/simpledocker/service/AuthService.java @@ -16,6 +16,8 @@ public interface AuthService { */ String login(String username, String password); + void logout(); + /** * 重置密码 * diff --git a/backend-src/src/main/java/com/taoes/simpledocker/service/RoleService.java b/backend-src/src/main/java/com/taoes/simpledocker/service/RoleService.java new file mode 100644 index 0000000000000000000000000000000000000000..7b0694ad14808b2d5eacc999902734238c960ad6 --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/service/RoleService.java @@ -0,0 +1,28 @@ +package com.taoes.simpledocker.service; + +import com.taoes.simpledocker.model.PageModel; +import com.taoes.simpledocker.model.Role; + +import java.util.List; + +/** + * @author manwang (569258yin) + * @date 2022/7/13 21:53 + */ +public interface RoleService { + + PageModel pageList(Integer pageNum, Integer pageSize); + + void addRole(Role role); + + void updateRole(Role role); + + void deleteRole(Integer id); + + Role getById(Integer id); + + List getByIds(List ids); + + + void savePermission(Integer roleId, List permissions); +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/service/UserService.java b/backend-src/src/main/java/com/taoes/simpledocker/service/UserService.java index 0705fa25b7a85356fee3ff07fe9efbfa6568d532..9d50fe4e9c4d1b85a4fd7aa9904dbcb72da9aeba 100644 --- a/backend-src/src/main/java/com/taoes/simpledocker/service/UserService.java +++ b/backend-src/src/main/java/com/taoes/simpledocker/service/UserService.java @@ -1,6 +1,7 @@ package com.taoes.simpledocker.service; +import com.taoes.simpledocker.model.Role; import com.taoes.simpledocker.model.User; import java.util.List; @@ -35,4 +36,8 @@ public interface UserService { void enabled(Long id); List list(); + + void authRole(Long userId, List roleIds); + + List getUserRoles(Long userId); } diff --git a/backend-src/src/main/java/com/taoes/simpledocker/service/auth/UserDetailService.java b/backend-src/src/main/java/com/taoes/simpledocker/service/auth/UserDetailService.java deleted file mode 100644 index 4341960c62a42e2ed62d47ea4a8dbb24ba6bbb07..0000000000000000000000000000000000000000 --- a/backend-src/src/main/java/com/taoes/simpledocker/service/auth/UserDetailService.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.taoes.simpledocker.service.auth; - -import com.taoes.simpledocker.dao.bean.UserDao; -import com.taoes.simpledocker.dao.responsity.UserRepository; -import java.util.Collections; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.core.userdetails.User; -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; - -@Slf4j -@Service -public class UserDetailService implements UserDetailsService { - - @Autowired - private UserRepository userRepository; - - @Override - public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { - final UserDao userDao = userRepository.findByName(username).orElse(null); - return new User(userDao.getUsername(), userDao.getPassword(), Collections.emptyList()); - } -} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/service/imple/AuthServiceImpl.java b/backend-src/src/main/java/com/taoes/simpledocker/service/imple/AuthServiceImpl.java index e95b5925ecc76614c052769d5c7c5b371710555d..04bbfa6f471f8a809332e5ae66799bcf61b8a184 100644 --- a/backend-src/src/main/java/com/taoes/simpledocker/service/imple/AuthServiceImpl.java +++ b/backend-src/src/main/java/com/taoes/simpledocker/service/imple/AuthServiceImpl.java @@ -1,18 +1,19 @@ package com.taoes.simpledocker.service.imple; -import com.taoes.simpledocker.config.securoty.JwtTokenUtil; -import java.util.Collections; -import java.util.Objects; -import java.util.Optional; - +import cn.dev33.satoken.stp.StpUtil; +import com.taoes.simpledocker.model.exception.AuthFailException; import com.taoes.simpledocker.dao.bean.UserDao; import com.taoes.simpledocker.dao.responsity.UserRepository; +import com.taoes.simpledocker.model.exception.DataNotFoundException; import com.taoes.simpledocker.service.AuthService; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.security.core.userdetails.User; +import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; +import java.util.Objects; +import java.util.Optional; + //import org.springframework.security.core.GrantedAuthority; /** @@ -28,52 +29,48 @@ public class AuthServiceImpl implements AuthService { private final UserRepository userRepository; - private final JwtTokenUtil tokenUtil; - @Override public String login(String username, String password) { // 查询用户信息 final Optional userOptional = userRepository.findByName(username); if (!userOptional.isPresent()) { log.warn("用户:{}登录失败,该用户不存在", username); - throw new RuntimeException("用户名和密码不匹配"); + throw new DataNotFoundException("用户名和密码不匹配"); } final UserDao user = userOptional.get(); // 比对用户信息 if (!Objects.equals(user.getPassword(), password)) { log.warn("用户:{}登录失败,密码不正确", username); - throw new RuntimeException("用户名和密码不匹配"); + throw new AuthFailException("用户名和密码不匹配"); } + StpUtil.login(user.getId()); + return StpUtil.getTokenValue(); + } - // 生成token - return tokenUtil.generateToken(new User(username,user.getPassword(), Collections.emptyList()));//createNewToken(username, new ArrayList<>()); + @Override + public void logout() { + log.info("id = {} 退出登录", StpUtil.getLoginIdDefaultNull()); + StpUtil.logout(); } + @Override public void reset(String username, String password, String newPassword) { - log.info("准备重置密码:{}", username); - // TODO 江南 重置密码 + final Optional userOptional = userRepository.findByName(username); + if (!userOptional.isPresent()) { + log.warn("用户:{}登录失败,该用户不存在", username); + throw new DataNotFoundException("用户不存在或已删除"); + } + final UserDao user = userOptional.get(); + if (!StringUtils.equals(user.getPassword(), password)) { + log.warn("用户:{} 密码验证失败", username); + throw new AuthFailException("原始密码不正确"); + } + user.setPassword(newPassword); + userRepository.updatePasswd(user); + StpUtil.logout(); } - //private String createNewToken(String username, Collection authorities) { - // // 定义存放角色集合的对象 - // List roleList = new ArrayList<>(); - // for (GrantedAuthority grantedAuthority : authorities) { - // roleList.add(grantedAuthority.getAuthority()); - // } - // - // // 生成token start - // Calendar calendar = Calendar.getInstance(); - // Date now = calendar.getTime(); - // calendar.setTime(new Date()); - // calendar.add(Calendar.HOUR, 2); - // Date time = calendar.getTime(); - // return Jwts.builder() - // .setSubject(username) - // .setIssuedAt(now) - // .setExpiration(time) - // .signWith(SignatureAlgorithm.HS512, "SIGNING_KEY") - // .compact(); - //} + } diff --git a/backend-src/src/main/java/com/taoes/simpledocker/service/imple/RoleServiceImpl.java b/backend-src/src/main/java/com/taoes/simpledocker/service/imple/RoleServiceImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..fc74a39597aafe746e860d708a62d474c51753dd --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/service/imple/RoleServiceImpl.java @@ -0,0 +1,120 @@ +package com.taoes.simpledocker.service.imple; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.ObjectUtil; +import com.github.pagehelper.PageInfo; +import com.github.pagehelper.page.PageMethod; +import com.google.common.collect.Lists; +import com.taoes.simpledocker.dao.bean.PermissionDao; +import com.taoes.simpledocker.dao.bean.RoleDao; +import com.taoes.simpledocker.dao.responsity.PermissionRepository; +import com.taoes.simpledocker.dao.responsity.RoleRepository; +import com.taoes.simpledocker.model.PageModel; +import com.taoes.simpledocker.model.Role; +import com.taoes.simpledocker.model.enums.PermissionEnum; +import com.taoes.simpledocker.model.exception.DataNotFoundException; +import com.taoes.simpledocker.model.exception.OperateFailException; +import com.taoes.simpledocker.model.exception.ParamCheckException; +import com.taoes.simpledocker.service.RoleService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author manwang (569258yin) + * @date 2022/7/13 21:53 + */ +@Service +public class RoleServiceImpl implements RoleService { + + @Autowired + private RoleRepository roleRepository; + @Autowired + private PermissionRepository permissionRepository; + + @Override + public PageModel pageList(Integer pageNum, Integer pageSize) { + PageMethod.startPage(pageNum, pageSize); + List roleDaoList = roleRepository.getAll(); + PageInfo pageInfo = new PageInfo<>(roleDaoList); + return PageModel.valueOfByPageInfo(pageInfo, Role::factoryRole); + } + + @Override + public void addRole(Role role) { + boolean result = roleRepository.insertRole(role.convertRoleDao()); + if (!result) { + throw new OperateFailException("保存角色失败"); + } + } + + @Override + public void updateRole(Role role) { + Assert.notNull(role.getId(), "参数不正确"); + checkRole(role.getId()); + boolean result = roleRepository.updateRole(role.convertRoleDao()); + if (!result) { + throw new OperateFailException("更新角色失败"); + } + } + + @Override + public void deleteRole(Integer id) { + checkRole(id); + boolean result = roleRepository.deleteRole(id); + if (!result) { + throw new OperateFailException("删除角色失败"); + } + } + + @Override + public Role getById(Integer id) { + RoleDao roleDao = roleRepository.getById(id); + if (ObjectUtil.isEmpty(roleDao)) { + return null; + } + List permissionDaoList = permissionRepository.getByRoleId(id); + return Role.factoryRole(roleDao, permissionDaoList); + } + + @Override + public List getByIds(List ids) { + List roleDaoList = roleRepository.getByIds(ids); + if (CollUtil.isEmpty(roleDaoList)) { + return Collections.emptyList(); + } + List dbRoleIds = roleDaoList.stream().map(RoleDao::getId).collect(Collectors.toList()); + List permissionDaoList = permissionRepository.getByRoleIds(dbRoleIds); + return Role.factoryRoles(roleDaoList, permissionDaoList); + } + + @Override + public void savePermission(Integer roleId, List permissions) { + checkRole(roleId); + for (String permission : permissions) { + PermissionEnum.getPermissionEnum(permission); + } + List permissionDaoList = Lists.newArrayListWithCapacity(permissions.size()); + for (String permission : permissions) { + permissionDaoList.add(new PermissionDao(roleId, permission)); + } + boolean result = permissionRepository.savePermission(roleId, permissionDaoList); + if (!result) { + throw new OperateFailException("更新角色权限失败"); + } + } + + private void checkRole(Integer id) { + RoleDao roleDao = roleRepository.getById(id); + if (roleDao == null) { + throw new DataNotFoundException("数据不存在或已删除"); + } + if (roleDao.getName().equals(Role.ADMIN_ROLE_NAME)) { + throw new ParamCheckException("超级管理员不能修改"); + } + } +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/service/imple/StpInterfaceImpl.java b/backend-src/src/main/java/com/taoes/simpledocker/service/imple/StpInterfaceImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..749ec7135f35d539e33c87e3db483ba49921f43d --- /dev/null +++ b/backend-src/src/main/java/com/taoes/simpledocker/service/imple/StpInterfaceImpl.java @@ -0,0 +1,44 @@ +package com.taoes.simpledocker.service.imple; + +import cn.dev33.satoken.stp.StpInterface; +import cn.hutool.core.collection.CollUtil; +import com.taoes.simpledocker.model.Role; +import com.taoes.simpledocker.service.UserService; +import org.apache.commons.lang3.math.NumberUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author manwang (569258yin) + * @date 2022/7/16 13:38 + */ +@Service +public class StpInterfaceImpl implements StpInterface { + + + @Autowired + private UserService userService; + + + @Override + public List getPermissionList(Object loginId, String loginType) { + List roles = userService.getUserRoles(NumberUtils.toLong(loginId.toString())); + if (CollUtil.isEmpty(roles)) { + return Collections.emptyList(); + } + return Role.getAllPermissions(roles); + } + + @Override + public List getRoleList(Object loginId, String loginType) { + List roles = userService.getUserRoles(NumberUtils.toLong(loginId.toString())); + if (CollUtil.isEmpty(roles)) { + return Collections.emptyList(); + } + return roles.stream().map(Role::getName).collect(Collectors.toList()); + } +} diff --git a/backend-src/src/main/java/com/taoes/simpledocker/service/imple/UserServiceImpl.java b/backend-src/src/main/java/com/taoes/simpledocker/service/imple/UserServiceImpl.java index 0aa10f79531001f88969258e9c68d5c088278cdd..5cc651b10633f3f86b9151bd1d5c6aacfcf43761 100644 --- a/backend-src/src/main/java/com/taoes/simpledocker/service/imple/UserServiceImpl.java +++ b/backend-src/src/main/java/com/taoes/simpledocker/service/imple/UserServiceImpl.java @@ -1,15 +1,25 @@ package com.taoes.simpledocker.service.imple; +import cn.hutool.core.collection.CollUtil; import com.taoes.simpledocker.converter.UserConverter; +import com.taoes.simpledocker.dao.bean.RoleDao; +import com.taoes.simpledocker.dao.bean.UserDao; +import com.taoes.simpledocker.dao.responsity.RoleRepository; import com.taoes.simpledocker.dao.responsity.UserRepository; +import com.taoes.simpledocker.model.Role; import com.taoes.simpledocker.model.User; +import com.taoes.simpledocker.model.exception.DataNotFoundException; +import com.taoes.simpledocker.model.exception.ParamCheckException; +import com.taoes.simpledocker.service.RoleService; import com.taoes.simpledocker.service.UserService; -import java.util.List; -import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + /** * 用户服务实现 * @@ -25,6 +35,12 @@ public class UserServiceImpl implements UserService { @Autowired private UserConverter userConverter; + + @Autowired + private RoleService roleService; + @Autowired + private RoleRepository roleRepository; + @Override public User findByName(String username) { @@ -45,4 +61,32 @@ public class UserServiceImpl implements UserService { public List list() { return userRepository.list().stream().map(userConverter::from).collect(Collectors.toList()); } + + @Override + public void authRole(Long userId, List roleIds) { + UserDao user = userRepository.getById(userId); + if (user == null) { + throw new DataNotFoundException("用户不存在或已删除"); + } + if (CollUtil.isNotEmpty(roleIds)) { + List roleDaoList = roleRepository.getByIds(roleIds); + if (roleDaoList.size() != roleIds.size()) { + throw new ParamCheckException("角色信息有误"); + } + } + userRepository.updateRole(userId, roleIds); + } + + @Override + public List getUserRoles(Long userId) { + UserDao user = userRepository.getById(userId); + if (user == null) { + throw new DataNotFoundException("用户不存在或已删除"); + } + List roleIds = UserDao.convertRoleStr2List(user.getRoleIds()); + if (CollUtil.isEmpty(roleIds)) { + return Collections.emptyList(); + } + return roleService.getByIds(roleIds); + } } diff --git a/backend-src/src/main/java/com/taoes/simpledocker/utils/JsonUtils.java b/backend-src/src/main/java/com/taoes/simpledocker/utils/JsonUtils.java index 8a061d00d77513f619bdb05d56dd59124152309c..6ee285626ae3b7ceab14c41468c4d0ec47c79758 100644 --- a/backend-src/src/main/java/com/taoes/simpledocker/utils/JsonUtils.java +++ b/backend-src/src/main/java/com/taoes/simpledocker/utils/JsonUtils.java @@ -1,7 +1,12 @@ package com.taoes.simpledocker.utils; import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +import java.util.List; /** * TODO: please input file info @@ -9,9 +14,10 @@ import com.fasterxml.jackson.databind.ObjectMapper; * @author 枕上江南 zhoutao925638@vip.qq.com * @date 2021/12/9 10:33 下午 */ +@Slf4j public class JsonUtils { - private final static ObjectMapper mapper = new ObjectMapper(); + private final static ObjectMapper MAPPER = new ObjectMapper(); static { @@ -19,10 +25,34 @@ public class JsonUtils { public static String toJsonString(Object obj) { try { - return mapper.writeValueAsString(obj); + return MAPPER.writeValueAsString(obj); } catch (JsonProcessingException e) { - e.printStackTrace(); - return ""; + log.error("{}对象转json字符串失败", obj, e); + return StringUtils.EMPTY; + } + } + + /** + * 将json数据转换成pojo对象list + *

Title: jsonToList

+ *

Description:

+ * + * @param jsonData + * @param beanType + * @return + */ + public static List jsonToList(String jsonData, Class beanType) { + JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType); + try { + return MAPPER.readValue(jsonData, javaType); + } catch (Exception e) { + log.error("解析json出错json={}", jsonData, e); } + + return null; + } + + private static JavaType getJavaType(Class clas, Class... parameterClasses) { + return MAPPER.getTypeFactory().constructParametricType(clas, parameterClasses); } } diff --git a/backend-src/src/main/resources/application-dev.yaml b/backend-src/src/main/resources/application-dev.yaml index 55e0aa5d206d489e99f0b7610c3e55f9a2d05021..4cb014c6777d5e9c35207b4e5cd2e2a914653aa2 100644 --- a/backend-src/src/main/resources/application-dev.yaml +++ b/backend-src/src/main/resources/application-dev.yaml @@ -6,3 +6,6 @@ spring: username: root password: admin123 driver-class-name: com.mysql.cj.jdbc.Driver + +swagger: + production: false diff --git a/backend-src/src/main/resources/application.yaml b/backend-src/src/main/resources/application.yaml index d769067c7c7aa8bcf5af38785ad091104426af2f..2efd1c185712815f4554adcbf7fcec5c313851c1 100644 --- a/backend-src/src/main/resources/application.yaml +++ b/backend-src/src/main/resources/application.yaml @@ -1,3 +1,26 @@ spring: profiles: - active: @profile.active@ \ No newline at end of file + active: @profile.active@ + mvc: + pathmatch: + matching-strategy: ant_path_matcher + +# Sa-Token配置 +sa-token: + # token 名称 (同时也是cookie名称) + token-name: Token + # token 有效期,单位s 默认30天, -1代表永不过期 + timeout: 2592000 + # token 临时有效期 (指定时间内无操作就视为token过期) 单位: 秒 + activity-timeout: -1 + # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录) + is-concurrent: true + # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token) + is-share: false + # token风格 + token-style: random-128 + # 是否输出操作日志 + is-log: false + # token前缀 + token-prefix: Bearer + diff --git a/database/update.sql b/database/update.sql new file mode 100644 index 0000000000000000000000000000000000000000..918d8ea790a2b27b67619738272c9effa29fb7b1 --- /dev/null +++ b/database/update.sql @@ -0,0 +1,32 @@ +#### 用户权限相关改动 +CREATE TABLE `role` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(64) NOT NULL, + `comment` varchar(255) DEFAULT NULL COMMENT '描述', + `deleted` tinyint(1) NOT NULL DEFAULT '0' COMMENT '逻辑删除', + `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_at` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + UNIQUE KEY `uk_name` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `permission` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT, + `permission` varchar(255) NOT NULL, + `role_id` int(11) NOT NULL, + `deleted` tinyint(1) NOT NULL DEFAULT '0', + `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_at` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + KEY `idx_role` (`role_id`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +ALTER TABLE `user` + CHANGE COLUMN `username` `account` varchar(128) NOT NULL COMMENT '账号' AFTER `id`, + ADD COLUMN `role_ids` varchar(255) NOT NULL DEFAULT '[]' COMMENT '角色数组' AFTER `salt_value`, + ADD COLUMN `deleted` tinyint(1) NOT NULL DEFAULT '0', + ADD COLUMN `name` varchar(64) NULL COMMENT '昵称' AFTER `id`; + +INSERT INTO `sd`.`role` (`id`, `name`, `comment`, `deleted`) VALUES (1, 'admin', '超级管理员', 0); + +