diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml new file mode 100644 index 0000000..c6c8a29 --- /dev/null +++ b/.github/workflows/docker-publish.yml @@ -0,0 +1,123 @@ +name: Docker Build and Publish + +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +on: + push: + branches: [ "main" ] + # Publish semver tags as releases. + tags: [ 'v*.*.*' ] + pull_request: + branches: [ "main" ] + +env: + # Use docker.io for Docker Hub if empty + REGISTRY: ghcr.io + # github.repository as / + IMAGE_NAME: ${{ github.repository }} + + +jobs: + build: + + runs-on: ubuntu-latest + permissions: + contents: write + packages: write + # This is used to complete the identity challenge + # with sigstore/fulcio when running outside of PRs. + id-token: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + # Install the cosign tool except on PR + # https://github.com/sigstore/cosign-installer + - name: Install cosign + if: github.event_name != 'pull_request' + uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 #v3.5.0 + with: + cosign-release: 'v2.2.4' + + # Set up BuildKit Docker container builder to be able to build + # multi-platform images and export cache + # https://github.com/docker/setup-buildx-action + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0 + + # Login against a Docker registry except on PR + # https://github.com/docker/login-action + - name: Log into registry ${{ env.REGISTRY }} + if: github.event_name != 'pull_request' + uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Get current date and commit ID + id: vars + run: | + echo "DATE=$(date +'%y%m%d')" >> $GITHUB_ENV + echo "COMMIT=$(git rev-parse --short HEAD)" >> $GITHUB_ENV + + # Extract metadata (tags, labels) for Docker + # https://github.com/docker/metadata-action + - name: Extract Docker metadata + id: meta + uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5.0.0 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: ${{ env.DATE }}-${{ env.COMMIT }} + + # Build and push Docker image with Buildx (don't push on PR) + # https://github.com/docker/build-push-action + - name: Build and push Docker image + id: build-and-push + uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5.0.0 + with: + context: . + push: ${{ github.event_name != 'pull_request' }} + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + cache-from: type=gha + cache-to: type=gha,mode=max + + # Sign the resulting Docker image digest except on PRs. + # This will only write to the public Rekor transparency log when the Docker + # repository is public to avoid leaking data. If you would like to publish + # transparency data even for private images, pass --force to cosign below. + # https://github.com/sigstore/cosign + - name: Sign the published Docker image + if: ${{ github.event_name != 'pull_request' }} + env: + # https://docs.github.com/en/actions/security-guides/security-hardening-for-github-actions#using-an-intermediate-environment-variable + TAGS: ${{ steps.meta.outputs.tags }} + DIGEST: ${{ steps.build-and-push.outputs.digest }} + # This step uses the identity token to provision an ephemeral certificate + # against the sigstore community Fulcio instance. + run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST} + + - name: Checkout manifest + if: github.event_name == 'push' + uses: actions/checkout@v4 + with: + ref: manifest + - name: Update manifest + if: github.event_name == 'push' + uses: mikefarah/yq@master + with: + cmd: yq eval '.image.tag = "${{ steps.meta.outputs.version }}"' -i values.yaml + - name: Git Auto Commit + uses: stefanzweifel/git-auto-commit-action@v5.0.1 + with: + commit_message: "Update deployment image to ${{ steps.meta.outputs.version }}" + branch: manifest + commit_user_name: "github-actions[bot]" + commit_user_email: "github-actions[bot]@users.noreply.github.com" + commit_author: "github-actions[bot] " + diff --git a/.github/workflows/gitea-sync.yml b/.github/workflows/gitea-sync.yml new file mode 100644 index 0000000..cc1c271 --- /dev/null +++ b/.github/workflows/gitea-sync.yml @@ -0,0 +1,20 @@ +name: gitea-sync.yml +on: + push: + branches: [ "main", "manifest" ] + workflow_dispatch: + workflow_run: + workflows: ["Docker Build and Publish"] + types: + - completed + + +jobs: + trigger-gitea-sync: + runs-on: ubuntu-latest + steps: + - name: Trigger Gitea sync + run: | + echo "Triggering Gitea sync" + curl 'https://git.suyiiyii.top/api/v1/repos/ssyg/SIMS/mirror-sync' -X POST -H 'Authorization: token ${{ secrets.GITEATOKEN }}' + diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index ee4c4c8..df6813a 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -11,13 +11,21 @@ name: Java CI with Maven on: push: branches: [ "main" ] + paths: + - 'pom.xml' + - 'src/**' pull_request: branches: [ "main" ] + paths: + - 'pom.xml' + - 'src/**' jobs: build: runs-on: ubuntu-latest + permissions: + contents: write steps: - uses: actions/checkout@v4 @@ -34,5 +42,5 @@ jobs: # Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive -# - name: Update dependency graph -# uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6 + - name: Update dependency graph + uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6 diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8992df6 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,29 @@ +FROM maven:3.9-eclipse-temurin-17-alpine AS build + +WORKDIR /app + +COPY pom.xml ./pom.xml + +COPY src ./src + +RUN --mount=type=cache,target=/root/.m2 \ + mvn package -am -DskipTests + +RUN mkdir -p /layers && \ + cp /app/target/SIMS-0.0.1-SNAPSHOT.jar /layers/target.jar && \ + cd /layers && \ + java -Djarmode=layertools -jar /layers/target.jar extract + +FROM eclipse-temurin:17-jre AS runtime + +WORKDIR /app + +COPY --from=build /layers/dependencies/ . +COPY --from=build /layers/snapshot-dependencies/ . +COPY --from=build /layers/spring-boot-loader/ . +COPY --from=build /layers/application/ . + +EXPOSE 8080 + +# 执行命令 +ENTRYPOINT [ "java", "org.springframework.boot.loader.launch.JarLauncher" ] diff --git a/pom.xml b/pom.xml index 29aef43..4374986 100644 --- a/pom.xml +++ b/pom.xml @@ -144,6 +144,10 @@ lombok + + true + + diff --git a/src/main/java/top/suyiiyii/sims/common/AuthAccess.java b/src/main/java/top/suyiiyii/sims/common/AuthAccess.java index 65ad38f..9ec5ccd 100644 --- a/src/main/java/top/suyiiyii/sims/common/AuthAccess.java +++ b/src/main/java/top/suyiiyii/sims/common/AuthAccess.java @@ -14,4 +14,5 @@ import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) @Documented public @interface AuthAccess { + String[] allowRoles() default {}; } diff --git a/src/main/java/top/suyiiyii/sims/common/InterceptorConfig.java b/src/main/java/top/suyiiyii/sims/common/InterceptorConfig.java index 5becb7b..69a7ff4 100644 --- a/src/main/java/top/suyiiyii/sims/common/InterceptorConfig.java +++ b/src/main/java/top/suyiiyii/sims/common/InterceptorConfig.java @@ -1,16 +1,10 @@ package top.suyiiyii.sims.common; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import top.suyiiyii.sims.service.RoleService; -import top.suyiiyii.sims.service.UserService; -import top.suyiiyii.sims.utils.JwtUtils; /** * @Author tortoise @@ -20,63 +14,28 @@ import top.suyiiyii.sims.utils.JwtUtils; * @Description: TODO 拦截器配置 * @Version 1.0 */ - @Configuration - public class InterceptorConfig extends WebMvcConfigurationSupport { +@Configuration +public class InterceptorConfig extends WebMvcConfigurationSupport { @Autowired - private RoleService roleService; + private RoleService roleService; + @Autowired + private JwtInterceptor jwtInterceptor; + @Autowired + private RbacInterceptor rbacInterceptor; - //UserService userService; - @Override - protected void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(jwtInterceptor()) - .addPathPatterns("/**") - .excludePathPatterns("/user/login") // 排除不需要验证的路径 - .excludePathPatterns("/user/register") - .excludePathPatterns("/v3/api-docs/**"); + @Override + protected void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(jwtInterceptor) + .addPathPatterns("/**") + .excludePathPatterns("/v3/api-docs/**"); + registry.addInterceptor(rbacInterceptor) + .excludePathPatterns("/v3/api-docs/**"); - // 注册AdminInterceptor,只拦截以admin/开头的路径 - registry.addInterceptor(new AdminInterceptor()) - .addPathPatterns("/admin/**"); - super.addInterceptors(registry); - } - - @Bean - public JwtInterceptor jwtInterceptor() { - return new JwtInterceptor(); - } - - // AdminInterceptor的实现 - public class AdminInterceptor implements HandlerInterceptor { - @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { - String path = request.getRequestURI(); - if (path.startsWith("/admin/") && !hasAdminPermission(request)) { - // 如果用户没有管理员权限,返回403 Forbidden - response.setStatus(HttpServletResponse.SC_FORBIDDEN); - return false; - } - return true; - } - - private boolean hasAdminPermission(HttpServletRequest request) { - // 这里应该实现检查用户权限的逻辑 - // 例如,从session、token或者数据库中获取用户信息并判断权限 - // 以下仅为示例 - String token = (String) request.getAttribute("token"); - //非空 - if (token == null) { - return false; - } - try { - Integer userId = Integer.valueOf(JwtUtils.extractUserId(token)); - return roleService.isRoleNameAdmin(userId); - } catch (Exception e) { - // 处理令牌解析过程中可能出现的异常 - return false; - } - } - } + super.addInterceptors(registry); } + +} + diff --git a/src/main/java/top/suyiiyii/sims/common/JwtInterceptor.java b/src/main/java/top/suyiiyii/sims/common/JwtInterceptor.java index a946758..63b0254 100644 --- a/src/main/java/top/suyiiyii/sims/common/JwtInterceptor.java +++ b/src/main/java/top/suyiiyii/sims/common/JwtInterceptor.java @@ -1,16 +1,16 @@ package top.suyiiyii.sims.common; -import cn.hutool.core.util.StrUtil; -import jakarta.annotation.Resource; +import com.auth0.jwt.exceptions.TokenExpiredException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; -import org.springframework.web.method.HandlerMethod; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; -import top.suyiiyii.sims.entity.User; import top.suyiiyii.sims.exception.ServiceException; -import top.suyiiyii.sims.mapper.UserMapper; import top.suyiiyii.sims.utils.JwtUtils; +import java.util.Objects; + /** * @Author tortoise * @Date 2024/8/12 11:33 @@ -20,49 +20,39 @@ import top.suyiiyii.sims.utils.JwtUtils; * @Version 1.0 */ +@Component public class JwtInterceptor implements HandlerInterceptor { - @Resource - UserMapper userMapper; + @Value("${jwt.secret}") + private String secret; + @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + if ("/error".equals(request.getRequestURI())) { + return true; + } // 从 Authorization 头中获取 token String token = request.getHeader("Authorization"); if (token != null && token.startsWith("Bearer ")) { - token = token.substring(7); // 去除 "Bearer " 前缀 + token = token.substring(7); } else { - // 如果 Authorization 头中没有 token,则尝试从请求参数中获取 - token = request.getParameter("token"); - } - // 如果不是映射到方法直接通过 - if (handler instanceof HandlerMethod) { - AuthAccess annotation = ((HandlerMethod) handler).getMethodAnnotation(AuthAccess.class); - if (annotation != null) { - return true; - } - } - // 执行认证 - if (StrUtil.isBlank(token)) { - //权限错误 - throw new ServiceException("401", "请登录"); - } - // 获取 token 中的 user id - String userId= JwtUtils.extractUserId(token); - if (userId == null) { - throw new ServiceException("401", "请登录"); - } - - User user = userMapper.selectById(Integer.parseInt(userId)); - if (user == null) { - throw new ServiceException("401", "请登录"); + // 如果没有有效的token,设置userId为-1,表示未登录 + request.setAttribute("userId", -1); + return true; } // 验证 token 的有效性 - if (!JwtUtils.verifyToken(token, user.getPassword())) { - throw new ServiceException("401", "请登录"); + try { + if (!JwtUtils.verifyToken(token, secret) || JwtUtils.extractUserId(token) == null) { + throw new ServiceException("401", "登录已过期,请重新登录"); + } + } catch (TokenExpiredException e) { + throw new ServiceException("401", "登录已过期,请重新登录"); } - // 验证token后,如果一切正常,将token存储到request的属性中 - request.setAttribute("token", token); + // 获取 token 中的 user id + Integer userId = Integer.parseInt(Objects.requireNonNull(JwtUtils.extractUserId(token))); + + request.setAttribute("userId", userId); return true; } } diff --git a/src/main/java/top/suyiiyii/sims/common/ModelMapperConfig.java b/src/main/java/top/suyiiyii/sims/common/ModelMapperConfig.java index 3241164..ad495cf 100644 --- a/src/main/java/top/suyiiyii/sims/common/ModelMapperConfig.java +++ b/src/main/java/top/suyiiyii/sims/common/ModelMapperConfig.java @@ -4,8 +4,6 @@ import org.modelmapper.ModelMapper; import org.modelmapper.convention.MatchingStrategies; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import top.suyiiyii.sims.dto.RecordDto; -import top.suyiiyii.sims.entity.User; /** * @Author tortoise @@ -25,19 +23,20 @@ public class ModelMapperConfig { // 设置匹配策略为严格模式 modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); - // configureUser(modelMapper); - return modelMapper; + // configureUser(modelMapper); + return modelMapper; } + // 配置 User 类的映射规则 private void configureUser(ModelMapper modelMapper) { // 定义 UserModel -> User 的映射规则 - // modelMapper.typeMap(RecordDto.class, Record.class) + // modelMapper.typeMap(RecordDto.class, Record.class) // 跳过设置密码字段 // 定义 User -> UserModel 的映射规则 - // modelMapper.typeMap(User.class, RecordDto.class) - // .addMappings(mapper -> mapper.skip(RecordDto::setPassword)) // 跳过设置密码字段 - // .addMappings(mapper -> mapper.map(User::getRealName, UserModel::setName)); // 将 User 的 realName 映射为 UserModel 的 name + // modelMapper.typeMap(User.class, RecordDto.class) + // .addMappings(mapper -> mapper.skip(RecordDto::setPassword)) // 跳过设置密码字段 + // .addMappings(mapper -> mapper.map(User::getRealName, UserModel::setName)); // 将 User 的 realName 映射为 UserModel 的 name // .addMappings(mapper -> mapper.using(dateToStringConverter).map(User::getCreateTime, UserModel::setCreateTime)) // .addMappings(mapper -> mapper.using(dateToStringConverter).map(User::getUpdateTime, UserModel::setUpdateTime)); } diff --git a/src/main/java/top/suyiiyii/sims/common/RbacInterceptor.java b/src/main/java/top/suyiiyii/sims/common/RbacInterceptor.java new file mode 100644 index 0000000..35ec723 --- /dev/null +++ b/src/main/java/top/suyiiyii/sims/common/RbacInterceptor.java @@ -0,0 +1,64 @@ +package top.suyiiyii.sims.common; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; +import top.suyiiyii.sims.entity.Role; +import top.suyiiyii.sims.exception.ServiceException; +import top.suyiiyii.sims.service.RbacService; + +import java.util.List; + +/** + * Rbac 拦截器 + * 从请求对象中获取用户信息,然后判断用户是否有权限访问当前路径 + */ +@Component +public class RbacInterceptor implements HandlerInterceptor { + + @Autowired + RbacService rbacService; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { + if ("/error".equals(request.getRequestURI())) { + return true; + } + // 获取用户角色 + List roles = getUserRole(request).stream().map(Role::getRoleName).toList(); + + List allowRoles = null; + + // 获取当前请求的方法上的 AuthAccess 注解,从而获取允许访问的角色 + if (handler instanceof HandlerMethod) { + AuthAccess annotation = ((HandlerMethod) handler).getMethodAnnotation(AuthAccess.class); + if (annotation != null) { + allowRoles = List.of(annotation.allowRoles()); + } + } + + if (allowRoles != null && !allowRoles.isEmpty()) { + if (allowRoles.contains("guest")) { + return true; + } + for (String role : roles) { + if (allowRoles.contains(role)) { + return true; + } + } + } + throw new ServiceException("403", "权限不足"); + } + + private List getUserRole(HttpServletRequest request) { + Integer UserId = (Integer) request.getAttribute("userId"); + if (UserId == null || UserId == -1) { + return List.of(Role.guest()); + } + return rbacService.getRolesByUserId(UserId); + } + +} diff --git a/src/main/java/top/suyiiyii/sims/controller/AdminController.java b/src/main/java/top/suyiiyii/sims/controller/AdminController.java index d241e77..412dd6c 100644 --- a/src/main/java/top/suyiiyii/sims/controller/AdminController.java +++ b/src/main/java/top/suyiiyii/sims/controller/AdminController.java @@ -4,6 +4,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import top.suyiiyii.sims.common.AuthAccess; import top.suyiiyii.sims.common.Result; import top.suyiiyii.sims.dto.RecordDto; import top.suyiiyii.sims.entity.User; @@ -28,12 +29,14 @@ public class AdminController { @Autowired private UserService userService; + @AuthAccess(allowRoles = {"admin"}) @GetMapping("/findAllUsersWithRoles") public Result findAllUsersWithRoles() { List userList = roleService.findAllUsersWithRoles(); return Result.success(userList); } + @AuthAccess(allowRoles = {"admin"}) @GetMapping("/selectAll") public Result selectAll() { List users = userService.selectAll(); @@ -42,8 +45,8 @@ public class AdminController { } /** - request.setAttribute();lUsers(); - return Result.success(userList); - } -} -**/ \ No newline at end of file + * request.setAttribute();lUsers(); + * return Result.success(userList); + * } + * } + **/ \ No newline at end of file diff --git a/src/main/java/top/suyiiyii/sims/controller/HealthzController.java b/src/main/java/top/suyiiyii/sims/controller/HealthzController.java index e3724b2..34010a3 100644 --- a/src/main/java/top/suyiiyii/sims/controller/HealthzController.java +++ b/src/main/java/top/suyiiyii/sims/controller/HealthzController.java @@ -5,14 +5,17 @@ import lombok.Data; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RestController; +import top.suyiiyii.sims.common.AuthAccess; @RestController public class HealthzController { + @AuthAccess(allowRoles = {"guest"}) @GetMapping("/healthz") public String healthz() { return "ok"; } + @AuthAccess(allowRoles = {"guest"}) @PostMapping("/healthz") public HealthzResponse healthzPost() { return new HealthzResponse("health"); diff --git a/src/main/java/top/suyiiyii/sims/controller/HelloController.java b/src/main/java/top/suyiiyii/sims/controller/HelloController.java deleted file mode 100644 index 9962cad..0000000 --- a/src/main/java/top/suyiiyii/sims/controller/HelloController.java +++ /dev/null @@ -1,27 +0,0 @@ -package top.suyiiyii.sims.controller; - -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RestController; -import top.suyiiyii.sims.common.Result; - -import java.util.List; - -@RestController -public class HelloController { - - @GetMapping("/hello") - public String hello(String username) { - return "Hello " + username; - } - @PostMapping("/hello") - public List helloPost(String username , Integer age) { - List list = List.of(username,age.toString()); - return list; - } - @GetMapping("/helloResult") - public Result healthz() { - return Result.success("Hello World"); - } - -} diff --git a/src/main/java/top/suyiiyii/sims/controller/RecordController.java b/src/main/java/top/suyiiyii/sims/controller/RecordController.java index 792a846..287c961 100644 --- a/src/main/java/top/suyiiyii/sims/controller/RecordController.java +++ b/src/main/java/top/suyiiyii/sims/controller/RecordController.java @@ -1,34 +1,24 @@ package top.suyiiyii.sims.controller; -import com.auth0.jwt.JWT; -import com.auth0.jwt.exceptions.JWTDecodeException; -import com.auth0.jwt.interfaces.DecodedJWT; import io.swagger.v3.oas.annotations.Operation; - import jakarta.servlet.http.HttpServletRequest; import org.modelmapper.ModelMapper; import org.springframework.beans.factory.annotation.Autowired; - import org.springframework.web.bind.annotation.*; +import top.suyiiyii.sims.common.AuthAccess; import top.suyiiyii.sims.common.Result; import top.suyiiyii.sims.dto.CommonResponse; import top.suyiiyii.sims.dto.RecordDto; import top.suyiiyii.sims.entity.Record; -import top.suyiiyii.sims.entity.Role; -import top.suyiiyii.sims.entity.UserRole; -import top.suyiiyii.sims.mapper.CategoryMapper; -import top.suyiiyii.sims.mapper.UserMapper; import top.suyiiyii.sims.service.CategoryService; import top.suyiiyii.sims.service.RecordService; import top.suyiiyii.sims.service.RoleService; import top.suyiiyii.sims.service.UserService; import top.suyiiyii.sims.utils.JwtUtils; -import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; @RestController public class @@ -44,6 +34,7 @@ RecordController { @Autowired ModelMapper modelMapper; + @AuthAccess(allowRoles = {"admin"}) @Operation(summary = "获取所有奖惩记录") @GetMapping("/admin/record") public Result> adminRecord( @@ -55,40 +46,46 @@ RecordController { RecordDto recordDto = modelMapper.map(record, RecordDto.class); recordDto.setCategoryName(categoryService.getCategoryName(record.getCategoryId())); - recordDto.setSubCategoryName(categoryService.getsubCategoryName( record.getCategoryId())); + recordDto.setSubCategoryName(categoryService.getsubCategoryName(record.getCategoryId())); recordDtos.add(recordDto); } return Result.success(recordDtos); } + @AuthAccess(allowRoles = {"user"}) @Operation(summary = "获取自己的奖惩记录") @GetMapping("/record") public Result> record(@RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "10") int size, HttpServletRequest request) { String token = (String) request.getAttribute("token"); - String userId= JwtUtils.extractUserId(token); - List recordDtos=new ArrayList<>(); + String userId = JwtUtils.extractUserId(token); + List recordDtos = new ArrayList<>(); - List records = recordService.getMyAllRecords(page, size,userId); + List records = recordService.getMyAllRecords(page, size, userId); for (Record record : records) { RecordDto recordDto = modelMapper.map(record, RecordDto.class); recordDto.setCategoryName(categoryService.getCategoryName(record.getCategoryId())); - recordDto.setSubCategoryName(categoryService.getsubCategoryName( record.getCategoryId())); + + recordDto.setSubCategoryName(categoryService.getsubCategoryName(record.getCategoryId())); + + recordDtos.add(recordDto); } return Result.success(recordDtos); } + @AuthAccess(allowRoles = {"admin"}) @Operation(summary = "更新单个奖惩记录") @PutMapping("/admin/record/{id}") public Result adminUpdateRecord(@PathVariable Integer id, @RequestBody RecordDto recordDto) { Record record = modelMapper.map(recordDto, Record.class); - recordService.updateRecord(record,id); + recordService.updateRecord(record, id); return Result.msg("修改成功"); } + @AuthAccess(allowRoles = {"admin"}) @Operation(summary = "删除单个奖惩记录") @DeleteMapping("/admin/record/{id}") public Result adminDeleteRecord(@PathVariable Integer id) { @@ -97,6 +94,7 @@ RecordController { } + @AuthAccess(allowRoles = {"admin"}) @Operation(summary = "添加奖惩记录") @PostMapping("/admin/record") public Result adminAddRecord(@RequestBody RecordDto recordDto) { @@ -121,7 +119,7 @@ RecordController { //rolename查用户id Integer userId = roleService.getIdByrolename(roleName); // 用户id查记录 - s1 = userService.selectStudentIdByUserId(userId); + // s1 = userService.selectStudentIdByUserId(userId); } if(username!="") { //username查用户StudentId diff --git a/src/main/java/top/suyiiyii/sims/controller/UserController.java b/src/main/java/top/suyiiyii/sims/controller/UserController.java index 3016451..85ebec9 100644 --- a/src/main/java/top/suyiiyii/sims/controller/UserController.java +++ b/src/main/java/top/suyiiyii/sims/controller/UserController.java @@ -11,7 +11,6 @@ import top.suyiiyii.sims.common.AuthAccess; import top.suyiiyii.sims.common.Result; import top.suyiiyii.sims.dto.CommonResponse; import top.suyiiyii.sims.dto.UserDto; -import top.suyiiyii.sims.entity.User; import top.suyiiyii.sims.exception.ServiceException; import top.suyiiyii.sims.service.RoleService; import top.suyiiyii.sims.service.UserService; @@ -38,14 +37,7 @@ public class UserController { RoleService roleService; - @AuthAccess - @GetMapping("/") - public Result hello() { - - return Result.success("success"); - - } - + @AuthAccess(allowRoles = {"guest"}) @PostMapping("/user/login") public Result login(@RequestBody LoginRequest request, HttpServletRequest httpServletRequest) { log.info("login request:{}", request); @@ -63,6 +55,7 @@ public class UserController { return Result.success(response); } + @AuthAccess(allowRoles = {"guest"}) @PostMapping("/user/register") public Result register(@RequestBody RegisterRequest request) { log.info("register request:{}", request); @@ -73,19 +66,15 @@ public class UserController { if (request.getPassword() == null || request.getPassword().length() < 3) { throw new ServiceException("密码长度不能小于3位"); } - User user = new User(); - user.setUsername(request.getUsername()); - user.setPassword(request.getPassword()); - user.setEmail(request.getEmail()); - user.setGrade(request.getGrade()); - user.setUserGroup(request.getUserGroup()); - userService.register(user); + userService.register(request); + return Result.success(CommonResponse.factory("注册成功")); } @Operation(description = "删除单个用户") + @AuthAccess(allowRoles = {"admin"}) @DeleteMapping("/admin/user/{id}") public Result adminDelete(@PathVariable Integer id) { log.info("delete request:{}", id); @@ -94,6 +83,7 @@ public class UserController { } @Operation(description = "获取所有用户信息") + @AuthAccess(allowRoles = {"admin"}) @GetMapping("/admin/user") public Result> adminGet() { List allUsers = userService.findAllUsers(); @@ -101,6 +91,7 @@ public class UserController { } @Operation(description = "根据 id 获取用户信息") + @AuthAccess(allowRoles = {"admin"}) @GetMapping("/admin/user/{id}") public Result adminGetById(@PathVariable Integer id) { log.info("selectById request:{}", id); @@ -109,6 +100,7 @@ public class UserController { } @Operation(description = "获取当前用户信息") + @AuthAccess(allowRoles = {"user"}) @GetMapping("/user/me") public Result getSelf() { UserDto user = userService.findUser(0); @@ -121,6 +113,7 @@ public class UserController { private String username; private Integer studentId; private String password; + private String email; private String grade; private String userGroup; diff --git a/src/main/java/top/suyiiyii/sims/dto/RecordDto.java b/src/main/java/top/suyiiyii/sims/dto/RecordDto.java index 617668e..4e68526 100644 --- a/src/main/java/top/suyiiyii/sims/dto/RecordDto.java +++ b/src/main/java/top/suyiiyii/sims/dto/RecordDto.java @@ -4,9 +4,6 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import java.time.LocalDateTime; -import java.util.List; - @Data @AllArgsConstructor @NoArgsConstructor diff --git a/src/main/java/top/suyiiyii/sims/entity/Attachment.java b/src/main/java/top/suyiiyii/sims/entity/Attachment.java index 4c4fcb3..5c4a312 100644 --- a/src/main/java/top/suyiiyii/sims/entity/Attachment.java +++ b/src/main/java/top/suyiiyii/sims/entity/Attachment.java @@ -1,7 +1,6 @@ package top.suyiiyii.sims.entity; import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.tangzc.mpe.autotable.annotation.Table; import lombok.AllArgsConstructor; diff --git a/src/main/java/top/suyiiyii/sims/entity/HierarchyRelation.java b/src/main/java/top/suyiiyii/sims/entity/HierarchyRelation.java index b590e82..285edfb 100644 --- a/src/main/java/top/suyiiyii/sims/entity/HierarchyRelation.java +++ b/src/main/java/top/suyiiyii/sims/entity/HierarchyRelation.java @@ -1,7 +1,6 @@ package top.suyiiyii.sims.entity; import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.tangzc.mpe.autotable.annotation.Table; import lombok.AllArgsConstructor; diff --git a/src/main/java/top/suyiiyii/sims/entity/Record.java b/src/main/java/top/suyiiyii/sims/entity/Record.java index 6390515..b1a2959 100644 --- a/src/main/java/top/suyiiyii/sims/entity/Record.java +++ b/src/main/java/top/suyiiyii/sims/entity/Record.java @@ -7,8 +7,6 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import java.time.LocalDateTime; - /** * @Author tortoise * @Date 2024/8/9 14:04 diff --git a/src/main/java/top/suyiiyii/sims/entity/RevokeRequest.java b/src/main/java/top/suyiiyii/sims/entity/RevokeRequest.java index 1c1bb42..65218c9 100644 --- a/src/main/java/top/suyiiyii/sims/entity/RevokeRequest.java +++ b/src/main/java/top/suyiiyii/sims/entity/RevokeRequest.java @@ -14,7 +14,7 @@ import java.time.LocalDateTime; * @Date 2024/8/10 0:31 * @PackageName:top.suyiiyii.sims.entity * @ClassName: RevokeRequest - * @Description: 存储普通成员提出的奖惩撤销申请,并跟踪申请状态 + * @Description: 存储普通成员提出的奖惩撤销申请,并跟踪申请状态 * @Version 1.0 */ @Data diff --git a/src/main/java/top/suyiiyii/sims/entity/RevokedRecord.java b/src/main/java/top/suyiiyii/sims/entity/RevokedRecord.java index f40c589..3918cd7 100644 --- a/src/main/java/top/suyiiyii/sims/entity/RevokedRecord.java +++ b/src/main/java/top/suyiiyii/sims/entity/RevokedRecord.java @@ -14,7 +14,7 @@ import java.time.LocalDateTime; * @Date 2024/8/10 0:34 * @PackageName:top.suyiiyii.sims.entity * @ClassName: RevokedRecord - * @Description: 存储管理员对奖惩记录的撤销信息,包括撤销原因 + * @Description: 存储管理员对奖惩记录的撤销信息,包括撤销原因 * @Version 1.0 */ @Data diff --git a/src/main/java/top/suyiiyii/sims/entity/Role.java b/src/main/java/top/suyiiyii/sims/entity/Role.java index e42e992..a1f815c 100644 --- a/src/main/java/top/suyiiyii/sims/entity/Role.java +++ b/src/main/java/top/suyiiyii/sims/entity/Role.java @@ -1,7 +1,8 @@ package top.suyiiyii.sims.entity; import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; +import com.tangzc.autotable.annotation.ColumnNotNull; +import com.tangzc.mpe.autotable.annotation.ColumnId; import com.tangzc.mpe.autotable.annotation.Table; import lombok.AllArgsConstructor; import lombok.Data; @@ -20,10 +21,16 @@ import lombok.NoArgsConstructor; @AllArgsConstructor @NoArgsConstructor public class Role { - @TableId(type= IdType.AUTO) - private Integer id; - private Integer roleId; - //管理员,普通用户,组员,组长,队长 - private String roleName; + @ColumnId(mode = IdType.AUTO, comment = "id主键") + + private Integer id; + //管理员,普通用户,组员,组长,队长 + @ColumnNotNull + private String roleName; + private String tag; + + public static Role guest() { + return new Role(-1, "guest", ""); + } } diff --git a/src/main/java/top/suyiiyii/sims/entity/RolePermission.java b/src/main/java/top/suyiiyii/sims/entity/RolePermission.java index 1de9789..9826ca9 100644 --- a/src/main/java/top/suyiiyii/sims/entity/RolePermission.java +++ b/src/main/java/top/suyiiyii/sims/entity/RolePermission.java @@ -1,15 +1,13 @@ package top.suyiiyii.sims.entity; import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableField; -import com.baomidou.mybatisplus.annotation.TableId; +import com.tangzc.autotable.annotation.ColumnNotNull; +import com.tangzc.mpe.autotable.annotation.ColumnId; import com.tangzc.mpe.autotable.annotation.Table; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import java.security.Permission; - /** * @Author tortoise * @Date 2024/8/9 14:03 @@ -23,8 +21,12 @@ import java.security.Permission; @AllArgsConstructor @NoArgsConstructor public class RolePermission { - @TableId(type= IdType.AUTO) + + @ColumnId(mode = IdType.AUTO, comment = "id主键") + private Integer id; + @ColumnNotNull private Integer roleId; + @ColumnNotNull private Integer permissionId; } diff --git a/src/main/java/top/suyiiyii/sims/entity/User.java b/src/main/java/top/suyiiyii/sims/entity/User.java index 93046af..3fd02d9 100644 --- a/src/main/java/top/suyiiyii/sims/entity/User.java +++ b/src/main/java/top/suyiiyii/sims/entity/User.java @@ -1,8 +1,12 @@ package top.suyiiyii.sims.entity; import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; + +import com.tangzc.mpe.autotable.annotation.Column; +import com.tangzc.mpe.autotable.annotation.ColumnId; + import com.tangzc.mpe.autotable.annotation.Table; +import com.tangzc.mpe.autotable.annotation.UniqueIndex; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -20,12 +24,25 @@ import lombok.NoArgsConstructor; @AllArgsConstructor @NoArgsConstructor public class User { - @TableId(type= IdType.AUTO) + + @ColumnId(mode = IdType.AUTO, comment = "id主键") + private Integer id; + @UniqueIndex + @Column(comment = "学生id", notNull = true) private Integer studentId; + @UniqueIndex + @Column(comment = "用户名", notNull = true) private String username; + @Column(comment = "密码", notNull = true) private String password; + @UniqueIndex + @Column(comment = "邮箱", notNull = true) private String email; + @UniqueIndex + @Column(comment = "年级", notNull = true) private String grade; + @UniqueIndex + @Column(comment = "用户所属团队", notNull = true) private String userGroup; } diff --git a/src/main/java/top/suyiiyii/sims/entity/UserRole.java b/src/main/java/top/suyiiyii/sims/entity/UserRole.java index c61603c..22042fc 100644 --- a/src/main/java/top/suyiiyii/sims/entity/UserRole.java +++ b/src/main/java/top/suyiiyii/sims/entity/UserRole.java @@ -1,7 +1,8 @@ package top.suyiiyii.sims.entity; import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; +import com.tangzc.autotable.annotation.ColumnNotNull; +import com.tangzc.mpe.autotable.annotation.ColumnId; import com.tangzc.mpe.autotable.annotation.Table; import lombok.AllArgsConstructor; import lombok.Data; @@ -20,8 +21,12 @@ import lombok.NoArgsConstructor; @AllArgsConstructor @NoArgsConstructor public class UserRole { - @TableId(type= IdType.AUTO) + + @ColumnId(mode = IdType.AUTO, comment = "id主键") + private Integer id; + @ColumnNotNull private Integer userId; + @ColumnNotNull private Integer roleId; } diff --git a/src/main/java/top/suyiiyii/sims/exception/GlobalException.java b/src/main/java/top/suyiiyii/sims/exception/GlobalException.java index fc85068..4645453 100644 --- a/src/main/java/top/suyiiyii/sims/exception/GlobalException.java +++ b/src/main/java/top/suyiiyii/sims/exception/GlobalException.java @@ -1,5 +1,6 @@ package top.suyiiyii.sims.exception; +import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ResponseBody; @@ -13,11 +14,15 @@ import top.suyiiyii.sims.common.Result; * @Description: TODO * @Version 1.0 */ +@Slf4j @ControllerAdvice public class GlobalException { @ExceptionHandler(ServiceException.class) @ResponseBody - public Result ServiceException(ServiceException e){ - return Result.error(e.getCode(),e.getMessage()); + public Result ServiceException(ServiceException e) { + log.warn("ServiceException:{}", e.getMessage()); + // 打印错误调用栈 + log.warn("ServiceException:", e); + return Result.error(e.getCode(), e.getMessage()); } } diff --git a/src/main/java/top/suyiiyii/sims/exception/ServiceException.java b/src/main/java/top/suyiiyii/sims/exception/ServiceException.java index 0b3e6d5..918c21e 100644 --- a/src/main/java/top/suyiiyii/sims/exception/ServiceException.java +++ b/src/main/java/top/suyiiyii/sims/exception/ServiceException.java @@ -11,14 +11,15 @@ import lombok.Getter; * @Version 1.0 */ @Getter -public class ServiceException extends RuntimeException{ +public class ServiceException extends RuntimeException { public final String code; - public ServiceException(String msg){ + public ServiceException(String msg) { super(msg); this.code = "500"; } - public ServiceException(String code ,String msg){ + + public ServiceException(String code, String msg) { super(msg); this.code = code; } diff --git a/src/main/java/top/suyiiyii/sims/mapper/CategoryMapper.java b/src/main/java/top/suyiiyii/sims/mapper/CategoryMapper.java index 902eadc..d1f0675 100644 --- a/src/main/java/top/suyiiyii/sims/mapper/CategoryMapper.java +++ b/src/main/java/top/suyiiyii/sims/mapper/CategoryMapper.java @@ -17,7 +17,8 @@ public interface CategoryMapper { String getCategoryName(Integer categoryId); @Select("SELECT category_name FROM reward_punishment_category WHERE category_id=#{categoryId}") - String getSubCategoryName(Integer categoryId); -@Select("SELECT category_id FROM reward_punishment_category WHERE sub_category_name=#{subCategoryName}") + String getSubCategoryName(Integer categoryId); + + @Select("SELECT category_id FROM reward_punishment_category WHERE sub_category_name=#{subCategoryName}") Integer getIdBySubCategoryName(String subCategoryName); } diff --git a/src/main/java/top/suyiiyii/sims/mapper/MpRoleMapper.java b/src/main/java/top/suyiiyii/sims/mapper/MpRoleMapper.java new file mode 100644 index 0000000..70d3bd4 --- /dev/null +++ b/src/main/java/top/suyiiyii/sims/mapper/MpRoleMapper.java @@ -0,0 +1,7 @@ +package top.suyiiyii.sims.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import top.suyiiyii.sims.entity.Role; + +public interface MpRoleMapper extends BaseMapper { +} diff --git a/src/main/java/top/suyiiyii/sims/mapper/MpUserRoleMapper.java b/src/main/java/top/suyiiyii/sims/mapper/MpUserRoleMapper.java new file mode 100644 index 0000000..759242d --- /dev/null +++ b/src/main/java/top/suyiiyii/sims/mapper/MpUserRoleMapper.java @@ -0,0 +1,7 @@ +package top.suyiiyii.sims.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import top.suyiiyii.sims.entity.UserRole; + +public interface MpUserRoleMapper extends BaseMapper { +} diff --git a/src/main/java/top/suyiiyii/sims/mapper/PermissionsMapper.java b/src/main/java/top/suyiiyii/sims/mapper/PermissionsMapper.java index dffca5c..245dc24 100644 --- a/src/main/java/top/suyiiyii/sims/mapper/PermissionsMapper.java +++ b/src/main/java/top/suyiiyii/sims/mapper/PermissionsMapper.java @@ -1,6 +1,5 @@ package top.suyiiyii.sims.mapper; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Select; import top.suyiiyii.sims.entity.Permissions; @@ -17,9 +16,10 @@ import java.util.List; * @Version 1.0 */ @Mapper -public interface PermissionsMapper { -@Select("SELECT * FROM role_permission WHERE role_id = #{id}") +public interface PermissionsMapper { + @Select("SELECT * FROM role_permission WHERE role_id = #{id}") List getRolePerminsionByRoleId(Integer id); -@Select("SELECT * FROM permissions WHERE permission_id = #{permissionId}") + + @Select("SELECT * FROM permissions WHERE permission_id = #{permissionId}") Permissions selectById(Integer permissionId); } diff --git a/src/main/java/top/suyiiyii/sims/mapper/RecordMapper.java b/src/main/java/top/suyiiyii/sims/mapper/RecordMapper.java index 2303c11..ab9f562 100644 --- a/src/main/java/top/suyiiyii/sims/mapper/RecordMapper.java +++ b/src/main/java/top/suyiiyii/sims/mapper/RecordMapper.java @@ -16,11 +16,12 @@ import java.util.List; @Mapper public interface RecordMapper { //分页查询 -@Select("select * from record limit #{page},#{size}") + @Select("select * from record limit #{page},#{size}") List getAllRecords(Integer page, Integer size); -//根据学号分页查询所以信息 + + //根据学号分页查询所以信息 @Select("select * from record where student_id = #{id} limit #{page},#{size}") - List getMyAllRecords(Integer page, Integer size, Integer id); + List getMyAllRecords(Integer page, Integer size, String id); //根据id,更新对应信息 @Update("UPDATE record SET " @@ -39,6 +40,7 @@ public interface RecordMapper { void updateRecord(Record record, Integer id); @Delete("delete from record where id = #{id}") void deleteRecord(Integer id); + @Insert({ "insert into record (student_id, category_id, `date`, content, reason, amount, remark, is_revoked,", "revoke_date, revoke_reason, revoke_remark, operator_user_id, last_update_time)", diff --git a/src/main/java/top/suyiiyii/sims/mapper/RoleMapper.java b/src/main/java/top/suyiiyii/sims/mapper/RoleMapper.java index 78661bf..e8be92e 100644 --- a/src/main/java/top/suyiiyii/sims/mapper/RoleMapper.java +++ b/src/main/java/top/suyiiyii/sims/mapper/RoleMapper.java @@ -1,12 +1,8 @@ package top.suyiiyii.sims.mapper; -import com.baomidou.mybatisplus.core.mapper.BaseMapper; -import lombok.Data; import org.apache.ibatis.annotations.*; -import top.suyiiyii.sims.entity.Permissions; import top.suyiiyii.sims.entity.Role; import top.suyiiyii.sims.entity.User; -import top.suyiiyii.sims.entity.UserRole; import java.util.List; @@ -22,15 +18,18 @@ import java.util.List; public interface RoleMapper { @Insert("INSERT INTO role(name) VALUES(#{name}") void addRole(String name); -@Delete("DELETE FROM role WHERE name=#{name}") + + @Delete("DELETE FROM role WHERE name=#{name}") void deleteRole(String name); -@Update("UPDATE role SET name=#{newName} WHERE name=#{name}") + + @Update("UPDATE role SET name=#{newName} WHERE name=#{name}") void updateRole(String name, String newName); + /** + * @param * @author: tortoise * @date: 2024/8/14 14:23 * @Description: TODO 查询用户信息 - * @param * @return: java.util.List */ @Select("SELECT u.username, u.name, u.userId, r.role_name " + @@ -53,7 +52,7 @@ public interface RoleMapper { "(SELECT role_id FROM user_role WHERE user_id = #{user_id})") List selectRolesById(@Param("user_id") int id); -@Select("SELECT role_name FROM role WHERE role_id=#{roleId}") + @Select("SELECT role_name FROM role WHERE role_id=#{roleId}") List selectRoleNamesByRoleId(Integer roleId); @Select("SELECT user_id " + diff --git a/src/main/java/top/suyiiyii/sims/mapper/UserMapper.java b/src/main/java/top/suyiiyii/sims/mapper/UserMapper.java index 8ffdc80..1d49de4 100644 --- a/src/main/java/top/suyiiyii/sims/mapper/UserMapper.java +++ b/src/main/java/top/suyiiyii/sims/mapper/UserMapper.java @@ -2,7 +2,6 @@ package top.suyiiyii.sims.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.*; -import top.suyiiyii.sims.entity.Role; import top.suyiiyii.sims.entity.User; import java.util.List; @@ -19,14 +18,18 @@ import java.util.List; public interface UserMapper extends BaseMapper { /** * 添加新用户 + * * @param user 新用户对象 * @return 影响的行数 */ - @Insert("insert INTO user (student_id, username, password, email, user_group) VALUES (#{studentId}, #{username}, #{password}, #{email}, #{userGroup})") + + @Insert("insert INTO user (id,student_id, username, password, username, email, user_group) VALUES (#{id},#{studentId}, #{username}, #{password}, #{name}, #{email}, #{userGroup})") + int addUser(User user); /** * 根据ID删除用户 + * * @param id 用户ID * @return 影响的行数 */ @@ -35,6 +38,7 @@ public interface UserMapper extends BaseMapper { /** * 更新用户信息 + * * @param user 更新后的用户对象 * @return 影响的行数 */ @@ -42,40 +46,54 @@ public interface UserMapper extends BaseMapper { "student_id = #{userId}, " + "username = #{username}, " + + "username = #{name}, " + + "email = #{email}, " + "grade = #{grade}, " + - "userGroup = #{group} " + + "user_group = #{group} " + "WHERE id = #{id}") int updateUser(User user); /** * 根据ID查询用户信息 + * * @param * @return 用户对象 */ - @Select("SELECT id, student_id, username, password, email,grade,user_group from user WHERE student_id = #{id}") + + @Select("SELECT id, student_id, username, password, username, email,grade,user_group from user WHERE student_id = #{id}") + User selectByUserId(Integer id); /** * 根据iD查询用户信息 + * * @param * @return 用户对象 */ - @Select("SELECT id, student_id, username, password, email,grade, user_group from user WHERE id = #{id}") + + @Select("SELECT id, student_id, username, password, username, email,grade, user_group from user WHERE id = #{id}") + User selectById(Integer id); + /** * 查询所有用户信息 + * * @return 用户列表 */ - @Select("SELECT id, student_id, username, password, email, grade, user_group FROM user") + + @Select("SELECT id, student_id, username, password, username, email, grade, user_group FROM user") + List selectAll(); - @Select("select * from user where username = #{username}") - User selectByUserName(@Param("username") String username); -@Update("update user set password = #{password} where username = #{username}") + @Select("select * from user where username = #{username}") + User selectByUserName(@Param("username") String username); + + @Update("update user set password = #{password} where username = #{username}") void updatePassword(User user); -@Select("select student_id from user where id = #{userId}") -Integer getStudentIdById(Integer userId); - @Select("SELECT student_id from user WHERE id = #{id}") - Integer selectStudentIdByUserId(Integer id); + + + @Select("select student_id from user where id = #{userId}") + String getStudentIdById(String userId); + } diff --git a/src/main/java/top/suyiiyii/sims/service/CategoryService.java b/src/main/java/top/suyiiyii/sims/service/CategoryService.java index 98e20d1..ee6c966 100644 --- a/src/main/java/top/suyiiyii/sims/service/CategoryService.java +++ b/src/main/java/top/suyiiyii/sims/service/CategoryService.java @@ -19,7 +19,7 @@ public class CategoryService { public String getCategoryName(Integer id) { - return categoryMapper.getCategoryName(id); + return categoryMapper.getCategoryName(id); } public String getsubCategoryName(Integer categoryId) { diff --git a/src/main/java/top/suyiiyii/sims/service/RbacService.java b/src/main/java/top/suyiiyii/sims/service/RbacService.java new file mode 100644 index 0000000..5cab939 --- /dev/null +++ b/src/main/java/top/suyiiyii/sims/service/RbacService.java @@ -0,0 +1,55 @@ +package top.suyiiyii.sims.service; + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import top.suyiiyii.sims.entity.Role; +import top.suyiiyii.sims.entity.UserRole; +import top.suyiiyii.sims.mapper.MpRoleMapper; +import top.suyiiyii.sims.mapper.MpUserMapper; +import top.suyiiyii.sims.mapper.MpUserRoleMapper; + +import java.util.List; + +@Slf4j +@Service +public class RbacService { + + @Autowired + MpUserMapper userMapper; + + @Autowired + MpUserRoleMapper userRoleMapper; + + @Autowired + MpRoleMapper roleMapper; + + /** + * 根据用户id获取用户的角色 + * + * @param userId 用户id + * @return 用户的角色列表 + */ + public List getRolesByUserId(int userId) { + // 根据用户id获取用户的角色id,使用mp的条件构造器 + List userRoles = userRoleMapper.selectList(new QueryWrapper().eq("user_id", userId)); + // 根据角色id获取角色 + return roleMapper.selectBatchIds(userRoles.stream().map(UserRole::getRoleId).toList()); + } + + public boolean addRoleWithUserId(int userId, String roleName) { + Role role = roleMapper.selectOne(new QueryWrapper().eq("role_name", roleName)); + if (role == null) { + Role newRole = new Role(); + newRole.setRoleName(roleName); + roleMapper.insert(newRole); + role = roleMapper.selectOne(new QueryWrapper().eq("role_name", roleName)); + } + UserRole userRole = new UserRole(); + userRole.setUserId(userId); + userRole.setRoleId(role.getId()); + return userRoleMapper.insert(userRole) > 0; + } + +} diff --git a/src/main/java/top/suyiiyii/sims/service/RecordService.java b/src/main/java/top/suyiiyii/sims/service/RecordService.java index ec0310c..5b0fde2 100644 --- a/src/main/java/top/suyiiyii/sims/service/RecordService.java +++ b/src/main/java/top/suyiiyii/sims/service/RecordService.java @@ -32,7 +32,7 @@ public class RecordService { public List getMyAllRecords(Integer page, Integer size, String userId) { - Integer studentId = userMapper.getStudentIdById(Integer.valueOf(userId)); + String studentId = userMapper.getStudentIdById(userId); return recordMapper.getMyAllRecords(page, size, studentId); } diff --git a/src/main/java/top/suyiiyii/sims/service/RoleService.java b/src/main/java/top/suyiiyii/sims/service/RoleService.java index 88dd9e6..d036fbb 100644 --- a/src/main/java/top/suyiiyii/sims/service/RoleService.java +++ b/src/main/java/top/suyiiyii/sims/service/RoleService.java @@ -1,11 +1,9 @@ package top.suyiiyii.sims.service; -import org.checkerframework.checker.units.qual.A; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import top.suyiiyii.sims.entity.Role; import top.suyiiyii.sims.entity.User; -import top.suyiiyii.sims.entity.UserRole; import top.suyiiyii.sims.mapper.RoleMapper; import java.util.List; @@ -23,23 +21,22 @@ public class RoleService { @Autowired RoleMapper roleMapper; - public List findAllUsersWithRoles(){ + public List findAllUsersWithRoles() { return roleMapper.selectAllUsersWithRoles(); } + /** + * @param * @author: tortoise * @date: 2024/8/14 14:39 * @Description: TODO 查看自己身份 - * @param Id * @return: java.util.List */ - public List selectRolesById(int id){ + public List selectRolesById(int id) { return roleMapper.selectRolesById(id); } - - public boolean isRoleNameAdmin(Integer id) { List roles = roleMapper.selectRolesById(id); for (Role role : roles) { diff --git a/src/main/java/top/suyiiyii/sims/service/UserService.java b/src/main/java/top/suyiiyii/sims/service/UserService.java index 90f13a6..82c3f2f 100644 --- a/src/main/java/top/suyiiyii/sims/service/UserService.java +++ b/src/main/java/top/suyiiyii/sims/service/UserService.java @@ -1,21 +1,23 @@ package top.suyiiyii.sims.service; - +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import org.modelmapper.ModelMapper; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; - - +import top.suyiiyii.sims.controller.UserController; import top.suyiiyii.sims.dto.UserDto; -import top.suyiiyii.sims.entity.*; +import top.suyiiyii.sims.entity.Role; +import top.suyiiyii.sims.entity.User; import top.suyiiyii.sims.exception.ServiceException; +import top.suyiiyii.sims.mapper.MpUserMapper; import top.suyiiyii.sims.mapper.PermissionsMapper; import top.suyiiyii.sims.mapper.RoleMapper; import top.suyiiyii.sims.mapper.UserMapper; import top.suyiiyii.sims.utils.JwtUtils; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; /** @@ -31,9 +33,17 @@ public class UserService { @Autowired UserMapper userMapper; @Autowired + MpUserMapper mpUserMapper; + @Autowired RoleMapper roleMapper; @Autowired PermissionsMapper permissionsMapper; + @Value("${jwt.secret}") + private String secret; + @Autowired + private RbacService rbacService; + @Autowired + private ModelMapper modelMapper; public void addUser(User user) { userMapper.addUser(user); @@ -50,8 +60,9 @@ public class UserService { public List selectAll() { return userMapper.selectAll(); } -//TODO:返回一个DTO,用户基本信息 - public String login(String username, String password) { + + //TODO:返回一个DTO,用户基本信息 + public String login(String username, String password) { User dbUser = userMapper.selectByUserName(username); if (dbUser == null) { @@ -60,59 +71,50 @@ public class UserService { if (!dbUser.getPassword().equals(password)) { throw new ServiceException("密码或用户名错误"); } - HashSet permissionsSet = new HashSet<>(); - Integer id = dbUser.getId(); - List roles = roleMapper.selectRolesById(id); - for (Role role : roles) { - //根据roleid找所有permissionId - List rolePerminsion = permissionsMapper.getRolePerminsionByRoleId(role.getRoleId()); - for (RolePermission rolePermission : rolePerminsion) { - Integer permissionId = rolePermission.getPermissionId(); - //根据permissionId找permission - Permissions permissions = permissionsMapper.selectById(permissionId); - permissionsSet.add(permissions); - } + return JwtUtils.createToken(dbUser.getId().toString(), secret); + } + + + public void register(UserController.RegisterRequest req) { + + User dbUser = userMapper.selectByUserId(req.getStudentId()); + + if (req.getUsername() == null || req.getUsername().equals("")) { + throw new ServiceException("用户名不能为空"); } - String token = JwtUtils.createToken(dbUser.getId().toString(), dbUser.getPassword()); - - - return token; - - } - - - public User register(User user) { - - User dbUser = userMapper.selectById(user.getId()); - - if (user.getUsername() == null || user.getUsername().equals("")) { - throw new ServiceException("用户名不能为空"); - } if (dbUser != null) { throw new ServiceException("账号已经存在"); } + if (req.getStudentId() == null || req.getStudentId().equals("")) { + throw new ServiceException("学号不能为空"); + } + if (req.getPassword() == null || req.getPassword().equals("")) { - if( user.getPassword() == null || user.getPassword().equals("")) { throw new ServiceException("密码不能为空"); } - if (user.getEmail() == null || user.getEmail().equals("")) { + if (req.getEmail() == null || req.getEmail().equals("")) { throw new ServiceException("邮箱不能为空"); } - if (user.getUserGroup() == null || user.getUserGroup().equals("")) { + if (req.getUserGroup() == null || req.getUserGroup().equals("")) { throw new ServiceException("组别不能为空"); } + User user = modelMapper.map(req, User.class); - userMapper.addUser(user); - return user; + mpUserMapper.insert(user); + user = mpUserMapper.selectOne(new LambdaQueryWrapper().eq(User::getUsername, req.getUsername())); + rbacService.addRoleWithUserId(user.getId(), "user"); } + public User selectByUsername(String username) { return userMapper.selectByUserName(username); } + public void updatePassword(User user) { userMapper.updatePassword(user); } - public List findAllUsers(){ + + public List findAllUsers() { List users = userMapper.selectAll(); List UserDtos = new ArrayList<>(); @@ -126,7 +128,7 @@ public class UserService { Integer id = user.getId(); List roles = roleMapper.selectRolesById(id); for (Role role : roles) { - Integer roleId = role.getRoleId(); + Integer roleId = role.getId(); // 获取一个角色的名称列表 List roleNameList = roleMapper.selectRoleNamesByRoleId(roleId); // 累加角色名称到用户的角色列表中 @@ -136,6 +138,7 @@ public class UserService { } return UserDtos; } + public UserDto findUser(Integer id) { UserDto UserDto = new UserDto(); @@ -147,7 +150,7 @@ public class UserService { UserDto.setRoles(new ArrayList<>()); List roles = roleMapper.selectRolesById(id); for (Role role : roles) { - Integer roleId = role.getRoleId(); + Integer roleId = role.getId(); // 获取一个角色的名称列表 List roleNameList = roleMapper.selectRoleNamesByRoleId(roleId); // 累加角色名称到用户的角色列表中 @@ -165,7 +168,6 @@ public class UserService { } - public Integer selectStudentIdByUserId(Integer userId) { - return userMapper.selectStudentIdByUserId(userId); - } + + } diff --git a/src/main/java/top/suyiiyii/sims/utils/JwtUtils.java b/src/main/java/top/suyiiyii/sims/utils/JwtUtils.java index cf050e0..e39f97b 100644 --- a/src/main/java/top/suyiiyii/sims/utils/JwtUtils.java +++ b/src/main/java/top/suyiiyii/sims/utils/JwtUtils.java @@ -30,17 +30,13 @@ public class JwtUtils { private static UserMapper staticUserMapper; @Resource UserMapper userMapper; - @PostConstruct - public void setUserService() { - staticUserMapper=userMapper; - } /** + * @param userId + * @param sign * @author: tortoise * @date: 2024/8/1 15:12 * @Description: 生成token - * @param userId - * @param sign * @return: java.lang.String */ public static String createToken(String userId, String sign) { @@ -48,8 +44,9 @@ public class JwtUtils { .withAudience(userId) .withExpiresAt(DateUtil.offsetHour(new Date(), 2)) .sign(Algorithm.HMAC256(sign)); - // 设置令牌过期时间为2小时 + // 设置令牌过期时间为2小时 } + public static User getCurrentUser() { try { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); @@ -63,6 +60,7 @@ public class JwtUtils { } return null; } + // 验证 JWT 令牌 public static boolean verifyToken(String token, String secret) { try { @@ -74,6 +72,7 @@ public class JwtUtils { return false; } } + public static String extractUserId(String token) { try { return JWT.decode(token).getAudience().get(0); // 从 token 中提取用户ID @@ -82,4 +81,9 @@ public class JwtUtils { return null; } } + + @PostConstruct + public void setUserService() { + staticUserMapper = userMapper; + } } diff --git a/src/main/resources/application-test.yaml b/src/main/resources/application-test.yaml index b73be74..978a6f0 100644 --- a/src/main/resources/application-test.yaml +++ b/src/main/resources/application-test.yaml @@ -5,4 +5,5 @@ spring: username: password: - +jwt: + secret: SuyiiyiiiiiiyiiiiTTTTTTTTTTTestttttttttttttt diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 2b0fca7..4b7599a 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -11,4 +11,7 @@ spring: auto-table: enable: true - model-package: top.suyiiyii.sims.entity \ No newline at end of file + model-package: top.suyiiyii.sims.entity + +jwt: + secret: ${JWT_SECRET} \ No newline at end of file diff --git a/src/test/java/top/suyiiyii/sims/mapper/UserMapperTest.java b/src/test/java/top/suyiiyii/sims/mapper/UserMapperTest.java deleted file mode 100644 index bb51181..0000000 --- a/src/test/java/top/suyiiyii/sims/mapper/UserMapperTest.java +++ /dev/null @@ -1,33 +0,0 @@ -package top.suyiiyii.sims.mapper; - -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; -import top.suyiiyii.sims.entity.User; - -@SpringBootTest -@ActiveProfiles("test") -public class UserMapperTest { - - @Autowired - private MpUserMapper userMapper; - - @Test - public void testAddUser() { - User user = new User(); - user.setStudentId(1); - user.setUsername("test"); - user.setPassword("test"); - user.setEmail("test"); - user.setGrade("test"); - user.setUserGroup("test"); - - - - int result = userMapper.insert(user); - Assertions.assertEquals(1, result); - } - -} \ No newline at end of file diff --git a/src/test/java/top/suyiiyii/sims/service/RbacServiceTest.java b/src/test/java/top/suyiiyii/sims/service/RbacServiceTest.java new file mode 100644 index 0000000..b06cec6 --- /dev/null +++ b/src/test/java/top/suyiiyii/sims/service/RbacServiceTest.java @@ -0,0 +1,35 @@ +package top.suyiiyii.sims.service; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import top.suyiiyii.sims.entity.Role; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +@ActiveProfiles("test") +class RbacServiceTest { + + @Autowired + private RbacService rbacService; + + @Test + void addRoleWithUserId() { + int userId = 1; // mock userId + String roleName = "ROLE"; // mock roleName + boolean result = rbacService.addRoleWithUserId(userId, roleName); + assertTrue(result); + } + @Test + void getRolesByUserId() { + int userId = 1; // mock userId + List roles = rbacService.getRolesByUserId(userId); + assertNotNull(roles); + assert roles.stream().map(Role::getRoleName).toList().contains("ROLE"); // mock roleName + } + +} \ No newline at end of file