feat: 初版提交

This commit is contained in:
2023-02-22 07:29:52 +08:00
commit 6265aeb413
59 changed files with 8564 additions and 0 deletions

47
blog-backend/build.gradle Normal file
View File

@@ -0,0 +1,47 @@
plugins {
id 'java'
id 'org.springframework.boot' version '3.0.2'
id 'io.spring.dependency-management' version '1.1.0'
}
group = 'cn.hamster3.application.blog'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
maven {
url "https://maven.airgame.net/maven-public"
}
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.flywaydb:flyway-core'
implementation 'org.flywaydb:flyway-mysql'
implementation 'org.springframework.session:spring-session-core'
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.springframework.security:spring-security-test'
}
tasks.named('test') {
useJUnitPlatform()
}
processResources {
dependsOn(":blog-frontend:npmBuild")
from(tasks.findByPath(":blog-frontend:npmBuild").outputs) {
into 'static'
}
}

View File

@@ -0,0 +1,13 @@
package cn.hamster3.application.blog;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class HamsterBlogApplication {
public static void main(String[] args) {
SpringApplication.run(HamsterBlogApplication.class, args);
}
}

View File

@@ -0,0 +1,22 @@
package cn.hamster3.application.blog.config;
import org.springframework.data.domain.AuditorAware;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.User;
import org.springframework.stereotype.Component;
import java.util.Optional;
@Component
public class UserIDAuditorAware implements AuditorAware<String> {
@Override
public Optional<String> getCurrentAuditor() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || !authentication.isAuthenticated()) {
return Optional.empty();
}
User user = (User) authentication.getPrincipal();
return Optional.of(user.getUsername());
}
}

View File

@@ -0,0 +1,11 @@
package cn.hamster3.application.blog.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@Slf4j
public class WebConfig implements WebMvcConfigurer {
}

View File

@@ -0,0 +1,22 @@
package cn.hamster3.application.blog.config.security;
import cn.hamster3.application.blog.dao.UserEntityRepository;
import jakarta.annotation.Resource;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import java.util.Collections;
public class UserDetailServiceImpl implements UserDetailsService {
@Resource
private UserEntityRepository userRepo;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
return userRepo.findByEmailOrUsername(username, username)
.map(o -> new User(o.getUsername(), o.getPassword(), Collections.emptyList()))
.orElseThrow(() -> new UsernameNotFoundException("user not found."));
}
}

View File

@@ -0,0 +1,12 @@
package cn.hamster3.application.blog.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 附件相关接口
*/
@RestController
@RequestMapping("/v1/attach")
public class AttachController {
}

View File

@@ -0,0 +1,12 @@
package cn.hamster3.application.blog.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 博文相关接口
*/
@RestController
@RequestMapping("/v1/blog")
public class BlogController {
}

View File

@@ -0,0 +1,30 @@
package cn.hamster3.application.blog.controller;
import cn.hamster3.application.blog.service.IUserService;
import jakarta.annotation.Resource;
import org.springframework.web.bind.annotation.*;
/**
* 用户相关接口
*/
@RestController
@RequestMapping("/v1/user")
public class UserController {
@Resource
private IUserService userService;
@PostMapping("/")
public Object registerUser() {
return null;
}
@PutMapping("/")
public Object modifyUserInfo() {
return null;
}
@GetMapping("/")
public Object getUserInfo() {
return null;
}
}

View File

@@ -0,0 +1,8 @@
package cn.hamster3.application.blog.dao;
import cn.hamster3.application.blog.entity.BlogEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
public interface BlogEntityRepository extends JpaRepository<BlogEntity, Long>, JpaSpecificationExecutor<BlogEntity> {
}

View File

@@ -0,0 +1,13 @@
package cn.hamster3.application.blog.dao;
import cn.hamster3.application.blog.entity.BlogEntity;
import cn.hamster3.application.blog.entity.UserEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import java.util.Optional;
import java.util.UUID;
public interface UserEntityRepository extends JpaRepository<UserEntity, UUID>, JpaSpecificationExecutor<BlogEntity> {
Optional<UserEntity> findByEmailOrUsername(String email, String username);
}

View File

@@ -0,0 +1,36 @@
package cn.hamster3.application.blog.entity;
import jakarta.persistence.*;
import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import java.sql.Blob;
import java.util.Date;
@Getter
@Entity
@Table(name = "attach_entity")
public class AttachEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", nullable = false)
private Long id;
@ManyToOne(optional = false)
@JoinColumn(name = "uploader_id", nullable = false)
private UserEntity uploader;
@Lob
@Basic(fetch = FetchType.LAZY)
@Column(name = "data")
private Blob data;
@CreatedDate
@Column(name = "create_time", nullable = false)
private Date createTime;
@LastModifiedDate
@Column(name = "update_time", nullable = false)
private Date updateTime;
}

View File

@@ -0,0 +1,51 @@
package cn.hamster3.application.blog.entity;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import org.hibernate.annotations.JdbcTypeCode;
import org.hibernate.type.SqlTypes;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import java.util.Date;
/**
* 博文实体
*/
@Getter
@Entity
@Table(name = "blog_entity")
public class BlogEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", nullable = false)
private Long id;
@Setter
@Basic(fetch = FetchType.LAZY)
@Column(name = "password", length = 32)
@JdbcTypeCode(SqlTypes.VARCHAR)
private String password;
@Lob
@Basic(fetch = FetchType.LAZY)
@Column(name = "content")
private String content;
@Setter
@CreatedBy
@ManyToOne(optional = false)
@JoinColumn(name = "uploader_id", nullable = false)
private UserEntity uploader;
@CreatedDate
@Column(name = "create_time", nullable = false)
private Date createTime;
@LastModifiedDate
@Column(name = "update_time", nullable = false)
private Date updateTime;
}

View File

@@ -0,0 +1,56 @@
package cn.hamster3.application.blog.entity;
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.hibernate.Hibernate;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import java.util.Date;
import java.util.Objects;
import java.util.UUID;
@Getter
@ToString
@Entity
@Table(name = "user_entity")
public class UserEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id", nullable = false, updatable = false)
private UUID id;
@Setter
@Column(name = "email", nullable = false, unique = true, length = 32)
private String email;
@Setter
@Column(name = "username", nullable = false, unique = true, length = 32)
private String username;
@Setter
@Column(name = "password", nullable = false, length = 32)
private String password;
@CreatedDate
@Column(name = "create_time", nullable = false)
private Date createTime;
@LastModifiedDate
@Column(name = "update_time", nullable = false)
private Date updateTime;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || Hibernate.getClass(this) != Hibernate.getClass(o)) return false;
UserEntity that = (UserEntity) o;
return id != null && Objects.equals(id, that.id);
}
@Override
public int hashCode() {
return getClass().hashCode();
}
}

View File

@@ -0,0 +1,4 @@
package cn.hamster3.application.blog.service;
public interface IBlogService {
}

View File

@@ -0,0 +1,4 @@
package cn.hamster3.application.blog.service;
public interface IUserService {
}

View File

@@ -0,0 +1,6 @@
package cn.hamster3.application.blog.service.impl;
import cn.hamster3.application.blog.service.IBlogService;
public class BlogService implements IBlogService {
}

View File

@@ -0,0 +1,17 @@
package cn.hamster3.application.blog.service.impl;
import cn.hamster3.application.blog.dao.UserEntityRepository;
import cn.hamster3.application.blog.service.IUserService;
import cn.hamster3.application.blog.vo.ResponseVO;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
@Service
public class UserService implements IUserService {
@Resource
private UserEntityRepository userRepo;
public ResponseVO<Void> registerUser() {
return null;
}
}

View File

@@ -0,0 +1,37 @@
package cn.hamster3.application.blog.vo;
import lombok.Data;
@Data
public class ResponseVO<T> {
private int code;
private String msg;
private T data;
private ResponseVO(int code, String msg, T data) {
this.code = code;
this.msg = msg;
this.data = data;
}
public static ResponseVO<Void> success() {
return new ResponseVO<>(200, "", null);
}
public static ResponseVO<Void> success(String msg) {
return new ResponseVO<>(200, msg, null);
}
public static <T> ResponseVO<T> success(T data) {
return new ResponseVO<>(200, "", data);
}
public static <T> ResponseVO<T> success(String msg, T data) {
return new ResponseVO<>(200, msg, data);
}
public static ResponseVO<Void> failed(String msg) {
return new ResponseVO<>(403, msg, null);
}
}

View File

@@ -0,0 +1,27 @@
spring:
# 数据库连接配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://sql.hamster3.cn:3306/Test3?characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8
username: Test
password: Test123..
flyway:
# 是否启用flyway
enabled: true
# 编码格式默认UTF-8
encoding: UTF-8
# 迁移sql脚本文件存放路径默认db/migration
locations: classpath:db/migration
# 迁移sql脚本文件名称的前缀默认V
sql-migration-prefix: V
# 迁移sql脚本文件名称的分隔符默认2个下划线__
sql-migration-separator: __
# 迁移sql脚本文件名称的后缀
sql-migration-suffixes: .sql
# 迁移时是否进行校验默认true
validate-on-migrate: true
# 当迁移发现数据库非空且存在没有元数据的表时自动执行基准迁移新建schema_version表
baseline-on-migrate: true
autoconfigure:
exclude[0]: org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration
exclude[1]: org.springframework.boot.actuate.autoconfigure.security.servlet.ManagementWebSecurityAutoConfigurationspring

View File

@@ -0,0 +1,25 @@
spring:
# 数据库连接配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://sql.hamster3.cn:3306/Test3?characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8
username: Test
password: Test123..
flyway:
# 是否启用flyway
enabled: true
# 编码格式默认UTF-8
encoding: UTF-8
# 迁移sql脚本文件存放路径默认db/migration
locations: classpath:db/migration
# 迁移sql脚本文件名称的前缀默认V
sql-migration-prefix: V
# 迁移sql脚本文件名称的分隔符默认2个下划线__
sql-migration-separator: __
# 迁移sql脚本文件名称的后缀
sql-migration-suffixes: .sql
# 迁移时是否进行校验默认true
validate-on-migrate: true
# 当迁移发现数据库非空且存在没有元数据的表时自动执行基准迁移新建schema_version表
baseline-on-migrate: true

View File

@@ -0,0 +1,24 @@
spring:
# 数据库连接配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://sql.hamster3.cn:3306/Test3?characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8
username: Test
password: Test123..
flyway:
# 是否启用flyway
enabled: true
# 编码格式默认UTF-8
encoding: UTF-8
# 迁移sql脚本文件存放路径默认db/migration
locations: classpath:db/migration
# 迁移sql脚本文件名称的前缀默认V
sql-migration-prefix: V
# 迁移sql脚本文件名称的分隔符默认2个下划线__
sql-migration-separator: __
# 迁移sql脚本文件名称的后缀
sql-migration-suffixes: .sql
# 迁移时是否进行校验默认true
validate-on-migrate: true
# 当迁移发现数据库非空且存在没有元数据的表时自动执行基准迁移新建schema_version表
baseline-on-migrate: true

View File

@@ -0,0 +1,13 @@
package cn.hamster3.application.blog;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class HamsterBlogApplicationTests {
@Test
void contextLoads() {
}
}