Change namespace to top.fatweb.oxygen.api
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
package top.fatweb.oxygen.api
|
||||
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication
|
||||
import org.springframework.boot.runApplication
|
||||
import org.springframework.scheduling.annotation.EnableScheduling
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Application main class
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@EnableTransactionManagement
|
||||
@EnableScheduling
|
||||
class OxygenApiApplication
|
||||
|
||||
/**
|
||||
* Main function
|
||||
*
|
||||
* @param args
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
fun main(args: Array<String>) {
|
||||
val logger = LoggerFactory.getLogger("main")
|
||||
|
||||
if (!File("data").isDirectory) {
|
||||
if (!File("data").mkdir()) {
|
||||
logger.error("Can not create directory 'data', please try again later.")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (!File("data/db").isDirectory) {
|
||||
if (!File("data/db").mkdir()) {
|
||||
logger.error("Can not create directory 'data/db', please try again later.")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (!File("data/db/sqlite.db").isFile || File("data/db/sqlite.db").inputStream()
|
||||
.use { it.readNBytes(15).toString(Charsets.UTF_8) != "SQLite format 3" }
|
||||
) {
|
||||
logger.warn("The 'data/db/sqlite.db' database is lost or damaged, recreating...")
|
||||
if (File("data/db/sqlite.db").exists() && !File("data/db/sqlite.db").delete()) {
|
||||
logger.error("Can not recreate database 'data/db/sqlite.db', please try again later.")
|
||||
}
|
||||
}
|
||||
|
||||
if (File("application-config.yml").exists() || File("data/application-config.yml").exists()) {
|
||||
runApplication<OxygenApiApplication>(*args)
|
||||
} else {
|
||||
logger.warn("File 'application-config.yml' cannot be found in the running path or the data path. The configuration file template 'application-config.example.yml' has been created in directory 'data'. Please change the configuration file content, move it to the running path, rename it to 'application-config.yml', and then restart the server.")
|
||||
OxygenApiApplication::class.java.getResource("/application-config-template.yml")?.readText()?.let {
|
||||
File("data/application-config.example.yml").writeText(
|
||||
it.replace(
|
||||
"\$uuid\$", UUID.randomUUID().toString().replace("-", "")
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package top.fatweb.oxygen.api.annotation
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag
|
||||
import org.springframework.core.annotation.AliasFor
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
/**
|
||||
* API controller annotation
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Tag
|
||||
* @see RequestMapping
|
||||
* @see RestController
|
||||
*/
|
||||
@Tag(name = "")
|
||||
@RequestMapping
|
||||
@RestController
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class ApiController(
|
||||
val version: Int = 1,
|
||||
|
||||
@get:AliasFor(annotation = RestController::class, attribute = "value") val value: String = "",
|
||||
|
||||
@get:AliasFor(annotation = RequestMapping::class, attribute = "path") val path: Array<String> = [""],
|
||||
|
||||
@get:AliasFor(annotation = Tag::class, attribute = "name") val name: String,
|
||||
|
||||
@get:AliasFor(annotation = Tag::class, attribute = "description") val description: String
|
||||
)
|
||||
@@ -0,0 +1,27 @@
|
||||
package top.fatweb.oxygen.api.annotation
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag
|
||||
import org.springframework.core.annotation.AliasFor
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
/**
|
||||
* Base controller annotation
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see RequestMapping
|
||||
* @see RestController
|
||||
*/
|
||||
@Tag(name = "")
|
||||
@RequestMapping
|
||||
@RestController
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class BaseController(
|
||||
@get:AliasFor(annotation = RequestMapping::class, attribute = "path") val path: Array<String> = [""],
|
||||
|
||||
@get:AliasFor(annotation = Tag::class, attribute = "name") val name: String,
|
||||
|
||||
@get:AliasFor(annotation = Tag::class, attribute = "description") val description: String
|
||||
)
|
||||
@@ -0,0 +1,15 @@
|
||||
package top.fatweb.oxygen.api.annotation
|
||||
|
||||
import top.fatweb.oxygen.api.entity.system.EventLog
|
||||
|
||||
/**
|
||||
* Event log record annotation
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Target(AnnotationTarget.FUNCTION)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class EventLogRecord(
|
||||
val event: EventLog.Event
|
||||
)
|
||||
@@ -0,0 +1,24 @@
|
||||
package top.fatweb.oxygen.api.annotation
|
||||
|
||||
import io.swagger.v3.oas.annotations.Hidden
|
||||
import org.springframework.core.annotation.AliasFor
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import org.springframework.web.bind.annotation.RestController
|
||||
|
||||
/**
|
||||
* Hidden controller annotation
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Hidden
|
||||
* @see RequestMapping
|
||||
* @see RestController
|
||||
*/
|
||||
@Hidden
|
||||
@RequestMapping
|
||||
@RestController
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class HiddenController(
|
||||
@get:AliasFor(annotation = RequestMapping::class, attribute = "path") val path: Array<String> = [""]
|
||||
)
|
||||
58
src/main/kotlin/top/fatweb/oxygen/api/aop/EventLogAspect.kt
Normal file
58
src/main/kotlin/top/fatweb/oxygen/api/aop/EventLogAspect.kt
Normal file
@@ -0,0 +1,58 @@
|
||||
package top.fatweb.oxygen.api.aop
|
||||
|
||||
import org.aspectj.lang.JoinPoint
|
||||
import org.aspectj.lang.annotation.AfterReturning
|
||||
import org.aspectj.lang.annotation.Aspect
|
||||
import org.aspectj.lang.annotation.Pointcut
|
||||
import org.aspectj.lang.reflect.MethodSignature
|
||||
import org.springframework.stereotype.Component
|
||||
import top.fatweb.oxygen.api.annotation.EventLogRecord
|
||||
import top.fatweb.oxygen.api.service.system.IEventLogService
|
||||
import top.fatweb.oxygen.api.util.WebUtil
|
||||
import top.fatweb.oxygen.api.vo.permission.LoginVo
|
||||
import top.fatweb.oxygen.api.vo.permission.RegisterVo
|
||||
|
||||
/**
|
||||
* Event log record aspect
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see IEventLogService
|
||||
*/
|
||||
@Aspect
|
||||
@Component
|
||||
class EventLogAspect(
|
||||
private val eventLogService: IEventLogService
|
||||
) {
|
||||
/**
|
||||
* Event log record pointcut
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Pointcut("@annotation(top.fatweb.oxygen.api.annotation.EventLogRecord)")
|
||||
fun eventLogPointcut() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Do after event log record pointcut
|
||||
*
|
||||
* @param joinPoint Join point
|
||||
* @param retValue Return value
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see JoinPoint
|
||||
*/
|
||||
@AfterReturning(value = "eventLogPointcut()", returning = "retValue")
|
||||
fun doAfter(joinPoint: JoinPoint, retValue: Any?) {
|
||||
val annotation = (joinPoint.signature as MethodSignature).method.getAnnotation(EventLogRecord::class.java)
|
||||
|
||||
val userId = WebUtil.getLoginUserId() ?: when (retValue) {
|
||||
is LoginVo -> retValue.userId!!
|
||||
is RegisterVo -> retValue.userId!!
|
||||
else -> -1
|
||||
}
|
||||
|
||||
eventLogService.saveEvent(annotation, userId)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package top.fatweb.oxygen.api.config
|
||||
|
||||
import com.fasterxml.jackson.databind.SerializationFeature
|
||||
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer
|
||||
import org.springframework.beans.factory.annotation.Value
|
||||
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer
|
||||
import org.springframework.boot.jackson.JsonComponent
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder
|
||||
import java.text.DateFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.time.LocalDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Data format configuration
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@JsonComponent
|
||||
class DataFormatConfig {
|
||||
/**
|
||||
* The format of the time in response when request APIs
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@set:Value("\${spring.jackson.date-format}")
|
||||
lateinit var dataFormat: String
|
||||
|
||||
/**
|
||||
* The timezone of the time in response when request APIs
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see TimeZone
|
||||
*/
|
||||
@set:Value("\${spring.jackson.time-zone}}")
|
||||
lateinit var timeZone: TimeZone
|
||||
|
||||
@Bean
|
||||
fun jackson2ObjectMapperBuilder() = Jackson2ObjectMapperBuilderCustomizer { builder: Jackson2ObjectMapperBuilder ->
|
||||
val tz = timeZone
|
||||
val df: DateFormat = SimpleDateFormat(dataFormat)
|
||||
df.timeZone = tz
|
||||
builder.failOnEmptyBeans(false).failOnUnknownProperties(false)
|
||||
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS).dateFormat(df)
|
||||
}
|
||||
|
||||
@Bean
|
||||
fun jackson2ObjectMapperBuilderCustomizer() =
|
||||
Jackson2ObjectMapperBuilderCustomizer { builder: Jackson2ObjectMapperBuilder ->
|
||||
builder.serializerByType(
|
||||
LocalDateTime::class.java, LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dataFormat))
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
24
src/main/kotlin/top/fatweb/oxygen/api/config/FilterConfig.kt
Normal file
24
src/main/kotlin/top/fatweb/oxygen/api/config/FilterConfig.kt
Normal file
@@ -0,0 +1,24 @@
|
||||
package top.fatweb.oxygen.api.config
|
||||
|
||||
import org.springframework.boot.web.servlet.FilterRegistrationBean
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import top.fatweb.oxygen.api.filter.ExceptionFilter
|
||||
|
||||
/**
|
||||
* Filter configuration
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
class FilterConfig {
|
||||
@Bean
|
||||
fun exceptionFilterRegistrationBean(exceptionFilter: ExceptionFilter): FilterRegistrationBean<ExceptionFilter> {
|
||||
val registrationBean = FilterRegistrationBean(exceptionFilter)
|
||||
registrationBean.setBeanName("exceptionFilter")
|
||||
registrationBean.order = -100
|
||||
|
||||
return registrationBean
|
||||
}
|
||||
}
|
||||
43
src/main/kotlin/top/fatweb/oxygen/api/config/FlywayConfig.kt
Normal file
43
src/main/kotlin/top/fatweb/oxygen/api/config/FlywayConfig.kt
Normal file
@@ -0,0 +1,43 @@
|
||||
package top.fatweb.oxygen.api.config
|
||||
|
||||
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource
|
||||
import jakarta.annotation.PostConstruct
|
||||
import org.flywaydb.core.Flyway
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.context.annotation.DependsOn
|
||||
import top.fatweb.oxygen.api.properties.FlywayProperties
|
||||
import javax.sql.DataSource
|
||||
|
||||
/**
|
||||
* Flyway configuration
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@DependsOn("flywayProperties")
|
||||
@Configuration
|
||||
class FlywayConfig(
|
||||
private val dataSource: DataSource
|
||||
) {
|
||||
@PostConstruct
|
||||
fun migrateOrder() {
|
||||
val ds = dataSource as DynamicRoutingDataSource
|
||||
ds.dataSources.forEach { (k: String, v: DataSource?) ->
|
||||
val flyway = Flyway.configure()
|
||||
.dataSource(v)
|
||||
.locations(*FlywayProperties.locations.map { "$it/$k" }.toTypedArray())
|
||||
.baselineOnMigrate(FlywayProperties.baselineOnMigrate)
|
||||
.table(FlywayProperties.table)
|
||||
.outOfOrder(FlywayProperties.outOfOrder)
|
||||
.validateOnMigrate(FlywayProperties.validateOnMigrate)
|
||||
.encoding(FlywayProperties.encoding)
|
||||
.sqlMigrationPrefix(FlywayProperties.sqlMigrationPrefix)
|
||||
.sqlMigrationSeparator(FlywayProperties.sqlMigrationSeparator)
|
||||
.sqlMigrationSuffixes(*FlywayProperties.sqlMigrationSuffixes.toTypedArray())
|
||||
.baselineVersion(FlywayProperties.baselineVersion)
|
||||
.load()
|
||||
flyway.migrate()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
69
src/main/kotlin/top/fatweb/oxygen/api/config/InitConfig.kt
Normal file
69
src/main/kotlin/top/fatweb/oxygen/api/config/InitConfig.kt
Normal file
@@ -0,0 +1,69 @@
|
||||
package top.fatweb.oxygen.api.config
|
||||
|
||||
import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper
|
||||
import jakarta.annotation.PostConstruct
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.context.annotation.DependsOn
|
||||
import org.springframework.security.crypto.password.PasswordEncoder
|
||||
import org.springframework.stereotype.Component
|
||||
import top.fatweb.avatargenerator.GitHubAvatar
|
||||
import top.fatweb.oxygen.api.entity.permission.User
|
||||
import top.fatweb.oxygen.api.entity.permission.UserInfo
|
||||
import top.fatweb.oxygen.api.properties.AdminProperties
|
||||
import top.fatweb.oxygen.api.service.permission.IUserInfoService
|
||||
import top.fatweb.oxygen.api.service.permission.IUserService
|
||||
import top.fatweb.oxygen.api.util.StrUtil
|
||||
|
||||
/**
|
||||
* Application initialization configuration
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see IUserService
|
||||
* @see IUserInfoService
|
||||
* @see PasswordEncoder
|
||||
*/
|
||||
@DependsOn("adminProperties")
|
||||
@Component
|
||||
class InitConfig(
|
||||
private val userService: IUserService,
|
||||
private val userInfoService: IUserInfoService,
|
||||
private val passwordEncoder: PasswordEncoder
|
||||
) {
|
||||
private val logger: Logger = LoggerFactory.getLogger(this::class.java)
|
||||
|
||||
@PostConstruct
|
||||
fun init() {
|
||||
if (!userService.exists(KtQueryWrapper(User()).eq(User::id, 0))) {
|
||||
userInfoService.remove(KtQueryWrapper(UserInfo()).eq(UserInfo::userId, 0))
|
||||
|
||||
val rawPassword = AdminProperties.password ?: let {
|
||||
logger.warn("No default administrator password is set, a randomly generated password will be used")
|
||||
StrUtil.getRandomPassword(10)
|
||||
}
|
||||
val encodedPassword = passwordEncoder.encode(rawPassword)
|
||||
|
||||
val user = User().apply {
|
||||
id = 0
|
||||
username = AdminProperties.username
|
||||
password = encodedPassword
|
||||
locking = 0
|
||||
enable = 1
|
||||
}
|
||||
val userInfo = UserInfo().apply {
|
||||
userId = 0
|
||||
nickname = AdminProperties.nickname
|
||||
avatar =
|
||||
GitHubAvatar.newAvatarBuilder().build().createAsBase64((Long.MIN_VALUE..Long.MAX_VALUE).random())
|
||||
email = AdminProperties.email
|
||||
}
|
||||
|
||||
if (userService.save(user) && userInfoService.save(userInfo)) {
|
||||
logger.warn("First startup, create administrator - username: admin, password: $rawPassword")
|
||||
logger.warn("This information will only be shown once. Please change your password promptly after logging in.")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package top.fatweb.oxygen.api.config
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor
|
||||
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
|
||||
/**
|
||||
* Mybatis-plus configuration
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
class MybatisPlusConfig {
|
||||
@Bean
|
||||
fun mybatisPlusInterceptor(): MybatisPlusInterceptor {
|
||||
val mybatisPlusInterceptor = MybatisPlusInterceptor()
|
||||
mybatisPlusInterceptor.addInnerInterceptor(OptimisticLockerInnerInterceptor())
|
||||
mybatisPlusInterceptor.addInnerInterceptor(PaginationInnerInterceptor())
|
||||
|
||||
return mybatisPlusInterceptor
|
||||
}
|
||||
}
|
||||
48
src/main/kotlin/top/fatweb/oxygen/api/config/RedisConfig.kt
Normal file
48
src/main/kotlin/top/fatweb/oxygen/api/config/RedisConfig.kt
Normal file
@@ -0,0 +1,48 @@
|
||||
package top.fatweb.oxygen.api.config
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory
|
||||
import org.springframework.data.redis.core.RedisTemplate
|
||||
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer
|
||||
import org.springframework.data.redis.serializer.StringRedisSerializer
|
||||
|
||||
/**
|
||||
* Redis configuration
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
class RedisConfig {
|
||||
@Bean
|
||||
fun redisTemplate(redisConnectionFactory: RedisConnectionFactory): RedisTemplate<*, *> {
|
||||
val redisTemplate = RedisTemplate<String, Any>()
|
||||
redisTemplate.connectionFactory = redisConnectionFactory
|
||||
val stringRedisSerializer = StringRedisSerializer()
|
||||
val objectMapper = ObjectMapper().registerModules(JavaTimeModule()).apply {
|
||||
setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY)
|
||||
activateDefaultTyping(
|
||||
this.polymorphicTypeValidator, ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY
|
||||
)
|
||||
}
|
||||
val anyJackson2JsonRedisSerializer = Jackson2JsonRedisSerializer(objectMapper, Any::class.java)
|
||||
|
||||
// 使用StringRedisSerializer来序列化和反序列化redis的key值
|
||||
redisTemplate.keySerializer = stringRedisSerializer
|
||||
redisTemplate.valueSerializer = anyJackson2JsonRedisSerializer
|
||||
|
||||
// Hash的key也采用StringRedisSerializer的序列化方式
|
||||
redisTemplate.hashKeySerializer = stringRedisSerializer
|
||||
redisTemplate.hashValueSerializer = anyJackson2JsonRedisSerializer
|
||||
|
||||
redisTemplate.afterPropertiesSet()
|
||||
|
||||
return redisTemplate
|
||||
}
|
||||
}
|
||||
104
src/main/kotlin/top/fatweb/oxygen/api/config/SecurityConfig.kt
Normal file
104
src/main/kotlin/top/fatweb/oxygen/api/config/SecurityConfig.kt
Normal file
@@ -0,0 +1,104 @@
|
||||
package top.fatweb.oxygen.api.config
|
||||
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.security.authentication.AuthenticationManager
|
||||
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity
|
||||
import org.springframework.security.config.annotation.web.configurers.*
|
||||
import org.springframework.security.config.http.SessionCreationPolicy
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
|
||||
import org.springframework.security.web.SecurityFilterChain
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
|
||||
import org.springframework.web.cors.CorsConfiguration
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource
|
||||
import top.fatweb.oxygen.api.filter.JwtAuthenticationTokenFilter
|
||||
import top.fatweb.oxygen.api.handler.JwtAccessDeniedHandler
|
||||
import top.fatweb.oxygen.api.handler.JwtAuthenticationEntryPointHandler
|
||||
|
||||
/**
|
||||
* Spring Security configuration
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see JwtAuthenticationTokenFilter
|
||||
* @see JwtAuthenticationEntryPointHandler
|
||||
* @see JwtAccessDeniedHandler
|
||||
*/
|
||||
@Configuration
|
||||
@EnableMethodSecurity
|
||||
class SecurityConfig(
|
||||
private val jwtAuthenticationTokenFilter: JwtAuthenticationTokenFilter,
|
||||
private val authenticationEntryPointHandler: JwtAuthenticationEntryPointHandler,
|
||||
private val accessDeniedHandler: JwtAccessDeniedHandler
|
||||
) {
|
||||
@Bean
|
||||
fun passwordEncoder() = BCryptPasswordEncoder()
|
||||
|
||||
@Bean
|
||||
fun authenticationManager(authenticationConfiguration: AuthenticationConfiguration): AuthenticationManager =
|
||||
authenticationConfiguration.authenticationManager
|
||||
|
||||
@Bean
|
||||
fun corsConfigurationSource(): UrlBasedCorsConfigurationSource {
|
||||
val corsConfiguration = CorsConfiguration()
|
||||
corsConfiguration.allowedMethods = listOf("*")
|
||||
corsConfiguration.allowedHeaders = listOf("*")
|
||||
corsConfiguration.maxAge = 3600L
|
||||
corsConfiguration.allowedOrigins = listOf("*")
|
||||
val source = UrlBasedCorsConfigurationSource()
|
||||
source.registerCorsConfiguration("/**", corsConfiguration)
|
||||
|
||||
return source
|
||||
}
|
||||
|
||||
@Bean
|
||||
fun securityFilterChain(httpSecurity: HttpSecurity): SecurityFilterChain = httpSecurity
|
||||
// Disable CSRF
|
||||
.csrf { csrfConfigurer: CsrfConfigurer<HttpSecurity> -> csrfConfigurer.disable() }
|
||||
// Do not get SecurityContent by Session
|
||||
.sessionManagement { sessionManagementConfigurer: SessionManagementConfigurer<HttpSecurity?> ->
|
||||
sessionManagementConfigurer.sessionCreationPolicy(
|
||||
SessionCreationPolicy.STATELESS
|
||||
)
|
||||
}
|
||||
.authorizeHttpRequests { authorizeHttpRequests: AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry ->
|
||||
authorizeHttpRequests
|
||||
// Allow anonymous access
|
||||
.requestMatchers(
|
||||
"/error/thrown",
|
||||
"/doc.html",
|
||||
"/swagger-ui/**",
|
||||
"/webjars/**",
|
||||
"/v3/**",
|
||||
"/swagger-ui.html",
|
||||
"/favicon.ico",
|
||||
"/login",
|
||||
"/register",
|
||||
"/forget",
|
||||
"/retrieve"
|
||||
).anonymous()
|
||||
// Authentication required
|
||||
.anyRequest().authenticated()
|
||||
}
|
||||
|
||||
.logout { logoutConfigurer: LogoutConfigurer<HttpSecurity> -> logoutConfigurer.disable() }
|
||||
|
||||
.exceptionHandling { exceptionHandlingConfigurer: ExceptionHandlingConfigurer<HttpSecurity?> ->
|
||||
exceptionHandlingConfigurer.authenticationEntryPoint(
|
||||
authenticationEntryPointHandler
|
||||
)
|
||||
exceptionHandlingConfigurer.accessDeniedHandler(
|
||||
accessDeniedHandler
|
||||
)
|
||||
}
|
||||
|
||||
.cors { cors: CorsConfigurer<HttpSecurity?> ->
|
||||
cors.configurationSource(
|
||||
corsConfigurationSource()
|
||||
)
|
||||
}
|
||||
|
||||
.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter::class.java).build()
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package top.fatweb.oxygen.api.config
|
||||
|
||||
import io.swagger.v3.oas.models.OpenAPI
|
||||
import io.swagger.v3.oas.models.info.Contact
|
||||
import io.swagger.v3.oas.models.info.Info
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import top.fatweb.oxygen.api.properties.ServerProperties
|
||||
|
||||
/**
|
||||
* Swagger API doc configuration
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
class SwaggerConfig {
|
||||
@Bean
|
||||
fun customOpenAPI(): OpenAPI? {
|
||||
val contact = Contact().name("FatttSnake").url("https://fatweb.top").email("fatttsnake@gmail.com")
|
||||
return OpenAPI().info(
|
||||
Info().title("Oxygen API 文档").description("Oxygen 后端 API 文档,包含各个 Controller 调用信息")
|
||||
.contact(contact).version(
|
||||
ServerProperties.version
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
24
src/main/kotlin/top/fatweb/oxygen/api/config/SysLogConfig.kt
Normal file
24
src/main/kotlin/top/fatweb/oxygen/api/config/SysLogConfig.kt
Normal file
@@ -0,0 +1,24 @@
|
||||
package top.fatweb.oxygen.api.config
|
||||
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
|
||||
import top.fatweb.oxygen.api.interceptor.SysLogInterceptor
|
||||
|
||||
/**
|
||||
* System log configuration
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see SysLogInterceptor
|
||||
* @see WebMvcConfigurer
|
||||
*/
|
||||
@Configuration
|
||||
class SysLogConfig(
|
||||
private val sysLogInterceptor: SysLogInterceptor
|
||||
) : WebMvcConfigurer {
|
||||
override fun addInterceptors(registry: InterceptorRegistry) {
|
||||
registry.addInterceptor(sysLogInterceptor).addPathPatterns("/**")
|
||||
.excludePathPatterns("/error/thrown", "/webjars/**")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package top.fatweb.oxygen.api.config
|
||||
|
||||
import org.apache.velocity.app.VelocityEngine
|
||||
import org.apache.velocity.runtime.RuntimeConstants
|
||||
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
|
||||
import org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
|
||||
/**
|
||||
* Velocity engine configuration
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Configuration
|
||||
class VelocityEngineConfig {
|
||||
@Bean
|
||||
fun velocityEngine() = VelocityEngine().apply {
|
||||
setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath")
|
||||
setProperty("classpath.resource.loader.class", ClasspathResourceLoader::class.java.name)
|
||||
init()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package top.fatweb.oxygen.api.config
|
||||
|
||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.web.servlet.config.annotation.PathMatchConfigurer
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
|
||||
import top.fatweb.oxygen.api.annotation.ApiController
|
||||
|
||||
/**
|
||||
* Web MVC configurer configuration
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see WebMvcRegistrations
|
||||
*/
|
||||
@Configuration
|
||||
class WebMvcConfigurerConfig : WebMvcConfigurer {
|
||||
override fun configurePathMatch(configurer: PathMatchConfigurer) {
|
||||
configurer.addPathPrefix("/api/{API_VERSION}") { it.isAnnotationPresent(ApiController::class.java) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package top.fatweb.oxygen.api.config
|
||||
|
||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcRegistrations
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping
|
||||
import top.fatweb.oxygen.api.util.ApiResponseMappingHandlerMapping
|
||||
|
||||
/**
|
||||
* Web MVC registrations configuration
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see WebMvcRegistrations
|
||||
*/
|
||||
@Configuration
|
||||
class WebMvcRegistrationsConfig : WebMvcRegistrations {
|
||||
override fun getRequestMappingHandlerMapping(): RequestMappingHandlerMapping = ApiResponseMappingHandlerMapping()
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package top.fatweb.oxygen.api.controller
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import org.springframework.web.bind.annotation.RequestMapping
|
||||
import top.fatweb.oxygen.api.annotation.HiddenController
|
||||
|
||||
/**
|
||||
* Exception controller
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@HiddenController(["/error"])
|
||||
class ExceptionController {
|
||||
@RequestMapping("/thrown")
|
||||
fun thrown(request: HttpServletRequest) {
|
||||
throw request.getAttribute("filter.error") as RuntimeException
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
package top.fatweb.oxygen.api.controller.api.v1
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation
|
||||
import jakarta.validation.Valid
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import top.fatweb.oxygen.api.annotation.ApiController
|
||||
import top.fatweb.oxygen.api.entity.common.ResponseCode
|
||||
import top.fatweb.oxygen.api.entity.common.ResponseResult
|
||||
import top.fatweb.oxygen.api.param.api.v1.avatar.AvatarBaseParam
|
||||
import top.fatweb.oxygen.api.param.api.v1.avatar.AvatarGitHubParam
|
||||
import top.fatweb.oxygen.api.service.api.v1.IAvatarService
|
||||
import top.fatweb.oxygen.api.vo.api.v1.avatar.AvatarBase64Vo
|
||||
|
||||
/**
|
||||
* Avatar controller
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see IAvatarService
|
||||
*/
|
||||
@ApiController(value = "avatarControllerV1", path = ["/avatar"], name = "随机头像 V1", description = "随机头像相关接口")
|
||||
class AvatarController(
|
||||
private val avatarService: IAvatarService
|
||||
) {
|
||||
/**
|
||||
* Get random avatar
|
||||
*
|
||||
* @param avatarBaseParam Avatar base parameters
|
||||
* @return Avatar byte array
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see AvatarBaseParam
|
||||
* @see ByteArray
|
||||
*/
|
||||
@Operation(summary = "获取随机头像")
|
||||
@GetMapping(produces = [MediaType.IMAGE_PNG_VALUE])
|
||||
fun getRandom(@Valid avatarBaseParam: AvatarBaseParam?): ByteArray =
|
||||
avatarService.random(avatarBaseParam)
|
||||
|
||||
/**
|
||||
* Get random avatar as base64
|
||||
*
|
||||
* @param avatarBaseParam Avatar base parameters
|
||||
* @return Response object includes avatar base64 string
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see AvatarBaseParam
|
||||
* @see ResponseResult
|
||||
* @see AvatarBase64Vo
|
||||
*/
|
||||
@Operation(summary = "获取随机头像 Base64")
|
||||
@GetMapping("base64")
|
||||
fun getRandomBase64(
|
||||
@Valid avatarBaseParam: AvatarBaseParam?
|
||||
): ResponseResult<AvatarBase64Vo> =
|
||||
ResponseResult.success(
|
||||
ResponseCode.API_AVATAR_SUCCESS, data = avatarService.randomBase64(avatarBaseParam)
|
||||
)
|
||||
|
||||
/**
|
||||
* Get triangle avatar
|
||||
*
|
||||
* @param avatarBaseParam Avatar base parameters
|
||||
* @return Avatar byte array
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see AvatarBaseParam
|
||||
* @see ByteArray
|
||||
*/
|
||||
@Operation(summary = "三角形头像")
|
||||
@GetMapping("/triangle", produces = [MediaType.IMAGE_PNG_VALUE])
|
||||
fun triangle(@Valid avatarBaseParam: AvatarBaseParam?): ByteArray =
|
||||
avatarService.triangle(avatarBaseParam)
|
||||
|
||||
/**
|
||||
* Get triangle avatar as base64
|
||||
*
|
||||
* @param avatarBaseParam Avatar base parameters
|
||||
* @return Response object includes avatar base64 string
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see AvatarBaseParam
|
||||
* @see ResponseResult
|
||||
* @see AvatarBase64Vo
|
||||
*/
|
||||
@Operation(summary = "三角形头像 Base64")
|
||||
@GetMapping("/triangle/base64")
|
||||
fun triangleBase64(
|
||||
@Valid avatarBaseParam: AvatarBaseParam?
|
||||
): ResponseResult<AvatarBase64Vo> =
|
||||
ResponseResult.success(
|
||||
ResponseCode.API_AVATAR_SUCCESS,
|
||||
data = avatarService.triangleBase64(avatarBaseParam)
|
||||
)
|
||||
|
||||
/**
|
||||
* Get square avatar
|
||||
*
|
||||
* @param avatarBaseParam Avatar base parameters
|
||||
* @return Avatar byte array
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see AvatarBaseParam
|
||||
* @see ByteArray
|
||||
*/
|
||||
@Operation(summary = "正方形头像")
|
||||
@GetMapping("/square", produces = [MediaType.IMAGE_PNG_VALUE])
|
||||
fun square(@Valid avatarBaseParam: AvatarBaseParam?): ByteArray =
|
||||
avatarService.square(avatarBaseParam)
|
||||
|
||||
/**
|
||||
* Get square avatar as base64
|
||||
*
|
||||
* @param avatarBaseParam Avatar base parameters
|
||||
* @return Response object includes avatar base64 string
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see AvatarBaseParam
|
||||
* @see ResponseResult
|
||||
* @see AvatarBase64Vo
|
||||
*/
|
||||
@Operation(summary = "正方形头像 Base64")
|
||||
@GetMapping("/square/base64")
|
||||
fun squareBase64(
|
||||
@Valid avatarBaseParam: AvatarBaseParam?
|
||||
): ResponseResult<AvatarBase64Vo> =
|
||||
ResponseResult.success(
|
||||
ResponseCode.API_AVATAR_SUCCESS,
|
||||
data = avatarService.squareBase64(avatarBaseParam)
|
||||
)
|
||||
|
||||
/**
|
||||
* Get identicon avatar
|
||||
*
|
||||
* @param avatarBaseParam Avatar base parameters
|
||||
* @return Avatar byte array
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see AvatarBaseParam
|
||||
* @see ByteArray
|
||||
*/
|
||||
@Operation(summary = "Identicon 头像")
|
||||
@GetMapping("/identicon", produces = [MediaType.IMAGE_PNG_VALUE])
|
||||
fun identicon(@Valid avatarBaseParam: AvatarBaseParam?): ByteArray =
|
||||
avatarService.identicon(avatarBaseParam)
|
||||
|
||||
/**
|
||||
* Get identicon avatar as base64
|
||||
*
|
||||
* @param avatarBaseParam Avatar base parameters
|
||||
* @return Response object includes avatar base64 string
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see AvatarBaseParam
|
||||
* @see ResponseResult
|
||||
* @see AvatarBase64Vo
|
||||
*/
|
||||
@Operation(summary = "Identicon 头像 Base64")
|
||||
@GetMapping("/identicon/base64")
|
||||
fun identiconBase64(
|
||||
@Valid avatarBaseParam: AvatarBaseParam?
|
||||
): ResponseResult<AvatarBase64Vo> =
|
||||
ResponseResult.success(
|
||||
ResponseCode.API_AVATAR_SUCCESS,
|
||||
data = avatarService.identiconBase64(avatarBaseParam)
|
||||
)
|
||||
|
||||
/**
|
||||
* Get GitHub avatar
|
||||
*
|
||||
* @param avatarGitHubParam Avatar base parameters
|
||||
* @return Avatar byte array
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see AvatarGitHubParam
|
||||
* @see ByteArray
|
||||
*/
|
||||
@Operation(summary = "GitHub 头像")
|
||||
@GetMapping("/github", produces = [MediaType.IMAGE_PNG_VALUE])
|
||||
fun github(@Valid avatarGitHubParam: AvatarGitHubParam?): ByteArray =
|
||||
avatarService.github(avatarGitHubParam)
|
||||
|
||||
/**
|
||||
* Get GitHub avatar as base64
|
||||
*
|
||||
* @param avatarGitHubParam Avatar base parameters
|
||||
* @return Response object includes avatar base64 string
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see AvatarGitHubParam
|
||||
* @see ResponseResult
|
||||
* @see AvatarBase64Vo
|
||||
*/
|
||||
@Operation(summary = "GitHub 头像 Base64")
|
||||
@GetMapping("/github/base64")
|
||||
fun githubBase64(
|
||||
@Valid avatarGitHubParam: AvatarGitHubParam?
|
||||
): ResponseResult<AvatarBase64Vo> =
|
||||
ResponseResult.success(
|
||||
ResponseCode.API_AVATAR_SUCCESS,
|
||||
data = avatarService.githubBase64(avatarGitHubParam)
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
package top.fatweb.oxygen.api.controller.permission
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.validation.Valid
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.PostMapping
|
||||
import org.springframework.web.bind.annotation.RequestBody
|
||||
import top.fatweb.oxygen.api.annotation.BaseController
|
||||
import top.fatweb.oxygen.api.entity.common.ResponseCode
|
||||
import top.fatweb.oxygen.api.entity.common.ResponseResult
|
||||
import top.fatweb.oxygen.api.param.permission.*
|
||||
import top.fatweb.oxygen.api.service.permission.IAuthenticationService
|
||||
import top.fatweb.oxygen.api.util.WebUtil
|
||||
import top.fatweb.oxygen.api.vo.permission.LoginVo
|
||||
import top.fatweb.oxygen.api.vo.permission.RegisterVo
|
||||
import top.fatweb.oxygen.api.vo.permission.TokenVo
|
||||
|
||||
/**
|
||||
* Authentication controller
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see IAuthenticationService
|
||||
*/
|
||||
@BaseController(name = "身份认证", description = "身份认证相关接口")
|
||||
class AuthenticationController(
|
||||
private val authenticationService: IAuthenticationService
|
||||
) {
|
||||
/**
|
||||
* Register
|
||||
*
|
||||
* @param registerParam Register parameters
|
||||
* @return Response object includes user ID
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see RegisterParam
|
||||
* @see ResponseResult
|
||||
* @see RegisterVo
|
||||
*/
|
||||
@Operation(summary = "注册")
|
||||
@PostMapping("/register")
|
||||
fun register(@Valid @RequestBody registerParam: RegisterParam): ResponseResult<RegisterVo> = ResponseResult.success(
|
||||
ResponseCode.PERMISSION_REGISTER_SUCCESS,
|
||||
data = authenticationService.register(registerParam)
|
||||
)
|
||||
|
||||
|
||||
/**
|
||||
* Send verify email
|
||||
*
|
||||
* @return Response object includes resend result
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see ResponseResult
|
||||
*/
|
||||
@Operation(summary = "发送验证邮件")
|
||||
@PostMapping("/resend")
|
||||
fun resend(): ResponseResult<Nothing> {
|
||||
authenticationService.resend()
|
||||
|
||||
return ResponseResult.success(ResponseCode.PERMISSION_RESEND_SUCCESS)
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify email
|
||||
*
|
||||
* @param verifyParam Verify parameters
|
||||
* @return Response object includes verify result
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see VerifyParam
|
||||
* @see ResponseResult
|
||||
*/
|
||||
@Operation(summary = "验证邮箱")
|
||||
@PostMapping("/verify")
|
||||
fun verify(@Valid @RequestBody verifyParam: VerifyParam): ResponseResult<Nothing> {
|
||||
authenticationService.verify(verifyParam)
|
||||
|
||||
return ResponseResult.success(ResponseCode.PERMISSION_VERIFY_SUCCESS)
|
||||
}
|
||||
|
||||
/**
|
||||
* Forget password
|
||||
*
|
||||
* @param request
|
||||
* @param forgetParam Forget parameters
|
||||
* @return Response object includes forget result
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see HttpServletRequest
|
||||
* @see ForgetParam
|
||||
* @see ResponseResult
|
||||
*/
|
||||
@Operation(summary = "忘记密码")
|
||||
@PostMapping("/forget")
|
||||
fun forget(request: HttpServletRequest, @Valid @RequestBody forgetParam: ForgetParam): ResponseResult<Nothing> {
|
||||
authenticationService.forget(request, forgetParam)
|
||||
|
||||
return ResponseResult.success(ResponseCode.PERMISSION_FORGET_SUCCESS)
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve password
|
||||
*
|
||||
* @param request
|
||||
* @param retrieveParam Retrieve parameters
|
||||
* @return Response object include retrieve result
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see HttpServletRequest
|
||||
* @see RetrieveParam
|
||||
* @see ResponseResult
|
||||
*/
|
||||
@Operation(summary = "找回密码")
|
||||
@PostMapping("/retrieve")
|
||||
fun retrieve(
|
||||
request: HttpServletRequest,
|
||||
@Valid @RequestBody retrieveParam: RetrieveParam
|
||||
): ResponseResult<Nothing> {
|
||||
authenticationService.retrieve(request, retrieveParam)
|
||||
|
||||
return ResponseResult.success(ResponseCode.PERMISSION_RETRIEVE_SUCCESS)
|
||||
}
|
||||
|
||||
/**
|
||||
* Login
|
||||
*
|
||||
* @param request
|
||||
* @param loginParam Login parameters
|
||||
* @return Response object includes login result
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see HttpServletRequest
|
||||
* @see LoginParam
|
||||
* @see ResponseResult
|
||||
* @see LoginVo
|
||||
*/
|
||||
@Operation(summary = "登录")
|
||||
@PostMapping("/login")
|
||||
fun login(request: HttpServletRequest, @Valid @RequestBody loginParam: LoginParam): ResponseResult<LoginVo> =
|
||||
ResponseResult.success(
|
||||
ResponseCode.PERMISSION_LOGIN_SUCCESS,
|
||||
"Login success",
|
||||
authenticationService.login(request, loginParam)
|
||||
)
|
||||
|
||||
/**
|
||||
* Logout
|
||||
*
|
||||
* @param request
|
||||
* @return Response object includes logout result
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see HttpServletRequest
|
||||
* @see ResponseResult
|
||||
*/
|
||||
@Operation(summary = "登出")
|
||||
@PostMapping("/logout")
|
||||
fun logout(request: HttpServletRequest): ResponseResult<Nothing> =
|
||||
when (authenticationService.logout(WebUtil.getToken(request))) {
|
||||
true -> ResponseResult.success(ResponseCode.PERMISSION_LOGOUT_SUCCESS, "Logout success", null)
|
||||
false -> ResponseResult.fail(ResponseCode.PERMISSION_LOGOUT_FAILED, "Logout failed", null)
|
||||
}
|
||||
|
||||
/**
|
||||
* Renew token
|
||||
*
|
||||
* @param request
|
||||
* @return Response object includes new token
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see HttpServletRequest
|
||||
* @see ResponseResult
|
||||
* @see TokenVo
|
||||
*/
|
||||
@Operation(summary = "更新 Token")
|
||||
@GetMapping("/token")
|
||||
fun renewToken(request: HttpServletRequest): ResponseResult<TokenVo> = ResponseResult.success(
|
||||
ResponseCode.PERMISSION_TOKEN_RENEW_SUCCESS,
|
||||
"Token renew success",
|
||||
authenticationService.renewToken(WebUtil.getToken(request))
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package top.fatweb.oxygen.api.controller.permission
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation
|
||||
import jakarta.validation.Valid
|
||||
import org.springframework.security.access.prepost.PreAuthorize
|
||||
import org.springframework.web.bind.annotation.*
|
||||
import top.fatweb.oxygen.api.annotation.BaseController
|
||||
import top.fatweb.oxygen.api.entity.common.ResponseCode
|
||||
import top.fatweb.oxygen.api.entity.common.ResponseResult
|
||||
import top.fatweb.oxygen.api.param.permission.group.*
|
||||
import top.fatweb.oxygen.api.service.permission.IGroupService
|
||||
import top.fatweb.oxygen.api.vo.PageVo
|
||||
import top.fatweb.oxygen.api.vo.permission.GroupWithRoleVo
|
||||
import top.fatweb.oxygen.api.vo.permission.base.GroupVo
|
||||
|
||||
/**
|
||||
* Group controller
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see IGroupService
|
||||
*/
|
||||
@BaseController(path = ["/system/group"], name = "用户组管理", description = "用户组管理相关接口")
|
||||
class GroupController(
|
||||
val groupService: IGroupService
|
||||
) {
|
||||
/**
|
||||
* Get group by ID
|
||||
*
|
||||
* @param id Group ID
|
||||
* @return Response object includes group info
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see ResponseResult
|
||||
* @see GroupWithRoleVo
|
||||
*/
|
||||
@Operation(summary = "获取单个用户组")
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("hasAnyAuthority('system:group:query:one')")
|
||||
fun getOne(@PathVariable id: Long): ResponseResult<GroupWithRoleVo> =
|
||||
ResponseResult.databaseSuccess(
|
||||
data = groupService.getOne(id)
|
||||
)
|
||||
|
||||
/**
|
||||
* Get group paging information
|
||||
*
|
||||
* @param groupGetParam Get group parameters
|
||||
* @return Response object includes group paging information
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see GroupGetParam
|
||||
* @see ResponseResult
|
||||
* @see PageVo
|
||||
* @see GroupWithRoleVo
|
||||
*/
|
||||
@Operation(summary = "获取用户组")
|
||||
@GetMapping
|
||||
@PreAuthorize("hasAnyAuthority('system:group:query:all')")
|
||||
fun get(@Valid groupGetParam: GroupGetParam?): ResponseResult<PageVo<GroupWithRoleVo>> =
|
||||
ResponseResult.databaseSuccess(
|
||||
data = groupService.getPage(groupGetParam)
|
||||
)
|
||||
|
||||
/**
|
||||
* Get group list
|
||||
*
|
||||
* @return Response object includes group list
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see ResponseResult
|
||||
* @see GroupVo
|
||||
*/
|
||||
@Operation(summary = "获取用户组列表")
|
||||
@GetMapping("/list")
|
||||
@PreAuthorize("hasAnyAuthority('system:group:query:list', 'system:user:add:one', 'system:user:modify:one')")
|
||||
fun list(): ResponseResult<List<GroupVo>> =
|
||||
ResponseResult.databaseSuccess(
|
||||
data = groupService.listAll()
|
||||
)
|
||||
|
||||
/**
|
||||
* Add group
|
||||
*
|
||||
* @param groupAddParam Add group parameters
|
||||
* @return Response object includes group information
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see GroupAddParam
|
||||
* @see ResponseResult
|
||||
* @see GroupVo
|
||||
*/
|
||||
@Operation(summary = "添加用户组")
|
||||
@PostMapping
|
||||
@PreAuthorize("hasAnyAuthority('system:group:add:one')")
|
||||
fun add(@Valid @RequestBody groupAddParam: GroupAddParam): ResponseResult<GroupVo> =
|
||||
groupService.add(groupAddParam)?.let {
|
||||
ResponseResult.databaseSuccess(
|
||||
ResponseCode.DATABASE_INSERT_SUCCESS, data = it
|
||||
)
|
||||
} ?: let { ResponseResult.databaseFail(ResponseCode.DATABASE_INSERT_FAILED) }
|
||||
|
||||
/**
|
||||
* Update group
|
||||
*
|
||||
* @param groupUpdateParam Update group parameters
|
||||
* @return Response object includes group information
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see GroupUpdateParam
|
||||
* @see ResponseResult
|
||||
* @see GroupVo
|
||||
*/
|
||||
@Operation(summary = "修改用户组")
|
||||
@PutMapping
|
||||
@PreAuthorize("hasAnyAuthority('system:group:modify:one')")
|
||||
fun update(@Valid @RequestBody groupUpdateParam: GroupUpdateParam): ResponseResult<GroupVo> =
|
||||
groupService.update(groupUpdateParam)?.let {
|
||||
ResponseResult.databaseSuccess(
|
||||
ResponseCode.DATABASE_UPDATE_SUCCESS, data = it
|
||||
)
|
||||
} ?: let { ResponseResult.databaseFail(ResponseCode.DATABASE_UPDATE_FILED) }
|
||||
|
||||
/**
|
||||
* Update status of group
|
||||
*
|
||||
* @param groupUpdateStatusParam Update status of group parameters
|
||||
* @return Response object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see GroupUpdateStatusParam
|
||||
* @see ResponseResult
|
||||
*/
|
||||
@Operation(summary = "修改用户组状态")
|
||||
@PatchMapping
|
||||
@PreAuthorize("hasAnyAuthority('system:group:modify:status')")
|
||||
fun updateStatus(@Valid @RequestBody groupUpdateStatusParam: GroupUpdateStatusParam): ResponseResult<Nothing> =
|
||||
if (groupService.status(groupUpdateStatusParam)) {
|
||||
ResponseResult.databaseSuccess(ResponseCode.DATABASE_UPDATE_SUCCESS)
|
||||
} else {
|
||||
ResponseResult.databaseFail(ResponseCode.DATABASE_UPDATE_FILED)
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete group by ID
|
||||
*
|
||||
* @param id Group ID
|
||||
* @return Response object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see ResponseResult
|
||||
*/
|
||||
@Operation(summary = "删除用户组")
|
||||
@DeleteMapping("/{id}")
|
||||
@PreAuthorize("hasAnyAuthority('system:group:delete:one')")
|
||||
fun delete(@PathVariable id: Long): ResponseResult<Nothing> {
|
||||
groupService.deleteOne(id)
|
||||
return ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS)
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete group by list
|
||||
*
|
||||
* @param groupDeleteParam Delete group parameters
|
||||
* @return Response object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see GroupDeleteParam
|
||||
* @see ResponseResult
|
||||
*/
|
||||
@Operation(summary = "批量删除用户组")
|
||||
@DeleteMapping
|
||||
@PreAuthorize("hasAnyAuthority('system:group:delete:multiple')")
|
||||
fun deleteList(@Valid @RequestBody groupDeleteParam: GroupDeleteParam): ResponseResult<Nothing> {
|
||||
groupService.delete(groupDeleteParam)
|
||||
return ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package top.fatweb.oxygen.api.controller.permission
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation
|
||||
import org.springframework.security.access.prepost.PreAuthorize
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import top.fatweb.oxygen.api.annotation.BaseController
|
||||
import top.fatweb.oxygen.api.entity.common.ResponseResult
|
||||
import top.fatweb.oxygen.api.service.permission.IPowerService
|
||||
import top.fatweb.oxygen.api.vo.permission.PowerSetVo
|
||||
|
||||
/**
|
||||
* Power controller
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see IPowerService
|
||||
*/
|
||||
@BaseController(path = ["/system/power"], name = "权限管理", description = "权限管理相关接口")
|
||||
class PowerController(
|
||||
private val powerService: IPowerService
|
||||
) {
|
||||
/**
|
||||
* Get power list
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see ResponseResult
|
||||
* @see PowerSetVo
|
||||
*/
|
||||
@Operation(summary = "获取权限列表")
|
||||
@GetMapping("/list")
|
||||
@PreAuthorize("hasAnyAuthority('system:power:query:list', 'system:role:add:one', 'system:role:modify:one')")
|
||||
fun getList(): ResponseResult<PowerSetVo> = ResponseResult.databaseSuccess(data = powerService.getList())
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
package top.fatweb.oxygen.api.controller.permission
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation
|
||||
import jakarta.validation.Valid
|
||||
import org.springframework.security.access.prepost.PreAuthorize
|
||||
import org.springframework.web.bind.annotation.*
|
||||
import top.fatweb.oxygen.api.annotation.BaseController
|
||||
import top.fatweb.oxygen.api.entity.common.ResponseCode
|
||||
import top.fatweb.oxygen.api.entity.common.ResponseResult
|
||||
import top.fatweb.oxygen.api.param.permission.role.*
|
||||
import top.fatweb.oxygen.api.service.permission.IRoleService
|
||||
import top.fatweb.oxygen.api.vo.PageVo
|
||||
import top.fatweb.oxygen.api.vo.permission.RoleWithPowerVo
|
||||
import top.fatweb.oxygen.api.vo.permission.base.RoleVo
|
||||
|
||||
/**
|
||||
* Role controller
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see IRoleService
|
||||
*/
|
||||
@BaseController(path = ["/system/role"], name = "角色管理", description = "角色管理相关接口")
|
||||
class RoleController(
|
||||
private val roleService: IRoleService
|
||||
) {
|
||||
/**
|
||||
* Get role by ID
|
||||
*
|
||||
* @param id Role ID
|
||||
* @return Response object includes role information
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see ResponseResult
|
||||
* @see RoleWithPowerVo
|
||||
*/
|
||||
@Operation(summary = "获取单个角色")
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("hasAnyAuthority('system:role:query:one')")
|
||||
fun getOne(@PathVariable id: Long): ResponseResult<RoleWithPowerVo> {
|
||||
return ResponseResult.databaseSuccess(
|
||||
data = roleService.getOne(id)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get role paging information
|
||||
*
|
||||
* @param roleGetParam Get role parameters
|
||||
* @return Response object includes role paging information
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see RoleGetParam
|
||||
* @see ResponseResult
|
||||
* @see RoleWithPowerVo
|
||||
*/
|
||||
@Operation(summary = "获取角色")
|
||||
@GetMapping
|
||||
@PreAuthorize("hasAnyAuthority('system:role:query:all')")
|
||||
fun get(roleGetParam: RoleGetParam?): ResponseResult<PageVo<RoleWithPowerVo>> {
|
||||
return ResponseResult.databaseSuccess(
|
||||
data = roleService.getPage(roleGetParam)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get role list
|
||||
*
|
||||
* @return Response object includes role list
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see ResponseResult
|
||||
* @see RoleVo
|
||||
*/
|
||||
@Operation(summary = "获取角色列表")
|
||||
@GetMapping("/list")
|
||||
@PreAuthorize("hasAnyAuthority('system:role:query:list', 'system:group:add:one', 'system:group:modify:one', 'system:user:add:one', 'system:user:modify:one')")
|
||||
fun list(): ResponseResult<List<RoleVo>> {
|
||||
return ResponseResult.databaseSuccess(
|
||||
data = roleService.listAll()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Add role
|
||||
*
|
||||
* @param roleAddParam Add role parameters
|
||||
* @return Response object includes role information
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see RoleAddParam
|
||||
* @see ResponseResult
|
||||
* @see RoleVo
|
||||
*/
|
||||
@Operation(summary = "添加角色")
|
||||
@PostMapping
|
||||
@PreAuthorize("hasAnyAuthority('system:role:add:one')")
|
||||
fun add(@Valid @RequestBody roleAddParam: RoleAddParam): ResponseResult<RoleVo> {
|
||||
return roleService.add(roleAddParam)?.let {
|
||||
ResponseResult.databaseSuccess(
|
||||
ResponseCode.DATABASE_INSERT_SUCCESS, data = it
|
||||
)
|
||||
} ?: let { ResponseResult.databaseFail(ResponseCode.DATABASE_INSERT_FAILED) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Update role
|
||||
*
|
||||
* @param roleUpdateParam Update role parameters
|
||||
* @return Response object includes role information
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see RoleUpdateParam
|
||||
* @see ResponseResult
|
||||
* @see RoleVo
|
||||
*/
|
||||
@Operation(summary = "修改角色")
|
||||
@PutMapping
|
||||
@PreAuthorize("hasAnyAuthority('system:role:modify:one')")
|
||||
fun update(@Valid @RequestBody roleUpdateParam: RoleUpdateParam): ResponseResult<RoleVo> {
|
||||
return roleService.update(roleUpdateParam)?.let {
|
||||
ResponseResult.databaseSuccess(
|
||||
ResponseCode.DATABASE_UPDATE_SUCCESS, data = it
|
||||
)
|
||||
} ?: let { ResponseResult.databaseFail(ResponseCode.DATABASE_UPDATE_FILED) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Update status of role
|
||||
*
|
||||
* @param roleUpdateStatusParam Update status of role parameters
|
||||
* @return Response object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see RoleUpdateStatusParam
|
||||
* @see ResponseResult
|
||||
*/
|
||||
@Operation(summary = "修改角色状态")
|
||||
@PatchMapping
|
||||
@PreAuthorize("hasAnyAuthority('system:role:modify:status')")
|
||||
fun status(@Valid @RequestBody roleUpdateStatusParam: RoleUpdateStatusParam): ResponseResult<Nothing> {
|
||||
return if (roleService.status(roleUpdateStatusParam)) {
|
||||
ResponseResult.databaseSuccess(ResponseCode.DATABASE_UPDATE_SUCCESS)
|
||||
} else {
|
||||
ResponseResult.databaseFail(ResponseCode.DATABASE_UPDATE_FILED)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete role by ID
|
||||
*
|
||||
* @param id
|
||||
* @return Response object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see ResponseResult
|
||||
*/
|
||||
@Operation(summary = "删除角色")
|
||||
@DeleteMapping("/{id}")
|
||||
@PreAuthorize("hasAnyAuthority('system:role:delete:one')")
|
||||
fun delete(@PathVariable id: Long): ResponseResult<Nothing> {
|
||||
roleService.deleteOne(id)
|
||||
return ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS)
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete role by list
|
||||
*
|
||||
* @param roleDeleteParam Delete role parameters
|
||||
* @return Response object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see RoleDeleteParam
|
||||
* @see ResponseResult
|
||||
*/
|
||||
@Operation(summary = "批量删除角色")
|
||||
@DeleteMapping
|
||||
@PreAuthorize("hasAnyAuthority('system:role:delete:multiple')")
|
||||
fun deleteList(@Valid @RequestBody roleDeleteParam: RoleDeleteParam): ResponseResult<Nothing> {
|
||||
roleService.delete(roleDeleteParam)
|
||||
return ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,178 @@
|
||||
package top.fatweb.oxygen.api.controller.permission
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation
|
||||
import jakarta.validation.Valid
|
||||
import org.springframework.security.access.prepost.PreAuthorize
|
||||
import org.springframework.web.bind.annotation.*
|
||||
import top.fatweb.oxygen.api.annotation.BaseController
|
||||
import top.fatweb.oxygen.api.entity.common.ResponseCode
|
||||
import top.fatweb.oxygen.api.entity.common.ResponseResult
|
||||
import top.fatweb.oxygen.api.exception.NoRecordFoundException
|
||||
import top.fatweb.oxygen.api.param.permission.user.*
|
||||
import top.fatweb.oxygen.api.service.permission.IUserService
|
||||
import top.fatweb.oxygen.api.vo.PageVo
|
||||
import top.fatweb.oxygen.api.vo.permission.UserWithPasswordRoleInfoVo
|
||||
import top.fatweb.oxygen.api.vo.permission.UserWithPowerInfoVo
|
||||
import top.fatweb.oxygen.api.vo.permission.UserWithRoleInfoVo
|
||||
|
||||
/**
|
||||
* User controller
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see IUserService
|
||||
*/
|
||||
@BaseController(path = ["/system/user"], name = "用户管理", description = "用户管理相关接口")
|
||||
class UserController(
|
||||
private val userService: IUserService
|
||||
) {
|
||||
/**
|
||||
* Get current user information
|
||||
*
|
||||
* @return Response object includes user information
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see ResponseResult
|
||||
* @see UserWithPowerInfoVo
|
||||
*/
|
||||
@Operation(summary = "获取当前用户信息")
|
||||
@GetMapping("info")
|
||||
fun getInfo(): ResponseResult<UserWithPowerInfoVo> =
|
||||
userService.getInfo()?.let {
|
||||
ResponseResult.databaseSuccess(data = it)
|
||||
} ?: let { ResponseResult.databaseFail() }
|
||||
|
||||
/**
|
||||
* Get user by ID
|
||||
*
|
||||
* @param id User ID
|
||||
* @return Response object includes user information
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see ResponseResult
|
||||
* @see UserWithRoleInfoVo
|
||||
*/
|
||||
@Operation(summary = "获取单个用户")
|
||||
@GetMapping("/{id}")
|
||||
@PreAuthorize("hasAnyAuthority('system:user:query:one')")
|
||||
fun getOne(@PathVariable id: Long): ResponseResult<UserWithRoleInfoVo> =
|
||||
userService.getOne(id)?.let {
|
||||
ResponseResult.databaseSuccess(data = it)
|
||||
} ?: let {
|
||||
throw NoRecordFoundException()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user paging information
|
||||
*
|
||||
* @param userGetParam Get user parameters
|
||||
* @return Response object includes user paging information
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see UserGetParam
|
||||
* @see ResponseResult
|
||||
* @see UserWithRoleInfoVo
|
||||
*/
|
||||
@Operation(summary = "获取用户")
|
||||
@GetMapping
|
||||
@PreAuthorize("hasAnyAuthority('system:user:query:all')")
|
||||
fun get(@Valid userGetParam: UserGetParam?): ResponseResult<PageVo<UserWithRoleInfoVo>> =
|
||||
ResponseResult.databaseSuccess(
|
||||
data = userService.getPage(userGetParam)
|
||||
)
|
||||
|
||||
/**
|
||||
* Add user
|
||||
*
|
||||
* @param userAddParam Add user parameters
|
||||
* @return Response object includes user information
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see UserAddParam
|
||||
* @see ResponseResult
|
||||
* @see UserWithPasswordRoleInfoVo
|
||||
*/
|
||||
@Operation(summary = "添加用户")
|
||||
@PostMapping
|
||||
@PreAuthorize("hasAnyAuthority('system:user:add:one')")
|
||||
fun add(@Valid @RequestBody userAddParam: UserAddParam): ResponseResult<UserWithPasswordRoleInfoVo> =
|
||||
userService.add(userAddParam)?.let {
|
||||
ResponseResult.databaseSuccess(
|
||||
ResponseCode.DATABASE_INSERT_SUCCESS, data = it
|
||||
)
|
||||
} ?: let { ResponseResult.databaseFail(ResponseCode.DATABASE_INSERT_FAILED) }
|
||||
|
||||
/**
|
||||
* Update user
|
||||
*
|
||||
* @param userUpdateParam Update user parameters
|
||||
* @return Response object includes user information
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see UserUpdateParam
|
||||
* @see ResponseResult
|
||||
* @see UserWithRoleInfoVo
|
||||
*/
|
||||
@Operation(summary = "修改用户")
|
||||
@PutMapping
|
||||
@PreAuthorize("hasAnyAuthority('system:user:modify:one')")
|
||||
fun update(@Valid @RequestBody userUpdateParam: UserUpdateParam): ResponseResult<UserWithRoleInfoVo> =
|
||||
userService.update(userUpdateParam)?.let {
|
||||
ResponseResult.databaseSuccess(
|
||||
ResponseCode.DATABASE_UPDATE_SUCCESS, data = it
|
||||
)
|
||||
} ?: let { ResponseResult.databaseFail(ResponseCode.DATABASE_UPDATE_FILED) }
|
||||
|
||||
/**
|
||||
* Update user password
|
||||
*
|
||||
* @param userUpdatePasswordParam Update user password parameters
|
||||
* @return Response object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see UserUpdatePasswordParam
|
||||
* @see ResponseResult
|
||||
*/
|
||||
@Operation(summary = "修改密码")
|
||||
@PatchMapping
|
||||
@PreAuthorize("hasAnyAuthority('system:user:modify:password')")
|
||||
fun password(@Valid @RequestBody userUpdatePasswordParam: UserUpdatePasswordParam): ResponseResult<Nothing> {
|
||||
userService.password(userUpdatePasswordParam)
|
||||
return ResponseResult.databaseSuccess(ResponseCode.DATABASE_UPDATE_SUCCESS)
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete user by ID
|
||||
*
|
||||
* @param id User ID
|
||||
* @return Response object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see ResponseResult
|
||||
*/
|
||||
@Operation(summary = "删除用户")
|
||||
@DeleteMapping("/{id}")
|
||||
@PreAuthorize("hasAnyAuthority('system:user:delete:one')")
|
||||
fun delete(@PathVariable id: Long): ResponseResult<Nothing> {
|
||||
userService.deleteOne(id)
|
||||
return ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS)
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete user by list
|
||||
*
|
||||
* @param userDeleteParam Delete user parameters
|
||||
* @return Response object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see UserDeleteParam
|
||||
* @see ResponseResult
|
||||
*/
|
||||
@Operation(summary = "批量删除用户")
|
||||
@DeleteMapping
|
||||
@PreAuthorize("hasAnyAuthority('system:user:delete:multiple')")
|
||||
fun deleteList(@Valid @RequestBody userDeleteParam: UserDeleteParam): ResponseResult<Nothing> {
|
||||
userService.delete(userDeleteParam)
|
||||
return ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package top.fatweb.oxygen.api.controller.system
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation
|
||||
import jakarta.validation.Valid
|
||||
import org.springframework.security.access.prepost.PreAuthorize
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import org.springframework.web.bind.annotation.PostMapping
|
||||
import org.springframework.web.bind.annotation.PutMapping
|
||||
import org.springframework.web.bind.annotation.RequestBody
|
||||
import top.fatweb.oxygen.api.annotation.BaseController
|
||||
import top.fatweb.oxygen.api.entity.common.ResponseResult
|
||||
import top.fatweb.oxygen.api.param.system.BaseSettingsParam
|
||||
import top.fatweb.oxygen.api.param.system.MailSendParam
|
||||
import top.fatweb.oxygen.api.param.system.MailSettingsParam
|
||||
import top.fatweb.oxygen.api.service.system.ISettingsService
|
||||
import top.fatweb.oxygen.api.vo.system.BaseSettingsVo
|
||||
import top.fatweb.oxygen.api.vo.system.MailSettingsVo
|
||||
|
||||
/**
|
||||
* System settings controller
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see ISettingsService
|
||||
*/
|
||||
@BaseController(path = ["/system/settings"], name = "系统设置", description = "系统设置相关接口")
|
||||
class SettingsController(
|
||||
private val settingsService: ISettingsService
|
||||
) {
|
||||
/**
|
||||
* Get base settings
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Operation(summary = "获取基础设置")
|
||||
@GetMapping("/base")
|
||||
@PreAuthorize("hasAnyAuthority('system:settings:query:base')")
|
||||
fun getApp(): ResponseResult<BaseSettingsVo> = ResponseResult.success(data = settingsService.getBase())
|
||||
|
||||
/**
|
||||
* Update base settings
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Operation(summary = "更新基础设置")
|
||||
@PutMapping("/base")
|
||||
@PreAuthorize("hasAnyAuthority('system:settings:modify:base')")
|
||||
fun updateApp(@RequestBody baseSettingsParam: BaseSettingsParam): ResponseResult<Nothing> {
|
||||
settingsService.updateBase(baseSettingsParam)
|
||||
return ResponseResult.success()
|
||||
}
|
||||
|
||||
/**
|
||||
* Get mail settings
|
||||
*
|
||||
* @return Response object includes mail settings
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see ResponseResult
|
||||
* @see MailSettingsVo
|
||||
*/
|
||||
@Operation(summary = "获取邮件设置")
|
||||
@GetMapping("/mail")
|
||||
@PreAuthorize("hasAnyAuthority('system:settings:query:mail')")
|
||||
fun getMail(): ResponseResult<MailSettingsVo> = ResponseResult.success(data = settingsService.getMail())
|
||||
|
||||
/**
|
||||
* Update mail settings
|
||||
*
|
||||
* @param mailSettingsParam Mail settings parameters
|
||||
* @return Response object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see MailSettingsParam
|
||||
* @see ResponseResult
|
||||
*/
|
||||
@Operation(summary = "更新邮件设置")
|
||||
@PutMapping("/mail")
|
||||
@PreAuthorize("hasAnyAuthority('system:settings:modify:mail')")
|
||||
fun updateMail(@RequestBody mailSettingsParam: MailSettingsParam): ResponseResult<Nothing> {
|
||||
settingsService.updateMail(mailSettingsParam)
|
||||
return ResponseResult.success()
|
||||
}
|
||||
|
||||
/**
|
||||
* Send mail test
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Operation(summary = "邮件发送测试")
|
||||
@PostMapping("/mail")
|
||||
@PreAuthorize("hasAnyAuthority('system:settings:modify:mail')")
|
||||
fun sendMail(@RequestBody @Valid mailSendParam: MailSendParam): ResponseResult<Nothing> {
|
||||
settingsService.sendMail(mailSendParam)
|
||||
return ResponseResult.success()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package top.fatweb.oxygen.api.controller.system
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation
|
||||
import org.springframework.security.access.prepost.PreAuthorize
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import top.fatweb.oxygen.api.annotation.BaseController
|
||||
import top.fatweb.oxygen.api.entity.common.ResponseResult
|
||||
import top.fatweb.oxygen.api.param.system.ActiveInfoGetParam
|
||||
import top.fatweb.oxygen.api.param.system.OnlineInfoGetParam
|
||||
import top.fatweb.oxygen.api.service.system.IStatisticsService
|
||||
import top.fatweb.oxygen.api.vo.system.*
|
||||
|
||||
/**
|
||||
* Statistics controller
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see IStatisticsService
|
||||
*/
|
||||
@BaseController(path = ["/system/statistics"], name = "统计接口", description = "系统信息统计相关接口")
|
||||
class StatisticsController(
|
||||
private val statisticService: IStatisticsService
|
||||
) {
|
||||
/**
|
||||
* Get software information
|
||||
*
|
||||
* @return Response object includes software information
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see ResponseResult
|
||||
* @see SoftwareInfoVo
|
||||
*/
|
||||
@Operation(summary = "获取软件信息")
|
||||
@GetMapping("/software")
|
||||
@PreAuthorize("hasAnyAuthority('system:statistics:query:base')")
|
||||
fun software(): ResponseResult<SoftwareInfoVo> = ResponseResult.success(data = statisticService.software())
|
||||
|
||||
/**
|
||||
* Get hardware information
|
||||
*
|
||||
* @return Response object includes hardware information
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see ResponseResult
|
||||
* @see HardwareInfoVo
|
||||
*/
|
||||
@Operation(summary = "获取硬件信息")
|
||||
@GetMapping("/hardware")
|
||||
@PreAuthorize("hasAnyAuthority('system:statistics:query:base')")
|
||||
fun hardware(): ResponseResult<HardwareInfoVo> = ResponseResult.success(data = statisticService.hardware())
|
||||
|
||||
/**
|
||||
* Get CPU information
|
||||
*
|
||||
* @return Response object includes CPU information
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see ResponseResult
|
||||
* @see CpuInfoVo
|
||||
*/
|
||||
@Operation(summary = "获取 CPU 信息")
|
||||
@GetMapping("/cpu")
|
||||
@PreAuthorize("hasAnyAuthority('system:statistics:query:real')")
|
||||
fun cpu(): ResponseResult<CpuInfoVo> = ResponseResult.success(data = statisticService.cpu())
|
||||
|
||||
/**
|
||||
* Get storage information
|
||||
*
|
||||
* @return Response object includes storage information
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see ResponseResult
|
||||
* @see StorageInfoVo
|
||||
*/
|
||||
@Operation(summary = "获取存储信息")
|
||||
@GetMapping("/storage")
|
||||
@PreAuthorize("hasAnyAuthority('system:statistics:query:real')")
|
||||
fun storage(): ResponseResult<StorageInfoVo> = ResponseResult.success(data = statisticService.storage())
|
||||
|
||||
/**
|
||||
* Get the history of online users information
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Operation(summary = "获取在线用户数量信息")
|
||||
@GetMapping("/online")
|
||||
@PreAuthorize("hasAnyAuthority('system:statistics:query:usage')")
|
||||
fun online(onlineInfoGetParam: OnlineInfoGetParam?): ResponseResult<OnlineInfoVo> =
|
||||
ResponseResult.success(data = statisticService.online(onlineInfoGetParam))
|
||||
|
||||
/**
|
||||
* Get the history of active information
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Operation(summary = "获取用户活跃信息")
|
||||
@GetMapping("/active")
|
||||
@PreAuthorize("hasAnyAuthority('system:statistics:query:usage')")
|
||||
fun active(activeInfoGetParam: ActiveInfoGetParam): ResponseResult<ActiveInfoVo> =
|
||||
ResponseResult.success(data = statisticService.active(activeInfoGetParam))
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package top.fatweb.oxygen.api.controller.system
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation
|
||||
import jakarta.validation.Valid
|
||||
import org.springframework.security.access.prepost.PreAuthorize
|
||||
import org.springframework.web.bind.annotation.GetMapping
|
||||
import top.fatweb.oxygen.api.annotation.BaseController
|
||||
import top.fatweb.oxygen.api.entity.common.ResponseCode
|
||||
import top.fatweb.oxygen.api.entity.common.ResponseResult
|
||||
import top.fatweb.oxygen.api.param.system.SysLogGetParam
|
||||
import top.fatweb.oxygen.api.service.system.ISysLogService
|
||||
import top.fatweb.oxygen.api.vo.PageVo
|
||||
import top.fatweb.oxygen.api.vo.system.SysLogVo
|
||||
|
||||
/**
|
||||
* System log controller
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see ISysLogService
|
||||
*/
|
||||
@BaseController(path = ["/system/log"], name = "系统日志", description = "系统日志相关接口")
|
||||
class SysLogController(
|
||||
private val sysLogService: ISysLogService
|
||||
) {
|
||||
/**
|
||||
* Get system log
|
||||
*
|
||||
* @param sysLogGetParam Get system log parameters
|
||||
* @return Response object includes system log
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see SysLogGetParam
|
||||
* @see ResponseResult
|
||||
* @see SysLogVo
|
||||
*/
|
||||
@Operation(summary = "获取")
|
||||
@GetMapping
|
||||
@PreAuthorize("hasAnyAuthority('system:log:query:all')")
|
||||
fun get(@Valid sysLogGetParam: SysLogGetParam?): ResponseResult<PageVo<SysLogVo>> {
|
||||
return ResponseResult.success(
|
||||
ResponseCode.DATABASE_SELECT_SUCCESS, data = sysLogService.getPage(sysLogGetParam)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package top.fatweb.oxygen.api.converter.permission
|
||||
|
||||
import top.fatweb.oxygen.api.entity.permission.Func
|
||||
import top.fatweb.oxygen.api.vo.permission.base.FuncVo
|
||||
|
||||
/**
|
||||
* Function converter
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
object FuncConverter {
|
||||
/**
|
||||
* Convert Func object into FuncVo object
|
||||
*
|
||||
* @param func Func object
|
||||
* @return FuncVo object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Func
|
||||
* @see FuncVo
|
||||
*/
|
||||
fun funcToFuncVo(func: Func) = FuncVo(
|
||||
id = func.id,
|
||||
name = func.name,
|
||||
parentId = func.parentId,
|
||||
menuId = func.menuId
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
package top.fatweb.oxygen.api.converter.permission
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage
|
||||
import top.fatweb.oxygen.api.entity.permission.Group
|
||||
import top.fatweb.oxygen.api.entity.permission.Role
|
||||
import top.fatweb.oxygen.api.param.permission.group.GroupAddParam
|
||||
import top.fatweb.oxygen.api.param.permission.group.GroupUpdateParam
|
||||
import top.fatweb.oxygen.api.param.permission.group.GroupUpdateStatusParam
|
||||
import top.fatweb.oxygen.api.vo.PageVo
|
||||
import top.fatweb.oxygen.api.vo.permission.GroupWithRoleVo
|
||||
import top.fatweb.oxygen.api.vo.permission.base.GroupVo
|
||||
|
||||
/**
|
||||
* Group converter
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
object GroupConverter {
|
||||
/**
|
||||
* Convert Group object into GroupVo object
|
||||
*
|
||||
* @param group Group object
|
||||
* @return GroupVo object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Group
|
||||
* @see GroupVo
|
||||
*/
|
||||
fun groupToGroupVo(group: Group) = GroupVo(
|
||||
id = group.id,
|
||||
name = group.name,
|
||||
enable = group.enable == 1,
|
||||
createTime = group.createTime,
|
||||
updateTime = group.updateTime
|
||||
)
|
||||
|
||||
/**
|
||||
* Convert Group object into GroupWithRoleVo object
|
||||
*
|
||||
* @param group Group object
|
||||
* @return GroupWithRoleVo object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Group
|
||||
* @see GroupWithRoleVo
|
||||
*/
|
||||
fun groupToGroupWithRoleVo(group: Group) = GroupWithRoleVo(
|
||||
id = group.id,
|
||||
name = group.name,
|
||||
enable = group.enable == 1,
|
||||
createTime = group.createTime,
|
||||
updateTime = group.updateTime,
|
||||
roles = group.roles?.map { RoleConverter.roleToRoleVo(it) }
|
||||
)
|
||||
|
||||
/**
|
||||
* Convert IPage<Group> object into PageVo<GroupWithRoleVo> object
|
||||
*
|
||||
* @param groupPage IPage<Group> object
|
||||
* @return PageVo<GroupWithRoleVo> object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see IPage
|
||||
* @see Group
|
||||
* @see PageVo
|
||||
* @see GroupWithRoleVo
|
||||
*/
|
||||
fun groupPageToGroupWithRolePageVo(groupPage: IPage<Group>) = PageVo(
|
||||
total = groupPage.total,
|
||||
pages = groupPage.pages,
|
||||
size = groupPage.size,
|
||||
current = groupPage.current,
|
||||
records = groupPage.records.map {
|
||||
groupToGroupWithRoleVo(it)
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Convert GroupAddParam object into Group object
|
||||
*
|
||||
* @param groupAddParam GroupAddParam object
|
||||
* @return Group object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see GroupAddParam
|
||||
* @see Group
|
||||
*/
|
||||
fun groupAddParamToGroup(groupAddParam: GroupAddParam) = Group().apply {
|
||||
name = groupAddParam.name
|
||||
enable = if (groupAddParam.enable) 1 else 0
|
||||
roles = groupAddParam.roleIds?.map { Role().apply { id = it } }
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert GroupUpdateParam object into Group object
|
||||
*
|
||||
* @param groupUpdateParam GroupUpdateParam object
|
||||
* @return Group object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see GroupUpdateParam
|
||||
* @see Group
|
||||
*/
|
||||
fun groupUpdateParamToGroup(groupUpdateParam: GroupUpdateParam) = Group().apply {
|
||||
id = groupUpdateParam.id
|
||||
name = groupUpdateParam.name
|
||||
enable = if (groupUpdateParam.enable) 1 else 0
|
||||
roles = groupUpdateParam.roleIds?.map { Role().apply { id = it } }
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert GroupUpdateStatusParam object into Group object
|
||||
*
|
||||
* @param groupUpdateStatusParam GroupUpdateStatusParam object
|
||||
* @return Group object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see GroupUpdateStatusParam
|
||||
* @see Group
|
||||
*/
|
||||
fun groupUpdateStatusParamToGroup(groupUpdateStatusParam: GroupUpdateStatusParam) = Group().apply {
|
||||
id = groupUpdateStatusParam.id
|
||||
enable = if (groupUpdateStatusParam.enable) 1 else 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package top.fatweb.oxygen.api.converter.permission
|
||||
|
||||
import top.fatweb.oxygen.api.entity.permission.Menu
|
||||
import top.fatweb.oxygen.api.vo.permission.base.MenuVo
|
||||
|
||||
/**
|
||||
* Menu converter
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
object MenuConverter {
|
||||
/**
|
||||
* Convert Menu object into MenuVo object
|
||||
*
|
||||
* @param menu Menu object
|
||||
* @return MenuVo object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Menu
|
||||
* @see MenuVo
|
||||
*/
|
||||
fun menuToMenuVo(menu: Menu) = MenuVo(
|
||||
id = menu.id,
|
||||
name = menu.name,
|
||||
url = menu.url,
|
||||
parentId = menu.parentId,
|
||||
moduleId = menu.moduleId
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package top.fatweb.oxygen.api.converter.permission
|
||||
|
||||
import top.fatweb.oxygen.api.entity.permission.Module
|
||||
import top.fatweb.oxygen.api.vo.permission.base.ModuleVo
|
||||
|
||||
/**
|
||||
* Module converter
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
object ModuleConverter {
|
||||
/**
|
||||
* Convert Module object into ModuleVo object
|
||||
*
|
||||
* @param module Module object
|
||||
* @return ModuleVo object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Module
|
||||
* @see ModuleVo
|
||||
*/
|
||||
fun moduleToModuleVo(module: Module) = ModuleVo(
|
||||
id = module.id,
|
||||
name = module.name
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package top.fatweb.oxygen.api.converter.permission
|
||||
|
||||
import top.fatweb.oxygen.api.entity.permission.Operation
|
||||
import top.fatweb.oxygen.api.vo.permission.base.OperationVo
|
||||
|
||||
/**
|
||||
* Operation converter
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
object OperationConverter {
|
||||
/**
|
||||
* Convert Operation object into OperationVo object
|
||||
*
|
||||
* @param operation Operation object
|
||||
* @return OperationVo object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Operation
|
||||
* @see OperationVo
|
||||
*/
|
||||
fun operationToOperationVo(operation: Operation) = OperationVo(
|
||||
id = operation.id,
|
||||
name = operation.name,
|
||||
code = operation.code,
|
||||
funcId = operation.funcId
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package top.fatweb.oxygen.api.converter.permission
|
||||
|
||||
import top.fatweb.oxygen.api.entity.permission.PowerSet
|
||||
import top.fatweb.oxygen.api.vo.permission.PowerSetVo
|
||||
|
||||
/**
|
||||
* Power converter
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
object PowerConverter {
|
||||
/**
|
||||
* Convert PowerSet object into PowerSetVo object
|
||||
*
|
||||
* @param powerSet PowerSet object
|
||||
* @return PowerSetVo object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see PowerSet
|
||||
* @see PowerSetVo
|
||||
*/
|
||||
fun powerSetToPowerSetVo(powerSet: PowerSet) = PowerSetVo(
|
||||
moduleList = powerSet.moduleList?.map { ModuleConverter.moduleToModuleVo(it) },
|
||||
menuList = powerSet.menuList?.map { MenuConverter.menuToMenuVo(it) },
|
||||
funcList = powerSet.funcList?.map { FuncConverter.funcToFuncVo(it) },
|
||||
operationList = powerSet.operationList?.map { OperationConverter.operationToOperationVo(it) }
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
package top.fatweb.oxygen.api.converter.permission
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage
|
||||
import top.fatweb.oxygen.api.entity.permission.Power
|
||||
import top.fatweb.oxygen.api.entity.permission.Role
|
||||
import top.fatweb.oxygen.api.param.permission.role.RoleAddParam
|
||||
import top.fatweb.oxygen.api.param.permission.role.RoleUpdateParam
|
||||
import top.fatweb.oxygen.api.param.permission.role.RoleUpdateStatusParam
|
||||
import top.fatweb.oxygen.api.vo.PageVo
|
||||
import top.fatweb.oxygen.api.vo.permission.RoleWithPowerVo
|
||||
import top.fatweb.oxygen.api.vo.permission.base.RoleVo
|
||||
|
||||
/**
|
||||
* Role converter
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
object RoleConverter {
|
||||
/**
|
||||
* Convert Role object into RoleVo object
|
||||
*
|
||||
* @param role Role object
|
||||
* @return RoleVo object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Role
|
||||
* @see RoleVo
|
||||
*/
|
||||
fun roleToRoleVo(role: Role) = RoleVo(
|
||||
id = role.id,
|
||||
name = role.name,
|
||||
enable = role.enable == 1,
|
||||
createTime = role.createTime,
|
||||
updateTime = role.updateTime
|
||||
)
|
||||
|
||||
/**
|
||||
* Convert Role object into RoleWithPowerVo object
|
||||
*
|
||||
* @param role Role object
|
||||
* @return RoleWithPowerVo object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Role
|
||||
* @see RoleWithPowerVo
|
||||
*/
|
||||
fun roleToRoleWithPowerVo(role: Role) = RoleWithPowerVo(
|
||||
id = role.id,
|
||||
name = role.name,
|
||||
enable = role.enable == 1,
|
||||
createTime = role.createTime,
|
||||
updateTime = role.updateTime,
|
||||
modules = role.modules?.map { ModuleConverter.moduleToModuleVo(it) },
|
||||
menus = role.menus?.map { MenuConverter.menuToMenuVo(it) },
|
||||
funcs = role.funcs?.map { FuncConverter.funcToFuncVo(it) },
|
||||
operations = role.operations?.map { OperationConverter.operationToOperationVo(it) }
|
||||
)
|
||||
|
||||
/**
|
||||
* Convert IPage<Role> object into PageVo object
|
||||
*
|
||||
* @param rolePage IPage<Role> object
|
||||
* @return PageVo<RoleWithPowerVo> object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see IPage
|
||||
* @see Role
|
||||
* @see PageVo
|
||||
* @see RoleWithPowerVo
|
||||
*/
|
||||
fun rolePageToRoleWithPowerPageVo(rolePage: IPage<Role>) = PageVo(
|
||||
total = rolePage.total,
|
||||
pages = rolePage.pages,
|
||||
size = rolePage.size,
|
||||
current = rolePage.current,
|
||||
records = rolePage.records.map {
|
||||
roleToRoleWithPowerVo(it)
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Convert RoleAddParam object into Role object
|
||||
*
|
||||
* @param roleAddParam RoleAddParam object
|
||||
* @return Role object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see RoleAddParam
|
||||
* @see Role
|
||||
*/
|
||||
fun roleAddParamToRole(roleAddParam: RoleAddParam) = Role().apply {
|
||||
name = roleAddParam.name
|
||||
enable = if (roleAddParam.enable) 1 else 0
|
||||
powers = roleAddParam.powerIds?.map { Power().apply { id = it } }
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert RoleUpdateParam into Role object
|
||||
*
|
||||
* @param roleUpdateParam RoleUpdateParam object
|
||||
* @return Role object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see RoleUpdateParam
|
||||
* @see Role
|
||||
*/
|
||||
fun roleUpdateParamToRole(roleUpdateParam: RoleUpdateParam) = Role().apply {
|
||||
id = roleUpdateParam.id
|
||||
name = roleUpdateParam.name
|
||||
enable = if (roleUpdateParam.enable) 1 else 0
|
||||
powers = roleUpdateParam.powerIds?.map { Power().apply { id = it } }
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert RoleUpdateStatusParam object into Role object
|
||||
*
|
||||
* @param roleUpdateStatusParam RoleUpdateStatusParam object
|
||||
* @return Role object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see RoleUpdateStatusParam
|
||||
* @see Role
|
||||
*/
|
||||
fun roleUpdateStatusParamToRole(roleUpdateStatusParam: RoleUpdateStatusParam) = Role().apply {
|
||||
id = roleUpdateStatusParam.id
|
||||
enable = if (roleUpdateStatusParam.enable) 1 else 0
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
package top.fatweb.oxygen.api.converter.permission
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage
|
||||
import top.fatweb.avatargenerator.GitHubAvatar
|
||||
import top.fatweb.oxygen.api.entity.permission.Group
|
||||
import top.fatweb.oxygen.api.entity.permission.Role
|
||||
import top.fatweb.oxygen.api.entity.permission.User
|
||||
import top.fatweb.oxygen.api.entity.permission.UserInfo
|
||||
import top.fatweb.oxygen.api.param.permission.user.UserAddParam
|
||||
import top.fatweb.oxygen.api.param.permission.user.UserUpdateParam
|
||||
import top.fatweb.oxygen.api.vo.PageVo
|
||||
import top.fatweb.oxygen.api.vo.permission.UserWithInfoVo
|
||||
import top.fatweb.oxygen.api.vo.permission.UserWithPasswordRoleInfoVo
|
||||
import top.fatweb.oxygen.api.vo.permission.UserWithPowerInfoVo
|
||||
import top.fatweb.oxygen.api.vo.permission.UserWithRoleInfoVo
|
||||
|
||||
/**
|
||||
* User converter
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
object UserConverter {
|
||||
/**
|
||||
* Convert User object into UserWithPowerInfoVo object
|
||||
*
|
||||
* @param user User object
|
||||
* @return UserWithPowerInfoVo object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see User
|
||||
* @see UserWithPowerInfoVo
|
||||
*/
|
||||
fun userToUserWithPowerInfoVo(user: User) = UserWithPowerInfoVo(
|
||||
id = user.id,
|
||||
username = user.username,
|
||||
verified = user.verify.isNullOrBlank(),
|
||||
locking = user.locking?.let { it == 1 },
|
||||
expiration = user.expiration,
|
||||
credentialsExpiration = user.credentialsExpiration,
|
||||
enable = user.enable?.let { it == 1 },
|
||||
currentLoginTime = user.currentLoginTime,
|
||||
currentLoginIp = user.currentLoginIp,
|
||||
lastLoginTime = user.lastLoginTime,
|
||||
lastLoginIp = user.lastLoginIp,
|
||||
createTime = user.createTime,
|
||||
updateTime = user.updateTime,
|
||||
userInfo = user.userInfo?.let {
|
||||
UserInfoConverter.userInfoToUserInfoVo(it)
|
||||
},
|
||||
modules = user.modules?.map {
|
||||
ModuleConverter.moduleToModuleVo(it)
|
||||
},
|
||||
menus = user.menus?.map {
|
||||
MenuConverter.menuToMenuVo(it)
|
||||
},
|
||||
funcs = user.funcs?.map {
|
||||
FuncConverter.funcToFuncVo(it)
|
||||
},
|
||||
operations = user.operations?.map {
|
||||
OperationConverter.operationToOperationVo(it)
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Convert User object into UserWithRoleInfoVo object
|
||||
*
|
||||
* @param user User object
|
||||
* @return UserWithRoleInfoVo object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see User
|
||||
* @see UserWithRoleInfoVo
|
||||
*/
|
||||
fun userToUserWithRoleInfoVo(user: User) = UserWithRoleInfoVo(
|
||||
id = user.id,
|
||||
username = user.username,
|
||||
verify = user.verify,
|
||||
locking = user.locking?.let { it == 1 },
|
||||
expiration = user.expiration,
|
||||
credentialsExpiration = user.credentialsExpiration,
|
||||
enable = user.enable?.let { it == 1 },
|
||||
currentLoginTime = user.currentLoginTime,
|
||||
currentLoginIp = user.currentLoginIp,
|
||||
lastLoginTime = user.lastLoginTime,
|
||||
lastLoginIp = user.lastLoginIp,
|
||||
createTime = user.createTime,
|
||||
updateTime = user.updateTime,
|
||||
userInfo = user.userInfo?.let {
|
||||
UserInfoConverter.userInfoToUserInfoVo(it)
|
||||
},
|
||||
roles = user.roles?.map {
|
||||
RoleConverter.roleToRoleVo(it)
|
||||
},
|
||||
groups = user.groups?.map {
|
||||
GroupConverter.groupToGroupVo(it)
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Convert User object into UserWithInfoVo object
|
||||
*
|
||||
* @param user User object
|
||||
* @return UserWithInfoVo object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see User
|
||||
* @see UserWithInfoVo
|
||||
*/
|
||||
fun userToUserWithInfoVo(user: User) = UserWithInfoVo(
|
||||
id = user.id,
|
||||
username = user.username,
|
||||
verified = user.verify.isNullOrBlank(),
|
||||
locking = user.locking?.let { it == 1 },
|
||||
expiration = user.expiration,
|
||||
credentialsExpiration = user.credentialsExpiration,
|
||||
enable = user.enable?.let { it == 1 },
|
||||
currentLoginTime = user.currentLoginTime,
|
||||
currentLoginIp = user.currentLoginIp,
|
||||
lastLoginTime = user.lastLoginTime,
|
||||
lastLoginIp = user.lastLoginIp,
|
||||
createTime = user.createTime,
|
||||
updateTime = user.updateTime,
|
||||
userInfo = user.userInfo?.let {
|
||||
UserInfoConverter.userInfoToUserInfoVo(it)
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Convert User object into UserWithPasswordRoleInfoVo object
|
||||
*
|
||||
* @param user User object
|
||||
* @return UserWithPasswordRoleInfoVo object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see User
|
||||
* @see UserWithPasswordRoleInfoVo
|
||||
*/
|
||||
fun userToUserWithPasswordRoleInfoVo(user: User) = UserWithPasswordRoleInfoVo(
|
||||
id = user.id,
|
||||
username = user.username,
|
||||
password = user.password,
|
||||
verify = user.verify,
|
||||
locking = user.locking?.let { it == 1 },
|
||||
expiration = user.expiration,
|
||||
credentialsExpiration = user.credentialsExpiration,
|
||||
enable = user.enable?.let { it == 1 },
|
||||
currentLoginTime = user.currentLoginTime,
|
||||
currentLoginIp = user.currentLoginIp,
|
||||
lastLoginTime = user.lastLoginTime,
|
||||
lastLoginIp = user.lastLoginIp,
|
||||
createTime = user.createTime,
|
||||
updateTime = user.updateTime,
|
||||
userInfo = user.userInfo?.let {
|
||||
UserInfoConverter.userInfoToUserInfoVo(it)
|
||||
},
|
||||
roles = user.roles?.map {
|
||||
RoleConverter.roleToRoleVo(it)
|
||||
},
|
||||
groups = user.groups?.map {
|
||||
GroupConverter.groupToGroupVo(it)
|
||||
}
|
||||
)
|
||||
|
||||
/**
|
||||
* Convert UserAddParam object into User object
|
||||
*
|
||||
* @param userAddParam UserAddParam object
|
||||
* @return User object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see UserAddParam
|
||||
* @see User
|
||||
*/
|
||||
fun userAddParamToUser(userAddParam: UserAddParam) = User().apply {
|
||||
username = userAddParam.username
|
||||
password = userAddParam.password
|
||||
locking = if (userAddParam.locking) 1 else 0
|
||||
expiration = userAddParam.expiration
|
||||
credentialsExpiration = userAddParam.credentialsExpiration
|
||||
enable = if (userAddParam.enable) 1 else 0
|
||||
userInfo = UserInfo().apply {
|
||||
nickname = userAddParam.nickname ?: userAddParam.username
|
||||
avatar = userAddParam.avatar ?: GitHubAvatar.newAvatarBuilder().build()
|
||||
.createAsBase64((Long.MIN_VALUE..Long.MAX_VALUE).random())
|
||||
email = userAddParam.email
|
||||
}
|
||||
roles = userAddParam.roleIds?.map { Role().apply { id = it } }
|
||||
groups = userAddParam.groupIds?.map { Group().apply { id = it } }
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert UserUpdateParam object into User object
|
||||
*
|
||||
* @param userUpdateParam UserUpdateParam object
|
||||
* @return User object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see UserUpdateParam
|
||||
* @see User
|
||||
*/
|
||||
fun userUpdateParamToUser(userUpdateParam: UserUpdateParam) = User().apply {
|
||||
id = userUpdateParam.id
|
||||
username = userUpdateParam.username
|
||||
locking = if (userUpdateParam.locking && userUpdateParam.id != 0L) 1 else 0
|
||||
expiration = if (userUpdateParam.id != 0L) userUpdateParam.expiration else null
|
||||
credentialsExpiration = userUpdateParam.credentialsExpiration
|
||||
enable = if (userUpdateParam.enable || userUpdateParam.id == 0L) 1 else 0
|
||||
userInfo = UserInfo().apply {
|
||||
nickname = userUpdateParam.nickname
|
||||
avatar = userUpdateParam.avatar
|
||||
email = userUpdateParam.email
|
||||
}
|
||||
roles = if (userUpdateParam.id != 0L) userUpdateParam.roleIds?.map { Role().apply { id = it } } else null
|
||||
groups = if (userUpdateParam.id != 0L) userUpdateParam.groupIds?.map { Group().apply { id = it } } else null
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert IPage<User> object into PageVo<UserWithRoleInfoVo> object
|
||||
*
|
||||
* @param userPage IPage<User> object
|
||||
* @return PageVo<UserWithRoleInfoVo> object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see IPage
|
||||
* @see User
|
||||
* @see PageVo
|
||||
* @see UserWithRoleInfoVo
|
||||
*/
|
||||
fun userPageToUserWithRoleInfoPageVo(userPage: IPage<User>) = PageVo(
|
||||
total = userPage.total,
|
||||
pages = userPage.pages,
|
||||
size = userPage.size,
|
||||
current = userPage.current,
|
||||
records = userPage.records.map {
|
||||
userToUserWithRoleInfoVo(it)
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package top.fatweb.oxygen.api.converter.permission
|
||||
|
||||
import top.fatweb.oxygen.api.entity.permission.UserInfo
|
||||
import top.fatweb.oxygen.api.vo.permission.base.UserInfoVo
|
||||
|
||||
/**
|
||||
* User information converter
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
object UserInfoConverter {
|
||||
/**
|
||||
* Convert UserInfo object into UserInfoVo object
|
||||
*
|
||||
* @param userInfo UserInfo object
|
||||
* @return UserInfoVo object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see UserInfo
|
||||
* @see UserInfoVo
|
||||
*/
|
||||
fun userInfoToUserInfoVo(userInfo: UserInfo) = UserInfoVo(
|
||||
id = userInfo.id,
|
||||
userId = userInfo.userId,
|
||||
nickname = userInfo.nickname,
|
||||
avatar = userInfo.avatar,
|
||||
email = userInfo.email,
|
||||
createTime = userInfo.createTime,
|
||||
updateTime = userInfo.updateTime
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package top.fatweb.oxygen.api.converter.system
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage
|
||||
import top.fatweb.oxygen.api.entity.system.SysLog
|
||||
import top.fatweb.oxygen.api.vo.PageVo
|
||||
import top.fatweb.oxygen.api.vo.system.SysLogVo
|
||||
|
||||
/**
|
||||
* System log converter
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
object SysLogConverter {
|
||||
/**
|
||||
* Convert IPage<SysLog> object into PageVo<SysLogVo> object
|
||||
*
|
||||
* @param syslogPage IPage<Syslog> object
|
||||
* @return PageVo<SysLogVo> object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see IPage
|
||||
* @see SysLog
|
||||
* @see PageVo
|
||||
* @see SysLogVo
|
||||
*/
|
||||
fun sysLogPageToSysLogPageVo(syslogPage: IPage<SysLog>) = PageVo(
|
||||
syslogPage.total,
|
||||
syslogPage.pages,
|
||||
syslogPage.size,
|
||||
syslogPage.current,
|
||||
syslogPage.records.map {
|
||||
SysLogVo(
|
||||
id = it.id,
|
||||
logType = it.logType,
|
||||
operateUserId = it.operateUserId,
|
||||
operateTime = it.operateTime,
|
||||
requestUri = it.requestUri,
|
||||
requestMethod = it.requestMethod,
|
||||
requestParams = it.requestParams,
|
||||
requestIp = it.requestIp,
|
||||
requestServerAddress = it.requestServerAddress,
|
||||
exception = it.exception == 1,
|
||||
exceptionInfo = it.exceptionInfo,
|
||||
startTime = it.startTime,
|
||||
endTime = it.endTime,
|
||||
executeTime = it.executeTime,
|
||||
userAgent = it.userAgent,
|
||||
operateUsername = it.operateUsername
|
||||
)
|
||||
})
|
||||
|
||||
}
|
||||
35
src/main/kotlin/top/fatweb/oxygen/api/cron/StatisticsCron.kt
Normal file
35
src/main/kotlin/top/fatweb/oxygen/api/cron/StatisticsCron.kt
Normal file
@@ -0,0 +1,35 @@
|
||||
package top.fatweb.oxygen.api.cron
|
||||
|
||||
import org.springframework.scheduling.annotation.Scheduled
|
||||
import org.springframework.stereotype.Component
|
||||
import top.fatweb.oxygen.api.entity.system.StatisticsLog
|
||||
import top.fatweb.oxygen.api.properties.SecurityProperties
|
||||
import top.fatweb.oxygen.api.service.system.IStatisticsLogService
|
||||
import top.fatweb.oxygen.api.util.RedisUtil
|
||||
|
||||
/**
|
||||
* Statistics scheduled tasks
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Component
|
||||
class StatisticsCron(
|
||||
private val redisUtil: RedisUtil,
|
||||
private val statisticsLogService: IStatisticsLogService
|
||||
) {
|
||||
/**
|
||||
* Auto record number of online users
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Scheduled(cron = "0 * * * * *")
|
||||
fun onlineUserCount() {
|
||||
statisticsLogService.save(StatisticsLog().apply {
|
||||
key = StatisticsLog.KeyItem.ONLINE_USERS_COUNT
|
||||
value = redisUtil.keys("${SecurityProperties.jwtIssuer}_login_*")
|
||||
.distinctBy { Regex("${SecurityProperties.jwtIssuer}_login_(.*):.*").matchEntire(it)?.groupValues?.getOrNull(1) }.size.toString()
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package top.fatweb.oxygen.api.entity.common
|
||||
|
||||
/**
|
||||
* Business code entity
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
enum class BusinessCode(val code: Int) {
|
||||
/**
|
||||
* System
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
SYSTEM(100),
|
||||
|
||||
/**
|
||||
* Permission
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
PERMISSION(200),
|
||||
|
||||
/**
|
||||
* Database
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
DATABASE(300),
|
||||
|
||||
/**
|
||||
* Avatar API
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
API_AVATAR(501)
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package top.fatweb.oxygen.api.entity.common
|
||||
|
||||
/**
|
||||
* Response code entity
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
enum class ResponseCode(val code: Int) {
|
||||
SYSTEM_OK(BusinessCode.SYSTEM, 0),
|
||||
|
||||
SYSTEM_ERROR(BusinessCode.SYSTEM, 50),
|
||||
SYSTEM_TIMEOUT(BusinessCode.SYSTEM, 51),
|
||||
SYSTEM_REQUEST_ILLEGAL(BusinessCode.SYSTEM, 52),
|
||||
SYSTEM_ARGUMENT_NOT_VALID(BusinessCode.SYSTEM, 53),
|
||||
|
||||
PERMISSION_LOGIN_SUCCESS(BusinessCode.PERMISSION, 0),
|
||||
PERMISSION_PASSWORD_CHANGE_SUCCESS(BusinessCode.PERMISSION, 1),
|
||||
PERMISSION_LOGOUT_SUCCESS(BusinessCode.PERMISSION, 2),
|
||||
PERMISSION_TOKEN_RENEW_SUCCESS(BusinessCode.PERMISSION, 3),
|
||||
PERMISSION_REGISTER_SUCCESS(BusinessCode.PERMISSION, 4),
|
||||
PERMISSION_RESEND_SUCCESS(BusinessCode.PERMISSION, 5),
|
||||
PERMISSION_VERIFY_SUCCESS(BusinessCode.PERMISSION, 6),
|
||||
PERMISSION_FORGET_SUCCESS(BusinessCode.PERMISSION, 7),
|
||||
PERMISSION_RETRIEVE_SUCCESS(BusinessCode.PERMISSION, 8),
|
||||
|
||||
PERMISSION_UNAUTHORIZED(BusinessCode.PERMISSION, 50),
|
||||
PERMISSION_USERNAME_NOT_FOUND(BusinessCode.PERMISSION, 51),
|
||||
PERMISSION_ACCESS_DENIED(BusinessCode.PERMISSION, 52),
|
||||
PERMISSION_USER_LOCKED(BusinessCode.PERMISSION, 53),
|
||||
PERMISSION_USER_EXPIRED(BusinessCode.PERMISSION, 54),
|
||||
PERMISSION_USER_CREDENTIALS_EXPIRED(BusinessCode.PERMISSION, 55),
|
||||
PERMISSION_USER_DISABLE(BusinessCode.PERMISSION, 56),
|
||||
PERMISSION_LOGIN_USERNAME_PASSWORD_ERROR(BusinessCode.PERMISSION, 57),
|
||||
PERMISSION_OLD_PASSWORD_NOT_MATCH(BusinessCode.PERMISSION, 58),
|
||||
PERMISSION_LOGOUT_FAILED(BusinessCode.PERMISSION, 59),
|
||||
PERMISSION_TOKEN_ILLEGAL(BusinessCode.PERMISSION, 60),
|
||||
PERMISSION_TOKEN_HAS_EXPIRED(BusinessCode.PERMISSION, 61),
|
||||
PERMISSION_NO_VERIFICATION_REQUIRED(BusinessCode.PERMISSION, 62),
|
||||
PERMISSION_VERIFY_CODE_ERROR_OR_EXPIRED(BusinessCode.PERMISSION, 63),
|
||||
PERMISSION_ACCOUNT_NEED_INIT(BusinessCode.PERMISSION, 64),
|
||||
PERMISSION_USER_NOT_FOUND(BusinessCode.PERMISSION, 65),
|
||||
PERMISSION_RETRIEVE_CODE_ERROR_OR_EXPIRED(BusinessCode.PERMISSION, 66),
|
||||
PERMISSION_ACCOUNT_NEED_RESET_PASSWORD(BusinessCode.PERMISSION, 67),
|
||||
|
||||
DATABASE_SELECT_SUCCESS(BusinessCode.DATABASE, 0),
|
||||
DATABASE_SELECT_FAILED(BusinessCode.DATABASE, 5),
|
||||
DATABASE_INSERT_SUCCESS(BusinessCode.DATABASE, 10),
|
||||
DATABASE_INSERT_FAILED(BusinessCode.DATABASE, 15),
|
||||
DATABASE_UPDATE_SUCCESS(BusinessCode.DATABASE, 20),
|
||||
DATABASE_UPDATE_FILED(BusinessCode.DATABASE, 25),
|
||||
DATABASE_DELETE_SUCCESS(BusinessCode.DATABASE, 30),
|
||||
DATABASE_DELETE_FILED(BusinessCode.DATABASE, 35),
|
||||
DATABASE_EXECUTE_ERROR(BusinessCode.DATABASE, 50),
|
||||
DATABASE_DUPLICATE_KEY(BusinessCode.DATABASE, 51),
|
||||
DATABASE_NO_RECORD_FOUND(BusinessCode.DATABASE, 52),
|
||||
|
||||
API_AVATAR_SUCCESS(BusinessCode.API_AVATAR, 0),
|
||||
API_AVATAR_ERROR(BusinessCode.API_AVATAR, 50);
|
||||
|
||||
constructor(businessCode: BusinessCode, code: Int) : this(businessCode.code * 100 + code)
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package top.fatweb.oxygen.api.entity.common
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema
|
||||
import java.io.Serializable
|
||||
|
||||
/**
|
||||
* Response result entity
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class ResponseResult<T> private constructor(
|
||||
@Schema(description = "响应码", defaultValue = "200") val code: Int,
|
||||
|
||||
@Schema(description = "是否调用成功") val success: Boolean,
|
||||
|
||||
@Schema(description = "信息") val msg: String,
|
||||
|
||||
@Schema(description = "数据") val data: T?
|
||||
) : Serializable {
|
||||
companion object {
|
||||
/**
|
||||
* Build response result object
|
||||
*
|
||||
* @param code Response code
|
||||
* @param success Is successful
|
||||
* @param msg Response message
|
||||
* @param data Response data
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
fun <T> build(code: Int, success: Boolean, msg: String, data: T?) =
|
||||
ResponseResult(code, success, msg, data)
|
||||
|
||||
/**
|
||||
* Build response result object
|
||||
*
|
||||
* @param code Response code object
|
||||
* @param success Is successful
|
||||
* @param msg Response message
|
||||
* @param data Response data
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see ResponseCode
|
||||
*/
|
||||
fun <T> build(code: ResponseCode, success: Boolean, msg: String, data: T?) =
|
||||
build(code.code, success, msg, data)
|
||||
|
||||
/**
|
||||
* Build successful response result object
|
||||
*
|
||||
* @param code Response code object
|
||||
* @param msg Response message
|
||||
* @param data Response data
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see ResponseCode
|
||||
*/
|
||||
fun <T> success(code: ResponseCode = ResponseCode.SYSTEM_OK, msg: String = "success", data: T? = null) =
|
||||
build(code, true, msg, data)
|
||||
|
||||
/**
|
||||
* Build failure response result object
|
||||
*
|
||||
* @param code Response code object
|
||||
* @param msg Response message
|
||||
* @param data Response data
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see ResponseCode
|
||||
*/
|
||||
fun <T> fail(code: ResponseCode = ResponseCode.SYSTEM_ERROR, msg: String = "fail", data: T? = null) =
|
||||
build(code, false, msg, data)
|
||||
|
||||
/**
|
||||
* Build database successful response result object
|
||||
*
|
||||
* @param code Response code object
|
||||
* @param msg Response message
|
||||
* @param data Response data
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see ResponseCode
|
||||
*/
|
||||
fun <T> databaseSuccess(
|
||||
code: ResponseCode = ResponseCode.DATABASE_SELECT_SUCCESS, msg: String = "success", data: T? = null
|
||||
) = build(code, true, msg, data)
|
||||
|
||||
/**
|
||||
* Build database failure response result object
|
||||
*
|
||||
* @param code Response code object
|
||||
* @param msg Response message
|
||||
* @param data Response data
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see ResponseCode
|
||||
*/
|
||||
fun <T> databaseFail(
|
||||
code: ResponseCode = ResponseCode.DATABASE_SELECT_FAILED, msg: String = "fail", data: T? = null
|
||||
) = build(code, false, msg, data)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package top.fatweb.oxygen.api.entity.permission
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField
|
||||
import com.baomidou.mybatisplus.annotation.TableId
|
||||
import com.baomidou.mybatisplus.annotation.TableName
|
||||
import java.io.Serializable
|
||||
|
||||
/**
|
||||
* Function entity
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableName("t_func")
|
||||
class Func : Serializable {
|
||||
/**
|
||||
* ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableId("id")
|
||||
var id: Long? = null
|
||||
|
||||
/**
|
||||
* Name
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("name")
|
||||
var name: String? = null
|
||||
|
||||
/**
|
||||
* Parent ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("parent_id")
|
||||
var parentId: Long? = null
|
||||
|
||||
/**
|
||||
* Menu ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("menu_id")
|
||||
var menuId: Long? = null
|
||||
|
||||
override fun toString(): String {
|
||||
return "Func(id=$id, name=$name, parentId=$parentId, menuId=$menuId)"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package top.fatweb.oxygen.api.entity.permission
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDateTime
|
||||
|
||||
/**
|
||||
* Group entity
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableName("t_group")
|
||||
class Group : Serializable {
|
||||
/**
|
||||
* ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableId("id")
|
||||
var id: Long? = null
|
||||
|
||||
/**
|
||||
* Name
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("name")
|
||||
var name: String? = null
|
||||
|
||||
/**
|
||||
* Enable
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("enable")
|
||||
var enable: Int? = null
|
||||
|
||||
/**
|
||||
* Create time
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see LocalDateTime
|
||||
*/
|
||||
@TableField("create_time", fill = FieldFill.INSERT)
|
||||
var createTime: LocalDateTime? = null
|
||||
|
||||
/**
|
||||
* Update time
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see LocalDateTime
|
||||
*/
|
||||
@TableField("update_time", fill = FieldFill.INSERT_UPDATE)
|
||||
var updateTime: LocalDateTime? = null
|
||||
|
||||
/**
|
||||
* Deleted
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("deleted")
|
||||
@TableLogic
|
||||
var deleted: Long? = null
|
||||
|
||||
/**
|
||||
* Version
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("version")
|
||||
@Version
|
||||
var version: Int? = null
|
||||
|
||||
/**
|
||||
* Role list
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Role
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
var roles: List<Role>? = null
|
||||
|
||||
override fun toString(): String {
|
||||
return "Group(id=$id, name=$name, enable=$enable, createTime=$createTime, updateTime=$updateTime, deleted=$deleted, version=$version, roles=$roles)"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package top.fatweb.oxygen.api.entity.permission
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo
|
||||
import org.springframework.security.core.GrantedAuthority
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority
|
||||
import org.springframework.security.core.userdetails.UserDetails
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneOffset
|
||||
|
||||
/**
|
||||
* Login user entity
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see UserDetails
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
|
||||
class LoginUser() : UserDetails {
|
||||
/**
|
||||
* User object
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see User
|
||||
*/
|
||||
lateinit var user: User
|
||||
|
||||
@JsonIgnore
|
||||
private var authorities: List<GrantedAuthority>? = null
|
||||
|
||||
constructor(user: User) : this() {
|
||||
this.user = user
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
override fun getAuthorities(): List<GrantedAuthority> {
|
||||
authorities?.let { return it }
|
||||
authorities = user.operations?.map { SimpleGrantedAuthority(it.code) } ?: emptyList()
|
||||
|
||||
return authorities as List<GrantedAuthority>
|
||||
}
|
||||
|
||||
@JsonIgnore
|
||||
override fun getPassword() = user.password
|
||||
|
||||
@JsonIgnore
|
||||
override fun getUsername() = user.username
|
||||
|
||||
@JsonIgnore
|
||||
override fun isAccountNonExpired() =
|
||||
user.expiration == null || user.expiration!!.isAfter(LocalDateTime.now(ZoneOffset.UTC))
|
||||
|
||||
@JsonIgnore
|
||||
override fun isAccountNonLocked() = user.locking == 0
|
||||
|
||||
@JsonIgnore
|
||||
override fun isCredentialsNonExpired() =
|
||||
user.credentialsExpiration == null || user.credentialsExpiration!!.isAfter(LocalDateTime.now(ZoneOffset.UTC))
|
||||
|
||||
@JsonIgnore
|
||||
override fun isEnabled() = user.enable == 1
|
||||
|
||||
override fun toString(): String {
|
||||
return "LoginUser(user=$user, authorities=$authorities)"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package top.fatweb.oxygen.api.entity.permission
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField
|
||||
import com.baomidou.mybatisplus.annotation.TableId
|
||||
import com.baomidou.mybatisplus.annotation.TableName
|
||||
import java.io.Serializable
|
||||
|
||||
/**
|
||||
* Menu entity
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableName("t_menu")
|
||||
class Menu : Serializable {
|
||||
/**
|
||||
* ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableId("id")
|
||||
var id: Long? = null
|
||||
|
||||
/**
|
||||
* Name
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("name")
|
||||
var name: String? = null
|
||||
|
||||
/**
|
||||
* URL
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("url")
|
||||
var url: String? = null
|
||||
|
||||
/**
|
||||
* Parent ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("parent_id")
|
||||
var parentId: Long? = null
|
||||
|
||||
/**
|
||||
* Module ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("module_id")
|
||||
var moduleId: Long? = null
|
||||
|
||||
override fun toString(): String {
|
||||
return "Menu(id=$id, name=$name, url=$url, parentId=$parentId, moduleId=$moduleId)"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package top.fatweb.oxygen.api.entity.permission
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField
|
||||
import com.baomidou.mybatisplus.annotation.TableId
|
||||
import com.baomidou.mybatisplus.annotation.TableName
|
||||
import java.io.Serializable
|
||||
|
||||
/**
|
||||
* Module Entity
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableName("t_module")
|
||||
class Module : Serializable {
|
||||
/**
|
||||
* ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableId("id")
|
||||
var id: Long? = null
|
||||
|
||||
/**
|
||||
* Name
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("name")
|
||||
var name: String? = null
|
||||
|
||||
override fun toString(): String {
|
||||
return "Module(id=$id, name=$name)"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package top.fatweb.oxygen.api.entity.permission
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField
|
||||
import com.baomidou.mybatisplus.annotation.TableId
|
||||
import com.baomidou.mybatisplus.annotation.TableName
|
||||
import java.io.Serializable
|
||||
|
||||
/**
|
||||
* Operation entity
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableName("t_operation")
|
||||
class Operation : Serializable {
|
||||
/**
|
||||
* ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableId("id")
|
||||
var id: Long? = null
|
||||
|
||||
/**
|
||||
* Name
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("name")
|
||||
var name: String? = null
|
||||
|
||||
/**
|
||||
* Code
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("code")
|
||||
var code: String? = null
|
||||
|
||||
/**
|
||||
* Function ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("func_id")
|
||||
var funcId: Long? = null
|
||||
|
||||
override fun toString(): String {
|
||||
return "Operation(id=$id, name=$name, code=$code, funcId=$funcId)"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package top.fatweb.oxygen.api.entity.permission
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField
|
||||
import com.baomidou.mybatisplus.annotation.TableId
|
||||
import com.baomidou.mybatisplus.annotation.TableName
|
||||
import java.io.Serializable
|
||||
|
||||
/**
|
||||
* Power entity
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableName("t_power")
|
||||
class Power : Serializable {
|
||||
/**
|
||||
* ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableId("id")
|
||||
var id: Long? = null
|
||||
|
||||
/**
|
||||
* Type ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("type_id")
|
||||
var typeId: Int? = null
|
||||
|
||||
override fun toString(): String {
|
||||
return "Power(id=$id, typeId=$typeId)"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package top.fatweb.oxygen.api.entity.permission
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*
|
||||
import java.io.Serializable
|
||||
|
||||
/**
|
||||
* Power role intermediate entity
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableName("t_power_role")
|
||||
class PowerRole : Serializable {
|
||||
/**
|
||||
* ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableId("id")
|
||||
var id: Long? = null
|
||||
|
||||
/**
|
||||
* Power ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("power_id")
|
||||
var powerId: Long? = null
|
||||
|
||||
/**
|
||||
* Role ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("role_id")
|
||||
var roleId: Long? = null
|
||||
|
||||
/**
|
||||
* Deleted
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("deleted")
|
||||
@TableLogic
|
||||
var deleted: Long? = null
|
||||
|
||||
/**
|
||||
* Version
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("version")
|
||||
@Version
|
||||
var version: Int? = null
|
||||
|
||||
override fun toString(): String {
|
||||
return "PowerRole(id=$id, powerId=$powerId, roleId=$roleId, deleted=$deleted, version=$version)"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package top.fatweb.oxygen.api.entity.permission
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
/**
|
||||
* Set of power entity
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class PowerSet : Serializable {
|
||||
/**
|
||||
* Module list
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Module
|
||||
*/
|
||||
var moduleList: List<Module>? = null
|
||||
|
||||
/**
|
||||
* Menu list
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Menu
|
||||
*/
|
||||
var menuList: List<Menu>? = null
|
||||
|
||||
/**
|
||||
* Function list
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Func
|
||||
*/
|
||||
var funcList: List<Func>? = null
|
||||
|
||||
/**
|
||||
* Operation list
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Operation
|
||||
*/
|
||||
var operationList: List<Operation>? = null
|
||||
|
||||
override fun toString(): String {
|
||||
return "PowerSet(moduleList=$moduleList, menuList=$menuList, funcList=$funcList, operationList=$operationList)"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package top.fatweb.oxygen.api.entity.permission
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField
|
||||
import com.baomidou.mybatisplus.annotation.TableId
|
||||
import com.baomidou.mybatisplus.annotation.TableName
|
||||
import java.io.Serializable
|
||||
|
||||
/**
|
||||
* Power type entity
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableName("t_power_type")
|
||||
class PowerType : Serializable {
|
||||
/**
|
||||
* ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableId("id")
|
||||
var id: Long? = null
|
||||
|
||||
/**
|
||||
* Name
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("name")
|
||||
var name: String? = null
|
||||
|
||||
override fun toString(): String {
|
||||
return "PowerType(id=$id, name=$name)"
|
||||
}
|
||||
}
|
||||
135
src/main/kotlin/top/fatweb/oxygen/api/entity/permission/Role.kt
Normal file
135
src/main/kotlin/top/fatweb/oxygen/api/entity/permission/Role.kt
Normal file
@@ -0,0 +1,135 @@
|
||||
package top.fatweb.oxygen.api.entity.permission
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDateTime
|
||||
|
||||
/**
|
||||
* Role entity
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableName("t_role")
|
||||
class Role : Serializable {
|
||||
/**
|
||||
* ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableId("id")
|
||||
var id: Long? = null
|
||||
|
||||
/**
|
||||
* Name
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("name")
|
||||
var name: String? = null
|
||||
|
||||
/**
|
||||
* Enable
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("enable")
|
||||
var enable: Int? = null
|
||||
|
||||
/**
|
||||
* Create time
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see LocalDateTime
|
||||
*/
|
||||
@TableField("create_time", fill = FieldFill.INSERT)
|
||||
var createTime: LocalDateTime? = null
|
||||
|
||||
/**
|
||||
* Update time
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see LocalDateTime
|
||||
*/
|
||||
@TableField("update_time", fill = FieldFill.INSERT_UPDATE)
|
||||
var updateTime: LocalDateTime? = null
|
||||
|
||||
/**
|
||||
* Deleted
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("deleted")
|
||||
@TableLogic
|
||||
var deleted: Long? = null
|
||||
|
||||
/**
|
||||
* Version
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("version")
|
||||
@Version
|
||||
var version: Int? = null
|
||||
|
||||
/**
|
||||
* Module list
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Module
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
var modules: List<Module>? = null
|
||||
|
||||
/**
|
||||
* Menu list
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Menu
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
var menus: List<Menu>? = null
|
||||
|
||||
/**
|
||||
* Function list
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Func
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
var funcs: List<Func>? = null
|
||||
|
||||
/**
|
||||
* Operation list
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Operation
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
var operations: List<Operation>? = null
|
||||
|
||||
/**
|
||||
* Power list
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Power
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
var powers: List<Power>? = null
|
||||
|
||||
override fun toString(): String {
|
||||
return "Role(id=$id, name=$name, enable=$enable, createTime=$createTime, updateTime=$updateTime, deleted=$deleted, version=$version, modules=$modules, menus=$menus, funcs=$funcs, operations=$operations, powers=$powers)"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package top.fatweb.oxygen.api.entity.permission
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*
|
||||
import java.io.Serializable
|
||||
|
||||
/**
|
||||
* Role group intermediate entity
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableName("t_role_group")
|
||||
class RoleGroup : Serializable {
|
||||
/**
|
||||
* ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableId("id")
|
||||
var id: Long? = null
|
||||
|
||||
/**
|
||||
* Role ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("role_id")
|
||||
var roleId: Long? = null
|
||||
|
||||
/**
|
||||
* Group ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("group_id")
|
||||
var groupId: Long? = null
|
||||
|
||||
/**
|
||||
* Deleted
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("deleted")
|
||||
@TableLogic
|
||||
var deleted: Long? = null
|
||||
|
||||
/**
|
||||
* Version
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("version")
|
||||
@Version
|
||||
var version: Int? = null
|
||||
|
||||
override fun toString(): String {
|
||||
return "RoleGroup(id=$id, roleId=$roleId, groupId=$groupId, deleted=$deleted, version=$version)"
|
||||
}
|
||||
}
|
||||
256
src/main/kotlin/top/fatweb/oxygen/api/entity/permission/User.kt
Normal file
256
src/main/kotlin/top/fatweb/oxygen/api/entity/permission/User.kt
Normal file
@@ -0,0 +1,256 @@
|
||||
package top.fatweb.oxygen.api.entity.permission
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDateTime
|
||||
|
||||
/**
|
||||
* User entity
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableName("t_user")
|
||||
class User() : Serializable {
|
||||
constructor(id: Long?, username: String, password: String, enable: Boolean = true) : this() {
|
||||
this.id = id
|
||||
this.username = username
|
||||
this.password = password
|
||||
this.enable = if (enable) 1 else 0
|
||||
}
|
||||
|
||||
/**
|
||||
* ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableId("id")
|
||||
var id: Long? = null
|
||||
|
||||
/**
|
||||
* Username
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("username")
|
||||
var username: String? = null
|
||||
|
||||
/**
|
||||
* Password
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("password")
|
||||
var password: String? = null
|
||||
|
||||
/**
|
||||
* Verify email
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("verify")
|
||||
var verify: String? = null
|
||||
|
||||
/**
|
||||
* Forget password
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("forget")
|
||||
var forget: String? = null
|
||||
|
||||
/**
|
||||
* Locking
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("locking")
|
||||
var locking: Int? = null
|
||||
|
||||
/**
|
||||
* Expiration time
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see LocalDateTime
|
||||
*/
|
||||
@TableField("expiration")
|
||||
var expiration: LocalDateTime? = null
|
||||
|
||||
/**
|
||||
* Credentials expiration time
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see LocalDateTime
|
||||
*/
|
||||
@TableField("credentials_expiration")
|
||||
var credentialsExpiration: LocalDateTime? = null
|
||||
|
||||
/**
|
||||
* Enable
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("enable")
|
||||
var enable: Int? = null
|
||||
|
||||
/**
|
||||
* Current login time
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see LocalDateTime
|
||||
*/
|
||||
@TableField("current_login_time")
|
||||
var currentLoginTime: LocalDateTime? = null
|
||||
|
||||
/**
|
||||
* Current login IP
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("current_login_ip")
|
||||
var currentLoginIp: String? = null
|
||||
|
||||
/**
|
||||
* Last login time
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see LocalDateTime
|
||||
*/
|
||||
@TableField("last_login_time")
|
||||
var lastLoginTime: LocalDateTime? = null
|
||||
|
||||
/**
|
||||
* Last login IP
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("last_login_ip")
|
||||
var lastLoginIp: String? = null
|
||||
|
||||
/**
|
||||
* Create time
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see LocalDateTime
|
||||
*/
|
||||
@TableField("create_time")
|
||||
var createTime: LocalDateTime? = null
|
||||
|
||||
/**
|
||||
* Update time
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see LocalDateTime
|
||||
*/
|
||||
@TableField("update_time")
|
||||
var updateTime: LocalDateTime? = null
|
||||
|
||||
/**
|
||||
* Deleted
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("deleted")
|
||||
@TableLogic
|
||||
var deleted: Long? = null
|
||||
|
||||
/**
|
||||
* Version
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("version")
|
||||
@Version
|
||||
var version: Int? = null
|
||||
|
||||
/**
|
||||
* User info
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see UserInfo
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
var userInfo: UserInfo? = null
|
||||
|
||||
/**
|
||||
* Role list
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Role
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
var roles: List<Role>? = null
|
||||
|
||||
/**
|
||||
* Group list
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Group
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
var groups: List<Group>? = null
|
||||
|
||||
/**
|
||||
* Module list
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Module
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
var modules: List<Module>? = null
|
||||
|
||||
/**
|
||||
* Menu list
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Menu
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
var menus: List<Menu>? = null
|
||||
|
||||
/**
|
||||
* Function list
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Func
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
var funcs: List<Func>? = null
|
||||
|
||||
/**
|
||||
* Operation list
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Operation
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
var operations: List<Operation>? = null
|
||||
|
||||
override fun toString(): String {
|
||||
return "User(id=$id, username=$username, password=$password, verify=$verify, forget=$forget, locking=$locking, expiration=$expiration, credentialsExpiration=$credentialsExpiration, enable=$enable, currentLoginTime=$currentLoginTime, currentLoginIp=$currentLoginIp, lastLoginTime=$lastLoginTime, lastLoginIp=$lastLoginIp, createTime=$createTime, updateTime=$updateTime, deleted=$deleted, version=$version, userInfo=$userInfo, roles=$roles, groups=$groups, modules=$modules, menus=$menus, funcs=$funcs, operations=$operations)"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package top.fatweb.oxygen.api.entity.permission
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*
|
||||
import java.io.Serializable
|
||||
|
||||
/**
|
||||
* User group intermediate entity
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableName("t_user_group")
|
||||
class UserGroup : Serializable {
|
||||
/**
|
||||
* ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableId("id")
|
||||
var id: Long? = null
|
||||
|
||||
/**
|
||||
* User ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("user_id")
|
||||
var userId: Long? = null
|
||||
|
||||
/**
|
||||
* Group ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("group_id")
|
||||
var groupId: Long? = null
|
||||
|
||||
/**
|
||||
* Deleted
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("deleted")
|
||||
@TableLogic
|
||||
var deleted: Long? = null
|
||||
|
||||
/**
|
||||
* Version
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("version")
|
||||
@Version
|
||||
var version: Int? = null
|
||||
|
||||
override fun toString(): String {
|
||||
return "UserGroup(id=$id, userId=$userId, groupId=$groupId, deleted=$deleted, version=$version)"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package top.fatweb.oxygen.api.entity.permission
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDateTime
|
||||
|
||||
/**
|
||||
* User information entity
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableName("t_user_info")
|
||||
class UserInfo : Serializable {
|
||||
/**
|
||||
* ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableId("id")
|
||||
var id: Long? = null
|
||||
|
||||
/**
|
||||
* User ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("user_id")
|
||||
var userId: Long? = null
|
||||
|
||||
/**
|
||||
* Nickname
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("nickname")
|
||||
var nickname: String? = null
|
||||
|
||||
/**
|
||||
* Avatar in base64
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("avatar")
|
||||
var avatar: String? = null
|
||||
|
||||
/**
|
||||
* Email
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("email")
|
||||
var email: String? = null
|
||||
|
||||
/**
|
||||
* Create time
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see LocalDateTime
|
||||
*/
|
||||
@TableField("create_time", fill = FieldFill.INSERT)
|
||||
var createTime: LocalDateTime? = null
|
||||
|
||||
/**
|
||||
* Update time
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see LocalDateTime
|
||||
*/
|
||||
@TableField("update_time", fill = FieldFill.INSERT_UPDATE)
|
||||
var updateTime: LocalDateTime? = null
|
||||
|
||||
/**
|
||||
* Deleted
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("deleted")
|
||||
@TableLogic
|
||||
var deleted: Long? = null
|
||||
|
||||
/**
|
||||
* Version
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("version")
|
||||
@Version
|
||||
var version: Int? = null
|
||||
|
||||
override fun toString(): String {
|
||||
return "UserInfo(id=$id, userId=$userId, nickname=$nickname, avatar=$avatar, email=$email, createTime=$createTime, updateTime=$updateTime, deleted=$deleted, version=$version)"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package top.fatweb.oxygen.api.entity.permission
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.*
|
||||
import java.io.Serializable
|
||||
|
||||
/**
|
||||
* User role intermediate entity
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableName("t_user_role")
|
||||
class UserRole : Serializable {
|
||||
/**
|
||||
* ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableId("id")
|
||||
var id: Long? = null
|
||||
|
||||
/**
|
||||
* User ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("user_id")
|
||||
var userId: Long? = null
|
||||
|
||||
/**
|
||||
* Role ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("role_id")
|
||||
var roleId: Long? = null
|
||||
|
||||
/**
|
||||
* Deleted
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("deleted")
|
||||
@TableLogic
|
||||
var deleted: Long? = null
|
||||
|
||||
/**
|
||||
* Version
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("version")
|
||||
@Version
|
||||
var version: Int? = null
|
||||
|
||||
override fun toString(): String {
|
||||
return "UserRole(id=$id, userId=$userId, roleId=$roleId, deleted=$deleted, version=$version)"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package top.fatweb.oxygen.api.entity.system
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.EnumValue
|
||||
import com.baomidou.mybatisplus.annotation.TableField
|
||||
import com.baomidou.mybatisplus.annotation.TableId
|
||||
import com.baomidou.mybatisplus.annotation.TableName
|
||||
import com.fasterxml.jackson.annotation.JsonFormat
|
||||
import com.fasterxml.jackson.annotation.JsonValue
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDateTime
|
||||
|
||||
/**
|
||||
* Event log entity
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableName("t_event_log")
|
||||
class EventLog : Serializable {
|
||||
enum class Event(@field:EnumValue @field:JsonValue val code: String) {
|
||||
LOGIN("LOGIN"), LOGOUT("LOGOUT"), REGISTER("REGISTER"), VERIFY("VERIFY"), API("API")
|
||||
}
|
||||
|
||||
/**
|
||||
* ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableId("id")
|
||||
var id: Long? = null
|
||||
|
||||
/**
|
||||
* Event
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("event")
|
||||
var event: Event? = null
|
||||
|
||||
/**
|
||||
* Operate user ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("operate_user_id")
|
||||
var operateUserId: Long? = null
|
||||
|
||||
/**
|
||||
* Operate time
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
|
||||
@TableField("operate_time")
|
||||
var operateTime: LocalDateTime? = null
|
||||
|
||||
override fun toString(): String {
|
||||
return "EventLog(id=$id, event=$event, operateUserId=$operateUserId, operateTime=$operateTime)"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package top.fatweb.oxygen.api.entity.system
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.EnumValue
|
||||
import com.baomidou.mybatisplus.annotation.TableField
|
||||
import com.baomidou.mybatisplus.annotation.TableId
|
||||
import com.baomidou.mybatisplus.annotation.TableName
|
||||
import com.fasterxml.jackson.annotation.JsonFormat
|
||||
import com.fasterxml.jackson.annotation.JsonValue
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDateTime
|
||||
|
||||
/**
|
||||
* Statistics log entity
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableName("t_statistics_log")
|
||||
class StatisticsLog : Serializable {
|
||||
enum class KeyItem(@field:EnumValue @field:JsonValue val code: String) {
|
||||
ONLINE_USERS_COUNT("ONLINE_USER_COUNT")
|
||||
}
|
||||
|
||||
/**
|
||||
* ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableId("id")
|
||||
var id: Long? = null
|
||||
|
||||
/**
|
||||
* Key
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("key")
|
||||
var key: KeyItem? = null
|
||||
|
||||
/**
|
||||
* Value
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("value")
|
||||
var value: String? = null
|
||||
|
||||
/**
|
||||
* Record time
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
|
||||
@TableField("record_time")
|
||||
var recordTime: LocalDateTime? = null
|
||||
|
||||
override fun toString(): String {
|
||||
return "StatisticsLog(id=$id, key=$key, value=$value, recordTime=$recordTime)"
|
||||
}
|
||||
}
|
||||
186
src/main/kotlin/top/fatweb/oxygen/api/entity/system/SysLog.kt
Normal file
186
src/main/kotlin/top/fatweb/oxygen/api/entity/system/SysLog.kt
Normal file
@@ -0,0 +1,186 @@
|
||||
package top.fatweb.oxygen.api.entity.system
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.EnumValue
|
||||
import com.baomidou.mybatisplus.annotation.TableField
|
||||
import com.baomidou.mybatisplus.annotation.TableId
|
||||
import com.baomidou.mybatisplus.annotation.TableName
|
||||
import com.fasterxml.jackson.annotation.JsonFormat
|
||||
import com.fasterxml.jackson.annotation.JsonValue
|
||||
import java.io.Serializable
|
||||
import java.time.LocalDateTime
|
||||
|
||||
/**
|
||||
* System log entity
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableName("t_sys_log")
|
||||
class SysLog : Serializable {
|
||||
/**
|
||||
* Log type enum
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
enum class LogType(@field:EnumValue @field:JsonValue val code: String) {
|
||||
INFO("INFO"), ERROR("ERROR"), LOGIN("LOGIN"), LOGOUT("LOGOUT"), REGISTER("REGISTER"), STATISTICS("STATISTICS"), API(
|
||||
"API"
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableId("id")
|
||||
var id: Long? = null
|
||||
|
||||
/**
|
||||
* Log type
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see LogType
|
||||
*/
|
||||
@TableField("log_type")
|
||||
var logType: LogType? = null
|
||||
|
||||
/**
|
||||
* Operate user ID
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("operate_user_id")
|
||||
var operateUserId: Long? = null
|
||||
|
||||
/**
|
||||
* Operate time
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see LocalDateTime
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
|
||||
@TableField("operate_time")
|
||||
var operateTime: LocalDateTime? = null
|
||||
|
||||
/**
|
||||
* Request URI
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("request_uri")
|
||||
var requestUri: String? = null
|
||||
|
||||
/**
|
||||
* Request method
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("request_method")
|
||||
var requestMethod: String? = null
|
||||
|
||||
/**
|
||||
* Request parameters
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("request_params")
|
||||
var requestParams: String? = null
|
||||
|
||||
/**
|
||||
* Request IP
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("request_ip")
|
||||
var requestIp: String? = null
|
||||
|
||||
/**
|
||||
* Request server address
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("request_server_address")
|
||||
var requestServerAddress: String? = null
|
||||
|
||||
/**
|
||||
* Is exception
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("exception")
|
||||
var exception: Int? = null
|
||||
|
||||
/**
|
||||
* Exception information
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("exception_info")
|
||||
var exceptionInfo: String? = null
|
||||
|
||||
/**
|
||||
* Start time
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see LocalDateTime
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
|
||||
@TableField("start_time")
|
||||
var startTime: LocalDateTime? = null
|
||||
|
||||
/**
|
||||
* End time
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see LocalDateTime
|
||||
*/
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss.SSS")
|
||||
@TableField("end_time")
|
||||
var endTime: LocalDateTime? = null
|
||||
|
||||
/**
|
||||
* Execute time
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("execute_time")
|
||||
var executeTime: Long? = null
|
||||
|
||||
/**
|
||||
* User agent
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField("user_agent")
|
||||
var userAgent: String? = null
|
||||
|
||||
/**
|
||||
* Operate username
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
var operateUsername: String? = null
|
||||
|
||||
override fun toString(): String {
|
||||
return "SysLog(id=$id, logType=$logType, operateUserId=$operateUserId, operateTime=$operateTime, requestUri=$requestUri, requestMethod=$requestMethod, requestParams=$requestParams, requestIp=$requestIp, requestServerAddress=$requestServerAddress, exception=$exception, exceptionInfo=$exceptionInfo, startTime=$startTime, endTime=$endTime, executeTime=$executeTime, userAgent=$userAgent, operateUsername=$operateUsername)"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package top.fatweb.oxygen.api.exception
|
||||
|
||||
/**
|
||||
* Account need initialize exception
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see RuntimeException
|
||||
*/
|
||||
class AccountNeedInitException : RuntimeException("Account need initialize")
|
||||
@@ -0,0 +1,10 @@
|
||||
package top.fatweb.oxygen.api.exception
|
||||
|
||||
/**
|
||||
* Account need reset password exception
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see RuntimeException
|
||||
*/
|
||||
class AccountNeedResetPasswordException : RuntimeException("Account need reset password")
|
||||
@@ -0,0 +1,13 @@
|
||||
package top.fatweb.oxygen.api.exception
|
||||
|
||||
/**
|
||||
* Email settings not configured exception
|
||||
*
|
||||
* @param configs Configs not config
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see RuntimeException
|
||||
*/
|
||||
class NoEmailConfigException(
|
||||
vararg configs: String
|
||||
) : RuntimeException("Email settings not configured: ${configs.joinToString(", ")}")
|
||||
@@ -0,0 +1,10 @@
|
||||
package top.fatweb.oxygen.api.exception
|
||||
|
||||
/**
|
||||
* No record found exception
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see RuntimeException
|
||||
*/
|
||||
class NoRecordFoundException : RuntimeException("No record found")
|
||||
@@ -0,0 +1,10 @@
|
||||
package top.fatweb.oxygen.api.exception
|
||||
|
||||
/**
|
||||
* No verification required exception
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see RuntimeException
|
||||
*/
|
||||
class NoVerificationRequiredException : RuntimeException("No verification required")
|
||||
@@ -0,0 +1,10 @@
|
||||
package top.fatweb.oxygen.api.exception
|
||||
|
||||
/**
|
||||
* Retrieve code error or expired exception
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see RuntimeException
|
||||
*/
|
||||
class RetrieveCodeErrorOrExpiredException : RuntimeException("Retrieve code error or expired")
|
||||
@@ -0,0 +1,10 @@
|
||||
package top.fatweb.oxygen.api.exception
|
||||
|
||||
/**
|
||||
* Token has expired exception
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see RuntimeException
|
||||
*/
|
||||
class TokenHasExpiredException : RuntimeException("Token has expired")
|
||||
@@ -0,0 +1,10 @@
|
||||
package top.fatweb.oxygen.api.exception
|
||||
|
||||
/**
|
||||
* User not found exception
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see RuntimeException
|
||||
*/
|
||||
class UserNotFoundException : RuntimeException("User not found")
|
||||
@@ -0,0 +1,10 @@
|
||||
package top.fatweb.oxygen.api.exception
|
||||
|
||||
/**
|
||||
* Verification code error or expired exception
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see RuntimeException
|
||||
*/
|
||||
class VerificationCodeErrorOrExpiredException : RuntimeException("Verification code is error or has expired")
|
||||
@@ -0,0 +1,28 @@
|
||||
package top.fatweb.oxygen.api.filter
|
||||
|
||||
import jakarta.servlet.Filter
|
||||
import jakarta.servlet.FilterChain
|
||||
import jakarta.servlet.ServletRequest
|
||||
import jakarta.servlet.ServletResponse
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
/**
|
||||
* Exception filter
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Filter
|
||||
*/
|
||||
@Component
|
||||
class ExceptionFilter : Filter {
|
||||
override fun doFilter(
|
||||
servletRequest: ServletRequest?, servletResponse: ServletResponse?, filterChain: FilterChain?
|
||||
) {
|
||||
try {
|
||||
filterChain!!.doFilter(servletRequest, servletResponse)
|
||||
} catch (e: Exception) {
|
||||
servletRequest?.setAttribute("filter.error", e)
|
||||
servletRequest?.getRequestDispatcher("/error/thrown")?.forward(servletRequest, servletResponse)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package top.fatweb.oxygen.api.filter
|
||||
|
||||
import jakarta.servlet.FilterChain
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
|
||||
import org.springframework.security.core.context.SecurityContextHolder
|
||||
import org.springframework.stereotype.Component
|
||||
import org.springframework.util.StringUtils
|
||||
import org.springframework.web.filter.OncePerRequestFilter
|
||||
import top.fatweb.oxygen.api.entity.permission.LoginUser
|
||||
import top.fatweb.oxygen.api.exception.TokenHasExpiredException
|
||||
import top.fatweb.oxygen.api.properties.SecurityProperties
|
||||
import top.fatweb.oxygen.api.util.JwtUtil
|
||||
import top.fatweb.oxygen.api.util.RedisUtil
|
||||
import top.fatweb.oxygen.api.util.WebUtil
|
||||
|
||||
/**
|
||||
* Jwt authentication token filter
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see RedisUtil
|
||||
* @see OncePerRequestFilter
|
||||
*/
|
||||
@Component
|
||||
class JwtAuthenticationTokenFilter(private val redisUtil: RedisUtil) : OncePerRequestFilter() {
|
||||
override fun doFilterInternal(
|
||||
request: HttpServletRequest, response: HttpServletResponse, filterChain: FilterChain
|
||||
) {
|
||||
val tokenWithPrefix = request.getHeader(SecurityProperties.headerKey)
|
||||
|
||||
if (!StringUtils.hasText(tokenWithPrefix) || "/error/thrown" == request.servletPath) {
|
||||
filterChain.doFilter(request, response)
|
||||
return
|
||||
}
|
||||
|
||||
val token = WebUtil.getToken(tokenWithPrefix)
|
||||
JwtUtil.parseJwt(token)
|
||||
|
||||
val redisKeyPattern = "${SecurityProperties.jwtIssuer}_login_*:" + token
|
||||
val redisKeys = redisUtil.keys(redisKeyPattern)
|
||||
if (redisKeys.isEmpty()) {
|
||||
throw TokenHasExpiredException()
|
||||
}
|
||||
|
||||
val loginUser = redisUtil.getObject<LoginUser>(redisKeys.first())
|
||||
loginUser ?: let { throw TokenHasExpiredException() }
|
||||
|
||||
redisUtil.setExpire(redisKeys.first(), SecurityProperties.redisTtl, SecurityProperties.redisTtlUnit)
|
||||
|
||||
val authenticationToken = UsernamePasswordAuthenticationToken(loginUser, null, loginUser.authorities)
|
||||
SecurityContextHolder.getContext().authentication = authenticationToken
|
||||
|
||||
filterChain.doFilter(request, response)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package top.fatweb.oxygen.api.handler
|
||||
|
||||
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler
|
||||
import org.apache.ibatis.reflection.MetaObject
|
||||
import org.springframework.stereotype.Component
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneOffset
|
||||
|
||||
/**
|
||||
* Date meta object handler
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see MetaObjectHandler
|
||||
*/
|
||||
@Component
|
||||
class DataMetaObjectHandler : MetaObjectHandler {
|
||||
override fun insertFill(metaObject: MetaObject?) {
|
||||
this.strictInsertFill(metaObject, "createTime", LocalDateTime::class.java, LocalDateTime.now(ZoneOffset.UTC))
|
||||
this.strictInsertFill(metaObject, "updateTime", LocalDateTime::class.java, LocalDateTime.now(ZoneOffset.UTC))
|
||||
}
|
||||
|
||||
override fun updateFill(metaObject: MetaObject?) {
|
||||
this.strictUpdateFill(metaObject, "updateTime", LocalDateTime::class.java, LocalDateTime.now(ZoneOffset.UTC))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
package top.fatweb.oxygen.api.handler
|
||||
|
||||
import com.auth0.jwt.exceptions.JWTDecodeException
|
||||
import com.auth0.jwt.exceptions.SignatureVerificationException
|
||||
import com.auth0.jwt.exceptions.TokenExpiredException
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.springframework.dao.DuplicateKeyException
|
||||
import org.springframework.http.converter.HttpMessageNotReadableException
|
||||
import org.springframework.jdbc.BadSqlGrammarException
|
||||
import org.springframework.security.access.AccessDeniedException
|
||||
import org.springframework.security.authentication.*
|
||||
import org.springframework.web.HttpRequestMethodNotSupportedException
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler
|
||||
import org.springframework.web.bind.annotation.RestControllerAdvice
|
||||
import top.fatweb.avatargenerator.AvatarException
|
||||
import top.fatweb.oxygen.api.entity.common.ResponseCode
|
||||
import top.fatweb.oxygen.api.entity.common.ResponseResult
|
||||
import top.fatweb.oxygen.api.exception.*
|
||||
|
||||
/**
|
||||
* Exception handler
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@RestControllerAdvice
|
||||
class ExceptionHandler {
|
||||
private val logger: Logger = LoggerFactory.getLogger(this::class.java)
|
||||
|
||||
/**
|
||||
* Handle all exception
|
||||
*
|
||||
* @param e Exception
|
||||
* @return Response object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Exception
|
||||
* @see ResponseResult
|
||||
*/
|
||||
@ExceptionHandler(value = [Exception::class])
|
||||
fun exceptionHandler(e: Exception): ResponseResult<*> {
|
||||
return when (e) {
|
||||
is HttpRequestMethodNotSupportedException -> {
|
||||
logger.debug(e.localizedMessage, e)
|
||||
ResponseResult.fail(ResponseCode.SYSTEM_REQUEST_ILLEGAL, e.localizedMessage, null)
|
||||
}
|
||||
|
||||
is HttpMessageNotReadableException -> {
|
||||
logger.debug(e.localizedMessage, e)
|
||||
ResponseResult.fail(ResponseCode.SYSTEM_REQUEST_ILLEGAL, e.localizedMessage.split(":")[0], null)
|
||||
}
|
||||
|
||||
is MethodArgumentNotValidException -> {
|
||||
logger.debug(e.localizedMessage, e)
|
||||
val errorMessage = e.allErrors.map { error -> error.defaultMessage }.joinToString(". ")
|
||||
ResponseResult.fail(ResponseCode.SYSTEM_ARGUMENT_NOT_VALID, errorMessage, null)
|
||||
}
|
||||
|
||||
is InsufficientAuthenticationException -> {
|
||||
logger.debug(e.localizedMessage, e)
|
||||
ResponseResult.fail(ResponseCode.PERMISSION_UNAUTHORIZED, e.localizedMessage, null)
|
||||
}
|
||||
|
||||
is LockedException -> {
|
||||
logger.debug(e.localizedMessage, e)
|
||||
ResponseResult.fail(ResponseCode.PERMISSION_USER_LOCKED, "User account has been locked", null)
|
||||
}
|
||||
|
||||
is AccountExpiredException -> {
|
||||
logger.debug(e.localizedMessage, e)
|
||||
ResponseResult.fail(ResponseCode.PERMISSION_USER_EXPIRED, "User account has expired", null)
|
||||
}
|
||||
|
||||
is CredentialsExpiredException -> {
|
||||
logger.debug(e.localizedMessage, e)
|
||||
ResponseResult.fail(
|
||||
ResponseCode.PERMISSION_USER_CREDENTIALS_EXPIRED,
|
||||
"User credentials have expired",
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
is DisabledException -> {
|
||||
logger.debug(e.localizedMessage, e)
|
||||
ResponseResult.fail(ResponseCode.PERMISSION_USER_CREDENTIALS_EXPIRED, "User has been disabled", null)
|
||||
}
|
||||
|
||||
is TokenExpiredException -> {
|
||||
logger.debug(e.localizedMessage, e)
|
||||
ResponseResult.fail(ResponseCode.PERMISSION_TOKEN_HAS_EXPIRED, e.localizedMessage, null)
|
||||
}
|
||||
|
||||
is InternalAuthenticationServiceException -> {
|
||||
logger.debug(e.localizedMessage, e)
|
||||
ResponseResult.fail(ResponseCode.PERMISSION_USERNAME_NOT_FOUND, "Username not found", null)
|
||||
}
|
||||
|
||||
is BadCredentialsException -> {
|
||||
logger.debug(e.localizedMessage, e)
|
||||
ResponseResult.fail(
|
||||
ResponseCode.PERMISSION_LOGIN_USERNAME_PASSWORD_ERROR,
|
||||
"Wrong user name or password",
|
||||
null
|
||||
)
|
||||
}
|
||||
|
||||
is SignatureVerificationException, is JWTDecodeException -> {
|
||||
logger.debug(e.localizedMessage, e)
|
||||
ResponseResult.fail(ResponseCode.PERMISSION_TOKEN_ILLEGAL, "Token illegal", null)
|
||||
}
|
||||
|
||||
is TokenHasExpiredException -> {
|
||||
logger.debug(e.localizedMessage, e)
|
||||
ResponseResult.fail(ResponseCode.PERMISSION_TOKEN_HAS_EXPIRED, e.localizedMessage, null)
|
||||
}
|
||||
|
||||
is AccessDeniedException -> {
|
||||
logger.debug(e.localizedMessage, e)
|
||||
ResponseResult.fail(ResponseCode.PERMISSION_ACCESS_DENIED, "Access Denied", null)
|
||||
}
|
||||
|
||||
is UserNotFoundException -> {
|
||||
logger.debug(e.localizedMessage, e)
|
||||
ResponseResult.fail(ResponseCode.PERMISSION_USER_NOT_FOUND, e.localizedMessage, null)
|
||||
}
|
||||
|
||||
is NoVerificationRequiredException -> {
|
||||
logger.debug(e.localizedMessage, e)
|
||||
ResponseResult.fail(ResponseCode.PERMISSION_NO_VERIFICATION_REQUIRED, e.localizedMessage, null)
|
||||
}
|
||||
|
||||
is VerificationCodeErrorOrExpiredException -> {
|
||||
logger.debug(e.localizedMessage, e)
|
||||
ResponseResult.fail(ResponseCode.PERMISSION_VERIFY_CODE_ERROR_OR_EXPIRED, e.localizedMessage, null)
|
||||
}
|
||||
|
||||
is AccountNeedInitException -> {
|
||||
logger.debug(e.localizedMessage, e)
|
||||
ResponseResult.fail(ResponseCode.PERMISSION_ACCOUNT_NEED_INIT, e.localizedMessage, null)
|
||||
}
|
||||
|
||||
is RetrieveCodeErrorOrExpiredException -> {
|
||||
logger.debug(e.localizedMessage, e)
|
||||
ResponseResult.fail(ResponseCode.PERMISSION_RETRIEVE_CODE_ERROR_OR_EXPIRED, e.localizedMessage, null)
|
||||
}
|
||||
|
||||
is AccountNeedResetPasswordException -> {
|
||||
logger.debug(e.localizedMessage, e)
|
||||
ResponseResult.fail(ResponseCode.PERMISSION_ACCOUNT_NEED_RESET_PASSWORD, e.localizedMessage, null)
|
||||
}
|
||||
|
||||
|
||||
is BadSqlGrammarException -> {
|
||||
logger.debug(e.localizedMessage, e)
|
||||
ResponseResult.fail(ResponseCode.DATABASE_EXECUTE_ERROR, "Incorrect SQL syntax", null)
|
||||
}
|
||||
|
||||
is DuplicateKeyException -> {
|
||||
logger.debug(e.localizedMessage, e)
|
||||
ResponseResult.fail(ResponseCode.DATABASE_DUPLICATE_KEY, "Duplicate key", null)
|
||||
}
|
||||
|
||||
is NoRecordFoundException -> {
|
||||
logger.debug(e.localizedMessage, e)
|
||||
ResponseResult.fail(ResponseCode.DATABASE_NO_RECORD_FOUND, e.localizedMessage, null)
|
||||
}
|
||||
|
||||
is AvatarException -> {
|
||||
logger.debug(e.localizedMessage, e)
|
||||
ResponseResult.fail(ResponseCode.API_AVATAR_ERROR, e.localizedMessage, null)
|
||||
}
|
||||
|
||||
else -> {
|
||||
logger.error(e.localizedMessage, e)
|
||||
ResponseResult.fail(ResponseCode.SYSTEM_ERROR, e.toString(), null)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package top.fatweb.oxygen.api.handler
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import org.springframework.security.access.AccessDeniedException
|
||||
import org.springframework.security.web.access.AccessDeniedHandler
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
/**
|
||||
* Jwt access denied handler
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see AccessDeniedHandler
|
||||
*/
|
||||
@Component
|
||||
class JwtAccessDeniedHandler : AccessDeniedHandler {
|
||||
override fun handle(
|
||||
request: HttpServletRequest?, response: HttpServletResponse?, accessDeniedException: AccessDeniedException?
|
||||
) {
|
||||
request?.setAttribute("filter.error", accessDeniedException)
|
||||
request?.getRequestDispatcher("/error/thrown")?.forward(request, response)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package top.fatweb.oxygen.api.handler
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import org.springframework.security.core.AuthenticationException
|
||||
import org.springframework.security.web.AuthenticationEntryPoint
|
||||
import org.springframework.stereotype.Component
|
||||
|
||||
/**
|
||||
* Jwt authentication entry point handler
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see AuthenticationEntryPoint
|
||||
*/
|
||||
@Component
|
||||
class JwtAuthenticationEntryPointHandler : AuthenticationEntryPoint {
|
||||
override fun commence(
|
||||
request: HttpServletRequest?, response: HttpServletResponse?, authException: AuthenticationException?
|
||||
) {
|
||||
request?.setAttribute("filter.error", authException)
|
||||
request?.getRequestDispatcher("/error/thrown")?.forward(request, response)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package top.fatweb.oxygen.api.interceptor
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import jakarta.servlet.http.HttpServletResponse
|
||||
import org.springframework.beans.factory.annotation.Qualifier
|
||||
import org.springframework.core.MethodParameter
|
||||
import org.springframework.http.MediaType
|
||||
import org.springframework.http.converter.HttpMessageConverter
|
||||
import org.springframework.http.server.ServerHttpRequest
|
||||
import org.springframework.http.server.ServerHttpResponse
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice
|
||||
import org.springframework.web.servlet.HandlerInterceptor
|
||||
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice
|
||||
import top.fatweb.oxygen.api.entity.common.ResponseCode
|
||||
import top.fatweb.oxygen.api.entity.common.ResponseResult
|
||||
import top.fatweb.oxygen.api.entity.system.SysLog
|
||||
import top.fatweb.oxygen.api.service.system.ISysLogService
|
||||
import top.fatweb.oxygen.api.util.WebUtil
|
||||
import top.fatweb.oxygen.api.vo.permission.LoginVo
|
||||
import java.net.URI
|
||||
import java.time.LocalDateTime
|
||||
import java.time.ZoneOffset
|
||||
import java.time.temporal.ChronoUnit
|
||||
import java.util.*
|
||||
import java.util.concurrent.Executor
|
||||
|
||||
/**
|
||||
* System log interceptor
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Executor
|
||||
* @see ISysLogService
|
||||
*/
|
||||
@ControllerAdvice
|
||||
class SysLogInterceptor(
|
||||
@Qualifier("applicationTaskExecutor") private val customThreadPoolTaskExecutor: Executor,
|
||||
private val sysLogService: ISysLogService
|
||||
) : HandlerInterceptor, ResponseBodyAdvice<Any> {
|
||||
private val sysLogThreadLocal = ThreadLocal<SysLog>()
|
||||
private val resultThreadLocal = ThreadLocal<Any>()
|
||||
|
||||
override fun preHandle(request: HttpServletRequest, response: HttpServletResponse, handler: Any): Boolean {
|
||||
val sysLog = SysLog().apply {
|
||||
operateUserId = WebUtil.getLoginUserId() ?: -1
|
||||
startTime = LocalDateTime.now(ZoneOffset.UTC)
|
||||
requestUri = URI(request.requestURI).path
|
||||
requestParams = formatParams(request.parameterMap)
|
||||
requestMethod = request.method
|
||||
requestIp = request.remoteAddr
|
||||
requestServerAddress = "${request.scheme}://${request.serverName}:${request.serverPort}"
|
||||
userAgent = request.getHeader("User-Agent")
|
||||
}
|
||||
|
||||
sysLogThreadLocal.set(sysLog)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun afterCompletion(
|
||||
request: HttpServletRequest, response: HttpServletResponse, handler: Any, ex: Exception?
|
||||
) {
|
||||
val sysLog = sysLogThreadLocal.get()
|
||||
val result = resultThreadLocal.get()
|
||||
sysLog.endTime = LocalDateTime.now(ZoneOffset.UTC)
|
||||
sysLog.executeTime = ChronoUnit.MILLIS.between(sysLog.startTime, sysLog.endTime)
|
||||
if (result is ResponseResult<*>) {
|
||||
if (result.success) {
|
||||
sysLog.apply {
|
||||
logType = requestUri?.let {
|
||||
when {
|
||||
it.startsWith("/login") -> SysLog.LogType.LOGIN
|
||||
it.startsWith("/logout") -> SysLog.LogType.LOGOUT
|
||||
it.startsWith("/register") -> SysLog.LogType.REGISTER
|
||||
it.startsWith("/system/statistics/") -> SysLog.LogType.STATISTICS
|
||||
it.startsWith("/api/") -> SysLog.LogType.API
|
||||
else -> SysLog.LogType.INFO
|
||||
}
|
||||
} ?: SysLog.LogType.INFO
|
||||
exception = 0
|
||||
}
|
||||
if (result.data is LoginVo) {
|
||||
sysLog.operateUserId = result.data.userId ?: -1
|
||||
}
|
||||
} else {
|
||||
sysLog.apply {
|
||||
logType = SysLog.LogType.ERROR
|
||||
exception = 1
|
||||
exceptionInfo = result.msg
|
||||
}
|
||||
}
|
||||
|
||||
customThreadPoolTaskExecutor.execute(SaveLogThread(sysLog, sysLogService))
|
||||
}
|
||||
sysLogThreadLocal.remove()
|
||||
}
|
||||
|
||||
private fun formatParams(parameterMap: Map<String, Array<String>>): String {
|
||||
val params = StringJoiner("&")
|
||||
|
||||
parameterMap.forEach {
|
||||
params.add("${it.key}=${if (it.key.endsWith("password", true)) "*" else it.value.joinToString(",")}")
|
||||
}
|
||||
|
||||
return params.toString()
|
||||
}
|
||||
|
||||
private class SaveLogThread(val sysLog: SysLog, val sysLogService: ISysLogService) : Thread() {
|
||||
override fun run() {
|
||||
sysLog.operateTime = LocalDateTime.now(ZoneOffset.UTC)
|
||||
sysLogService.save(sysLog)
|
||||
}
|
||||
}
|
||||
|
||||
override fun supports(returnType: MethodParameter, converterType: Class<out HttpMessageConverter<*>>): Boolean =
|
||||
true
|
||||
|
||||
override fun beforeBodyWrite(
|
||||
body: Any?,
|
||||
returnType: MethodParameter,
|
||||
selectedContentType: MediaType,
|
||||
selectedConverterType: Class<out HttpMessageConverter<*>>,
|
||||
request: ServerHttpRequest,
|
||||
response: ServerHttpResponse
|
||||
): Any? {
|
||||
resultThreadLocal.set(body)
|
||||
|
||||
if (body is ResponseResult<*> && body.code == ResponseCode.SYSTEM_ERROR.code) {
|
||||
return ResponseResult.build(body.code, body.success, "fail", body.data)
|
||||
}
|
||||
|
||||
return body
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package top.fatweb.oxygen.api.mapper.permission
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper
|
||||
import org.apache.ibatis.annotations.Mapper
|
||||
import top.fatweb.oxygen.api.entity.permission.Func
|
||||
|
||||
/**
|
||||
* Function mapper
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see BaseMapper
|
||||
* @see Func
|
||||
*/
|
||||
@Mapper
|
||||
interface FuncMapper : BaseMapper<Func>
|
||||
@@ -0,0 +1,57 @@
|
||||
package top.fatweb.oxygen.api.mapper.permission
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage
|
||||
import org.apache.ibatis.annotations.Mapper
|
||||
import org.apache.ibatis.annotations.Param
|
||||
import top.fatweb.oxygen.api.entity.permission.Group
|
||||
|
||||
/**
|
||||
* Group mapper
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see BaseMapper
|
||||
* @see Group
|
||||
*/
|
||||
@Mapper
|
||||
interface GroupMapper : BaseMapper<Group> {
|
||||
/**
|
||||
* Select group in page
|
||||
*
|
||||
* @param page Pagination
|
||||
* @param searchName Name to search for
|
||||
* @param searchRegex Use regex
|
||||
* @return Group in page
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see IPage
|
||||
*/
|
||||
fun selectPage(
|
||||
page: IPage<Long>,
|
||||
@Param("searchName") searchName: String?,
|
||||
@Param("searchRegex") searchRegex: Boolean
|
||||
): IPage<Long>
|
||||
|
||||
/**
|
||||
* Select group with role list by list of group IDs
|
||||
*
|
||||
* @param groupIds List of group IDs
|
||||
* @return Group with role list
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Group
|
||||
*/
|
||||
fun selectListWithRoleByIds(@Param("groupIds") groupIds: List<Long>): List<Group>?
|
||||
|
||||
/**
|
||||
* Select one group by ID
|
||||
*
|
||||
* @param id Group ID
|
||||
* @return Group object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Group
|
||||
*/
|
||||
fun selectOneById(@Param("id") id: Long): Group?
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package top.fatweb.oxygen.api.mapper.permission
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper
|
||||
import org.apache.ibatis.annotations.Mapper
|
||||
import top.fatweb.oxygen.api.entity.permission.Menu
|
||||
|
||||
/**
|
||||
* Menu mapper
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see BaseMapper
|
||||
* @see Menu
|
||||
*/
|
||||
@Mapper
|
||||
interface MenuMapper : BaseMapper<Menu>
|
||||
@@ -0,0 +1,16 @@
|
||||
package top.fatweb.oxygen.api.mapper.permission
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper
|
||||
import org.apache.ibatis.annotations.Mapper
|
||||
import top.fatweb.oxygen.api.entity.permission.Module
|
||||
|
||||
/**
|
||||
* Module mapper
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see BaseMapper
|
||||
* @see Module
|
||||
*/
|
||||
@Mapper
|
||||
interface ModuleMapper : BaseMapper<Module>
|
||||
@@ -0,0 +1,16 @@
|
||||
package top.fatweb.oxygen.api.mapper.permission
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper
|
||||
import org.apache.ibatis.annotations.Mapper
|
||||
import top.fatweb.oxygen.api.entity.permission.Operation
|
||||
|
||||
/**
|
||||
* Operation mapper
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see BaseMapper
|
||||
* @see Operation
|
||||
*/
|
||||
@Mapper
|
||||
interface OperationMapper : BaseMapper<Operation>
|
||||
@@ -0,0 +1,16 @@
|
||||
package top.fatweb.oxygen.api.mapper.permission
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper
|
||||
import org.apache.ibatis.annotations.Mapper
|
||||
import top.fatweb.oxygen.api.entity.permission.Power
|
||||
|
||||
/**
|
||||
* Power mapper
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see BaseMapper
|
||||
* @see Power
|
||||
*/
|
||||
@Mapper
|
||||
interface PowerMapper : BaseMapper<Power>
|
||||
@@ -0,0 +1,16 @@
|
||||
package top.fatweb.oxygen.api.mapper.permission
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper
|
||||
import org.apache.ibatis.annotations.Mapper
|
||||
import top.fatweb.oxygen.api.entity.permission.PowerRole
|
||||
|
||||
/**
|
||||
* Power role intermediate mapper
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see BaseMapper
|
||||
* @see PowerRole
|
||||
*/
|
||||
@Mapper
|
||||
interface PowerRoleMapper : BaseMapper<PowerRole>
|
||||
@@ -0,0 +1,16 @@
|
||||
package top.fatweb.oxygen.api.mapper.permission
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper
|
||||
import org.apache.ibatis.annotations.Mapper
|
||||
import top.fatweb.oxygen.api.entity.permission.RoleGroup
|
||||
|
||||
/**
|
||||
* Role group intermediate mapper
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see BaseMapper
|
||||
* @see RoleGroup
|
||||
*/
|
||||
@Mapper
|
||||
interface RoleGroupMapper : BaseMapper<RoleGroup>
|
||||
@@ -0,0 +1,57 @@
|
||||
package top.fatweb.oxygen.api.mapper.permission
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage
|
||||
import org.apache.ibatis.annotations.Mapper
|
||||
import org.apache.ibatis.annotations.Param
|
||||
import top.fatweb.oxygen.api.entity.permission.Role
|
||||
|
||||
/**
|
||||
* Role mapper
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see BaseMapper
|
||||
* @see Role
|
||||
*/
|
||||
@Mapper
|
||||
interface RoleMapper : BaseMapper<Role> {
|
||||
/**
|
||||
* Select role in page
|
||||
*
|
||||
* @param page Pagination
|
||||
* @param searchName Name to search for
|
||||
* @param searchRegex Use regex
|
||||
* @return Role in page
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see IPage
|
||||
*/
|
||||
fun selectPage(
|
||||
page: IPage<Long>,
|
||||
@Param("searchName") searchName: String?,
|
||||
@Param("searchRegex") searchRegex: Boolean
|
||||
): IPage<Long>
|
||||
|
||||
/**
|
||||
* Select role with power list by list of role IDs
|
||||
*
|
||||
* @param roleIds List of role IDs
|
||||
* @return Role with power list
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Role
|
||||
*/
|
||||
fun selectListWithPowerByIds(@Param("roleIds") roleIds: List<Long>): List<Role>?
|
||||
|
||||
/**
|
||||
* Select one role by ID
|
||||
*
|
||||
* @param id Role ID
|
||||
* @return Role object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see Role
|
||||
*/
|
||||
fun selectOneById(@Param("id") id: Long): Role?
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package top.fatweb.oxygen.api.mapper.permission
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper
|
||||
import org.apache.ibatis.annotations.Mapper
|
||||
import top.fatweb.oxygen.api.entity.permission.UserGroup
|
||||
|
||||
/**
|
||||
* User group intermediate mapper
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see BaseMapper
|
||||
* @see UserGroup
|
||||
*/
|
||||
@Mapper
|
||||
interface UserGroupMapper : BaseMapper<UserGroup>
|
||||
@@ -0,0 +1,16 @@
|
||||
package top.fatweb.oxygen.api.mapper.permission
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper
|
||||
import org.apache.ibatis.annotations.Mapper
|
||||
import top.fatweb.oxygen.api.entity.permission.UserInfo
|
||||
|
||||
/**
|
||||
* User information mapper
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see BaseMapper
|
||||
* @see UserInfo
|
||||
*/
|
||||
@Mapper
|
||||
interface UserInfoMapper : BaseMapper<UserInfo>
|
||||
@@ -0,0 +1,100 @@
|
||||
package top.fatweb.oxygen.api.mapper.permission
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage
|
||||
import org.apache.ibatis.annotations.Mapper
|
||||
import org.apache.ibatis.annotations.Param
|
||||
import top.fatweb.oxygen.api.entity.permission.User
|
||||
|
||||
/**
|
||||
* User mapper
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see BaseMapper
|
||||
* @see User
|
||||
*/
|
||||
@Mapper
|
||||
interface UserMapper : BaseMapper<User> {
|
||||
/**
|
||||
* Select one user with power and information by username or email
|
||||
*
|
||||
* @param account Username or email
|
||||
* @return User object with power and information
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see User
|
||||
*/
|
||||
fun selectOneWithPowerInfoByAccount(@Param("account") account: String): User?
|
||||
|
||||
/**
|
||||
* Select user in page
|
||||
*
|
||||
* @param page Pagination
|
||||
* @param searchType Type of search
|
||||
* @param searchValue Value to search for
|
||||
* @param searchRegex Use regex
|
||||
* @return User in page
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see IPage
|
||||
*/
|
||||
fun selectPage(
|
||||
page: IPage<Long>,
|
||||
@Param("searchType") searchType: String,
|
||||
@Param("searchValue") searchValue: String?,
|
||||
@Param("searchRegex") searchRegex: Boolean
|
||||
): IPage<Long>
|
||||
|
||||
/**
|
||||
* Select user with role and information list by list of user IDs
|
||||
*
|
||||
* @param userIds List of user IDs
|
||||
* @return User with role and information list
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see User
|
||||
*/
|
||||
fun selectListWithRoleInfoByIds(@Param("userIds") userIds: List<Long>): List<User>
|
||||
|
||||
/**
|
||||
* Select one user by ID
|
||||
*
|
||||
* @param id User ID
|
||||
* @return User object
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see User
|
||||
*/
|
||||
fun selectOneWithRoleInfoById(@Param("id") id: Long): User?
|
||||
|
||||
/**
|
||||
* Select all user with information list
|
||||
*
|
||||
* @return User with information list
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see User
|
||||
*/
|
||||
fun selectListWithInfo(): List<User>
|
||||
|
||||
/**
|
||||
* Select user IDs list by list of role IDs
|
||||
*
|
||||
* @param roleIds List of role IDs
|
||||
* @return User IDs list
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
fun selectIdsWithRoleIds(@Param("roleIds") roleIds: List<Long>): List<Long>
|
||||
|
||||
/**
|
||||
* Select user IDs list by list of group IDs
|
||||
*
|
||||
* @param groupIds List of group IDs
|
||||
* @return User IDs list
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
fun selectIdsWithGroupIds(@Param("groupIds") groupIds: List<Long>): List<Long>
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package top.fatweb.oxygen.api.mapper.permission
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper
|
||||
import org.apache.ibatis.annotations.Mapper
|
||||
import top.fatweb.oxygen.api.entity.permission.UserRole
|
||||
|
||||
/**
|
||||
* User role intermediate mapper
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see BaseMapper
|
||||
* @see UserRole
|
||||
*/
|
||||
@Mapper
|
||||
interface UserRoleMapper : BaseMapper<UserRole>
|
||||
@@ -0,0 +1,14 @@
|
||||
package top.fatweb.oxygen.api.mapper.system
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper
|
||||
import org.apache.ibatis.annotations.Mapper
|
||||
import top.fatweb.oxygen.api.entity.system.EventLog
|
||||
|
||||
/**
|
||||
* Event log mapper
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Mapper
|
||||
interface EventLogMapper : BaseMapper<EventLog>
|
||||
@@ -0,0 +1,14 @@
|
||||
package top.fatweb.oxygen.api.mapper.system
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper
|
||||
import org.apache.ibatis.annotations.Mapper
|
||||
import top.fatweb.oxygen.api.entity.system.StatisticsLog
|
||||
|
||||
/**
|
||||
* Statistics log mapper
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Mapper
|
||||
interface StatisticsLogMapper : BaseMapper<StatisticsLog>
|
||||
@@ -0,0 +1,44 @@
|
||||
package top.fatweb.oxygen.api.mapper.system
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage
|
||||
import org.apache.ibatis.annotations.Mapper
|
||||
import org.apache.ibatis.annotations.Param
|
||||
import top.fatweb.oxygen.api.entity.system.SysLog
|
||||
import java.time.LocalDateTime
|
||||
|
||||
/**
|
||||
* System log mapper
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see BaseMapper
|
||||
* @see SysLog
|
||||
*/
|
||||
@Mapper
|
||||
interface SysLogMapper : BaseMapper<SysLog> {
|
||||
/**
|
||||
* Select system log in page
|
||||
*
|
||||
* @param page Pagination
|
||||
* @param logType List of log types
|
||||
* @param requestMethod List of request methods
|
||||
* @param searchRequestUrl Request URL to search for
|
||||
* @param searchStartTime Start time to search for
|
||||
* @param searchEndTime end time to search for
|
||||
* @return System log in page
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
* @see IPage
|
||||
* @see SysLog
|
||||
* @see LocalDateTime
|
||||
*/
|
||||
fun selectPage(
|
||||
page: IPage<SysLog>,
|
||||
@Param("logType") logType: List<String>?,
|
||||
@Param("requestMethod") requestMethod: List<String>?,
|
||||
@Param("searchRequestUrl") searchRequestUrl: String?,
|
||||
@Param("searchStartTime") searchStartTime: LocalDateTime?,
|
||||
@Param("searchEndTime") searchEndTime: LocalDateTime?
|
||||
): IPage<SysLog>
|
||||
}
|
||||
50
src/main/kotlin/top/fatweb/oxygen/api/param/PageSortParam.kt
Normal file
50
src/main/kotlin/top/fatweb/oxygen/api/param/PageSortParam.kt
Normal file
@@ -0,0 +1,50 @@
|
||||
package top.fatweb.oxygen.api.param
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema
|
||||
import jakarta.validation.constraints.Min
|
||||
|
||||
/**
|
||||
* Page sort parameters
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
open class PageSortParam {
|
||||
/**
|
||||
* Current page number
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Schema(description = "分页页码", defaultValue = "1", example = "1")
|
||||
@field:Min(1, message = "Pagination page number must be a positive integer")
|
||||
var currentPage: Long = 1
|
||||
|
||||
/**
|
||||
* Size of page
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Schema(description = "分页大小", defaultValue = "20", example = "20")
|
||||
@field:Min(1, message = "The number of data per page must be a positive integer")
|
||||
var pageSize: Long = 20
|
||||
|
||||
/**
|
||||
* Field name to sort
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Schema(description = "排序字段", example = "id")
|
||||
var sortField: String? = null
|
||||
|
||||
/**
|
||||
* Sort order by
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Schema(description = "排序方式", allowableValues = ["desc", "asc"], defaultValue = "desc", example = "desc")
|
||||
var sortOrder: String? = null
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
package top.fatweb.oxygen.api.param.api.v1.avatar
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema
|
||||
import jakarta.validation.constraints.Max
|
||||
import jakarta.validation.constraints.Pattern
|
||||
|
||||
/**
|
||||
* Avatar base parameters
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
open class AvatarBaseParam {
|
||||
/**
|
||||
* Seed to generate avatar
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Schema(description = "种子")
|
||||
var seed: Long? = null
|
||||
|
||||
/**
|
||||
* Size of image
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Schema(description = "图像大小", defaultValue = "128")
|
||||
@field:Max(256, message = "Size must be less than or equal to 256")
|
||||
var size: Int? = null
|
||||
|
||||
/**
|
||||
* Margin of image
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Schema(description = "外边距", defaultValue = "0")
|
||||
var margin: Int? = null
|
||||
|
||||
/**
|
||||
* Padding of image
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Schema(description = "内边距", defaultValue = "0")
|
||||
var padding: Int? = null
|
||||
|
||||
/**
|
||||
* List of colors to generate avatar
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Schema(defaultValue = "颜色列表", example = "#FFFFFFAA")
|
||||
var colors: List<String>? = null
|
||||
|
||||
/**
|
||||
* Background of image
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Schema(defaultValue = "背景颜色", example = "#FFFFFFAA")
|
||||
@field:Pattern(regexp = "^#[0-9a-fA-F]{6}|#[0-9a-fA-F]{8}$", message = "Background color must be a hex color code")
|
||||
var background: String? = null
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package top.fatweb.oxygen.api.param.api.v1.avatar
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema
|
||||
import jakarta.validation.constraints.Max
|
||||
|
||||
/**
|
||||
* GitHub style avatar parameters
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
data class AvatarGitHubParam(
|
||||
/**
|
||||
* Size of element
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Schema(description = "元素大小", defaultValue = "400")
|
||||
@field:Max(1000, message = "Element size must be less than or equal to 1000")
|
||||
val elementSize: Int = 400,
|
||||
|
||||
/**
|
||||
* Precision of element
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Schema(description = "精确度", defaultValue = "5")
|
||||
val precision: Int = 5
|
||||
) : AvatarBaseParam()
|
||||
@@ -0,0 +1,25 @@
|
||||
package top.fatweb.oxygen.api.param.permission
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema
|
||||
import jakarta.validation.constraints.NotBlank
|
||||
import jakarta.validation.constraints.Pattern
|
||||
|
||||
/**
|
||||
* Forget password parameters
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Schema(description = "忘记密码请求参数")
|
||||
data class ForgetParam(
|
||||
/**
|
||||
* Email
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Schema(description = "邮箱", required = true, example = "user@email.com")
|
||||
@field:NotBlank(message = "Email can not be blank")
|
||||
@field:Pattern(regexp = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*\$", message = "Illegal email address")
|
||||
val email: String?
|
||||
)
|
||||
@@ -0,0 +1,33 @@
|
||||
package top.fatweb.oxygen.api.param.permission
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema
|
||||
import jakarta.validation.constraints.NotBlank
|
||||
|
||||
/**
|
||||
* Login parameters
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Schema(description = "登录请求参数")
|
||||
data class LoginParam(
|
||||
/**
|
||||
* Account
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Schema(description = "账户", required = true, example = "test")
|
||||
@field:NotBlank(message = "Account can not be blank")
|
||||
val account: String?,
|
||||
|
||||
/**
|
||||
* Password
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Schema(description = "密码", required = true)
|
||||
@field:NotBlank(message = "Password can not be blank")
|
||||
val password: String?
|
||||
)
|
||||
@@ -0,0 +1,48 @@
|
||||
package top.fatweb.oxygen.api.param.permission
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema
|
||||
import jakarta.validation.constraints.NotBlank
|
||||
import jakarta.validation.constraints.Pattern
|
||||
import jakarta.validation.constraints.Size
|
||||
|
||||
/**
|
||||
* Register parameters
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Schema(description = "注册请求参数")
|
||||
data class RegisterParam(
|
||||
/**
|
||||
* Username
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Schema(description = "用户名", required = true, example = "abc")
|
||||
@field:NotBlank(message = "Username can not be blank")
|
||||
@field:Pattern(regexp = "[a-zA-Z-_][0-9a-zA-Z-_]{2,38}", message = "Illegal username")
|
||||
val username: String?,
|
||||
|
||||
/**
|
||||
* Email
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Schema(description = "邮箱", required = true, example = "user@email.com")
|
||||
@field:NotBlank(message = "Email can not be blank")
|
||||
@field:Pattern(regexp = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*\$", message = "Illegal email address")
|
||||
val email: String?,
|
||||
|
||||
/**
|
||||
* Password
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Schema(description = "密码", required = true)
|
||||
@field:NotBlank(message = "Password can not be blank")
|
||||
@field:Size(min = 10, max = 30)
|
||||
val password: String?
|
||||
)
|
||||
@@ -0,0 +1,35 @@
|
||||
package top.fatweb.oxygen.api.param.permission
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema
|
||||
import jakarta.validation.constraints.NotBlank
|
||||
import jakarta.validation.constraints.Size
|
||||
|
||||
/**
|
||||
* Retrieve password parameters
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Schema(description = "找回密码请求参数")
|
||||
data class RetrieveParam(
|
||||
/**
|
||||
* Code
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Schema(description = "验证码", required = true)
|
||||
@field:NotBlank(message = "Code can not be blank")
|
||||
val code: String?,
|
||||
|
||||
/**
|
||||
* New password
|
||||
*
|
||||
* @author FatttSnake, fatttsnake@gmail.com
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Schema(description = "新密码")
|
||||
@field:NotBlank(message = "New password can not be blank")
|
||||
@field:Size(min = 10, max = 30)
|
||||
val password: String?
|
||||
)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user