改成main的

This commit is contained in:
tortoise 2024-08-26 19:49:40 +08:00
commit a7052ec87a
44 changed files with 621 additions and 326 deletions

123
.github/workflows/docker-publish.yml vendored Normal file
View File

@ -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 <account>/<repo>
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] <github-actions[bot]@users.noreply.github.com>"

20
.github/workflows/gitea-sync.yml vendored Normal file
View File

@ -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 }}'

View File

@ -11,13 +11,21 @@ name: Java CI with Maven
on: on:
push: push:
branches: [ "main" ] branches: [ "main" ]
paths:
- 'pom.xml'
- 'src/**'
pull_request: pull_request:
branches: [ "main" ] branches: [ "main" ]
paths:
- 'pom.xml'
- 'src/**'
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
contents: write
steps: steps:
- uses: actions/checkout@v4 - 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 # Optional: Uploads the full dependency graph to GitHub to improve the quality of Dependabot alerts this repository can receive
# - name: Update dependency graph - name: Update dependency graph
# uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6 uses: advanced-security/maven-dependency-submission-action@571e99aab1055c2e71a1e2309b9691de18d6b7d6

29
Dockerfile Normal file
View File

@ -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" ]

View File

@ -144,6 +144,10 @@
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
</exclude> </exclude>
</excludes> </excludes>
<layers>
<enabled>true</enabled>
</layers>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>

View File

@ -14,4 +14,5 @@ import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Documented @Documented
public @interface AuthAccess { public @interface AuthAccess {
String[] allowRoles() default {};
} }

View File

@ -1,16 +1,10 @@
package top.suyiiyii.sims.common; 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.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; 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.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import top.suyiiyii.sims.service.RoleService; import top.suyiiyii.sims.service.RoleService;
import top.suyiiyii.sims.service.UserService;
import top.suyiiyii.sims.utils.JwtUtils;
/** /**
* @Author tortoise * @Author tortoise
@ -20,63 +14,28 @@ import top.suyiiyii.sims.utils.JwtUtils;
* @Description: TODO 拦截器配置 * @Description: TODO 拦截器配置
* @Version 1.0 * @Version 1.0
*/ */
@Configuration @Configuration
public class InterceptorConfig extends WebMvcConfigurationSupport { public class InterceptorConfig extends WebMvcConfigurationSupport {
@Autowired @Autowired
private RoleService roleService; private RoleService roleService;
@Autowired
private JwtInterceptor jwtInterceptor;
@Autowired
private RbacInterceptor rbacInterceptor;
//UserService userService; @Override
@Override protected void addInterceptors(InterceptorRegistry registry) {
protected void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(jwtInterceptor)
registry.addInterceptor(jwtInterceptor()) .addPathPatterns("/**")
.addPathPatterns("/**") .excludePathPatterns("/v3/api-docs/**");
.excludePathPatterns("/user/login") // 排除不需要验证的路径 registry.addInterceptor(rbacInterceptor)
.excludePathPatterns("/user/register") .excludePathPatterns("/v3/api-docs/**");
.excludePathPatterns("/v3/api-docs/**");
// 注册AdminInterceptor只拦截以admin/开头的路径 super.addInterceptors(registry);
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) {
// 这里应该实现检查用户权限的逻辑
// 例如从sessiontoken或者数据库中获取用户信息并判断权限
// 以下仅为示例
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;
}
}
}
} }
}

View File

@ -1,16 +1,16 @@
package top.suyiiyii.sims.common; package top.suyiiyii.sims.common;
import cn.hutool.core.util.StrUtil; import com.auth0.jwt.exceptions.TokenExpiredException;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; 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 org.springframework.web.servlet.HandlerInterceptor;
import top.suyiiyii.sims.entity.User;
import top.suyiiyii.sims.exception.ServiceException; import top.suyiiyii.sims.exception.ServiceException;
import top.suyiiyii.sims.mapper.UserMapper;
import top.suyiiyii.sims.utils.JwtUtils; import top.suyiiyii.sims.utils.JwtUtils;
import java.util.Objects;
/** /**
* @Author tortoise * @Author tortoise
* @Date 2024/8/12 11:33 * @Date 2024/8/12 11:33
@ -20,49 +20,39 @@ import top.suyiiyii.sims.utils.JwtUtils;
* @Version 1.0 * @Version 1.0
*/ */
@Component
public class JwtInterceptor implements HandlerInterceptor { public class JwtInterceptor implements HandlerInterceptor {
@Resource @Value("${jwt.secret}")
UserMapper userMapper; private String secret;
@Override @Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if ("/error".equals(request.getRequestURI())) {
return true;
}
// Authorization 头中获取 token // Authorization 头中获取 token
String token = request.getHeader("Authorization"); String token = request.getHeader("Authorization");
if (token != null && token.startsWith("Bearer ")) { if (token != null && token.startsWith("Bearer ")) {
token = token.substring(7);
// 去除 "Bearer " 前缀 // 去除 "Bearer " 前缀
token = token.substring(7);
} else { } else {
// 如果 Authorization 头中没有 token则尝试从请求参数中获取 // 如果没有有效的token设置userId为-1表示未登录
token = request.getParameter("token"); request.setAttribute("userId", -1);
} return true;
// 如果不是映射到方法直接通过
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 的有效性 // 验证 token 的有效性
if (!JwtUtils.verifyToken(token, user.getPassword())) { try {
throw new ServiceException("401", "请登录"); if (!JwtUtils.verifyToken(token, secret) || JwtUtils.extractUserId(token) == null) {
throw new ServiceException("401", "登录已过期,请重新登录");
}
} catch (TokenExpiredException e) {
throw new ServiceException("401", "登录已过期,请重新登录");
} }
// 验证token后如果一切正常将token存储到request的属性中 // 获取 token 中的 user id
request.setAttribute("token", token); Integer userId = Integer.parseInt(Objects.requireNonNull(JwtUtils.extractUserId(token)));
request.setAttribute("userId", userId);
return true; return true;
} }
} }

View File

@ -4,8 +4,6 @@ import org.modelmapper.ModelMapper;
import org.modelmapper.convention.MatchingStrategies; import org.modelmapper.convention.MatchingStrategies;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import top.suyiiyii.sims.dto.RecordDto;
import top.suyiiyii.sims.entity.User;
/** /**
* @Author tortoise * @Author tortoise
@ -25,19 +23,20 @@ public class ModelMapperConfig {
// 设置匹配策略为严格模式 // 设置匹配策略为严格模式
modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT); modelMapper.getConfiguration().setMatchingStrategy(MatchingStrategies.STRICT);
// configureUser(modelMapper); // configureUser(modelMapper);
return modelMapper; return modelMapper;
} }
// 配置 User 类的映射规则 // 配置 User 类的映射规则
private void configureUser(ModelMapper modelMapper) { private void configureUser(ModelMapper modelMapper) {
// 定义 UserModel -> User 的映射规则 // 定义 UserModel -> User 的映射规则
// modelMapper.typeMap(RecordDto.class, Record.class) // modelMapper.typeMap(RecordDto.class, Record.class)
// 跳过设置密码字段 // 跳过设置密码字段
// 定义 User -> UserModel 的映射规则 // 定义 User -> UserModel 的映射规则
// modelMapper.typeMap(User.class, RecordDto.class) // modelMapper.typeMap(User.class, RecordDto.class)
// .addMappings(mapper -> mapper.skip(RecordDto::setPassword)) // 跳过设置密码字段 // .addMappings(mapper -> mapper.skip(RecordDto::setPassword)) // 跳过设置密码字段
// .addMappings(mapper -> mapper.map(User::getRealName, UserModel::setName)); // User realName 映射为 UserModel name // .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::getCreateTime, UserModel::setCreateTime))
// .addMappings(mapper -> mapper.using(dateToStringConverter).map(User::getUpdateTime, UserModel::setUpdateTime)); // .addMappings(mapper -> mapper.using(dateToStringConverter).map(User::getUpdateTime, UserModel::setUpdateTime));
} }

View File

@ -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<String> roles = getUserRole(request).stream().map(Role::getRoleName).toList();
List<String> 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<Role> getUserRole(HttpServletRequest request) {
Integer UserId = (Integer) request.getAttribute("userId");
if (UserId == null || UserId == -1) {
return List.of(Role.guest());
}
return rbacService.getRolesByUserId(UserId);
}
}

View File

@ -4,6 +4,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import top.suyiiyii.sims.common.AuthAccess;
import top.suyiiyii.sims.common.Result; import top.suyiiyii.sims.common.Result;
import top.suyiiyii.sims.dto.RecordDto; import top.suyiiyii.sims.dto.RecordDto;
import top.suyiiyii.sims.entity.User; import top.suyiiyii.sims.entity.User;
@ -28,12 +29,14 @@ public class AdminController {
@Autowired @Autowired
private UserService userService; private UserService userService;
@AuthAccess(allowRoles = {"admin"})
@GetMapping("/findAllUsersWithRoles") @GetMapping("/findAllUsersWithRoles")
public Result findAllUsersWithRoles() { public Result findAllUsersWithRoles() {
List<User> userList = roleService.findAllUsersWithRoles(); List<User> userList = roleService.findAllUsersWithRoles();
return Result.success(userList); return Result.success(userList);
} }
@AuthAccess(allowRoles = {"admin"})
@GetMapping("/selectAll") @GetMapping("/selectAll")
public Result selectAll() { public Result selectAll() {
List<User> users = userService.selectAll(); List<User> users = userService.selectAll();
@ -42,8 +45,8 @@ public class AdminController {
} }
/** /**
request.setAttribute();lUsers(); * request.setAttribute();lUsers();
return Result.success(userList); * return Result.success(userList);
} * }
} * }
**/ **/

View File

@ -5,14 +5,17 @@ import lombok.Data;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import top.suyiiyii.sims.common.AuthAccess;
@RestController @RestController
public class HealthzController { public class HealthzController {
@AuthAccess(allowRoles = {"guest"})
@GetMapping("/healthz") @GetMapping("/healthz")
public String healthz() { public String healthz() {
return "ok"; return "ok";
} }
@AuthAccess(allowRoles = {"guest"})
@PostMapping("/healthz") @PostMapping("/healthz")
public HealthzResponse healthzPost() { public HealthzResponse healthzPost() {
return new HealthzResponse("health"); return new HealthzResponse("health");

View File

@ -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<String> helloPost(String username , Integer age) {
List<String> list = List.of(username,age.toString());
return list;
}
@GetMapping("/helloResult")
public Result healthz() {
return Result.success("Hello World");
}
}

View File

@ -1,34 +1,24 @@
package top.suyiiyii.sims.controller; 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 io.swagger.v3.oas.annotations.Operation;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.modelmapper.ModelMapper; import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import top.suyiiyii.sims.common.AuthAccess;
import top.suyiiyii.sims.common.Result; import top.suyiiyii.sims.common.Result;
import top.suyiiyii.sims.dto.CommonResponse; import top.suyiiyii.sims.dto.CommonResponse;
import top.suyiiyii.sims.dto.RecordDto; import top.suyiiyii.sims.dto.RecordDto;
import top.suyiiyii.sims.entity.Record; 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.CategoryService;
import top.suyiiyii.sims.service.RecordService; import top.suyiiyii.sims.service.RecordService;
import top.suyiiyii.sims.service.RoleService; import top.suyiiyii.sims.service.RoleService;
import top.suyiiyii.sims.service.UserService; import top.suyiiyii.sims.service.UserService;
import top.suyiiyii.sims.utils.JwtUtils; import top.suyiiyii.sims.utils.JwtUtils;
import java.time.LocalDateTime;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
@RestController @RestController
public class public class
@ -44,6 +34,7 @@ RecordController {
@Autowired @Autowired
ModelMapper modelMapper; ModelMapper modelMapper;
@AuthAccess(allowRoles = {"admin"})
@Operation(summary = "获取所有奖惩记录") @Operation(summary = "获取所有奖惩记录")
@GetMapping("/admin/record") @GetMapping("/admin/record")
public Result<List<RecordDto>> adminRecord( public Result<List<RecordDto>> adminRecord(
@ -55,40 +46,46 @@ RecordController {
RecordDto recordDto = modelMapper.map(record, RecordDto.class); RecordDto recordDto = modelMapper.map(record, RecordDto.class);
recordDto.setCategoryName(categoryService.getCategoryName(record.getCategoryId())); recordDto.setCategoryName(categoryService.getCategoryName(record.getCategoryId()));
recordDto.setSubCategoryName(categoryService.getsubCategoryName( record.getCategoryId())); recordDto.setSubCategoryName(categoryService.getsubCategoryName(record.getCategoryId()));
recordDtos.add(recordDto); recordDtos.add(recordDto);
} }
return Result.success(recordDtos); return Result.success(recordDtos);
} }
@AuthAccess(allowRoles = {"user"})
@Operation(summary = "获取自己的奖惩记录") @Operation(summary = "获取自己的奖惩记录")
@GetMapping("/record") @GetMapping("/record")
public Result<List<RecordDto>> record(@RequestParam(defaultValue = "0") int page, public Result<List<RecordDto>> record(@RequestParam(defaultValue = "0") int page,
@RequestParam(defaultValue = "10") int size, @RequestParam(defaultValue = "10") int size,
HttpServletRequest request) { HttpServletRequest request) {
String token = (String) request.getAttribute("token"); String token = (String) request.getAttribute("token");
String userId= JwtUtils.extractUserId(token); String userId = JwtUtils.extractUserId(token);
List<RecordDto> recordDtos=new ArrayList<>(); List<RecordDto> recordDtos = new ArrayList<>();
List<Record> records = recordService.getMyAllRecords(page, size,userId); List<Record> records = recordService.getMyAllRecords(page, size, userId);
for (Record record : records) { for (Record record : records) {
RecordDto recordDto = modelMapper.map(record, RecordDto.class); RecordDto recordDto = modelMapper.map(record, RecordDto.class);
recordDto.setCategoryName(categoryService.getCategoryName(record.getCategoryId())); recordDto.setCategoryName(categoryService.getCategoryName(record.getCategoryId()));
recordDto.setSubCategoryName(categoryService.getsubCategoryName( record.getCategoryId()));
recordDto.setSubCategoryName(categoryService.getsubCategoryName(record.getCategoryId()));
recordDtos.add(recordDto); recordDtos.add(recordDto);
} }
return Result.success(recordDtos); return Result.success(recordDtos);
} }
@AuthAccess(allowRoles = {"admin"})
@Operation(summary = "更新单个奖惩记录") @Operation(summary = "更新单个奖惩记录")
@PutMapping("/admin/record/{id}") @PutMapping("/admin/record/{id}")
public Result<CommonResponse> adminUpdateRecord(@PathVariable Integer id, @RequestBody RecordDto recordDto) { public Result<CommonResponse> adminUpdateRecord(@PathVariable Integer id, @RequestBody RecordDto recordDto) {
Record record = modelMapper.map(recordDto, Record.class); Record record = modelMapper.map(recordDto, Record.class);
recordService.updateRecord(record,id); recordService.updateRecord(record, id);
return Result.msg("修改成功"); return Result.msg("修改成功");
} }
@AuthAccess(allowRoles = {"admin"})
@Operation(summary = "删除单个奖惩记录") @Operation(summary = "删除单个奖惩记录")
@DeleteMapping("/admin/record/{id}") @DeleteMapping("/admin/record/{id}")
public Result<CommonResponse> adminDeleteRecord(@PathVariable Integer id) { public Result<CommonResponse> adminDeleteRecord(@PathVariable Integer id) {
@ -97,6 +94,7 @@ RecordController {
} }
@AuthAccess(allowRoles = {"admin"})
@Operation(summary = "添加奖惩记录") @Operation(summary = "添加奖惩记录")
@PostMapping("/admin/record") @PostMapping("/admin/record")
public Result<CommonResponse> adminAddRecord(@RequestBody RecordDto recordDto) { public Result<CommonResponse> adminAddRecord(@RequestBody RecordDto recordDto) {
@ -121,7 +119,7 @@ RecordController {
//rolename查用户id //rolename查用户id
Integer userId = roleService.getIdByrolename(roleName); Integer userId = roleService.getIdByrolename(roleName);
// 用户id查记录 // 用户id查记录
s1 = userService.selectStudentIdByUserId(userId); // s1 = userService.selectStudentIdByUserId(userId);
} }
if(username!="") { if(username!="") {
//username查用户StudentId //username查用户StudentId

View File

@ -11,7 +11,6 @@ import top.suyiiyii.sims.common.AuthAccess;
import top.suyiiyii.sims.common.Result; import top.suyiiyii.sims.common.Result;
import top.suyiiyii.sims.dto.CommonResponse; import top.suyiiyii.sims.dto.CommonResponse;
import top.suyiiyii.sims.dto.UserDto; import top.suyiiyii.sims.dto.UserDto;
import top.suyiiyii.sims.entity.User;
import top.suyiiyii.sims.exception.ServiceException; import top.suyiiyii.sims.exception.ServiceException;
import top.suyiiyii.sims.service.RoleService; import top.suyiiyii.sims.service.RoleService;
import top.suyiiyii.sims.service.UserService; import top.suyiiyii.sims.service.UserService;
@ -38,14 +37,7 @@ public class UserController {
RoleService roleService; RoleService roleService;
@AuthAccess @AuthAccess(allowRoles = {"guest"})
@GetMapping("/")
public Result hello() {
return Result.success("success");
}
@PostMapping("/user/login") @PostMapping("/user/login")
public Result<LoginResponse> login(@RequestBody LoginRequest request, HttpServletRequest httpServletRequest) { public Result<LoginResponse> login(@RequestBody LoginRequest request, HttpServletRequest httpServletRequest) {
log.info("login request:{}", request); log.info("login request:{}", request);
@ -63,6 +55,7 @@ public class UserController {
return Result.success(response); return Result.success(response);
} }
@AuthAccess(allowRoles = {"guest"})
@PostMapping("/user/register") @PostMapping("/user/register")
public Result<CommonResponse> register(@RequestBody RegisterRequest request) { public Result<CommonResponse> register(@RequestBody RegisterRequest request) {
log.info("register request:{}", request); log.info("register request:{}", request);
@ -73,19 +66,15 @@ public class UserController {
if (request.getPassword() == null || request.getPassword().length() < 3) { if (request.getPassword() == null || request.getPassword().length() < 3) {
throw new ServiceException("密码长度不能小于3位"); throw new ServiceException("密码长度不能小于3位");
} }
User user = new User();
user.setUsername(request.getUsername()); userService.register(request);
user.setPassword(request.getPassword());
user.setEmail(request.getEmail());
user.setGrade(request.getGrade());
user.setUserGroup(request.getUserGroup());
userService.register(user);
return Result.success(CommonResponse.factory("注册成功")); return Result.success(CommonResponse.factory("注册成功"));
} }
@Operation(description = "删除单个用户") @Operation(description = "删除单个用户")
@AuthAccess(allowRoles = {"admin"})
@DeleteMapping("/admin/user/{id}") @DeleteMapping("/admin/user/{id}")
public Result<CommonResponse> adminDelete(@PathVariable Integer id) { public Result<CommonResponse> adminDelete(@PathVariable Integer id) {
log.info("delete request:{}", id); log.info("delete request:{}", id);
@ -94,6 +83,7 @@ public class UserController {
} }
@Operation(description = "获取所有用户信息") @Operation(description = "获取所有用户信息")
@AuthAccess(allowRoles = {"admin"})
@GetMapping("/admin/user") @GetMapping("/admin/user")
public Result<List<UserDto>> adminGet() { public Result<List<UserDto>> adminGet() {
List<UserDto> allUsers = userService.findAllUsers(); List<UserDto> allUsers = userService.findAllUsers();
@ -101,6 +91,7 @@ public class UserController {
} }
@Operation(description = "根据 id 获取用户信息") @Operation(description = "根据 id 获取用户信息")
@AuthAccess(allowRoles = {"admin"})
@GetMapping("/admin/user/{id}") @GetMapping("/admin/user/{id}")
public Result<UserDto> adminGetById(@PathVariable Integer id) { public Result<UserDto> adminGetById(@PathVariable Integer id) {
log.info("selectById request:{}", id); log.info("selectById request:{}", id);
@ -109,6 +100,7 @@ public class UserController {
} }
@Operation(description = "获取当前用户信息") @Operation(description = "获取当前用户信息")
@AuthAccess(allowRoles = {"user"})
@GetMapping("/user/me") @GetMapping("/user/me")
public Result<UserDto> getSelf() { public Result<UserDto> getSelf() {
UserDto user = userService.findUser(0); UserDto user = userService.findUser(0);
@ -121,6 +113,7 @@ public class UserController {
private String username; private String username;
private Integer studentId; private Integer studentId;
private String password; private String password;
private String email; private String email;
private String grade; private String grade;
private String userGroup; private String userGroup;

View File

@ -4,9 +4,6 @@ import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
import java.util.List;
@Data @Data
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor

View File

@ -1,7 +1,6 @@
package top.suyiiyii.sims.entity; package top.suyiiyii.sims.entity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.tangzc.mpe.autotable.annotation.Table; import com.tangzc.mpe.autotable.annotation.Table;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;

View File

@ -1,7 +1,6 @@
package top.suyiiyii.sims.entity; package top.suyiiyii.sims.entity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableId;
import com.tangzc.mpe.autotable.annotation.Table; import com.tangzc.mpe.autotable.annotation.Table;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;

View File

@ -7,8 +7,6 @@ import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/** /**
* @Author tortoise * @Author tortoise
* @Date 2024/8/9 14:04 * @Date 2024/8/9 14:04

View File

@ -14,7 +14,7 @@ import java.time.LocalDateTime;
* @Date 2024/8/10 0:31 * @Date 2024/8/10 0:31
* @PackageName:top.suyiiyii.sims.entity * @PackageName:top.suyiiyii.sims.entity
* @ClassName: RevokeRequest * @ClassName: RevokeRequest
* @Description: 存储普通成员提出的奖惩撤销申请并跟踪申请状态 * @Description: 存储普通成员提出的奖惩撤销申请并跟踪申请状态
* @Version 1.0 * @Version 1.0
*/ */
@Data @Data

View File

@ -14,7 +14,7 @@ import java.time.LocalDateTime;
* @Date 2024/8/10 0:34 * @Date 2024/8/10 0:34
* @PackageName:top.suyiiyii.sims.entity * @PackageName:top.suyiiyii.sims.entity
* @ClassName: RevokedRecord * @ClassName: RevokedRecord
* @Description: 存储管理员对奖惩记录的撤销信息包括撤销原因 * @Description: 存储管理员对奖惩记录的撤销信息包括撤销原因
* @Version 1.0 * @Version 1.0
*/ */
@Data @Data

View File

@ -1,7 +1,8 @@
package top.suyiiyii.sims.entity; package top.suyiiyii.sims.entity;
import com.baomidou.mybatisplus.annotation.IdType; 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 com.tangzc.mpe.autotable.annotation.Table;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
@ -20,10 +21,16 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public class Role { 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", "");
}
} }

View File

@ -1,15 +1,13 @@
package top.suyiiyii.sims.entity; package top.suyiiyii.sims.entity;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField; import com.tangzc.autotable.annotation.ColumnNotNull;
import com.baomidou.mybatisplus.annotation.TableId; import com.tangzc.mpe.autotable.annotation.ColumnId;
import com.tangzc.mpe.autotable.annotation.Table; import com.tangzc.mpe.autotable.annotation.Table;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import java.security.Permission;
/** /**
* @Author tortoise * @Author tortoise
* @Date 2024/8/9 14:03 * @Date 2024/8/9 14:03
@ -23,8 +21,12 @@ import java.security.Permission;
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public class RolePermission { public class RolePermission {
@TableId(type= IdType.AUTO)
@ColumnId(mode = IdType.AUTO, comment = "id主键")
private Integer id; private Integer id;
@ColumnNotNull
private Integer roleId; private Integer roleId;
@ColumnNotNull
private Integer permissionId; private Integer permissionId;
} }

View File

@ -1,8 +1,12 @@
package top.suyiiyii.sims.entity; package top.suyiiyii.sims.entity;
import com.baomidou.mybatisplus.annotation.IdType; 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.Table;
import com.tangzc.mpe.autotable.annotation.UniqueIndex;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
@ -20,12 +24,25 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public class User { public class User {
@TableId(type= IdType.AUTO)
@ColumnId(mode = IdType.AUTO, comment = "id主键")
private Integer id; private Integer id;
@UniqueIndex
@Column(comment = "学生id", notNull = true)
private Integer studentId; private Integer studentId;
@UniqueIndex
@Column(comment = "用户名", notNull = true)
private String username; private String username;
@Column(comment = "密码", notNull = true)
private String password; private String password;
@UniqueIndex
@Column(comment = "邮箱", notNull = true)
private String email; private String email;
@UniqueIndex
@Column(comment = "年级", notNull = true)
private String grade; private String grade;
@UniqueIndex
@Column(comment = "用户所属团队", notNull = true)
private String userGroup; private String userGroup;
} }

View File

@ -1,7 +1,8 @@
package top.suyiiyii.sims.entity; package top.suyiiyii.sims.entity;
import com.baomidou.mybatisplus.annotation.IdType; 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 com.tangzc.mpe.autotable.annotation.Table;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Data; import lombok.Data;
@ -20,8 +21,12 @@ import lombok.NoArgsConstructor;
@AllArgsConstructor @AllArgsConstructor
@NoArgsConstructor @NoArgsConstructor
public class UserRole { public class UserRole {
@TableId(type= IdType.AUTO)
@ColumnId(mode = IdType.AUTO, comment = "id主键")
private Integer id; private Integer id;
@ColumnNotNull
private Integer userId; private Integer userId;
@ColumnNotNull
private Integer roleId; private Integer roleId;
} }

View File

@ -1,5 +1,6 @@
package top.suyiiyii.sims.exception; package top.suyiiyii.sims.exception;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
@ -13,11 +14,15 @@ import top.suyiiyii.sims.common.Result;
* @Description: TODO * @Description: TODO
* @Version 1.0 * @Version 1.0
*/ */
@Slf4j
@ControllerAdvice @ControllerAdvice
public class GlobalException { public class GlobalException {
@ExceptionHandler(ServiceException.class) @ExceptionHandler(ServiceException.class)
@ResponseBody @ResponseBody
public Result ServiceException(ServiceException e){ public Result ServiceException(ServiceException e) {
return Result.error(e.getCode(),e.getMessage()); log.warn("ServiceException:{}", e.getMessage());
// 打印错误调用栈
log.warn("ServiceException:", e);
return Result.error(e.getCode(), e.getMessage());
} }
} }

View File

@ -11,14 +11,15 @@ import lombok.Getter;
* @Version 1.0 * @Version 1.0
*/ */
@Getter @Getter
public class ServiceException extends RuntimeException{ public class ServiceException extends RuntimeException {
public final String code; public final String code;
public ServiceException(String msg){ public ServiceException(String msg) {
super(msg); super(msg);
this.code = "500"; this.code = "500";
} }
public ServiceException(String code ,String msg){
public ServiceException(String code, String msg) {
super(msg); super(msg);
this.code = code; this.code = code;
} }

View File

@ -17,7 +17,8 @@ public interface CategoryMapper {
String getCategoryName(Integer categoryId); String getCategoryName(Integer categoryId);
@Select("SELECT category_name FROM reward_punishment_category WHERE category_id=#{categoryId}") @Select("SELECT category_name FROM reward_punishment_category WHERE category_id=#{categoryId}")
String getSubCategoryName(Integer categoryId); String getSubCategoryName(Integer categoryId);
@Select("SELECT category_id FROM reward_punishment_category WHERE sub_category_name=#{subCategoryName}")
@Select("SELECT category_id FROM reward_punishment_category WHERE sub_category_name=#{subCategoryName}")
Integer getIdBySubCategoryName(String subCategoryName); Integer getIdBySubCategoryName(String subCategoryName);
} }

View File

@ -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<Role> {
}

View File

@ -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<UserRole> {
}

View File

@ -1,6 +1,5 @@
package top.suyiiyii.sims.mapper; package top.suyiiyii.sims.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Select;
import top.suyiiyii.sims.entity.Permissions; import top.suyiiyii.sims.entity.Permissions;
@ -17,9 +16,10 @@ import java.util.List;
* @Version 1.0 * @Version 1.0
*/ */
@Mapper @Mapper
public interface PermissionsMapper { public interface PermissionsMapper {
@Select("SELECT * FROM role_permission WHERE role_id = #{id}") @Select("SELECT * FROM role_permission WHERE role_id = #{id}")
List<RolePermission> getRolePerminsionByRoleId(Integer id); List<RolePermission> getRolePerminsionByRoleId(Integer id);
@Select("SELECT * FROM permissions WHERE permission_id = #{permissionId}")
@Select("SELECT * FROM permissions WHERE permission_id = #{permissionId}")
Permissions selectById(Integer permissionId); Permissions selectById(Integer permissionId);
} }

View File

@ -16,11 +16,12 @@ import java.util.List;
@Mapper @Mapper
public interface RecordMapper { public interface RecordMapper {
//分页查询 //分页查询
@Select("select * from record limit #{page},#{size}") @Select("select * from record limit #{page},#{size}")
List<Record> getAllRecords(Integer page, Integer size); List<Record> getAllRecords(Integer page, Integer size);
//根据学号分页查询所以信息
//根据学号分页查询所以信息
@Select("select * from record where student_id = #{id} limit #{page},#{size}") @Select("select * from record where student_id = #{id} limit #{page},#{size}")
List<Record> getMyAllRecords(Integer page, Integer size, Integer id); List<Record> getMyAllRecords(Integer page, Integer size, String id);
//根据id更新对应信息 //根据id更新对应信息
@Update("UPDATE record SET " @Update("UPDATE record SET "
@ -39,6 +40,7 @@ public interface RecordMapper {
void updateRecord(Record record, Integer id); void updateRecord(Record record, Integer id);
@Delete("delete from record where id = #{id}") @Delete("delete from record where id = #{id}")
void deleteRecord(Integer id); void deleteRecord(Integer id);
@Insert({ @Insert({
"insert into record (student_id, category_id, `date`, content, reason, amount, remark, is_revoked,", "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)", "revoke_date, revoke_reason, revoke_remark, operator_user_id, last_update_time)",

View File

@ -1,12 +1,8 @@
package top.suyiiyii.sims.mapper; package top.suyiiyii.sims.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import lombok.Data;
import org.apache.ibatis.annotations.*; import org.apache.ibatis.annotations.*;
import top.suyiiyii.sims.entity.Permissions;
import top.suyiiyii.sims.entity.Role; import top.suyiiyii.sims.entity.Role;
import top.suyiiyii.sims.entity.User; import top.suyiiyii.sims.entity.User;
import top.suyiiyii.sims.entity.UserRole;
import java.util.List; import java.util.List;
@ -22,15 +18,18 @@ import java.util.List;
public interface RoleMapper { public interface RoleMapper {
@Insert("INSERT INTO role(name) VALUES(#{name}") @Insert("INSERT INTO role(name) VALUES(#{name}")
void addRole(String name); void addRole(String name);
@Delete("DELETE FROM role WHERE name=#{name}")
@Delete("DELETE FROM role WHERE name=#{name}")
void deleteRole(String 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); void updateRole(String name, String newName);
/** /**
* @param
* @author: tortoise * @author: tortoise
* @date: 2024/8/14 14:23 * @date: 2024/8/14 14:23
* @Description: TODO 查询用户信息 * @Description: TODO 查询用户信息
* @param
* @return: java.util.List<top.suyiiyii.sims.entity.User> * @return: java.util.List<top.suyiiyii.sims.entity.User>
*/ */
@Select("SELECT u.username, u.name, u.userId, r.role_name " + @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})") "(SELECT role_id FROM user_role WHERE user_id = #{user_id})")
List<Role> selectRolesById(@Param("user_id") int id); List<Role> 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<String> selectRoleNamesByRoleId(Integer roleId); List<String> selectRoleNamesByRoleId(Integer roleId);
@Select("SELECT user_id " + @Select("SELECT user_id " +

View File

@ -2,7 +2,6 @@ package top.suyiiyii.sims.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.*; import org.apache.ibatis.annotations.*;
import top.suyiiyii.sims.entity.Role;
import top.suyiiyii.sims.entity.User; import top.suyiiyii.sims.entity.User;
import java.util.List; import java.util.List;
@ -19,14 +18,18 @@ import java.util.List;
public interface UserMapper extends BaseMapper<User> { public interface UserMapper extends BaseMapper<User> {
/** /**
* 添加新用户 * 添加新用户
*
* @param user 新用户对象 * @param user 新用户对象
* @return 影响的行数 * @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); int addUser(User user);
/** /**
* 根据ID删除用户 * 根据ID删除用户
*
* @param id 用户ID * @param id 用户ID
* @return 影响的行数 * @return 影响的行数
*/ */
@ -35,6 +38,7 @@ public interface UserMapper extends BaseMapper<User> {
/** /**
* 更新用户信息 * 更新用户信息
*
* @param user 更新后的用户对象 * @param user 更新后的用户对象
* @return 影响的行数 * @return 影响的行数
*/ */
@ -42,40 +46,54 @@ public interface UserMapper extends BaseMapper<User> {
"student_id = #{userId}, " + "student_id = #{userId}, " +
"username = #{username}, " + "username = #{username}, " +
"username = #{name}, " +
"email = #{email}, " + "email = #{email}, " +
"grade = #{grade}, " + "grade = #{grade}, " +
"userGroup = #{group} " + "user_group = #{group} " +
"WHERE id = #{id}") "WHERE id = #{id}")
int updateUser(User user); int updateUser(User user);
/** /**
* 根据ID查询用户信息 * 根据ID查询用户信息
*
* @param * @param
* @return 用户对象 * @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); User selectByUserId(Integer id);
/** /**
* 根据iD查询用户信息 * 根据iD查询用户信息
*
* @param * @param
* @return 用户对象 * @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); User selectById(Integer id);
/** /**
* 查询所有用户信息 * 查询所有用户信息
*
* @return 用户列表 * @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<User> selectAll(); List<User> selectAll();
@Select("select * from user where username = #{username}") @Select("select * from user where username = #{username}")
User selectByUserName(@Param("username") String username); User selectByUserName(@Param("username") String username);
@Update("update user set password = #{password} where username = #{username}")
@Update("update user set password = #{password} where username = #{username}")
void updatePassword(User user); 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}") @Select("select student_id from user where id = #{userId}")
Integer selectStudentIdByUserId(Integer id); String getStudentIdById(String userId);
} }

View File

@ -19,7 +19,7 @@ public class CategoryService {
public String getCategoryName(Integer id) { public String getCategoryName(Integer id) {
return categoryMapper.getCategoryName(id); return categoryMapper.getCategoryName(id);
} }
public String getsubCategoryName(Integer categoryId) { public String getsubCategoryName(Integer categoryId) {

View File

@ -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<Role> getRolesByUserId(int userId) {
// 根据用户id获取用户的角色id使用mp的条件构造器
List<UserRole> userRoles = userRoleMapper.selectList(new QueryWrapper<UserRole>().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<Role>().eq("role_name", roleName));
if (role == null) {
Role newRole = new Role();
newRole.setRoleName(roleName);
roleMapper.insert(newRole);
role = roleMapper.selectOne(new QueryWrapper<Role>().eq("role_name", roleName));
}
UserRole userRole = new UserRole();
userRole.setUserId(userId);
userRole.setRoleId(role.getId());
return userRoleMapper.insert(userRole) > 0;
}
}

View File

@ -32,7 +32,7 @@ public class RecordService {
public List<Record> getMyAllRecords(Integer page, Integer size, String userId) { public List<Record> 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); return recordMapper.getMyAllRecords(page, size, studentId);
} }

View File

@ -1,11 +1,9 @@
package top.suyiiyii.sims.service; package top.suyiiyii.sims.service;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import top.suyiiyii.sims.entity.Role; import top.suyiiyii.sims.entity.Role;
import top.suyiiyii.sims.entity.User; import top.suyiiyii.sims.entity.User;
import top.suyiiyii.sims.entity.UserRole;
import top.suyiiyii.sims.mapper.RoleMapper; import top.suyiiyii.sims.mapper.RoleMapper;
import java.util.List; import java.util.List;
@ -23,23 +21,22 @@ public class RoleService {
@Autowired @Autowired
RoleMapper roleMapper; RoleMapper roleMapper;
public List<User> findAllUsersWithRoles(){ public List<User> findAllUsersWithRoles() {
return roleMapper.selectAllUsersWithRoles(); return roleMapper.selectAllUsersWithRoles();
} }
/** /**
* @param
* @author: tortoise * @author: tortoise
* @date: 2024/8/14 14:39 * @date: 2024/8/14 14:39
* @Description: TODO 查看自己身份 * @Description: TODO 查看自己身份
* @param Id
* @return: java.util.List<top.suyiiyii.sims.entity.Role> * @return: java.util.List<top.suyiiyii.sims.entity.Role>
*/ */
public List<Role> selectRolesById(int id){ public List<Role> selectRolesById(int id) {
return roleMapper.selectRolesById(id); return roleMapper.selectRolesById(id);
} }
public boolean isRoleNameAdmin(Integer id) { public boolean isRoleNameAdmin(Integer id) {
List<Role> roles = roleMapper.selectRolesById(id); List<Role> roles = roleMapper.selectRolesById(id);
for (Role role : roles) { for (Role role : roles) {

View File

@ -1,21 +1,23 @@
package top.suyiiyii.sims.service; 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.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import top.suyiiyii.sims.controller.UserController;
import top.suyiiyii.sims.dto.UserDto; 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.exception.ServiceException;
import top.suyiiyii.sims.mapper.MpUserMapper;
import top.suyiiyii.sims.mapper.PermissionsMapper; import top.suyiiyii.sims.mapper.PermissionsMapper;
import top.suyiiyii.sims.mapper.RoleMapper; import top.suyiiyii.sims.mapper.RoleMapper;
import top.suyiiyii.sims.mapper.UserMapper; import top.suyiiyii.sims.mapper.UserMapper;
import top.suyiiyii.sims.utils.JwtUtils; import top.suyiiyii.sims.utils.JwtUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet;
import java.util.List; import java.util.List;
/** /**
@ -31,9 +33,17 @@ public class UserService {
@Autowired @Autowired
UserMapper userMapper; UserMapper userMapper;
@Autowired @Autowired
MpUserMapper mpUserMapper;
@Autowired
RoleMapper roleMapper; RoleMapper roleMapper;
@Autowired @Autowired
PermissionsMapper permissionsMapper; PermissionsMapper permissionsMapper;
@Value("${jwt.secret}")
private String secret;
@Autowired
private RbacService rbacService;
@Autowired
private ModelMapper modelMapper;
public void addUser(User user) { public void addUser(User user) {
userMapper.addUser(user); userMapper.addUser(user);
@ -50,8 +60,9 @@ public class UserService {
public List<User> selectAll() { public List<User> selectAll() {
return userMapper.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); User dbUser = userMapper.selectByUserName(username);
if (dbUser == null) { if (dbUser == null) {
@ -60,59 +71,50 @@ public class UserService {
if (!dbUser.getPassword().equals(password)) { if (!dbUser.getPassword().equals(password)) {
throw new ServiceException("密码或用户名错误"); throw new ServiceException("密码或用户名错误");
} }
HashSet<Permissions> permissionsSet = new HashSet<>(); return JwtUtils.createToken(dbUser.getId().toString(), secret);
Integer id = dbUser.getId(); }
List<Role> roles = roleMapper.selectRolesById(id);
for (Role role : roles) {
//根据roleid找所有permissionId public void register(UserController.RegisterRequest req) {
List<RolePermission> rolePerminsion = permissionsMapper.getRolePerminsionByRoleId(role.getRoleId());
for (RolePermission rolePermission : rolePerminsion) { User dbUser = userMapper.selectByUserId(req.getStudentId());
Integer permissionId = rolePermission.getPermissionId();
//根据permissionId找permission if (req.getUsername() == null || req.getUsername().equals("")) {
Permissions permissions = permissionsMapper.selectById(permissionId); throw new ServiceException("用户名不能为空");
permissionsSet.add(permissions);
}
} }
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) { if (dbUser != null) {
throw new ServiceException("账号已经存在"); 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("密码不能为空"); throw new ServiceException("密码不能为空");
} }
if (user.getEmail() == null || user.getEmail().equals("")) { if (req.getEmail() == null || req.getEmail().equals("")) {
throw new ServiceException("邮箱不能为空"); throw new ServiceException("邮箱不能为空");
} }
if (user.getUserGroup() == null || user.getUserGroup().equals("")) { if (req.getUserGroup() == null || req.getUserGroup().equals("")) {
throw new ServiceException("组别不能为空"); throw new ServiceException("组别不能为空");
} }
User user = modelMapper.map(req, User.class);
userMapper.addUser(user); mpUserMapper.insert(user);
return user; user = mpUserMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getUsername, req.getUsername()));
rbacService.addRoleWithUserId(user.getId(), "user");
} }
public User selectByUsername(String username) { public User selectByUsername(String username) {
return userMapper.selectByUserName(username); return userMapper.selectByUserName(username);
} }
public void updatePassword(User user) { public void updatePassword(User user) {
userMapper.updatePassword(user); userMapper.updatePassword(user);
} }
public List<UserDto> findAllUsers(){
public List<UserDto> findAllUsers() {
List<User> users = userMapper.selectAll(); List<User> users = userMapper.selectAll();
List<UserDto> UserDtos = new ArrayList<>(); List<UserDto> UserDtos = new ArrayList<>();
@ -126,7 +128,7 @@ public class UserService {
Integer id = user.getId(); Integer id = user.getId();
List<Role> roles = roleMapper.selectRolesById(id); List<Role> roles = roleMapper.selectRolesById(id);
for (Role role : roles) { for (Role role : roles) {
Integer roleId = role.getRoleId(); Integer roleId = role.getId();
// 获取一个角色的名称列表 // 获取一个角色的名称列表
List<String> roleNameList = roleMapper.selectRoleNamesByRoleId(roleId); List<String> roleNameList = roleMapper.selectRoleNamesByRoleId(roleId);
// 累加角色名称到用户的角色列表中 // 累加角色名称到用户的角色列表中
@ -136,6 +138,7 @@ public class UserService {
} }
return UserDtos; return UserDtos;
} }
public UserDto findUser(Integer id) { public UserDto findUser(Integer id) {
UserDto UserDto = new UserDto(); UserDto UserDto = new UserDto();
@ -147,7 +150,7 @@ public class UserService {
UserDto.setRoles(new ArrayList<>()); UserDto.setRoles(new ArrayList<>());
List<Role> roles = roleMapper.selectRolesById(id); List<Role> roles = roleMapper.selectRolesById(id);
for (Role role : roles) { for (Role role : roles) {
Integer roleId = role.getRoleId(); Integer roleId = role.getId();
// 获取一个角色的名称列表 // 获取一个角色的名称列表
List<String> roleNameList = roleMapper.selectRoleNamesByRoleId(roleId); List<String> roleNameList = roleMapper.selectRoleNamesByRoleId(roleId);
// 累加角色名称到用户的角色列表中 // 累加角色名称到用户的角色列表中
@ -165,7 +168,6 @@ public class UserService {
} }
public Integer selectStudentIdByUserId(Integer userId) {
return userMapper.selectStudentIdByUserId(userId);
}
} }

View File

@ -30,17 +30,13 @@ public class JwtUtils {
private static UserMapper staticUserMapper; private static UserMapper staticUserMapper;
@Resource @Resource
UserMapper userMapper; UserMapper userMapper;
@PostConstruct
public void setUserService() {
staticUserMapper=userMapper;
}
/** /**
* @param userId
* @param sign
* @author: tortoise * @author: tortoise
* @date: 2024/8/1 15:12 * @date: 2024/8/1 15:12
* @Description: 生成token * @Description: 生成token
* @param userId
* @param sign
* @return: java.lang.String * @return: java.lang.String
*/ */
public static String createToken(String userId, String sign) { public static String createToken(String userId, String sign) {
@ -48,8 +44,9 @@ public class JwtUtils {
.withAudience(userId) .withAudience(userId)
.withExpiresAt(DateUtil.offsetHour(new Date(), 2)) .withExpiresAt(DateUtil.offsetHour(new Date(), 2))
.sign(Algorithm.HMAC256(sign)); .sign(Algorithm.HMAC256(sign));
// 设置令牌过期时间为2小时 // 设置令牌过期时间为2小时
} }
public static User getCurrentUser() { public static User getCurrentUser() {
try { try {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
@ -63,6 +60,7 @@ public class JwtUtils {
} }
return null; return null;
} }
// 验证 JWT 令牌 // 验证 JWT 令牌
public static boolean verifyToken(String token, String secret) { public static boolean verifyToken(String token, String secret) {
try { try {
@ -74,6 +72,7 @@ public class JwtUtils {
return false; return false;
} }
} }
public static String extractUserId(String token) { public static String extractUserId(String token) {
try { try {
return JWT.decode(token).getAudience().get(0); // token 中提取用户ID return JWT.decode(token).getAudience().get(0); // token 中提取用户ID
@ -82,4 +81,9 @@ public class JwtUtils {
return null; return null;
} }
} }
@PostConstruct
public void setUserService() {
staticUserMapper = userMapper;
}
} }

View File

@ -5,4 +5,5 @@ spring:
username: username:
password: password:
jwt:
secret: SuyiiyiiiiiiyiiiiTTTTTTTTTTTestttttttttttttt

View File

@ -11,4 +11,7 @@ spring:
auto-table: auto-table:
enable: true enable: true
model-package: top.suyiiyii.sims.entity model-package: top.suyiiyii.sims.entity
jwt:
secret: ${JWT_SECRET}

View File

@ -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);
}
}

View File

@ -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<Role> roles = rbacService.getRolesByUserId(userId);
assertNotNull(roles);
assert roles.stream().map(Role::getRoleName).toList().contains("ROLE"); // mock roleName
}
}