commit
3c852421d5
2
.gitignore
vendored
2
.gitignore
vendored
@ -140,3 +140,5 @@ gradle-app.setting
|
||||
# JDT-specific (Eclipse Java Development Tools)
|
||||
.classpath
|
||||
|
||||
# Running
|
||||
run/
|
19
.idea/dataSources.xml
generated
Normal file
19
.idea/dataSources.xml
generated
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||
<data-source source="LOCAL" name="itzx@wzpmc.cn" uuid="6d73dcf2-41f4-4403-89d0-be443cbd1b39">
|
||||
<driver-ref>mysql.8</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<imported>true</imported>
|
||||
<remarks>$PROJECT_DIR$/src/main/resources/application.properties</remarks>
|
||||
<jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
|
||||
<jdbc-url>jdbc:mysql://wzpmc.cn:3306/itzx</jdbc-url>
|
||||
<jdbc-additional-properties>
|
||||
<property name="com.intellij.clouds.kubernetes.db.host.port" />
|
||||
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
|
||||
<property name="com.intellij.clouds.kubernetes.db.container.port" />
|
||||
</jdbc-additional-properties>
|
||||
<working-dir>$ProjectFileDir$</working-dir>
|
||||
</data-source>
|
||||
</component>
|
||||
</project>
|
12
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
12
.idea/inspectionProfiles/Project_Default.xml
generated
Normal file
@ -0,0 +1,12 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="IncorrectHttpHeaderInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="customHeaders">
|
||||
<set>
|
||||
<option value="Set-Authorization" />
|
||||
</set>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
20
.idea/jarRepositories.xml
generated
20
.idea/jarRepositories.xml
generated
@ -16,5 +16,25 @@
|
||||
<option name="name" value="MavenRepo" />
|
||||
<option name="url" value="https://repo.maven.apache.org/maven2/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven" />
|
||||
<option name="name" value="maven" />
|
||||
<option name="url" value="https://maven.aliyun.com/repository/gradle-plugin" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven4" />
|
||||
<option name="name" value="maven4" />
|
||||
<option name="url" value="https://mirrors.cloud.tencent.com/repository/maven/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven2" />
|
||||
<option name="name" value="maven2" />
|
||||
<option name="url" value="https://maven.aliyun.com/repository/public/" />
|
||||
</remote-repository>
|
||||
<remote-repository>
|
||||
<option name="id" value="maven3" />
|
||||
<option name="name" value="maven3" />
|
||||
<option name="url" value="https://repo.huaweicloud.com/repository/maven/" />
|
||||
</remote-repository>
|
||||
</component>
|
||||
</project>
|
9
.idea/modules.xml
generated
Normal file
9
.idea/modules.xml
generated
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/clubs.iml" filepath="$PROJECT_DIR$/.idea/modules/clubs.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/clubs.main.iml" filepath="$PROJECT_DIR$/.idea/modules/clubs.main.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
10
.idea/modules/clubs.iml
generated
Normal file
10
.idea/modules/clubs.iml
generated
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module version="4">
|
||||
<component name="AdditionalModuleElements">
|
||||
<content url="file://$MODULE_DIR$/../.." dumb="true">
|
||||
<excludeFolder url="file://$MODULE_DIR$/../dataSources" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/../dictionaries" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/../../run" />
|
||||
</content>
|
||||
</component>
|
||||
</module>
|
8
.idea/modules/clubs.main.iml
generated
Normal file
8
.idea/modules/clubs.main.iml
generated
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module version="4">
|
||||
<component name="AdditionalModuleElements">
|
||||
<content url="file://$MODULE_DIR$/../../build/generated/sources/annotationProcessor/java/main">
|
||||
<sourceFolder url="file://$MODULE_DIR$/../../build/generated/sources/annotationProcessor/java/main" isTestSource="false" generated="true" />
|
||||
</content>
|
||||
</component>
|
||||
</module>
|
33
README.md
33
README.md
@ -1,4 +1,33 @@
|
||||
# ITZX-Clubs-Home-Server
|
||||
|
||||
A clubs home for Hangzhou Electron & Information Vocational School
|
||||
building by springboot3.0 with mysql db
|
||||
A clubs home for Hangzhou Electron & Information Vocational School
|
||||
building by springboot3.0 with mysql db
|
||||
---
|
||||
## Usage
|
||||
|
||||
### 1.Create user table
|
||||
|
||||
```mysql
|
||||
create table user
|
||||
(
|
||||
id int comment '用户ID(自增)',
|
||||
name varchar(20) not null comment '用户名',
|
||||
password char(40) not null comment '密码(使用SHA1)',
|
||||
auth int default 0 not null comment '用户对应权限组ID',
|
||||
avatar char(40) null comment '用户头像sha1',
|
||||
create_time datetime default now() not null comment '用户创建时间',
|
||||
update_time datetime default now() not null on update now() comment '用户数据更新时间'
|
||||
)
|
||||
comment '用户表';
|
||||
|
||||
create unique index user_id_index
|
||||
on user (id)
|
||||
comment '用户表主键';
|
||||
|
||||
alter table user
|
||||
add constraint user_pk
|
||||
primary key (id) comment '用户表主键';
|
||||
|
||||
alter table user
|
||||
modify id int auto_increment comment '用户ID(自增)';
|
||||
```
|
||||
|
@ -4,6 +4,7 @@ plugins {
|
||||
id("io.spring.dependency-management") version "1.1.4"
|
||||
id("org.graalvm.buildtools.native") version "0.9.28"
|
||||
id("org.asciidoctor.jvm.convert") version "3.3.2"
|
||||
id("org.springdoc.openapi-gradle-plugin") version "1.8.0"
|
||||
}
|
||||
|
||||
group = "org.mmga"
|
||||
@ -20,6 +21,10 @@ configurations {
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven { url = uri("https://maven.aliyun.com/repository/gradle-plugin") }
|
||||
maven { url = uri("https://maven.aliyun.com/repository/public/") }
|
||||
maven { url = uri("https://repo.huaweicloud.com/repository/maven/") }
|
||||
maven { url = uri("https://mirrors.cloud.tencent.com/repository/maven/") }
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
@ -32,13 +37,18 @@ dependencies {
|
||||
implementation("org.springframework.boot:spring-boot-starter-websocket")
|
||||
implementation("org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3")
|
||||
implementation("org.springframework.shell:spring-shell-starter")
|
||||
implementation("org.springdoc:springdoc-openapi-starter-webmvc-api:2.5.0")
|
||||
implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:2.5.0")
|
||||
// https://mvnrepository.com/artifact/commons-codec/commons-codec
|
||||
implementation("commons-codec:commons-codec:1.16.1")
|
||||
// https://mvnrepository.com/artifact/com.auth0/java-jwt
|
||||
implementation("com.auth0:java-jwt:4.4.0")
|
||||
compileOnly("org.projectlombok:lombok")
|
||||
developmentOnly("org.springframework.boot:spring-boot-devtools")
|
||||
runtimeOnly("com.mysql:mysql-connector-j")
|
||||
annotationProcessor("org.projectlombok:lombok")
|
||||
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
||||
testImplementation("org.mybatis.spring.boot:mybatis-spring-boot-starter-test:3.0.3")
|
||||
testImplementation("org.springframework.restdocs:spring-restdocs-mockmvc")
|
||||
}
|
||||
|
||||
dependencyManagement {
|
||||
|
31
src/main/java/org/mmga/clubs/commands/UserCommands.java
Normal file
31
src/main/java/org/mmga/clubs/commands/UserCommands.java
Normal file
@ -0,0 +1,31 @@
|
||||
package org.mmga.clubs.commands;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.mmga.clubs.controller.UserController;
|
||||
import org.mmga.clubs.entities.BaseResponse;
|
||||
import org.mmga.clubs.entities.user.User;
|
||||
import org.mmga.clubs.entities.user.UserLoginVo;
|
||||
import org.mmga.clubs.entities.user.UserRegVo;
|
||||
import org.mmga.clubs.utils.ShellUtils;
|
||||
import org.springframework.shell.standard.ShellComponent;
|
||||
import org.springframework.shell.standard.ShellMethod;
|
||||
|
||||
@ShellComponent
|
||||
@Slf4j
|
||||
public class UserCommands {
|
||||
private final UserController userController;
|
||||
public UserCommands(UserController userController){
|
||||
this.userController = userController;
|
||||
}
|
||||
@ShellMethod("创建用户")
|
||||
public void createUser(String name, String password) {
|
||||
BaseResponse<User> user = this.userController.createUser(new UserRegVo(name, DigestUtils.md5Hex(password), 1), null);
|
||||
ShellUtils.logToResult(log, user);
|
||||
}
|
||||
@ShellMethod("登录")
|
||||
public void login(String name, String password) {
|
||||
BaseResponse<User> user = this.userController.login(new UserLoginVo(name, DigestUtils.md5Hex(password)), null);
|
||||
ShellUtils.logToResult(log, user);
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package org.mmga.clubs.configuration;
|
||||
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.info.Info;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class DocsConfiguration {
|
||||
@Bean
|
||||
public OpenAPI api(){
|
||||
return new OpenAPI().info(new Info()
|
||||
.title("ITZX-Clubs-Home")
|
||||
.description("杭州电子信息职业学校社团主页"));
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
package org.mmga.clubs.configuration;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.security.KeyFactory;
|
||||
import java.security.KeyPair;
|
||||
import java.security.KeyPairGenerator;
|
||||
import java.security.interfaces.ECPrivateKey;
|
||||
import java.security.interfaces.ECPublicKey;
|
||||
import java.security.spec.ECGenParameterSpec;
|
||||
import java.security.spec.PKCS8EncodedKeySpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
|
||||
@Configuration
|
||||
public class ECKeyProviderConfiguration {
|
||||
private KeyPair keyPair;
|
||||
private ECPublicKey publicKey;
|
||||
private ECPrivateKey privateKey;
|
||||
@SneakyThrows
|
||||
public KeyPair keyPair(){
|
||||
if (this.keyPair != null){
|
||||
return this.keyPair;
|
||||
}
|
||||
KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("EC");
|
||||
ECGenParameterSpec ecGenParameterSpec = new ECGenParameterSpec("secp256r1");
|
||||
keyPairGenerator.initialize(ecGenParameterSpec);
|
||||
this.keyPair = keyPairGenerator.generateKeyPair();
|
||||
return this.keyPair;
|
||||
}
|
||||
@SneakyThrows
|
||||
@Bean
|
||||
public ECPublicKey ecPublicKey(){
|
||||
if (this.publicKey == null){
|
||||
File file = new File("jwt_pub.pem");
|
||||
if (file.exists()){
|
||||
FileInputStream publicKeyInputStream = new FileInputStream(file);
|
||||
byte[] publicKeyData = publicKeyInputStream.readAllBytes();
|
||||
publicKeyInputStream.close();
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("EC");
|
||||
this.publicKey = (ECPublicKey) keyFactory.generatePublic(new X509EncodedKeySpec(publicKeyData));
|
||||
}else {
|
||||
this.publicKey = (ECPublicKey) keyPair().getPublic();
|
||||
if (!file.createNewFile()) {
|
||||
throw new RuntimeException("Can't create public key file");
|
||||
}
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(file);
|
||||
fileOutputStream.write(publicKey.getEncoded());
|
||||
fileOutputStream.close();
|
||||
}
|
||||
}
|
||||
return this.publicKey;
|
||||
}
|
||||
@SneakyThrows
|
||||
@Bean
|
||||
public ECPrivateKey ecPrivateKey(){
|
||||
if (this.privateKey == null){
|
||||
File file = new File("jwt_pri.pem");
|
||||
if (file.exists()){
|
||||
FileInputStream publicKeyInputStream = new FileInputStream(file);
|
||||
byte[] publicKeyData = publicKeyInputStream.readAllBytes();
|
||||
publicKeyInputStream.close();
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("EC");
|
||||
this.privateKey = (ECPrivateKey) keyFactory.generatePrivate(new PKCS8EncodedKeySpec(publicKeyData));
|
||||
}else {
|
||||
this.privateKey = (ECPrivateKey) keyPair().getPrivate();
|
||||
if (!file.createNewFile()) {
|
||||
throw new RuntimeException("Can't create private key file");
|
||||
}
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(file);
|
||||
fileOutputStream.write(privateKey.getEncoded());
|
||||
fileOutputStream.close();
|
||||
}
|
||||
}
|
||||
return this.privateKey;
|
||||
}
|
||||
}
|
36
src/main/java/org/mmga/clubs/controller/UserController.java
Normal file
36
src/main/java/org/mmga/clubs/controller/UserController.java
Normal file
@ -0,0 +1,36 @@
|
||||
package org.mmga.clubs.controller;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.mmga.clubs.entities.BaseResponse;
|
||||
import org.mmga.clubs.entities.user.User;
|
||||
import org.mmga.clubs.entities.user.UserLoginVo;
|
||||
import org.mmga.clubs.entities.user.UserRegVo;
|
||||
import org.mmga.clubs.service.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/user")
|
||||
@Tag(name = "用户", description = "用户相关接口")
|
||||
@Slf4j
|
||||
public class UserController {
|
||||
private final UserService service;
|
||||
@Autowired
|
||||
public UserController(UserService userService){
|
||||
this.service = userService;
|
||||
}
|
||||
@PostMapping("/login")
|
||||
@Operation(description = "用户登录", responses = {@ApiResponse(description = "返回是否登录成功", responseCode = "200")})
|
||||
public BaseResponse<User> login(@RequestBody UserLoginVo user, HttpServletResponse response){
|
||||
return service.login(user, response);
|
||||
}
|
||||
@PutMapping("/create")
|
||||
@Operation(description = "创建用户", responses = {@ApiResponse(description = "返回创建后的用户")})
|
||||
public BaseResponse<User> createUser(@RequestBody UserRegVo user, HttpServletResponse response){
|
||||
return service.createUser(user, response);
|
||||
}
|
||||
}
|
9
src/main/java/org/mmga/clubs/dao/AuthDao.java
Normal file
9
src/main/java/org/mmga/clubs/dao/AuthDao.java
Normal file
@ -0,0 +1,9 @@
|
||||
package org.mmga.clubs.dao;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.mmga.clubs.entities.auth.AuthVo;
|
||||
|
||||
@Mapper
|
||||
public interface AuthDao {
|
||||
AuthVo getAuthById(int id);
|
||||
}
|
12
src/main/java/org/mmga/clubs/dao/AuthPermissionDao.java
Normal file
12
src/main/java/org/mmga/clubs/dao/AuthPermissionDao.java
Normal file
@ -0,0 +1,12 @@
|
||||
package org.mmga.clubs.dao;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.mmga.clubs.entities.permission.Permission;
|
||||
import org.mmga.clubs.entities.permission.PermissionVo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface AuthPermissionDao {
|
||||
List<PermissionVo> getAllPermissionByAuthId(int authId);
|
||||
}
|
10
src/main/java/org/mmga/clubs/dao/PermissionDao.java
Normal file
10
src/main/java/org/mmga/clubs/dao/PermissionDao.java
Normal file
@ -0,0 +1,10 @@
|
||||
package org.mmga.clubs.dao;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.mmga.clubs.entities.permission.Permission;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface PermissionDao {
|
||||
}
|
11
src/main/java/org/mmga/clubs/dao/PermissionRouterDao.java
Normal file
11
src/main/java/org/mmga/clubs/dao/PermissionRouterDao.java
Normal file
@ -0,0 +1,11 @@
|
||||
package org.mmga.clubs.dao;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.mmga.clubs.entities.router.RouterVo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface PermissionRouterDao {
|
||||
List<RouterVo> getRouterByPermissionId(int permissionId);
|
||||
}
|
7
src/main/java/org/mmga/clubs/dao/RouterDao.java
Normal file
7
src/main/java/org/mmga/clubs/dao/RouterDao.java
Normal file
@ -0,0 +1,7 @@
|
||||
package org.mmga.clubs.dao;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface RouterDao {
|
||||
}
|
13
src/main/java/org/mmga/clubs/dao/UserDao.java
Normal file
13
src/main/java/org/mmga/clubs/dao/UserDao.java
Normal file
@ -0,0 +1,13 @@
|
||||
package org.mmga.clubs.dao;
|
||||
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.mmga.clubs.entities.user.UserRegResponseVo;
|
||||
import org.mmga.clubs.entities.user.UserVo;
|
||||
|
||||
@Mapper
|
||||
public interface UserDao {
|
||||
UserVo getUser(String username, String password);
|
||||
void addUser(UserRegResponseVo userVo);
|
||||
int countUser(String username);
|
||||
UserVo getUserById(int id);
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package org.mmga.clubs.entities;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public record AuthPermissionVo(int authId, int permissionId, Date createTime, Date updateTime) {
|
||||
}
|
28
src/main/java/org/mmga/clubs/entities/BaseResponse.java
Normal file
28
src/main/java/org/mmga/clubs/entities/BaseResponse.java
Normal file
@ -0,0 +1,28 @@
|
||||
package org.mmga.clubs.entities;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.mmga.clubs.entities.user.User;
|
||||
|
||||
@Data
|
||||
@Schema(description = "基础返回值")
|
||||
public class BaseResponse<T> {
|
||||
@Schema(description = "返回代码(参考HTTP响应码)", examples = {"200", "404", "500", "403"})
|
||||
private int code;
|
||||
@Schema(description = "返回信息(自定义)")
|
||||
private String msg;
|
||||
@Schema(description = "返回数据")
|
||||
private T data;
|
||||
private BaseResponse(int code, String msg, T data){
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
this.data = data;
|
||||
}
|
||||
public static <T> BaseResponse<T> success(T data){
|
||||
return new BaseResponse<>(200, "接口执行成功", data);
|
||||
}
|
||||
|
||||
public static<T> BaseResponse<T> failed(int code, String msg) {
|
||||
return new BaseResponse<>(code, msg, null);
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package org.mmga.clubs.entities;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public record PermissionRouterVo (int permissionId, int routerId, Date createTime, Date updateTime) {
|
||||
}
|
20
src/main/java/org/mmga/clubs/entities/auth/Auth.java
Normal file
20
src/main/java/org/mmga/clubs/entities/auth/Auth.java
Normal file
@ -0,0 +1,20 @@
|
||||
package org.mmga.clubs.entities.auth;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import org.mmga.clubs.entities.permission.Permission;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@Schema(description = "用户权限组")
|
||||
public class Auth {
|
||||
@Schema(description = "权限组ID")
|
||||
private int id;
|
||||
@Schema(description = "权限组名称")
|
||||
private String name;
|
||||
@Schema(description = "权限组所拥有的权限")
|
||||
private List<Permission> permissions;
|
||||
}
|
7
src/main/java/org/mmga/clubs/entities/auth/AuthVo.java
Normal file
7
src/main/java/org/mmga/clubs/entities/auth/AuthVo.java
Normal file
@ -0,0 +1,7 @@
|
||||
package org.mmga.clubs.entities.auth;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public record AuthVo(int id, String name, Date createTime, Date updateTime) {
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package org.mmga.clubs.entities.permission;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import org.mmga.clubs.entities.router.Router;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@Schema(description = "单个权限")
|
||||
public class Permission {
|
||||
@Schema(description = "权限ID")
|
||||
private int id;
|
||||
@Schema(description = "权限名称")
|
||||
private String name;
|
||||
@Schema(description = "此权限可访问的Router")
|
||||
private List<Router> routers;
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package org.mmga.clubs.entities.permission;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public record PermissionVo(int id, String name, Date createTime, Date updateTime) {
|
||||
}
|
21
src/main/java/org/mmga/clubs/entities/router/Router.java
Normal file
21
src/main/java/org/mmga/clubs/entities/router/Router.java
Normal file
@ -0,0 +1,21 @@
|
||||
package org.mmga.clubs.entities.router;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@Schema(description = "路由节点")
|
||||
public class Router {
|
||||
@Schema(description = "节点ID")
|
||||
private int id;
|
||||
@Schema(description = "节点名称")
|
||||
private String name;
|
||||
@Schema(description = "节点对应组件名称")
|
||||
private String component;
|
||||
@Schema(description = "节点的子节点")
|
||||
private List<Router> children;
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package org.mmga.clubs.entities.router;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public record RouterVo(int id, String name, Integer parent, String component, Date createTime, Date updateTime) {
|
||||
}
|
18
src/main/java/org/mmga/clubs/entities/user/User.java
Normal file
18
src/main/java/org/mmga/clubs/entities/user/User.java
Normal file
@ -0,0 +1,18 @@
|
||||
package org.mmga.clubs.entities.user;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.mmga.clubs.entities.auth.Auth;
|
||||
|
||||
@Data
|
||||
@Schema(description = "用户")
|
||||
public class User {
|
||||
@Schema(description = "用户ID")
|
||||
private int id;
|
||||
@Schema(description = "用户名")
|
||||
private String name;
|
||||
@Schema(description = "用户所在权限组")
|
||||
private Auth auth;
|
||||
@Schema(description = "用户头像SHA1值")
|
||||
private String avatar;
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package org.mmga.clubs.entities.user;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
@Schema(description = "用户登录参数类")
|
||||
public record UserLoginVo(@Schema(description = "用户名") String username,@Schema(description = "用户密码(使用MD5摘要后的hex字符串)") String password) {
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package org.mmga.clubs.entities.user;
|
||||
|
||||
import lombok.Data;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
|
||||
@Data
|
||||
public class UserRegResponseVo {
|
||||
private int id;
|
||||
private final String username;
|
||||
private final String password;
|
||||
private final int auth;
|
||||
public UserRegResponseVo(UserRegVo userRegVo) {
|
||||
this.username = userRegVo.username();
|
||||
this.password = DigestUtils.sha1Hex(userRegVo.password());
|
||||
this.auth = userRegVo.auth();
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package org.mmga.clubs.entities.user;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
@Schema(description = "用户注册参数")
|
||||
public record UserRegVo(@Schema(description = "用户名") String username,@Schema(description = "密码(使用MD5摘要后的hex字符串)") String password,@Schema(description = "用户的权限组ID") int auth) {
|
||||
}
|
6
src/main/java/org/mmga/clubs/entities/user/UserVo.java
Normal file
6
src/main/java/org/mmga/clubs/entities/user/UserVo.java
Normal file
@ -0,0 +1,6 @@
|
||||
package org.mmga.clubs.entities.user;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public record UserVo(int id, String name, String password, int auth, String avatar, Date createTime, Date updateTime) {
|
||||
}
|
32
src/main/java/org/mmga/clubs/service/AuthService.java
Normal file
32
src/main/java/org/mmga/clubs/service/AuthService.java
Normal file
@ -0,0 +1,32 @@
|
||||
package org.mmga.clubs.service;
|
||||
|
||||
import org.mmga.clubs.dao.AuthDao;
|
||||
import org.mmga.clubs.dao.AuthPermissionDao;
|
||||
import org.mmga.clubs.entities.auth.Auth;
|
||||
import org.mmga.clubs.entities.auth.AuthVo;
|
||||
import org.mmga.clubs.entities.permission.Permission;
|
||||
import org.mmga.clubs.entities.permission.PermissionVo;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class AuthService {
|
||||
private final AuthDao authDao;
|
||||
private final AuthPermissionDao authPermissionDao;
|
||||
private final PermissionService permissionService;
|
||||
@Autowired
|
||||
public AuthService(AuthDao authDao, AuthPermissionDao authPermissionDao, PermissionService permissionService) {
|
||||
this.authDao = authDao;
|
||||
this.authPermissionDao = authPermissionDao;
|
||||
this.permissionService = permissionService;
|
||||
}
|
||||
|
||||
public Auth getAuthById(int auth) {
|
||||
AuthVo authVo = this.authDao.getAuthById(auth);
|
||||
List<PermissionVo> permissionVos = this.authPermissionDao.getAllPermissionByAuthId(auth);
|
||||
List<Permission> permissions = permissionVos.stream().map(permissionService::packagePermission).toList();
|
||||
return new Auth(authVo.id(), authVo.name(), permissions);
|
||||
}
|
||||
}
|
29
src/main/java/org/mmga/clubs/service/PermissionService.java
Normal file
29
src/main/java/org/mmga/clubs/service/PermissionService.java
Normal file
@ -0,0 +1,29 @@
|
||||
package org.mmga.clubs.service;
|
||||
|
||||
import org.mmga.clubs.dao.PermissionDao;
|
||||
import org.mmga.clubs.dao.PermissionRouterDao;
|
||||
import org.mmga.clubs.entities.permission.Permission;
|
||||
import org.mmga.clubs.entities.permission.PermissionVo;
|
||||
import org.mmga.clubs.entities.router.Router;
|
||||
import org.mmga.clubs.entities.router.RouterVo;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class PermissionService {
|
||||
private final PermissionDao permissionDao;
|
||||
private final PermissionRouterDao permissionRouterDao;
|
||||
private final RouterService routerService;
|
||||
public PermissionService(PermissionDao permissionDao, PermissionRouterDao permissionRouterDao, RouterService routerService) {
|
||||
this.permissionDao = permissionDao;
|
||||
this.permissionRouterDao = permissionRouterDao;
|
||||
this.routerService = routerService;
|
||||
}
|
||||
public Permission packagePermission(PermissionVo vo){
|
||||
int id = vo.id();
|
||||
List<RouterVo> routerVos = permissionRouterDao.getRouterByPermissionId(id);
|
||||
List<Router> routers = this.routerService.packageRouter(routerVos);
|
||||
return new Permission(id, vo.name(), routers);
|
||||
}
|
||||
}
|
36
src/main/java/org/mmga/clubs/service/RouterService.java
Normal file
36
src/main/java/org/mmga/clubs/service/RouterService.java
Normal file
@ -0,0 +1,36 @@
|
||||
package org.mmga.clubs.service;
|
||||
|
||||
import org.mmga.clubs.dao.RouterDao;
|
||||
import org.mmga.clubs.entities.router.Router;
|
||||
import org.mmga.clubs.entities.router.RouterVo;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
public class RouterService {
|
||||
private final RouterDao routerDao;
|
||||
public RouterService(RouterDao routerDao) {
|
||||
this.routerDao = routerDao;
|
||||
}
|
||||
public List<Router> packageRouter(List<RouterVo> routerVos) {
|
||||
Map<Integer, Router> idRouterMap = new HashMap<>();
|
||||
List<Integer> rootId = new ArrayList<>();
|
||||
for (RouterVo routerVo : routerVos) {
|
||||
idRouterMap.put(routerVo.id(), new Router(routerVo.id(), routerVo.name(), routerVo.component(), new ArrayList<>()));
|
||||
if (routerVo.parent() == null){
|
||||
rootId.add(routerVo.id());
|
||||
}
|
||||
}
|
||||
for (RouterVo routerVo : routerVos) {
|
||||
Integer parent = routerVo.parent();
|
||||
if (parent != null) {
|
||||
idRouterMap.get(parent).getChildren().add(idRouterMap.get(routerVo.id()));
|
||||
}
|
||||
}
|
||||
return rootId.stream().map(idRouterMap::get).toList();
|
||||
}
|
||||
}
|
57
src/main/java/org/mmga/clubs/service/UserService.java
Normal file
57
src/main/java/org/mmga/clubs/service/UserService.java
Normal file
@ -0,0 +1,57 @@
|
||||
package org.mmga.clubs.service;
|
||||
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.mmga.clubs.dao.UserDao;
|
||||
import org.mmga.clubs.entities.BaseResponse;
|
||||
import org.mmga.clubs.entities.user.*;
|
||||
import org.mmga.clubs.utils.JwtUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class UserService {
|
||||
private final UserDao userDao;
|
||||
private final AuthService authService;
|
||||
private final JwtUtils jwtUtils;
|
||||
@Autowired
|
||||
public UserService(UserDao userDao, AuthService authService, JwtUtils jwtUtils){
|
||||
this.userDao = userDao;
|
||||
this.authService = authService;
|
||||
this.jwtUtils = jwtUtils;
|
||||
}
|
||||
|
||||
public BaseResponse<User> login(UserLoginVo user, HttpServletResponse response) {
|
||||
UserVo userVo = userDao.getUser(user.username(), DigestUtils.sha1Hex(user.password()));
|
||||
User u = packageUser(userVo);
|
||||
if (response != null && u != null){
|
||||
response.addHeader("Set-Authorization", jwtUtils.createToken(u));
|
||||
}
|
||||
return u == null ? BaseResponse.failed(404, "无效用户") : BaseResponse.success(u);
|
||||
}
|
||||
|
||||
public BaseResponse<User> createUser(UserRegVo user, HttpServletResponse response) {
|
||||
String username = user.username();
|
||||
if (userDao.countUser(username) > 0) {
|
||||
return BaseResponse.failed(409, "用户已存在");
|
||||
}
|
||||
UserRegResponseVo responseVo = new UserRegResponseVo(user);
|
||||
userDao.addUser(responseVo);
|
||||
int newUserId = responseVo.getId();
|
||||
User newUser = packageUser(userDao.getUserById(newUserId));
|
||||
if (newUser != null && response != null) {
|
||||
response.addHeader("Set-Authorization", jwtUtils.createToken(newUser));
|
||||
}
|
||||
return BaseResponse.success(newUser);
|
||||
}
|
||||
private User packageUser(UserVo vo) {
|
||||
if (vo == null){
|
||||
return null;
|
||||
}
|
||||
User result = new User();
|
||||
result.setId(vo.id());
|
||||
result.setName(vo.name());
|
||||
result.setAuth(authService.getAuthById(vo.auth()));
|
||||
return result;
|
||||
}
|
||||
}
|
28
src/main/java/org/mmga/clubs/utils/JwtUtils.java
Normal file
28
src/main/java/org/mmga/clubs/utils/JwtUtils.java
Normal file
@ -0,0 +1,28 @@
|
||||
package org.mmga.clubs.utils;
|
||||
|
||||
import com.auth0.jwt.JWT;
|
||||
import com.auth0.jwt.algorithms.Algorithm;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.mmga.clubs.entities.user.User;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.security.interfaces.ECPrivateKey;
|
||||
import java.security.interfaces.ECPublicKey;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class JwtUtils {
|
||||
private final ECPublicKey ecPublicKey;
|
||||
private final ECPrivateKey ecPrivateKey;
|
||||
@Autowired
|
||||
public JwtUtils(ECPublicKey ecPublicKey, ECPrivateKey ecPrivateKey){
|
||||
this.ecPublicKey = ecPublicKey;
|
||||
this.ecPrivateKey = ecPrivateKey;
|
||||
}
|
||||
public String createToken(User user){
|
||||
String jwt = JWT.create().withClaim("uid", user.getId()).sign(Algorithm.ECDSA512(ecPublicKey, ecPrivateKey));
|
||||
log.debug("对用户:{},生成JWT:{}", user.getName(), jwt);
|
||||
return jwt;
|
||||
}
|
||||
}
|
13
src/main/java/org/mmga/clubs/utils/ShellUtils.java
Normal file
13
src/main/java/org/mmga/clubs/utils/ShellUtils.java
Normal file
@ -0,0 +1,13 @@
|
||||
package org.mmga.clubs.utils;
|
||||
|
||||
import org.mmga.clubs.entities.BaseResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class ShellUtils {
|
||||
public static void logToResult(Logger logger, BaseResponse<?> response){
|
||||
logger.info("返回代码:{},返回信息:{}", response.getCode(), response.getMsg());
|
||||
logger.info("返回结果:{}", response.getData());
|
||||
}
|
||||
}
|
@ -1 +1,2 @@
|
||||
spring.application.name=ITZX-Clubs-Home-Server
|
||||
springdoc.swagger-ui.path=/docs
|
9
src/main/resources/org/mmga/clubs/dao/AuthDao.xml
Normal file
9
src/main/resources/org/mmga/clubs/dao/AuthDao.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.mmga.clubs.dao.AuthDao">
|
||||
<select id="getAuthById" resultType="org.mmga.clubs.entities.auth.AuthVo">
|
||||
select * from `auth` where `id` = #{id};
|
||||
</select>
|
||||
</mapper>
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.mmga.clubs.dao.AuthPermissionDao">
|
||||
<select id="getAllPermissionByAuthId" resultType="org.mmga.clubs.entities.permission.PermissionVo">
|
||||
select `permission`.* from `auth_permission` left join `permission` on `auth_permission`.`permission_id` = `permission`.`id` where `auth_id` = #{authId};
|
||||
</select>
|
||||
</mapper>
|
6
src/main/resources/org/mmga/clubs/dao/PermissionDao.xml
Normal file
6
src/main/resources/org/mmga/clubs/dao/PermissionDao.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.mmga.clubs.dao.PermissionDao">
|
||||
</mapper>
|
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.mmga.clubs.dao.PermissionRouterDao">
|
||||
<select id="getRouterByPermissionId" resultType="org.mmga.clubs.entities.router.RouterVo">
|
||||
select `router`.* from `permission_router` left join `router` on `permission_router`.`router_id` = `router`.`id` where `permission_id` = #{permissionId};
|
||||
</select>
|
||||
</mapper>
|
6
src/main/resources/org/mmga/clubs/dao/RouterDao.xml
Normal file
6
src/main/resources/org/mmga/clubs/dao/RouterDao.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.mmga.clubs.dao.RouterDao">
|
||||
</mapper>
|
18
src/main/resources/org/mmga/clubs/dao/UserDao.xml
Normal file
18
src/main/resources/org/mmga/clubs/dao/UserDao.xml
Normal file
@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="org.mmga.clubs.dao.UserDao">
|
||||
<insert id="addUser" useGeneratedKeys="true" keyProperty="id">
|
||||
insert into `user`(`name`, `password`, `auth`) values(#{username}, #{password}, #{auth});
|
||||
</insert>
|
||||
<select id="getUser" resultType="org.mmga.clubs.entities.user.UserVo">
|
||||
select * from `user` where `name` = #{username} and `password` = #{password};
|
||||
</select>
|
||||
<select id="countUser" resultType="java.lang.Integer">
|
||||
select count(*) from `user` where `name` = #{username};
|
||||
</select>
|
||||
<select id="getUserById" resultType="org.mmga.clubs.entities.user.UserVo">
|
||||
select * from `user` where `id` = #{id};
|
||||
</select>
|
||||
</mapper>
|
Loading…
x
Reference in New Issue
Block a user