diff --git a/build-docker.sh b/build-docker.sh index 3839b82..877f249 100644 --- a/build-docker.sh +++ b/build-docker.sh @@ -10,15 +10,15 @@ java -Djarmode=layertools -jar target/*.jar extract --destination target/extract if [[ "${JAR_VERSION}" =~ ^.*SNAPSHOT$ ]] then - docker build -t hub.fatweb.top/fatweb-api:snapshot-latest -t hub.fatweb.top/fatweb-api:$JAR_VERSION -t hub.fatweb.top/fatweb-api:$JAR_VERSION-${BUILD_TIME} . + docker build -t hub.fatweb.top/oxygen-api:snapshot-latest -t hub.fatweb.top/oxygen-api:$JAR_VERSION -t hub.fatweb.top/oxygen-api:$JAR_VERSION-${BUILD_TIME} . cat "${KEYS_PATH}/docker.password" | docker login hub.fatweb.top -u jenkins --password-stdin - docker push hub.fatweb.top/fatweb-api:snapshot-latest - docker push hub.fatweb.top/fatweb-api:$JAR_VERSION - docker push hub.fatweb.top/fatweb-api:$JAR_VERSION-${BUILD_TIME} + docker push hub.fatweb.top/oxygen-api:snapshot-latest + docker push hub.fatweb.top/oxygen-api:$JAR_VERSION + docker push hub.fatweb.top/oxygen-api:$JAR_VERSION-${BUILD_TIME} else - docker build -t hub.fatweb.top/fatweb-api:latest -t hub.fatweb.top/fatweb-api:$JAR_VERSION -t hub.fatweb.top/fatweb-api:$JAR_VERSION-${BUILD_TIME} . + docker build -t hub.fatweb.top/oxygen-api:latest -t hub.fatweb.top/oxygen-api:$JAR_VERSION -t hub.fatweb.top/oxygen-api:$JAR_VERSION-${BUILD_TIME} . cat "${KEYS_PATH}/docker.password" | docker login hub.fatweb.top -u jenkins --password-stdin - docker push hub.fatweb.top/fatweb-api:latest - docker push hub.fatweb.top/fatweb-api:$JAR_VERSION - docker push hub.fatweb.top/fatweb-api:$JAR_VERSION-${BUILD_TIME} + docker push hub.fatweb.top/oxygen-api:latest + docker push hub.fatweb.top/oxygen-api:$JAR_VERSION + docker push hub.fatweb.top/oxygen-api:$JAR_VERSION-${BUILD_TIME} fi \ No newline at end of file diff --git a/db/schema.sql b/db/schema.sql deleted file mode 100644 index a1140fd..0000000 --- a/db/schema.sql +++ /dev/null @@ -1,12 +0,0 @@ -drop table if exists t_user; - -create table if not exists t_user -( - id bigint not null primary key, - username varchar(20) not null comment '用户名', - password char(70) not null comment '密码', - enable int not null comment '启用', - deleted bigint not null default 0, - version int not null default 0, - constraint t_user_unique unique (username, deleted) -) comment '用户'; diff --git a/doc/database.drawio b/doc/database.drawio new file mode 100644 index 0000000..007b0d0 --- /dev/null +++ b/doc/database.drawio @@ -0,0 +1,982 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/doc/permission.drawio b/doc/permission.drawio new file mode 100644 index 0000000..f2f17a0 --- /dev/null +++ b/doc/permission.drawio @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml index abe9e27..133a5d1 100644 --- a/pom.xml +++ b/pom.xml @@ -5,14 +5,28 @@ org.springframework.boot spring-boot-starter-parent - 3.1.4 + 3.2.1 top.fatweb api 0.0.1-SNAPSHOT - fatweb-api - fatweb-api + oxygen-api + oxygen-api + + + + sonatype-oss-snapshots + sonatype-oss-snapshots + https://s01.oss.sonatype.org/content/repositories/snapshots + + false + + + true + + + @@ -28,7 +42,7 @@ com.github.xiaoymin knife4j-openapi3-jakarta-spring-boot-starter - 4.3.0 + 4.4.0 @@ -61,15 +75,12 @@ 17 - 1.8.22 + 1.9.21 ${maven.build.timestamp} yyyy-MM-dd'T'HH:mm:ss + 9.22.3 - - org.springframework.boot - spring-boot-starter-security - org.springframework.boot spring-boot-starter-web @@ -79,29 +90,27 @@ spring-boot-starter-validation - com.fasterxml.jackson.module - jackson-module-kotlin + org.springframework.boot + spring-boot-starter-actuator - org.jetbrains.kotlin - kotlin-reflect + org.springframework.boot + spring-boot-starter-aop - org.jetbrains.kotlin - kotlin-stdlib + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-mail - org.springframework.boot spring-boot-devtools runtime true - - com.mysql - mysql-connector-j - runtime - org.springframework.boot spring-boot-starter-test @@ -112,51 +121,91 @@ spring-security-test test + + com.github.lianjiatech + retrofit-spring-boot-starter + 3.0.3 + - com.baomidou - mybatis-plus-boot-starter - 3.5.3.2 + org.jetbrains.kotlin + kotlin-reflect - com.baomidou - mybatis-plus-boot-starter-test - 3.5.3.2 - test + org.jetbrains.kotlin + kotlin-stdlib - com.alibaba - druid-spring-boot-starter - 1.2.19 + com.fasterxml.jackson.module + jackson-module-kotlin - + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + org.apache.velocity velocity-engine-core 2.3 + + com.mysql + mysql-connector-j + runtime + + + com.baomidou + mybatis-plus-spring-boot3-starter + 3.5.5 + + + org.xerial + sqlite-jdbc + 3.44.1.0 + + + com.baomidou + dynamic-datasource-spring-boot3-starter + 4.2.0 + + + org.flywaydb + flyway-mysql + ${flyway.version} + org.springframework.boot spring-boot-starter-data-redis + + com.baomidou + mybatis-plus-spring-boot3-starter-test + 3.5.5 + test + + + com.auth0 java-jwt 4.4.0 - org.springframework.boot - spring-boot-starter-actuator + top.fatweb + avatar-generator + 1.1.0 - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 + com.github.oshi + oshi-core + 6.4.9 @@ -202,6 +251,19 @@ + + org.jetbrains.dokka + dokka-maven-plugin + 1.9.10 + + + pre-site + + dokka + + + + diff --git a/src/main/kotlin/top/fatweb/api/FatWebApiApplication.kt b/src/main/kotlin/top/fatweb/api/FatWebApiApplication.kt deleted file mode 100644 index a2d2e01..0000000 --- a/src/main/kotlin/top/fatweb/api/FatWebApiApplication.kt +++ /dev/null @@ -1,36 +0,0 @@ -package top.fatweb.api - -import org.slf4j.LoggerFactory -import org.springframework.boot.autoconfigure.SpringBootApplication -import org.springframework.boot.runApplication -import org.springframework.transaction.annotation.EnableTransactionManagement -import java.io.File -import java.util.* - -@SpringBootApplication -@EnableTransactionManagement -class FatWebApiApplication - -fun main(args: Array) { - 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("application-config.yml").exists() || File("data/application-config.yml").exists()) { - runApplication(*args) - } else { - logger.warn("File ‘application.yml’ cannot be found in the running path. The configuration file template 'application.example.yml' has been created in directory 'data'. Please change the configuration file content, rename it to 'application.yml', and then restart the server.") - FatWebApiApplication::class.java.getResource("/application-config-template.yml")?.readText()?.let { - File("data/application-config.example.yml").writeText( - it.replace( - "\$uuid\$", UUID.randomUUID().toString().replace("-", "") - ) - ) - } - } -} diff --git a/src/main/kotlin/top/fatweb/api/annotation/ApiVersion.kt b/src/main/kotlin/top/fatweb/api/annotation/ApiVersion.kt deleted file mode 100644 index a0b064c..0000000 --- a/src/main/kotlin/top/fatweb/api/annotation/ApiVersion.kt +++ /dev/null @@ -1,11 +0,0 @@ -package top.fatweb.api.annotation - -import org.springframework.core.annotation.AliasFor - -@Target(AnnotationTarget.CLASS) -@Retention(AnnotationRetention.RUNTIME) -annotation class ApiVersion( - @get:AliasFor("version") val value: Int = 1, - - @get:AliasFor("value") val version: Int = 1 -) diff --git a/src/main/kotlin/top/fatweb/api/constant/SecurityConstants.kt b/src/main/kotlin/top/fatweb/api/constant/SecurityConstants.kt deleted file mode 100644 index c2b1738..0000000 --- a/src/main/kotlin/top/fatweb/api/constant/SecurityConstants.kt +++ /dev/null @@ -1,25 +0,0 @@ -package top.fatweb.api.constant - -import org.springframework.boot.context.properties.ConfigurationProperties -import org.springframework.stereotype.Component -import java.util.concurrent.TimeUnit - -@Component -@ConfigurationProperties("app.security") -object SecurityConstants { - var headerString = "Authorization" - - var tokenPrefix = "Bearer " - - var jwtTtl = 2L - - var jwtTtlUnit = TimeUnit.HOURS - - var jwtKey = "FatWeb" - - var jwtIssuer = "FatWeb" - - var redisTtl = 20L - - var redisTtlUnit = TimeUnit.MINUTES -} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/constant/ServerConstants.kt b/src/main/kotlin/top/fatweb/api/constant/ServerConstants.kt deleted file mode 100644 index 5f55621..0000000 --- a/src/main/kotlin/top/fatweb/api/constant/ServerConstants.kt +++ /dev/null @@ -1,18 +0,0 @@ -package top.fatweb.api.constant - -import org.springframework.boot.context.properties.ConfigurationProperties -import org.springframework.stereotype.Component -import java.time.LocalDateTime -import java.time.ZoneId -import java.time.ZonedDateTime - -@Component -@ConfigurationProperties("app") -object ServerConstants { - lateinit var version: String - - lateinit var buildTime: String - - fun buildZoneDateTime(zoneId: ZoneId = ZoneId.systemDefault()): ZonedDateTime = - LocalDateTime.parse(buildTime).atZone(ZoneId.of("UTC")).withZoneSameInstant(zoneId) -} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/controller/UserController.kt b/src/main/kotlin/top/fatweb/api/controller/UserController.kt deleted file mode 100644 index 188caf5..0000000 --- a/src/main/kotlin/top/fatweb/api/controller/UserController.kt +++ /dev/null @@ -1,17 +0,0 @@ -package top.fatweb.api.controller - -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RestController - -/** - *

- * 用户 前端控制器 - *

- * - * @author FatttSnake - * @since 2023-10-04 - */ -@RestController -@RequestMapping("/api/user") -class UserController - diff --git a/src/main/kotlin/top/fatweb/api/controller/permission/AuthenticationController.kt b/src/main/kotlin/top/fatweb/api/controller/permission/AuthenticationController.kt deleted file mode 100644 index 2dd6960..0000000 --- a/src/main/kotlin/top/fatweb/api/controller/permission/AuthenticationController.kt +++ /dev/null @@ -1,45 +0,0 @@ -package top.fatweb.api.controller.permission - -import io.swagger.v3.oas.annotations.Operation -import io.swagger.v3.oas.annotations.tags.Tag -import jakarta.servlet.http.HttpServletRequest -import jakarta.validation.Valid -import org.springframework.web.bind.annotation.* -import top.fatweb.api.annotation.ApiVersion -import top.fatweb.api.converter.UserConverter -import top.fatweb.api.entity.common.ResponseCode -import top.fatweb.api.entity.common.ResponseResult -import top.fatweb.api.param.LoginParam -import top.fatweb.api.service.permission.IAuthenticationService -import top.fatweb.api.util.WebUtil - -@Tag(name = "身份认证", description = "身份认证相关接口") -@ApiVersion(2) -@RestController -class AuthenticationController(val authenticationService: IAuthenticationService, val userConverter: UserConverter) { - @Operation(summary = "登录") - @PostMapping("/login") - fun login(@Valid @RequestBody loginParam: LoginParam) = - ResponseResult.success( - ResponseCode.SYSTEM_LOGIN_SUCCESS, - "Login success", - authenticationService.login(userConverter.loginParamToUser(loginParam)) - ) - - @Operation(summary = "登出") - @PostMapping("/logout") - fun logout(request: HttpServletRequest) = - when (authenticationService.logout(WebUtil.getToken(request))) { - true -> ResponseResult.success(ResponseCode.SYSTEM_LOGOUT_SUCCESS, "Logout success", null) - false -> ResponseResult.fail(ResponseCode.SYSTEM_LOGOUT_FAILED, "Logout failed", null) - } - - @Operation(summary = "更新 Token") - @GetMapping("/token") - fun renewToken(request: HttpServletRequest) = - ResponseResult.success( - ResponseCode.SYSTEM_TOKEN_RENEW_SUCCESS, - "Token renew success", - authenticationService.renewToken(WebUtil.getToken(request)) - ) -} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/converter/UserConverter.kt b/src/main/kotlin/top/fatweb/api/converter/UserConverter.kt deleted file mode 100644 index 1bfd381..0000000 --- a/src/main/kotlin/top/fatweb/api/converter/UserConverter.kt +++ /dev/null @@ -1,17 +0,0 @@ -package top.fatweb.api.converter - -import org.springframework.stereotype.Component -import top.fatweb.api.entity.permission.User -import top.fatweb.api.param.LoginParam - -@Component -object UserConverter { - fun loginParamToUser(loginParam: LoginParam): User { - val user = User().apply { - username = loginParam.username - password = loginParam.password - } - - return user - } -} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/entity/common/BusinessCode.kt b/src/main/kotlin/top/fatweb/api/entity/common/BusinessCode.kt deleted file mode 100644 index 02178f5..0000000 --- a/src/main/kotlin/top/fatweb/api/entity/common/BusinessCode.kt +++ /dev/null @@ -1,6 +0,0 @@ -package top.fatweb.api.entity.common - -enum class BusinessCode(val code: Int) { - SYSTEM(100), - DATABASE(200) -} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/entity/common/ResponseCode.kt b/src/main/kotlin/top/fatweb/api/entity/common/ResponseCode.kt deleted file mode 100644 index f6095bb..0000000 --- a/src/main/kotlin/top/fatweb/api/entity/common/ResponseCode.kt +++ /dev/null @@ -1,24 +0,0 @@ -package top.fatweb.api.entity.common - -enum class ResponseCode(val code: Int) { - SYSTEM_OK(BusinessCode.SYSTEM, 0), - SYSTEM_LOGIN_SUCCESS(BusinessCode.SYSTEM, 20), - SYSTEM_PASSWORD_CHANGE_SUCCESS(BusinessCode.SYSTEM, 21), - SYSTEM_LOGOUT_SUCCESS(BusinessCode.SYSTEM, 22), - SYSTEM_TOKEN_RENEW_SUCCESS(BusinessCode.SYSTEM, 23), - SYSTEM_UNAUTHORIZED(BusinessCode.SYSTEM, 30), - SYSTEM_USERNAME_NOT_FOUND(BusinessCode.SYSTEM, 31), - SYSTEM_ACCESS_DENIED(BusinessCode.SYSTEM, 32), - SYSTEM_USER_DISABLE(BusinessCode.SYSTEM, 33), - SYSTEM_LOGIN_USERNAME_PASSWORD_ERROR(BusinessCode.SYSTEM, 34), - SYSTEM_OLD_PASSWORD_NOT_MATCH(BusinessCode.SYSTEM, 35), - SYSTEM_LOGOUT_FAILED(BusinessCode.SYSTEM, 36), - SYSTEM_TOKEN_ILLEGAL(BusinessCode.SYSTEM, 37), - SYSTEM_TOKEN_HAS_EXPIRED(BusinessCode.SYSTEM, 38), - SYSTEM_REQUEST_ILLEGAL(BusinessCode.SYSTEM, 40), - SYSTEM_ARGUMENT_NOT_VALID(BusinessCode.SYSTEM, 41), - SYSTEM_ERROR(BusinessCode.SYSTEM, 50), - SYSTEM_TIMEOUT(BusinessCode.SYSTEM, 51); - - constructor(businessCode: BusinessCode, code: Int) : this(businessCode.code * 100 + code) -} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/entity/common/ResponseResult.kt b/src/main/kotlin/top/fatweb/api/entity/common/ResponseResult.kt deleted file mode 100644 index 9559c1d..0000000 --- a/src/main/kotlin/top/fatweb/api/entity/common/ResponseResult.kt +++ /dev/null @@ -1,29 +0,0 @@ -package top.fatweb.api.entity.common - -import io.swagger.v3.oas.annotations.media.Schema -import java.io.Serializable - -class ResponseResult 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 { - fun build(code: ResponseCode, success: Boolean, msg: String, data: T?) = - ResponseResult(code.code, success, msg, data) - - fun success(code: ResponseCode = ResponseCode.SYSTEM_OK, msg: String = "success", data: T? = null) = - build(code, true, msg, data) - - fun fail(code: ResponseCode = ResponseCode.SYSTEM_ERROR, msg: String = "fail", data: T? = null) = - build(code, false, msg, data) - } -} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/entity/permission/LoginUser.kt b/src/main/kotlin/top/fatweb/api/entity/permission/LoginUser.kt deleted file mode 100644 index 951d1e2..0000000 --- a/src/main/kotlin/top/fatweb/api/entity/permission/LoginUser.kt +++ /dev/null @@ -1,44 +0,0 @@ -package top.fatweb.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.userdetails.UserDetails - -@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) -class LoginUser() : UserDetails { - lateinit var user: User - - @JsonIgnore - private var authorities: List? = null - - constructor(user: User) : this() { - this.user = user - } - - @JsonIgnore - override fun getAuthorities(): List { - authorities?.let { return it } - authorities = emptyList() - - return authorities as List - } - - @JsonIgnore - override fun getPassword(): String? = user.password - - @JsonIgnore - override fun getUsername(): String? = user.username - - @JsonIgnore - override fun isAccountNonExpired(): Boolean = true - - @JsonIgnore - override fun isAccountNonLocked(): Boolean = true - - @JsonIgnore - override fun isCredentialsNonExpired(): Boolean = true - - @JsonIgnore - override fun isEnabled(): Boolean = user.enable == 1 -} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/entity/permission/User.kt b/src/main/kotlin/top/fatweb/api/entity/permission/User.kt deleted file mode 100644 index bff63ab..0000000 --- a/src/main/kotlin/top/fatweb/api/entity/permission/User.kt +++ /dev/null @@ -1,54 +0,0 @@ -package top.fatweb.api.entity.permission - -import com.baomidou.mybatisplus.annotation.* -import java.io.Serializable - -/** - *

- * 用户 - *

- * - * @author FatttSnake - * @since 2023-10-04 - */ -@TableName("t_user") -class User() : Serializable { - constructor(username: String, password: String, enable: Boolean = true) : this() { - this.username = username - this.password = password - this.enable = if (enable) 1 else 0 - } - - @TableId("id") - var id: Long? = null - - /** - * 用户名 - */ - @TableField("username") - var username: String? = null - - /** - * 密码 - */ - @TableField("password") - var password: String? = null - - /** - * 启用 - */ - @TableField("enable") - var enable: Int? = null - - @TableField("deleted") - @TableLogic - var deleted: Long? = null - - @TableField("version") - @Version - var version: Int? = null - - override fun toString(): String { - return "User{id=$id, username=$username, password=$password, enable=$enable, deleted=$deleted, version=$version}" - } -} diff --git a/src/main/kotlin/top/fatweb/api/exception/TokenHasExpiredException.kt b/src/main/kotlin/top/fatweb/api/exception/TokenHasExpiredException.kt deleted file mode 100644 index 2b0521f..0000000 --- a/src/main/kotlin/top/fatweb/api/exception/TokenHasExpiredException.kt +++ /dev/null @@ -1,3 +0,0 @@ -package top.fatweb.api.exception - -class TokenHasExpiredException : RuntimeException("Token has expired") \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/filter/JwtAuthenticationTokenFilter.kt b/src/main/kotlin/top/fatweb/api/filter/JwtAuthenticationTokenFilter.kt deleted file mode 100644 index 048aa39..0000000 --- a/src/main/kotlin/top/fatweb/api/filter/JwtAuthenticationTokenFilter.kt +++ /dev/null @@ -1,46 +0,0 @@ -package top.fatweb.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.api.constant.SecurityConstants -import top.fatweb.api.entity.permission.LoginUser -import top.fatweb.api.exception.TokenHasExpiredException -import top.fatweb.api.util.JwtUtil -import top.fatweb.api.util.RedisUtil -import top.fatweb.api.util.WebUtil - -@Component -class JwtAuthenticationTokenFilter(private val redisUtil: RedisUtil) : OncePerRequestFilter() { - override fun doFilterInternal( - request: HttpServletRequest, - response: HttpServletResponse, - filterChain: FilterChain - ) { - val tokenWithPrefix = request.getHeader(SecurityConstants.headerString) - - if (!StringUtils.hasText(tokenWithPrefix) || "/error/thrown" == request.servletPath) { - filterChain.doFilter(request, response) - return - } - - val token = WebUtil.getToken(tokenWithPrefix) - JwtUtil.parseJwt(token) - - val redisKey = "${SecurityConstants.jwtIssuer}_login:" + token - val loginUser = redisUtil.getObject(redisKey) - loginUser ?: let { throw TokenHasExpiredException() } - - redisUtil.setExpire(redisKey, SecurityConstants.redisTtl, SecurityConstants.redisTtlUnit) - - val authenticationToken = UsernamePasswordAuthenticationToken(loginUser, null, loginUser.authorities) - SecurityContextHolder.getContext().authentication = authenticationToken - - filterChain.doFilter(request, response) - } -} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/handler/ExceptionHandler.kt b/src/main/kotlin/top/fatweb/api/handler/ExceptionHandler.kt deleted file mode 100644 index c4abedb..0000000 --- a/src/main/kotlin/top/fatweb/api/handler/ExceptionHandler.kt +++ /dev/null @@ -1,67 +0,0 @@ -package top.fatweb.api.handler - -import com.auth0.jwt.exceptions.JWTDecodeException -import com.auth0.jwt.exceptions.SignatureVerificationException -import org.slf4j.Logger -import org.slf4j.LoggerFactory -import org.springframework.http.converter.HttpMessageNotReadableException -import org.springframework.security.authentication.BadCredentialsException -import org.springframework.security.authentication.InsufficientAuthenticationException -import org.springframework.security.authentication.InternalAuthenticationServiceException -import org.springframework.web.bind.MethodArgumentNotValidException -import org.springframework.web.bind.annotation.ExceptionHandler -import org.springframework.web.bind.annotation.RestControllerAdvice -import top.fatweb.api.entity.common.ResponseCode -import top.fatweb.api.entity.common.ResponseResult -import top.fatweb.api.exception.TokenHasExpiredException - -@RestControllerAdvice -class ExceptionHandler { - private val log: Logger = LoggerFactory.getLogger(this::class.java) - - @ExceptionHandler(value = [Exception::class]) - fun exceptionHandler(e: Exception): ResponseResult<*> { - return when (e) { - is InsufficientAuthenticationException -> { - log.debug(e.localizedMessage, e) - ResponseResult.fail(ResponseCode.SYSTEM_UNAUTHORIZED, e.localizedMessage, null) - } - - is HttpMessageNotReadableException -> { - log.debug(e.localizedMessage, e) - ResponseResult.fail(ResponseCode.SYSTEM_REQUEST_ILLEGAL, e.localizedMessage.split(":")[0], null) - } - - is MethodArgumentNotValidException -> { - log.debug(e.localizedMessage, e) - val errorMessage = e.allErrors.map { error -> error.defaultMessage }.joinToString(". ") - ResponseResult.fail(ResponseCode.SYSTEM_ARGUMENT_NOT_VALID, errorMessage, null) - } - - is InternalAuthenticationServiceException -> { - log.debug(e.localizedMessage, e) - ResponseResult.fail(ResponseCode.SYSTEM_USERNAME_NOT_FOUND, "Username not found", null) - } - - is BadCredentialsException -> { - log.debug(e.localizedMessage, e) - ResponseResult.fail(ResponseCode.SYSTEM_LOGIN_USERNAME_PASSWORD_ERROR, e.localizedMessage, null) - } - - is SignatureVerificationException, is JWTDecodeException -> { - log.debug(e.localizedMessage, e) - ResponseResult.fail(ResponseCode.SYSTEM_TOKEN_ILLEGAL, "Token illegal", null) - } - - is TokenHasExpiredException -> { - log.debug(e.localizedMessage, e) - ResponseResult.fail(ResponseCode.SYSTEM_TOKEN_HAS_EXPIRED, e.localizedMessage, null) - } - - else -> { - log.error(e.localizedMessage, e) - ResponseResult.fail(ResponseCode.SYSTEM_ERROR, data = null) - } - } - } -} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/mapper/UserMapper.kt b/src/main/kotlin/top/fatweb/api/mapper/UserMapper.kt deleted file mode 100644 index 8b37df3..0000000 --- a/src/main/kotlin/top/fatweb/api/mapper/UserMapper.kt +++ /dev/null @@ -1,16 +0,0 @@ -package top.fatweb.api.mapper - -import com.baomidou.mybatisplus.core.mapper.BaseMapper -import org.apache.ibatis.annotations.Mapper -import top.fatweb.api.entity.permission.User - -/** - *

- * 用户 Mapper 接口 - *

- * - * @author FatttSnake - * @since 2023-10-04 - */ -@Mapper -interface UserMapper : BaseMapper diff --git a/src/main/kotlin/top/fatweb/api/param/LoginParam.kt b/src/main/kotlin/top/fatweb/api/param/LoginParam.kt deleted file mode 100644 index 701ab12..0000000 --- a/src/main/kotlin/top/fatweb/api/param/LoginParam.kt +++ /dev/null @@ -1,17 +0,0 @@ -package top.fatweb.api.param - -import io.swagger.v3.oas.annotations.media.Schema -import jakarta.validation.constraints.NotBlank -import java.io.Serializable - -@Schema(description = "登录请求参数") -class LoginParam : Serializable { - - @Schema(description = "用户名", example = "test", required = true) - @NotBlank(message = "Username can not be blank") - val username: String? = null - - @Schema(description = "密码", example = "test123456", required = true) - @NotBlank(message = "Password can not be blank") - val password: String? = null -} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/service/IUserService.kt b/src/main/kotlin/top/fatweb/api/service/IUserService.kt deleted file mode 100644 index 7bc58e9..0000000 --- a/src/main/kotlin/top/fatweb/api/service/IUserService.kt +++ /dev/null @@ -1,14 +0,0 @@ -package top.fatweb.api.service - -import com.baomidou.mybatisplus.extension.service.IService -import top.fatweb.api.entity.permission.User - -/** - *

- * 用户 服务类 - *

- * - * @author FatttSnake - * @since 2023-10-04 - */ -interface IUserService : IService diff --git a/src/main/kotlin/top/fatweb/api/service/impl/UserServiceImpl.kt b/src/main/kotlin/top/fatweb/api/service/impl/UserServiceImpl.kt deleted file mode 100644 index e522f6b..0000000 --- a/src/main/kotlin/top/fatweb/api/service/impl/UserServiceImpl.kt +++ /dev/null @@ -1,18 +0,0 @@ -package top.fatweb.api.service.impl - -import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl -import org.springframework.stereotype.Service -import top.fatweb.api.entity.permission.User -import top.fatweb.api.mapper.UserMapper -import top.fatweb.api.service.IUserService - -/** - *

- * 用户 服务实现类 - *

- * - * @author FatttSnake - * @since 2023-10-04 - */ -@Service -class UserServiceImpl : ServiceImpl(), IUserService diff --git a/src/main/kotlin/top/fatweb/api/service/permission/IAuthenticationService.kt b/src/main/kotlin/top/fatweb/api/service/permission/IAuthenticationService.kt deleted file mode 100644 index 28becfc..0000000 --- a/src/main/kotlin/top/fatweb/api/service/permission/IAuthenticationService.kt +++ /dev/null @@ -1,13 +0,0 @@ -package top.fatweb.api.service.permission - -import top.fatweb.api.entity.permission.User -import top.fatweb.api.vo.LoginVo -import top.fatweb.api.vo.TokenVo - -interface IAuthenticationService { - fun login(user: User): LoginVo - - fun logout(token: String): Boolean - - fun renewToken(token: String): TokenVo -} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/service/permission/impl/AuthenticationServiceImpl.kt b/src/main/kotlin/top/fatweb/api/service/permission/impl/AuthenticationServiceImpl.kt deleted file mode 100644 index d08bc10..0000000 --- a/src/main/kotlin/top/fatweb/api/service/permission/impl/AuthenticationServiceImpl.kt +++ /dev/null @@ -1,65 +0,0 @@ -package top.fatweb.api.service.permission.impl - -import org.springframework.security.authentication.AuthenticationManager -import org.springframework.security.authentication.UsernamePasswordAuthenticationToken -import org.springframework.stereotype.Service -import top.fatweb.api.constant.SecurityConstants -import top.fatweb.api.entity.permission.LoginUser -import top.fatweb.api.entity.permission.User -import top.fatweb.api.service.permission.IAuthenticationService -import top.fatweb.api.util.JwtUtil -import top.fatweb.api.util.RedisUtil -import top.fatweb.api.util.WebUtil -import top.fatweb.api.vo.LoginVo -import top.fatweb.api.vo.TokenVo - -@Service -class AuthenticationServiceImpl( - private val authenticationManager: AuthenticationManager, - private val redisUtil: RedisUtil -) : IAuthenticationService { - override fun login(user: User): LoginVo { - val usernamePasswordAuthenticationToken = UsernamePasswordAuthenticationToken(user.username, user.password) - val authentication = authenticationManager.authenticate(usernamePasswordAuthenticationToken) - authentication ?: let { - throw RuntimeException("Login failed") - } - - val loginUser = authentication.principal as LoginUser - loginUser.user.password = "" - val userId = loginUser.user.id.toString() - val jwt = JwtUtil.createJwt(userId) - - jwt ?: let { - throw RuntimeException("Login failed") - } - - val redisKey = "${SecurityConstants.jwtIssuer}_login:" + jwt - redisUtil.setObject(redisKey, loginUser, SecurityConstants.redisTtl, SecurityConstants.redisTtlUnit) - - return LoginVo(jwt) - } - - override fun logout(token: String): Boolean = - redisUtil.delObject("${SecurityConstants.jwtIssuer}_login:" + token) - - override fun renewToken(token: String): TokenVo { - val oldRedisKey = "${SecurityConstants.jwtIssuer}_login:" + token - redisUtil.delObject(oldRedisKey) - val jwt = JwtUtil.createJwt(WebUtil.getLoginUserId().toString()) - - jwt ?: let { - throw RuntimeException("Login failed") - } - - val redisKey = "${SecurityConstants.jwtIssuer}_login:" + jwt - redisUtil.setObject( - redisKey, - WebUtil.getLoginUser(), - SecurityConstants.redisTtl, - SecurityConstants.redisTtlUnit - ) - - return TokenVo(jwt) - } -} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/service/permission/impl/UserDetailsServiceImpl.kt b/src/main/kotlin/top/fatweb/api/service/permission/impl/UserDetailsServiceImpl.kt deleted file mode 100644 index 6b78e76..0000000 --- a/src/main/kotlin/top/fatweb/api/service/permission/impl/UserDetailsServiceImpl.kt +++ /dev/null @@ -1,19 +0,0 @@ -package top.fatweb.api.service.permission.impl - -import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper -import org.springframework.security.core.userdetails.UserDetails -import org.springframework.security.core.userdetails.UserDetailsService -import org.springframework.stereotype.Service -import top.fatweb.api.entity.permission.LoginUser -import top.fatweb.api.entity.permission.User -import top.fatweb.api.service.IUserService - -@Service -class UserDetailsServiceImpl(val userService: IUserService) : UserDetailsService { - override fun loadUserByUsername(username: String?): UserDetails { - val user = userService.getOne(KtQueryWrapper(User()).eq(User::username, username)) - user ?: let { throw Exception("Username not found") } - - return LoginUser(user) - } -} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/util/ApiResponseMappingHandlerMapping.kt b/src/main/kotlin/top/fatweb/api/util/ApiResponseMappingHandlerMapping.kt deleted file mode 100644 index 8dafc0e..0000000 --- a/src/main/kotlin/top/fatweb/api/util/ApiResponseMappingHandlerMapping.kt +++ /dev/null @@ -1,31 +0,0 @@ -package top.fatweb.api.util - -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.servlet.mvc.condition.RequestCondition -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping -import top.fatweb.api.annotation.ApiVersion -import java.lang.reflect.Method - -class ApiResponseMappingHandlerMapping : RequestMappingHandlerMapping() { - private val versionFlag = "{apiVersion}" - - private fun createCondition(clazz: Class<*>): RequestCondition? { - val classRequestMapping = clazz.getAnnotation(RequestMapping::class.java) - classRequestMapping ?: let { return null } - val mappingUrlBuilder = StringBuilder() - if (classRequestMapping.value.isNotEmpty()) { - mappingUrlBuilder.append(classRequestMapping.value[0]) - } - val mappingUrl = mappingUrlBuilder.toString() - if (!mappingUrl.contains(versionFlag)) { - return null - } - val apiVersion = clazz.getAnnotation(ApiVersion::class.java) - - return if (apiVersion == null) ApiVersionCondition(1) else ApiVersionCondition(apiVersion.version) - } - - override fun getCustomMethodCondition(method: Method): RequestCondition<*>? = createCondition(method.javaClass) - - override fun getCustomTypeCondition(handlerType: Class<*>): RequestCondition<*>? = createCondition(handlerType) -} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/util/RedisUtil.kt b/src/main/kotlin/top/fatweb/api/util/RedisUtil.kt deleted file mode 100644 index 35991a8..0000000 --- a/src/main/kotlin/top/fatweb/api/util/RedisUtil.kt +++ /dev/null @@ -1,183 +0,0 @@ -package top.fatweb.api.util - -import org.springframework.data.redis.core.BoundSetOperations -import org.springframework.data.redis.core.RedisTemplate -import org.springframework.stereotype.Component -import java.util.concurrent.TimeUnit - -@Suppress("UNCHECKED_CAST") -@Component -class RedisUtil(private val redisTemplate: RedisTemplate) { - /** - * 设置有效时间 - * - * @param key 缓存的键 - * @param timeout 超时时间 - * @param timeUnit 时间颗粒度 - * @return true=设置成功;false=设置失败 - */ - fun setExpire(key: String, timeout: Long, timeUnit: TimeUnit = TimeUnit.SECONDS) = - redisTemplate.expire(key, timeout, timeUnit) - - /** - * 获取有效时间 - * - * @param key 缓存的键 - * @return 有效时间 - */ - fun getExpire(key: String, timeUnit: TimeUnit = TimeUnit.SECONDS) = redisTemplate.getExpire(key, timeUnit) - - /** - * 判断 key 是否存在 - * - * @param key 缓存的键 - * @return true=存在; false=不存在 - */ - fun hasKey(key: String) = redisTemplate.hasKey(key) - - /** - * 获得缓存的基本对象列表 - * - * @param pattern 字符串前缀 - * @return 对象列表 - */ - fun keys(pattern: String): Set = redisTemplate.keys(pattern) - - /** - * 缓存基本的对象,Integer、String、实体类等 - * - * @param key 缓存的键 - * @param value 缓存的值 - */ - fun setObject(key: String, value: Any) = redisTemplate.opsForValue().set(key, value) - - /** - * 缓存基本的对象,Integer、String、实体类等 - * - * @param key 缓存的键 - * @param value 缓存的值 - * @param timeout 超时时间 - * @param timeUnit 时间颗粒度 - */ - fun setObject(key: String, value: Any, timeout: Long, timeUnit: TimeUnit = TimeUnit.SECONDS) = - redisTemplate.opsForValue().set(key, value, timeout, timeUnit) - - - /** - * 获得缓存的基本对象 - * - * @param key 缓存的键 - * @return 缓存的值 - */ - fun getObject(key: String) = redisTemplate.opsForValue().get(key) as? T - - /** - * 删除单个对象 - * - * @param key 缓存的键 - * @return true=删除成功;false=删除失败 - */ - fun delObject(key: String) = redisTemplate.delete(key) - - /** - * 删除对象集合 - * - * @param collection 键集合 - * @return 删除个数 - */ - fun delObject(collection: Collection) = redisTemplate.delete(collection) - - /** - * 缓存 List 数据 - * - * @param key 缓存的键 - * @param dataList 缓存的 List 数据 - * @return 缓存的个数 - */ - fun setList(key: String, dataList: List) = redisTemplate.opsForList().rightPushAll(key, dataList) - - /** - * 获得缓存的 List 数据 - * - * @param key 缓存的键 - * @return 缓存的键对应的 List 数据 - */ - fun getList(key: String): List? = redisTemplate.opsForList().range(key, 0, -1) as? List - - /** - * 缓存 Set 数据 - * - * @param key 缓存的键 - * @param dataSet 缓存的 Set 数据 - * @return 缓存数据的对象 - */ - fun setSet(key: String, dataSet: Set): BoundSetOperations { - val boundSetOps: BoundSetOperations = redisTemplate.boundSetOps(key) - for (data in dataSet) { - boundSetOps.add(data) - } - return boundSetOps - } - - /** - * 获得缓存的 Set 数据 - * - * @param key 缓存的键 - * @return 缓存的键对应的 Set 数据 - */ - fun getSet(key: String): Set? = redisTemplate.opsForSet().members(key) as? Set - - /** - * 缓存 Map 数据 - * - * @param key 缓存的键 - * @param dataMap 缓存的 Map 数据 - */ - fun setMap(key: String, dataMap: Map) = redisTemplate.opsForHash().putAll(key, dataMap) - - /** - * 获得缓存的 Map 数据 - * - * @param key 缓存的键 - * @return 缓存的键对应的 Map 数据 - */ - fun getMap(key: String): Map? = - redisTemplate.opsForHash().entries(key) as? Map - - /** - * 往 Hash 中存入数据 - * - * @param key Redis 键 - * @param hKey Hash 键 - * @param value 值 - */ - fun setMapValue(key: String, hKey: String, value: Any) = - redisTemplate.opsForHash().put(key, hKey, value) - - /** - * 获取 Hash 中的数据 - * - * @param key Redis 键 - * @param hKey Hash 键 - * @return Hash 中的对象 - */ - fun getMapValue(key: String, hKey: String) = redisTemplate.opsForHash().get(key, hKey) - - /** - * 删除 Hash 中的数据 - * - * @param key Redis 键 - * @param hKey Hash 键 - */ - fun delMapValue(key: String, hKey: String) = redisTemplate.opsForHash().delete(key, hKey) - - /** - * 获取多个 Hash 中的数据 - * - * @param key Redis 键 - * @param hKeys Hash 键集合 - * @return Hash 对象集合 - */ - fun getMultiMapValue(key: String, hKeys: Collection): List = - redisTemplate.opsForHash().multiGet(key, hKeys) -} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/util/WebUtil.kt b/src/main/kotlin/top/fatweb/api/util/WebUtil.kt deleted file mode 100644 index da37681..0000000 --- a/src/main/kotlin/top/fatweb/api/util/WebUtil.kt +++ /dev/null @@ -1,16 +0,0 @@ -package top.fatweb.api.util - -import jakarta.servlet.http.HttpServletRequest -import org.springframework.security.core.context.SecurityContextHolder -import top.fatweb.api.constant.SecurityConstants -import top.fatweb.api.entity.permission.LoginUser - -object WebUtil { - fun getLoginUser() = SecurityContextHolder.getContext().authentication.principal as LoginUser - - fun getLoginUserId() = getLoginUser().user.id - - fun getToken(tokenWithPrefix: String) = tokenWithPrefix.removePrefix(SecurityConstants.tokenPrefix) - - fun getToken(request: HttpServletRequest) = getToken(request.getHeader(SecurityConstants.headerString)) -} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/vo/LoginVo.kt b/src/main/kotlin/top/fatweb/api/vo/LoginVo.kt deleted file mode 100644 index 8727d54..0000000 --- a/src/main/kotlin/top/fatweb/api/vo/LoginVo.kt +++ /dev/null @@ -1,11 +0,0 @@ -package top.fatweb.api.vo - -import io.swagger.v3.oas.annotations.media.Schema - -@Schema(description = "登录返回参数") -data class LoginVo( - @Schema( - description = "Token", - example = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkYTllYjFkYmVmZDQ0OWRkOThlOGNjNzZlNzZkMDgyNSIsInN1YiI6IjE3MDk5ODYwNTg2Nzk5NzU5MzgiLCJpc3MiOiJGYXRXZWIiLCJpYXQiOjE2OTY1MjgxMTcsImV4cCI6MTY5NjUzNTMxN30.U2ZsyrGk7NbsP-DJfdz9xgWSfect5r2iKQnlEsscAA8" - ) val token: String -) \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/OxygenApiApplication.kt b/src/main/kotlin/top/fatweb/oxygen/api/OxygenApiApplication.kt new file mode 100644 index 0000000..146c2fb --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/OxygenApiApplication.kt @@ -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) { + 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(*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("-", "") + ) + ) + } + } +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/annotation/ApiController.kt b/src/main/kotlin/top/fatweb/oxygen/api/annotation/ApiController.kt new file mode 100644 index 0000000..5805c4e --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/annotation/ApiController.kt @@ -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 = [""], + + @get:AliasFor(annotation = Tag::class, attribute = "name") val name: String, + + @get:AliasFor(annotation = Tag::class, attribute = "description") val description: String +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/annotation/BaseController.kt b/src/main/kotlin/top/fatweb/oxygen/api/annotation/BaseController.kt new file mode 100644 index 0000000..598555d --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/annotation/BaseController.kt @@ -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 = [""], + + @get:AliasFor(annotation = Tag::class, attribute = "name") val name: String, + + @get:AliasFor(annotation = Tag::class, attribute = "description") val description: String +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/annotation/EventLogRecord.kt b/src/main/kotlin/top/fatweb/oxygen/api/annotation/EventLogRecord.kt new file mode 100644 index 0000000..f0e023b --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/annotation/EventLogRecord.kt @@ -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 +) \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/annotation/HiddenController.kt b/src/main/kotlin/top/fatweb/oxygen/api/annotation/HiddenController.kt new file mode 100644 index 0000000..90287fb --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/annotation/HiddenController.kt @@ -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 = [""] +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/aop/EventLogAspect.kt b/src/main/kotlin/top/fatweb/oxygen/api/aop/EventLogAspect.kt new file mode 100644 index 0000000..c9710e5 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/aop/EventLogAspect.kt @@ -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) + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/config/DateFormatConfig.kt b/src/main/kotlin/top/fatweb/oxygen/api/config/DateFormatConfig.kt new file mode 100644 index 0000000..2e908a8 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/config/DateFormatConfig.kt @@ -0,0 +1,59 @@ +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 java.text.DateFormat +import java.text.SimpleDateFormat +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter +import java.util.* + +/** + * Date format configuration + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@JsonComponent +class DateFormatConfig { + /** + * 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 dateFormat: 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 { + val tz = timeZone + val df: DateFormat = SimpleDateFormat(dateFormat) + df.timeZone = tz + it.failOnEmptyBeans(false).failOnUnknownProperties(false) + .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS).dateFormat(df) + } + + @Bean + fun jackson2ObjectMapperBuilderCustomizer() = + Jackson2ObjectMapperBuilderCustomizer { + it.serializerByType( + LocalDateTime::class.java, LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateFormat)) + ) + } + +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/config/FilterConfig.kt b/src/main/kotlin/top/fatweb/oxygen/api/config/FilterConfig.kt similarity index 74% rename from src/main/kotlin/top/fatweb/api/config/FilterConfig.kt rename to src/main/kotlin/top/fatweb/oxygen/api/config/FilterConfig.kt index 71374f9..7b1883b 100644 --- a/src/main/kotlin/top/fatweb/api/config/FilterConfig.kt +++ b/src/main/kotlin/top/fatweb/oxygen/api/config/FilterConfig.kt @@ -1,10 +1,16 @@ -package top.fatweb.api.config +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.api.filter.ExceptionFilter +import top.fatweb.oxygen.api.filter.ExceptionFilter +/** + * Filter configuration + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ @Configuration class FilterConfig { @Bean diff --git a/src/main/kotlin/top/fatweb/oxygen/api/config/FlywayConfig.kt b/src/main/kotlin/top/fatweb/oxygen/api/config/FlywayConfig.kt new file mode 100644 index 0000000..9e34385 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/config/FlywayConfig.kt @@ -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() + } + + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/config/InitConfig.kt b/src/main/kotlin/top/fatweb/oxygen/api/config/InitConfig.kt new file mode 100644 index 0000000..7e4d123 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/config/InitConfig.kt @@ -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.") + } + } + + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/config/JacksonConfig.kt b/src/main/kotlin/top/fatweb/oxygen/api/config/JacksonConfig.kt new file mode 100644 index 0000000..b3518e0 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/config/JacksonConfig.kt @@ -0,0 +1,28 @@ +package top.fatweb.oxygen.api.config + +import com.fasterxml.jackson.annotation.JsonInclude +import com.fasterxml.jackson.databind.DeserializationFeature +import com.fasterxml.jackson.databind.json.JsonMapper +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration +import retrofit2.converter.jackson.JacksonConverterFactory + +/** + * Jackson configuration + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Configuration +class JacksonConfig { + @Bean + fun jacksonConverterFactory(): JacksonConverterFactory { + val mapper = JsonMapper.builder() + .findAndAddModules() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .serializationInclusion(JsonInclude.Include.NON_NULL) + .build() + + return JacksonConverterFactory.create(mapper) + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/config/MybatisPlusConfig.kt b/src/main/kotlin/top/fatweb/oxygen/api/config/MybatisPlusConfig.kt similarity index 84% rename from src/main/kotlin/top/fatweb/api/config/MybatisPlusConfig.kt rename to src/main/kotlin/top/fatweb/oxygen/api/config/MybatisPlusConfig.kt index 2ce739c..9d36fe0 100644 --- a/src/main/kotlin/top/fatweb/api/config/MybatisPlusConfig.kt +++ b/src/main/kotlin/top/fatweb/oxygen/api/config/MybatisPlusConfig.kt @@ -1,4 +1,4 @@ -package top.fatweb.api.config +package top.fatweb.oxygen.api.config import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor @@ -6,6 +6,12 @@ import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerIntercept 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 @@ -16,5 +22,4 @@ class MybatisPlusConfig { return mybatisPlusInterceptor } - } \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/config/RedisConfig.kt b/src/main/kotlin/top/fatweb/oxygen/api/config/RedisConfig.kt similarity index 93% rename from src/main/kotlin/top/fatweb/api/config/RedisConfig.kt rename to src/main/kotlin/top/fatweb/oxygen/api/config/RedisConfig.kt index 14d3ee0..b22b12f 100644 --- a/src/main/kotlin/top/fatweb/api/config/RedisConfig.kt +++ b/src/main/kotlin/top/fatweb/oxygen/api/config/RedisConfig.kt @@ -1,4 +1,4 @@ -package top.fatweb.api.config +package top.fatweb.oxygen.api.config import com.fasterxml.jackson.annotation.JsonAutoDetect import com.fasterxml.jackson.annotation.JsonTypeInfo @@ -12,6 +12,12 @@ 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 diff --git a/src/main/kotlin/top/fatweb/api/config/SecurityConfig.kt b/src/main/kotlin/top/fatweb/oxygen/api/config/SecurityConfig.kt similarity index 66% rename from src/main/kotlin/top/fatweb/api/config/SecurityConfig.kt rename to src/main/kotlin/top/fatweb/oxygen/api/config/SecurityConfig.kt index 4ab79bc..c62c302 100644 --- a/src/main/kotlin/top/fatweb/api/config/SecurityConfig.kt +++ b/src/main/kotlin/top/fatweb/oxygen/api/config/SecurityConfig.kt @@ -1,4 +1,4 @@ -package top.fatweb.api.config +package top.fatweb.oxygen.api.config import org.springframework.context.annotation.Bean import org.springframework.context.annotation.Configuration @@ -6,23 +6,31 @@ 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.api.filter.JwtAuthenticationTokenFilter -import top.fatweb.api.handler.JwtAccessDeniedHandler -import top.fatweb.api.handler.JwtAuthenticationEntryPointHandler +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( - val jwtAuthenticationTokenFilter: JwtAuthenticationTokenFilter, - val authenticationEntryPointHandler: JwtAuthenticationEntryPointHandler, - val accessDeniedHandler: JwtAccessDeniedHandler + private val jwtAuthenticationTokenFilter: JwtAuthenticationTokenFilter, + private val authenticationEntryPointHandler: JwtAuthenticationEntryPointHandler, + private val accessDeniedHandler: JwtAccessDeniedHandler ) { @Bean fun passwordEncoder() = BCryptPasswordEncoder() @@ -47,43 +55,51 @@ class SecurityConfig( @Bean fun securityFilterChain(httpSecurity: HttpSecurity): SecurityFilterChain = httpSecurity // Disable CSRF - .csrf { csrfConfigurer: CsrfConfigurer -> csrfConfigurer.disable() } + .csrf { + it.disable() + } // Do not get SecurityContent by Session - .sessionManagement { sessionManagementConfigurer: SessionManagementConfigurer -> - sessionManagementConfigurer.sessionCreationPolicy( + .sessionManagement { + it.sessionCreationPolicy( SessionCreationPolicy.STATELESS ) } - .authorizeHttpRequests { authorizeHttpRequests: AuthorizeHttpRequestsConfigurer.AuthorizationManagerRequestMatcherRegistry -> - authorizeHttpRequests + .authorizeHttpRequests { + it // Allow anonymous access .requestMatchers( - "/login", "/error/thrown", "/doc.html", "/swagger-ui/**", "/webjars/**", "/v3/**", "/swagger-ui.html", - "/favicon.ico" + "/favicon.ico", + "/login", + "/register", + "/forget", + "/retrieve" ).anonymous() + .requestMatchers("/tool/detail/**", "/tool/store", "/tool/store/*", "/system/user/info/*").permitAll() // Authentication required .anyRequest().authenticated() } - .logout { logoutConfigurer: LogoutConfigurer -> logoutConfigurer.disable() } + .logout { + it.disable() + } - .exceptionHandling { exceptionHandlingConfigurer: ExceptionHandlingConfigurer -> - exceptionHandlingConfigurer.authenticationEntryPoint( + .exceptionHandling { + it.authenticationEntryPoint( authenticationEntryPointHandler ) - exceptionHandlingConfigurer.accessDeniedHandler( + it.accessDeniedHandler( accessDeniedHandler ) } - .cors { cors: CorsConfigurer -> - cors.configurationSource( + .cors { + it.configurationSource( corsConfigurationSource() ) } diff --git a/src/main/kotlin/top/fatweb/api/config/SwaggerConfig.kt b/src/main/kotlin/top/fatweb/oxygen/api/config/SwaggerConfig.kt similarity index 54% rename from src/main/kotlin/top/fatweb/api/config/SwaggerConfig.kt rename to src/main/kotlin/top/fatweb/oxygen/api/config/SwaggerConfig.kt index fde4588..af0ca61 100644 --- a/src/main/kotlin/top/fatweb/api/config/SwaggerConfig.kt +++ b/src/main/kotlin/top/fatweb/oxygen/api/config/SwaggerConfig.kt @@ -1,22 +1,27 @@ -package top.fatweb.api.config +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.api.constant.ServerConstants +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@fatweb.top") + val contact = Contact().name("FatttSnake").url("https://fatweb.top").email("fatttsnake@gmail.com") return OpenAPI().info( - Info().title("FatWeb API 文档").description("FatWeb 后端 API 文档,包含各个 Controller 调用信息") + Info().title("Oxygen API 文档").description("Oxygen 后端 API 文档,包含各个 Controller 调用信息") .contact(contact).version( - ServerConstants.version + ServerProperties.version ) ) } diff --git a/src/main/kotlin/top/fatweb/oxygen/api/config/SysLogConfig.kt b/src/main/kotlin/top/fatweb/oxygen/api/config/SysLogConfig.kt new file mode 100644 index 0000000..fbd40c3 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/config/SysLogConfig.kt @@ -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/**") + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/config/VelocityEngineConfig.kt b/src/main/kotlin/top/fatweb/oxygen/api/config/VelocityEngineConfig.kt new file mode 100644 index 0000000..0995ada --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/config/VelocityEngineConfig.kt @@ -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() + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/config/WebMvcConfigurerConfig.kt b/src/main/kotlin/top/fatweb/oxygen/api/config/WebMvcConfigurerConfig.kt new file mode 100644 index 0000000..604a8ab --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/config/WebMvcConfigurerConfig.kt @@ -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) } + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/config/WebMvcRegistrationsConfig.kt b/src/main/kotlin/top/fatweb/oxygen/api/config/WebMvcRegistrationsConfig.kt similarity index 63% rename from src/main/kotlin/top/fatweb/api/config/WebMvcRegistrationsConfig.kt rename to src/main/kotlin/top/fatweb/oxygen/api/config/WebMvcRegistrationsConfig.kt index 1db6a0f..f65a30c 100644 --- a/src/main/kotlin/top/fatweb/api/config/WebMvcRegistrationsConfig.kt +++ b/src/main/kotlin/top/fatweb/oxygen/api/config/WebMvcRegistrationsConfig.kt @@ -1,10 +1,17 @@ -package top.fatweb.api.config +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.api.util.ApiResponseMappingHandlerMapping +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() diff --git a/src/main/kotlin/top/fatweb/api/controller/ExceptionController.kt b/src/main/kotlin/top/fatweb/oxygen/api/controller/ExceptionController.kt similarity index 56% rename from src/main/kotlin/top/fatweb/api/controller/ExceptionController.kt rename to src/main/kotlin/top/fatweb/oxygen/api/controller/ExceptionController.kt index e5dfad2..c61cceb 100644 --- a/src/main/kotlin/top/fatweb/api/controller/ExceptionController.kt +++ b/src/main/kotlin/top/fatweb/oxygen/api/controller/ExceptionController.kt @@ -1,13 +1,16 @@ -package top.fatweb.api.controller +package top.fatweb.oxygen.api.controller -import io.swagger.v3.oas.annotations.Hidden import jakarta.servlet.http.HttpServletRequest import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RestController +import top.fatweb.oxygen.api.annotation.HiddenController -@Hidden -@RestController -@RequestMapping("/error") +/** + * Exception controller + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@HiddenController(["/error"]) class ExceptionController { @RequestMapping("/thrown") fun thrown(request: HttpServletRequest) { diff --git a/src/main/kotlin/top/fatweb/oxygen/api/controller/api/v1/AvatarController.kt b/src/main/kotlin/top/fatweb/oxygen/api/controller/api/v1/AvatarController.kt new file mode 100644 index 0000000..0747aff --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/controller/api/v1/AvatarController.kt @@ -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 = + 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 = + 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 = + 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 = + 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 = + ResponseResult.success( + ResponseCode.API_AVATAR_SUCCESS, + data = avatarService.githubBase64(avatarGitHubParam) + ) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/controller/permission/AuthenticationController.kt b/src/main/kotlin/top/fatweb/oxygen/api/controller/permission/AuthenticationController.kt new file mode 100644 index 0000000..1d21a2c --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/controller/permission/AuthenticationController.kt @@ -0,0 +1,187 @@ +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( + request: HttpServletRequest, + @Valid @RequestBody registerParam: RegisterParam + ): ResponseResult = ResponseResult.success( + ResponseCode.PERMISSION_REGISTER_SUCCESS, + data = authenticationService.register(request, 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 { + 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 { + 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 { + authenticationService.forget(request, forgetParam) + + return ResponseResult.success(ResponseCode.PERMISSION_FORGET_SUCCESS) + } + + /** + * Retrieve password + * + * @param request + * @param retrieveParam Retrieve parameters + * @return Response object includes 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 { + 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 = + 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 = + 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 = ResponseResult.success( + ResponseCode.PERMISSION_TOKEN_RENEW_SUCCESS, + "Token renew success", + authenticationService.renewToken(WebUtil.getToken(request)) + ) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/controller/permission/GroupController.kt b/src/main/kotlin/top/fatweb/oxygen/api/controller/permission/GroupController.kt new file mode 100644 index 0000000..664a928 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/controller/permission/GroupController.kt @@ -0,0 +1,170 @@ +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 management 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 information + * @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 = + 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> = + 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> = + ResponseResult.databaseSuccess( + data = groupService.getList() + ) + + /** + * 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 = + ResponseResult.databaseSuccess( + ResponseCode.DATABASE_INSERT_SUCCESS, data = groupService.add(groupAddParam) + ) + + /** + * 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 = + ResponseResult.databaseSuccess( + ResponseCode.DATABASE_UPDATE_SUCCESS, data = groupService.update(groupUpdateParam) + ) + + /** + * 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 { + groupService.status(groupUpdateStatusParam) + return ResponseResult.databaseSuccess(ResponseCode.DATABASE_UPDATE_SUCCESS) + } + + /** + * 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 { + 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 { + groupService.delete(groupDeleteParam) + return ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS) + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/controller/permission/PowerController.kt b/src/main/kotlin/top/fatweb/oxygen/api/controller/permission/PowerController.kt new file mode 100644 index 0000000..f4bbd0d --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/controller/permission/PowerController.kt @@ -0,0 +1,35 @@ +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 management 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 + * + * @return Response object includes 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 = ResponseResult.databaseSuccess(data = powerService.getList()) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/controller/permission/RoleController.kt b/src/main/kotlin/top/fatweb/oxygen/api/controller/permission/RoleController.kt new file mode 100644 index 0000000..77144e2 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/controller/permission/RoleController.kt @@ -0,0 +1,170 @@ +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 management 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 = + 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> = + 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> { + return ResponseResult.databaseSuccess( + data = roleService.getList() + ) + } + + /** + * 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 = + ResponseResult.databaseSuccess( + ResponseCode.DATABASE_INSERT_SUCCESS, data = roleService.add(roleAddParam) + ) + + /** + * 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 = + ResponseResult.databaseSuccess( + ResponseCode.DATABASE_UPDATE_SUCCESS, data = roleService.update(roleUpdateParam) + ) + + /** + * 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 { + roleService.status(roleUpdateStatusParam) + return ResponseResult.databaseSuccess(ResponseCode.DATABASE_UPDATE_SUCCESS) + } + + /** + * 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 { + 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 { + roleService.delete(roleDeleteParam) + return ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS) + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/controller/permission/UserController.kt b/src/main/kotlin/top/fatweb/oxygen/api/controller/permission/UserController.kt new file mode 100644 index 0000000..e7c4490 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/controller/permission/UserController.kt @@ -0,0 +1,217 @@ +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.user.* +import top.fatweb.oxygen.api.service.permission.IUserService +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 management 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 = + ResponseResult.databaseSuccess(data = userService.getInfo()) + + /** + * Get basic user information + * + * @param username Username + * @return Response object includes user basic information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ResponseResult + * @see UserWithPowerInfoVo + */ + @Operation(summary = "获取指定用户基本信息") + @GetMapping("/info/{username}") + fun getBasicInfo(@PathVariable username: String): ResponseResult = + ResponseResult.databaseSuccess(data = userService.getBasicInfo(username)) + + /** + * Update current user information + * + * @param userInfoUpdateParam Update user information parameters + * @return Response object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see UserInfoUpdateParam + * @see ResponseResult + */ + @Operation(summary = "更新当前用户信息") + @PatchMapping("info") + fun updateInfo(@RequestBody @Valid userInfoUpdateParam: UserInfoUpdateParam): ResponseResult = + if (userService.updateInfo(userInfoUpdateParam)) ResponseResult.databaseSuccess(ResponseCode.DATABASE_UPDATE_SUCCESS) + else ResponseResult.databaseSuccess(ResponseCode.DATABASE_UPDATE_FAILED) + + /** + * Change password + * + * @param userChangePasswordParam User change password parameters + * @return Response object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see UserChangePasswordParam + * @see ResponseResult + */ + @Operation(summary = "更改密码") + @PostMapping("info") + fun password(@RequestBody @Valid userChangePasswordParam: UserChangePasswordParam): ResponseResult { + userService.password(userChangePasswordParam) + + return ResponseResult.databaseSuccess(ResponseCode.DATABASE_UPDATE_SUCCESS) + } + + /** + * 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 = + ResponseResult.databaseSuccess(data = userService.getOne(id)) + + /** + * 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> = + 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 = + ResponseResult.databaseSuccess( + ResponseCode.DATABASE_INSERT_SUCCESS, data = userService.add(userAddParam) + ) + + /** + * 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 = + ResponseResult.databaseSuccess( + ResponseCode.DATABASE_UPDATE_SUCCESS, data = userService.update(userUpdateParam) + ) + + /** + * 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 { + 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 { + 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 { + userService.delete(userDeleteParam) + return ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS) + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/controller/system/SettingsController.kt b/src/main/kotlin/top/fatweb/oxygen/api/controller/system/SettingsController.kt new file mode 100644 index 0000000..5d5c28b --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/controller/system/SettingsController.kt @@ -0,0 +1,184 @@ +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.DeleteMapping +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable +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.ResponseCode +import top.fatweb.oxygen.api.entity.common.ResponseResult +import top.fatweb.oxygen.api.param.system.* +import top.fatweb.oxygen.api.service.system.ISensitiveWordService +import top.fatweb.oxygen.api.service.system.ISettingsService +import top.fatweb.oxygen.api.vo.system.BaseSettingsVo +import top.fatweb.oxygen.api.vo.system.MailSettingsVo +import top.fatweb.oxygen.api.vo.system.SensitiveWordVo + +/** + * System settings management controller + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ISettingsService + * @see ISensitiveWordService + */ +@BaseController(path = ["/system/settings"], name = "系统设置", description = "系统设置相关接口") +class SettingsController( + private val settingsService: ISettingsService, + private val sensitiveWordService: ISensitiveWordService +) { + /** + * Get base settings + * + * @return Response object includes base settings information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ResponseResult + * @see BaseSettingsVo + */ + @Operation(summary = "获取基础设置") + @GetMapping("/base") + @PreAuthorize("hasAnyAuthority('system:settings:query:base')") + fun getApp(): ResponseResult = ResponseResult.success(data = settingsService.getBase()) + + /** + * Update base settings + * + * @param baseSettingsParam Base settings parameters + * @return Response object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see BaseSettingsParam + * @see ResponseResult + */ + @Operation(summary = "更新基础设置") + @PutMapping("/base") + @PreAuthorize("hasAnyAuthority('system:settings:modify:base')") + fun updateApp(@RequestBody baseSettingsParam: BaseSettingsParam): ResponseResult { + 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 = 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 { + settingsService.updateMail(mailSettingsParam) + return ResponseResult.success() + } + + /** + * Send mail test + * + * @param mailSendParam Mail send parameters + * @return Response object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see MailSendParam + * @see ResponseResult + */ + @Operation(summary = "邮件发送测试") + @PostMapping("/mail") + @PreAuthorize("hasAnyAuthority('system:settings:modify:mail')") + fun sendMail(@RequestBody @Valid mailSendParam: MailSendParam): ResponseResult { + settingsService.sendMail(mailSendParam) + return ResponseResult.success() + } + + /** + * Get sensitive word settings + * + * @return Response object includes sensitive word settings information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ResponseResult + * @see SensitiveWordVo + */ + @Operation(summary = "获取敏感词配置") + @GetMapping("/sensitive") + @PreAuthorize("hasAnyAuthority('system:settings:query:sensitive')") + fun getSensitive(): ResponseResult> = + ResponseResult.databaseSuccess(ResponseCode.DATABASE_SELECT_SUCCESS, data = sensitiveWordService.get()) + + /** + * Add sensitive word + * + * @param sensitiveWordAddParam Add sensitive word settings parameters + * @return Response object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see SensitiveWordAddParam + * @see ResponseResult + */ + @Operation(summary = "添加敏感词") + @PostMapping("/sensitive") + @PreAuthorize("hasAnyAuthority('system:settings:modify:sensitive')") + fun addSensitive(@RequestBody @Valid sensitiveWordAddParam: SensitiveWordAddParam): ResponseResult { + sensitiveWordService.add(sensitiveWordAddParam) + return ResponseResult.databaseSuccess(ResponseCode.DATABASE_INSERT_SUCCESS) + } + + /** + * Update sensitive word + * + * @param sensitiveWordUpdateParam Update sensitive word settings parameters + * @return Response object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see SensitiveWordUpdateParam + * @see ResponseResult + */ + @Operation(summary = "修改敏感词") + @PutMapping("/sensitive") + @PreAuthorize("hasAnyAuthority('system:settings:modify:sensitive')") + fun updateSensitive(@RequestBody sensitiveWordUpdateParam: SensitiveWordUpdateParam): ResponseResult { + sensitiveWordService.update(sensitiveWordUpdateParam) + return ResponseResult.databaseSuccess(ResponseCode.DATABASE_UPDATE_SUCCESS) + } + + /** + * Delete sensitive word + * + * @see id Sensitive word ID + * @return Response object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ResponseResult + */ + @Operation(summary = "删除敏感词") + @DeleteMapping("/sensitive/{id}") + @PreAuthorize("hasAnyAuthority('system:settings:modify:sensitive')") + fun deleteSensitive(@PathVariable id: Long): ResponseResult { + sensitiveWordService.delete(id) + return ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS) + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/controller/system/StatisticsController.kt b/src/main/kotlin/top/fatweb/oxygen/api/controller/system/StatisticsController.kt new file mode 100644 index 0000000..a04d961 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/controller/system/StatisticsController.kt @@ -0,0 +1,113 @@ +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 management 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 = 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 = 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 = 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 = ResponseResult.success(data = statisticService.storage()) + + /** + * Get the history of online users information + * + * @param onlineInfoGetParam Get online information parameters + * @return Response object includes online user information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see OnlineInfoGetParam + * @see ResponseResult + * @see OnlineInfoVo + */ + @Operation(summary = "获取在线用户数量信息") + @GetMapping("/online") + @PreAuthorize("hasAnyAuthority('system:statistics:query:usage')") + fun online(onlineInfoGetParam: OnlineInfoGetParam?): ResponseResult = + ResponseResult.success(data = statisticService.online(onlineInfoGetParam)) + + /** + * Get the history of active information + * + * @param activeInfoGetParam Get active information parameters + * @return Response object includes history of active information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ActiveInfoGetParam + * @see ResponseResult + * @see ActiveInfoVo + */ + @Operation(summary = "获取用户活跃信息") + @GetMapping("/active") + @PreAuthorize("hasAnyAuthority('system:statistics:query:usage')") + fun active(activeInfoGetParam: ActiveInfoGetParam): ResponseResult = + ResponseResult.success(data = statisticService.active(activeInfoGetParam)) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/controller/system/SysLogController.kt b/src/main/kotlin/top/fatweb/oxygen/api/controller/system/SysLogController.kt new file mode 100644 index 0000000..09c76e7 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/controller/system/SysLogController.kt @@ -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 viewer 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 in page + * + * @param sysLogGetParam Get system log parameters + * @return Response object includes system log in page + * @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> { + return ResponseResult.success( + ResponseCode.DATABASE_SELECT_SUCCESS, data = sysLogService.getPage(sysLogGetParam) + ) + } +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/controller/tool/BaseController.kt b/src/main/kotlin/top/fatweb/oxygen/api/controller/tool/BaseController.kt new file mode 100644 index 0000000..f682fd3 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/controller/tool/BaseController.kt @@ -0,0 +1,112 @@ +package top.fatweb.oxygen.api.controller.tool + +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.tool.ToolBaseAddParam +import top.fatweb.oxygen.api.param.tool.ToolBaseUpdateParam +import top.fatweb.oxygen.api.service.tool.IToolBaseService +import top.fatweb.oxygen.api.vo.tool.ToolBaseVo + +/** + * Tool base management controller + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IToolBaseService + */ +@BaseController(path = ["/system/tool/base"], name = "工具基板管理", description = "工具基板管理相关接口") +class BaseController( + private val toolBaseService: IToolBaseService +) { + /** + * Get tool base by ID + * + * @param id Tool base ID + * @return Response object includes tool base information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ResponseResult + * @see ToolBaseVo + */ + @Operation(summary = "获取单个基板") + @GetMapping("/{id}") + @PreAuthorize("hasAnyAuthority('system:tool:query:base')") + fun getOne(@PathVariable id: Long): ResponseResult = + ResponseResult.databaseSuccess(data = toolBaseService.getOne(id)) + + /** + * Get tool base list + * + * @return Response object includes tool base list + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ResponseResult + * @see ToolBaseVo + */ + @Operation(summary = "获取基板") + @GetMapping + @PreAuthorize("hasAnyAuthority('system:tool:query:base', 'system:tool:add:template', 'system:tool:modify:template')") + fun get(): ResponseResult> = + ResponseResult.databaseSuccess(data = toolBaseService.get()) + + /** + * Add tool base + * + * @param toolBaseAddParam Add tool base parameters + * @return Response object includes tool base information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolBaseAddParam + * @see ResponseResult + * @see ToolBaseVo + */ + @Operation(summary = "新增基板") + @PostMapping + @PreAuthorize("hasAnyAuthority('system:tool:add:base')") + fun add(@RequestBody @Valid toolBaseAddParam: ToolBaseAddParam): ResponseResult = + ResponseResult.databaseSuccess( + ResponseCode.DATABASE_INSERT_SUCCESS, + data = toolBaseService.add(toolBaseAddParam) + ) + + /** + * Update tool base + * + * @param toolBaseUpdateParam Update tool base parameters + * @return Response object includes tool base information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolBaseUpdateParam + * @see ResponseResult + * @see ToolBaseVo + */ + @Operation(summary = "更新基板") + @PutMapping + @PreAuthorize("hasAnyAuthority('system:tool:modify:base')") + fun update(@RequestBody @Valid toolBaseUpdateParam: ToolBaseUpdateParam): ResponseResult = + ResponseResult.databaseSuccess( + ResponseCode.DATABASE_UPDATE_SUCCESS, + data = toolBaseService.update(toolBaseUpdateParam) + ) + + /** + * Delete tool base by ID + * + * @param id Tool base ID + * @return Response object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ResponseResult + */ + @Operation(summary = "删除基板") + @DeleteMapping("/{id}") + @PreAuthorize("hasAnyAuthority('system:tool:delete:base')") + fun delete(@PathVariable id: Long): ResponseResult = + if (toolBaseService.delete(id)) ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS) + else ResponseResult.databaseFail(ResponseCode.DATABASE_DELETE_FAILED) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/controller/tool/CategoryController.kt b/src/main/kotlin/top/fatweb/oxygen/api/controller/tool/CategoryController.kt new file mode 100644 index 0000000..1872a39 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/controller/tool/CategoryController.kt @@ -0,0 +1,112 @@ +package top.fatweb.oxygen.api.controller.tool + +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.tool.ToolCategoryAddParam +import top.fatweb.oxygen.api.param.tool.ToolCategoryUpdateParam +import top.fatweb.oxygen.api.service.tool.IToolCategoryService +import top.fatweb.oxygen.api.vo.tool.ToolCategoryVo + +/** + * Tool category management controller + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IToolCategoryService + */ +@BaseController(path = ["/system/tool/category"], name = "工具类别管理", description = "工具列别管理相关接口") +class CategoryController( + private val toolCategoryService: IToolCategoryService +) { + /** + * Get tool category by ID + * + * @param id Tool category ID + * @return Response object includes tool template information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ResponseResult + * @see ToolCategoryVo + */ + @Operation(summary = "获取单个类别") + @GetMapping("/{id}") + @PreAuthorize("hasAnyAuthority('system:tool:query:category')") + fun getOne(@PathVariable id: Long): ResponseResult = + ResponseResult.databaseSuccess(data = toolCategoryService.getOne(id)) + + /** + * Get tool category list + * + * @return Response object includes tool template list + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ResponseResult + * @see ToolCategoryVo + */ + @Operation(summary = "获取类别") + @GetMapping + @PreAuthorize("hasAnyAuthority('system:tool:query:category')") + fun get(): ResponseResult> = + ResponseResult.databaseSuccess(data = toolCategoryService.get()) + + /** + * Add tool category + * + * @param toolCategoryAddParam Add tool category parameters + * @return Response object includes tool category information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolCategoryAddParam + * @see ResponseResult + * @see ToolCategoryVo + */ + @Operation(summary = "新增类别") + @PostMapping + @PreAuthorize("hasAnyAuthority('system:tool:add:category')") + fun add(@RequestBody @Valid toolCategoryAddParam: ToolCategoryAddParam): ResponseResult = + ResponseResult.databaseSuccess( + ResponseCode.DATABASE_INSERT_SUCCESS, + data = toolCategoryService.add(toolCategoryAddParam) + ) + + /** + * Update tool category + * + * @param toolCategoryUpdateParam Update tool category parameters + * @return Response object includes tool category information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolCategoryUpdateParam + * @see ResponseResult + * @see ToolCategoryVo + */ + @Operation(summary = "更新类别") + @PutMapping + @PreAuthorize("hasAnyAuthority('system:tool:modify:category')") + fun update(@RequestBody @Valid toolCategoryUpdateParam: ToolCategoryUpdateParam): ResponseResult = + ResponseResult.databaseSuccess( + ResponseCode.DATABASE_UPDATE_SUCCESS, + data = toolCategoryService.update(toolCategoryUpdateParam) + ) + + /** + * Delete tool category + * + * @param id Tool category ID + * @return Response object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ResponseResult + */ + @Operation(summary = "删除类别") + @DeleteMapping("/{id}") + @PreAuthorize("hasAnyAuthority('system:tool:delete:category')") + fun delete(@PathVariable id: Long): ResponseResult = + if (toolCategoryService.delete(id)) ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS) + else ResponseResult.databaseFail(ResponseCode.DATABASE_DELETE_FAILED) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/controller/tool/EditController.kt b/src/main/kotlin/top/fatweb/oxygen/api/controller/tool/EditController.kt new file mode 100644 index 0000000..2e4863e --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/controller/tool/EditController.kt @@ -0,0 +1,204 @@ +package top.fatweb.oxygen.api.controller.tool + +import io.swagger.v3.oas.annotations.Operation +import jakarta.validation.Valid +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.tool.ToolCreateParam +import top.fatweb.oxygen.api.param.tool.ToolUpdateParam +import top.fatweb.oxygen.api.param.tool.ToolUpgradeParam +import top.fatweb.oxygen.api.service.tool.IEditService +import top.fatweb.oxygen.api.vo.tool.ToolCategoryVo +import top.fatweb.oxygen.api.vo.tool.ToolTemplateVo +import top.fatweb.oxygen.api.vo.tool.ToolVo + +/** + * Tool edit controller + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IEditService + */ +@BaseController(path = ["/tool"], name = "工具编辑", description = "工具编辑相关接口") +class EditController( + private val editService: IEditService +) { + /** + * Get tool template list + * + * @return Response object includes tool template list + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ResponseResult + * @see ToolTemplateVo + */ + @Operation(summary = "获取模板") + @GetMapping("/template") + fun getTemplate(): ResponseResult> = + ResponseResult.databaseSuccess(data = editService.getTemplate()) + + /** + * Get tool template by ID + * + * @param id ID + * @return Response object includes tool template information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ResponseResult + * @see ToolTemplateVo + */ + @Operation(summary = "获取单个模板") + @GetMapping("/template/{id}") + fun getTemplate(@PathVariable id: Long): ResponseResult = + ResponseResult.databaseSuccess(data = editService.getTemplate(id)) + + /** + * Get tool category list + * + * @return Response object includes tool category list + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ResponseResult + * @see ToolCategoryVo + */ + @Operation(summary = "获取类别") + @GetMapping("/category") + fun getCategory(): ResponseResult> = + ResponseResult.databaseSuccess(data = editService.getCategory()) + + /** + * Create tool + * + * @param toolCreateParam Create tool parameters + * @return Response object includes tool information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolCreateParam + * @see ResponseResult + * @see ToolVo + */ + @Operation(summary = "创建工具") + @PostMapping + fun create(@RequestBody @Valid toolCreateParam: ToolCreateParam): ResponseResult = + ResponseResult.databaseSuccess(ResponseCode.DATABASE_INSERT_SUCCESS, data = editService.create(toolCreateParam)) + + /** + * Upgrade tool + * + * @param toolUpgradeParam Upgrade tool parameters + * @return Response object includes tool information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolUpgradeParam + * @see ResponseResult + * @see ToolVo + */ + @Operation(summary = "升级工具") + @PatchMapping + fun upgrade(@RequestBody @Valid toolUpgradeParam: ToolUpgradeParam): ResponseResult = + ResponseResult.databaseSuccess( + ResponseCode.DATABASE_UPDATE_SUCCESS, + data = editService.upgrade(toolUpgradeParam) + ) + + /** + * Get personal tool + * + * @return Response object includes tool list + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ResponseResult + * @see ToolVo + */ + @Operation(summary = "获取个人工具") + @GetMapping + fun get(): ResponseResult> = + ResponseResult.databaseSuccess(ResponseCode.DATABASE_SELECT_SUCCESS, data = editService.get()) + + /** + * Get tool detail + * + * @param username Username + * @param toolId Tool ID + * @param ver Version + * @return Response object includes tool information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ResponseResult + * @see ToolVo + */ + @Operation(summary = "获取工具内容") + @GetMapping("/detail/{username}/{toolId}/{ver}") + fun detail( + @PathVariable username: String, + @PathVariable toolId: String, + @PathVariable ver: String + ): ResponseResult = + ResponseResult.databaseSuccess( + ResponseCode.DATABASE_SELECT_SUCCESS, + data = editService.detail(username, toolId, ver) + ) + + /** + * Update tool + * + * @param toolUpdateParam Update tool parameters + * @return Response object includes tool information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolUpdateParam + * @see ResponseResult + * @see ToolVo + */ + @Operation(summary = "更新工具") + @PutMapping + fun update(@RequestBody @Valid toolUpdateParam: ToolUpdateParam): ResponseResult = + ResponseResult.databaseSuccess(ResponseCode.DATABASE_UPDATE_SUCCESS, data = editService.update(toolUpdateParam)) + + /** + * Submit tool review + * + * @param id Tool ID + * @return Response object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ResponseResult + */ + @Operation(summary = "提交工具审核") + @PostMapping("/{id}") + fun submit(@PathVariable id: Long): ResponseResult = + if (editService.submit(id)) ResponseResult.success(ResponseCode.TOOL_SUBMIT_SUCCESS) + else ResponseResult.fail(ResponseCode.TOOL_SUBMIT_ERROR) + + /** + * Cancel tool review + * + * @param id Tool ID + * @return Response object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ResponseResult + */ + @Operation(summary = "取消工具审核") + @PutMapping("/{id}") + fun cancel(@PathVariable id: Long): ResponseResult = + if (editService.cancel(id)) ResponseResult.success(ResponseCode.TOOL_CANCEL_SUCCESS) + else ResponseResult.fail(ResponseCode.TOOL_CANCEL_ERROR) + + /** + * Delete tool + * + * @param id Tool ID + * @return Response object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ResponseResult + */ + @Operation(summary = "删除工具") + @DeleteMapping("/{id}") + fun delete(@PathVariable id: Long): ResponseResult = + if (editService.delete(id)) ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS) + else ResponseResult.databaseFail(ResponseCode.DATABASE_DELETE_FAILED) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/controller/tool/ManagementController.kt b/src/main/kotlin/top/fatweb/oxygen/api/controller/tool/ManagementController.kt new file mode 100644 index 0000000..9bdff74 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/controller/tool/ManagementController.kt @@ -0,0 +1,132 @@ +package top.fatweb.oxygen.api.controller.tool + +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.tool.ToolManagementGetParam +import top.fatweb.oxygen.api.param.tool.ToolManagementPassParam +import top.fatweb.oxygen.api.service.tool.IManagementService +import top.fatweb.oxygen.api.vo.PageVo +import top.fatweb.oxygen.api.vo.tool.ToolVo + +/** + * Tool management controller + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IManagementService + */ +@BaseController(path = ["/system/tool"], name = "工具管理", description = "工具管理相关接口") +class ManagementController( + private val managementService: IManagementService +) { + /** + * Get tool by ID + * + * @param id Tool ID + * @return Response object includes tool information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ResponseResult + * @see ToolVo + */ + @Operation(summary = "获取单个工具") + @GetMapping("/{id}") + @PreAuthorize("hasAnyAuthority('system:tool:query:tool')") + fun getOne(@PathVariable id: Long): ResponseResult = + ResponseResult.databaseSuccess(data = managementService.getOne(id)) + + /** + * Get tool paging information + * + * @param toolManagementGetParam Get tool parameters in tool management + * @return Response object includes tool paging information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolManagementGetParam + * @see ResponseResult + * @see PageVo + * @see ToolVo + */ + @Operation(summary = "获取工具") + @GetMapping + @PreAuthorize("hasAnyAuthority('system:tool:query:tool')") + fun get(toolManagementGetParam: ToolManagementGetParam): ResponseResult> = + ResponseResult.databaseSuccess(data = managementService.getPage(toolManagementGetParam)) + + /** + * Pass tool review + * + * @param id Tool ID + * @param toolManagementPassParam Pass tool parameters in tool management + * @return Response object includes tool information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolManagementPassParam + * @see ResponseResult + * @see ToolVo + */ + @Operation(summary = "通过审核") + @PostMapping("/{id}") + @PreAuthorize("hasAnyAuthority('system:tool:modify:tool')") + fun pass( + @PathVariable id: Long, + @RequestBody @Valid toolManagementPassParam: ToolManagementPassParam + ): ResponseResult = + ResponseResult.databaseSuccess( + ResponseCode.DATABASE_UPDATE_SUCCESS, + data = managementService.pass(id, toolManagementPassParam) + ) + + /** + * Reject tool review + * + * @param id Tool ID + * @return Response object includes tool information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ResponseResult + * @see ToolVo + */ + @Operation(summary = "驳回审核") + @PutMapping("/{id}") + @PreAuthorize("hasAnyAuthority('system:tool:modify:tool')") + fun reject(@PathVariable id: Long): ResponseResult = + ResponseResult.databaseSuccess(ResponseCode.DATABASE_UPDATE_SUCCESS, data = managementService.reject(id)) + + /** + * Put off shelve + * + * @param id Tool ID + * @return Response object includes tool information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ResponseResult + * @see ToolVo + */ + @Operation(summary = "下架") + @PatchMapping("/{id}") + @PreAuthorize("hasAnyAuthority('system:tool:modify:tool')") + fun offShelve(@PathVariable id: Long): ResponseResult = + ResponseResult.databaseSuccess(ResponseCode.DATABASE_UPDATE_SUCCESS, data = managementService.offShelve(id)) + + /** + * Delete tool + * + * @param id Tool ID + * @return Response object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ResponseResult + */ + @Operation(summary = "删除工具") + @DeleteMapping("/{id}") + @PreAuthorize("hasAnyAuthority('system:tool:delete:tool')") + fun delete(@PathVariable id: Long): ResponseResult = + if (managementService.delete(id)) ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS) + else ResponseResult.databaseFail(ResponseCode.DATABASE_DELETE_FAILED) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/controller/tool/StoreController.kt b/src/main/kotlin/top/fatweb/oxygen/api/controller/tool/StoreController.kt new file mode 100644 index 0000000..3c18850 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/controller/tool/StoreController.kt @@ -0,0 +1,57 @@ +package top.fatweb.oxygen.api.controller.tool + +import jakarta.validation.Valid +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PathVariable +import top.fatweb.oxygen.api.annotation.BaseController +import top.fatweb.oxygen.api.entity.common.ResponseResult +import top.fatweb.oxygen.api.param.PageSortParam +import top.fatweb.oxygen.api.param.tool.ToolStoreGetParam +import top.fatweb.oxygen.api.service.tool.IStoreService +import top.fatweb.oxygen.api.vo.PageVo +import top.fatweb.oxygen.api.vo.tool.ToolVo + +/** + * Tool store controller + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IStoreService + */ +@BaseController(path = ["/tool/store"], name = "工具商店", description = "工具商店相关接口") +class StoreController( + private val storeService: IStoreService +) { + /** + * Get store tool paging information + * + * @param toolStoreGetParam Get tool parameters in tool store + * @return Response object includes store tool paging information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolStoreGetParam + * @see ResponseResult + * @see PageVo + * @see ToolVo + */ + @GetMapping + fun get(@Valid toolStoreGetParam: ToolStoreGetParam): ResponseResult> = + ResponseResult.databaseSuccess(data = storeService.getPage(toolStoreGetParam)) + + /** + * Get store tool paging information by username + * + * @param username Username + * @param pageSortParam Page sort parameters + * @return Response object includes store tool paging information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see PageSortParam + * @see ResponseResult + * @see PageVo + * @see ToolVo + */ + @GetMapping("/{username}") + fun get(@PathVariable username: String, @Valid pageSortParam: PageSortParam): ResponseResult> = + ResponseResult.databaseSuccess(data = storeService.getPage(pageSortParam, username)) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/controller/tool/TemplateController.kt b/src/main/kotlin/top/fatweb/oxygen/api/controller/tool/TemplateController.kt new file mode 100644 index 0000000..ab7fe7e --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/controller/tool/TemplateController.kt @@ -0,0 +1,112 @@ +package top.fatweb.oxygen.api.controller.tool + +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.tool.ToolTemplateAddParam +import top.fatweb.oxygen.api.param.tool.ToolTemplateUpdateParam +import top.fatweb.oxygen.api.service.tool.IToolTemplateService +import top.fatweb.oxygen.api.vo.tool.ToolTemplateVo + +/** + * Tool template management controller + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IToolTemplateService + */ +@BaseController(path = ["/system/tool/template"], name = "工具模板管理", description = "工具模板管理相关接口") +class TemplateController( + private val toolTemplateService: IToolTemplateService +) { + /** + * Get tool template by ID + * + * @param id Tool template ID + * @return Response object includes tool template information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ResponseResult + * @see ToolTemplateVo + */ + @Operation(summary = "获取单个模板") + @GetMapping("/{id}") + @PreAuthorize("hasAnyAuthority('system:tool:query:template')") + fun getOne(@PathVariable id: Long): ResponseResult = + ResponseResult.databaseSuccess(data = toolTemplateService.getOne(id)) + + /** + * Get tool template list + * + * @return Response object includes tool template list + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ResponseResult + * @see ToolTemplateVo + */ + @Operation(summary = "获取模板") + @GetMapping + @PreAuthorize("hasAnyAuthority('system:tool:query:template')") + fun get(): ResponseResult> = + ResponseResult.databaseSuccess(data = toolTemplateService.get()) + + /** + * Add tool template + * + * @param toolTemplateAddParam Add tool template parameters + * @return Response object includes tool template information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolTemplateAddParam + * @see ResponseResult + * @see ToolTemplateVo + */ + @Operation(summary = "添加模板") + @PostMapping + @PreAuthorize("hasAnyAuthority('system:tool:add:template')") + fun add(@RequestBody @Valid toolTemplateAddParam: ToolTemplateAddParam): ResponseResult = + ResponseResult.databaseSuccess( + ResponseCode.DATABASE_INSERT_SUCCESS, + data = toolTemplateService.add(toolTemplateAddParam) + ) + + /** + * Update tool template + * + * @param toolTemplateUpdateParam Update tool template parameters + * @return Response object includes tool template information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolTemplateUpdateParam + * @see ResponseResult + * @see ToolTemplateVo + */ + @Operation(summary = "更新模板") + @PutMapping + @PreAuthorize("hasAnyAuthority('system:tool:modify:template')") + fun update(@RequestBody @Valid toolTemplateUpdateParam: ToolTemplateUpdateParam): ResponseResult = + ResponseResult.databaseSuccess( + ResponseCode.DATABASE_UPDATE_SUCCESS, + data = toolTemplateService.update(toolTemplateUpdateParam) + ) + + /** + * Delete tool template + * + * @param id Tool template ID + * @return Response object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ResponseResult + */ + @Operation(summary = "删除模板") + @DeleteMapping("/{id}") + @PreAuthorize("hasAnyAuthority('system:tool:delete:template')") + fun delete(@PathVariable id: Long): ResponseResult = + if (toolTemplateService.delete(id)) ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS) + else ResponseResult.databaseFail(ResponseCode.DATABASE_DELETE_FAILED) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/FuncConverter.kt b/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/FuncConverter.kt new file mode 100644 index 0000000..ed5c227 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/FuncConverter.kt @@ -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 + ) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/GroupConverter.kt b/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/GroupConverter.kt new file mode 100644 index 0000000..28cbbd6 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/GroupConverter.kt @@ -0,0 +1,124 @@ +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) + ) + + /** + * Convert IPage object into PageVo object + * + * @param groupPage IPage object + * @return PageVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IPage + * @see Group + * @see PageVo + * @see GroupWithRoleVo + */ + fun groupPageToGroupWithRolePageVo(groupPage: IPage) = PageVo( + total = groupPage.total, + pages = groupPage.pages, + size = groupPage.size, + current = groupPage.current, + records = groupPage.records.map(::groupToGroupWithRoleVo) + ) + + /** + * 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 + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/MenuConverter.kt b/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/MenuConverter.kt new file mode 100644 index 0000000..ef573d1 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/MenuConverter.kt @@ -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 + ) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/ModuleConverter.kt b/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/ModuleConverter.kt new file mode 100644 index 0000000..4760c51 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/ModuleConverter.kt @@ -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 + ) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/OperationConverter.kt b/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/OperationConverter.kt new file mode 100644 index 0000000..dd9f0b3 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/OperationConverter.kt @@ -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 + ) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/PowerConverter.kt b/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/PowerConverter.kt new file mode 100644 index 0000000..5fea079 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/PowerConverter.kt @@ -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), + menuList = powerSet.menuList?.map(MenuConverter::menuToMenuVo), + funcList = powerSet.funcList?.map(FuncConverter::funcToFuncVo), + operationList = powerSet.operationList?.map(OperationConverter::operationToOperationVo) + ) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/RoleConverter.kt b/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/RoleConverter.kt new file mode 100644 index 0000000..98f7375 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/RoleConverter.kt @@ -0,0 +1,127 @@ +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), + menus = role.menus?.map(MenuConverter::menuToMenuVo), + funcs = role.funcs?.map(FuncConverter::funcToFuncVo), + operations = role.operations?.map(OperationConverter::operationToOperationVo) + ) + + /** + * Convert IPage object into PageVo object + * + * @param rolePage IPage object + * @return PageVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IPage + * @see Role + * @see PageVo + * @see RoleWithPowerVo + */ + fun rolePageToRoleWithPowerPageVo(rolePage: IPage) = PageVo( + total = rolePage.total, + pages = rolePage.pages, + size = rolePage.size, + current = rolePage.current, + records = rolePage.records.map(::roleToRoleWithPowerVo) + ) + + /** + * 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 + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/UserConverter.kt b/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/UserConverter.kt new file mode 100644 index 0000000..9f299b7 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/UserConverter.kt @@ -0,0 +1,213 @@ +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), + modules = user.modules?.map(ModuleConverter::moduleToModuleVo), + menus = user.menus?.map(MenuConverter::menuToMenuVo), + funcs = user.funcs?.map(FuncConverter::funcToFuncVo), + operations = user.operations?.map(OperationConverter::operationToOperationVo) + ) + + /** + * 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), + roles = user.roles?.map(RoleConverter::roleToRoleVo), + groups = user.groups?.map(GroupConverter::groupToGroupVo) + ) + + /** + * 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) + ) + + /** + * 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), + roles = user.roles?.map(RoleConverter::roleToRoleVo), + groups = user.groups?.map(GroupConverter::groupToGroupVo) + ) + + /** + * 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 object into PageVo object + * + * @param userPage IPage object + * @return PageVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IPage + * @see User + * @see PageVo + * @see UserWithRoleInfoVo + */ + fun userPageToUserWithRoleInfoPageVo(userPage: IPage) = PageVo( + total = userPage.total, + pages = userPage.pages, + size = userPage.size, + current = userPage.current, + records = userPage.records.map(::userToUserWithRoleInfoVo) + ) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/UserInfoConverter.kt b/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/UserInfoConverter.kt new file mode 100644 index 0000000..89bf651 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/converter/permission/UserInfoConverter.kt @@ -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 + ) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/converter/system/SettingsConverter.kt b/src/main/kotlin/top/fatweb/oxygen/api/converter/system/SettingsConverter.kt new file mode 100644 index 0000000..2d7f717 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/converter/system/SettingsConverter.kt @@ -0,0 +1,46 @@ +package top.fatweb.oxygen.api.converter.system + +import top.fatweb.oxygen.api.entity.system.SensitiveWord +import top.fatweb.oxygen.api.param.system.SensitiveWordAddParam +import top.fatweb.oxygen.api.vo.system.SensitiveWordVo + +/** + * Settings converter + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +object SettingsConverter { + /** + * Convert SensitiveWord object into SensitiveWordVo object + * + * @param sensitiveWord SensitiveWord object + * @return SensitiveWordVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see SensitiveWord + * @see SensitiveWordVo + */ + fun sensitiveWordToSensitiveWordVo(sensitiveWord: SensitiveWord) = SensitiveWordVo( + id = sensitiveWord.id, + word = sensitiveWord.word, + useFor = sensitiveWord.useFor?.map(SensitiveWord.Use::valueOf)?.toSet(), + enable = sensitiveWord.enable == 1 + ) + + /** + * Convert SensitiveWordAddParam object into SensitiveWord object + * + * @param sensitiveWordAddParam SensitiveWordAddParam object + * @return SensitiveWord object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see SensitiveWordAddParam + * @see SensitiveWord + */ + fun sensitiveWordAddParamToSensitiveWord(sensitiveWordAddParam: SensitiveWordAddParam) = SensitiveWord().apply { + word = sensitiveWordAddParam.word + useFor = sensitiveWordAddParam.useFor.map(SensitiveWord.Use::code).toSet() + enable = if (sensitiveWordAddParam.enable) 1 else 0 + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/converter/system/SysLogConverter.kt b/src/main/kotlin/top/fatweb/oxygen/api/converter/system/SysLogConverter.kt new file mode 100644 index 0000000..d94bd90 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/converter/system/SysLogConverter.kt @@ -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 object into PageVo object + * + * @param syslogPage IPage object + * @return PageVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IPage + * @see SysLog + * @see PageVo + * @see SysLogVo + */ + fun sysLogPageToSysLogPageVo(syslogPage: IPage) = 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 + ) + }) + +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/converter/tool/ToolBaseConverter.kt b/src/main/kotlin/top/fatweb/oxygen/api/converter/tool/ToolBaseConverter.kt new file mode 100644 index 0000000..1877c39 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/converter/tool/ToolBaseConverter.kt @@ -0,0 +1,53 @@ +package top.fatweb.oxygen.api.converter.tool + +import top.fatweb.oxygen.api.entity.tool.ToolBase +import top.fatweb.oxygen.api.vo.tool.ToolBaseVo +import top.fatweb.oxygen.api.vo.tool.ToolDataVo + +/** + * Tool base converter + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +object ToolBaseConverter { + /** + * Convert ToolBase object into ToolBaseVo object + * + * @param toolBase ToolBase object + * @return ToolBaseVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolBase + * @see ToolBaseVo + */ + fun toolBaseToToolBaseVo(toolBase: ToolBase) = ToolBaseVo( + id = toolBase.id, + name = toolBase.name, + source = toolBase.source?.let(ToolDataConverter::toolDataToToolDataVo), + dist = toolBase.dist?.let(ToolDataConverter::toolDataToToolDataVo), + compiled = toolBase.compiled == 1, + createTime = toolBase.createTime, + updateTime = toolBase.updateTime + ) + + /** + * Convert ToolBase object into ToolBaseVo object by get list + * + * @param toolBase ToolBase object + * @return ToolBaseVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolBase + * @see ToolBaseVo + */ + fun toolBaseToToolBaseVoByGetList(toolBase: ToolBase) = ToolBaseVo( + id = toolBase.id, + name = toolBase.name, + source = ToolDataVo(id = toolBase.sourceId, data = null, createTime = null, updateTime = null), + dist = ToolDataVo(id = toolBase.distId, data = null, createTime = null, updateTime = null), + compiled = toolBase.compiled == 1, + createTime = toolBase.createTime, + updateTime = toolBase.updateTime + ) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/converter/tool/ToolCategoryConverter.kt b/src/main/kotlin/top/fatweb/oxygen/api/converter/tool/ToolCategoryConverter.kt new file mode 100644 index 0000000..f01feb8 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/converter/tool/ToolCategoryConverter.kt @@ -0,0 +1,63 @@ +package top.fatweb.oxygen.api.converter.tool + +import top.fatweb.oxygen.api.entity.tool.ToolCategory +import top.fatweb.oxygen.api.param.tool.ToolCategoryAddParam +import top.fatweb.oxygen.api.param.tool.ToolCategoryUpdateParam +import top.fatweb.oxygen.api.vo.tool.ToolCategoryVo + +/** + * Tool category converter + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +object ToolCategoryConverter { + /** + * Convert ToolCategory object into ToolCategoryVo object + * + * @param toolCategory ToolCategory object + * @return ToolCategoryVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolCategory + * @see ToolCategoryVo + */ + fun toolCategoryToToolCategoryVo(toolCategory: ToolCategory) = ToolCategoryVo( + id = toolCategory.id, + name = toolCategory.name, + enable = toolCategory.enable == 1, + createTime = toolCategory.createTime, + updateTime = toolCategory.updateTime + ) + + /** + * Convert ToolCategoryAddParam object into ToolCategory object + * + * @param toolCategoryAddParam ToolCategoryAddParam object + * @return ToolCateGory object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolCategoryAddParam + * @see ToolCategory + */ + fun toolCategoryAddParamToToolCategory(toolCategoryAddParam: ToolCategoryAddParam) = ToolCategory().apply { + name = toolCategoryAddParam.name + enable = if (toolCategoryAddParam.enable) 1 else 0 + } + + /** + * Convert ToolCategoryUpdateParam object into ToolCategory object + * + * @param toolCategoryUpdateParam ToolCategoryUpdateParam object + * @return ToolCategory object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolCategoryUpdateParam + * @see ToolCategory + */ + fun toolCategoryUpdateParamToToolCategory(toolCategoryUpdateParam: ToolCategoryUpdateParam) = ToolCategory().apply { + id = toolCategoryUpdateParam.id + name = toolCategoryUpdateParam.name + enable = toolCategoryUpdateParam.enable?. let { if (it) 1 else 0 } + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/converter/tool/ToolConverter.kt b/src/main/kotlin/top/fatweb/oxygen/api/converter/tool/ToolConverter.kt new file mode 100644 index 0000000..b07c8bc --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/converter/tool/ToolConverter.kt @@ -0,0 +1,65 @@ +package top.fatweb.oxygen.api.converter.tool + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page +import top.fatweb.oxygen.api.converter.permission.UserConverter +import top.fatweb.oxygen.api.entity.tool.Tool +import top.fatweb.oxygen.api.vo.PageVo +import top.fatweb.oxygen.api.vo.tool.ToolVo + +/** + * Tool converter + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +object ToolConverter { + /** + * Convert Tool object into ToolVo object + * + * @param tool Tool object + * @return ToolVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see Tool + * @see ToolVo + */ + fun toolToToolVo(tool: Tool) = ToolVo( + id = tool.id, + name = tool.name, + toolId = tool.toolId, + icon = tool.icon, + description = tool.description, + base = tool.base?.let(ToolBaseConverter::toolBaseToToolBaseVo), + author = tool.author?.let(UserConverter::userToUserWithInfoVo), + ver = tool.ver, + keywords = tool.keywords, + categories = tool.categories?.map(ToolCategoryConverter::toolCategoryToToolCategoryVo), + source = tool.source?.let(ToolDataConverter::toolDataToToolDataVo), + dist = tool.dist?.let(ToolDataConverter::toolDataToToolDataVo), + entryPoint = tool.entryPoint, + publish = tool.publish, + review = tool.review, + createTime = tool.createTime, + updateTime = tool.updateTime + ) + + /** + * Convert Page object into PageVo object + * + * @param toolPage Page object + * @return PageVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see Page + * @see Tool + * @see PageVo + * @see ToolVo + */ + fun toolPageToToolPageVo(toolPage: Page): PageVo = PageVo( + total = toolPage.total, + pages = toolPage.pages, + size = toolPage.size, + current = toolPage.current, + records = toolPage.records.map(::toolToToolVo) + ) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/converter/tool/ToolDataConverter.kt b/src/main/kotlin/top/fatweb/oxygen/api/converter/tool/ToolDataConverter.kt new file mode 100644 index 0000000..117752d --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/converter/tool/ToolDataConverter.kt @@ -0,0 +1,29 @@ +package top.fatweb.oxygen.api.converter.tool + +import top.fatweb.oxygen.api.entity.tool.ToolData +import top.fatweb.oxygen.api.vo.tool.ToolDataVo + +/** + * Tool data converter + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +object ToolDataConverter { + /** + * Convert ToolData object into ToolDataVo object + * + * @param toolData ToolData object + * @return ToolDataVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolData + * @see ToolDataVo + */ + fun toolDataToToolDataVo(toolData: ToolData) = ToolDataVo( + id = toolData.id, + data = toolData.data, + createTime = toolData.createTime, + updateTime = toolData.updateTime + ) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/converter/tool/ToolTemplateConverter.kt b/src/main/kotlin/top/fatweb/oxygen/api/converter/tool/ToolTemplateConverter.kt new file mode 100644 index 0000000..e3243ce --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/converter/tool/ToolTemplateConverter.kt @@ -0,0 +1,85 @@ +package top.fatweb.oxygen.api.converter.tool + +import top.fatweb.oxygen.api.entity.tool.ToolTemplate +import top.fatweb.oxygen.api.vo.tool.ToolBaseVo +import top.fatweb.oxygen.api.vo.tool.ToolDataVo +import top.fatweb.oxygen.api.vo.tool.ToolTemplateVo + +/** + * Tool template converter + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +object ToolTemplateConverter { + /** + * Convert ToolTemplate object into ToolTemplateVo object + * + * @param toolTemplate ToolTemplate object + * @return ToolTemplateVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolTemplate + * @see ToolTemplateVo + */ + fun toolTemplateToToolTemplateVo(toolTemplate: ToolTemplate) = ToolTemplateVo( + id = toolTemplate.id, + name = toolTemplate.name, + base = toolTemplate.base?.let(ToolBaseConverter::toolBaseToToolBaseVo), + source = toolTemplate.source?.let(ToolDataConverter::toolDataToToolDataVo), + entryPoint = toolTemplate.entryPoint, + enable = toolTemplate.enable == 1, + createTime = toolTemplate.createTime, + updateTime = toolTemplate.updateTime + ) + + /** + * Convert ToolTemplate object into ToolTemplateVo object by list + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun toolTemplateToToolTemplateVoByList(toolTemplate: ToolTemplate) = ToolTemplateVo( + id = toolTemplate.id, + name = toolTemplate.name, + base = ToolBaseVo( + id = toolTemplate.baseId, + name = null, + source = null, + dist = null, + compiled = null, + createTime = null, + updateTime = null + ), + source = ToolDataVo(id = toolTemplate.sourceId, data = null, createTime = null, updateTime = null), + entryPoint = toolTemplate.entryPoint, + enable = toolTemplate.enable == 1, + createTime = toolTemplate.createTime, + updateTime = toolTemplate.updateTime + ) + + /** + * Convert ToolTemplate object into ToolTemplateVo object with base dist + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun toolTemplateToToolTemplateVoWithBaseDist(toolTemplate: ToolTemplate) = ToolTemplateVo( + id = toolTemplate.id, + name = toolTemplate.name, + base = ToolBaseVo( + id = toolTemplate.baseId, + name = toolTemplate.base?.name, + source = null, + dist = ToolDataVo(id = null, data = toolTemplate.base?.distData, createTime = null, updateTime = null), + compiled = null, + createTime = null, + updateTime = null + ), + source = toolTemplate.source?.let(ToolDataConverter::toolDataToToolDataVo), + entryPoint = toolTemplate.entryPoint, + enable = toolTemplate.enable == 1, + createTime = toolTemplate.createTime, + updateTime = toolTemplate.updateTime + ) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/cron/StatisticsCron.kt b/src/main/kotlin/top/fatweb/oxygen/api/cron/StatisticsCron.kt new file mode 100644 index 0000000..e4b014f --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/cron/StatisticsCron.kt @@ -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() + }) + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/common/BusinessCode.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/common/BusinessCode.kt new file mode 100644 index 0000000..5b1f363 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/common/BusinessCode.kt @@ -0,0 +1,49 @@ +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), + + /** + * Tool + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + TOOL(400), + + /** + * Avatar API + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + API_AVATAR(501) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/common/ResponseCode.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/common/ResponseCode.kt new file mode 100644 index 0000000..83a3dfd --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/common/ResponseCode.kt @@ -0,0 +1,76 @@ +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), + SYSTEM_INVALID_CAPTCHA_CODE(BusinessCode.SYSTEM, 54), + SYSTEM_REQUEST_TOO_FREQUENT(BusinessCode.SYSTEM, 55), + SYSTEM_MATCH_SENSITIVE_WORD(BusinessCode.SYSTEM, 56), + + 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_FAILED(BusinessCode.DATABASE, 25), + DATABASE_DELETE_SUCCESS(BusinessCode.DATABASE, 30), + DATABASE_DELETE_FAILED(BusinessCode.DATABASE, 35), + DATABASE_EXECUTE_ERROR(BusinessCode.DATABASE, 50), + DATABASE_DUPLICATE_KEY(BusinessCode.DATABASE, 51), + DATABASE_NO_RECORD_FOUND(BusinessCode.DATABASE, 52), + + TOOL_SUBMIT_SUCCESS(BusinessCode.TOOL, 10), + TOOL_CANCEL_SUCCESS(BusinessCode.TOOL, 11), + TOOL_ILLEGAL_VERSION(BusinessCode.TOOL, 50), + TOOL_UNDER_REVIEW(BusinessCode.TOOL, 51), + TOOL_NOT_UNDER_REVIEW(BusinessCode.TOOL, 52), + TOOL_HAS_UNPUBLISHED_VERSION(BusinessCode.TOOL, 53), + TOOL_HAS_NOT_BEEN_PUBLISHED(BusinessCode.TOOL, 54), + TOOL_HAS_BEEN_PUBLISHED(BusinessCode.TOOL, 55), + TOOL_SUBMIT_ERROR(BusinessCode.TOOL, 60), + TOOL_CANCEL_ERROR(BusinessCode.TOOL, 61), + + API_AVATAR_SUCCESS(BusinessCode.API_AVATAR, 0), + API_AVATAR_ERROR(BusinessCode.API_AVATAR, 50); + + constructor(businessCode: BusinessCode, code: Int) : this(businessCode.code * 100 + code) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/common/ResponseResult.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/common/ResponseResult.kt new file mode 100644 index 0000000..7c866fe --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/common/ResponseResult.kt @@ -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 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 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 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 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 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 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 databaseFail( + code: ResponseCode = ResponseCode.DATABASE_SELECT_FAILED, msg: String = "fail", data: T? = null + ) = build(code, false, msg, data) + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/Func.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/Func.kt new file mode 100644 index 0000000..61fa701 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/Func.kt @@ -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_s_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)" + } +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/Group.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/Group.kt new file mode 100644 index 0000000..5d779ad --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/Group.kt @@ -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_s_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? = null + + override fun toString(): String { + return "Group(id=$id, name=$name, enable=$enable, createTime=$createTime, updateTime=$updateTime, deleted=$deleted, version=$version, roles=$roles)" + } +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/LoginUser.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/LoginUser.kt new file mode 100644 index 0000000..29fafce --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/LoginUser.kt @@ -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? = null + + constructor(user: User) : this() { + this.user = user + } + + @JsonIgnore + override fun getAuthorities(): List { + authorities?.let { return it } + authorities = user.operations?.map { SimpleGrantedAuthority(it.code) } ?: emptyList() + + return authorities as List + } + + @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)" + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/Menu.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/Menu.kt new file mode 100644 index 0000000..d81e235 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/Menu.kt @@ -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_s_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)" + } +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/Module.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/Module.kt new file mode 100644 index 0000000..fa26a28 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/Module.kt @@ -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_s_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)" + } +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/Operation.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/Operation.kt new file mode 100644 index 0000000..c111ce6 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/Operation.kt @@ -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_s_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)" + } +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/Power.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/Power.kt new file mode 100644 index 0000000..4f1a7a0 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/Power.kt @@ -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_s_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)" + } +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/PowerSet.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/PowerSet.kt new file mode 100644 index 0000000..c99f5ae --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/PowerSet.kt @@ -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? = null + + /** + * Menu list + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see Menu + */ + var menuList: List? = null + + /** + * Function list + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see Func + */ + var funcList: List? = null + + /** + * Operation list + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see Operation + */ + var operationList: List? = null + + override fun toString(): String { + return "PowerSet(moduleList=$moduleList, menuList=$menuList, funcList=$funcList, operationList=$operationList)" + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/PowerType.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/PowerType.kt new file mode 100644 index 0000000..c2be1e4 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/PowerType.kt @@ -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_s_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)" + } +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/RPowerRole.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/RPowerRole.kt new file mode 100644 index 0000000..fc0da02 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/RPowerRole.kt @@ -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_r_power_role") +class RPowerRole : 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 "RPowerRole(id=$id, powerId=$powerId, roleId=$roleId, deleted=$deleted, version=$version)" + } +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/RRoleGroup.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/RRoleGroup.kt new file mode 100644 index 0000000..a3af844 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/RRoleGroup.kt @@ -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_r_role_group") +class RRoleGroup : 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 "RRoleGroup(id=$id, roleId=$roleId, groupId=$groupId, deleted=$deleted, version=$version)" + } +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/RUserGroup.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/RUserGroup.kt new file mode 100644 index 0000000..60986f3 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/RUserGroup.kt @@ -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_r_user_group") +class RUserGroup : 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 "RUserGroup(id=$id, userId=$userId, groupId=$groupId, deleted=$deleted, version=$version)" + } +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/RUserRole.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/RUserRole.kt new file mode 100644 index 0000000..a3f7d77 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/RUserRole.kt @@ -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_r_user_role") +class RUserRole : 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 "RUserRole(id=$id, userId=$userId, roleId=$roleId, deleted=$deleted, version=$version)" + } +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/Role.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/Role.kt new file mode 100644 index 0000000..e5175fc --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/Role.kt @@ -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_s_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? = null + + /** + * Menu list + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see Menu + */ + @TableField(exist = false) + var menus: List? = null + + /** + * Function list + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see Func + */ + @TableField(exist = false) + var funcs: List? = null + + /** + * Operation list + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see Operation + */ + @TableField(exist = false) + var operations: List? = null + + /** + * Power list + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see Power + */ + @TableField(exist = false) + var powers: List? = 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)" + } +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/User.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/User.kt new file mode 100644 index 0000000..11324c6 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/User.kt @@ -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_s_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 information + * + * @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? = null + + /** + * Group list + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see Group + */ + @TableField(exist = false) + var groups: List? = null + + /** + * Module list + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see Module + */ + @TableField(exist = false) + var modules: List? = null + + /** + * Menu list + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see Menu + */ + @TableField(exist = false) + var menus: List? = null + + /** + * Function list + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see Func + */ + @TableField(exist = false) + var funcs: List? = null + + /** + * Operation list + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see Operation + */ + @TableField(exist = false) + var operations: List? = 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)" + } +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/UserInfo.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/UserInfo.kt new file mode 100644 index 0000000..8aa8e24 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/permission/UserInfo.kt @@ -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_s_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)" + } +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/system/EventLog.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/system/EventLog.kt new file mode 100644 index 0000000..c689547 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/system/EventLog.kt @@ -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_l_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)" + } +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/system/SensitiveWord.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/system/SensitiveWord.kt new file mode 100644 index 0000000..a024d6e --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/system/SensitiveWord.kt @@ -0,0 +1,63 @@ +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.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler +import com.fasterxml.jackson.annotation.JsonValue +import java.io.Serializable + +/** + * Sensitive word entity + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@TableName("t_s_sensitive_word", autoResultMap = true) +class SensitiveWord : Serializable { + enum class Use(@field:EnumValue @field:JsonValue val code: String) { + USERNAME("USERNAME"), TITLE("TITLE"); + } + + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableId("id") + var id: Long? = null + + /** + * Word + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField("word") + var word: String? = null + + /** + * Use for + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField(value = "use_for", typeHandler = JacksonTypeHandler::class) + @JvmField + var useFor: Set? = null + + /** + * Enable + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField("enable") + var enable: Int? = null + + override fun toString(): String { + return "SensitiveWord(id=$id, word=$word, useFor=$useFor, enable=$enable)" + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/system/StatisticsLog.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/system/StatisticsLog.kt new file mode 100644 index 0000000..165a2c4 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/system/StatisticsLog.kt @@ -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_l_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)" + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/system/SysLog.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/system/SysLog.kt new file mode 100644 index 0000000..b17e2fa --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/system/SysLog.kt @@ -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_l_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)" + } +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/tool/RToolCategory.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/tool/RToolCategory.kt new file mode 100644 index 0000000..cce2436 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/tool/RToolCategory.kt @@ -0,0 +1,64 @@ +package top.fatweb.oxygen.api.entity.tool + +import com.baomidou.mybatisplus.annotation.* +import java.io.Serializable + +/** + * Tool category intermediate entity + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@TableName("t_r_tool_main_category") +class RToolCategory : Serializable { + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableId("id") + var id: Long? = null + + /** + * Tool ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField("tool_id") + var toolId: Long? = null + + /** + * Category ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField("category_id") + var categoryId: 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 "RToolCategory(id=$id, toolId=$toolId, categoryId=$categoryId, deleted=$deleted, version=$version)" + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/tool/Tool.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/tool/Tool.kt new file mode 100644 index 0000000..a06d660 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/tool/Tool.kt @@ -0,0 +1,242 @@ +package top.fatweb.oxygen.api.entity.tool + +import com.baomidou.mybatisplus.annotation.* +import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler +import com.fasterxml.jackson.annotation.JsonValue +import top.fatweb.oxygen.api.entity.permission.User +import java.time.LocalDateTime + +/** + * Tool entity + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@TableName("t_b_tool_main", autoResultMap = true) +class Tool { + /** + * Tool review type enum + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + enum class ReviewType(@field:EnumValue @field:JsonValue val code: String) { + NONE("NONE"), PROCESSING("PROCESSING"), PASS("PASS"), REJECT("REJECT") + } + + /** + * 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 + + /** + * Tool ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField("tool_id") + var toolId: String? = null + + /** + * Icon + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField("icon") + var icon: String? = null + + /** + * Description + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField("description") + var description: String? = null + + /** + * Base ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField("base_id") + var baseId: Long? = null + + /** + * Author ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField("author_id") + var authorId: Long? = null + + /** + * Version of tool + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField("ver") + var ver: String? = null + + /** + * Keywords + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField("keywords", typeHandler = JacksonTypeHandler::class) + var keywords: List? = null + + /** + * Source code ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField("source_id") + var sourceId: Long? = null + + /** + * Compile product ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField("dist_id") + var distId: Long? = null + + /** + * Entry point + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField("entry_point") + var entryPoint: String? = null + + /** + * Publish + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField("publish") + var publish: Long? = null + + /** + * Review + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ReviewType + */ + @TableField("review") + var review: ReviewType? = 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 + + /** + * Author + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField(exist = false) + var author: User? = null + + /** + * Base + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField(exist = false) + var base: ToolBase? = null + + /** + * Categories + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField(exist = false) + var categories: List? = null + + /** + * Source + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField(exist = false) + var source: ToolData? = null + + /** + * Dist + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField(exist = false) + var dist: ToolData? = null + + override fun toString(): String { + return "Tool(id=$id, name=$name, toolId=$toolId, icon=$icon, description=$description, baseId=$baseId, authorId=$authorId, ver=$ver, keywords=$keywords, sourceId=$sourceId, distId=$distId, entryPoint=$entryPoint, publish=$publish, review=$review, createTime=$createTime, updateTime=$updateTime, deleted=$deleted, version=$version, author=$author, base=$base, categories=$categories, source=$source, dist=$dist)" + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/tool/ToolBase.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/tool/ToolBase.kt new file mode 100644 index 0000000..9878b57 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/tool/ToolBase.kt @@ -0,0 +1,129 @@ +package top.fatweb.oxygen.api.entity.tool + +import com.baomidou.mybatisplus.annotation.* +import java.time.LocalDateTime + +/** + * Tool base entity + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@TableName("t_b_tool_base") +class ToolBase { + /** + * 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 + + /** + * Source ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField("source_id") + var sourceId: Long? = null + + /** + * Dist ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField("dist_id") + var distId: Long? = null + + /** + * Has compiled + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField("compiled") + var compiled: 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 + + /** + * Source + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField(exist = false) + var source: ToolData? = null + + /** + * Dist + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField(exist = false) + var dist: ToolData? = null + + /** + * Dist data + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField(exist = false) + var distData: String? = null + + override fun toString(): String { + return "ToolBase(id=$id, name=$name, sourceId=$sourceId, distId=$distId, compiled=$compiled, createTime=$createTime, updateTime=$updateTime, deleted=$deleted, version=$version, source=$source, dist=$dist, distData=$distData)" + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/tool/ToolCategory.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/tool/ToolCategory.kt new file mode 100644 index 0000000..f111e1d --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/tool/ToolCategory.kt @@ -0,0 +1,84 @@ +package top.fatweb.oxygen.api.entity.tool + +import com.baomidou.mybatisplus.annotation.* +import java.time.LocalDateTime + +/** + * Tool category entity + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@TableName("t_b_tool_category") +class ToolCategory { + /** + * 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 + + /** + * Enabel + * + * @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 + + override fun toString(): String { + return "ToolCategory(id=$id, name=$name, enable=$enable, createTime=$createTime, updateTime=$updateTime, deleted=$deleted, version=$version)" + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/tool/ToolData.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/tool/ToolData.kt new file mode 100644 index 0000000..d576b23 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/tool/ToolData.kt @@ -0,0 +1,75 @@ +package top.fatweb.oxygen.api.entity.tool + +import com.baomidou.mybatisplus.annotation.* +import java.time.LocalDateTime + +/** + * Tool data entity + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@TableName("t_b_tool_data") +class ToolData { + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableId("id") + var id: Long? = null + + /** + * Data + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField("data") + var data: 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 "ToolData(id=$id, data=$data, createTime=$createTime, updateTime=$updateTime, deleted=$deleted, version=$version)" + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/entity/tool/ToolTemplate.kt b/src/main/kotlin/top/fatweb/oxygen/api/entity/tool/ToolTemplate.kt new file mode 100644 index 0000000..124995b --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/entity/tool/ToolTemplate.kt @@ -0,0 +1,129 @@ +package top.fatweb.oxygen.api.entity.tool + +import com.baomidou.mybatisplus.annotation.* +import java.time.LocalDateTime + +/** + * Tool template entity + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@TableName("t_b_tool_template") +class ToolTemplate { + /** + * 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 + + /** + * Base ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField("base_id") + var baseId: Long? = null + + /** + * Source ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField("source_id") + var sourceId: Long? = null + + /** + * Entry point + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField("entry_point") + var entryPoint: 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 + + /** + * Source + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField(exist = false) + var source: ToolData? = null + + /** + * Base + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @TableField(exist = false) + var base: ToolBase? = null + + override fun toString(): String { + return "ToolTemplate(id=$id, name=$name, baseId=$baseId, sourceId=$sourceId, entryPoint=$entryPoint, enable=$enable, createTime=$createTime, updateTime=$updateTime, deleted=$deleted, version=$version, source=$source, base=$base)" + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/exception/AccountNeedInitException.kt b/src/main/kotlin/top/fatweb/oxygen/api/exception/AccountNeedInitException.kt new file mode 100644 index 0000000..311a9a6 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/exception/AccountNeedInitException.kt @@ -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") \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/exception/AccountNeedResetPasswordException.kt b/src/main/kotlin/top/fatweb/oxygen/api/exception/AccountNeedResetPasswordException.kt new file mode 100644 index 0000000..756682b --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/exception/AccountNeedResetPasswordException.kt @@ -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") \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/exception/DatabaseDeleteException.kt b/src/main/kotlin/top/fatweb/oxygen/api/exception/DatabaseDeleteException.kt new file mode 100644 index 0000000..cd1ea34 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/exception/DatabaseDeleteException.kt @@ -0,0 +1,11 @@ +package top.fatweb.oxygen.api.exception + +/** + * Database delete exception + * + * @param message Exception message + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RuntimeException + */ +class DatabaseDeleteException(message: String = "Database delete failed"): RuntimeException(message) \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/exception/DatabaseInsertException.kt b/src/main/kotlin/top/fatweb/oxygen/api/exception/DatabaseInsertException.kt new file mode 100644 index 0000000..b3e301d --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/exception/DatabaseInsertException.kt @@ -0,0 +1,11 @@ +package top.fatweb.oxygen.api.exception + +/** + * Database insert exception + * + * @param message Exception message + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RuntimeException + */ +class DatabaseInsertException(message: String = "Database insert failed"): RuntimeException(message) \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/exception/DatabaseSelectException.kt b/src/main/kotlin/top/fatweb/oxygen/api/exception/DatabaseSelectException.kt new file mode 100644 index 0000000..1b5623b --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/exception/DatabaseSelectException.kt @@ -0,0 +1,11 @@ +package top.fatweb.oxygen.api.exception + +/** + * Database select exception + * + * @param message Exception message + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RuntimeException + */ +class DatabaseSelectException(message: String = "Database select failed"): RuntimeException(message) \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/exception/DatabaseUpdateException.kt b/src/main/kotlin/top/fatweb/oxygen/api/exception/DatabaseUpdateException.kt new file mode 100644 index 0000000..43f6c09 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/exception/DatabaseUpdateException.kt @@ -0,0 +1,11 @@ +package top.fatweb.oxygen.api.exception + +/** + * Database update exception + * + * @param message Exception message + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RuntimeException + */ +class DatabaseUpdateException(message: String = "Database update failed"): RuntimeException(message) \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/exception/IllegalVersionException.kt b/src/main/kotlin/top/fatweb/oxygen/api/exception/IllegalVersionException.kt new file mode 100644 index 0000000..b53fc99 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/exception/IllegalVersionException.kt @@ -0,0 +1,10 @@ +package top.fatweb.oxygen.api.exception + +/** + * Illegal version exception + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RuntimeException + */ +class IllegalVersionException : RuntimeException("Illegal Version") \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/exception/InvalidCaptchaCodeException.kt b/src/main/kotlin/top/fatweb/oxygen/api/exception/InvalidCaptchaCodeException.kt new file mode 100644 index 0000000..6e2b6a5 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/exception/InvalidCaptchaCodeException.kt @@ -0,0 +1,10 @@ +package top.fatweb.oxygen.api.exception + +/** + * Invalid captcha code exception + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RuntimeException + */ +class InvalidCaptchaCodeException : RuntimeException("Invalid captcha code") \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/exception/MatchSensitiveWordException.kt b/src/main/kotlin/top/fatweb/oxygen/api/exception/MatchSensitiveWordException.kt new file mode 100644 index 0000000..dbf5cf6 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/exception/MatchSensitiveWordException.kt @@ -0,0 +1,10 @@ +package top.fatweb.oxygen.api.exception + +/** + * Match sensitive word exception + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RuntimeException + */ +class MatchSensitiveWordException : RuntimeException("Match sensitive word") \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/exception/NoEmailConfigException.kt b/src/main/kotlin/top/fatweb/oxygen/api/exception/NoEmailConfigException.kt new file mode 100644 index 0000000..a7bd6f2 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/exception/NoEmailConfigException.kt @@ -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(", ")}") \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/exception/NoRecordFoundException.kt b/src/main/kotlin/top/fatweb/oxygen/api/exception/NoRecordFoundException.kt new file mode 100644 index 0000000..65274fa --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/exception/NoRecordFoundException.kt @@ -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") \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/exception/NoVerificationRequiredException.kt b/src/main/kotlin/top/fatweb/oxygen/api/exception/NoVerificationRequiredException.kt new file mode 100644 index 0000000..c0bcc3a --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/exception/NoVerificationRequiredException.kt @@ -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") \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/exception/RequestTooFrequentException.kt b/src/main/kotlin/top/fatweb/oxygen/api/exception/RequestTooFrequentException.kt new file mode 100644 index 0000000..59a5b16 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/exception/RequestTooFrequentException.kt @@ -0,0 +1,10 @@ +package top.fatweb.oxygen.api.exception + +/** + * Request too frequent exception + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RuntimeException + */ +class RequestTooFrequentException: RuntimeException("Request too frequent") \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/exception/RetrieveCodeErrorOrExpiredException.kt b/src/main/kotlin/top/fatweb/oxygen/api/exception/RetrieveCodeErrorOrExpiredException.kt new file mode 100644 index 0000000..d8010c1 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/exception/RetrieveCodeErrorOrExpiredException.kt @@ -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") \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/exception/TokenHasExpiredException.kt b/src/main/kotlin/top/fatweb/oxygen/api/exception/TokenHasExpiredException.kt new file mode 100644 index 0000000..7250ef7 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/exception/TokenHasExpiredException.kt @@ -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") \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/exception/ToolHasBeenPublishedException.kt b/src/main/kotlin/top/fatweb/oxygen/api/exception/ToolHasBeenPublishedException.kt new file mode 100644 index 0000000..f80dfca --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/exception/ToolHasBeenPublishedException.kt @@ -0,0 +1,10 @@ +package top.fatweb.oxygen.api.exception + +/** + * Tool has been published exception + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RuntimeException + */ +class ToolHasBeenPublishedException : RuntimeException("Tool has been published") \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/exception/ToolHasNotBeenPublishedException.kt b/src/main/kotlin/top/fatweb/oxygen/api/exception/ToolHasNotBeenPublishedException.kt new file mode 100644 index 0000000..af82607 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/exception/ToolHasNotBeenPublishedException.kt @@ -0,0 +1,10 @@ +package top.fatweb.oxygen.api.exception + +/** + * Tool has not been published exception + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RuntimeException + */ +class ToolHasNotBeenPublishedException : RuntimeException("Tool has not been published") \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/exception/ToolHasUnpublishedVersionException.kt b/src/main/kotlin/top/fatweb/oxygen/api/exception/ToolHasUnpublishedVersionException.kt new file mode 100644 index 0000000..0b4d41e --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/exception/ToolHasUnpublishedVersionException.kt @@ -0,0 +1,10 @@ +package top.fatweb.oxygen.api.exception + +/** + * Tool has unpublished version exception + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RuntimeException + */ +class ToolHasUnpublishedVersionException : RuntimeException("Has unpublished version") \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/exception/ToolNotUnderReviewException.kt b/src/main/kotlin/top/fatweb/oxygen/api/exception/ToolNotUnderReviewException.kt new file mode 100644 index 0000000..586d71f --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/exception/ToolNotUnderReviewException.kt @@ -0,0 +1,10 @@ +package top.fatweb.oxygen.api.exception + +/** + * Tool not under review exception + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RuntimeException + */ +class ToolNotUnderReviewException : RuntimeException("Tool not under review") \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/exception/ToolUnderReviewException.kt b/src/main/kotlin/top/fatweb/oxygen/api/exception/ToolUnderReviewException.kt new file mode 100644 index 0000000..83083f0 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/exception/ToolUnderReviewException.kt @@ -0,0 +1,10 @@ +package top.fatweb.oxygen.api.exception + +/** + * Tool under review exception + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RuntimeException + */ +class ToolUnderReviewException : RuntimeException("Tool under review") \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/exception/UserNotFoundException.kt b/src/main/kotlin/top/fatweb/oxygen/api/exception/UserNotFoundException.kt new file mode 100644 index 0000000..6b2dc60 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/exception/UserNotFoundException.kt @@ -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") \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/exception/VerificationCodeErrorOrExpiredException.kt b/src/main/kotlin/top/fatweb/oxygen/api/exception/VerificationCodeErrorOrExpiredException.kt new file mode 100644 index 0000000..bfbbee7 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/exception/VerificationCodeErrorOrExpiredException.kt @@ -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") \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/filter/ExceptionFilter.kt b/src/main/kotlin/top/fatweb/oxygen/api/filter/ExceptionFilter.kt similarity index 69% rename from src/main/kotlin/top/fatweb/api/filter/ExceptionFilter.kt rename to src/main/kotlin/top/fatweb/oxygen/api/filter/ExceptionFilter.kt index 3097036..6117074 100644 --- a/src/main/kotlin/top/fatweb/api/filter/ExceptionFilter.kt +++ b/src/main/kotlin/top/fatweb/oxygen/api/filter/ExceptionFilter.kt @@ -1,4 +1,4 @@ -package top.fatweb.api.filter +package top.fatweb.oxygen.api.filter import jakarta.servlet.Filter import jakarta.servlet.FilterChain @@ -6,12 +6,17 @@ 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? + servletRequest: ServletRequest?, servletResponse: ServletResponse?, filterChain: FilterChain? ) { try { filterChain!!.doFilter(servletRequest, servletResponse) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/filter/JwtAuthenticationTokenFilter.kt b/src/main/kotlin/top/fatweb/oxygen/api/filter/JwtAuthenticationTokenFilter.kt new file mode 100644 index 0000000..a3ab155 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/filter/JwtAuthenticationTokenFilter.kt @@ -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(redisKeys.first()) + loginUser ?: 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) + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/handler/DataMetaObjectHandler.kt b/src/main/kotlin/top/fatweb/oxygen/api/handler/DataMetaObjectHandler.kt new file mode 100644 index 0000000..e667eec --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/handler/DataMetaObjectHandler.kt @@ -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)) + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/handler/ExceptionHandler.kt b/src/main/kotlin/top/fatweb/oxygen/api/handler/ExceptionHandler.kt new file mode 100644 index 0000000..8624e10 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/handler/ExceptionHandler.kt @@ -0,0 +1,263 @@ +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.jdbc.UncategorizedSQLException +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 org.springframework.web.servlet.resource.NoResourceFoundException +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) { + /* Request */ + is HttpRequestMethodNotSupportedException, is NoResourceFoundException -> { + 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 RequestTooFrequentException -> { + logger.debug(e.localizedMessage, e) + ResponseResult.fail(ResponseCode.SYSTEM_REQUEST_TOO_FREQUENT, e.localizedMessage, null) + } + + /* Authentication */ + 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 InvalidCaptchaCodeException -> { + logger.debug(e.localizedMessage, e) + ResponseResult.fail(ResponseCode.SYSTEM_INVALID_CAPTCHA_CODE, e.localizedMessage, null) + } + + /* SQL */ + is DatabaseSelectException -> { + logger.debug(e.localizedMessage, e) + ResponseResult.databaseFail(ResponseCode.DATABASE_SELECT_FAILED, e.localizedMessage, null) + } + + is DatabaseInsertException -> { + logger.debug(e.localizedMessage, e) + ResponseResult.databaseFail(ResponseCode.DATABASE_INSERT_FAILED, e.localizedMessage, null) + } + + is DatabaseUpdateException -> { + logger.debug(e.localizedMessage, e) + ResponseResult.databaseFail(ResponseCode.DATABASE_UPDATE_FAILED, e.localizedMessage, null) + } + + is DatabaseDeleteException -> { + logger.debug(e.localizedMessage, e) + ResponseResult.databaseFail(ResponseCode.DATABASE_DELETE_FAILED, 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 UncategorizedSQLException -> { + if (e.localizedMessage.contains("SQLITE_CONSTRAINT_UNIQUE")) { + logger.debug(e.localizedMessage, e) + return ResponseResult.fail(ResponseCode.DATABASE_DUPLICATE_KEY, "Duplicate key", null) + } + + logger.error(e.localizedMessage, e) + ResponseResult.fail(ResponseCode.DATABASE_EXECUTE_ERROR, e.localizedMessage, null) + } + + /* Tool */ + is IllegalVersionException -> { + logger.debug(e.localizedMessage, e) + ResponseResult.fail(ResponseCode.TOOL_ILLEGAL_VERSION, e.localizedMessage, null) + } + + is ToolUnderReviewException -> { + logger.debug(e.localizedMessage, e) + ResponseResult.fail(ResponseCode.TOOL_UNDER_REVIEW, e.localizedMessage, null) + } + + is ToolNotUnderReviewException -> { + logger.debug(e.localizedMessage, e) + ResponseResult.fail(ResponseCode.TOOL_NOT_UNDER_REVIEW, e.localizedMessage, null) + } + + is ToolHasUnpublishedVersionException -> { + logger.debug(e.localizedMessage, e) + ResponseResult.fail(ResponseCode.TOOL_HAS_UNPUBLISHED_VERSION, e.localizedMessage, null) + } + + is ToolHasNotBeenPublishedException -> { + logger.debug(e.localizedMessage, e) + ResponseResult.fail(ResponseCode.TOOL_HAS_NOT_BEEN_PUBLISHED, e.localizedMessage, null) + } + + is ToolHasBeenPublishedException -> { + logger.debug(e.localizedMessage, e) + ResponseResult.fail(ResponseCode.TOOL_HAS_BEEN_PUBLISHED, e.localizedMessage, null) + } + + /* Other */ + is MatchSensitiveWordException -> { + logger.debug(e.localizedMessage, e) + ResponseResult.fail(ResponseCode.SYSTEM_MATCH_SENSITIVE_WORD, e.localizedMessage, null) + } + + /* API */ + 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) + } + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/handler/JwtAccessDeniedHandler.kt b/src/main/kotlin/top/fatweb/oxygen/api/handler/JwtAccessDeniedHandler.kt similarity index 51% rename from src/main/kotlin/top/fatweb/api/handler/JwtAccessDeniedHandler.kt rename to src/main/kotlin/top/fatweb/oxygen/api/handler/JwtAccessDeniedHandler.kt index 22e03c6..294b888 100644 --- a/src/main/kotlin/top/fatweb/api/handler/JwtAccessDeniedHandler.kt +++ b/src/main/kotlin/top/fatweb/oxygen/api/handler/JwtAccessDeniedHandler.kt @@ -1,4 +1,4 @@ -package top.fatweb.api.handler +package top.fatweb.oxygen.api.handler import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletResponse @@ -6,14 +6,18 @@ 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: HttpServletRequest?, response: HttpServletResponse?, accessDeniedException: AccessDeniedException? ) { - request?.setAttribute("filter.error", accessDeniedException) - request?.getRequestDispatcher("/error/thrown")?.forward(request, response) + throw accessDeniedException ?: AccessDeniedException("Access Denied") } } \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/handler/JwtAuthenticationEntryPointHandler.kt b/src/main/kotlin/top/fatweb/oxygen/api/handler/JwtAuthenticationEntryPointHandler.kt similarity index 64% rename from src/main/kotlin/top/fatweb/api/handler/JwtAuthenticationEntryPointHandler.kt rename to src/main/kotlin/top/fatweb/oxygen/api/handler/JwtAuthenticationEntryPointHandler.kt index cf5b808..b215232 100644 --- a/src/main/kotlin/top/fatweb/api/handler/JwtAuthenticationEntryPointHandler.kt +++ b/src/main/kotlin/top/fatweb/oxygen/api/handler/JwtAuthenticationEntryPointHandler.kt @@ -1,4 +1,4 @@ -package top.fatweb.api.handler +package top.fatweb.oxygen.api.handler import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletResponse @@ -6,12 +6,17 @@ 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: HttpServletRequest?, response: HttpServletResponse?, authException: AuthenticationException? ) { request?.setAttribute("filter.error", authException) request?.getRequestDispatcher("/error/thrown")?.forward(request, response) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/http/TurnstileApi.kt b/src/main/kotlin/top/fatweb/oxygen/api/http/TurnstileApi.kt new file mode 100644 index 0000000..7f28258 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/http/TurnstileApi.kt @@ -0,0 +1,33 @@ +package top.fatweb.oxygen.api.http + +import com.github.lianjiatech.retrofit.spring.boot.core.RetrofitClient +import org.springframework.stereotype.Service +import retrofit2.http.Field +import retrofit2.http.FormUrlEncoded +import retrofit2.http.POST +import top.fatweb.oxygen.api.http.entity.turnstile.SiteverifyResponse +import top.fatweb.oxygen.api.properties.ServerProperties + +/** + * Turnstile http request api + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Service +@RetrofitClient(baseUrl = "https://challenges.cloudflare.com/turnstile/v0/") +interface TurnstileApi { + /** + * Turnstile post verify captcha code + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see SiteverifyResponse + */ + @FormUrlEncoded + @POST("siteverify") + fun siteverify( + @Field("response") captchaCode: String, + @Field("secret") secret: String = ServerProperties.turnstileSecretKey + ): SiteverifyResponse +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/http/entity/turnstile/SiteverifyResponse.kt b/src/main/kotlin/top/fatweb/oxygen/api/http/entity/turnstile/SiteverifyResponse.kt new file mode 100644 index 0000000..e6e6b94 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/http/entity/turnstile/SiteverifyResponse.kt @@ -0,0 +1,48 @@ +package top.fatweb.oxygen.api.http.entity.turnstile + +import com.fasterxml.jackson.annotation.JsonProperty +import java.time.LocalDateTime + +/** + * Turnstile verify captcha code response + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +data class SiteverifyResponse( + /** + * Is success + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @JsonProperty("success") + val success: Boolean, + + /** + * Challenge time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @JsonProperty("challenge_ts") + val challengeTs: LocalDateTime?, + + /** + * Hostname + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @JsonProperty("hostname") + val hostname: String?, + + /** + * Error codes list + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @JsonProperty("error-codes") + val errorCodes: List? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/interceptor/SysLogInterceptor.kt b/src/main/kotlin/top/fatweb/oxygen/api/interceptor/SysLogInterceptor.kt new file mode 100644 index 0000000..73ac78a --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/interceptor/SysLogInterceptor.kt @@ -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 { + private val sysLogThreadLocal = ThreadLocal() + private val resultThreadLocal = ThreadLocal() + + 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 { + 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>): Boolean = + true + + override fun beforeBodyWrite( + body: Any?, + returnType: MethodParameter, + selectedContentType: MediaType, + selectedConverterType: Class>, + 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 + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/FuncMapper.kt b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/FuncMapper.kt new file mode 100644 index 0000000..167353d --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/FuncMapper.kt @@ -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 diff --git a/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/GroupMapper.kt b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/GroupMapper.kt new file mode 100644 index 0000000..8413f65 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/GroupMapper.kt @@ -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 { + /** + * 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, + @Param("searchName") searchName: String?, + @Param("searchRegex") searchRegex: Boolean + ): IPage + + /** + * 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): List? + + /** + * 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? +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/MenuMapper.kt b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/MenuMapper.kt new file mode 100644 index 0000000..1952dcd --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/MenuMapper.kt @@ -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 diff --git a/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/ModuleMapper.kt b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/ModuleMapper.kt new file mode 100644 index 0000000..bc2e492 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/ModuleMapper.kt @@ -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 diff --git a/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/OperationMapper.kt b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/OperationMapper.kt new file mode 100644 index 0000000..848a5bf --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/OperationMapper.kt @@ -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 diff --git a/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/PowerMapper.kt b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/PowerMapper.kt new file mode 100644 index 0000000..1100fdd --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/PowerMapper.kt @@ -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 diff --git a/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/RPowerRoleMapper.kt b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/RPowerRoleMapper.kt new file mode 100644 index 0000000..be569f3 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/RPowerRoleMapper.kt @@ -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.RPowerRole + +/** + * Power role intermediate mapper + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see BaseMapper + * @see RPowerRole + */ +@Mapper +interface RPowerRoleMapper : BaseMapper diff --git a/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/RRoleGroupMapper.kt b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/RRoleGroupMapper.kt new file mode 100644 index 0000000..48f10da --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/RRoleGroupMapper.kt @@ -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.RRoleGroup + +/** + * Role group intermediate mapper + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see BaseMapper + * @see RRoleGroup + */ +@Mapper +interface RRoleGroupMapper : BaseMapper diff --git a/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/RUserGroupMapper.kt b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/RUserGroupMapper.kt new file mode 100644 index 0000000..fa0b8bb --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/RUserGroupMapper.kt @@ -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.RUserGroup + +/** + * User group intermediate mapper + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see BaseMapper + * @see RUserGroup + */ +@Mapper +interface RUserGroupMapper : BaseMapper diff --git a/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/RUserRoleMapper.kt b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/RUserRoleMapper.kt new file mode 100644 index 0000000..b6a18f4 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/RUserRoleMapper.kt @@ -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.RUserRole + +/** + * User role intermediate mapper + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see BaseMapper + * @see RUserRole + */ +@Mapper +interface RUserRoleMapper : BaseMapper diff --git a/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/RoleMapper.kt b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/RoleMapper.kt new file mode 100644 index 0000000..b036bee --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/RoleMapper.kt @@ -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 { + /** + * 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, + @Param("searchName") searchName: String?, + @Param("searchRegex") searchRegex: Boolean + ): IPage + + /** + * 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): List? + + /** + * 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? +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/UserInfoMapper.kt b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/UserInfoMapper.kt new file mode 100644 index 0000000..8e816d6 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/UserInfoMapper.kt @@ -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 diff --git a/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/UserMapper.kt b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/UserMapper.kt new file mode 100644 index 0000000..80c1aad --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/mapper/permission/UserMapper.kt @@ -0,0 +1,111 @@ +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 { + /** + * 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 one user with basic information by username + * + * @param username Username + * @return User object with basic information + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see User + */ + fun selectOneWithBasicInfoByUsername(@Param("username") username: String): User? + + /** + * Select user ID 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, + @Param("searchType") searchType: String, + @Param("searchValue") searchValue: String?, + @Param("searchRegex") searchRegex: Boolean + ): IPage + + /** + * 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): List + + /** + * 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 + + /** + * 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): List + + /** + * 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): List +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/mapper/system/EventLogMapper.kt b/src/main/kotlin/top/fatweb/oxygen/api/mapper/system/EventLogMapper.kt new file mode 100644 index 0000000..aaf96e0 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/mapper/system/EventLogMapper.kt @@ -0,0 +1,16 @@ +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 + * @see BaseMapper + * @see EventLog + */ +@Mapper +interface EventLogMapper : BaseMapper \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/mapper/system/SensitiveWordMapper.kt b/src/main/kotlin/top/fatweb/oxygen/api/mapper/system/SensitiveWordMapper.kt new file mode 100644 index 0000000..be01e0c --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/mapper/system/SensitiveWordMapper.kt @@ -0,0 +1,16 @@ +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.SensitiveWord + +/** + * Sensitive word mapper + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see BaseMapper + * @see SensitiveWord + */ +@Mapper +interface SensitiveWordMapper : BaseMapper \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/mapper/system/StatisticsLogMapper.kt b/src/main/kotlin/top/fatweb/oxygen/api/mapper/system/StatisticsLogMapper.kt new file mode 100644 index 0000000..59b1523 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/mapper/system/StatisticsLogMapper.kt @@ -0,0 +1,16 @@ +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 + * @see BaseMapper + * @see StatisticsLog + */ +@Mapper +interface StatisticsLogMapper : BaseMapper \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/mapper/system/SysLogMapper.kt b/src/main/kotlin/top/fatweb/oxygen/api/mapper/system/SysLogMapper.kt new file mode 100644 index 0000000..06088a2 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/mapper/system/SysLogMapper.kt @@ -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 { + /** + * 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, + @Param("logType") logType: List?, + @Param("requestMethod") requestMethod: List?, + @Param("searchRequestUrl") searchRequestUrl: String?, + @Param("searchStartTime") searchStartTime: LocalDateTime?, + @Param("searchEndTime") searchEndTime: LocalDateTime? + ): IPage +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/mapper/tool/EditMapper.kt b/src/main/kotlin/top/fatweb/oxygen/api/mapper/tool/EditMapper.kt new file mode 100644 index 0000000..3cfca8b --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/mapper/tool/EditMapper.kt @@ -0,0 +1,71 @@ +package top.fatweb.oxygen.api.mapper.tool + +import com.baomidou.mybatisplus.core.mapper.BaseMapper +import org.apache.ibatis.annotations.Mapper +import org.apache.ibatis.annotations.Param +import top.fatweb.oxygen.api.entity.tool.Tool +import top.fatweb.oxygen.api.entity.tool.ToolTemplate + +/** + * Tool edit mapper + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see BaseMapper + * @see Tool + */ +@Mapper +interface EditMapper : BaseMapper { + /** + * Select tool template by ID + * + * @param id Template ID + * @return ToolTemplate object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolTemplate + */ + fun selectTemplate(@Param("id") id: Long): ToolTemplate? + + /** + * Select tool by ID and user ID + * + * @param id Tool ID + * @param userId User ID + * @return Tool object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see Tool + */ + fun selectOne(@Param("id") id: Long, @Param("userId") userId: Long): Tool? + + /** + * Select tool in list by User ID + * + * @param userId User ID + * @return List of tool object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see Tool + */ + fun selectPersonal(@Param("userId") userId: Long): List + + /** + * Select tool detail + * + * @param username Username + * @param toolId Tool ID + * @param ver Tool version + * @param operator Operator username + * @return List of tool object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see Tool + */ + fun selectDetail( + @Param("username") username: String, + @Param("toolId") toolId: String, + @Param("ver") ver: String, + @Param("operator") operator: String? + ): List? +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/mapper/tool/ManagementMapper.kt b/src/main/kotlin/top/fatweb/oxygen/api/mapper/tool/ManagementMapper.kt new file mode 100644 index 0000000..8ef9eb7 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/mapper/tool/ManagementMapper.kt @@ -0,0 +1,61 @@ +package top.fatweb.oxygen.api.mapper.tool + +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.tool.Tool + +/** + * Tool management mapper + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see BaseMapper + * @see Tool + */ +@Mapper +interface ManagementMapper : BaseMapper { + /** + * Select tool by ID + * + * @param id Tool ID + * @return Tool object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see Tool + */ + fun selectOne(@Param("id") id: Long): Tool? + + /** + * Select tool ID in page + * + * @param page Pagination + * @param review Review + * @param searchType Type of search + * @param searchValue Value to search for + * @param searchRegex Use regex + * @return Tool ID in page + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IPage + */ + fun selectPage( + page: IPage, + @Param("review") review: List?, + @Param("searchType") searchType: String, + @Param("searchValue") searchValue: String?, + @Param("searchRegex") searchRegex: Boolean + ): IPage + + /** + * Select tool in list by tool IDs + * + * @param ids List of tool IDs + * @return List of tool object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see Tool + */ + fun selectListByIds(@Param("ids") ids: List): List +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/mapper/tool/RToolCategoryMapper.kt b/src/main/kotlin/top/fatweb/oxygen/api/mapper/tool/RToolCategoryMapper.kt new file mode 100644 index 0000000..1bc8be4 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/mapper/tool/RToolCategoryMapper.kt @@ -0,0 +1,16 @@ +package top.fatweb.oxygen.api.mapper.tool + +import com.baomidou.mybatisplus.core.mapper.BaseMapper +import org.apache.ibatis.annotations.Mapper +import top.fatweb.oxygen.api.entity.tool.RToolCategory + +/** + * Tool category intermediate mapper + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see BaseMapper + * @see RToolCategory + */ +@Mapper +interface RToolCategoryMapper : BaseMapper \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/mapper/tool/StoreMapper.kt b/src/main/kotlin/top/fatweb/oxygen/api/mapper/tool/StoreMapper.kt new file mode 100644 index 0000000..96da5e0 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/mapper/tool/StoreMapper.kt @@ -0,0 +1,53 @@ +package top.fatweb.oxygen.api.mapper.tool + +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.tool.Tool + +/** + * Tool store mapper + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see BaseMapper + * @see Tool + */ +@Mapper +interface StoreMapper : BaseMapper { + /** + * Select tool ID in page + * + * @param page Pagination + * @param searchValue Value to search for + * @return Tool ID in page + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IPage + */ + fun selectPage(page: IPage, @Param("searchValue") searchValue: String?): IPage + + /** + * Select tool ID by username in page + * + * @param page Pagination + * @param username Username + * @return Tool ID in page + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IPage + */ + fun selectPageByUsername(page: IPage, @Param("username") username: String): IPage + + /** + * Select tool in list by tool IDs + * + * @param ids List of tool IDs + * @return List of tool object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see Tool + */ + fun selectListByIds(@Param("ids") ids: List): List +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/mapper/tool/ToolBaseMapper.kt b/src/main/kotlin/top/fatweb/oxygen/api/mapper/tool/ToolBaseMapper.kt new file mode 100644 index 0000000..26f470f --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/mapper/tool/ToolBaseMapper.kt @@ -0,0 +1,28 @@ +package top.fatweb.oxygen.api.mapper.tool + +import com.baomidou.mybatisplus.core.mapper.BaseMapper +import org.apache.ibatis.annotations.Mapper +import org.apache.ibatis.annotations.Param +import top.fatweb.oxygen.api.entity.tool.ToolBase + +/** + * Tool base mapper + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see BaseMapper + * @see ToolBase + */ +@Mapper +interface ToolBaseMapper : BaseMapper { + /** + * Select tool base by ID + * + * @param id Tool base ID + * @return ToolBase object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolBase + */ + fun selectOne(@Param("id") id: Long): ToolBase? +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/mapper/tool/ToolCategoryMapper.kt b/src/main/kotlin/top/fatweb/oxygen/api/mapper/tool/ToolCategoryMapper.kt new file mode 100644 index 0000000..414eb72 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/mapper/tool/ToolCategoryMapper.kt @@ -0,0 +1,16 @@ +package top.fatweb.oxygen.api.mapper.tool + +import com.baomidou.mybatisplus.core.mapper.BaseMapper +import org.apache.ibatis.annotations.Mapper +import top.fatweb.oxygen.api.entity.tool.ToolCategory + +/** + * Tool category mapper + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see BaseMapper + * @see ToolCategory + */ +@Mapper +interface ToolCategoryMapper : BaseMapper \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/mapper/tool/ToolDataMapper.kt b/src/main/kotlin/top/fatweb/oxygen/api/mapper/tool/ToolDataMapper.kt new file mode 100644 index 0000000..088f219 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/mapper/tool/ToolDataMapper.kt @@ -0,0 +1,16 @@ +package top.fatweb.oxygen.api.mapper.tool + +import com.baomidou.mybatisplus.core.mapper.BaseMapper +import org.apache.ibatis.annotations.Mapper +import top.fatweb.oxygen.api.entity.tool.ToolData + +/** + * Tool data mapper + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see BaseMapper + * @see ToolData + */ +@Mapper +interface ToolDataMapper : BaseMapper \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/mapper/tool/ToolTemplateMapper.kt b/src/main/kotlin/top/fatweb/oxygen/api/mapper/tool/ToolTemplateMapper.kt new file mode 100644 index 0000000..e50c009 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/mapper/tool/ToolTemplateMapper.kt @@ -0,0 +1,38 @@ +package top.fatweb.oxygen.api.mapper.tool + +import com.baomidou.mybatisplus.core.mapper.BaseMapper +import org.apache.ibatis.annotations.Mapper +import org.apache.ibatis.annotations.Param +import top.fatweb.oxygen.api.entity.tool.ToolTemplate + +/** + * Tool template mapper + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see BaseMapper + * @see ToolTemplate + */ +@Mapper +interface ToolTemplateMapper : BaseMapper { + /** + * Select tool template by ID + * + * @param id Tool template ID + * @return ToolTemplate object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolTemplate + */ + fun selectOne(@Param("id") id: Long): ToolTemplate? + + /** + * Select tool template in list + * + * @return List of ToolTemplate object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolTemplate + */ + fun selectList(): List +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/CaptchaCodeParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/CaptchaCodeParam.kt new file mode 100644 index 0000000..fa686ce --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/CaptchaCodeParam.kt @@ -0,0 +1,22 @@ +package top.fatweb.oxygen.api.param + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotBlank + +/** + * Captcha code parameter + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +open class CaptchaCodeParam { + /** + * Captcha code + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "验证码", required = true) + @field:NotBlank(message = "Captcha code can not be blank") + var captchaCode: String? = null +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/PageSortParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/PageSortParam.kt new file mode 100644 index 0000000..cab7e95 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/PageSortParam.kt @@ -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 +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/api/v1/avatar/AvatarBaseParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/api/v1/avatar/AvatarBaseParam.kt new file mode 100644 index 0000000..c949017 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/api/v1/avatar/AvatarBaseParam.kt @@ -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(description = "颜色列表", example = "#FFFFFFAA") + var colors: List? = null + + /** + * Background of image + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "背景颜色", 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 +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/api/v1/avatar/AvatarGitHubParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/api/v1/avatar/AvatarGitHubParam.kt new file mode 100644 index 0000000..6ea06a5 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/api/v1/avatar/AvatarGitHubParam.kt @@ -0,0 +1,32 @@ +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 + * @see AvatarBaseParam + */ +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() diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/permission/ForgetParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/ForgetParam.kt new file mode 100644 index 0000000..de70365 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/ForgetParam.kt @@ -0,0 +1,27 @@ +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 top.fatweb.oxygen.api.param.CaptchaCodeParam + +/** + * Forget password parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see CaptchaCodeParam + */ +@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? +) : CaptchaCodeParam() diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/permission/LoginParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/LoginParam.kt new file mode 100644 index 0000000..df53af9 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/LoginParam.kt @@ -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 top.fatweb.oxygen.api.param.CaptchaCodeParam + +/** + * Login parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see CaptchaCodeParam + */ +@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? +) : CaptchaCodeParam() \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/permission/RegisterParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/RegisterParam.kt new file mode 100644 index 0000000..7b26d33 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/RegisterParam.kt @@ -0,0 +1,50 @@ +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 +import top.fatweb.oxygen.api.param.CaptchaCodeParam + +/** + * Register parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see CaptchaCodeParam + */ +@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, message = "Password must be 10-20 characters") + val password: String? +) : CaptchaCodeParam() \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/permission/RetrieveParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/RetrieveParam.kt new file mode 100644 index 0000000..1b8f685 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/RetrieveParam.kt @@ -0,0 +1,37 @@ +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 +import top.fatweb.oxygen.api.param.CaptchaCodeParam + +/** + * Retrieve password parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see CaptchaCodeParam + */ +@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? +) : CaptchaCodeParam() diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/permission/VerifyParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/VerifyParam.kt new file mode 100644 index 0000000..90e832f --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/VerifyParam.kt @@ -0,0 +1,43 @@ +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 + +/** + * Verify email parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "验证邮箱请求参数") +data class VerifyParam( + /** + * 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?, + + /** + * Nickname + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "昵称", example = "QwQ") + @field:Pattern(regexp = "^.{3,20}$", message = "Nickname must be 3-20 characters") + val nickname: String?, + + /** + * Avatar + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "头像") + val avatar: String? +) \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/permission/group/GroupAddParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/group/GroupAddParam.kt new file mode 100644 index 0000000..6f24d3d --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/group/GroupAddParam.kt @@ -0,0 +1,41 @@ +package top.fatweb.oxygen.api.param.permission.group + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotBlank + +/** + * Add group parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "用户组添加请求参数") +data class GroupAddParam( + /** + * Name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "用户组名称", required = true, example = "Group_1") + @field:NotBlank(message = "Name can not be blank") + val name: String?, + + /** + * Enable + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "启用", allowableValues = ["true", "false"], defaultValue = "true", example = "true") + val enable: Boolean = true, + + /** + * List of role IDs + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "角色 ID 列表") + val roleIds: List? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/permission/group/GroupDeleteParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/group/GroupDeleteParam.kt new file mode 100644 index 0000000..ff08c35 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/group/GroupDeleteParam.kt @@ -0,0 +1,23 @@ +package top.fatweb.oxygen.api.param.permission.group + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotEmpty + +/** + * Delete group parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "用户组删除请求参数") +data class GroupDeleteParam( + /** + * List of group IDs + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "用户组 ID 列表", required = true) + @field: NotEmpty(message = "Ids can not be empty") + val ids: List? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/permission/group/GroupGetParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/group/GroupGetParam.kt new file mode 100644 index 0000000..f494191 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/group/GroupGetParam.kt @@ -0,0 +1,37 @@ +package top.fatweb.oxygen.api.param.permission.group + +import io.swagger.v3.oas.annotations.media.Schema +import top.fatweb.oxygen.api.param.PageSortParam + +/** + * Get group parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see PageSortParam + */ +@Schema(description = "用户组查询请求参数") +data class GroupGetParam( + /** + * Name to search for + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "查询用户组名称", example = "Group_1") + val searchName: String?, + + /** + * Use regex + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema( + description = "查询使用正则表达式", + allowableValues = ["true", "false"], + defaultValue = "false", + example = "false" + ) + val searchRegex: Boolean = false, +) : PageSortParam() diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/permission/group/GroupUpdateParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/group/GroupUpdateParam.kt new file mode 100644 index 0000000..937679c --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/group/GroupUpdateParam.kt @@ -0,0 +1,52 @@ +package top.fatweb.oxygen.api.param.permission.group + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.NotNull + +/** + * Update group parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "用户组更新请求参数") +data class GroupUpdateParam( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "用户组 ID", required = true) + @field:NotNull(message = "ID can not be null") + val id: Long?, + + /** + * Name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "用户组名称", required = true, example = "Group_1") + @field:NotBlank(message = "Name can not be blank") + val name: String?, + + /** + * Enable + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "启用", allowableValues = ["true", "false"], defaultValue = "true", example = "true") + val enable: Boolean = true, + + /** + * List of role IDs + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "角色 ID 列表") + val roleIds: List? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/permission/group/GroupUpdateStatusParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/group/GroupUpdateStatusParam.kt new file mode 100644 index 0000000..2676a93 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/group/GroupUpdateStatusParam.kt @@ -0,0 +1,32 @@ +package top.fatweb.oxygen.api.param.permission.group + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotNull + +/** + * Update status of group parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "用户组更改状态请求参数") +data class GroupUpdateStatusParam( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "用户组 ID", required = true) + @field:NotNull(message = "ID can not be null") + val id: Long?, + + /** + * Enable + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "启用", allowableValues = ["true", "false"], defaultValue = "true", example = "true") + val enable: Boolean = true +) \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/permission/role/RoleAddParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/role/RoleAddParam.kt new file mode 100644 index 0000000..ab093c5 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/role/RoleAddParam.kt @@ -0,0 +1,41 @@ +package top.fatweb.oxygen.api.param.permission.role + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotBlank + +/** + * Add role parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "角色添加请求参数") +data class RoleAddParam( + /** + * Name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "角色名称", required = true, example = "Role_1") + @field:NotBlank(message = "Name can not be blank") + val name: String?, + + /** + * Enable + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "启用", allowableValues = ["true", "false"], defaultValue = "true", example = "true") + val enable: Boolean = true, + + /** + * List of power IDs + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "权限 ID 列表") + val powerIds: List? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/permission/role/RoleDeleteParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/role/RoleDeleteParam.kt new file mode 100644 index 0000000..0704b2a --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/role/RoleDeleteParam.kt @@ -0,0 +1,23 @@ +package top.fatweb.oxygen.api.param.permission.role + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotEmpty + +/** + * Delete role parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "角色删除请求参数") +data class RoleDeleteParam( + /** + * List of role IDs + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "角色 ID 列表", required = true) + @field: NotEmpty(message = "Ids can not be empty") + val ids: List? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/permission/role/RoleGetParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/role/RoleGetParam.kt new file mode 100644 index 0000000..929ba19 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/role/RoleGetParam.kt @@ -0,0 +1,37 @@ +package top.fatweb.oxygen.api.param.permission.role + +import io.swagger.v3.oas.annotations.media.Schema +import top.fatweb.oxygen.api.param.PageSortParam + +/** + * Get role parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see PageSortParam + */ +@Schema(description = "角色查询请求参数") +data class RoleGetParam( + /** + * Name to search for + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "查询角色名称", example = "Role_1") + val searchName: String?, + + /** + * Use regex + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema( + description = "查询使用正则表达式", + allowableValues = ["true", "false"], + defaultValue = "false", + example = "false" + ) + val searchRegex: Boolean = false, +) : PageSortParam() diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/permission/role/RoleUpdateParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/role/RoleUpdateParam.kt new file mode 100644 index 0000000..c24704f --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/role/RoleUpdateParam.kt @@ -0,0 +1,52 @@ +package top.fatweb.oxygen.api.param.permission.role + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.NotNull + +/** + * Update role parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "角色更新请求参数") +data class RoleUpdateParam( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "角色 ID", required = true) + @field:NotNull(message = "Role id can not be null") + val id: Long?, + + /** + * Name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "角色名称", required = true, example = "Role_1") + @field:NotBlank(message = "Name can not be blank") + val name: String?, + + /** + * Enable + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "启用", allowableValues = ["true", "false"], defaultValue = "true", example = "true") + val enable: Boolean = true, + + /** + * List of power IDs + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "权限 ID 列表") + val powerIds: List? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/permission/role/RoleUpdateStatusParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/role/RoleUpdateStatusParam.kt new file mode 100644 index 0000000..5fda3c1 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/role/RoleUpdateStatusParam.kt @@ -0,0 +1,32 @@ +package top.fatweb.oxygen.api.param.permission.role + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotNull + +/** + * Update status of role parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "角色更改状态请求参数") +data class RoleUpdateStatusParam( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "角色 ID", required = true) + @field:NotNull(message = "Role id can not be null") + val id: Long?, + + /** + * Enable + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "启用", allowableValues = ["true", "false"], defaultValue = "true", example = "true") + val enable: Boolean = true +) \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/permission/user/UserAddParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/user/UserAddParam.kt new file mode 100644 index 0000000..ae817a8 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/user/UserAddParam.kt @@ -0,0 +1,129 @@ +package top.fatweb.oxygen.api.param.permission.user + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.Pattern +import java.time.LocalDateTime + +/** + * Add user parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "添加用户请求参数") +data class UserAddParam( + /** + * Username + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "用户名", required = true, example = "User_1") + @field:NotBlank(message = "Username can not be blank") + val username: String?, + + /** + * Password + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "密码(为空自动生成随机密码)") + val password: String?, + + /** + * Verified + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "是否已验证", allowableValues = ["true", "false"], defaultValue = "false", example = "false") + val verified: Boolean = false, + + /** + * Locking + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "锁定", allowableValues = ["true", "false"], defaultValue = "false", example = "false") + val locking: Boolean = false, + + /** + * Expiration time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "过期时间", example = "1900-01-01T00:00:00.000Z") + val expiration: LocalDateTime?, + + /** + * Credentials expiration time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "认证过期时间", example = "1900-01-01T00:00:00.000Z") + val credentialsExpiration: LocalDateTime?, + + /** + * Enable + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "启用", allowableValues = ["true", "false"], defaultValue = "true", example = "true") + val enable: Boolean = true, + + /** + * Nickname + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "昵称", required = true, example = "Nickname_1") + @field:NotBlank(message = "Nickname can not be blank") + val nickname: String?, + + /** + * Avatar base63 + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "头像") + val avatar: String?, + + /** + * Email + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "邮箱", required = true, example = "user@email.com") + @NotBlank(message = "Email can not be blank") + @Pattern(regexp = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*\$", message = "Illegal email address") + val email: String?, + + /** + * List of role IDs + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "角色 ID 列表") + val roleIds: List?, + + /** + * List of group IDs + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "用户组 ID 列表") + val groupIds: List? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/permission/user/UserChangePasswordParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/user/UserChangePasswordParam.kt new file mode 100644 index 0000000..7e704e6 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/user/UserChangePasswordParam.kt @@ -0,0 +1,35 @@ +package top.fatweb.oxygen.api.param.permission.user + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.Size + +/** + * Change password of user parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "用户更改密码请求参数") +data class UserChangePasswordParam( + /** + * Original password + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "原密码", required = true) + @field:NotBlank(message = "Original password can not be blank") + val originalPassword: String?, + + /** + * New password + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "原密码", required = true) + @field:NotBlank(message = "New password can not be blank") + @field:Size(min = 10, max = 30, message = "New password must be 10-20 characters") + val newPassword: String? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/permission/user/UserDeleteParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/user/UserDeleteParam.kt new file mode 100644 index 0000000..714a096 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/user/UserDeleteParam.kt @@ -0,0 +1,23 @@ +package top.fatweb.oxygen.api.param.permission.user + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotEmpty + +/** + * Delete user parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "删除用户请求参数") +data class UserDeleteParam( + /** + * List of user IDs + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "用户 ID 列表", required = true) + @field: NotEmpty(message = "Ids can not be empty") + val ids: List? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/permission/user/UserGetParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/user/UserGetParam.kt new file mode 100644 index 0000000..c8a68ec --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/user/UserGetParam.kt @@ -0,0 +1,51 @@ +package top.fatweb.oxygen.api.param.permission.user + +import io.swagger.v3.oas.annotations.media.Schema +import top.fatweb.oxygen.api.param.PageSortParam + +/** + * Get user parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see PageSortParam + */ +@Schema(description = "查询用户请求参数") +data class UserGetParam( + /** + * Type of search + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema( + description = "搜索类型", + allowableValues = ["ALL", "ID", "USERNAME", "NICKNAME", "EMAIL"], + defaultValue = "ALL", + example = "ALL" + ) + val searchType: String = "ALL", + + /** + * Value to search for + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "查询内容", example = "User_1") + val searchValue: String?, + + /** + * Use regex + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema( + description = "查询使用正则表达式", + allowableValues = ["true", "false"], + defaultValue = "false", + example = "false" + ) + val searchRegex: Boolean = false, +) : PageSortParam() diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/permission/user/UserInfoUpdateParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/user/UserInfoUpdateParam.kt new file mode 100644 index 0000000..92529ed --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/user/UserInfoUpdateParam.kt @@ -0,0 +1,34 @@ +package top.fatweb.oxygen.api.param.permission.user + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.Size + +/** + * Update user information parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "更新用户信息请求参数") +data class UserInfoUpdateParam( + /** + * Avatar base64 + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "头像") + val avatar: String?, + + /** + * Nickname + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "昵称", example = "QwQ") + @field:NotBlank(message = "Nickname can not be blank") + @field:Size(min = 3, max = 30, message = "Nickname must be 3-20 characters") + val nickname: String? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/permission/user/UserUpdateParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/user/UserUpdateParam.kt new file mode 100644 index 0000000..b8830a6 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/user/UserUpdateParam.kt @@ -0,0 +1,131 @@ +package top.fatweb.oxygen.api.param.permission.user + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern +import java.time.LocalDateTime + +/** + * Update user parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "更新用户请求参数") +data class UserUpdateParam( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "用户 ID", required = true) + @field:NotNull(message = "ID can not be null") + val id: Long?, + + /** + * Username + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "用户名", required = true, example = "User_1") + @field:NotBlank(message = "Username can not be blank") + val username: String?, + + /** + * Verified + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "是否已验证", allowableValues = ["true", "false"], defaultValue = "false", example = "false") + val verified: Boolean = false, + + /** + * Locking + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "锁定", allowableValues = ["true", "false"], defaultValue = "false", example = "false") + val locking: Boolean = false, + + /** + * Expiration time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "过期时间", example = "1900-01-01T00:00:00.000Z") + val expiration: LocalDateTime?, + + /** + * Credentials expiration time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "认证过期时间", example = "1900-01-01T00:00:00.000Z") + val credentialsExpiration: LocalDateTime?, + + /** + * Enable + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "启用", allowableValues = ["true", "false"], defaultValue = "true", example = "true") + val enable: Boolean = true, + + /** + * Nickname + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "昵称", required = true, example = "Nickname_1") + @field:NotBlank(message = "Nickname can not be blank") + val nickname: String?, + + /** + * Avatar base64 + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "头像") + val avatar: String?, + + /** + * Email + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "邮箱", required = true, example = "user@email.com") + @NotBlank(message = "Email can not be blank") + @Pattern(regexp = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*\$", message = "Illegal email address") + val email: String?, + + /** + * List of role IDs + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "角色 ID 列表") + val roleIds: List?, + + /** + * List of group IDs + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "用户组 ID 列表") + val groupIds: List? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/permission/user/UserUpdatePasswordParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/user/UserUpdatePasswordParam.kt new file mode 100644 index 0000000..3801ecd --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/permission/user/UserUpdatePasswordParam.kt @@ -0,0 +1,45 @@ +package top.fatweb.oxygen.api.param.permission.user + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.NotNull +import java.time.LocalDateTime + +/** + * Update password of user parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "更改用户密码请求参数") +data class UserUpdatePasswordParam( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "用户 ID", required = true) + @field:NotNull(message = "ID can not be null") + val id: Long?, + + /** + * New 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?, + + /** + * Credentials expiration time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "认证过期时间", example = "1900-01-01T00:00:00.000Z") + val credentialsExpiration: LocalDateTime? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/system/ActiveInfoGetParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/system/ActiveInfoGetParam.kt new file mode 100644 index 0000000..c085c80 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/system/ActiveInfoGetParam.kt @@ -0,0 +1,46 @@ +package top.fatweb.oxygen.api.param.system + +import com.baomidou.mybatisplus.annotation.EnumValue +import com.fasterxml.jackson.annotation.JsonValue +import io.swagger.v3.oas.annotations.media.Schema + +/** + * Get active information parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "用户活跃信息请求参数") +data class ActiveInfoGetParam( + /** + * Scope + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema( + description = "范围", + allowableValues = ["WEAK", "MONTH", "QUARTER", "YEAR", "TWO_YEARS", "THREE_YEARS", "FIVE_YEARS", "ALL"], + defaultValue = "WEAK", + example = "WEAK" + ) + val scope: Scope = Scope.WEAK +) { + enum class Scope(@field:EnumValue @field:JsonValue val code: String) { + WEAK("WEAK"), + + MONTH("MONTH"), + + QUARTER("QUARTER"), + + YEAR("YEAR"), + + TWO_YEARS("TWO_YEARS"), + + THREE_YEARS("THREE_YEARS"), + + FIVE_YEARS("FIVE_YEARS"), + + ALL("ALL") + } +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/system/BaseSettingsParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/system/BaseSettingsParam.kt new file mode 100644 index 0000000..eaf5226 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/system/BaseSettingsParam.kt @@ -0,0 +1,48 @@ +package top.fatweb.oxygen.api.param.system + +import io.swagger.v3.oas.annotations.media.Schema + +/** + * Base settings parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "基础设置请求参数") +data class BaseSettingsParam( + /** + * Application name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "应用名称") + val appName: String?, + + /** + * Application URL + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "应用 URL") + val appUrl: String?, + + /** + * Verify URL + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "验证邮箱 URL") + val verifyUrl: String?, + + /** + * Retrieve URL + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "找回密码 URL") + val retrieveUrl: String? +) \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/system/MailSendParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/system/MailSendParam.kt new file mode 100644 index 0000000..08ffd20 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/system/MailSendParam.kt @@ -0,0 +1,23 @@ +package top.fatweb.oxygen.api.param.system + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotBlank + +/** + * Mail send parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "邮件发送请求参数") +data class MailSendParam( + /** + * Receiver + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "接收者", required = true, example = "user@email.com") + @field:NotBlank + val to: String? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/system/MailSettingsParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/system/MailSettingsParam.kt new file mode 100644 index 0000000..d56ca69 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/system/MailSettingsParam.kt @@ -0,0 +1,76 @@ +package top.fatweb.oxygen.api.param.system + +import io.swagger.v3.oas.annotations.media.Schema +import top.fatweb.oxygen.api.settings.MailSecurityType + +/** + * Mail settings parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "邮件设置请求参数") +data class MailSettingsParam( + /** + * Host + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "SMTP 服务器") + val host: String?, + + /** + * Port + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "端口号") + val port: Int?, + + /** + * Security type + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "安全类型", allowableValues = ["None", "SSL/TLS", "StartTls"], defaultValue = "None") + val securityType: MailSecurityType? = MailSecurityType.NONE, + + /** + * Username + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "用户名") + val username: String?, + + /** + * Password + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "密码") + val password: String?, + + /** + * Sender + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "发送者") + val from: String?, + + /** + * Sender name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "发送者名称") + val fromName: String? +) \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/system/OnlineInfoGetParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/system/OnlineInfoGetParam.kt new file mode 100644 index 0000000..932f10e --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/system/OnlineInfoGetParam.kt @@ -0,0 +1,48 @@ +package top.fatweb.oxygen.api.param.system + +import com.baomidou.mybatisplus.annotation.EnumValue +import com.fasterxml.jackson.annotation.JsonValue +import io.swagger.v3.oas.annotations.media.Schema + +/** + * Get online information parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "在线信息请求参数") +data class OnlineInfoGetParam( + /** + * Scope + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema( + description = "范围", + allowableValues = ["WEAK", "MONTH", "QUARTER", "YEAR", "TWO_YEARS", "THREE_YEARS", "FIVE_YEARS", "ALL"], + defaultValue = "WEAK", + example = "WEAK" + ) + val scope: Scope = Scope.WEAK +) { + enum class Scope(@field:EnumValue @field:JsonValue val code: String) { + DAY("DAY"), + + WEAK("WEAK"), + + MONTH("MONTH"), + + QUARTER("QUARTER"), + + YEAR("YEAR"), + + TWO_YEARS("TWO_YEARS"), + + THREE_YEARS("THREE_YEARS"), + + FIVE_YEARS("FIVE_YEARS"), + + ALL("ALL") + } +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/system/SensitiveWordAddParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/system/SensitiveWordAddParam.kt new file mode 100644 index 0000000..6071bf2 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/system/SensitiveWordAddParam.kt @@ -0,0 +1,43 @@ +package top.fatweb.oxygen.api.param.system + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotBlank +import top.fatweb.oxygen.api.entity.system.SensitiveWord + +/** + * Add sensitive word settings parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(defaultValue = "敏感词添加请求参数") +data class SensitiveWordAddParam( + /** + * Word + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "词", required = true) + @field:NotBlank(message = "Word can not be blank") + val word: String?, + + /** + * Use for + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see SensitiveWord.Use + */ + @Schema(description = "用于", allowableValues = ["USERNAME"]) + val useFor: Set = emptySet(), + + /** + * Enable + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "启用", allowableValues = ["true", "false"], defaultValue = "true") + val enable: Boolean = true +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/system/SensitiveWordUpdateParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/system/SensitiveWordUpdateParam.kt new file mode 100644 index 0000000..1faf759 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/system/SensitiveWordUpdateParam.kt @@ -0,0 +1,15 @@ +package top.fatweb.oxygen.api.param.system + +import io.swagger.v3.oas.annotations.media.Schema + +/** + * Update sensitive word settings parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(defaultValue = "敏感词修改请求参数") +data class SensitiveWordUpdateParam( + @Schema(description = "ID 列表") + val ids: Set = emptySet() +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/system/SysLogGetParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/system/SysLogGetParam.kt new file mode 100644 index 0000000..ef5263b --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/system/SysLogGetParam.kt @@ -0,0 +1,84 @@ +package top.fatweb.oxygen.api.param.system + +import io.swagger.v3.oas.annotations.media.Schema +import org.springframework.format.annotation.DateTimeFormat +import top.fatweb.oxygen.api.param.PageSortParam +import java.time.LocalDateTime + +/** + * Get system log parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see PageSortParam + */ +@Schema(description = "获取系统日志请求参数") +data class SysLogGetParam( + /** + * Log type + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema( + description = "类型过滤(多个使用逗号分隔)", + allowableValues = ["INFO", "LOGIN", "LOGOUT", "REGISTER", "STATISTICS", "API", "ERROR"], + example = "INFO" + ) + val logType: String?, + + /** + * Request method to filter + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema( + description = "请求方式过滤(多个使用逗号分隔)", + allowableValues = ["GET", "POST", "PUT", "PATCH", "DELETE", "DELETE", "OPTIONS"], + example = "GET,POST" + ) + val requestMethod: String?, + + /** + * Request URL to search for + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "查询请求 Url") + val searchRequestUrl: String?, + + /** + * Use regex + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + /* + @Schema(description = "查询使用正则表达式", allowableValues = ["true", "false"], defaultValue = "false") + val searchRegex: Boolean = false, + */ + + /** + * Start time to search for + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "查询开始时间", example = "1900-01-01T00:00:00.000Z") + @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") + val searchStartTime: LocalDateTime?, + + /** + * End time to search for + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "查询结束时间", example = "1900-01-01T00:00:00.000Z") + @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") + val searchEndTime: LocalDateTime? +) : PageSortParam() \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolBaseAddParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolBaseAddParam.kt new file mode 100644 index 0000000..582925b --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolBaseAddParam.kt @@ -0,0 +1,22 @@ +package top.fatweb.oxygen.api.param.tool + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotBlank + +/** + * Add tool base parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +data class ToolBaseAddParam( + /** + * Name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "名称", required = true) + @field: NotBlank(message = "Name can not be blank") + val name: String? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolBaseUpdateParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolBaseUpdateParam.kt new file mode 100644 index 0000000..d4da30e --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolBaseUpdateParam.kt @@ -0,0 +1,49 @@ +package top.fatweb.oxygen.api.param.tool + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotNull + +/** + * Update tool base parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +data class ToolBaseUpdateParam( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "ID", required = true) + @field: NotNull(message = "ID can not be null") + val id: Long?, + + /** + * Name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "名称") + val name: String?, + + /** + * Source + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "源码") + val source: String?, + + /** + * Dist + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "产物") + val dist: String? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolCategoryAddParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolCategoryAddParam.kt new file mode 100644 index 0000000..657bb98 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolCategoryAddParam.kt @@ -0,0 +1,31 @@ +package top.fatweb.oxygen.api.param.tool + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotBlank + +/** + * Add tool category parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +data class ToolCategoryAddParam( + /** + * Name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "名称", required = true) + @field: NotBlank(message = "Name can not be blank") + val name: String?, + + /** + * Enable + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "启用", allowableValues = ["true", "false"], defaultValue = "true") + val enable: Boolean = true +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolCategoryUpdateParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolCategoryUpdateParam.kt new file mode 100644 index 0000000..84496b3 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolCategoryUpdateParam.kt @@ -0,0 +1,40 @@ +package top.fatweb.oxygen.api.param.tool + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotNull + +/** + * Update tool category parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +data class ToolCategoryUpdateParam( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "ID", required = true) + @field: NotNull(message = "ID can not be null") + val id: Long?, + + /** + * Name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "名称") + val name: String?, + + /** + * Enable + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "启用", allowableValues = ["true", "false"]) + val enable: Boolean? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolCreateParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolCreateParam.kt new file mode 100644 index 0000000..3cb0361 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolCreateParam.kt @@ -0,0 +1,100 @@ +package top.fatweb.oxygen.api.param.tool + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.NotEmpty +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Pattern + +/** + * Create tool parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "创建工具请求参数") +data class ToolCreateParam( + /** + * Name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "名称", required = true) + @field: NotBlank(message = "Name can not be blank") + val name: String?, + + /** + * Tool ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "工具唯一 ID", required = true, example = "tool_a") + @field: NotBlank(message = "ToolId can not be blank") + @field: Pattern( + regexp = "^[a-zA-Z-_][0-9a-zA-Z-_]{2,19}\$", + message = "Ver can only match '^[a-zA-Z-_][0-9a-zA-Z-_]{2,19}\$'" + ) + val toolId: String?, + + /** + * Icon + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "图标", required = true) + @field: NotBlank(message = "Icon can not be blank") + val icon: String?, + + /** + * Description + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "简介") + val description: String?, + + /** + * Version + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "版本", required = true, example = "1.0.3") + @field: NotBlank(message = "Ver can not be blank") + @field: Pattern(regexp = "^\\d+\\.\\d+\\.\\d+\$", message = "Ver can only match '..'") + val ver: String?, + + /** + * Template ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "模板 ID", required = true) + @field: NotNull(message = "TemplateId can not be null") + val templateId: Long?, + + /** + * Keywords + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "关键词", required = true) + @field: NotEmpty(message = "Keywords can not be empty") + val keywords: List?, + + /** + * Categories + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "类别", required = true) + @field: NotEmpty(message = "Categories can not be empty") + val categories: List? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolManagementGetParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolManagementGetParam.kt new file mode 100644 index 0000000..dd58600 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolManagementGetParam.kt @@ -0,0 +1,63 @@ +package top.fatweb.oxygen.api.param.tool + +import io.swagger.v3.oas.annotations.media.Schema +import top.fatweb.oxygen.api.param.PageSortParam + +/** + * Get tool parameters in tool management + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see PageSortParam + */ +data class ToolManagementGetParam( + /** + * Type of search + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema( + description = "搜索类型", + allowableValues = ["ALL", "NAME", "TOOL_ID", "NICKNAME", "USERNAME", "KEYWORD"], + defaultValue = "ALL", + example = "ALL" + ) + val searchType: String = "ALL", + + /** + * Value to search for + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "查询内容", example = "ToolName") + val searchValue: String?, + + /** + * Use regex + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema( + description = "查询使用正则表达式", + allowableValues = ["true", "false"], + defaultValue = "false", + example = "false" + ) + val searchRegex: Boolean = false, + + /** + * Review + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema( + description = "审核状态过滤(多个使用逗号分隔)", + allowableValues = ["NONE", "PROCESSING", "REJECT", "PASS"], + example = "NONE,PASS" + ) + val review: String? +) : PageSortParam() diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolManagementPassParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolManagementPassParam.kt new file mode 100644 index 0000000..bf993c1 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolManagementPassParam.kt @@ -0,0 +1,22 @@ +package top.fatweb.oxygen.api.param.tool + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotBlank + +/** + * Pass tool parameters in tool management + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +data class ToolManagementPassParam( + /** + * Dist + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "产物") + @field:NotBlank(message = "Dist can not be blank") + val dist: String? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolStoreGetParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolStoreGetParam.kt new file mode 100644 index 0000000..a83ae41 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolStoreGetParam.kt @@ -0,0 +1,16 @@ +package top.fatweb.oxygen.api.param.tool + +import io.swagger.v3.oas.annotations.media.Schema +import top.fatweb.oxygen.api.param.PageSortParam + +/** + * Get tool parameters in tool store + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see PageSortParam + */ +data class ToolStoreGetParam( + @Schema(description = "查询内容", example = "ToolName") + val searchValue: String? +) : PageSortParam() diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolTemplateAddParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolTemplateAddParam.kt new file mode 100644 index 0000000..137c554 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolTemplateAddParam.kt @@ -0,0 +1,52 @@ +package top.fatweb.oxygen.api.param.tool + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.NotNull + +/** + * Add tool template parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +data class ToolTemplateAddParam( + /** + * Name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "名称", required = true) + @field: NotBlank(message = "Name can not be blank") + val name: String?, + + /** + * Base ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "Base ID", required = true) + @field: NotNull(message = "BaseId can not be null") + val baseId: Long? = null, + + /** + * Entry point + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "入口文件", required = true) + @field:NotBlank(message = "EntryPoint can not be null") + val entryPoint: String? = null, + + /** + * Enable + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "启用", allowableValues = ["true", "false"], defaultValue = "true") + val enable: Boolean = true +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolTemplateUpdateParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolTemplateUpdateParam.kt new file mode 100644 index 0000000..523f74d --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolTemplateUpdateParam.kt @@ -0,0 +1,67 @@ +package top.fatweb.oxygen.api.param.tool + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotNull + +/** + * Update tool template parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +data class ToolTemplateUpdateParam( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "ID", required = true) + @field: NotNull(message = "ID can not be null") + val id: Long?, + + /** + * Name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "名称") + val name: String?, + + /** + * Base ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "Base ID") + val baseId: Long?, + + /** + * Source + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "源码") + val source: String?, + + /** + * Entry point + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "入口文件") + val entryPoint: String?, + + /** + * Enable + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "启用", allowableValues = ["true", "false"]) + val enable: Boolean? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolUpdateParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolUpdateParam.kt new file mode 100644 index 0000000..935ceef --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolUpdateParam.kt @@ -0,0 +1,77 @@ +package top.fatweb.oxygen.api.param.tool + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotNull + +/** + * Update tool parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "更新工具请求参数") +data class ToolUpdateParam( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "ID", required = true) + @field: NotNull(message = "ID can not be null") + val id: Long?, + + /** + * Name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "名称") + val name: String?, + + /** + * Icon + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "图标") + val icon: String?, + + /** + * Description + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "简介") + val description: String?, + + /** + * Keywords + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "关键词") + val keywords: List?, + + /** + * Categories + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "类别") + val categories: List?, + + /** + * Source + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "源码") + val source: String? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolUpgradeParam.kt b/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolUpgradeParam.kt new file mode 100644 index 0000000..e3cca51 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/param/tool/ToolUpgradeParam.kt @@ -0,0 +1,39 @@ +package top.fatweb.oxygen.api.param.tool + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotBlank +import jakarta.validation.constraints.Pattern + +/** + * Upgrade tool parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "升级工具请求参数") +data class ToolUpgradeParam( + /** + * Tool ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "工具唯一 ID", required = true, example = "tool_a") + @field: NotBlank(message = "ToolId can not be blank") + @field: Pattern( + regexp = "^[a-zA-Z-_][0-9a-zA-Z-_]{2,19}\$", + message = "Ver can only match '^[a-zA-Z-_][0-9a-zA-Z-_]{2,19}\$'" + ) + val toolId: String?, + + /** + * Version + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "版本", required = true, example = "1.0.3") + @field: NotBlank(message = "Ver can not be blank") + @field: Pattern(regexp = "^\\d+\\.\\d+\\.\\d+\$", message = "Ver can only match '..'") + val ver: String? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/properties/AdminProperties.kt b/src/main/kotlin/top/fatweb/oxygen/api/properties/AdminProperties.kt new file mode 100644 index 0000000..4638122 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/properties/AdminProperties.kt @@ -0,0 +1,46 @@ +package top.fatweb.oxygen.api.properties + +import org.springframework.boot.context.properties.ConfigurationProperties +import org.springframework.stereotype.Component + +/** + * Admin properties + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Component +@ConfigurationProperties("app.admin") +object AdminProperties { + /** + * Username + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var username = "admin" + + /** + * Password + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var password: String? = null + + /** + * Nickname + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var nickname = "Administrator" + + /** + * Email + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var email = "admin@mail.com" +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/properties/FlywayProperties.kt b/src/main/kotlin/top/fatweb/oxygen/api/properties/FlywayProperties.kt new file mode 100644 index 0000000..c6f857e --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/properties/FlywayProperties.kt @@ -0,0 +1,95 @@ +package top.fatweb.oxygen.api.properties + +import org.springframework.boot.context.properties.ConfigurationProperties +import org.springframework.stereotype.Component + +/** + * Flyway properties + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Component +@ConfigurationProperties("spring.flyway") +object FlywayProperties { + /** + * Locations of migrations scripts. Can contain the special "{vendor}" placeholder to + * use vendor-specific locations. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var locations = listOf("classpath:db/migration") + + /** + * Name of the schema history table that will be used by Flyway. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var table = "flyway_schema_history" + + /** + * Whether to allow migrations to be run out of order. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var outOfOrder = false + + /** + * Whether to automatically call validate when performing a migration. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var validateOnMigrate = true + + /** + * Encoding of SQL migrations. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var encoding = Charsets.UTF_8 + + /** + * File name prefix for SQL migrations. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var sqlMigrationPrefix = "V" + + /** + * File name separator for SQL migrations. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var sqlMigrationSeparator = "__" + + /** + * File name suffix for SQL migrations. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var sqlMigrationSuffixes = listOf(".sql") + + /** + * Whether to automatically call baseline when migrating a non-empty schema. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var baselineOnMigrate = true + + /** + * Version to tag an existing schema with when executing baseline. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var baselineVersion = "0" +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/properties/SecurityProperties.kt b/src/main/kotlin/top/fatweb/oxygen/api/properties/SecurityProperties.kt new file mode 100644 index 0000000..fe70e6d --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/properties/SecurityProperties.kt @@ -0,0 +1,79 @@ +package top.fatweb.oxygen.api.properties + +import org.springframework.boot.context.properties.ConfigurationProperties +import org.springframework.stereotype.Component +import java.util.concurrent.TimeUnit + +/** + * Security properties + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Component +@ConfigurationProperties("app.security") +object SecurityProperties { + /** + * Key to get authentication from header + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var headerKey = "Authorization" + + /** + * Prefix of token + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var tokenPrefix = "Bearer " + + /** + * TTL of JWT + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var jwtTtl = 2L + + /** + * TTL unit of JWT + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var jwtTtlUnit = TimeUnit.HOURS + + /** + * Key of JWT + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var jwtKey = "Oxygen" + + /** + * Issuer of JWT + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var jwtIssuer = "Oxygen" + + /** + * TTL of redis + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var redisTtl = 20L + + /** + * TTL unit of redis + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var redisTtlUnit = TimeUnit.MINUTES +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/properties/ServerProperties.kt b/src/main/kotlin/top/fatweb/oxygen/api/properties/ServerProperties.kt new file mode 100644 index 0000000..83b2835 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/properties/ServerProperties.kt @@ -0,0 +1,61 @@ +package top.fatweb.oxygen.api.properties + +import org.springframework.boot.context.properties.ConfigurationProperties +import org.springframework.stereotype.Component +import java.time.LocalDateTime +import java.time.ZoneId +import java.time.ZoneOffset +import java.time.ZonedDateTime + +/** + * Application properties + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Component +@ConfigurationProperties("app") +object ServerProperties { + /** + * App name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + lateinit var appName: String + + /** + * Version + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + lateinit var version: String + + /** + * Build time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + lateinit var buildTime: String + + /** + * Startup time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + val startupTime: LocalDateTime = LocalDateTime.now(ZoneOffset.UTC) + + /** + * Turnstile secret key + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + lateinit var turnstileSecretKey: String + + fun buildZoneDateTime(zoneId: ZoneId = ZoneId.systemDefault()): ZonedDateTime = + LocalDateTime.parse(buildTime).atZone(ZoneId.of("UTC")).withZoneSameInstant(zoneId) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/api/v1/IAvatarService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/api/v1/IAvatarService.kt new file mode 100644 index 0000000..46520c9 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/api/v1/IAvatarService.kt @@ -0,0 +1,125 @@ +package top.fatweb.oxygen.api.service.api.v1 + +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.vo.api.v1.avatar.AvatarBase64Vo + +/** + * Avatar service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +interface IAvatarService { + /** + * Generate random avatar + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun random(avatarBaseParam: AvatarBaseParam?): ByteArray + + /** + * Generate random avatar as base64 + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun randomBase64(avatarBaseParam: AvatarBaseParam?): AvatarBase64Vo + + /** + * Generate triangle style avatar + * + * @param avatarBaseParam Avatar base parameters + * @return Avatar byte array + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see AvatarBaseParam + * @see ByteArray + */ + fun triangle(avatarBaseParam: AvatarBaseParam?): ByteArray + + /** + * Generate triangle style avatar as base64 + * + * @param avatarBaseParam Avatar base parameters + * @return AvatarBase64Vo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see AvatarBaseParam + * @see AvatarBase64Vo + */ + fun triangleBase64(avatarBaseParam: AvatarBaseParam?): AvatarBase64Vo + + /** + * Generate square style avatar + * + * @param avatarBaseParam Avatar base parameters + * @return Avatar byte array + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see AvatarBaseParam + * @see ByteArray + */ + fun square(avatarBaseParam: AvatarBaseParam?): ByteArray + + /** + * Generate square style avatar as base64 + * + * @param avatarBaseParam Avatar base parameters + * @return AvatarBase64Vo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see AvatarBaseParam + * @see AvatarBase64Vo + */ + fun squareBase64(avatarBaseParam: AvatarBaseParam?): AvatarBase64Vo + + /** + * Generate identicon style avatar + * + * @param avatarBaseParam Avatar base parameters + * @return Avatar byte array + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see AvatarBaseParam + * @see ByteArray + */ + fun identicon(avatarBaseParam: AvatarBaseParam?): ByteArray + + /** + * Generate identicon style avatar as base64 + * + * @param avatarBaseParam Avatar base parameters + * @return AvatarBase64Vo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see AvatarBaseParam + * @see AvatarBase64Vo + */ + fun identiconBase64(avatarBaseParam: AvatarBaseParam?): AvatarBase64Vo + + /** + * Generate GitHub style avatar + * + * @param avatarGitHubParam Avatar base parameters + * @return Avatar byte array + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see AvatarBaseParam + * @see ByteArray + */ + fun github(avatarGitHubParam: AvatarGitHubParam?): ByteArray + + /** + * Generate GitHub style avatar as base64 + * + * @param avatarGitHubParam Avatar base parameters + * @return AvatarBase64Vo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see AvatarBaseParam + * @see AvatarBase64Vo + */ + fun githubBase64(avatarGitHubParam: AvatarGitHubParam?): AvatarBase64Vo +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/api/v1/impl/AvatarServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/api/v1/impl/AvatarServiceImpl.kt new file mode 100644 index 0000000..630d46b --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/api/v1/impl/AvatarServiceImpl.kt @@ -0,0 +1,144 @@ +package top.fatweb.oxygen.api.service.api.v1.impl + +import org.springframework.stereotype.Service +import top.fatweb.avatargenerator.GitHubAvatar +import top.fatweb.avatargenerator.IdenticonAvatar +import top.fatweb.avatargenerator.SquareAvatar +import top.fatweb.avatargenerator.TriangleAvatar +import top.fatweb.avatargenerator.layer.background.ColorPaintBackgroundLayer +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.util.NumberUtil +import top.fatweb.oxygen.api.vo.api.v1.avatar.AvatarBase64Vo +import java.awt.Color +import kotlin.io.encoding.Base64 +import kotlin.io.encoding.ExperimentalEncodingApi + +/** + * Avatar service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IAvatarService + */ +@OptIn(ExperimentalEncodingApi::class) +@Service +class AvatarServiceImpl : IAvatarService { + override fun random(avatarBaseParam: AvatarBaseParam?): ByteArray = + when ((1..4).random()) { + 1 -> triangle(avatarBaseParam) + 2 -> square(avatarBaseParam) + 3 -> identicon(avatarBaseParam) + else -> github(AvatarGitHubParam().apply { + seed = avatarBaseParam?.seed + size = avatarBaseParam?.size + margin = avatarBaseParam?.margin + padding = avatarBaseParam?.padding + colors = avatarBaseParam?.colors + background = avatarBaseParam?.background + }) + } + + override fun randomBase64(avatarBaseParam: AvatarBaseParam?): AvatarBase64Vo = when ((1..4).random()) { + 1 -> triangleBase64(avatarBaseParam) + 2 -> squareBase64(avatarBaseParam) + 3 -> identiconBase64(avatarBaseParam) + else -> githubBase64(AvatarGitHubParam().apply { + seed = avatarBaseParam?.seed + size = avatarBaseParam?.size + margin = avatarBaseParam?.margin + padding = avatarBaseParam?.padding + colors = avatarBaseParam?.colors + background = avatarBaseParam?.background + }) + } + + override fun triangle(avatarBaseParam: AvatarBaseParam?): ByteArray { + val avatar = ( + if (avatarBaseParam == null || avatarBaseParam.colors.isNullOrEmpty()) + TriangleAvatar.newAvatarBuilder() + else TriangleAvatar.newAvatarBuilder( + *avatarBaseParam.colors!!.map(::decodeColor).toTypedArray() + ) + ).apply { + avatarBaseParam?.size?.let(::size) + avatarBaseParam?.margin?.let(::margin) + avatarBaseParam?.padding?.let(::padding) + avatarBaseParam?.background?.let { layers(ColorPaintBackgroundLayer(decodeColor(it))) } + }.build() + + return avatar.createAsPngBytes(avatarBaseParam?.seed ?: NumberUtil.getRandomLong()) + } + + override fun triangleBase64(avatarBaseParam: AvatarBaseParam?) = + AvatarBase64Vo(Base64.encode(triangle(avatarBaseParam))) + + override fun square(avatarBaseParam: AvatarBaseParam?): ByteArray { + val avatar = ( + if (avatarBaseParam == null || avatarBaseParam.colors.isNullOrEmpty()) + SquareAvatar.newAvatarBuilder() + else SquareAvatar.newAvatarBuilder( + *avatarBaseParam.colors!!.map(::decodeColor).toTypedArray() + ) + ).apply { + avatarBaseParam?.size?.let(::size) + avatarBaseParam?.margin?.let(::margin) + avatarBaseParam?.padding?.let(::padding) + avatarBaseParam?.background?.let { layers(ColorPaintBackgroundLayer(decodeColor(it))) } + }.build() + + return avatar.createAsPngBytes(avatarBaseParam?.seed ?: NumberUtil.getRandomLong()) + } + + override fun squareBase64(avatarBaseParam: AvatarBaseParam?) = + AvatarBase64Vo(Base64.encode(square(avatarBaseParam))) + + override fun identicon(avatarBaseParam: AvatarBaseParam?): ByteArray { + val avatar = IdenticonAvatar.newAvatarBuilder().apply { + avatarBaseParam?.size?.let(::size) + avatarBaseParam?.margin?.let(::margin) + avatarBaseParam?.padding?.let(::padding) + if (avatarBaseParam != null && !avatarBaseParam.colors.isNullOrEmpty()) { + color(decodeColor(avatarBaseParam.colors!!.random())) + } + avatarBaseParam?.background?.let { layers(ColorPaintBackgroundLayer(decodeColor(it))) } + }.build() + + return avatar.createAsPngBytes(avatarBaseParam?.seed ?: NumberUtil.getRandomLong()) + } + + override fun identiconBase64(avatarBaseParam: AvatarBaseParam?) = + AvatarBase64Vo(Base64.encode(identicon(avatarBaseParam))) + + override fun github(avatarGitHubParam: AvatarGitHubParam?): ByteArray { + val avatar = (avatarGitHubParam?.let { GitHubAvatar.newAvatarBuilder(it.elementSize, it.precision) } + ?: let { GitHubAvatar.newAvatarBuilder(400, 5) }).apply { + avatarGitHubParam?.size?.let(::size) + avatarGitHubParam?.margin?.let(::margin) + avatarGitHubParam?.padding?.let(::padding) + if (avatarGitHubParam != null && !avatarGitHubParam.colors.isNullOrEmpty()) { + color(decodeColor(avatarGitHubParam.colors!!.random())) + } + avatarGitHubParam?.background?.let { layers(ColorPaintBackgroundLayer(decodeColor(it))) } + }.build() + + return avatar.createAsPngBytes(avatarGitHubParam?.seed ?: NumberUtil.getRandomLong()) + } + + override fun githubBase64(avatarGitHubParam: AvatarGitHubParam?) = + AvatarBase64Vo(Base64.encode(github(avatarGitHubParam))) + + fun decodeColor(nm: String): Color { + return if (Regex("^#[0-9a-fA-F]{6}$").matches(nm)) { + Color.decode(nm) + } else if (Regex("^#[0-9a-fA-F]{8}$").matches(nm)) { + val intVal = Integer.decode(nm.substring(1..6).prependIndent("#")) + val alpha = Integer.decode(nm.substring(7).prependIndent("#")) + Color(intVal shr 16 and 0xFF, intVal shr 8 and 0XFF, intVal and 0xFF, alpha and 0xFF) + } else { + Color.WHITE + } + } + +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IAuthenticationService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IAuthenticationService.kt new file mode 100644 index 0000000..a242964 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IAuthenticationService.kt @@ -0,0 +1,105 @@ +package top.fatweb.oxygen.api.service.permission + +import jakarta.servlet.http.HttpServletRequest +import top.fatweb.oxygen.api.entity.permission.User +import top.fatweb.oxygen.api.param.permission.* +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 service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +interface IAuthenticationService { + /** + * Register + * + * @param registerParam Register parameters + * @return RegisterVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RegisterParam + * @see RegisterVo + */ + fun register(request: HttpServletRequest, registerParam: RegisterParam): RegisterVo + + /** + * Send verify email + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun resend() + + /** + * Verify email + * + * @param verifyParam Verify parameters + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see VerifyParam + */ + fun verify(verifyParam: VerifyParam) + + /** + * Forget password + * + * @param request + * @param forgetParam Forget parameters + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see HttpServletRequest + * @see ForgetParam + */ + fun forget(request: HttpServletRequest, forgetParam: ForgetParam) + + /** + * Retrieve password + * + * @param request + * @param retrieveParam Retrieve parameters + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see HttpServletRequest + * @see RetrieveParam + */ + fun retrieve(request: HttpServletRequest, retrieveParam: RetrieveParam) + + /** + * Login + * + * @param request + * @param loginParam Login parameters + * @return LoginVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see HttpServletRequest + * @see User + * @see LoginVo + */ + fun login(request: HttpServletRequest, loginParam: LoginParam): LoginVo + + /** + * Logout + * + * @param token Token + * @return Logout result + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun logout(token: String): Boolean + + /** + * Renew token + * + * @param token Token + * @return TokenVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see TokenVo + */ + fun renewToken(token: String): TokenVo +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IFuncService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IFuncService.kt new file mode 100644 index 0000000..36af68a --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IFuncService.kt @@ -0,0 +1,14 @@ +package top.fatweb.oxygen.api.service.permission + +import com.baomidou.mybatisplus.extension.service.IService +import top.fatweb.oxygen.api.entity.permission.Func + +/** + * Function service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IService + * @see Func + */ +interface IFuncService : IService diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IGroupService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IGroupService.kt new file mode 100644 index 0000000..9db4c4f --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IGroupService.kt @@ -0,0 +1,106 @@ +package top.fatweb.oxygen.api.service.permission + +import com.baomidou.mybatisplus.extension.service.IService +import top.fatweb.oxygen.api.entity.permission.Group +import top.fatweb.oxygen.api.param.permission.group.* +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 service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IService + * @see Group + */ +interface IGroupService : IService { + /** + * Get one group by ID + * + * @param id ID + * @return GroupWithRoleVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see GroupWithRoleVo + */ + fun getOne(id: Long): GroupWithRoleVo + + /** + * Get group in page + * + * @param groupGetParam Get group parameters + * @return PageVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see GroupGetParam + * @see PageVo + * @see GroupWithRoleVo + */ + fun getPage(groupGetParam: GroupGetParam?): PageVo + + /** + * Get all group in list + * + * @return List of GroupVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see GroupVo + */ + fun getList(): List + + /** + * Add group + * + * @param groupAddParam Add group parameters + * @return GroupVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see GroupAddParam + * @see GroupVo + */ + fun add(groupAddParam: GroupAddParam): GroupVo + + /** + * Update group + * + * @param groupUpdateParam Update group parameters + * @return GroupVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see GroupUpdateParam + * @see GroupVo + */ + fun update(groupUpdateParam: GroupUpdateParam): GroupVo + + /** + * Update status of group + * + * @param groupUpdateStatusParam Update status of group parameters + * @return Result + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see GroupUpdateStatusParam + */ + fun status(groupUpdateStatusParam: GroupUpdateStatusParam) + + /** + * Delete group by ID + * + * @param id ID + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun deleteOne(id: Long) + + /** + * Delete group by list + * + * @param groupDeleteParam Delete group parameters + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see GroupDeleteParam + */ + fun delete(groupDeleteParam: GroupDeleteParam) +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IMenuService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IMenuService.kt new file mode 100644 index 0000000..967d56a --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IMenuService.kt @@ -0,0 +1,14 @@ +package top.fatweb.oxygen.api.service.permission + +import com.baomidou.mybatisplus.extension.service.IService +import top.fatweb.oxygen.api.entity.permission.Menu + +/** + * Menu service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IService + * @see Menu + */ +interface IMenuService : IService diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IModuleService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IModuleService.kt new file mode 100644 index 0000000..431a84d --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IModuleService.kt @@ -0,0 +1,14 @@ +package top.fatweb.oxygen.api.service.permission + +import com.baomidou.mybatisplus.extension.service.IService +import top.fatweb.oxygen.api.entity.permission.Module + +/** + * Module service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IService + * @see Module + */ +interface IModuleService : IService diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IOperationService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IOperationService.kt new file mode 100644 index 0000000..a468550 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IOperationService.kt @@ -0,0 +1,14 @@ +package top.fatweb.oxygen.api.service.permission + +import com.baomidou.mybatisplus.extension.service.IService +import top.fatweb.oxygen.api.entity.permission.Operation + +/** + * Operation service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IService + * @see Operation + */ +interface IOperationService : IService diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IPowerService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IPowerService.kt new file mode 100644 index 0000000..b5a34cd --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IPowerService.kt @@ -0,0 +1,25 @@ +package top.fatweb.oxygen.api.service.permission + +import com.baomidou.mybatisplus.extension.service.IService +import top.fatweb.oxygen.api.entity.permission.Power +import top.fatweb.oxygen.api.vo.permission.PowerSetVo + +/** + * Power service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IService + * @see Power + */ +interface IPowerService : IService { + /** + * Get all power as list + * + * @return powerSetVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see PowerSetVo + */ + fun getList(): PowerSetVo +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IRPowerRoleService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IRPowerRoleService.kt new file mode 100644 index 0000000..9984d69 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IRPowerRoleService.kt @@ -0,0 +1,14 @@ +package top.fatweb.oxygen.api.service.permission + +import com.baomidou.mybatisplus.extension.service.IService +import top.fatweb.oxygen.api.entity.permission.RPowerRole + +/** + * Power role intermediate service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IService + * @see RPowerRole + */ +interface IRPowerRoleService : IService diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IRRoleGroupService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IRRoleGroupService.kt new file mode 100644 index 0000000..f536395 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IRRoleGroupService.kt @@ -0,0 +1,14 @@ +package top.fatweb.oxygen.api.service.permission + +import com.baomidou.mybatisplus.extension.service.IService +import top.fatweb.oxygen.api.entity.permission.RRoleGroup + +/** + * Role group intermediate service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IService + * @see RRoleGroup + */ +interface IRRoleGroupService : IService diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IRUserGroupService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IRUserGroupService.kt new file mode 100644 index 0000000..008aa4c --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IRUserGroupService.kt @@ -0,0 +1,14 @@ +package top.fatweb.oxygen.api.service.permission + +import com.baomidou.mybatisplus.extension.service.IService +import top.fatweb.oxygen.api.entity.permission.RUserGroup + +/** + * User group intermediate service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IService + * @see RUserGroup + */ +interface IRUserGroupService : IService diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IRUserRoleService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IRUserRoleService.kt new file mode 100644 index 0000000..969f3ee --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IRUserRoleService.kt @@ -0,0 +1,14 @@ +package top.fatweb.oxygen.api.service.permission + +import com.baomidou.mybatisplus.extension.service.IService +import top.fatweb.oxygen.api.entity.permission.RUserRole + +/** + * User role intermediate service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IService + * @see RUserRole + */ +interface IRUserRoleService : IService diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IRoleService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IRoleService.kt new file mode 100644 index 0000000..37d6da7 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IRoleService.kt @@ -0,0 +1,106 @@ +package top.fatweb.oxygen.api.service.permission + +import com.baomidou.mybatisplus.extension.service.IService +import top.fatweb.oxygen.api.entity.permission.Role +import top.fatweb.oxygen.api.param.permission.role.* +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 service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IService + * @see Role + */ +interface IRoleService : IService { + /** + * Get user by ID + * + * @param id ID + * @return RoleWithPowerVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RoleWithPowerVo + */ + fun getOne(id: Long): RoleWithPowerVo + + /** + * Get role in page + * + * @param roleGetParam Get role parameters + * @return PageVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RoleGetParam + * @see PageVo + * @see RoleWithPowerVo + */ + fun getPage(roleGetParam: RoleGetParam?): PageVo + + /** + * Get all role in list + * + * @return List of RoleVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RoleVo + */ + fun getList(): List + + /** + * Add role + * + * @param roleAddParam Add role parameters + * @return RoleVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RoleAddParam + * @see RoleVo + */ + fun add(roleAddParam: RoleAddParam): RoleVo + + /** + * Update role + * + * @param roleUpdateParam Update role parameters + * @return RoleVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RoleUpdateParam + * @see RoleVo + */ + fun update(roleUpdateParam: RoleUpdateParam): RoleVo + + /** + * Update status of role + * + * @param roleUpdateStatusParam Update status of role parameters + * @return Result + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RoleUpdateStatusParam + */ + fun status(roleUpdateStatusParam: RoleUpdateStatusParam) + + /** + * Delete role by ID + * + * @param id ID + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun deleteOne(id: Long) + + /** + * Delete role by list + * + * @param roleDeleteParam Delete role parameters + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RoleDeleteParam + */ + fun delete(roleDeleteParam: RoleDeleteParam) +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IUserInfoService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IUserInfoService.kt new file mode 100644 index 0000000..c2b29f3 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IUserInfoService.kt @@ -0,0 +1,14 @@ +package top.fatweb.oxygen.api.service.permission + +import com.baomidou.mybatisplus.extension.service.IService +import top.fatweb.oxygen.api.entity.permission.UserInfo + +/** + * User information service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IService + * @see UserInfo + */ +interface IUserInfoService : IService diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IUserService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IUserService.kt new file mode 100644 index 0000000..06351d7 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/IUserService.kt @@ -0,0 +1,175 @@ +package top.fatweb.oxygen.api.service.permission + +import com.baomidou.mybatisplus.extension.service.IService +import top.fatweb.oxygen.api.entity.permission.User +import top.fatweb.oxygen.api.param.permission.user.* +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 service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IService + * @see User + */ +interface IUserService : IService { + /** + * Get user with power by username or email + * + * @param account Username or email + * @return User object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see User + */ + fun getUserWithPowerByAccount(account: String): User? + + /** + * Get user information + * + * @return UserWithPowerInfoVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see UserWithPowerInfoVo + */ + fun getInfo(): UserWithPowerInfoVo + + /** + * Get user information by username + * + * @param username Username + * @return UserWithInfoVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see UserWithInfoVo + */ + fun getBasicInfo(username: String): UserWithInfoVo + + /** + * Update user information + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun updateInfo(userInfoUpdateParam: UserInfoUpdateParam): Boolean + + /** + * Change password + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun password(userChangePasswordParam: UserChangePasswordParam) + + /** + * Get one user by ID + * + * @param id ID + * @return UserWithRoleInfoVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see UserWithRoleInfoVo + */ + fun getOne(id: Long): UserWithRoleInfoVo + + /** + * Get user in page + * + * @param userGetParam Get user parameters + * @return PageVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see UserGetParam + * @see PageVo + * @see UserWithRoleInfoVo + */ + fun getPage(userGetParam: UserGetParam?): PageVo + + /** + * Get all user as list + * + * @return List of UserWithInfoVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see UserWithInfoVo + */ + fun getList(): List + + /** + * Add user + * + * @param userAddParam Add user parameters + * @return UserWithPasswordRoleInfoVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see UserAddParam + * @see UserWithPasswordRoleInfoVo + */ + fun add(userAddParam: UserAddParam): UserWithPasswordRoleInfoVo + + /** + * Update user + * + * @param userUpdateParam Update user parameters + * @return UserWithRoleInfoVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see UserUpdateParam + * @see UserWithRoleInfoVo + */ + fun update(userUpdateParam: UserUpdateParam): UserWithRoleInfoVo + + /** + * Update user password + * + * @param userUpdatePasswordParam Update user password parameters + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see UserUpdatePasswordParam + */ + fun password(userUpdatePasswordParam: UserUpdatePasswordParam) + + /** + * Delete user by ID + * + * @param id ID + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun deleteOne(id: Long) + + /** + * Delete user by list + * + * @param userDeleteParam Delete user parameters + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see UserDeleteParam + */ + fun delete(userDeleteParam: UserDeleteParam) + + /** + * Get 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 getIdsWithRoleIds(roleIds: List): List + + /** + * Get 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 getIdsWithGroupIds(groupIds: List): List +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/AuthenticationServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/AuthenticationServiceImpl.kt new file mode 100644 index 0000000..5b360aa --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/AuthenticationServiceImpl.kt @@ -0,0 +1,343 @@ +package top.fatweb.oxygen.api.service.permission.impl + +import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper +import com.baomidou.mybatisplus.extension.kotlin.KtUpdateWrapper +import jakarta.servlet.http.HttpServletRequest +import org.apache.velocity.VelocityContext +import org.apache.velocity.app.VelocityEngine +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.springframework.security.access.AccessDeniedException +import org.springframework.security.authentication.AuthenticationManager +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken +import org.springframework.security.crypto.password.PasswordEncoder +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import top.fatweb.oxygen.api.annotation.EventLogRecord +import top.fatweb.oxygen.api.entity.permission.LoginUser +import top.fatweb.oxygen.api.entity.permission.User +import top.fatweb.oxygen.api.entity.permission.UserInfo +import top.fatweb.oxygen.api.entity.system.EventLog +import top.fatweb.oxygen.api.exception.* +import top.fatweb.oxygen.api.http.TurnstileApi +import top.fatweb.oxygen.api.param.permission.* +import top.fatweb.oxygen.api.properties.SecurityProperties +import top.fatweb.oxygen.api.service.api.v1.IAvatarService +import top.fatweb.oxygen.api.service.permission.IAuthenticationService +import top.fatweb.oxygen.api.service.permission.IUserInfoService +import top.fatweb.oxygen.api.service.permission.IUserService +import top.fatweb.oxygen.api.service.system.ISensitiveWordService +import top.fatweb.oxygen.api.settings.BaseSettings +import top.fatweb.oxygen.api.settings.SettingsOperator +import top.fatweb.oxygen.api.util.JwtUtil +import top.fatweb.oxygen.api.util.MailUtil +import top.fatweb.oxygen.api.util.RedisUtil +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 +import java.io.StringWriter +import java.time.Instant +import java.time.LocalDateTime +import java.time.ZoneOffset +import java.util.* + +/** + * Authentication service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see AuthenticationManager + * @see RedisUtil + * @see IUserService + * @see IAuthenticationService + */ +@Service +class AuthenticationServiceImpl( + private val velocityEngine: VelocityEngine, + private val authenticationManager: AuthenticationManager, + private val passwordEncoder: PasswordEncoder, + private val redisUtil: RedisUtil, + private val turnstileApi: TurnstileApi, + private val userService: IUserService, + private val userInfoService: IUserInfoService, + private val sensitiveWordService: ISensitiveWordService, + private val avatarService: IAvatarService +) : IAuthenticationService { + private val logger: Logger = LoggerFactory.getLogger(this::class.java) + + @EventLogRecord(EventLog.Event.REGISTER) + @Transactional + override fun register(request: HttpServletRequest, registerParam: RegisterParam): RegisterVo { + verifyCaptcha(registerParam.captchaCode!!) + sensitiveWordService.checkSensitiveWord(registerParam.username!!) + + val user = User().apply { + username = registerParam.username + password = passwordEncoder.encode(registerParam.password) + verify = + "${ + LocalDateTime.now(ZoneOffset.UTC).toInstant(ZoneOffset.UTC).toEpochMilli() + }-${UUID.randomUUID()}-${UUID.randomUUID()}-${UUID.randomUUID()}" + locking = 0 + enable = 1 + } + userService.save(user) + userInfoService.save(UserInfo().apply { + userId = user.id + nickname = registerParam.username + avatar = avatarService.randomBase64(null).base64 + email = registerParam.email + }) + + sendVerifyMail(user.username!!, user.verify!!, registerParam.email!!) + + val loginVo = this.login(request, registerParam.username, registerParam.password!!) + + return RegisterVo(token = loginVo.token, userId = loginVo.userId) + } + + @Transactional + override fun resend() { + val user = userService.getById(WebUtil.getLoginUserId()) + + user.verify ?: throw NoVerificationRequiredException() + + if (LocalDateTime.ofInstant(Instant.ofEpochMilli(user.verify!!.split("-").first().toLong()), ZoneOffset.UTC) + .isAfter(LocalDateTime.now(ZoneOffset.UTC).minusMinutes(5)) + ) { + throw RequestTooFrequentException() + } + + user.verify = + "${ + LocalDateTime.now(ZoneOffset.UTC).toInstant(ZoneOffset.UTC).toEpochMilli() + }-${UUID.randomUUID()}-${UUID.randomUUID()}-${UUID.randomUUID()}" + user.updateTime = LocalDateTime.now(ZoneOffset.UTC) + userService.updateById(user) + + WebUtil.getLoginUser()?.user?.userInfo?.email?.let { + sendVerifyMail(user.username!!, user.verify!!, it) + } ?: throw AccessDeniedException("Access Denied") + } + + @EventLogRecord(EventLog.Event.VERIFY) + @Transactional + override fun verify(verifyParam: VerifyParam) { + val user = userService.getById(WebUtil.getLoginUserId()) + user.verify ?: throw NoVerificationRequiredException() + if (LocalDateTime.ofInstant(Instant.ofEpochMilli(user.verify!!.split("-").first().toLong()), ZoneOffset.UTC) + .isBefore(LocalDateTime.now(ZoneOffset.UTC).minusHours(2)) || user.verify != verifyParam.code + ) { + throw VerificationCodeErrorOrExpiredException() + } + + if (verifyParam.nickname.isNullOrBlank() || verifyParam.avatar.isNullOrBlank()) { + throw AccountNeedInitException() + } + sensitiveWordService.checkSensitiveWord(verifyParam.nickname) + + userService.update( + KtUpdateWrapper(User()).eq(User::id, user.id).set(User::verify, null) + .set(User::updateTime, LocalDateTime.now(ZoneOffset.UTC)) + ) + userInfoService.update( + KtUpdateWrapper(UserInfo()).eq(UserInfo::userId, user.id).set(UserInfo::nickname, verifyParam.nickname) + .set(UserInfo::avatar, verifyParam.avatar) + ) + } + + @Transactional + override fun forget(request: HttpServletRequest, forgetParam: ForgetParam) { + verifyCaptcha(forgetParam.captchaCode!!) + + val user = userService.getUserWithPowerByAccount(forgetParam.email!!) + user ?: throw UserNotFoundException() + + user.forget?.let { + if (LocalDateTime.ofInstant(Instant.ofEpochMilli(it.split("-").first().toLong()), ZoneOffset.UTC) + .isAfter(LocalDateTime.now(ZoneOffset.UTC).minusMinutes(5)) + ) { + throw RequestTooFrequentException() + } + } + + val code = "${ + LocalDateTime.now(ZoneOffset.UTC).toInstant(ZoneOffset.UTC).toEpochMilli() + }-${UUID.randomUUID()}-${UUID.randomUUID()}-${UUID.randomUUID()}" + userService.update(KtUpdateWrapper(User()).eq(User::id, user.id).set(User::forget, code)) + sendRetrieveMail(user.username!!, request.remoteAddr, code, forgetParam.email) + } + + @Transactional + override fun retrieve(request: HttpServletRequest, retrieveParam: RetrieveParam) { + verifyCaptcha(retrieveParam.captchaCode!!) + + val codeStrings = retrieveParam.code!!.split("-") + if (codeStrings.size != 16) { + throw RetrieveCodeErrorOrExpiredException() + } + try { + if (LocalDateTime.ofInstant(Instant.ofEpochMilli(codeStrings.first().toLong()), ZoneOffset.UTC) + .isBefore(LocalDateTime.now(ZoneOffset.UTC).minusHours(2)) + ) { + throw RetrieveCodeErrorOrExpiredException() + } + } catch (e: Exception) { + throw RetrieveCodeErrorOrExpiredException() + } + + val user = userService.getOne(KtQueryWrapper(User()).eq(User::forget, retrieveParam.code)) + ?: throw RetrieveCodeErrorOrExpiredException() + val userInfo = userInfoService.getOne(KtQueryWrapper(UserInfo()).eq(UserInfo::userId, user.id)) + + userService.update( + KtUpdateWrapper(User()).eq(User::id, user.id).set(User::forget, null) + .set(User::password, passwordEncoder.encode(retrieveParam.password!!)) + ) + + WebUtil.offlineUser(redisUtil, user.id!!) + + sendPasswordChangedMail(user.username!!, request.remoteAddr, userInfo!!.email!!) + } + + @EventLogRecord(EventLog.Event.LOGIN) + override fun login(request: HttpServletRequest, loginParam: LoginParam): LoginVo { + verifyCaptcha(loginParam.captchaCode!!) + + return this.login(request, loginParam.account!!, loginParam.password!!) + } + + @EventLogRecord(EventLog.Event.LOGOUT) + override fun logout(token: String): Boolean { + val loginUser = WebUtil.getLoginUser() ?: throw TokenHasExpiredException() + + return redisUtil.delObject("${SecurityProperties.jwtIssuer}_login_${loginUser.user.id}:" + token) + } + + override fun renewToken(token: String): TokenVo { + val loginUser = WebUtil.getLoginUser() ?: throw TokenHasExpiredException() + + val oldRedisKey = "${SecurityProperties.jwtIssuer}_login_${loginUser.user.id}:" + token + redisUtil.delObject(oldRedisKey) + val jwt = JwtUtil.createJwt(WebUtil.getLoginUserId().toString()) + + jwt ?: throw RuntimeException("Login failed") + + val redisKey = "${SecurityProperties.jwtIssuer}_login_${loginUser.user.id}:" + jwt + redisUtil.setObject( + redisKey, loginUser, SecurityProperties.redisTtl, SecurityProperties.redisTtlUnit + ) + + return TokenVo(jwt) + } + + private fun sendVerifyMail(username: String, code: String, email: String) { + val velocityContext = VelocityContext().apply { + put("appName", SettingsOperator.getAppValue(BaseSettings::appName, "氧工具")) + put("appUrl", SettingsOperator.getAppValue(BaseSettings::appUrl, "http://localhost")) + put("username", username) + put( + "verifyUrl", + SettingsOperator.getAppValue(BaseSettings::verifyUrl, "http://localhost/verify?code=\${verifyCode}") + .replace( + Regex("(?<=([^\\\\]))\\$\\{verifyCode}"), code + ) + ) + } + val template = velocityEngine.getTemplate("templates/email-verify-account-cn.vm") + + val stringWriter = StringWriter() + template.merge(velocityContext, stringWriter) + + MailUtil.sendSimpleMail( + "验证您的账号", stringWriter.toString(), true, + email + ) + } + + private fun sendRetrieveMail(username: String, ip: String, code: String, email: String) { + val velocityContext = VelocityContext().apply { + put("appName", SettingsOperator.getAppValue(BaseSettings::appName, "氧工具")) + put("appUrl", SettingsOperator.getAppValue(BaseSettings::appUrl, "http://localhost")) + put("username", username) + put("ipAddress", ip) + put( + "retrieveUrl", + SettingsOperator.getAppValue( + BaseSettings::retrieveUrl, + "http://localhost/retrieve?code=\${retrieveCode}" + ) + .replace( + Regex("(?<=([^\\\\]))\\$\\{retrieveCode}"), code + ) + ) + } + val template = velocityEngine.getTemplate("templates/email-retrieve-password-cn.vm") + + val stringWriter = StringWriter() + template.merge(velocityContext, stringWriter) + + MailUtil.sendSimpleMail( + "找回您的密码", stringWriter.toString(), true, + email + ) + } + + private fun sendPasswordChangedMail(username: String, ip: String, email: String) { + val velocityContext = VelocityContext().apply { + put("appName", SettingsOperator.getAppValue(BaseSettings::appName, "氧工具")) + put("appUrl", SettingsOperator.getAppValue(BaseSettings::appUrl, "http://localhost")) + put("username", username) + put("ipAddress", ip) + } + val template = velocityEngine.getTemplate("templates/email-password-changed-cn.vm") + + val stringWriter = StringWriter() + template.merge(velocityContext, stringWriter) + + MailUtil.sendSimpleMail( + "您的密码已更改", stringWriter.toString(), true, + email + ) + } + + private fun login(request: HttpServletRequest, account: String, password: String): LoginVo { + val usernamePasswordAuthenticationToken = + UsernamePasswordAuthenticationToken(account, password) + val authentication = authenticationManager.authenticate(usernamePasswordAuthenticationToken) + authentication ?: throw RuntimeException("Login failed") + + val loginUser = authentication.principal as LoginUser + loginUser.user.password = "" + + logger.info("用户登录 [用户名: '{}', IP: '{}']", loginUser.username, request.remoteAddr) + userService.update(User().apply { + currentLoginIp = request.remoteAddr + currentLoginTime = LocalDateTime.now(ZoneOffset.UTC) + lastLoginIp = loginUser.user.currentLoginIp + lastLoginTime = loginUser.user.currentLoginTime + }, KtUpdateWrapper(User()).eq(User::username, loginUser.username)) + + val userId = loginUser.user.id.toString() + val jwt = JwtUtil.createJwt(userId) + + jwt ?: throw RuntimeException("Login failed") + + val redisKey = "${SecurityProperties.jwtIssuer}_login_${userId}:" + jwt + redisUtil.setObject(redisKey, loginUser, SecurityProperties.redisTtl, SecurityProperties.redisTtlUnit) + + return LoginVo(jwt, loginUser.user.id, loginUser.user.currentLoginTime, loginUser.user.currentLoginIp) + } + + private fun verifyCaptcha(captchaCode: String) { + try { + val siteverifyResponse = turnstileApi.siteverify(captchaCode) + if (!siteverifyResponse.success) { + throw InvalidCaptchaCodeException() + } + } catch (e: Exception) { + throw InvalidCaptchaCodeException() + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/FuncServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/FuncServiceImpl.kt new file mode 100644 index 0000000..cbfbba6 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/FuncServiceImpl.kt @@ -0,0 +1,20 @@ +package top.fatweb.oxygen.api.service.permission.impl + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import org.springframework.stereotype.Service +import top.fatweb.oxygen.api.entity.permission.Func +import top.fatweb.oxygen.api.mapper.permission.FuncMapper +import top.fatweb.oxygen.api.service.permission.IFuncService + +/** + * Function service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ServiceImpl + * @see FuncMapper + * @see Func + * @see IFuncService + */ +@Service +class FuncServiceImpl : ServiceImpl(), IFuncService diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/GroupServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/GroupServiceImpl.kt new file mode 100644 index 0000000..416bc65 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/GroupServiceImpl.kt @@ -0,0 +1,154 @@ +package top.fatweb.oxygen.api.service.permission.impl + +import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper +import com.baomidou.mybatisplus.extension.plugins.pagination.Page +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import top.fatweb.oxygen.api.converter.permission.GroupConverter +import top.fatweb.oxygen.api.entity.permission.Group +import top.fatweb.oxygen.api.entity.permission.RRoleGroup +import top.fatweb.oxygen.api.exception.DatabaseInsertException +import top.fatweb.oxygen.api.exception.DatabaseUpdateException +import top.fatweb.oxygen.api.exception.NoRecordFoundException +import top.fatweb.oxygen.api.mapper.permission.GroupMapper +import top.fatweb.oxygen.api.param.permission.group.* +import top.fatweb.oxygen.api.service.permission.IGroupService +import top.fatweb.oxygen.api.service.permission.IRRoleGroupService +import top.fatweb.oxygen.api.service.permission.IUserService +import top.fatweb.oxygen.api.util.PageUtil +import top.fatweb.oxygen.api.util.RedisUtil +import top.fatweb.oxygen.api.util.WebUtil +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 service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RedisUtil + * @see IRRoleGroupService + * @see IUserService + * @see ServiceImpl + * @see GroupMapper + * @see Group + * @see IGroupService + */ +@Service +class GroupServiceImpl( + private val redisUtil: RedisUtil, + private val rRoleGroupService: IRRoleGroupService, + private val userService: IUserService +) : ServiceImpl(), IGroupService { + override fun getPage(groupGetParam: GroupGetParam?): PageVo { + val groupIdsPage = Page(groupGetParam?.currentPage ?: 1, groupGetParam?.pageSize ?: 20) + + PageUtil.setPageSort(groupGetParam, groupIdsPage) + + val groupIdsIPage = + baseMapper.selectPage(groupIdsPage, groupGetParam?.searchName, groupGetParam?.searchRegex ?: false) + val groupPage = Page(groupIdsPage.current, groupIdsIPage.size, groupIdsIPage.total) + if (groupIdsIPage.total > 0) { + groupPage.setRecords(baseMapper.selectListWithRoleByIds(groupIdsIPage.records)) + } + + return GroupConverter.groupPageToGroupWithRolePageVo(groupPage) + } + + override fun getOne(id: Long): GroupWithRoleVo = + baseMapper.selectOneById(id)?.let(GroupConverter::groupToGroupWithRoleVo) ?: throw NoRecordFoundException() + + override fun getList(): List = this.list().map(GroupConverter::groupToGroupVo) + + @Transactional + override fun add(groupAddParam: GroupAddParam): GroupVo { + val group = GroupConverter.groupAddParamToGroup(groupAddParam) + if (baseMapper.insert(group) != 1) { + throw DatabaseInsertException() + } + + if (group.roles.isNullOrEmpty()) { + return GroupConverter.groupToGroupVo(group) + } + + rRoleGroupService.saveBatch(group.roles!!.map { + RRoleGroup().apply { + groupId = group.id + roleId = it.id + } + }) + + return GroupConverter.groupToGroupVo(group) + } + + @Transactional + override fun update(groupUpdateParam: GroupUpdateParam): GroupVo { + val group = GroupConverter.groupUpdateParamToGroup(groupUpdateParam) + + if (baseMapper.updateById(group) != 1) { + throw DatabaseUpdateException() + } + + val oldRoleList = rRoleGroupService.list( + KtQueryWrapper(RRoleGroup()).select(RRoleGroup::roleId).eq(RRoleGroup::groupId, groupUpdateParam.id) + ).map { it.roleId } + val addRoleIds = HashSet() + val removeRoleIds = HashSet() + groupUpdateParam.roleIds?.forEach(addRoleIds::add) + oldRoleList.forEach { + it?.let(removeRoleIds::add) + } + removeRoleIds.removeAll(addRoleIds) + oldRoleList.toSet().let(addRoleIds::removeAll) + + removeRoleIds.forEach { + rRoleGroupService.remove( + KtQueryWrapper(RRoleGroup()).eq( + RRoleGroup::groupId, groupUpdateParam.id + ).eq(RRoleGroup::roleId, it) + ) + } + + addRoleIds.forEach { + rRoleGroupService.save(RRoleGroup().apply { + groupId = groupUpdateParam.id + roleId = it + }) + } + + groupUpdateParam.id?.let { offlineUser(it) } + + return GroupConverter.groupToGroupVo(group) + } + + override fun status(groupUpdateStatusParam: GroupUpdateStatusParam) { + updateById(GroupConverter.groupUpdateStatusParamToGroup(groupUpdateStatusParam)).let { + if (!it) { + throw DatabaseUpdateException() + } + + if (!groupUpdateStatusParam.enable) { + groupUpdateStatusParam.id?.let { id -> offlineUser(id) } + } + } + } + + @Transactional + override fun deleteOne(id: Long) { + this.delete(GroupDeleteParam(listOf(id))) + } + + @Transactional + override fun delete(groupDeleteParam: GroupDeleteParam) { + baseMapper.deleteBatchIds(groupDeleteParam.ids) + rRoleGroupService.remove(KtQueryWrapper(RRoleGroup()).`in`(RRoleGroup::groupId, groupDeleteParam.ids)) + offlineUser(*groupDeleteParam.ids!!.toLongArray()) + } + + private fun offlineUser(vararg groupIds: Long) { + val userIds = userService.getIdsWithGroupIds(groupIds.toList()) + WebUtil.offlineUser(redisUtil, *userIds.toLongArray()) + } +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/MenuServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/MenuServiceImpl.kt new file mode 100644 index 0000000..3c85e99 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/MenuServiceImpl.kt @@ -0,0 +1,20 @@ +package top.fatweb.oxygen.api.service.permission.impl + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import org.springframework.stereotype.Service +import top.fatweb.oxygen.api.entity.permission.Menu +import top.fatweb.oxygen.api.mapper.permission.MenuMapper +import top.fatweb.oxygen.api.service.permission.IMenuService + +/** + * Menu service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ServiceImpl + * @see MenuMapper + * @see Menu + * @see IMenuService + */ +@Service +class MenuServiceImpl : ServiceImpl(), IMenuService diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/ModuleServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/ModuleServiceImpl.kt new file mode 100644 index 0000000..23f0886 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/ModuleServiceImpl.kt @@ -0,0 +1,20 @@ +package top.fatweb.oxygen.api.service.permission.impl + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import org.springframework.stereotype.Service +import top.fatweb.oxygen.api.entity.permission.Module +import top.fatweb.oxygen.api.mapper.permission.ModuleMapper +import top.fatweb.oxygen.api.service.permission.IModuleService + +/** + * Module service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ServiceImpl + * @see ModuleMapper + * @see Module + * @see IModuleService + */ +@Service +class ModuleServiceImpl : ServiceImpl(), IModuleService diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/OperationServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/OperationServiceImpl.kt new file mode 100644 index 0000000..241efa9 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/OperationServiceImpl.kt @@ -0,0 +1,20 @@ +package top.fatweb.oxygen.api.service.permission.impl + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import org.springframework.stereotype.Service +import top.fatweb.oxygen.api.entity.permission.Operation +import top.fatweb.oxygen.api.mapper.permission.OperationMapper +import top.fatweb.oxygen.api.service.permission.IOperationService + +/** + * Operation service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ServiceImpl + * @see OperationMapper + * @see Operation + * @see IOperationService + */ +@Service +class OperationServiceImpl : ServiceImpl(), IOperationService diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/PowerServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/PowerServiceImpl.kt new file mode 100644 index 0000000..d709f72 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/PowerServiceImpl.kt @@ -0,0 +1,38 @@ +package top.fatweb.oxygen.api.service.permission.impl + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import org.springframework.stereotype.Service +import top.fatweb.oxygen.api.converter.permission.PowerConverter +import top.fatweb.oxygen.api.entity.permission.Power +import top.fatweb.oxygen.api.entity.permission.PowerSet +import top.fatweb.oxygen.api.mapper.permission.PowerMapper +import top.fatweb.oxygen.api.service.permission.* + +/** + * Power service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IModuleService + * @see IMenuService + * @see IFuncService + * @see IOperationService + * @see ServiceImpl + * @see PowerMapper + * @see Power + * @see IPowerService + */ +@Service +class PowerServiceImpl( + private val moduleService: IModuleService, + private val menuService: IMenuService, + private val funcService: IFuncService, + private val operationService: IOperationService +) : ServiceImpl(), IPowerService { + override fun getList() = PowerConverter.powerSetToPowerSetVo(PowerSet().apply { + moduleList = moduleService.list() + menuList = menuService.list() + funcList = funcService.list() + operationList = operationService.list() + }) +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/RPowerRoleServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/RPowerRoleServiceImpl.kt new file mode 100644 index 0000000..9522f91 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/RPowerRoleServiceImpl.kt @@ -0,0 +1,20 @@ +package top.fatweb.oxygen.api.service.permission.impl + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import org.springframework.stereotype.Service +import top.fatweb.oxygen.api.entity.permission.RPowerRole +import top.fatweb.oxygen.api.mapper.permission.RPowerRoleMapper +import top.fatweb.oxygen.api.service.permission.IRPowerRoleService + +/** + * Power role intermediate service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ServiceImpl + * @see RPowerRoleMapper + * @see RPowerRole + * @see IRPowerRoleService + */ +@Service +class RPowerRoleServiceImpl : ServiceImpl(), IRPowerRoleService diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/RRoleGroupServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/RRoleGroupServiceImpl.kt new file mode 100644 index 0000000..e83e8b1 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/RRoleGroupServiceImpl.kt @@ -0,0 +1,20 @@ +package top.fatweb.oxygen.api.service.permission.impl + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import org.springframework.stereotype.Service +import top.fatweb.oxygen.api.entity.permission.RRoleGroup +import top.fatweb.oxygen.api.mapper.permission.RRoleGroupMapper +import top.fatweb.oxygen.api.service.permission.IRRoleGroupService + +/** + * Role group intermediate service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ServiceImpl + * @see RRoleGroupMapper + * @see RRoleGroup + * @see IRRoleGroupService + */ +@Service +class RRoleGroupServiceImpl : ServiceImpl(), IRRoleGroupService diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/RUserGroupServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/RUserGroupServiceImpl.kt new file mode 100644 index 0000000..12b5100 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/RUserGroupServiceImpl.kt @@ -0,0 +1,20 @@ +package top.fatweb.oxygen.api.service.permission.impl + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import org.springframework.stereotype.Service +import top.fatweb.oxygen.api.entity.permission.RUserGroup +import top.fatweb.oxygen.api.mapper.permission.RUserGroupMapper +import top.fatweb.oxygen.api.service.permission.IRUserGroupService + +/** + * User group intermediate service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ServiceImpl + * @see RUserGroupMapper + * @see RUserGroup + * @see IRUserGroupService + */ +@Service +class RUserGroupServiceImpl : ServiceImpl(), IRUserGroupService diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/RUserRoleServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/RUserRoleServiceImpl.kt new file mode 100644 index 0000000..86f705c --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/RUserRoleServiceImpl.kt @@ -0,0 +1,19 @@ +package top.fatweb.oxygen.api.service.permission.impl + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import org.springframework.stereotype.Service +import top.fatweb.oxygen.api.entity.permission.RUserRole +import top.fatweb.oxygen.api.mapper.permission.RUserRoleMapper +import top.fatweb.oxygen.api.service.permission.IRUserRoleService + +/** + * User role intermediate service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ServiceImpl + * @see RUserRoleMapper + * @see IRUserRoleService + */ +@Service +class RUserRoleServiceImpl : ServiceImpl(), IRUserRoleService diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/RoleServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/RoleServiceImpl.kt new file mode 100644 index 0000000..4fb6636 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/RoleServiceImpl.kt @@ -0,0 +1,187 @@ +package top.fatweb.oxygen.api.service.permission.impl + +import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper +import com.baomidou.mybatisplus.extension.plugins.pagination.Page +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import top.fatweb.oxygen.api.converter.permission.RoleConverter +import top.fatweb.oxygen.api.entity.permission.RPowerRole +import top.fatweb.oxygen.api.entity.permission.Role +import top.fatweb.oxygen.api.exception.DatabaseInsertException +import top.fatweb.oxygen.api.exception.DatabaseUpdateException +import top.fatweb.oxygen.api.exception.NoRecordFoundException +import top.fatweb.oxygen.api.mapper.permission.RoleMapper +import top.fatweb.oxygen.api.param.permission.role.* +import top.fatweb.oxygen.api.service.permission.* +import top.fatweb.oxygen.api.util.PageUtil +import top.fatweb.oxygen.api.util.RedisUtil +import top.fatweb.oxygen.api.util.WebUtil +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 service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RedisUtil + * @see IRPowerRoleService + * @see IFuncService + * @see IMenuService + * @see IUserService + * @see ServiceImpl + * @see RoleMapper + * @see Role + * @see IRoleService + */ +@Service +class RoleServiceImpl( + private val redisUtil: RedisUtil, + private val rPowerRoleService: IRPowerRoleService, + private val funcService: IFuncService, + private val menuService: IMenuService, + private val userService: IUserService +) : ServiceImpl(), IRoleService { + override fun getPage(roleGetParam: RoleGetParam?): PageVo { + val roleIdsPage = Page(roleGetParam?.currentPage ?: 1, roleGetParam?.pageSize ?: 20) + + PageUtil.setPageSort(roleGetParam, roleIdsPage) + + val roleIdsIPage = + baseMapper.selectPage(roleIdsPage, roleGetParam?.searchName, roleGetParam?.searchRegex ?: false) + + val rolePage = Page(roleIdsPage.current, roleIdsIPage.size, roleIdsIPage.total) + if (roleIdsIPage.total > 0) { + rolePage.setRecords(baseMapper.selectListWithPowerByIds(roleIdsIPage.records)) + } + + + return RoleConverter.rolePageToRoleWithPowerPageVo(rolePage) + } + + override fun getOne(id: Long): RoleWithPowerVo = + baseMapper.selectOneById(id)?.let(RoleConverter::roleToRoleWithPowerVo) ?: throw NoRecordFoundException() + + override fun getList(): List = this.list().map(RoleConverter::roleToRoleVo) + + @Transactional + override fun add(roleAddParam: RoleAddParam): RoleVo { + val fullPowerIds = roleAddParam.powerIds?.let(::getFullPowerIds) + + val role = RoleConverter.roleAddParamToRole(roleAddParam) + if (baseMapper.insert(role) != 1) { + throw DatabaseInsertException() + } + + if (fullPowerIds.isNullOrEmpty()) { + return RoleConverter.roleToRoleVo(role) + } + + rPowerRoleService.saveBatch(fullPowerIds.map { + RPowerRole().apply { + roleId = role.id + powerId = it + } + }) + return RoleConverter.roleToRoleVo(role) + } + + @Transactional + override fun update(roleUpdateParam: RoleUpdateParam): RoleVo { + val fullPowerIds = roleUpdateParam.powerIds?.let(::getFullPowerIds) + + val role = RoleConverter.roleUpdateParamToRole(roleUpdateParam) + + if (baseMapper.updateById(role) != 1) { + throw DatabaseUpdateException() + } + + val oldPowerList = rPowerRoleService.list( + KtQueryWrapper(RPowerRole()).select(RPowerRole::powerId).eq(RPowerRole::roleId, roleUpdateParam.id) + ).map { it.powerId } + val addPowerIds = HashSet() + val removePowerIds = HashSet() + fullPowerIds?.forEach(addPowerIds::add) + oldPowerList.forEach { + it?.let(removePowerIds::add) + } + removePowerIds.removeAll(addPowerIds) + oldPowerList.toSet().let(addPowerIds::removeAll) + + removePowerIds.forEach { + rPowerRoleService.remove( + KtQueryWrapper(RPowerRole()).eq( + RPowerRole::roleId, roleUpdateParam.id + ).eq(RPowerRole::powerId, it) + ) + } + + addPowerIds.forEach { + rPowerRoleService.save(RPowerRole().apply { + roleId = roleUpdateParam.id + powerId = it + }) + } + + roleUpdateParam.id?.let { offlineUser(it) } + + return RoleConverter.roleToRoleVo(role) + } + + override fun status(roleUpdateStatusParam: RoleUpdateStatusParam) { + updateById(RoleConverter.roleUpdateStatusParamToRole(roleUpdateStatusParam)).let { + if (!it) { + throw DatabaseUpdateException() + } + + if (!roleUpdateStatusParam.enable) { + roleUpdateStatusParam.id?.let { id -> offlineUser(id) } + } + } + } + + @Transactional + override fun deleteOne(id: Long) { + this.delete(RoleDeleteParam(listOf(id))) + } + + @Transactional + override fun delete(roleDeleteParam: RoleDeleteParam) { + baseMapper.deleteBatchIds(roleDeleteParam.ids) + rPowerRoleService.remove(KtQueryWrapper(RPowerRole()).`in`(RPowerRole::roleId, roleDeleteParam.ids)) + offlineUser(*roleDeleteParam.ids!!.toLongArray()) + } + + private fun getFullPowerIds(powerIds: List): Set { + val fullPowerIds: HashSet = hashSetOf() + powerIds.forEach { + fullPowerIds.add(it) + getElementParent(it / 100 * 100, fullPowerIds) + getMenuParent(it / 10000 * 10000, fullPowerIds) + fullPowerIds.add(it / 1000000 * 1000000) + } + + return fullPowerIds + } + + private fun getElementParent(id: Long, parentIds: HashSet) { + parentIds.add(id) + funcService.getById(id)?.parentId?.let { + getElementParent(it, parentIds) + } + } + + private fun getMenuParent(id: Long, parentIds: HashSet) { + parentIds.add(id) + menuService.getById(id)?.parentId?.let { + getMenuParent(it, parentIds) + } + } + + private fun offlineUser(vararg roleIds: Long) { + val userIds = userService.getIdsWithRoleIds(roleIds.toList()) + WebUtil.offlineUser(redisUtil, *userIds.toLongArray()) + } +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/UserDetailsServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/UserDetailsServiceImpl.kt new file mode 100644 index 0000000..5b3bad7 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/UserDetailsServiceImpl.kt @@ -0,0 +1,25 @@ +package top.fatweb.oxygen.api.service.permission.impl + +import org.springframework.security.core.userdetails.UserDetails +import org.springframework.security.core.userdetails.UserDetailsService +import org.springframework.stereotype.Service +import top.fatweb.oxygen.api.entity.permission.LoginUser +import top.fatweb.oxygen.api.service.permission.IUserService + +/** + * User details service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IUserService + * @see UserDetailsService + */ +@Service +class UserDetailsServiceImpl(val userService: IUserService) : UserDetailsService { + override fun loadUserByUsername(account: String): UserDetails { + val user = userService.getUserWithPowerByAccount(account) + user ?: throw Exception("Username not found") + + return LoginUser(user) + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/UserInfoServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/UserInfoServiceImpl.kt new file mode 100644 index 0000000..c9ceb1e --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/UserInfoServiceImpl.kt @@ -0,0 +1,19 @@ +package top.fatweb.oxygen.api.service.permission.impl + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import org.springframework.stereotype.Service +import top.fatweb.oxygen.api.entity.permission.UserInfo +import top.fatweb.oxygen.api.mapper.permission.UserInfoMapper +import top.fatweb.oxygen.api.service.permission.IUserInfoService + +/** + * User information service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ServiceImpl + * @see UserInfoMapper + * @see IUserInfoService + */ +@Service +class UserInfoServiceImpl : ServiceImpl(), IUserInfoService diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/UserServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/UserServiceImpl.kt new file mode 100644 index 0000000..d0a4d30 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/permission/impl/UserServiceImpl.kt @@ -0,0 +1,329 @@ +package top.fatweb.oxygen.api.service.permission.impl + +import com.baomidou.dynamic.datasource.annotation.DS +import com.baomidou.mybatisplus.core.metadata.OrderItem +import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper +import com.baomidou.mybatisplus.extension.kotlin.KtUpdateWrapper +import com.baomidou.mybatisplus.extension.plugins.pagination.Page +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import org.springframework.security.access.AccessDeniedException +import org.springframework.security.authentication.BadCredentialsException +import org.springframework.security.crypto.password.PasswordEncoder +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import top.fatweb.oxygen.api.converter.permission.UserConverter +import top.fatweb.oxygen.api.entity.permission.RUserGroup +import top.fatweb.oxygen.api.entity.permission.RUserRole +import top.fatweb.oxygen.api.entity.permission.User +import top.fatweb.oxygen.api.entity.permission.UserInfo +import top.fatweb.oxygen.api.exception.DatabaseInsertException +import top.fatweb.oxygen.api.exception.DatabaseUpdateException +import top.fatweb.oxygen.api.exception.NoRecordFoundException +import top.fatweb.oxygen.api.exception.UserNotFoundException +import top.fatweb.oxygen.api.mapper.permission.UserMapper +import top.fatweb.oxygen.api.param.permission.user.* +import top.fatweb.oxygen.api.service.permission.* +import top.fatweb.oxygen.api.util.PageUtil +import top.fatweb.oxygen.api.util.RedisUtil +import top.fatweb.oxygen.api.util.StrUtil +import top.fatweb.oxygen.api.util.WebUtil +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 +import java.time.LocalDateTime +import java.time.ZoneOffset +import java.util.* + +/** + * User service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see PasswordEncoder + * @see RedisUtil + * @see IUserInfoService + * @see IModuleService + * @see IMenuService + * @see IFuncService + * @see IOperationService + * @see IRUserRoleService + * @see IRUserGroupService + * @see ServiceImpl + * @see UserMapper + * @see User + * @see IUserService + */ +@DS("master") +@Service +class UserServiceImpl( + private val passwordEncoder: PasswordEncoder, + private val redisUtil: RedisUtil, + private val userInfoService: IUserInfoService, + private val moduleService: IModuleService, + private val menuService: IMenuService, + private val funcService: IFuncService, + private val operationService: IOperationService, + private val rUserRoleService: IRUserRoleService, + private val rUserGroupService: IRUserGroupService +) : ServiceImpl(), IUserService { + override fun getUserWithPowerByAccount(account: String): User? { + val user = baseMapper.selectOneWithPowerInfoByAccount(account) + user ?: return null + + if (user.id == 0L) { + user.modules = moduleService.list() + user.menus = menuService.list() + user.funcs = funcService.list() + user.operations = operationService.list() + } + + return user + } + + override fun getInfo(): UserWithPowerInfoVo = + WebUtil.getLoginUsername()?.let(::getUserWithPowerByAccount)?.let(UserConverter::userToUserWithPowerInfoVo) + ?: throw UserNotFoundException() + + override fun getBasicInfo(username: String): UserWithInfoVo = + baseMapper.selectOneWithBasicInfoByUsername(username)?.let(UserConverter::userToUserWithInfoVo) + ?: throw NoRecordFoundException() + + + override fun updateInfo(userInfoUpdateParam: UserInfoUpdateParam): Boolean { + val userId = WebUtil.getLoginUserId() ?: throw AccessDeniedException("Access denied") + return userInfoService.update( + KtUpdateWrapper(UserInfo()).eq(UserInfo::userId, userId) + .set(UserInfo::avatar, userInfoUpdateParam.avatar) + .set(UserInfo::nickname, userInfoUpdateParam.nickname) + ) + } + + override fun password(userChangePasswordParam: UserChangePasswordParam) { + val user = this.getById(WebUtil.getLoginUserId() ?: throw AccessDeniedException("Access denied")) + user?.let { + if (!passwordEncoder.matches(userChangePasswordParam.originalPassword, user.password)) { + throw BadCredentialsException("Passwords do not match") + } + val wrapper = KtUpdateWrapper(User()) + .eq(User::id, user.id) + .set(User::password, passwordEncoder.encode(userChangePasswordParam.newPassword)) + .set(User::credentialsExpiration, null) + .set(User::updateTime, LocalDateTime.now(ZoneOffset.UTC)) + + if (!this.update(wrapper)) { + throw DatabaseUpdateException() + } + + WebUtil.offlineUser(redisUtil, user.id!!) + } ?: throw NoRecordFoundException() + } + + override fun getOne(id: Long): UserWithRoleInfoVo = + baseMapper.selectOneWithRoleInfoById(id)?.let(UserConverter::userToUserWithRoleInfoVo) + ?: throw UserNotFoundException() + + override fun getPage(userGetParam: UserGetParam?): PageVo { + val userIdsPage = Page(userGetParam?.currentPage ?: 1, userGetParam?.pageSize ?: 20) + + PageUtil.setPageSort(userGetParam, userIdsPage, OrderItem.asc("id")) + + val userIdsIPage = + baseMapper.selectPage( + userIdsPage, + userGetParam?.searchType ?: "ALL", + userGetParam?.searchValue, + userGetParam?.searchRegex ?: false + ) + val userPage = Page(userIdsIPage.current, userIdsIPage.size, userIdsIPage.total) + if (userIdsIPage.total > 0) { + userPage.setRecords(baseMapper.selectListWithRoleInfoByIds(userIdsIPage.records)) + } + + return UserConverter.userPageToUserWithRoleInfoPageVo(userPage) + } + + override fun getList() = baseMapper.selectListWithInfo().map(UserConverter::userToUserWithInfoVo) + + @Transactional + override fun add(userAddParam: UserAddParam): UserWithPasswordRoleInfoVo { + val rawPassword = + if (userAddParam.password.isNullOrBlank()) StrUtil.getRandomPassword(10) else userAddParam.password + val user = UserConverter.userAddParamToUser(userAddParam) + + user.apply { + password = passwordEncoder.encode(rawPassword) + verify = if (userAddParam.verified) null else "${ + LocalDateTime.now(ZoneOffset.UTC).toInstant(ZoneOffset.UTC).toEpochMilli() + }-${UUID.randomUUID()}-${UUID.randomUUID()}-${UUID.randomUUID()}" + } + + if (!this.save(user)) { + throw DatabaseInsertException() + } + + + user.userInfo?.apply { userId = user.id }?.let(userInfoService::save) + + if (!user.roles.isNullOrEmpty()) { + rUserRoleService.saveBatch(user.roles!!.map { + RUserRole().apply { + userId = user.id + roleId = it.id + } + }) + } + + if (!user.groups.isNullOrEmpty()) { + rUserGroupService.saveBatch(user.groups!!.map { + RUserGroup().apply { + userId = user.id + groupId = it.id + } + }) + } + + user.password = rawPassword + + return UserConverter.userToUserWithPasswordRoleInfoVo(user) + } + + @Transactional + override fun update(userUpdateParam: UserUpdateParam): UserWithRoleInfoVo { + val user = UserConverter.userUpdateParamToUser(userUpdateParam) + user.updateTime = LocalDateTime.now(ZoneOffset.UTC) + + val oldRoleList = rUserRoleService.list( + KtQueryWrapper(RUserRole()).select(RUserRole::roleId).eq(RUserRole::userId, userUpdateParam.id) + ).map { it.roleId } + val addRoleIds = HashSet() + val removeRoleIds = HashSet() + userUpdateParam.roleIds?.forEach(addRoleIds::add) + oldRoleList.forEach { + it?.let(removeRoleIds::add) + } + removeRoleIds.removeAll(addRoleIds) + oldRoleList.toSet().let(addRoleIds::removeAll) + + val oldGroupList = rUserGroupService.list( + KtQueryWrapper(RUserGroup()).select(RUserGroup::groupId).eq(RUserGroup::userId, userUpdateParam.id) + ).map { it.groupId } + val addGroupIds = HashSet() + val removeGroupIds = HashSet() + userUpdateParam.groupIds?.forEach(addGroupIds::add) + oldGroupList.forEach { + it?.let(removeGroupIds::add) + } + removeGroupIds.removeAll(addGroupIds) + oldGroupList.toSet().let(addGroupIds::removeAll) + + this.updateById(user) + this.update( + KtUpdateWrapper(User()).eq(User::id, user.id) + .set( + User::verify, + if (userUpdateParam.verified) null else "${ + LocalDateTime.now(ZoneOffset.UTC).toInstant(ZoneOffset.UTC).toEpochMilli() + }-${UUID.randomUUID()}-${UUID.randomUUID()}-${UUID.randomUUID()}" + ) + .set(User::expiration, user.expiration) + .set(User::credentialsExpiration, user.credentialsExpiration) + ) + + user.userInfo?.let { userInfo -> + userInfoService.getOne( + KtQueryWrapper(UserInfo()).select(UserInfo::id).eq(UserInfo::userId, userUpdateParam.id) + )?.let { + userInfo.id = it.id + userInfoService.updateById(userInfo) + } + } + + removeRoleIds.forEach { + rUserRoleService.remove( + KtQueryWrapper(RUserRole()).eq( + RUserRole::userId, userUpdateParam.id + ).eq(RUserRole::roleId, it) + ) + } + + addRoleIds.forEach { + rUserRoleService.save(RUserRole().apply { + userId = userUpdateParam.id + roleId = it + }) + } + + removeGroupIds.forEach { + rUserGroupService.remove( + KtQueryWrapper(RUserGroup()).eq( + RUserGroup::userId, userUpdateParam.id + ).eq(RUserGroup::groupId, it) + ) + } + + addGroupIds.forEach { + rUserGroupService.save(RUserGroup().apply { + userId = userUpdateParam.id + groupId = it + }) + } + + userUpdateParam.id?.let { WebUtil.offlineUser(redisUtil, it) } + + return UserConverter.userToUserWithRoleInfoVo(user) + } + + override fun password(userUpdatePasswordParam: UserUpdatePasswordParam) { + if (WebUtil.getLoginUserId() != 0L && userUpdatePasswordParam.id == 0L) { + throw AccessDeniedException("Access denied") + } + + val user = this.getById(userUpdatePasswordParam.id) + user?.let { + val wrapper = KtUpdateWrapper(User()) + .eq(User::id, user.id) + .set(User::password, passwordEncoder.encode(userUpdatePasswordParam.password)) + .set( + User::credentialsExpiration, + if (user.id != 0L) userUpdatePasswordParam.credentialsExpiration else null + ) + .set(User::updateTime, LocalDateTime.now(ZoneOffset.UTC)) + + if (!this.update(wrapper)) { + throw DatabaseUpdateException() + } + + userUpdatePasswordParam.id?.let { WebUtil.offlineUser(redisUtil, it) } + } ?: throw NoRecordFoundException() + } + + @Transactional + override fun deleteOne(id: Long) { + if (id == 0L) { + return + } + + this.delete(UserDeleteParam(listOf(id))) + } + + @Transactional + override fun delete(userDeleteParam: UserDeleteParam) { + val ids = userDeleteParam.ids!!.filter { it != 0L } + if (ids.isEmpty()) { + return + } + + this.removeBatchByIds(ids) + userInfoService.remove(KtQueryWrapper(UserInfo()).`in`(UserInfo::userId, ids)) + rUserRoleService.remove(KtQueryWrapper(RUserRole()).`in`(RUserRole::userId, ids)) + rUserGroupService.remove(KtQueryWrapper(RUserGroup()).`in`(RUserGroup::userId, ids)) + + WebUtil.offlineUser(redisUtil, *ids.toLongArray()) + } + + override fun getIdsWithRoleIds(roleIds: List) = baseMapper.selectIdsWithRoleIds(roleIds) + + override fun getIdsWithGroupIds(groupIds: List) = baseMapper.selectIdsWithGroupIds(groupIds) +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/system/IEventLogService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/system/IEventLogService.kt new file mode 100644 index 0000000..ca2693c --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/system/IEventLogService.kt @@ -0,0 +1,22 @@ +package top.fatweb.oxygen.api.service.system + +import com.baomidou.mybatisplus.extension.service.IService +import top.fatweb.oxygen.api.annotation.EventLogRecord +import top.fatweb.oxygen.api.entity.system.EventLog + +/** + * Event log service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +interface IEventLogService : IService { + /** + * Save event + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see EventLogRecord + */ + fun saveEvent(annotation: EventLogRecord, userId: Long) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/system/ISensitiveWordService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/system/ISensitiveWordService.kt new file mode 100644 index 0000000..c51606e --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/system/ISensitiveWordService.kt @@ -0,0 +1,58 @@ +package top.fatweb.oxygen.api.service.system + +import com.baomidou.mybatisplus.extension.service.IService +import top.fatweb.oxygen.api.entity.system.SensitiveWord +import top.fatweb.oxygen.api.param.system.SensitiveWordAddParam +import top.fatweb.oxygen.api.param.system.SensitiveWordUpdateParam +import top.fatweb.oxygen.api.vo.system.SensitiveWordVo + +/** + * Sensitive word service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +interface ISensitiveWordService : IService { + /** + * Get sensitive word settings + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see SensitiveWordVo + */ + fun get(): List + + /** + * Add sensitive word settings item + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see SensitiveWordAddParam + */ + fun add(sensitiveWordAddParam: SensitiveWordAddParam) + + /** + * Update sensitive word settings + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see SensitiveWordUpdateParam + */ + fun update(sensitiveWordUpdateParam: SensitiveWordUpdateParam) + + /** + * Delete sensitive word settings item + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun delete(id: Long) + + /** + * Check sensitive word + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun checkSensitiveWord(str: String) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/system/ISettingsService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/system/ISettingsService.kt new file mode 100644 index 0000000..0e7eee6 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/system/ISettingsService.kt @@ -0,0 +1,65 @@ +package top.fatweb.oxygen.api.service.system + +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.vo.system.BaseSettingsVo +import top.fatweb.oxygen.api.vo.system.MailSettingsVo + +/** + * Settings service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +interface ISettingsService { + /** + * Get base settings + * + * @return BaseSettingsVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see BaseSettingsVo + */ + fun getBase(): BaseSettingsVo? + + /** + * Update base settings + * + * @param baseSettingsParam Base settings parameters + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see BaseSettingsParam + */ + fun updateBase(baseSettingsParam: BaseSettingsParam) + + /** + * Get mail settings + * + * @return MailSettingsVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see MailSettingsVo + */ + fun getMail(): MailSettingsVo? + + /** + * Update mail settings + * + * @param mailSettingsParam Mail settings parameters + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see MailSettingsParam + */ + fun updateMail(mailSettingsParam: MailSettingsParam) + + /** + * Send mail + * + * @param mailSendParam Send mail parameters + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see MailSettingsParam + */ + fun sendMail(mailSendParam: MailSendParam) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/system/IStatisticsLogService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/system/IStatisticsLogService.kt new file mode 100644 index 0000000..571149a --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/system/IStatisticsLogService.kt @@ -0,0 +1,12 @@ +package top.fatweb.oxygen.api.service.system + +import com.baomidou.mybatisplus.extension.service.IService +import top.fatweb.oxygen.api.entity.system.StatisticsLog + +/** + * Statistics log service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +interface IStatisticsLogService : IService \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/system/IStatisticsService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/system/IStatisticsService.kt new file mode 100644 index 0000000..c698c8d --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/system/IStatisticsService.kt @@ -0,0 +1,69 @@ +package top.fatweb.oxygen.api.service.system + +import top.fatweb.oxygen.api.param.system.ActiveInfoGetParam +import top.fatweb.oxygen.api.param.system.OnlineInfoGetParam +import top.fatweb.oxygen.api.vo.system.* + +/** + * Statistics service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +interface IStatisticsService { + /** + * Get software information + * + * @return SoftwareInfoVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see SoftwareInfoVo + */ + fun software(): SoftwareInfoVo + + /** + * Get hardware information + * + * @return HardwareInfoVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see HardwareInfoVo + */ + fun hardware(): HardwareInfoVo + + /** + * Get CPU information + * + * @return CpuInfoVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see CpuInfoVo + */ + fun cpu(): CpuInfoVo + + /** + * Get storage information + * + * @return StorageInfoVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see StorageInfoVo + */ + fun storage(): StorageInfoVo + + /** + * Get the history of online users information + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun online(onlineInfoGetParam: OnlineInfoGetParam?): OnlineInfoVo + + /** + * Get the history of active information + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun active(activeInfoGetParam: ActiveInfoGetParam?): ActiveInfoVo +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/system/ISysLogService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/system/ISysLogService.kt new file mode 100644 index 0000000..16430ca --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/system/ISysLogService.kt @@ -0,0 +1,30 @@ +package top.fatweb.oxygen.api.service.system + +import com.baomidou.mybatisplus.extension.service.IService +import top.fatweb.oxygen.api.entity.system.SysLog +import top.fatweb.oxygen.api.param.system.SysLogGetParam +import top.fatweb.oxygen.api.vo.PageVo +import top.fatweb.oxygen.api.vo.system.SysLogVo + +/** + * System log service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IService + * @see SysLog + */ +interface ISysLogService : IService { + /** + * Get system log in page + * + * @param sysLogGetParam Get system log parameters + * @return IPage object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see SysLogGetParam + * @see PageVo + * @see SysLogVo + */ + fun getPage(sysLogGetParam: SysLogGetParam?): PageVo +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/system/impl/EventLogServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/system/impl/EventLogServiceImpl.kt new file mode 100644 index 0000000..b2d51d6 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/system/impl/EventLogServiceImpl.kt @@ -0,0 +1,37 @@ +package top.fatweb.oxygen.api.service.system.impl + +import com.baomidou.dynamic.datasource.annotation.DS +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Propagation +import org.springframework.transaction.annotation.Transactional +import top.fatweb.oxygen.api.annotation.EventLogRecord +import top.fatweb.oxygen.api.entity.system.EventLog +import top.fatweb.oxygen.api.mapper.system.EventLogMapper +import top.fatweb.oxygen.api.service.system.IEventLogService + +/** + * Event log service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@DS("sqlite") +@Service +class EventLogServiceImpl : ServiceImpl(), IEventLogService { + private val logger: Logger = LoggerFactory.getLogger(this::class.java) + + @Transactional(propagation = Propagation.REQUIRES_NEW) + override fun saveEvent(annotation: EventLogRecord, userId: Long) { + try { + this.save(EventLog().apply { + this.event = annotation.event + operateUserId = userId + }) + } catch (e: Exception) { + logger.error("Cannot record event!!!", e) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/system/impl/SensitiveWordServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/system/impl/SensitiveWordServiceImpl.kt new file mode 100644 index 0000000..e973d23 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/system/impl/SensitiveWordServiceImpl.kt @@ -0,0 +1,64 @@ +package top.fatweb.oxygen.api.service.system.impl + +import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper +import com.baomidou.mybatisplus.extension.kotlin.KtUpdateWrapper +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Propagation +import org.springframework.transaction.annotation.Transactional +import top.fatweb.oxygen.api.converter.system.SettingsConverter +import top.fatweb.oxygen.api.entity.system.SensitiveWord +import top.fatweb.oxygen.api.exception.MatchSensitiveWordException +import top.fatweb.oxygen.api.mapper.system.SensitiveWordMapper +import top.fatweb.oxygen.api.param.system.SensitiveWordAddParam +import top.fatweb.oxygen.api.param.system.SensitiveWordUpdateParam +import top.fatweb.oxygen.api.service.system.ISensitiveWordService +import top.fatweb.oxygen.api.vo.system.SensitiveWordVo + +/** + * Sensitive word service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Service +class SensitiveWordServiceImpl : ServiceImpl(), ISensitiveWordService { + @Transactional(propagation = Propagation.REQUIRES_NEW) + override fun get(): List = this.list().map(SettingsConverter::sensitiveWordToSensitiveWordVo) + + @Transactional(propagation = Propagation.REQUIRES_NEW) + override fun add(sensitiveWordAddParam: SensitiveWordAddParam) { + checkSensitiveWord(sensitiveWordAddParam.word!!) + this.save(SettingsConverter.sensitiveWordAddParamToSensitiveWord(sensitiveWordAddParam)) + } + + @Transactional(propagation = Propagation.REQUIRES_NEW) + override fun update(sensitiveWordUpdateParam: SensitiveWordUpdateParam) { + this.update(KtUpdateWrapper(SensitiveWord()).set(SensitiveWord::enable, false)) + this.update( + KtUpdateWrapper(SensitiveWord()).`in`(SensitiveWord::id, sensitiveWordUpdateParam.ids) + .set(SensitiveWord::enable, true) + ) + } + + @Transactional(propagation = Propagation.REQUIRES_NEW) + override fun delete(id: Long) { + this.removeById(id) + } + + @Transactional(propagation = Propagation.REQUIRES_NEW) + override fun checkSensitiveWord(str: String) { + this.list(KtQueryWrapper(SensitiveWord()).eq(SensitiveWord::enable, 1)).map(SensitiveWord::word).forEach { + it ?: return@forEach + + try { + if (Regex(it, RegexOption.IGNORE_CASE).matches(str)) { + throw MatchSensitiveWordException() + } + } catch (e: MatchSensitiveWordException) { + throw e + } catch (_: Exception) { + } + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/system/impl/SettingsServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/system/impl/SettingsServiceImpl.kt new file mode 100644 index 0000000..aa3a7e5 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/system/impl/SettingsServiceImpl.kt @@ -0,0 +1,82 @@ +package top.fatweb.oxygen.api.service.system.impl + +import org.springframework.stereotype.Service +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.properties.ServerProperties +import top.fatweb.oxygen.api.service.system.ISettingsService +import top.fatweb.oxygen.api.settings.BaseSettings +import top.fatweb.oxygen.api.settings.MailSettings +import top.fatweb.oxygen.api.settings.SettingsOperator +import top.fatweb.oxygen.api.util.MailUtil +import top.fatweb.oxygen.api.util.StrUtil +import top.fatweb.oxygen.api.vo.system.BaseSettingsVo +import top.fatweb.oxygen.api.vo.system.MailSettingsVo + +/** + * Settings service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ISettingsService + */ +@Service +class SettingsServiceImpl : ISettingsService { + override fun getBase() = BaseSettingsVo( + appName = SettingsOperator.getAppValue(BaseSettings::appName, "氧工具"), + appUrl = SettingsOperator.getAppValue(BaseSettings::appUrl, "http://localhost"), + verifyUrl = SettingsOperator.getAppValue( + BaseSettings::verifyUrl, + "http://localhost/verify?code=\${verifyCode}" + ), + retrieveUrl = SettingsOperator.getAppValue( + BaseSettings::retrieveUrl, + "http://localhost/retrieve?code=\${retrieveCode}" + ) + ) + + override fun updateBase(baseSettingsParam: BaseSettingsParam) { + baseSettingsParam.run { + SettingsOperator.setAppValue(BaseSettings::appName, appName) + SettingsOperator.setAppValue(BaseSettings::appUrl, appUrl) + SettingsOperator.setAppValue(BaseSettings::verifyUrl, verifyUrl) + SettingsOperator.setAppValue(BaseSettings::retrieveUrl, retrieveUrl) + } + } + + override fun getMail() = MailSettingsVo( + host = SettingsOperator.getMailValue(MailSettings::host), + port = SettingsOperator.getMailValue(MailSettings::port), + securityType = SettingsOperator.getMailValue(MailSettings::securityType), + username = SettingsOperator.getMailValue(MailSettings::username), + password = SettingsOperator.getMailValue(MailSettings::password)?.let(StrUtil::md5), + from = SettingsOperator.getMailValue(MailSettings::from), + fromName = SettingsOperator.getMailValue(MailSettings::fromName) + ) + + override fun updateMail(mailSettingsParam: MailSettingsParam) { + mailSettingsParam.run { + SettingsOperator.setMailValue(MailSettings::host, host) + SettingsOperator.setMailValue(MailSettings::port, port) + SettingsOperator.setMailValue(MailSettings::securityType, securityType) + SettingsOperator.setMailValue(MailSettings::username, username) + SettingsOperator.setMailValue(MailSettings::password, password) + SettingsOperator.setMailValue(MailSettings::from, from) + SettingsOperator.setMailValue(MailSettings::fromName, fromName) + } + + MailUtil.init() + } + + override fun sendMail(mailSendParam: MailSendParam) { + mailSendParam.to?.let { + MailUtil.sendSimpleMail( + "${ServerProperties.appName} Test Message", + "This is a test email sent when testing the system email sending service.", + false, + it + ) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/system/impl/StatisticsLogServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/system/impl/StatisticsLogServiceImpl.kt new file mode 100644 index 0000000..b7faec6 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/system/impl/StatisticsLogServiceImpl.kt @@ -0,0 +1,18 @@ +package top.fatweb.oxygen.api.service.system.impl + +import com.baomidou.dynamic.datasource.annotation.DS +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import org.springframework.stereotype.Service +import top.fatweb.oxygen.api.entity.system.StatisticsLog +import top.fatweb.oxygen.api.mapper.system.StatisticsLogMapper +import top.fatweb.oxygen.api.service.system.IStatisticsLogService + +/** + * Statistics log service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@DS("sqlite") +@Service +class StatisticsLogServiceImpl : ServiceImpl(), IStatisticsLogService \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/system/impl/StatisticsServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/system/impl/StatisticsServiceImpl.kt new file mode 100644 index 0000000..e6394f8 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/system/impl/StatisticsServiceImpl.kt @@ -0,0 +1,228 @@ +package top.fatweb.oxygen.api.service.system.impl + +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper +import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper +import org.springframework.stereotype.Service +import oshi.SystemInfo +import oshi.hardware.CentralProcessor +import top.fatweb.oxygen.api.entity.system.EventLog +import top.fatweb.oxygen.api.entity.system.StatisticsLog +import top.fatweb.oxygen.api.param.system.ActiveInfoGetParam +import top.fatweb.oxygen.api.param.system.OnlineInfoGetParam +import top.fatweb.oxygen.api.properties.SecurityProperties +import top.fatweb.oxygen.api.properties.ServerProperties +import top.fatweb.oxygen.api.service.system.IEventLogService +import top.fatweb.oxygen.api.service.system.IStatisticsLogService +import top.fatweb.oxygen.api.service.system.IStatisticsService +import top.fatweb.oxygen.api.util.ByteUtil +import top.fatweb.oxygen.api.util.RedisUtil +import top.fatweb.oxygen.api.vo.system.* +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.ZoneOffset +import java.time.format.DateTimeFormatter +import java.util.* +import java.util.concurrent.TimeUnit + +/** + * Statistics service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Service +class StatisticsServiceImpl( + private val redisUtil: RedisUtil, + private val statisticsLogService: IStatisticsLogService, + private val eventLogService: IEventLogService +) : IStatisticsService { + private val systemProperties: Properties = System.getProperties() + private val systemInfo: SystemInfo = SystemInfo() + private val runtime: Runtime = Runtime.getRuntime() + + override fun software() = SoftwareInfoVo( + os = systemInfo.operatingSystem.toString(), + bitness = systemInfo.operatingSystem.bitness, + javaVersion = systemProperties.getProperty("java.version"), + javaVersionDate = systemProperties.getProperty("java.version.date"), + javaVendor = systemProperties.getProperty("java.vendor"), + javaRuntime = systemProperties.getProperty("java.runtime.name"), + javaRuntimeVersion = systemProperties.getProperty("java.runtime.version"), + jvm = systemProperties.getProperty("java.vm.name"), + jvmVersion = systemProperties.getProperty("java.vm.version"), + jvmInfo = systemProperties.getProperty("java.vm.info"), + jvmVendor = systemProperties.getProperty("java.vm.vendor"), + javaClassVersion = systemProperties.getProperty("java.class.version"), + osBootTime = LocalDateTime.ofEpochSecond(systemInfo.operatingSystem.systemBootTime, 0, ZoneOffset.UTC), + serverStartupTime = ServerProperties.startupTime + ) + + override fun hardware() = HardwareInfoVo( + cpu = systemInfo.hardware.processor.processorIdentifier.name, + arch = systemProperties.getProperty("os.arch"), + is64Bit = systemInfo.hardware.processor.processorIdentifier.isCpu64bit, + cpuPhysicalPackageCount = systemInfo.hardware.processor.physicalPackageCount, + cpuPhysicalProcessorCount = systemInfo.hardware.processor.physicalProcessorCount, + cpuLogicalProcessorCount = systemInfo.hardware.processor.logicalProcessorCount, + microarchitecture = systemInfo.hardware.processor.processorIdentifier.microarchitecture, + memories = "${ByteUtil.formatByteSize(systemInfo.hardware.memory.total)} (${ + systemInfo.hardware.memory.physicalMemory.joinToString( + " + " + ) { ByteUtil.formatByteSize(it.capacity) } + })", + disks = "${ByteUtil.formatByteSize(systemInfo.hardware.diskStores.sumOf { it.size })} (${ + systemInfo.hardware.diskStores.joinToString( + " + " + ) { ByteUtil.formatByteSize(it.size) } + })" + ) + + override fun cpu(): CpuInfoVo { + val processor = systemInfo.hardware.processor + val prevTicks = processor.systemCpuLoadTicks + val processorPrevTicksList = processor.processorCpuLoadTicks + TimeUnit.MILLISECONDS.sleep(500) + val ticks = processor.systemCpuLoadTicks + val processorTicksList = processor.processorCpuLoadTicks + + val user = ticks[CentralProcessor.TickType.USER.index] - prevTicks[CentralProcessor.TickType.USER.index] + val nice = ticks[CentralProcessor.TickType.NICE.index] - prevTicks[CentralProcessor.TickType.NICE.index] + val system = ticks[CentralProcessor.TickType.SYSTEM.index] - prevTicks[CentralProcessor.TickType.SYSTEM.index] + val idle = ticks[CentralProcessor.TickType.IDLE.index] - prevTicks[CentralProcessor.TickType.IDLE.index] + val iowait = ticks[CentralProcessor.TickType.IOWAIT.index] - prevTicks[CentralProcessor.TickType.IOWAIT.index] + val irq = ticks[CentralProcessor.TickType.IRQ.index] - prevTicks[CentralProcessor.TickType.IRQ.index] + val softirq = + ticks[CentralProcessor.TickType.SOFTIRQ.index] - prevTicks[CentralProcessor.TickType.SOFTIRQ.index] + val steal = ticks[CentralProcessor.TickType.STEAL.index] - prevTicks[CentralProcessor.TickType.STEAL.index] + val total = user + nice + system + idle + iowait + irq + softirq + steal + return CpuInfoVo( + user, + nice, + system, + idle, + iowait, + irq, + softirq, + steal, + total, + listOf(*processorPrevTicksList.mapIndexed { index, processorPrevTicks -> + val processorTicks = processorTicksList[index] + val processorUser = + processorTicks[CentralProcessor.TickType.USER.index] - processorPrevTicks[CentralProcessor.TickType.USER.index] + val processorNice = + processorTicks[CentralProcessor.TickType.NICE.index] - processorPrevTicks[CentralProcessor.TickType.NICE.index] + val processorSystem = + processorTicks[CentralProcessor.TickType.SYSTEM.index] - processorPrevTicks[CentralProcessor.TickType.SYSTEM.index] + val processorIdle = + processorTicks[CentralProcessor.TickType.IDLE.index] - processorPrevTicks[CentralProcessor.TickType.IDLE.index] + val processorIowait = + processorTicks[CentralProcessor.TickType.IOWAIT.index] - processorPrevTicks[CentralProcessor.TickType.IOWAIT.index] + val processorIrq = + processorTicks[CentralProcessor.TickType.IRQ.index] - processorPrevTicks[CentralProcessor.TickType.IRQ.index] + val processorSoftirq = + processorTicks[CentralProcessor.TickType.SOFTIRQ.index] - processorPrevTicks[CentralProcessor.TickType.SOFTIRQ.index] + val processorSteal = + processorTicks[CentralProcessor.TickType.STEAL.index] - processorPrevTicks[CentralProcessor.TickType.STEAL.index] + val processorTotal = + processorUser + processorNice + processorSystem + processorIdle + processorIowait + processorIrq + processorSoftirq + processorSteal + CpuInfoVo( + processorUser, + processorNice, + processorSystem, + processorIdle, + processorIowait, + processorIrq, + processorSoftirq, + processorSteal, + processorTotal + ) + + }.toTypedArray()) + ) + } + + override fun storage() = StorageInfoVo( + memoryTotal = systemInfo.hardware.memory.total, + memoryFree = systemInfo.hardware.memory.available, + virtualMemoryMax = systemInfo.hardware.memory.virtualMemory.virtualMax, + virtualMemoryInUse = systemInfo.hardware.memory.virtualMemory.virtualInUse, + swapTotal = systemInfo.hardware.memory.virtualMemory.swapTotal, + swapUsed = systemInfo.hardware.memory.virtualMemory.swapUsed, + jvmTotal = runtime.totalMemory(), + jvmFree = runtime.freeMemory(), + fileStores = systemInfo.operatingSystem.fileSystem.fileStores.map { + FileStoreInfoVo( + mount = it.mount, + total = it.totalSpace, + free = it.freeSpace + ) + } + ) + + override fun online(onlineInfoGetParam: OnlineInfoGetParam?): OnlineInfoVo { + val history: List = statisticsLogService.list( + KtQueryWrapper(StatisticsLog()) + .select(StatisticsLog::value, StatisticsLog::recordTime) + .eq(StatisticsLog::key, StatisticsLog.KeyItem.ONLINE_USERS_COUNT) + .between( + onlineInfoGetParam?.scope != OnlineInfoGetParam.Scope.ALL, + StatisticsLog::recordTime, + LocalDateTime.now(ZoneOffset.UTC).run { + when (onlineInfoGetParam?.scope) { + OnlineInfoGetParam.Scope.DAY -> minusDays(1) + OnlineInfoGetParam.Scope.MONTH -> minusMonths(1) + OnlineInfoGetParam.Scope.QUARTER -> minusMonths(3) + OnlineInfoGetParam.Scope.YEAR -> minusYears(1) + OnlineInfoGetParam.Scope.TWO_YEARS -> minusYears(2) + OnlineInfoGetParam.Scope.THREE_YEARS -> minusYears(3) + OnlineInfoGetParam.Scope.FIVE_YEARS -> minusYears(5) + else -> minusWeeks(1) + } + }.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")), + LocalDateTime.now(ZoneOffset.UTC).plusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + ) + ).map { + OnlineInfoVo.HistoryVo( + time = it.recordTime!!, + record = it.value!! + ) + } + + return OnlineInfoVo( + current = redisUtil.keys("${SecurityProperties.jwtIssuer}_login_*") + .distinctBy { Regex("${SecurityProperties.jwtIssuer}_login_(.*):.*").matchEntire(it)?.groupValues?.getOrNull(1) }.size.toLong(), + history = history + ) + } + + override fun active(activeInfoGetParam: ActiveInfoGetParam?): ActiveInfoVo { + fun getHistory(event: String) = eventLogService.listMaps( + QueryWrapper().select("strftime('%Y-%m-%d', operate_time) time, count(distinct operate_user_id) count") + .eq("event", event).groupBy("time").between( + activeInfoGetParam?.scope != ActiveInfoGetParam.Scope.ALL, + "operate_time", + LocalDateTime.now(ZoneOffset.UTC).run { + when (activeInfoGetParam?.scope) { + ActiveInfoGetParam.Scope.MONTH -> minusMonths(1) + ActiveInfoGetParam.Scope.QUARTER -> minusMonths(3) + ActiveInfoGetParam.Scope.YEAR -> minusYears(1) + ActiveInfoGetParam.Scope.TWO_YEARS -> minusYears(2) + ActiveInfoGetParam.Scope.THREE_YEARS -> minusYears(3) + ActiveInfoGetParam.Scope.FIVE_YEARS -> minusYears(5) + else -> minusWeeks(1) + } + }.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")), + LocalDateTime.now(ZoneOffset.UTC).plusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + ) + ).map { + ActiveInfoVo.HistoryVo( + LocalDate.parse( + it["time"] as String, + DateTimeFormatter.ofPattern("yyyy-MM-dd") + ), it["count"] as Int + ) + } + + return ActiveInfoVo(getHistory("REGISTER"), getHistory("LOGIN"), getHistory("VERIFY")) + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/system/impl/SysLogServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/system/impl/SysLogServiceImpl.kt new file mode 100644 index 0000000..709c560 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/system/impl/SysLogServiceImpl.kt @@ -0,0 +1,64 @@ +package top.fatweb.oxygen.api.service.system.impl + +import com.baomidou.dynamic.datasource.annotation.DS +import com.baomidou.mybatisplus.core.metadata.OrderItem +import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper +import com.baomidou.mybatisplus.extension.plugins.pagination.Page +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import org.springframework.stereotype.Service +import top.fatweb.oxygen.api.converter.system.SysLogConverter +import top.fatweb.oxygen.api.entity.permission.User +import top.fatweb.oxygen.api.entity.system.SysLog +import top.fatweb.oxygen.api.mapper.system.SysLogMapper +import top.fatweb.oxygen.api.param.system.SysLogGetParam +import top.fatweb.oxygen.api.service.permission.IUserService +import top.fatweb.oxygen.api.service.system.ISysLogService +import top.fatweb.oxygen.api.util.PageUtil +import top.fatweb.oxygen.api.vo.PageVo +import top.fatweb.oxygen.api.vo.system.SysLogVo + +/** + * System log service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ServiceImpl + * @see SysLogMapper + * @see SysLog + * @see ISysLogService + */ +@DS("sqlite") +@Service +class SysLogServiceImpl( + private val userService: IUserService +) : ServiceImpl(), ISysLogService { + override fun getPage(sysLogGetParam: SysLogGetParam?): PageVo { + val sysLogPage = Page(sysLogGetParam?.currentPage ?: 1, sysLogGetParam?.pageSize ?: 20) + + PageUtil.setPageSort(sysLogGetParam, sysLogPage, OrderItem.desc("start_time")) + + val sysLogIPage = baseMapper.selectPage( + sysLogPage, + sysLogGetParam?.logType?.split(","), + sysLogGetParam?.requestMethod?.split(","), + sysLogGetParam?.searchRequestUrl, + sysLogGetParam?.searchStartTime, + sysLogGetParam?.searchEndTime + ) + + if (sysLogIPage.records.isNotEmpty()) { + val userIds = sysLogIPage.records.map { it.operateUserId } + + userService.list(KtQueryWrapper(User()).select(User::id, User::username).`in`(User::id, userIds)) + .forEach { user -> + sysLogIPage.records.forEach { + if (it.operateUserId == user.id) { + it.operateUsername = user.username + } + } + } + } + + return SysLogConverter.sysLogPageToSysLogPageVo(sysLogIPage) + } +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/tool/IEditService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/IEditService.kt new file mode 100644 index 0000000..3a92b4a --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/IEditService.kt @@ -0,0 +1,150 @@ +package top.fatweb.oxygen.api.service.tool + +import com.baomidou.mybatisplus.extension.service.IService +import top.fatweb.oxygen.api.entity.tool.Tool +import top.fatweb.oxygen.api.param.tool.ToolCreateParam +import top.fatweb.oxygen.api.param.tool.ToolUpdateParam +import top.fatweb.oxygen.api.param.tool.ToolUpgradeParam +import top.fatweb.oxygen.api.vo.tool.ToolCategoryVo +import top.fatweb.oxygen.api.vo.tool.ToolTemplateVo +import top.fatweb.oxygen.api.vo.tool.ToolVo + +/** + * Tool edit service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IService + * @see Tool + */ +interface IEditService : IService { + /** + * Get tool template as list + * + * @return List of ToolTemplateVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolTemplateVo + */ + fun getTemplate(): List + + /** + * Get tool template by ID + * + * @param id ID + * @return ToolTemplateVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolTemplateVo + */ + fun getTemplate(id: Long): ToolTemplateVo + + /** + * Get tool category as list + * + * @return List of ToolCategoryVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolCategoryVo + */ + fun getCategory(): List + + /** + * Get tool by ID + * + * @param id Tool ID + * @return ToolVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun getOne(id: Long): ToolVo + + /** + * Create tool + * + * @param toolCreateParam Create tool parameters + * @return ToolVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolCreateParam + * @see ToolVo + */ + fun create(toolCreateParam: ToolCreateParam): ToolVo + + /** + * Upgrade tool + * + * @param toolUpgradeParam Upgrade tool parameters + * @return ToolVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolUpgradeParam + * @see ToolVo + */ + fun upgrade(toolUpgradeParam: ToolUpgradeParam): ToolVo + + /** + * Update tool + * + * @param toolUpdateParam Update tool parameters + * @return ToolVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolUpdateParam + * @see ToolVo + */ + fun update(toolUpdateParam: ToolUpdateParam): ToolVo + + /** + * Get personal tools + * + * @return List of ToolVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolVo + */ + fun get(): List + + /** + * Get tool detail + * + * @param username Username + * @param toolId Tool ID + * @param ver Version + * @return ToolVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolVo + */ + fun detail(username: String, toolId: String, ver: String): ToolVo + + /** + * Submit tool review + * + * @param id Tool ID + * @return Result + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun submit(id: Long): Boolean + + /** + * Cancel tool review + * + * @param id Tool ID + * @return Result + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun cancel(id: Long): Boolean + + /** + * Delete tool + * + * @param id Tool ID + * @return Result + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun delete(id: Long): Boolean +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/tool/IManagementService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/IManagementService.kt new file mode 100644 index 0000000..2ec08a7 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/IManagementService.kt @@ -0,0 +1,87 @@ +package top.fatweb.oxygen.api.service.tool + +import com.baomidou.mybatisplus.extension.service.IService +import top.fatweb.oxygen.api.entity.tool.Tool +import top.fatweb.oxygen.api.param.tool.ToolManagementGetParam +import top.fatweb.oxygen.api.param.tool.ToolManagementPassParam +import top.fatweb.oxygen.api.vo.PageVo +import top.fatweb.oxygen.api.vo.tool.ToolVo + +/** + * Tool management service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IService + * @see Tool + */ +interface IManagementService : IService { + /** + * Get tool by ID + * + * @param id Tool ID + * @return ToolVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolVo + */ + fun getOne(id: Long): ToolVo + + /** + * Get tool in page + * + * @param toolManagementGetParam Get tool parameters in tool management + * @return PageVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolManagementGetParam + * @see PageVo + * @see ToolVo + */ + fun getPage(toolManagementGetParam: ToolManagementGetParam?): PageVo + + /** + * Pass tool review + * + * @param id Tool ID + * @param toolManagementPassParam Pass tool review parameters in tool management + * @return ToolVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolManagementPassParam + * @see ToolVo + */ + fun pass(id: Long, toolManagementPassParam: ToolManagementPassParam): ToolVo + + /** + * Reject tool review + * + * @param id Tool ID + * @return ToolVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolVo + */ + fun reject(id: Long): ToolVo + + /** + * Off shelve tool + * + * @param id Tool ID + * @return ToolVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolVo + */ + fun offShelve(id: Long): ToolVo + + /** + * Delete tool + * + * @param id Tool ID + * @return Result + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun delete(id: Long): Boolean +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/tool/IRToolCategoryService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/IRToolCategoryService.kt new file mode 100644 index 0000000..4fc46c5 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/IRToolCategoryService.kt @@ -0,0 +1,14 @@ +package top.fatweb.oxygen.api.service.tool + +import com.baomidou.mybatisplus.extension.service.IService +import top.fatweb.oxygen.api.entity.tool.RToolCategory + +/** + * Tool category intermediate service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IService + * @see RToolCategory + */ +interface IRToolCategoryService : IService \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/tool/IStoreService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/IStoreService.kt new file mode 100644 index 0000000..956d114 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/IStoreService.kt @@ -0,0 +1,34 @@ +package top.fatweb.oxygen.api.service.tool + +import com.baomidou.mybatisplus.extension.service.IService +import top.fatweb.oxygen.api.entity.tool.Tool +import top.fatweb.oxygen.api.param.PageSortParam +import top.fatweb.oxygen.api.param.tool.ToolStoreGetParam +import top.fatweb.oxygen.api.vo.PageVo +import top.fatweb.oxygen.api.vo.tool.ToolVo + +/** + * Tool store service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IService + * @see Tool + */ +interface IStoreService : IService { + /** + * Get tool in page + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun getPage(toolStoreGetParam: ToolStoreGetParam?): PageVo + + /** + * Get tool by username in page + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun getPage(pageSortParam: PageSortParam, username: String): PageVo +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/tool/IToolBaseService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/IToolBaseService.kt new file mode 100644 index 0000000..5bd0966 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/IToolBaseService.kt @@ -0,0 +1,72 @@ +package top.fatweb.oxygen.api.service.tool + +import com.baomidou.mybatisplus.extension.service.IService +import top.fatweb.oxygen.api.entity.tool.ToolBase +import top.fatweb.oxygen.api.param.tool.ToolBaseAddParam +import top.fatweb.oxygen.api.param.tool.ToolBaseUpdateParam +import top.fatweb.oxygen.api.vo.tool.ToolBaseVo + +/** + * Tool base service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IService + * @see ToolBase + */ +interface IToolBaseService : IService { + /** + * Get tool base by ID + * + * @param id ID + * @return ToolBaseVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolBaseVo + */ + fun getOne(id: Long): ToolBaseVo + + /** + * Get tool base in list + * + * @return List of ToolBaseVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolBaseVo + */ + fun get(): List + + /** + * Add tool base + * + * @param toolBaseAddParam Add tool base parameters + * @return ToolBaseVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolBaseAddParam + * @see ToolBaseVo + */ + fun add(toolBaseAddParam: ToolBaseAddParam): ToolBaseVo + + /** + * Update tool base + * + * @param toolBaseUpdateParam Update tool base parameters + * @return ToolBaseVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolBaseUpdateParam + * @see ToolBaseVo + */ + fun update(toolBaseUpdateParam: ToolBaseUpdateParam): ToolBaseVo + + /** + * Delete tool base + * + * @param id ID + * @return Result + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun delete(id: Long): Boolean +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/tool/IToolCategoryService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/IToolCategoryService.kt new file mode 100644 index 0000000..7b2e3a5 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/IToolCategoryService.kt @@ -0,0 +1,72 @@ +package top.fatweb.oxygen.api.service.tool + +import com.baomidou.mybatisplus.extension.service.IService +import top.fatweb.oxygen.api.entity.tool.ToolCategory +import top.fatweb.oxygen.api.param.tool.ToolCategoryAddParam +import top.fatweb.oxygen.api.param.tool.ToolCategoryUpdateParam +import top.fatweb.oxygen.api.vo.tool.ToolCategoryVo + +/** + * Tool category service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IService + * @see ToolCategory + */ +interface IToolCategoryService : IService { + /** + * Get tool category by ID + * + * @param id ID + * @return ToolCategoryVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolCategoryVo + */ + fun getOne(id: Long): ToolCategoryVo + + /** + * Get tool category in list + * + * @return List of ToolCategoryVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolCategoryVo + */ + fun get(): List + + /** + * Add tool category + * + * @param toolCategoryAddParam Add tool category parameters + * @return ToolCategoryVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolCategoryAddParam + * @see ToolCategoryVo + */ + fun add(toolCategoryAddParam: ToolCategoryAddParam): ToolCategoryVo + + /** + * Update tool category + * + * @param toolCategoryUpdateParam Update tool category parameters + * @return ToolCategoryVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolCategoryUpdateParam + * @see ToolCategoryVo + */ + fun update(toolCategoryUpdateParam: ToolCategoryUpdateParam): ToolCategoryVo + + /** + * Delete tool category + * + * @param id ID + * @return Result + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun delete(id: Long): Boolean +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/tool/IToolDataService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/IToolDataService.kt new file mode 100644 index 0000000..b8e9adc --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/IToolDataService.kt @@ -0,0 +1,14 @@ +package top.fatweb.oxygen.api.service.tool + +import com.baomidou.mybatisplus.extension.service.IService +import top.fatweb.oxygen.api.entity.tool.ToolData + +/** + * Tool data service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IService + * @see ToolData + */ +interface IToolDataService : IService \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/tool/IToolTemplateService.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/IToolTemplateService.kt new file mode 100644 index 0000000..1cb3d54 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/IToolTemplateService.kt @@ -0,0 +1,72 @@ +package top.fatweb.oxygen.api.service.tool + +import com.baomidou.mybatisplus.extension.service.IService +import top.fatweb.oxygen.api.entity.tool.ToolTemplate +import top.fatweb.oxygen.api.param.tool.ToolTemplateAddParam +import top.fatweb.oxygen.api.param.tool.ToolTemplateUpdateParam +import top.fatweb.oxygen.api.vo.tool.ToolTemplateVo + +/** + * Tool template service interface + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see IService + * @see ToolTemplate + */ +interface IToolTemplateService : IService { + /** + * Get tool template by ID + * + * @param id ID + * @return ToolTemplateVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolTemplateVo + */ + fun getOne(id: Long): ToolTemplateVo + + /** + * Get tool template in list + * + * @return List of ToolTemplateVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolTemplateVo + */ + fun get(): List + + /** + * Add tool template + * + * @param toolTemplateAddParam Add tool template parameters + * @return ToolTemplateVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolTemplateAddParam + * @see ToolTemplateVo + */ + fun add(toolTemplateAddParam: ToolTemplateAddParam): ToolTemplateVo + + /** + * Update tool template + * + * @param toolTemplateUpdateParam Update tool template parameters + * @return ToolTemplateVo object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolTemplateUpdateParam + * @see ToolTemplateVo + */ + fun update(toolTemplateUpdateParam: ToolTemplateUpdateParam): ToolTemplateVo + + /** + * Delete tool template + * + * @param id ID + * @return Result + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun delete(id: Long): Boolean +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/tool/impl/EditServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/impl/EditServiceImpl.kt new file mode 100644 index 0000000..ab8268c --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/impl/EditServiceImpl.kt @@ -0,0 +1,256 @@ +package top.fatweb.oxygen.api.service.tool.impl + +import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper +import com.baomidou.mybatisplus.extension.kotlin.KtUpdateWrapper +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import org.springframework.dao.DuplicateKeyException +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import top.fatweb.oxygen.api.converter.tool.ToolCategoryConverter +import top.fatweb.oxygen.api.converter.tool.ToolConverter +import top.fatweb.oxygen.api.converter.tool.ToolTemplateConverter +import top.fatweb.oxygen.api.entity.tool.* +import top.fatweb.oxygen.api.exception.* +import top.fatweb.oxygen.api.mapper.tool.EditMapper +import top.fatweb.oxygen.api.param.tool.ToolCreateParam +import top.fatweb.oxygen.api.param.tool.ToolUpdateParam +import top.fatweb.oxygen.api.param.tool.ToolUpgradeParam +import top.fatweb.oxygen.api.service.tool.* +import top.fatweb.oxygen.api.util.WebUtil +import top.fatweb.oxygen.api.vo.tool.ToolCategoryVo +import top.fatweb.oxygen.api.vo.tool.ToolTemplateVo +import top.fatweb.oxygen.api.vo.tool.ToolVo + +/** + * Tool edit service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ServiceImpl + * @see EditMapper + * @see Tool + * @see IEditService + */ +@Service +class EditServiceImpl( + private val toolTemplateService: IToolTemplateService, + private val toolCategoryService: IToolCategoryService, + private val toolDataService: IToolDataService, + private val rToolCategoryService: IRToolCategoryService +) : ServiceImpl(), IEditService { + override fun getTemplate(): List = + toolTemplateService.list(KtQueryWrapper(ToolTemplate()).eq(ToolTemplate::enable, 1)) + .map(ToolTemplateConverter::toolTemplateToToolTemplateVoByList) + + override fun getTemplate(id: Long): ToolTemplateVo = + baseMapper.selectTemplate(id)?.let(ToolTemplateConverter::toolTemplateToToolTemplateVoWithBaseDist) + ?: throw NoRecordFoundException() + + override fun getCategory(): List = + toolCategoryService.list(KtQueryWrapper(ToolCategory()).eq(ToolCategory::enable, 1)) + .map(ToolCategoryConverter::toolCategoryToToolCategoryVo) + + override fun getOne(id: Long): ToolVo = + baseMapper.selectOne(id, WebUtil.getLoginUserId()!!) + ?.let(ToolConverter::toolToToolVo) ?: throw NoRecordFoundException() + + @Transactional + override fun create(toolCreateParam: ToolCreateParam): ToolVo { + baseMapper.selectOne( + KtQueryWrapper(Tool()).eq(Tool::toolId, toolCreateParam.toolId!!) + .eq(Tool::authorId, WebUtil.getLoginUserId()!!) + )?.let { throw DuplicateKeyException("Duplicate Key") } + val template = this.getTemplate(toolCreateParam.templateId!!) + val newSource = ToolData().apply { data = template.source!!.data } + val newDist = ToolData().apply { data = "" } + toolDataService.saveBatch(listOf(newSource, newDist)) + + val tool = Tool().apply { + name = toolCreateParam.name!!.trim() + toolId = toolCreateParam.toolId + icon = toolCreateParam.icon + description = toolCreateParam.description + baseId = template.base!!.id + authorId = WebUtil.getLoginUserId()!! + ver = toolCreateParam.ver!!.split(".").map(String::toLong).joinToString(".") + keywords = toolCreateParam.keywords + sourceId = newSource.id + distId = newDist.id + entryPoint = template.entryPoint + } + + this.save(tool) + + toolCreateParam.categories!!.forEach { + toolCategoryService.getById(it) ?: throw NoRecordFoundException() + rToolCategoryService.save(RToolCategory().apply { + toolId = tool.id + categoryId = it + }) + } + + return this.getOne(tool.id!!) + } + + @Transactional + override fun upgrade(toolUpgradeParam: ToolUpgradeParam): ToolVo { + val originalTool = this.detail("!", toolUpgradeParam.toolId!!, "latest") + if (originalTool.review == Tool.ReviewType.PROCESSING) { + throw ToolUnderReviewException() + } + if (originalTool.review != Tool.ReviewType.PASS || originalTool.publish == 0L) { + throw ToolHasUnpublishedVersionException() + } + + val originalVersion = originalTool.ver!! + if (originalVersion.split(".").map(String::toLong).joinToString(".") == toolUpgradeParam.ver!!.split(".") + .map(String::toLong).joinToString(".") + ) { + throw IllegalVersionException() + } + originalVersion.split(".").forEachIndexed { index, s -> + if ((toolUpgradeParam.ver.split(".")[index].toLong() < s.toLong())) { + throw IllegalVersionException() + } + } + + val newSource = ToolData().apply { data = originalTool.source!!.data } + val newDist = ToolData().apply { data = "" } + toolDataService.saveBatch(listOf(newSource, newDist)) + + val tool = Tool().apply { + name = originalTool.name!! + toolId = originalTool.toolId + icon = originalTool.icon + description = originalTool.description + baseId = originalTool.base!!.id + authorId = WebUtil.getLoginUserId()!! + ver = toolUpgradeParam.ver.split(".").map(String::toLong).joinToString(".") + keywords = originalTool.keywords + sourceId = newSource.id + distId = newDist.id + entryPoint = originalTool.entryPoint + } + + this.save(tool) + + originalTool.categories!!.forEach { + toolCategoryService.getById(it.id) ?: throw NoRecordFoundException() + rToolCategoryService.save(RToolCategory().apply { + toolId = tool.id + categoryId = it.id + }) + } + + return this.getOne(tool.id!!) + } + + @Transactional + override fun update(toolUpdateParam: ToolUpdateParam): ToolVo { + val tool = getById(toolUpdateParam.id) + if (tool.review == Tool.ReviewType.PROCESSING) { + throw ToolUnderReviewException() + } + if (tool.review == Tool.ReviewType.PASS || tool.publish != 0L) { + throw ToolHasBeenPublishedException() + } + + this.updateById(Tool().apply { + id = toolUpdateParam.id + name = toolUpdateParam.name + icon = toolUpdateParam.icon + description = toolUpdateParam.description + keywords = toolUpdateParam.keywords + }) + + if (!toolUpdateParam.categories.isNullOrEmpty()) { + val oldCategories = rToolCategoryService.list( + KtQueryWrapper(RToolCategory()).select(RToolCategory::categoryId).eq(RToolCategory::toolId, tool.id) + ).map(RToolCategory::categoryId) + val addCategories = HashSet() + val removeCategories = HashSet() + toolUpdateParam.categories.forEach(addCategories::add) + oldCategories.forEach { + it?.let(removeCategories::add) + } + removeCategories.removeAll(addCategories) + oldCategories.toSet().let(addCategories::removeAll) + + removeCategories.forEach { + rToolCategoryService.remove( + KtQueryWrapper(RToolCategory()).eq( + RToolCategory::toolId, tool.id + ).eq(RToolCategory::categoryId, it) + ) + } + + addCategories.forEach { + rToolCategoryService.save(RToolCategory().apply { + toolId = tool.id + categoryId = it + }) + } + } + + if (!toolUpdateParam.source.isNullOrBlank()) { + toolDataService.updateById(ToolData().apply { + id = tool.sourceId + data = toolUpdateParam.source + }) + } + + return this.getOne(tool.id!!) + } + + override fun get(): List = + baseMapper.selectPersonal(WebUtil.getLoginUserId()!!) + .map(ToolConverter::toolToToolVo) + + override fun detail(username: String, toolId: String, ver: String): ToolVo { + if (username == "!" && WebUtil.getLoginUserId() == null) { + throw NoRecordFoundException() + } + val toolList = baseMapper.selectDetail(username, toolId, ver, WebUtil.getLoginUsername()) + if (toolList.isNullOrEmpty()) { + throw NoRecordFoundException() + } + + return toolList.first().let(ToolConverter::toolToToolVo) + } + + override fun submit(id: Long): Boolean { + val tool = getById(id) + if (tool.review == Tool.ReviewType.PROCESSING) { + throw ToolUnderReviewException() + } + if (tool.review == Tool.ReviewType.PASS && tool.publish != 0L) { + throw ToolHasBeenPublishedException() + } + + return update(KtUpdateWrapper(Tool()).eq(Tool::id, id).set(Tool::review, Tool.ReviewType.PROCESSING)) + } + + override fun cancel(id: Long): Boolean { + val tool = getById(id) + if (tool.review == Tool.ReviewType.PASS && tool.publish != 0L) { + throw ToolHasBeenPublishedException() + } + if (tool.review != Tool.ReviewType.PROCESSING) { + throw ToolNotUnderReviewException() + } + + return update(KtUpdateWrapper(Tool()).eq(Tool::id, id).set(Tool::review, Tool.ReviewType.NONE)) + } + + @Transactional + override fun delete(id: Long): Boolean { + val tool = baseMapper.selectOne( + KtQueryWrapper(Tool()).eq(Tool::id, id) + .eq(Tool::authorId, WebUtil.getLoginUserId()!!) + ) ?: throw NoRecordFoundException() + + toolDataService.removeBatchByIds(listOf(tool.sourceId, tool.distId)) + rToolCategoryService.remove(KtQueryWrapper(RToolCategory()).eq(RToolCategory::toolId, tool.id)) + return this.removeById(id) + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/tool/impl/ManagementServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/impl/ManagementServiceImpl.kt new file mode 100644 index 0000000..19309bc --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/impl/ManagementServiceImpl.kt @@ -0,0 +1,128 @@ +package top.fatweb.oxygen.api.service.tool.impl + +import com.baomidou.mybatisplus.core.metadata.OrderItem +import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper +import com.baomidou.mybatisplus.extension.kotlin.KtUpdateWrapper +import com.baomidou.mybatisplus.extension.plugins.pagination.Page +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import top.fatweb.oxygen.api.converter.tool.ToolConverter +import top.fatweb.oxygen.api.entity.tool.RToolCategory +import top.fatweb.oxygen.api.entity.tool.Tool +import top.fatweb.oxygen.api.entity.tool.ToolData +import top.fatweb.oxygen.api.exception.NoRecordFoundException +import top.fatweb.oxygen.api.exception.ToolHasNotBeenPublishedException +import top.fatweb.oxygen.api.exception.ToolNotUnderReviewException +import top.fatweb.oxygen.api.mapper.tool.ManagementMapper +import top.fatweb.oxygen.api.param.tool.ToolManagementGetParam +import top.fatweb.oxygen.api.param.tool.ToolManagementPassParam +import top.fatweb.oxygen.api.service.tool.IManagementService +import top.fatweb.oxygen.api.service.tool.IRToolCategoryService +import top.fatweb.oxygen.api.service.tool.IToolDataService +import top.fatweb.oxygen.api.util.PageUtil +import top.fatweb.oxygen.api.vo.PageVo +import top.fatweb.oxygen.api.vo.tool.ToolVo +import java.time.LocalDateTime +import java.time.ZoneOffset + +/** + * Tool management service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ServiceImpl + * @see ManagementMapper + * @see Tool + * @see IManagementService + */ +@Service +class ManagementServiceImpl( + private val toolDataService: IToolDataService, + private val rToolCategoryService: IRToolCategoryService +) : ServiceImpl(), IManagementService { + override fun getOne(id: Long): ToolVo = + baseMapper.selectOne(id) + ?.let(ToolConverter::toolToToolVo) ?: throw NoRecordFoundException() + + override fun getPage(toolManagementGetParam: ToolManagementGetParam?): PageVo { + val toolIdsPage = Page(toolManagementGetParam?.currentPage ?: 1, toolManagementGetParam?.pageSize ?: 20) + toolIdsPage.setOptimizeCountSql(false) + + val toolIdsIPage = + baseMapper.selectPage( + toolIdsPage, + toolManagementGetParam?.review?.split(","), + toolManagementGetParam?.searchType ?: "ALL", + toolManagementGetParam?.searchValue, + toolManagementGetParam?.searchRegex ?: false + ) + val toolPage = Page(toolIdsIPage.current, toolIdsIPage.size, toolIdsIPage.total) + if (toolIdsIPage.total > 0) { + toolPage.setRecords(baseMapper.selectListByIds(toolIdsIPage.records)) + } + + return ToolConverter.toolPageToToolPageVo(toolPage) + } + + override fun pass(id: Long, toolManagementPassParam: ToolManagementPassParam): ToolVo { + val tool = this.getById(id) ?: throw NoRecordFoundException() + if (tool.review !== Tool.ReviewType.PROCESSING) { + throw ToolNotUnderReviewException() + } + + toolDataService.update( + KtUpdateWrapper(ToolData()).eq(ToolData::id, tool.distId).set(ToolData::data, toolManagementPassParam.dist) + ) + + this.update( + KtUpdateWrapper(Tool()) + .eq(Tool::id, id) + .set(Tool::review, Tool.ReviewType.PASS) + .set(Tool::publish, LocalDateTime.now(ZoneOffset.UTC).toInstant(ZoneOffset.UTC).toEpochMilli()) + ) + + return this.getOne(id) + } + + override fun reject(id: Long): ToolVo { + val tool = this.getById(id) ?: throw NoRecordFoundException() + if (tool.review !== Tool.ReviewType.PROCESSING) { + throw ToolNotUnderReviewException() + } + + this.update( + KtUpdateWrapper(Tool()) + .eq(Tool::id, id) + .set(Tool::review, Tool.ReviewType.REJECT) + ) + + return this.getOne(id) + } + + override fun offShelve(id: Long): ToolVo { + val tool = this.getById(id) ?: throw NoRecordFoundException() + if (tool.review !== Tool.ReviewType.PASS && tool.publish == 0L) { + throw ToolHasNotBeenPublishedException() + } + + this.update( + KtUpdateWrapper(Tool()) + .eq(Tool::id, id) + .set(Tool::review, Tool.ReviewType.REJECT) + ) + + return this.getOne(id) + } + + @Transactional + override fun delete(id: Long): Boolean { + val tool = this.getById(id) ?: throw NoRecordFoundException() + + toolDataService.removeBatchByIds(listOf(tool.sourceId, tool.distId)) + rToolCategoryService.remove(KtQueryWrapper(RToolCategory()).eq(RToolCategory::toolId, id)) + + return this.removeById(id) + } + +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/tool/impl/RToolCategoryServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/impl/RToolCategoryServiceImpl.kt new file mode 100644 index 0000000..87844df --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/impl/RToolCategoryServiceImpl.kt @@ -0,0 +1,20 @@ +package top.fatweb.oxygen.api.service.tool.impl + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import org.springframework.stereotype.Service +import top.fatweb.oxygen.api.entity.tool.RToolCategory +import top.fatweb.oxygen.api.mapper.tool.RToolCategoryMapper +import top.fatweb.oxygen.api.service.tool.IRToolCategoryService + +/** + * Tool category service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ServiceImpl + * @see RToolCategoryMapper + * @see RToolCategory + * @see IRToolCategoryService + */ +@Service +class RToolCategoryServiceImpl : ServiceImpl(), IRToolCategoryService \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/tool/impl/StoreServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/impl/StoreServiceImpl.kt new file mode 100644 index 0000000..a59d487 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/impl/StoreServiceImpl.kt @@ -0,0 +1,52 @@ +package top.fatweb.oxygen.api.service.tool.impl + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import org.springframework.stereotype.Service +import top.fatweb.oxygen.api.converter.tool.ToolConverter +import top.fatweb.oxygen.api.entity.tool.Tool +import top.fatweb.oxygen.api.mapper.tool.StoreMapper +import top.fatweb.oxygen.api.param.PageSortParam +import top.fatweb.oxygen.api.param.tool.ToolStoreGetParam +import top.fatweb.oxygen.api.service.tool.IStoreService +import top.fatweb.oxygen.api.vo.PageVo +import top.fatweb.oxygen.api.vo.tool.ToolVo + +/** + * Tool store service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ServiceImpl + * @see StoreMapper + * @see Tool + * @see IStoreService + */ +@Service +class StoreServiceImpl : ServiceImpl(), IStoreService { + override fun getPage(toolStoreGetParam: ToolStoreGetParam?): PageVo { + val toolIdsPage = Page(toolStoreGetParam?.currentPage ?: 1, 20) + toolIdsPage.setOptimizeCountSql(false) + + val toolIdsIPage = baseMapper.selectPage(toolIdsPage, toolStoreGetParam?.searchValue) + val toolPage = Page(toolIdsIPage.current, toolIdsIPage.size, toolIdsIPage.total) + if (toolIdsIPage.total > 0) { + toolPage.setRecords(baseMapper.selectListByIds(toolIdsIPage.records)) + } + + return ToolConverter.toolPageToToolPageVo(toolPage) + } + + override fun getPage(pageSortParam: PageSortParam, username: String): PageVo { + val toolIdsPage = Page(pageSortParam.currentPage, 20) + toolIdsPage.setOptimizeCountSql(false) + + val toolIdsIPage = baseMapper.selectPageByUsername(toolIdsPage, username) + val toolPage = Page(toolIdsIPage.current, toolIdsIPage.size, toolIdsIPage.total) + if (toolIdsIPage.total > 0) { + toolPage.setRecords(baseMapper.selectListByIds(toolIdsIPage.records)) + } + + return ToolConverter.toolPageToToolPageVo(toolPage) + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/tool/impl/ToolBaseServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/impl/ToolBaseServiceImpl.kt new file mode 100644 index 0000000..e1070f9 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/impl/ToolBaseServiceImpl.kt @@ -0,0 +1,94 @@ +package top.fatweb.oxygen.api.service.tool.impl + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import top.fatweb.oxygen.api.converter.tool.ToolBaseConverter +import top.fatweb.oxygen.api.entity.tool.ToolBase +import top.fatweb.oxygen.api.entity.tool.ToolData +import top.fatweb.oxygen.api.exception.NoRecordFoundException +import top.fatweb.oxygen.api.mapper.tool.ToolBaseMapper +import top.fatweb.oxygen.api.param.tool.ToolBaseAddParam +import top.fatweb.oxygen.api.param.tool.ToolBaseUpdateParam +import top.fatweb.oxygen.api.service.tool.IToolBaseService +import top.fatweb.oxygen.api.service.tool.IToolDataService +import top.fatweb.oxygen.api.vo.tool.ToolBaseVo + +/** + * Tool base service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ServiceImpl + * @see ToolBaseMapper + * @see ToolBase + * @see IToolBaseService + */ +@Service +class ToolBaseServiceImpl( + private val toolDataService: IToolDataService +) : ServiceImpl(), IToolBaseService { + override fun getOne(id: Long): ToolBaseVo = + baseMapper.selectOne(id)?.let(ToolBaseConverter::toolBaseToToolBaseVo) ?: throw NoRecordFoundException() + + override fun get(): List = this.list().map(ToolBaseConverter::toolBaseToToolBaseVoByGetList) + + @Transactional + override fun add(toolBaseAddParam: ToolBaseAddParam): ToolBaseVo { + val newSource = ToolData().apply { data = "" } + val newDist = ToolData().apply { data = "" } + + toolDataService.saveBatch(listOf(newSource, newDist)) + + val toolBase = ToolBase().apply { + name = toolBaseAddParam.name + sourceId = newSource.id + distId = newDist.id + source = newSource + dist = newDist + } + + this.save(toolBase) + + return ToolBaseConverter.toolBaseToToolBaseVo(toolBase) + } + + @Transactional + override fun update(toolBaseUpdateParam: ToolBaseUpdateParam): ToolBaseVo { + val toolBase = baseMapper.selectOne(toolBaseUpdateParam.id!!) ?: throw NoRecordFoundException() + + var hasCompiled: Int? = null + + if (!toolBaseUpdateParam.source.isNullOrBlank()) { + toolDataService.updateById(ToolData().apply { + id = toolBase.sourceId + data = toolBaseUpdateParam.source + }) + hasCompiled = 0 + } + + if (!toolBaseUpdateParam.dist.isNullOrBlank()) { + toolDataService.updateById(ToolData().apply { + id = toolBase.distId + data = toolBaseUpdateParam.dist + }) + hasCompiled = 1 + } + + this.updateById(ToolBase().apply { + id = toolBaseUpdateParam.id + name = toolBaseUpdateParam.name + compiled = hasCompiled + }) + + return this.getOne(toolBase.id!!) + } + + @Transactional + override fun delete(id: Long): Boolean { + val toolBase = this.getById(id) + + return toolDataService.removeBatchByIds(listOf(toolBase.sourceId, toolBase.distId)) + && this.removeById(id) + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/tool/impl/ToolCategoryServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/impl/ToolCategoryServiceImpl.kt new file mode 100644 index 0000000..ed11c75 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/impl/ToolCategoryServiceImpl.kt @@ -0,0 +1,55 @@ +package top.fatweb.oxygen.api.service.tool.impl + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import org.springframework.stereotype.Service +import top.fatweb.oxygen.api.converter.tool.ToolCategoryConverter +import top.fatweb.oxygen.api.entity.tool.ToolCategory +import top.fatweb.oxygen.api.exception.DatabaseInsertException +import top.fatweb.oxygen.api.exception.DatabaseUpdateException +import top.fatweb.oxygen.api.exception.NoRecordFoundException +import top.fatweb.oxygen.api.mapper.tool.ToolCategoryMapper +import top.fatweb.oxygen.api.param.tool.ToolCategoryAddParam +import top.fatweb.oxygen.api.param.tool.ToolCategoryUpdateParam +import top.fatweb.oxygen.api.service.tool.IToolCategoryService +import top.fatweb.oxygen.api.vo.tool.ToolCategoryVo + +/** + * Tool category service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ServiceImpl + * @see ToolCategoryMapper + * @see ToolCategory + * @see IToolCategoryService + */ +@Service +class ToolCategoryServiceImpl : ServiceImpl(), IToolCategoryService { + override fun getOne(id: Long): ToolCategoryVo = + this.getById(id)?.let(ToolCategoryConverter::toolCategoryToToolCategoryVo) ?: throw NoRecordFoundException() + + override fun get(): List = + this.list().map(ToolCategoryConverter::toolCategoryToToolCategoryVo) + + override fun add(toolCategoryAddParam: ToolCategoryAddParam): ToolCategoryVo { + val toolCategory = ToolCategoryConverter.toolCategoryAddParamToToolCategory(toolCategoryAddParam) + + if (!this.save(toolCategory)) { + throw DatabaseInsertException() + } + + return ToolCategoryConverter.toolCategoryToToolCategoryVo(toolCategory) + } + + override fun update(toolCategoryUpdateParam: ToolCategoryUpdateParam): ToolCategoryVo { + val toolCategory = ToolCategoryConverter.toolCategoryUpdateParamToToolCategory(toolCategoryUpdateParam) + + if (!this.updateById(toolCategory)) { + throw DatabaseUpdateException() + } + + return ToolCategoryConverter.toolCategoryToToolCategoryVo(toolCategory) + } + + override fun delete(id: Long): Boolean = this.removeById(id) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/tool/impl/ToolDataServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/impl/ToolDataServiceImpl.kt new file mode 100644 index 0000000..74cc3ca --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/impl/ToolDataServiceImpl.kt @@ -0,0 +1,20 @@ +package top.fatweb.oxygen.api.service.tool.impl + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import org.springframework.stereotype.Service +import top.fatweb.oxygen.api.entity.tool.ToolData +import top.fatweb.oxygen.api.mapper.tool.ToolDataMapper +import top.fatweb.oxygen.api.service.tool.IToolDataService + +/** + * Tool data service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ServiceImpl + * @see ToolDataMapper + * @see ToolData + * @see IToolDataService + */ +@Service +class ToolDataServiceImpl : ServiceImpl(), IToolDataService \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/service/tool/impl/ToolTemplateServiceImpl.kt b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/impl/ToolTemplateServiceImpl.kt new file mode 100644 index 0000000..ab9e16a --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/service/tool/impl/ToolTemplateServiceImpl.kt @@ -0,0 +1,90 @@ +package top.fatweb.oxygen.api.service.tool.impl + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import top.fatweb.oxygen.api.converter.tool.ToolTemplateConverter +import top.fatweb.oxygen.api.entity.tool.ToolData +import top.fatweb.oxygen.api.entity.tool.ToolTemplate +import top.fatweb.oxygen.api.exception.NoRecordFoundException +import top.fatweb.oxygen.api.mapper.tool.ToolTemplateMapper +import top.fatweb.oxygen.api.param.tool.ToolTemplateAddParam +import top.fatweb.oxygen.api.param.tool.ToolTemplateUpdateParam +import top.fatweb.oxygen.api.service.tool.IToolBaseService +import top.fatweb.oxygen.api.service.tool.IToolDataService +import top.fatweb.oxygen.api.service.tool.IToolTemplateService +import top.fatweb.oxygen.api.vo.tool.ToolTemplateVo + +/** + * Tool template service implement + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ServiceImpl + * @see ToolTemplateMapper + * @see ToolTemplate + * @see IToolTemplateService + */ +@Service +class ToolTemplateServiceImpl( + private val toolDataService: IToolDataService, + private val toolBaseService: IToolBaseService +) : ServiceImpl(), IToolTemplateService { + override fun getOne(id: Long): ToolTemplateVo = + baseMapper.selectOne(id)?.let(ToolTemplateConverter::toolTemplateToToolTemplateVo) + ?: throw NoRecordFoundException() + + override fun get(): List = + baseMapper.selectList().map(ToolTemplateConverter::toolTemplateToToolTemplateVo) + + @Transactional + override fun add(toolTemplateAddParam: ToolTemplateAddParam): ToolTemplateVo { + toolBaseService.getOne(toolTemplateAddParam.baseId!!) + + val newSource = ToolData().apply { data = "" } + + toolDataService.save(newSource) + + val toolTemplate = ToolTemplate().apply { + name = toolTemplateAddParam.name + baseId = toolTemplateAddParam.baseId + sourceId = newSource.id + source = newSource + entryPoint = toolTemplateAddParam.entryPoint + enable = if (toolTemplateAddParam.enable) 1 else 0 + } + + this.save(toolTemplate) + + return ToolTemplateConverter.toolTemplateToToolTemplateVo(toolTemplate) + } + + @Transactional + override fun update(toolTemplateUpdateParam: ToolTemplateUpdateParam): ToolTemplateVo { + val toolTemplate = baseMapper.selectOne(toolTemplateUpdateParam.id!!) ?: throw NoRecordFoundException() + toolTemplateUpdateParam.baseId?.let(toolBaseService::getOne) + + toolDataService.updateById(ToolData().apply { + id = toolTemplate.sourceId + data = toolTemplateUpdateParam.source + }) + + this.updateById(ToolTemplate().apply { + id = toolTemplateUpdateParam.id + name = toolTemplateUpdateParam.name + baseId = toolTemplateUpdateParam.baseId + entryPoint = toolTemplateUpdateParam.entryPoint + enable = toolTemplateUpdateParam.enable?.let { if (it) 1 else 0 } + }) + + return this.getOne(toolTemplate.id!!) + } + + @Transactional + override fun delete(id: Long): Boolean { + val toolTemplate = this.getById(id) + + return toolDataService.removeById(toolTemplate.sourceId) + && this.removeById(id) + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/settings/BaseSettings.kt b/src/main/kotlin/top/fatweb/oxygen/api/settings/BaseSettings.kt new file mode 100644 index 0000000..4de70bf --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/settings/BaseSettings.kt @@ -0,0 +1,44 @@ +package top.fatweb.oxygen.api.settings + +import com.fasterxml.jackson.annotation.JsonInclude + +/** + * Base settings entity + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@JsonInclude(JsonInclude.Include.NON_EMPTY) +data class BaseSettings( + /** + * Application name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var appName: String? = null, + + /** + * Application URL + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var appUrl: String? = null, + + /** + * Verify URL + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var verifyUrl: String? = null, + + /** + * Retrieve URL + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var retrieveUrl: String? = null +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/settings/MailSecurityType.kt b/src/main/kotlin/top/fatweb/oxygen/api/settings/MailSecurityType.kt new file mode 100644 index 0000000..ede4118 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/settings/MailSecurityType.kt @@ -0,0 +1,31 @@ +package top.fatweb.oxygen.api.settings + +import com.fasterxml.jackson.annotation.JsonCreator +import com.fasterxml.jackson.annotation.JsonValue + +/** + * Type of mail security + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +enum class MailSecurityType(val code: String) { + NONE("None"), + SSL_TLS("SSL/TLS"), + START_TLS("StartTls"); + + @JsonCreator + fun fromCode(code: String): MailSecurityType? { + entries.forEach { + if (it.code == code) { + return it + } + } + return null + } + + @JsonValue + override fun toString(): String { + return code + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/settings/MailSettings.kt b/src/main/kotlin/top/fatweb/oxygen/api/settings/MailSettings.kt new file mode 100644 index 0000000..5c2fa27 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/settings/MailSettings.kt @@ -0,0 +1,68 @@ +package top.fatweb.oxygen.api.settings + +import com.fasterxml.jackson.annotation.JsonInclude + +/** + * Mail settings entity + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@JsonInclude(JsonInclude.Include.NON_EMPTY) +data class MailSettings( + /** + * Host + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var host: String? = null, + + /** + * Port + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var port: Int? = null, + + /** + * Security type + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var securityType: MailSecurityType? = MailSecurityType.NONE, + + /** + * Username + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var username: String? = null, + + /** + * Password + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var password: String? = null, + + /** + * Sender + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var from: String? = null, + + /** + * Sender name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var fromName: String? = null +) \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/settings/SettingsOperator.kt b/src/main/kotlin/top/fatweb/oxygen/api/settings/SettingsOperator.kt new file mode 100644 index 0000000..7388b72 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/settings/SettingsOperator.kt @@ -0,0 +1,172 @@ +package top.fatweb.oxygen.api.settings + +import com.fasterxml.jackson.databind.exc.MismatchedInputException +import com.fasterxml.jackson.dataformat.yaml.YAMLMapper +import com.fasterxml.jackson.module.kotlin.readValue +import top.fatweb.oxygen.api.util.StrUtil +import java.io.File +import java.io.IOException +import kotlin.reflect.KMutableProperty1 + +/** + * Settings operator + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +object SettingsOperator { + private const val SETTINGS_FILE_NAME = "data/config/settings.yml" + + private val yamlMapper = YAMLMapper() + private val settingFile = File(SETTINGS_FILE_NAME) + private lateinit var systemSettings: SystemSettings + + init { + getFromSettingsFile() + } + + /** + * Get settings from settings file + * + * @throws IOException + * @throws MismatchedInputException + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Throws(IOException::class, MismatchedInputException::class) + private fun getFromSettingsFile() { + if (settingFile.isDirectory) { + throw IOException("'${settingFile.absoluteFile}' is a directory, cannot create settings file") + } + + if (!settingFile.isFile) { + if (settingFile.parentFile.isFile) { + throw IOException("'${settingFile.parentFile.absoluteFile}' is a file, cannot create settings file") + } + + if (!settingFile.parentFile.isDirectory) { + if (!settingFile.parentFile.mkdirs()) { + throw IOException("Cannot make directory: ${settingFile.parentFile.absolutePath}") + } + } + settingFile.delete() + settingFile.createNewFile() + } + + if (settingFile.length() == 0L) { + systemSettings = SystemSettings() + saveSettingsToFile() + } + + systemSettings = yamlMapper.readValue(settingFile) + } + + /** + * Save settings to settings file + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + private fun saveSettingsToFile() { + yamlMapper.writeValue(settingFile, systemSettings) + } + + /** + * Set base settings value + * + * @param field Field to set value. e.g. BaseSettings::appName + * @param value Value to set + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see KMutableProperty1 + * @see BaseSettings + */ + fun setAppValue(field: KMutableProperty1, value: V?) { + systemSettings.base?.let { + field.set(it, value) + } ?: let { + systemSettings.base = BaseSettings().also { field.set(it, value) } + } + + saveSettingsToFile() + } + + /** + * Get base settings value + * + * @param field Field to get value from. e.g. BaseSettings::appName + * @return Value + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see KMutableProperty1 + * @see BaseSettings + */ + fun getAppValue(field: KMutableProperty1): V? = this.getAppValue(field, null) + + /** + * Get base settings value with default value + * + * @param field Field to get value from. e.g. BaseSettings::appName + * @param default Return default value when setting not found + * @return Value + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see KMutableProperty1 + * @see BaseSettings + */ + fun getAppValue(field: KMutableProperty1, default: V): V = + systemSettings.base?.let(field) ?: default + + /** + * Set mail settings value + * + * @param field Field to set value. e.g. MailSettings::host + * @param value Value to set + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see KMutableProperty1 + * @see MailSettings + */ + fun setMailValue(field: KMutableProperty1, value: V?) { + systemSettings.mail?.let { + if (field == MailSettings::password) { + getMailValue(MailSettings::password)?.let { password -> + if (StrUtil.md5(password) == value) { + return + } + } + } + field.set(it, value) + } ?: let { + systemSettings.mail = MailSettings().also { field.set(it, value) } + } + + saveSettingsToFile() + } + + /** + * Get value from mail settings + * + * @param field Field to get value from. e.g. MailSettings::host + * @return Value + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see KMutableProperty1 + * @see MailSettings + */ + fun getMailValue(field: KMutableProperty1): V? = this.getMailValue(field, null) + + /** + * Get value from mail settings with default value + * + * @param field Field to get value from. e.g. MailSettings::host + * @param default Return default value when setting not found + * @return Value + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see KMutableProperty1 + * @see MailSettings + */ + fun getMailValue(field: KMutableProperty1, default: V): V = + systemSettings.mail?.let(field) ?: default +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/settings/SystemSettings.kt b/src/main/kotlin/top/fatweb/oxygen/api/settings/SystemSettings.kt new file mode 100644 index 0000000..b15a9f7 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/settings/SystemSettings.kt @@ -0,0 +1,28 @@ +package top.fatweb.oxygen.api.settings + +import com.fasterxml.jackson.annotation.JsonInclude + +/** + * System setting entity + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@JsonInclude(JsonInclude.Include.NON_EMPTY) +data class SystemSettings( + /** + * Base setting + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var base: BaseSettings? = null, + + /** + * Mail setting + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + var mail: MailSettings? = null +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/util/ApiResponseMappingHandlerMapping.kt b/src/main/kotlin/top/fatweb/oxygen/api/util/ApiResponseMappingHandlerMapping.kt new file mode 100644 index 0000000..7d10d7e --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/util/ApiResponseMappingHandlerMapping.kt @@ -0,0 +1,26 @@ +package top.fatweb.oxygen.api.util + +import org.springframework.web.servlet.mvc.condition.RequestCondition +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping +import top.fatweb.oxygen.api.annotation.ApiController +import java.lang.reflect.Method + +/** + * Api response mapping handler mapping + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +class ApiResponseMappingHandlerMapping : RequestMappingHandlerMapping() { + + private fun createCondition(clazz: Class<*>): RequestCondition? { + val apiController = clazz.getAnnotation(ApiController::class.java) + apiController ?: return null + + return ApiVersionCondition(apiController.version) + } + + override fun getCustomMethodCondition(method: Method): RequestCondition<*>? = createCondition(method.javaClass) + + override fun getCustomTypeCondition(handlerType: Class<*>): RequestCondition<*>? = createCondition(handlerType) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/util/ApiVersionCondition.kt b/src/main/kotlin/top/fatweb/oxygen/api/util/ApiVersionCondition.kt similarity index 65% rename from src/main/kotlin/top/fatweb/api/util/ApiVersionCondition.kt rename to src/main/kotlin/top/fatweb/oxygen/api/util/ApiVersionCondition.kt index 381edaa..90411cf 100644 --- a/src/main/kotlin/top/fatweb/api/util/ApiVersionCondition.kt +++ b/src/main/kotlin/top/fatweb/oxygen/api/util/ApiVersionCondition.kt @@ -1,19 +1,22 @@ -package top.fatweb.api.util +package top.fatweb.oxygen.api.util import jakarta.servlet.http.HttpServletRequest import org.springframework.web.servlet.mvc.condition.RequestCondition -import java.util.regex.Pattern +/** + * Api version condition + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ class ApiVersionCondition(private val apiVersion: Int) : RequestCondition { - private val versionPrefixPattern: Pattern = Pattern.compile(".*v(\\d+).*") + private val versionPrefixRegex = Regex("/api/v(\\d+)/.*") override fun combine(other: ApiVersionCondition): ApiVersionCondition = ApiVersionCondition(other.apiVersion) override fun getMatchingCondition(request: HttpServletRequest): ApiVersionCondition? { - val matcher = versionPrefixPattern.matcher(request.requestURI) - if (matcher.find()) { - val version = matcher.group(1).toInt() - if (version >= this.apiVersion) { + versionPrefixRegex.matchAt(request.requestURI, 0)?.let { + if (it.groupValues[1].toInt() >= this.apiVersion) { return this } } diff --git a/src/main/kotlin/top/fatweb/oxygen/api/util/ByteUtil.kt b/src/main/kotlin/top/fatweb/oxygen/api/util/ByteUtil.kt new file mode 100644 index 0000000..c18a46e --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/util/ByteUtil.kt @@ -0,0 +1,166 @@ +package top.fatweb.oxygen.api.util + +import kotlin.math.floor + +/** + * Byte util + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +object ByteUtil { + private const val BASE = 1024 + + /** + * Byte unit + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + enum class ByteUnit { + /** + * Byte + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + B, + + /** + * Kibibyte + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + KiB, + + /** + * Mebibyte + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + MiB, + + /** + * Gibibyte + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + GiB, + + /** + * Tebibyte + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + TiB, + + /** + * Pebibyte + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + PiB, + + /** + * Exbibyte + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + EiB, + + /** + * Zebibyte + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + ZiB, + + /** + * Yobibyte + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + YiB + } + + /** + * Format byte size + * + * @param byteSize ByteSize + * @return Result + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun formatByteSize(byteSize: Long): String { + if (byteSize <= -1) { + return byteSize.toString() + } + + var size = byteSize.toDouble() + if (floor(size / BASE) <= 0) { + return format(size, ByteUnit.B) + } + + size /= BASE + if (floor(size / BASE) <= 0) { + return format(size, ByteUnit.KiB) + } + + size /= BASE + if (floor(size / BASE) <= 0) { + return format(size, ByteUnit.MiB) + } + + size /= BASE + if (floor(size / BASE) <= 0) { + return format(size, ByteUnit.GiB) + } + + size /= BASE + if (floor(size / BASE) <= 0) { + return format(size, ByteUnit.TiB) + } + + size /= BASE + if (floor(size / BASE) <= 0) { + return format(size, ByteUnit.PiB) + } + + size /= BASE + if (floor(size / BASE) <= 0) { + return format(size, ByteUnit.EiB) + } + + size /= BASE + if (floor(size / BASE) <= 0) { + return format(size, ByteUnit.ZiB) + } + + size /= BASE + return format(size, ByteUnit.YiB) + } + + private fun format(size: Double, unit: ByteUnit): String { + val precision = if (size * 1000 % 10 > 0) { + 3 + } else if (size * 100 % 10 > 0) { + 2 + } else if (size * 10 % 10 > 0) { + 1 + } else { + 0 + } + + val formatStr = "%.${precision}f" + + return String.format(formatStr, size) + unit.name + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/api/util/JwtUtil.kt b/src/main/kotlin/top/fatweb/oxygen/api/util/JwtUtil.kt similarity index 55% rename from src/main/kotlin/top/fatweb/api/util/JwtUtil.kt rename to src/main/kotlin/top/fatweb/oxygen/api/util/JwtUtil.kt index ea7c5aa..a831d5f 100644 --- a/src/main/kotlin/top/fatweb/api/util/JwtUtil.kt +++ b/src/main/kotlin/top/fatweb/oxygen/api/util/JwtUtil.kt @@ -1,41 +1,52 @@ -package top.fatweb.api.util +package top.fatweb.oxygen.api.util import com.auth0.jwt.JWT import com.auth0.jwt.algorithms.Algorithm import com.auth0.jwt.interfaces.DecodedJWT -import top.fatweb.api.constant.SecurityConstants +import top.fatweb.oxygen.api.properties.SecurityProperties import java.util.* import java.util.concurrent.TimeUnit import javax.crypto.spec.SecretKeySpec +/** + * Jwt util + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ object JwtUtil { private fun getUUID() = UUID.randomUUID().toString().replace("-", "") /** - * 生成加密后的秘钥 secretKey + * Generate encrypted secret key * - * @return 密钥 + * @return Secret key + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 */ private fun generalKey(): SecretKeySpec { - val encodeKey = Base64.getDecoder().decode(SecurityConstants.jwtKey) + val encodeKey = Base64.getDecoder().decode(SecurityProperties.jwtKey) return SecretKeySpec(encodeKey, 0, encodeKey.size, "AES") } private fun algorithm(): Algorithm = Algorithm.HMAC256(generalKey().toString()) /** - * 创建 token + * Create token * - * @param subject token 中存放的数据(json格式) - * @param ttl token 生存时间 - * @param timeUnit ttl 时间单位 - * @param uuid 唯一 ID - * @return jwt 串 + * @param subject Data stored in token (json format) + * @param ttl TTL of token + * @param timeUnit TTL unit of token + * @param uuid UUID + * @return JWT token + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see TimeUnit */ fun createJwt( subject: String, - ttl: Long = SecurityConstants.jwtTtl, - timeUnit: TimeUnit = SecurityConstants.jwtTtlUnit, + ttl: Long = SecurityProperties.jwtTtl, + timeUnit: TimeUnit = SecurityProperties.jwtTtlUnit, uuid: String = getUUID() ): String? { val nowMillis = System.currentTimeMillis() @@ -52,16 +63,18 @@ object JwtUtil { val expMillis = nowMillis + unitTtl val expDate = Date(expMillis) - return JWT.create().withJWTId(uuid).withSubject(subject).withIssuer(SecurityConstants.jwtIssuer) + return JWT.create().withJWTId(uuid).withSubject(subject).withIssuer(SecurityProperties.jwtIssuer) .withIssuedAt(nowDate).withExpiresAt(expDate).sign(algorithm()) } /** - * 解析 jwt + * Parse JWT token * - * @param jwt jwt 串 - * @return 解析内容 + * @param jwt JWT token + * @return Parsed content + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see DecodedJWT */ - fun parseJwt(jwt: String): DecodedJWT = - JWT.require(algorithm()).build().verify(jwt) + fun parseJwt(jwt: String): DecodedJWT = JWT.require(algorithm()).build().verify(jwt) } \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/util/MailUtil.kt b/src/main/kotlin/top/fatweb/oxygen/api/util/MailUtil.kt new file mode 100644 index 0000000..d89d02c --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/util/MailUtil.kt @@ -0,0 +1,57 @@ +package top.fatweb.oxygen.api.util + +import org.springframework.mail.javamail.JavaMailSenderImpl +import org.springframework.mail.javamail.MimeMessageHelper +import top.fatweb.oxygen.api.exception.NoEmailConfigException +import top.fatweb.oxygen.api.settings.MailSecurityType +import top.fatweb.oxygen.api.settings.MailSettings +import top.fatweb.oxygen.api.settings.SettingsOperator +import java.util.* + +/** + * Mail util + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +object MailUtil { + private val mailSender: JavaMailSenderImpl = JavaMailSenderImpl() + + init { + init() + } + + fun init() { + mailSender.defaultEncoding = Charsets.UTF_8.name() + mailSender.protocol = "smtp" + mailSender.host = SettingsOperator.getMailValue(MailSettings::host) + SettingsOperator.getMailValue(MailSettings::port)?.let { mailSender.port = it } + mailSender.username = SettingsOperator.getMailValue(MailSettings::username) + mailSender.password = SettingsOperator.getMailValue(MailSettings::password) + + val properties = Properties() + when (SettingsOperator.getMailValue(MailSettings::securityType)) { + MailSecurityType.SSL_TLS -> properties.setProperty("mail.smtp.ssl.enable", "true") + MailSecurityType.START_TLS -> properties.setProperty("mail.smtp.starttls.enable", "true") + else -> {} + } + properties["mail.smtp.timeout"] = "10000" + mailSender.javaMailProperties = properties + } + + fun sendSimpleMail(subject: String, text: String, html: Boolean = false, vararg to: String) { + val fromName = SettingsOperator.getMailValue(MailSettings::fromName) ?: throw NoEmailConfigException("fromName") + val from = SettingsOperator.getMailValue(MailSettings::from) ?: throw NoEmailConfigException("from") + + val mimeMessage = mailSender.createMimeMessage() + val messageHelper = MimeMessageHelper(mimeMessage, true) + messageHelper.apply { + setSubject(subject) + setFrom(from, fromName) + setSentDate(Date()) + setTo(to) + setText(text, html) + } + mailSender.send(mimeMessage) + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/util/NumberUtil.kt b/src/main/kotlin/top/fatweb/oxygen/api/util/NumberUtil.kt new file mode 100644 index 0000000..48db483 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/util/NumberUtil.kt @@ -0,0 +1,35 @@ +package top.fatweb.oxygen.api.util + +/** + * Number util + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +object NumberUtil { + /** + * Get random int value + * + * @param start Lower limit of random int value + * @param end Upper limit of random int value + * @return Random int value + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun getRandomInt(start: Int = Int.MIN_VALUE, end: Int = Int.MAX_VALUE): Int { + return (start..end).random() + } + + /** + * Get random long value + * + * @param start Lower limit of random long value + * @param end Upper limit of random long value + * @return Random long value + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun getRandomLong(start: Long = Long.MIN_VALUE, end: Long = Long.MAX_VALUE): Long { + return (start..end).random() + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/util/PageUtil.kt b/src/main/kotlin/top/fatweb/oxygen/api/util/PageUtil.kt new file mode 100644 index 0000000..4de5005 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/util/PageUtil.kt @@ -0,0 +1,42 @@ +package top.fatweb.oxygen.api.util + +import com.baomidou.mybatisplus.core.metadata.OrderItem +import com.baomidou.mybatisplus.extension.plugins.pagination.Page +import top.fatweb.oxygen.api.param.PageSortParam + +/** + * Page util + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +object PageUtil { + /** + * Set sort parameters into page object + * + * @param pageSortParam Sort parameters + * @param page Page object + * @param defaultOrder Default order by + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see Page + * @see PageSortParam + * @see OrderItem + */ + fun > setPageSort(pageSortParam: PageSortParam?, page: T, defaultOrder: OrderItem? = null) { + if (pageSortParam?.sortField != null || pageSortParam?.sortOrder != null) { + page.addOrder( + if (pageSortParam.sortOrder?.startsWith( + "desc", true + ) == true + ) OrderItem.desc(StrUtil.upperToUnderLetter(pageSortParam.sortField)) else OrderItem.asc( + StrUtil.upperToUnderLetter( + pageSortParam.sortField + ) + ) + ) + } else { + defaultOrder?.let { page.addOrder(defaultOrder) } + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/util/RedisUtil.kt b/src/main/kotlin/top/fatweb/oxygen/api/util/RedisUtil.kt new file mode 100644 index 0000000..67dd99e --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/util/RedisUtil.kt @@ -0,0 +1,230 @@ +package top.fatweb.oxygen.api.util + +import org.springframework.data.redis.core.BoundSetOperations +import org.springframework.data.redis.core.RedisTemplate +import org.springframework.stereotype.Component +import java.util.concurrent.TimeUnit + +/** + * Redis util + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Suppress("UNCHECKED_CAST") +@Component +class RedisUtil(private val redisTemplate: RedisTemplate) { + /** + * Set valid time + * + * @param key Cache key + * @param timeout Timeout + * @param timeUnit Unit of timeout + * @return true=Success;false=Fail + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see TimeUnit + */ + fun setExpire(key: String, timeout: Long, timeUnit: TimeUnit = TimeUnit.SECONDS): Boolean = + redisTemplate.expire(key, timeout, timeUnit) + + /** + * Get valid time + * + * @param key Cache key + * @param timeUnit Unit of time + * @return Valid time + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun getExpire(key: String, timeUnit: TimeUnit = TimeUnit.SECONDS): Long = redisTemplate.getExpire(key, timeUnit) + + /** + * Determine whether key exists + * + * @param key Cache key + * @return true=exist; false=not exist + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun hasKey(key: String): Boolean = redisTemplate.hasKey(key) + + /** + * Get list of cached key + * + * @param pattern Pattern of key + * @return List of key + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun keys(pattern: String): Set = redisTemplate.keys(pattern) + + /** + * Cache basic object + * + * @param key Cache key + * @param value Cache object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun setObject(key: String, value: Any) = redisTemplate.opsForValue().set(key, value) + + /** + * Cache basic object + * + * @param key Cache key + * @param value Cache object + * @param timeout Timeout + * @param timeUnit Unit of timeout + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun setObject(key: String, value: Any, timeout: Long, timeUnit: TimeUnit = TimeUnit.SECONDS) = + redisTemplate.opsForValue().set(key, value, timeout, timeUnit) + + + /** + * Get cached basic object + * + * @param key cache key + * @return Cached object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun getObject(key: String): T? = redisTemplate.opsForValue().get(key) as? T + + /** + * Delete cached object + * + * @param key Cache key + * @return true=success; false=fail + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun delObject(key: String): Boolean = redisTemplate.delete(key) + + /** + * Delete list of cached objects + * + * @param collection List of cache key + * @return Number of deleted objects + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun delObject(collection: Collection): Long = redisTemplate.delete(collection) + + /** + * Cache list of objects + * + * @param key Cache key + * @param dataList List of objects + * @return Number of cached objects + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun setList(key: String, dataList: List): Long? = redisTemplate.opsForList().rightPushAll(key, dataList) + + /** + * Get cached list of objects + * + * @param key Cache key + * @return List of cached objects + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun getList(key: String): List? = redisTemplate.opsForList().range(key, 0, -1) as? List + + /** + * Cache set of objects + * + * @param key Cache key + * @param dataSet Set of objects + * @return Bound set operations + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun setSet(key: String, dataSet: Set): BoundSetOperations { + val boundSetOps: BoundSetOperations = redisTemplate.boundSetOps(key) + for (data in dataSet) { + boundSetOps.add(data) + } + return boundSetOps + } + + /** + * Get set of cached objects + * + * @param key Cache key + * @return Set of cached object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun getSet(key: String): Set? = redisTemplate.opsForSet().members(key) as? Set + + /** + * Cache map of objects + * + * @param key Cache key + * @param dataMap Map of objects + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun setMap(key: String, dataMap: Map) = redisTemplate.opsForHash().putAll(key, dataMap) + + /** + * Get cached map of objects + * + * @param key Cache key + * @return Map of cached objects + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun getMap(key: String): Map? = + redisTemplate.opsForHash().entries(key) as? Map + + /** + * Set value into cached map + * + * @param key Cache key + * @param hKey Map key + * @param value Value in map + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun setMapValue(key: String, hKey: String, value: Any) = + redisTemplate.opsForHash().put(key, hKey, value) + + /** + * Get value in cached map + * + * @param key Cache key + * @param hKey Map key + * @return Value in map + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun getMapValue(key: String, hKey: String) = redisTemplate.opsForHash().get(key, hKey) + + /** + * Delete value in cached map + * + * @param key Cache key + * @param hKey Map key + * @return Number of deleted value + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun delMapValue(key: String, hKey: String): Long = redisTemplate.opsForHash().delete(key, hKey) + + /** + * Get multiple value in cached map + * + * @param key Cache key + * @param hKeys List of map key + * @return HashMap object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun getMultiMapValue(key: String, hKeys: Collection): List = + redisTemplate.opsForHash().multiGet(key, hKeys) +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/util/StrUtil.kt b/src/main/kotlin/top/fatweb/oxygen/api/util/StrUtil.kt new file mode 100644 index 0000000..c237ee0 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/util/StrUtil.kt @@ -0,0 +1,80 @@ +package top.fatweb.oxygen.api.util + +import java.security.MessageDigest + +/** + * String util + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +object StrUtil { + + /** + * Convert CamelCase string to underscore-delimited string + * + * @param str CamelCase string + * @return Underscore-delimited string + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun upperToUnderLetter(str: String?): String { + str ?: return "" + + return Regex("[A-Z]").replace(str) { matchResult -> "_${matchResult.value.lowercase()}" } + } + + /** + * Convert underscore-delimited string to CamelCase string + * + * @param str Underscore-delimited string + * @return CamelCase string + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun underToUpperLetter(str: String?): String { + str ?: return "" + + return Regex("_[a-z]").replace(str) { matchResult -> matchResult.value.removePrefix("_").uppercase() } + } + + /** + * Get random password + * + * @param length Length of password + * @return Random password + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun getRandomPassword(length: Int): String { + val characterSet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + val password = StringBuilder() + + for (i in 0 until length) { + password.append(characterSet.random()) + } + + return password.toString() + } + + /** + * Get MD5 of a string + * + * @param content Content + * @return MD5 of content + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun md5(content: String): String { + val hash = MessageDigest.getInstance("MD5").digest(content.toByteArray()) + val hex = StringBuilder(hash.size * 2) + for (b in hash) { + var str = Integer.toHexString(b.toInt()) + if (b < 0x10) { + str = "0$str" + } + hex.append(str.substring(str.length - 2)) + } + return hex.toString() + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/util/WebUtil.kt b/src/main/kotlin/top/fatweb/oxygen/api/util/WebUtil.kt new file mode 100644 index 0000000..4e0838c --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/util/WebUtil.kt @@ -0,0 +1,79 @@ +package top.fatweb.oxygen.api.util + +import jakarta.servlet.http.HttpServletRequest +import org.springframework.security.core.context.SecurityContextHolder +import top.fatweb.oxygen.api.entity.permission.LoginUser +import top.fatweb.oxygen.api.properties.SecurityProperties + +/** + * Web util + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +object WebUtil { + /** + * Get the user currently calling api + * + * @return LoginUser object + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LoginUser + */ + fun getLoginUser(): LoginUser? = if (SecurityContextHolder.getContext().authentication.principal is String) null + else SecurityContextHolder.getContext().authentication.principal as LoginUser + + /** + * Get ID of the user currently calling api + * + * @return User ID + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun getLoginUserId(): Long? = getLoginUser()?.user?.id + + /** + * Get username of the user currently calling api + * + * @return Username + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun getLoginUsername(): String? = getLoginUser()?.user?.username + + /** + * Get token of the user currently calling api + * + * @return Token + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun getToken(tokenWithPrefix: String): String = tokenWithPrefix.removePrefix(SecurityProperties.tokenPrefix) + + /** + * Get token of the user currently calling api + * + * @return Token + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + fun getToken(request: HttpServletRequest): String = getToken(request.getHeader(SecurityProperties.headerKey)) + + /** + * Offline user + * + * @param redisUtil RedisUtil object + * @param userIds List of user IDs + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RedisUtil + */ + fun offlineUser(redisUtil: RedisUtil, vararg userIds: Long) { + val keys = HashSet() + userIds.forEach { + keys.addAll(redisUtil.keys("${SecurityProperties.jwtIssuer}_login_${it}:*")) + } + + redisUtil.delObject(keys) + } +} \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/PageVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/PageVo.kt new file mode 100644 index 0000000..3990b58 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/PageVo.kt @@ -0,0 +1,57 @@ +package top.fatweb.oxygen.api.vo + +import io.swagger.v3.oas.annotations.media.Schema + +/** + * Page value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "分页返回参数") +data class PageVo( + /** + * Total number of records + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "总数量", example = "100") + val total: Long, + + /** + * Total number of pages + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "总页码", example = "10") + val pages: Long, + + /** + * Size of page + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "分页大小", example = "10") + val size: Long, + + /** + * Current page number + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "当前页码", example = "2") + val current: Long, + + /** + * Records in current page + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "数据") + val records: List +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/api/v1/avatar/AvatarBase64Vo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/api/v1/avatar/AvatarBase64Vo.kt new file mode 100644 index 0000000..34bb7bd --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/api/v1/avatar/AvatarBase64Vo.kt @@ -0,0 +1,21 @@ +package top.fatweb.oxygen.api.vo.api.v1.avatar + +import io.swagger.v3.oas.annotations.media.Schema + +/** + * Avatar base64 value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "头像 Base64 返回参数") +data class AvatarBase64Vo( + /** + * Base64 + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "base64") + val base64: String? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/GroupWithRoleVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/GroupWithRoleVo.kt new file mode 100644 index 0000000..7d5c28b --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/GroupWithRoleVo.kt @@ -0,0 +1,72 @@ +package top.fatweb.oxygen.api.vo.permission + +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer +import io.swagger.v3.oas.annotations.media.Schema +import top.fatweb.oxygen.api.vo.permission.base.RoleVo +import java.time.LocalDateTime + +/** + * Group with role value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +data class GroupWithRoleVo( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @JsonSerialize(using = ToStringSerializer::class) + val id: Long?, + + /** + * Name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "用户组名", example = "Role") + val name: String?, + + /** + * Enable + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "启用", example = "true") + val enable: Boolean?, + + /** + * Create time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "创建时间", example = "1900-01-01T00:00:00.000Z") + val createTime: LocalDateTime?, + + /** + * Update time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "修改时间", example = "1900-01-01T00:00:00.000Z") + val updateTime: LocalDateTime?, + + /** + * List of RoleVo object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RoleVo + */ + @Schema(description = "角色列表") + val roles: List? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/LoginVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/LoginVo.kt new file mode 100644 index 0000000..b49a3fd --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/LoginVo.kt @@ -0,0 +1,62 @@ +package top.fatweb.oxygen.api.vo.permission + +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer +import io.swagger.v3.oas.annotations.media.Schema +import java.time.LocalDateTime + +/** + * Login value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "登录返回参数") +data class LoginVo( + /** + * Token + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema( + description = "Token", + example = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkYTllYjFkYmVmZDQ0OWRkOThlOGNjNzZlNzZkMDgyNSIsInN1YiI6IjE3MDk5ODYwNTg2Nzk5NzU5MzgiLCJpc3MiOiJGYXRXZWIiLCJpYXQiOjE2OTY1MjgxMTcsImV4cCI6MTY5NjUzNTMxN30.U2ZsyrGk7NbsP-DJfdz9xgWSfect5r2iKQnlEsscAA8" + ) val token: String, + + /** + * User ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema( + description = "User ID", + example = "1709986058679975938" + ) + @JsonSerialize(using = ToStringSerializer::class) + val userId: Long?, + + /** + * Last login time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema( + description = "上次登录时间", + example = "1900-01-01 00:00:00" + ) val lastLoginTime: LocalDateTime?, + + /** + * Last login IP + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema( + description = "上次登录 IP", + example = "10.0.0.1" + ) val lastLoginIp: String? +) \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/PowerSetVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/PowerSetVo.kt new file mode 100644 index 0000000..b3be209 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/PowerSetVo.kt @@ -0,0 +1,56 @@ +package top.fatweb.oxygen.api.vo.permission + +import io.swagger.v3.oas.annotations.media.Schema +import top.fatweb.oxygen.api.vo.permission.base.FuncVo +import top.fatweb.oxygen.api.vo.permission.base.MenuVo +import top.fatweb.oxygen.api.vo.permission.base.ModuleVo +import top.fatweb.oxygen.api.vo.permission.base.OperationVo + +/** + * Set of power value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "权限集合返回参数") +data class PowerSetVo( + /** + * List of ModuleVo object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ModuleVo + */ + @Schema(description = "模块列表") + val moduleList: List?, + + /** + * List of MenuVo object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see MenuVo + */ + @Schema(description = "菜单列表") + val menuList: List?, + + /** + * List of FuncVo object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see FuncVo + */ + @Schema(description = "功能列表") + val funcList: List?, + + /** + * List of OperationVo object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see OperationVo + */ + @Schema(description = "操作列表") + val operationList: List? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/RegisterVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/RegisterVo.kt new file mode 100644 index 0000000..b15ca14 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/RegisterVo.kt @@ -0,0 +1,35 @@ +package top.fatweb.oxygen.api.vo.permission + +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer +import io.swagger.v3.oas.annotations.media.Schema + +/** + * Register value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "注册返回参数") +data class RegisterVo( + /** + * Token + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema( + description = "Token", + example = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkYTllYjFkYmVmZDQ0OWRkOThlOGNjNzZlNzZkMDgyNSIsInN1YiI6IjE3MDk5ODYwNTg2Nzk5NzU5MzgiLCJpc3MiOiJGYXRXZWIiLCJpYXQiOjE2OTY1MjgxMTcsImV4cCI6MTY5NjUzNTMxN30.U2ZsyrGk7NbsP-DJfdz9xgWSfect5r2iKQnlEsscAA8" + ) val token: String, + + /** + * User ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "User ID", example = "1709986058679975938") + @JsonSerialize(using = ToStringSerializer::class) + val userId: Long? +) \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/RoleWithPowerVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/RoleWithPowerVo.kt new file mode 100644 index 0000000..d86b0cb --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/RoleWithPowerVo.kt @@ -0,0 +1,106 @@ +package top.fatweb.oxygen.api.vo.permission + +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer +import io.swagger.v3.oas.annotations.media.Schema +import top.fatweb.oxygen.api.vo.permission.base.FuncVo +import top.fatweb.oxygen.api.vo.permission.base.MenuVo +import top.fatweb.oxygen.api.vo.permission.base.ModuleVo +import top.fatweb.oxygen.api.vo.permission.base.OperationVo +import java.time.LocalDateTime + +/** + * Role with power value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "角色返回参数") +data class RoleWithPowerVo( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @JsonSerialize(using = ToStringSerializer::class) + val id: Long?, + + /** + * Name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "角色名", example = "Role") + val name: String?, + + /** + * Enable + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "启用", example = "true") + val enable: Boolean?, + + /** + * Create time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "创建时间", example = "1900-01-01T00:00:00.000Z") + val createTime: LocalDateTime?, + + /** + * Update time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "修改时间", example = "1900-01-01T00:00:00.000Z") + val updateTime: LocalDateTime?, + + /** + * List of ModuleVo object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ModuleVo + */ + @Schema(description = "模块列表") + val modules: List?, + + /** + * List of MenuVo object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see MenuVo + */ + @Schema(description = "菜单列表") + val menus: List?, + + /** + * List of FuncVo object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see FuncVo + */ + @Schema(description = "功能列表") + val funcs: List?, + + /** + * List of OperationVo object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see OperationVo + */ + @Schema(description = "操作列表") + val operations: List? +) diff --git a/src/main/kotlin/top/fatweb/api/vo/TokenVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/TokenVo.kt similarity index 58% rename from src/main/kotlin/top/fatweb/api/vo/TokenVo.kt rename to src/main/kotlin/top/fatweb/oxygen/api/vo/permission/TokenVo.kt index c17ea01..669ea6e 100644 --- a/src/main/kotlin/top/fatweb/api/vo/TokenVo.kt +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/TokenVo.kt @@ -1,9 +1,21 @@ -package top.fatweb.api.vo +package top.fatweb.oxygen.api.vo.permission import io.swagger.v3.oas.annotations.media.Schema -@Schema(description = "Token") +/** + * Token value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "Token 返回参数") data class TokenVo( + /** + * Token + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ @Schema( description = "Token", example = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiJkYTllYjFkYmVmZDQ0OWRkOThlOGNjNzZlNzZkMDgyNSIsInN1YiI6IjE3MDk5ODYwNTg2Nzk5NzU5MzgiLCJpc3MiOiJGYXRXZWIiLCJpYXQiOjE2OTY1MjgxMTcsImV4cCI6MTY5NjUzNTMxN30.U2ZsyrGk7NbsP-DJfdz9xgWSfect5r2iKQnlEsscAA8" diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/UserWithInfoVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/UserWithInfoVo.kt new file mode 100644 index 0000000..f1f14f7 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/UserWithInfoVo.kt @@ -0,0 +1,149 @@ +package top.fatweb.oxygen.api.vo.permission + +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer +import io.swagger.v3.oas.annotations.media.Schema +import top.fatweb.oxygen.api.vo.permission.base.UserInfoVo +import java.time.LocalDateTime + +/** + * User with information value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "用户信息返回参数") +data class UserWithInfoVo( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @JsonSerialize(using = ToStringSerializer::class) + val id: Long?, + + /** + * Username + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "用户名", example = "User") + val username: String?, + + /** + * Verified + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "已验证", example = "true") + val verified: Boolean?, + + /** + * Locking + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "是否锁定", example = "false") + val locking: Boolean?, + + /** + * Expiration time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "过期时间", example = "1900-01-01T00:00:00.000Z") + val expiration: LocalDateTime?, + + /** + * Credentials expiration time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "认证过期时间", example = "1900-01-01T00:00:00.000Z") + val credentialsExpiration: LocalDateTime?, + + /** + * Enable + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "是否启用", example = "true") + val enable: Boolean?, + + /** + * Current login time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "当前登录时间", example = "1900-01-01T00:00:00.000Z") + val currentLoginTime: LocalDateTime?, + + /** + * Current login IP + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "当前登录 IP", example = "1.1.1.1") + val currentLoginIp: String?, + + /** + * Last login time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "最后登录时间", example = "1900-01-01T00:00:00.000Z") + val lastLoginTime: LocalDateTime?, + + /** + * Last login IP + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "最后登录 IP", example = "1.1.1.1") + val lastLoginIp: String?, + + /** + * Create time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "创建时间", example = "1900-01-01T00:00:00.000Z") + val createTime: LocalDateTime?, + + /** + * Update time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "修改时间", example = "1900-01-01T00:00:00.000Z") + val updateTime: LocalDateTime?, + + /** + * User information object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see UserInfoVo + */ + @Schema(description = "用户资料") + val userInfo: UserInfoVo? +) \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/UserWithPasswordRoleInfoVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/UserWithPasswordRoleInfoVo.kt new file mode 100644 index 0000000..945bbdd --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/UserWithPasswordRoleInfoVo.kt @@ -0,0 +1,180 @@ +package top.fatweb.oxygen.api.vo.permission + +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer +import io.swagger.v3.oas.annotations.media.Schema +import top.fatweb.oxygen.api.vo.permission.base.GroupVo +import top.fatweb.oxygen.api.vo.permission.base.RoleVo +import top.fatweb.oxygen.api.vo.permission.base.UserInfoVo +import java.time.LocalDateTime + +/** + * User with password role information value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "用户密码角色信息返回参数") +data class UserWithPasswordRoleInfoVo( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @JsonSerialize(using = ToStringSerializer::class) + val id: Long?, + + /** + * Username + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "用户名", example = "User") + val username: String?, + + /** + * Password + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "密码") + val password: String?, + + /** + * Verify + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "验证信息") + val verify: String?, + + /** + * Locking + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "是否锁定", example = "false") + val locking: Boolean?, + + /** + * Expiration time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "过期时间", example = "1900-01-01T00:00:00.000Z") + val expiration: LocalDateTime?, + + /** + * Credentials expiration time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "认证过期时间", example = "1900-01-01T00:00:00.000Z") + val credentialsExpiration: LocalDateTime?, + + /** + * Enable + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "是否启用", example = "true") + val enable: Boolean?, + + /** + * Current login time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "当前登录时间", example = "1900-01-01T00:00:00.000Z") + val currentLoginTime: LocalDateTime?, + + /** + * Current login IP + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "当前登录 IP", example = "1.1.1.1") + val currentLoginIp: String?, + + /** + * Last login time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "最后登录时间", example = "1900-01-01T00:00:00.000Z") + val lastLoginTime: LocalDateTime?, + + /** + * Last login IP + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "最后登录 IP", example = "1.1.1.1") + val lastLoginIp: String?, + + /** + * Create time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "创建时间", example = "1900-01-01T00:00:00.000Z") + val createTime: LocalDateTime?, + + /** + * Update time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "修改时间", example = "1900-01-01T00:00:00.000Z") + val updateTime: LocalDateTime?, + + /** + * User information object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see UserInfoVo + */ + @Schema(description = "用户资料") + val userInfo: UserInfoVo?, + + /** + * List of RoleVo object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RoleVo + */ + @Schema(description = "角色列表") + val roles: List?, + + /** + * List of GroupVo object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see GroupVo + */ + @Schema(description = "用户组列表") + val groups: List? +) \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/UserWithPowerInfoVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/UserWithPowerInfoVo.kt new file mode 100644 index 0000000..4616b50 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/UserWithPowerInfoVo.kt @@ -0,0 +1,186 @@ +package top.fatweb.oxygen.api.vo.permission + +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer +import io.swagger.v3.oas.annotations.media.Schema +import top.fatweb.oxygen.api.vo.permission.base.* +import java.time.LocalDateTime + +/** + * User with power information value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "用户权限信息返回参数") +data class UserWithPowerInfoVo( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @JsonSerialize(using = ToStringSerializer::class) + val id: Long?, + + /** + * Username + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "用户名", example = "User") + val username: String?, + + /** + * Verified + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "已验证", example = "true") + val verified: Boolean?, + + /** + * Locking + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "是否锁定", example = "false") + val locking: Boolean?, + + /** + * Expiration time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "过期时间", example = "1900-01-01T00:00:00.000Z") + val expiration: LocalDateTime?, + + /** + * Credentials expiration time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "认证过期时间", example = "1900-01-01T00:00:00.000Z") + val credentialsExpiration: LocalDateTime?, + + /** + * Enable + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "是否启用", example = "true") + val enable: Boolean?, + + /** + * Current login time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "当前登录时间", example = "1900-01-01T00:00:00.000Z") + val currentLoginTime: LocalDateTime?, + + /** + * Last login time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "当前登录 IP", example = "1.1.1.1") + val currentLoginIp: String?, + + /** + * Last login time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "最后登录时间", example = "1900-01-01T00:00:00.000Z") + val lastLoginTime: LocalDateTime?, + + /** + * Last login IP + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "最后登录 IP", example = "1.1.1.1") + val lastLoginIp: String?, + + /** + * Create time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "创建时间", example = "1900-01-01T00:00:00.000Z") + val createTime: LocalDateTime?, + + /** + * Update time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "修改时间", example = "1900-01-01T00:00:00.000Z") + val updateTime: LocalDateTime?, + + /** + * User information object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see UserInfoVo + */ + @Schema(description = "用户资料") + val userInfo: UserInfoVo?, + + /** + * List of ModuleVo object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "模块列表") + val modules: List?, + + /** + * List of MenuVo object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "菜单列表") + val menus: List?, + + /** + * List of FuncVo object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "功能列表") + val funcs: List?, + + /** + * List of OperationVo object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "操作列表") + val operations: List? +) \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/UserWithRoleInfoVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/UserWithRoleInfoVo.kt new file mode 100644 index 0000000..edc69db --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/UserWithRoleInfoVo.kt @@ -0,0 +1,173 @@ +package top.fatweb.oxygen.api.vo.permission + +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer +import io.swagger.v3.oas.annotations.media.Schema +import top.fatweb.oxygen.api.vo.permission.base.GroupVo +import top.fatweb.oxygen.api.vo.permission.base.RoleVo +import top.fatweb.oxygen.api.vo.permission.base.UserInfoVo +import java.time.LocalDateTime + +/** + * User with role information value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "用户角色信息返回参数") +data class UserWithRoleInfoVo( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @JsonSerialize(using = ToStringSerializer::class) + val id: Long?, + + /** + * Username + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "用户名", example = "User") + val username: String?, + + /** + * Verify + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "验证信息") + val verify: String?, + + /** + * Locking + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "是否锁定", example = "false") + val locking: Boolean?, + + /** + * Expiration time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "过期时间", example = "1900-01-01T00:00:00.000Z") + val expiration: LocalDateTime?, + + /** + * Credentials expiration time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "认证过期时间", example = "1900-01-01T00:00:00.000Z") + val credentialsExpiration: LocalDateTime?, + + /** + * Current login time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "是否启用", example = "true") + val enable: Boolean?, + + /** + * Current login time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "当前登录时间", example = "1900-01-01T00:00:00.000Z") + val currentLoginTime: LocalDateTime?, + + /** + * Last login time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "当前登录 IP", example = "1.1.1.1") + val currentLoginIp: String?, + + /** + * Last login time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "最后登录时间", example = "1900-01-01T00:00:00.000Z") + val lastLoginTime: LocalDateTime?, + + /** + * Last login IP + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "最后登录 IP", example = "1.1.1.1") + val lastLoginIp: String?, + + /** + * Create time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "创建时间", example = "1900-01-01T00:00:00.000Z") + val createTime: LocalDateTime?, + + /** + * User information object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see UserInfoVo + */ + @Schema(description = "修改时间", example = "1900-01-01T00:00:00.000Z") + val updateTime: LocalDateTime?, + + /** + * User information object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see UserInfoVo + */ + @Schema(description = "用户资料") + val userInfo: UserInfoVo?, + + /** + * List of RoleVo object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see RoleVo + */ + @Schema(description = "角色列表") + val roles: List?, + + /** + * List of GroupVo object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see GroupVo + */ + @Schema(description = "用户组列表") + val groups: List? +) \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/base/FuncVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/base/FuncVo.kt new file mode 100644 index 0000000..656723f --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/base/FuncVo.kt @@ -0,0 +1,47 @@ +package top.fatweb.oxygen.api.vo.permission.base + +import io.swagger.v3.oas.annotations.media.Schema + +/** + * Function value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "功能返回参数") +data class FuncVo( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + val id: Long?, + + /** + * Name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "功能名", example = "AddButton") + val name: String?, + + /** + * Parent ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "父 ID") + val parentId: Long?, + + /** + * Menu ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "菜单 ID") + val menuId: Long? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/base/GroupVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/base/GroupVo.kt new file mode 100644 index 0000000..2e3da98 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/base/GroupVo.kt @@ -0,0 +1,62 @@ +package top.fatweb.oxygen.api.vo.permission.base + +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer +import io.swagger.v3.oas.annotations.media.Schema +import java.time.LocalDateTime + +/** + * Group value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "用户组返回参数") +data class GroupVo( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @JsonSerialize(using = ToStringSerializer::class) + val id: Long?, + + /** + * Name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "用户组名", example = "Group") + val name: String?, + + /** + * Enable + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "启用", example = "true") + val enable: Boolean?, + + /** + * Create time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "创建时间", example = "1900-01-01T00:00:00.000Z") + val createTime: LocalDateTime?, + + /** + * Update time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "修改时间", example = "1900-01-01T00:00:00.000Z") + val updateTime: LocalDateTime? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/base/MenuVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/base/MenuVo.kt new file mode 100644 index 0000000..78b26bc --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/base/MenuVo.kt @@ -0,0 +1,56 @@ +package top.fatweb.oxygen.api.vo.permission.base + +import io.swagger.v3.oas.annotations.media.Schema + +/** + * Menu value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "菜单返回参数") +data class MenuVo( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + val id: Long?, + + /** + * Name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "菜单名", example = "System") + val name: String?, + + /** + * URL + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "URL", example = "/system") + val url: String?, + + /** + * Parent ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "父 ID") + val parentId: Long?, + + /** + * Module ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "模块 ID") + val moduleId: Long? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/base/ModuleVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/base/ModuleVo.kt new file mode 100644 index 0000000..2bb4af0 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/base/ModuleVo.kt @@ -0,0 +1,29 @@ +package top.fatweb.oxygen.api.vo.permission.base + +import io.swagger.v3.oas.annotations.media.Schema + +/** + * Module value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "模块返回参数") +data class ModuleVo( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + val id: Long?, + + /** + * Name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "模块名", example = "系统") + val name: String? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/base/OperationVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/base/OperationVo.kt new file mode 100644 index 0000000..cb28ebb --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/base/OperationVo.kt @@ -0,0 +1,47 @@ +package top.fatweb.oxygen.api.vo.permission.base + +import io.swagger.v3.oas.annotations.media.Schema + +/** + * Operation value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "操作返回参数") +data class OperationVo( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + val id: Long?, + + /** + * Name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "操作名", example = "Add User") + val name: String?, + + /** + * Code + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "操作编码", example = "system:user:add") + val code: String?, + + /** + * Function ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "功能 ID") + val funcId: Long? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/base/RoleVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/base/RoleVo.kt new file mode 100644 index 0000000..2bcd01d --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/base/RoleVo.kt @@ -0,0 +1,62 @@ +package top.fatweb.oxygen.api.vo.permission.base + +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer +import io.swagger.v3.oas.annotations.media.Schema +import java.time.LocalDateTime + +/** + * Role value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "角色返回参数") +data class RoleVo( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @JsonSerialize(using = ToStringSerializer::class) + val id: Long?, + + /** + * Name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "角色名", example = "Role") + val name: String?, + + /** + * Enable + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "启用", example = "true") + val enable: Boolean?, + + /** + * Create time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "创建时间", example = "1900-01-01T00:00:00.000Z") + val createTime: LocalDateTime?, + + /** + * Update time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "修改时间", example = "1900-01-01T00:00:00.000Z") + val updateTime: LocalDateTime? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/base/UserInfoVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/base/UserInfoVo.kt new file mode 100644 index 0000000..a6edbb8 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/permission/base/UserInfoVo.kt @@ -0,0 +1,81 @@ +package top.fatweb.oxygen.api.vo.permission.base + +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer +import io.swagger.v3.oas.annotations.media.Schema +import java.time.LocalDateTime + +/** + * User information value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "用户资料返回参数") +data class UserInfoVo( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @JsonSerialize(using = ToStringSerializer::class) + val id: Long?, + + /** + * User ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "用户ID") + @JsonSerialize(using = ToStringSerializer::class) + val userId: Long?, + + /** + * Nickname + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "昵称", example = "User") + val nickname: String?, + + /** + * Avatar base64 + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "头像") + val avatar: String?, + + /** + * Email + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "邮箱", example = "user@mail.com") + val email: String?, + + /** + * Create time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "创建时间", example = "1900-01-01T00:00:00.000Z") + val createTime: LocalDateTime?, + + /** + * Update time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "修改时间", example = "1900-01-01T00:00:00.000Z") + val updateTime: LocalDateTime? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/system/ActiveInfoVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/system/ActiveInfoVo.kt new file mode 100644 index 0000000..1394ced --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/system/ActiveInfoVo.kt @@ -0,0 +1,63 @@ +package top.fatweb.oxygen.api.vo.system + +import io.swagger.v3.oas.annotations.media.Schema +import top.fatweb.oxygen.api.vo.system.ActiveInfoVo.HistoryVo +import java.time.LocalDate + +/** + * Active information value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "用户活跃信息返回参数") +data class ActiveInfoVo( + /** + * Register user number history + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "注册用户数量历史") + val registerHistory: List, + + /** + * Login user number history + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see HistoryVo + */ + @Schema(description = "登录用户数量历史") + val loginHistory: List, + + /** + * Verify user number history + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "验证用户数量历史") + val verifyHistory: List +) { + data class HistoryVo( + /** + * Time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDate + */ + @Schema(description = "记录时间", example = "1900-01-01") + val time: LocalDate, + + /** + * Count + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "数量") + val count: Int + ) +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/system/BaseSettingsVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/system/BaseSettingsVo.kt new file mode 100644 index 0000000..1d70fd0 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/system/BaseSettingsVo.kt @@ -0,0 +1,48 @@ +package top.fatweb.oxygen.api.vo.system + +import io.swagger.v3.oas.annotations.media.Schema + +/** + * Base settings value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "基础设置返回参数") +data class BaseSettingsVo( + /** + * Application name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "应用名称") + val appName: String?, + + /** + * Application URL + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "应用 URL") + val appUrl: String?, + + /** + * Verify URL + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "验证邮箱 URL") + val verifyUrl: String?, + + /** + * Retrieve URL + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "找回密码 URL") + val retrieveUrl: String? +) \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/system/CpuInfoVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/system/CpuInfoVo.kt new file mode 100644 index 0000000..17e843a --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/system/CpuInfoVo.kt @@ -0,0 +1,124 @@ +package top.fatweb.oxygen.api.vo.system + +import com.fasterxml.jackson.annotation.JsonInclude +import io.swagger.v3.oas.annotations.media.Schema + +/** + * CPU information value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "CPU 信息返回参数") +@JsonInclude(JsonInclude.Include.NON_EMPTY) +data class CpuInfoVo( + /** + * Show the percentage of CPU utilization + * that occurred while executing at the user + * level (application). + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "user") + val user: Long, + + /** + * Show the percentage of CPU utilization + * that occurred while executing at the user + * level with nice priority. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "nice") + val nice: Long, + + /** + * Show the percentage of CPU utilization that + * occurred while executing at the system level + * (kernel). Note that this does not include time + * spent servicing hardware and software + * interrupts. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "system") + val system: Long, + + /** + * Show the percentage of time that the + * CPU or CPUs were idle and the system did + * not have an outstanding disk I/O request. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "idle") + val idle: Long, + + /** + * Show the percentage of time that the + * CPU or CPUs were idle during which the + * system had an outstanding disk I/O + * request. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "iowait") + val iowait: Long, + + /** + * Show the percentage of time spent by + * the CPU or CPUs to service hardware + * interrupts. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "irq") + val irq: Long, + + /** + * Show the percentage of time spent by + * the CPU or CPUs to service software + * interrupts. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "softirq") + val softirq: Long, + + /** + * Show the percentage of time spent in + * involuntary wait by the virtual CPU or CPUs + * while the hypervisor was servicing another + * virtual processor. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "steal") + val steal: Long, + + /** + * total = user + nice + system + idle + iowait + irq + softirq + steal + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "total") + val total: Long, + + /** + * List of CPU processors information + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "处理器列表") + val processors: List? = null +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/system/FileStoreInfoVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/system/FileStoreInfoVo.kt new file mode 100644 index 0000000..e98b4c1 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/system/FileStoreInfoVo.kt @@ -0,0 +1,43 @@ +package top.fatweb.oxygen.api.vo.system + +import io.swagger.v3.oas.annotations.media.Schema + +/** + * File storage information value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "文件存储信息返回参数") +data class FileStoreInfoVo( + /** + * Mount point of the File System. The + * directory users will normally use to + * interface with the file store. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "挂载点") + val mount: String, + + /** + * Total space/capacity of the drive. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "总容量") + val total: Long, + + /** + * Free space on the drive. This space is + * unallocated but may require elevated + * permissions to write. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "空闲容量") + val free: Long +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/system/HardwareInfoVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/system/HardwareInfoVo.kt new file mode 100644 index 0000000..8f1e6a8 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/system/HardwareInfoVo.kt @@ -0,0 +1,104 @@ +package top.fatweb.oxygen.api.vo.system + +import io.swagger.v3.oas.annotations.media.Schema + +/** + * Hardware information value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "硬件信息返回参数") +data class HardwareInfoVo( + /** + * Name of CPU + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "CPU") + val cpu: String, + + /** + * Arch of CPU + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "架构") + val arch: String, + + /** + * Is CPU 64bit + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "是否为64位") + val is64Bit: Boolean, + + /** + * Number of packages/sockets in the system. A + * single package may contain multiple cores. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "物理 CPU") + val cpuPhysicalPackageCount: Int, + + /** + * Number of physical CPUs/cores available for + * processing. + * + * On some operating systems with variable numbers + * of physical processors available to the OS, may + * return a max value. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "物理核心") + val cpuPhysicalProcessorCount: Int, + + /** + * Number of logical CPUs available for processing. + * This value may be higher than physical CPUs if + * hyperthreading is enabled. + * + * On some operating systems with variable numbers + * of logical processors, may return a max value. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "逻辑核心") + val cpuLogicalProcessorCount: Int, + + /** + * Processor's microarchitecture, if known. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "微架构") + val microarchitecture: String, + + /** + * Memory information overview + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "内存") + val memories: String, + + /** + * Disk information overview + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "存储") + val disks: String +) \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/system/MailSettingsVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/system/MailSettingsVo.kt new file mode 100644 index 0000000..cf14853 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/system/MailSettingsVo.kt @@ -0,0 +1,76 @@ +package top.fatweb.oxygen.api.vo.system + +import io.swagger.v3.oas.annotations.media.Schema +import top.fatweb.oxygen.api.settings.MailSecurityType + +/** + * Mail settings value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "邮件设置返回参数") +data class MailSettingsVo( + /** + * Host + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "SMTP 服务器") + val host: String?, + + /** + * Port + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "端口") + val port: Int?, + + /** + * Security type + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "安全类型") + val securityType: MailSecurityType?, + + /** + * Username + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "用户名") + val username: String?, + + /** + * Password + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "密码") + val password: String?, + + /** + * Sender + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "发送者") + val from: String?, + + /** + * Sender name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "发送者名称") + val fromName: String? +) \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/system/OnlineInfoVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/system/OnlineInfoVo.kt new file mode 100644 index 0000000..4e76b70 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/system/OnlineInfoVo.kt @@ -0,0 +1,54 @@ +package top.fatweb.oxygen.api.vo.system + +import io.swagger.v3.oas.annotations.media.Schema +import top.fatweb.oxygen.api.vo.system.OnlineInfoVo.HistoryVo +import java.time.LocalDateTime + +/** + * Online information value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "在线信息返回参数") +data class OnlineInfoVo( + /** + * Number of user currently online + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "当前在线用户数量") + val current: Long, + + /** + * Online number history + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see HistoryVo + */ + @Schema(description = "历史记录") + val history: List +) { + data class HistoryVo( + /** + * Time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "记录时间") + val time: LocalDateTime, + + /** + * Record + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "记录") + val record: String + ) +} diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/system/SensitiveWordVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/system/SensitiveWordVo.kt new file mode 100644 index 0000000..926e4e1 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/system/SensitiveWordVo.kt @@ -0,0 +1,52 @@ +package top.fatweb.oxygen.api.vo.system + +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer +import io.swagger.v3.oas.annotations.media.Schema +import top.fatweb.oxygen.api.entity.system.SensitiveWord + +/** + * Sensitive word settings value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(defaultValue = "敏感词设置返回参数") +data class SensitiveWordVo( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @JsonSerialize(using = ToStringSerializer::class) + val id: Long?, + + /** + * Word + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "词") + val word: String?, + + /** + * Use for + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see SensitiveWord.Use + */ + @Schema(description = "用于") + val useFor: Set?, + + /** + * Enable + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "启用") + val enable: Boolean +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/system/SettingsVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/system/SettingsVo.kt new file mode 100644 index 0000000..7555b6b --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/system/SettingsVo.kt @@ -0,0 +1,23 @@ +package top.fatweb.oxygen.api.vo.system + +import io.swagger.v3.oas.annotations.media.Schema + +/** + * System settings value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + +@Schema(description = "系统设置返回参数") +data class SettingsVo( + /** + * MailSettingVo object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see MailSettingsVo + */ + @Schema(description = "邮件设置") + val mail: MailSettingsVo? +) \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/system/SoftwareInfoVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/system/SoftwareInfoVo.kt new file mode 100644 index 0000000..6a96097 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/system/SoftwareInfoVo.kt @@ -0,0 +1,139 @@ +package top.fatweb.oxygen.api.vo.system + +import io.swagger.v3.oas.annotations.media.Schema +import java.time.LocalDateTime + +/** + * Software information value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "软甲信息返回参数") +data class SoftwareInfoVo( + /** + * Operating system + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "操作系统") + val os: String, + + /** + * Bitness (32 or 64) of the operating system. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "位数") + val bitness: Int, + + /** + * Version of Java + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "Java 版本") + val javaVersion: String, + + /** + * Version date of Java + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "Java 版本日期") + val javaVersionDate: String, + + /** + * Vendor of Java + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "Java 供应商") + val javaVendor: String, + + /** + * Name of Java runtime + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "Java 运行时") + val javaRuntime: String, + + /** + * Version of Java runtime + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "Java 运行时版本") + val javaRuntimeVersion: String, + + /** + * Name of Java virtual machine + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "Java 虚拟机") + val jvm: String, + + /** + * Version of Java virtual machine + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "Java 虚拟机版本") + val jvmVersion: String, + + /** + * Version of Java Virtual machine + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "Java 虚拟机信息") + val jvmInfo: String, + + /** + * Vendor of Java Virtual machine + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "Java 虚拟机供应商") + val jvmVendor: String, + + /** + * Version of Java class + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "Java 字节文件版本") + val javaClassVersion: String, + + /** + * Boot time of operating system + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "操作系统启动时间") + val osBootTime: LocalDateTime, + + /** + * Startup time of server + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "服务器启动时间") + val serverStartupTime: LocalDateTime +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/system/StorageInfoVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/system/StorageInfoVo.kt new file mode 100644 index 0000000..2a467a0 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/system/StorageInfoVo.kt @@ -0,0 +1,117 @@ +package top.fatweb.oxygen.api.vo.system + +import io.swagger.v3.oas.annotations.media.Schema + +/** + * Storage information value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "存储信息返回参数") +data class StorageInfoVo( + /** + * The amount of actual physical memory. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "总内存容量") + val memoryTotal: Long, + + /** + * The amount of physical memory currently + * available。 + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "空闲内存容量") + val memoryFree: Long, + + /** + * The maximum memory that can be committed by the + * system without extending the paging file(s). Also called the + * Commit Limit. If the paging/swap file can be extended, this + * is a soft limit. This is generally equal to the sum of the sizes + * of physical memory and paging/swap file(s). + * + * On Linux, represents the total amount of memory currently + * available to be allocated on the system based on the + * overcommit ratio, identified as CommitLimit. This may be + * higher or lower than the total size of physical and swap + * memory depending on system configuration. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "总虚拟内存容量") + val virtualMemoryMax: Long, + + /** + * The memory currently committed by the system, in + * bytes. Also called the Commit Total. This is generally + * equal to the sum of the bytes used of physical + * memory and paging/swap file(s). + * + * On Windows, committing pages changes this value + * immediately; however, the physical memory is not + * charged until the pages are accessed, so this + * value may exceed the sum of used physical and + * paging/swap file memory. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "已用虚拟内存容量") + val virtualMemoryInUse: Long, + + /** + * The current size of the paging/swap + * file(s). If the paging/swap file can be + * extended, this is a soft limit. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "总交换区容量") + val swapTotal: Long, + + /** + * The current memory committed to the + * paging/swap file(s). + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "可用交换区容量") + val swapUsed: Long, + + /** + * Total amount of memory in the Java virtual machine. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "Java 虚拟机总内存容量") + val jvmTotal: Long, + + /** + * Amount of free memory in the Java Virtual Machine. + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "Java 虚拟机空闲内存容量") + val jvmFree: Long, + + /** + * List of FileStoreInfoVo object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see FileStoreInfoVo + */ + @Schema(description = "文件存储信息列表") + val fileStores: List +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/system/SysLogVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/system/SysLogVo.kt new file mode 100644 index 0000000..4c44028 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/system/SysLogVo.kt @@ -0,0 +1,164 @@ +package top.fatweb.oxygen.api.vo.system + +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer +import io.swagger.v3.oas.annotations.media.Schema +import top.fatweb.oxygen.api.entity.system.SysLog +import java.time.LocalDateTime + +/** + * System log value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "获取系统日志返回参数") +data class SysLogVo( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @JsonSerialize(using = ToStringSerializer::class) + val id: Long?, + + /** + * Log type + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "日志类型") + val logType: SysLog.LogType?, + + /** + * Operate user ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "操作用户 ID") + @JsonSerialize(using = ToStringSerializer::class) + val operateUserId: Long?, + + /** + * Operate time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "操作时间") + val operateTime: LocalDateTime?, + + /** + * Request URI + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "请求 Uri") + val requestUri: String?, + + /** + * Request Method + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "请求方式") + val requestMethod: String?, + + /** + * Request parameters + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "请求参数") + val requestParams: String?, + + /** + * Request IP + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "请求 IP") + val requestIp: String?, + + /** + * Request server address + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "请求服务器地址") + val requestServerAddress: String?, + + /** + * Is exception + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "是否异常") + val exception: Boolean?, + + /** + * Exception information + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "异常信息") + val exceptionInfo: String?, + + /** + * Start time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "开始时间") + val startTime: LocalDateTime?, + + /** + * End time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "结束时间") + val endTime: LocalDateTime?, + + /** + * Execute time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "执行时间") + val executeTime: Long?, + + /** + * User agent + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "用户代理") + val userAgent: String?, + + /** + * Operate username + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "操作用户名") + val operateUsername: String? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/tool/ToolBaseVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/tool/ToolBaseVo.kt new file mode 100644 index 0000000..0704766 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/tool/ToolBaseVo.kt @@ -0,0 +1,80 @@ +package top.fatweb.oxygen.api.vo.tool + +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer +import io.swagger.v3.oas.annotations.media.Schema +import java.time.LocalDateTime + +/** + * Tool base value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "工具基板返回参数") +data class ToolBaseVo( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @JsonSerialize(using = ToStringSerializer::class) + val id: Long?, + + /** + * Name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "名称") + val name: String?, + + /** + * Source + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "源码") + val source: ToolDataVo?, + + /** + * Dist + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "产物") + val dist: ToolDataVo?, + + /** + * Compiled + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "已编译") + val compiled: Boolean?, + + /** + * Create time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "创建时间", example = "1900-01-01T00:00:00.000Z") + val createTime: LocalDateTime?, + + /** + * Update time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "修改时间", example = "1900-01-01T00:00:00.000Z") + val updateTime: LocalDateTime? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/tool/ToolCategoryVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/tool/ToolCategoryVo.kt new file mode 100644 index 0000000..3be4db8 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/tool/ToolCategoryVo.kt @@ -0,0 +1,62 @@ +package top.fatweb.oxygen.api.vo.tool + +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer +import io.swagger.v3.oas.annotations.media.Schema +import java.time.LocalDateTime + +/** + * Tool base value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "工具类别返回参数") +data class ToolCategoryVo( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @JsonSerialize(using = ToStringSerializer::class) + val id: Long?, + + /** + * Name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "名称") + val name: String?, + + /** + * Enable + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "启用") + val enable: Boolean?, + + /** + * Create time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "创建时间", example = "1900-01-01T00:00:00.000Z") + val createTime: LocalDateTime?, + + /** + * Update time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "修改时间", example = "1900-01-01T00:00:00.000Z") + val updateTime: LocalDateTime? +) diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/tool/ToolDataVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/tool/ToolDataVo.kt new file mode 100644 index 0000000..309dbf4 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/tool/ToolDataVo.kt @@ -0,0 +1,53 @@ +package top.fatweb.oxygen.api.vo.tool + +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer +import io.swagger.v3.oas.annotations.media.Schema +import java.time.LocalDateTime + +/** + * Tool data value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "工具数据返回参数") +data class ToolDataVo( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @JsonSerialize(using = ToStringSerializer::class) + val id: Long?, + + /** + * Data + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "数据") + val data: String?, + + /** + * Create time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "创建时间", example = "1900-01-01T00:00:00.000Z") + val createTime: LocalDateTime?, + + /** + * Update time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "修改时间", example = "1900-01-01T00:00:00.000Z") + val updateTime: LocalDateTime? +) \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/tool/ToolTemplateVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/tool/ToolTemplateVo.kt new file mode 100644 index 0000000..fea3b1f --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/tool/ToolTemplateVo.kt @@ -0,0 +1,89 @@ +package top.fatweb.oxygen.api.vo.tool + +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer +import io.swagger.v3.oas.annotations.media.Schema +import java.time.LocalDateTime + +/** + * Tool template value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +@Schema(description = "工具模板返回参数") +data class ToolTemplateVo( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @JsonSerialize(using = ToStringSerializer::class) + val id: Long?, + + /** + * Name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "名称") + val name: String?, + + /** + * Base + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "基板") + val base: ToolBaseVo?, + + /** + * Source + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "源码") + val source: ToolDataVo?, + + /** + * Entry point + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "入口文件") + val entryPoint: String?, + + /** + * Enable + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "启用") + val enable: Boolean?, + + /** + * Create time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "创建时间", example = "1900-01-01T00:00:00.000Z") + val createTime: LocalDateTime?, + + /** + * Update time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "修改时间", example = "1900-01-01T00:00:00.000Z") + val updateTime: LocalDateTime? +) \ No newline at end of file diff --git a/src/main/kotlin/top/fatweb/oxygen/api/vo/tool/ToolVo.kt b/src/main/kotlin/top/fatweb/oxygen/api/vo/tool/ToolVo.kt new file mode 100644 index 0000000..5a32d44 --- /dev/null +++ b/src/main/kotlin/top/fatweb/oxygen/api/vo/tool/ToolVo.kt @@ -0,0 +1,177 @@ +package top.fatweb.oxygen.api.vo.tool + +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer +import io.swagger.v3.oas.annotations.media.Schema +import top.fatweb.oxygen.api.entity.tool.Tool +import top.fatweb.oxygen.api.vo.permission.UserWithInfoVo +import java.time.LocalDateTime + +/** + * Tool value object + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ +data class ToolVo( + /** + * ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @JsonSerialize(using = ToStringSerializer::class) + val id: Long?, + + /** + * Name + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "名称") + val name: String?, + + /** + * Tool ID + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "工具 ID") + val toolId: String?, + + /** + * Icon + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "图标") + val icon: String?, + + /** + * Description + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "简介") + val description: String?, + + /** + * Base + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "基板") + val base: ToolBaseVo?, + + /** + * Author + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see UserWithInfoVo + */ + @Schema(description = "作者") + val author: UserWithInfoVo?, + + /** + * Version + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "版本") + val ver: String?, + + /** + * Keywords + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "关键字") + val keywords: List?, + + /** + * Categories + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolCategoryVo + */ + @Schema(description = "类别") + val categories: List?, + + /** + * Source + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolDataVo + */ + @Schema(description = "源码") + val source: ToolDataVo?, + + /** + * Dist + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see ToolDataVo + */ + @Schema(description = "产物") + val dist: ToolDataVo?, + + /** + * Entry point + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @Schema(description = "入口文件") + val entryPoint: String?, + + /** + * Publish + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + */ + @JsonSerialize(using = ToStringSerializer::class) + @Schema(description = "发布") + val publish: Long?, + + /** + * Review + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see Tool.ReviewType + */ + @Schema(description = "审核") + val review: Tool.ReviewType?, + + /** + * Create time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "创建时间", example = "1900-01-01T00:00:00.000Z") + val createTime: LocalDateTime?, + + /** + * Update time + * + * @author FatttSnake, fatttsnake@gmail.com + * @since 1.0.0 + * @see LocalDateTime + */ + @Schema(description = "修改时间", example = "1900-01-01T00:00:00.000Z") + val updateTime: LocalDateTime? +) \ No newline at end of file diff --git a/src/main/resources/application-config-template.yml b/src/main/resources/application-config-template.yml index 487ce6e..dbe25d5 100644 --- a/src/main/resources/application-config-template.yml +++ b/src/main/resources/application-config-template.yml @@ -1,11 +1,18 @@ app: + app-name: Oxygen Toolbox # Application name + turnstile-secret-key: 1x0000000000000000000000000000000AA # Turnstile secret key + admin: +# username: admin # Username of administrator +# password: admin # Default password of administrator +# nickname: Administrator # Nickname of administrator +# email: admin@mail.com # Email of administrator security: # header-string: "Authorization" # The key of head to get token # token-prefix: "Bearer " # Token prefix # jwt-ttl: 2 # The life of token # jwt-ttl-unit: hours # Unit of life of token [nanoseconds, microseconds, milliseconds, seconds, minutes, hours, days] jwt-key: $uuid$ # Key to generate token (Only numbers and letters allow) -# jwt-issuer: FatWeb # Token issuer +# jwt-issuer: Oxygen # Token issuer # redis-ttl: 20 # The life of token in redis # redis-ttl-unit: minutes # Unit of life of token in redis [nanoseconds, microseconds, milliseconds, seconds, minutes, hours, days] @@ -14,19 +21,22 @@ server: spring: datasource: - url: jdbc:mysql://localhost # MySQL url - username: root # MySQL username - password: root # MySQL password + dynamic: + datasource: + master: + url: jdbc:mysql://localhost # MySQL url + username: root # MySQL username + password: root # MySQL password + hikari: +# pool-name: HikariCP # Connection pool name +# minimum-idle: 5 # Minimum number of connection in pool +# idle-timeout: 600000 # The lifetime of connection when idle +# maximum-pool-size: 10 # Maximum number of connection in pool +# auto-commit: true # Auto commit +# max-lifetime: 1800000 # Maximum lifetime of connection +# connection-timeout: 30000 # Connection timeout +# connection-test-query: select 1 # Test query then connect - druid: -# initial-size: 20 # Initial number of connections -# min-idle: 20 # Minimum number of connection pools -# max-active: 20 # Maximum number of connection pools -# max-wait: 3000 # Maximum connection timeout -# min-evictable-idle-time-millis: 300000 # Minimum time for a connection to live in the pool -# max-evictable-idle-time-millis: 900000 # Maximum time for a connection to live in the pool -# break-after-acquire-failure: true # Terminate the retry when the server fails to reconnect for the specified number of times -# connection-error-retry-attempts: 5 # Number of failed reconnections data: redis: @@ -40,4 +50,17 @@ spring: # min-idle: 0 # max-idle: 8 # max-active: 8 -# max-wait: -1ms \ No newline at end of file +# max-wait: -1ms + +logging: + level: + root: info # Logging level + file: + name: data/log/fat-api.log # Logging path and name + logback: + rollingpolicy: +# max-file-size: 10MB # Maximum log file size +# max-history: 7 # Maximum number of archive log files to keep + +knife4j: + production: true # Production environment mode will block doc \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index cec8de8..46ec570 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -1,4 +1,5 @@ app: + app-name: Oxygen Toolbox version: @project.version@ build-time: @build.timestamp@ @@ -6,8 +7,27 @@ spring: profiles: active: config datasource: - type: com.alibaba.druid.pool.DruidDataSource - driver-class-name: com.mysql.cj.jdbc.Driver + dynamic: + primary: master + strict: false + datasource: + master: + type: com.zaxxer.hikari.HikariDataSource + driver-class-name: com.mysql.cj.jdbc.Driver + sqlite: + type: com.zaxxer.hikari.HikariDataSource + driver-class-name: org.sqlite.JDBC + url: jdbc:sqlite:data/db/sqlite.db + + + jackson: + date-format: yyyy-MM-dd'T'HH:mm:ss.SSS'Z' + time-zone: GMT + flyway: + enabled: false + baseline-on-migrate: true + baseline-version: 0 + mybatis-plus: global-config: db-config: @@ -15,4 +35,13 @@ mybatis-plus: logic-not-delete-value: 0 logic-delete-value: id id-type: assign_id - type-aliases-package: top.fatweb.api.entity + type-aliases-package: top.fatweb.oxygen.api.entity + +logging: + level: + root: info + file: + name: data/log/fat-api.log + +knife4j: + enable: true \ No newline at end of file diff --git a/src/main/resources/db/migration/master/R__Basic_data.sql b/src/main/resources/db/migration/master/R__Basic_data.sql new file mode 100644 index 0000000..e8bb177 --- /dev/null +++ b/src/main/resources/db/migration/master/R__Basic_data.sql @@ -0,0 +1,191 @@ +insert into t_s_power_type (id, name) + values (1, 'module'), + (2, 'menu'), + (3, 'func'), + (4, 'operation') as new_value +on duplicate key update name = new_value.name; + +insert into t_s_power (id, type_id) + values (1000000, 1), + (1990000, 2), + (1010000, 2), + (1020000, 2), + (1030000, 2), + (1040000, 2), + (1510000, 2), + (1520000, 2), + (1530000, 2), + (1540000, 2), + (1010100, 3), + (1010200, 3), + (1010300, 3), + (1010400, 3), + (1020100, 3), + (1020200, 3), + (1020300, 3), + (1020400, 3), + (1030100, 3), + (1030200, 3), + (1030300, 3), + (1030400, 3), + (1040100, 3), + (1510100, 3), + (1520100, 3), + (1530100, 3), + (1530300, 3), + (1540100, 3), + (1540200, 3), + (1540300, 3), + (1540400, 3), + (1010101, 4), + (1010102, 4), + (1010103, 4), + (1010201, 4), + (1010301, 4), + (1010302, 4), + (1010401, 4), + (1010402, 4), + (1020101, 4), + (1020102, 4), + (1020103, 4), + (1020201, 4), + (1020301, 4), + (1020302, 4), + (1020401, 4), + (1020402, 4), + (1030101, 4), + (1030102, 4), + (1030103, 4), + (1030201, 4), + (1030301, 4), + (1030302, 4), + (1030401, 4), + (1030402, 4), + (1040103, 4), + (1510101, 4), + (1510102, 4), + (1510103, 4), + (1520101, 4), + (1530101, 4), + (1530102, 4), + (1530103, 4), + (1530301, 4), + (1530302, 4), + (1530303, 4), + (1540101, 4), + (1540102, 4), + (1540103, 4), + (1540104, 4), + (1540201, 4), + (1540202, 4), + (1540203, 4), + (1540204, 4), + (1540301, 4), + (1540302, 4), + (1540303, 4), + (1540304, 4), + (1540401, 4), + (1540402, 4), + (1540403, 4), + (1540404, 4) as new_value +on duplicate key update type_id = new_value.type_id; + +insert into t_s_module (id, name) + values (1000000, '系统') as new_value +on duplicate key update name = new_value.name; + +insert into t_s_menu (id, name, url, parent_id, module_id) + values (1990000, '系统管理', '^/system$', null, 1000000), + (1010000, '用户管理', '^/system/user$', 1990000, 1000000), + (1020000, '角色管理', '^/system/role$', 1990000, 1000000), + (1030000, '用户组管理', '^/system/group$', 1990000, 1000000), + (1040000, '权限管理', '^/system/power$', 1990000, 1000000), + (1510000, '系统概况', '^/system/statistics$', 1990000, 1000000), + (1520000, '日志管理', '^/system/log$', 1990000, 1000000), + (1530000, '系统设置', '^/system/settings$', 1990000, 1000000), + (1540000, '工具配置', '^/system/tools(/.*)?$', 1990000, 1000000) as new_value +on duplicate key update name =new_value.name, + url =new_value.url, + parent_id =new_value.parent_id; + +insert into t_s_func(id, name, menu_id, parent_id) + values (1010100, '查询', 1010000, null), + (1010200, '增加', 1010000, null), + (1010300, '修改', 1010000, null), + (1010400, '删除', 1010000, null), + (1020100, '查询', 1020000, null), + (1020200, '增加', 1020000, null), + (1020300, '修改', 1020000, null), + (1020400, '删除', 1020000, null), + (1030100, '查询', 1030000, null), + (1030200, '增加', 1030000, null), + (1030300, '修改', 1030000, null), + (1030400, '删除', 1030000, null), + (1040100, '查询', 1040000, null), + (1510100, '查询', 1510000, null), + (1520100, '查询', 1520000, null), + (1530100, '查询', 1530000, null), + (1530300, '修改', 1530000, null), + (1540100, '查询', 1540000, null), + (1540200, '增加', 1540000, null), + (1540300, '修改', 1540000, null), + (1540400, '删除', 1540000, null) as new_value +on duplicate key update name = new_value.name, + menu_id = new_value.menu_id, + parent_id = new_value.parent_id; + +insert into t_s_operation(id, name, code, func_id) + values (1010101, '单个', 'system:user:query:one', 1010100), + (1010102, '全部', 'system:user:query:all', 1010100), + (1010103, '列表', 'system:user:query:list', 1010100), + (1010201, '单个', 'system:user:add:one', 1010200), + (1010301, '单个', 'system:user:modify:one', 1010300), + (1010302, '密码', 'system:user:modify:password', 1010300), + (1010401, '单个', 'system:user:delete:one', 1010400), + (1010402, '多个', 'system:user:delete:multiple', 1010400), + (1020101, '单个', 'system:role:query:one', 1020100), + (1020102, '全部', 'system:role:query:all', 1020100), + (1020103, '列表', 'system:role:query:list', 1020100), + (1020201, '单个', 'system:role:add:one', 1020200), + (1020301, '单个', 'system:role:modify:one', 1020300), + (1020302, '状态', 'system:role:modify:status', 1020300), + (1020401, '单个', 'system:role:delete:one', 1020400), + (1020402, '多个', 'system:role:delete:multiple', 1020400), + (1030101, '单个', 'system:group:query:one', 1030100), + (1030102, '全部', 'system:group:query:all', 1030100), + (1030103, '列表', 'system:group:query:list', 1030100), + (1030201, '单个', 'system:group:add:one', 1030200), + (1030301, '单个', 'system:group:modify:one', 1030300), + (1030302, '状态', 'system:group:modify:status', 1030300), + (1030401, '单个', 'system:group:delete:one', 1030400), + (1030402, '多个', 'system:group:delete:multiple', 1030400), + (1040103, '列表', 'system:power:query:list', 1040100), + (1510101, '使用情况', 'system:statistics:query:usage', 1510100), + (1510102, '基础信息', 'system:statistics:query:base', 1510100), + (1510103, '实时信息', 'system:statistics:query:real', 1510100), + (1520101, '全部', 'system:log:query:all', 1520100), + (1530101, '基础', 'system:settings:query:base', 1530100), + (1530102, '邮件', 'system:settings:query:mail', 1530100), + (1530103, '敏感词', 'system:settings:query:sensitive', 1530100), + (1530301, '基础', 'system:settings:modify:base', 1530300), + (1530302, '邮件', 'system:settings:modify:mail', 1530300), + (1530303, '敏感词', 'system:settings:modify:sensitive', 1530300), + (1540101, '类别', 'system:tool:query:category', 1540100), + (1540102, '基板', 'system:tool:query:base', 1540100), + (1540103, '模板', 'system:tool:query:template', 1540100), + (1540104, '工具', 'system:tool:query:tool', 1540100), + (1540201, '类别', 'system:tool:add:category', 1540200), + (1540202, '基板', 'system:tool:add:base', 1540200), + (1540203, '模板', 'system:tool:add:template', 1540200), + (1540204, '工具', 'system:tool:add:tool', 1540200), + (1540301, '类别', 'system:tool:modify:category', 1540300), + (1540302, '基板', 'system:tool:modify:base', 1540300), + (1540303, '模板', 'system:tool:modify:template', 1540300), + (1540304, '工具', 'system:tool:modify:tool', 1540300), + (1540401, '类别', 'system:tool:delete:category', 1540400), + (1540402, '基板', 'system:tool:delete:base', 1540400), + (1540403, '模板', 'system:tool:delete:template', 1540400), + (1540404, '工具', 'system:tool:delete:tool', 1540400) as new_value +on duplicate key update name=new_value.name, + code=new_value.code, + func_id=new_value.func_id; \ No newline at end of file diff --git a/src/main/resources/db/migration/master/V1_0_0_231019__Add_table_'t_s_user'.sql b/src/main/resources/db/migration/master/V1_0_0_231019__Add_table_'t_s_user'.sql new file mode 100644 index 0000000..9e2287d --- /dev/null +++ b/src/main/resources/db/migration/master/V1_0_0_231019__Add_table_'t_s_user'.sql @@ -0,0 +1,25 @@ +drop table if exists t_s_user; + +create table if not exists t_s_user +( + id bigint not null primary key, + username varchar(20) not null comment '用户名', + password char(70) not null comment '密码', + verify varchar(144) null comment '验证邮箱', + forget varchar(144) null comment '忘记密码', + locking int not null comment '锁定', + expiration datetime comment '过期时间', + credentials_expiration datetime comment '认证过期时间', + enable int not null comment '启用', + current_login_time datetime comment '当前登录时间', + current_login_ip varchar(128) comment '当前登录 IP', + last_login_time datetime comment '上次登录时间', + last_login_ip varchar(128) comment '上次登录 IP', + create_time datetime not null default (utc_timestamp()) comment '创建时间', + update_time datetime not null default (utc_timestamp()) comment '修改时间', + deleted bigint not null default 0, + version int not null default 0, + constraint t_s_user_unique_username unique (username, deleted), + constraint t_s_user_unique_verify unique (verify, deleted), + constraint t_s_user_unique_forget unique (forget, deleted) +) comment '系统-用户表'; \ No newline at end of file diff --git a/src/main/resources/db/migration/master/V1_0_0_231023__Add_table_'t_s_power_type'.sql b/src/main/resources/db/migration/master/V1_0_0_231023__Add_table_'t_s_power_type'.sql new file mode 100644 index 0000000..8544453 --- /dev/null +++ b/src/main/resources/db/migration/master/V1_0_0_231023__Add_table_'t_s_power_type'.sql @@ -0,0 +1,7 @@ +drop table if exists t_s_power_type; + +create table if not exists t_s_power_type +( + id bigint not null primary key, + name varchar(50) not null comment '权限类型名' +) comment '系统-权限类型表'; \ No newline at end of file diff --git a/src/main/resources/db/migration/master/V1_0_0_231024__Add_table_'t_s_power'.sql b/src/main/resources/db/migration/master/V1_0_0_231024__Add_table_'t_s_power'.sql new file mode 100644 index 0000000..1407a9b --- /dev/null +++ b/src/main/resources/db/migration/master/V1_0_0_231024__Add_table_'t_s_power'.sql @@ -0,0 +1,7 @@ +drop table if exists t_s_power; + +create table if not exists t_s_power +( + id bigint not null primary key, + type_id int not null comment '权限类型' +) comment '系统-权限表'; \ No newline at end of file diff --git a/src/main/resources/db/migration/master/V1_0_0_231025__Add_table_'t_s_menu'.sql b/src/main/resources/db/migration/master/V1_0_0_231025__Add_table_'t_s_menu'.sql new file mode 100644 index 0000000..6b8de95 --- /dev/null +++ b/src/main/resources/db/migration/master/V1_0_0_231025__Add_table_'t_s_menu'.sql @@ -0,0 +1,10 @@ +drop table if exists t_s_menu; + +create table if not exists t_s_menu +( + id bigint not null primary key, + name varchar(30) not null comment ' 菜单名', + url varchar(100) null comment 'URL', + parent_id bigint null comment '父ID', + module_id bigint not null comment '模块ID' +) comment '系统-菜单表'; \ No newline at end of file diff --git a/src/main/resources/db/migration/master/V1_0_0_231026__Add_table_'t_s_func'.sql b/src/main/resources/db/migration/master/V1_0_0_231026__Add_table_'t_s_func'.sql new file mode 100644 index 0000000..0f5f33f --- /dev/null +++ b/src/main/resources/db/migration/master/V1_0_0_231026__Add_table_'t_s_func'.sql @@ -0,0 +1,9 @@ +drop table if exists t_s_func; + +create table if not exists t_s_func +( + id bigint not null primary key, + name varchar(100) not null comment '功能名', + parent_id bigint null comment '父ID', + menu_id bigint not null comment '菜单ID' +) comment '系统-功能表'; \ No newline at end of file diff --git a/src/main/resources/db/migration/master/V1_0_0_231027__Add_table_'t_s_operation'.sql b/src/main/resources/db/migration/master/V1_0_0_231027__Add_table_'t_s_operation'.sql new file mode 100644 index 0000000..a527025 --- /dev/null +++ b/src/main/resources/db/migration/master/V1_0_0_231027__Add_table_'t_s_operation'.sql @@ -0,0 +1,9 @@ +drop table if exists t_s_operation; + +create table if not exists t_s_operation +( + id bigint not null primary key, + name varchar(50) not null comment '操作名', + code varchar(50) null comment '操作编码', + func_id bigint not null comment '功能ID' +) comment '系统-操作表'; \ No newline at end of file diff --git a/src/main/resources/db/migration/master/V1_0_0_231028__Add_table_'t_s_group'.sql b/src/main/resources/db/migration/master/V1_0_0_231028__Add_table_'t_s_group'.sql new file mode 100644 index 0000000..6168a2b --- /dev/null +++ b/src/main/resources/db/migration/master/V1_0_0_231028__Add_table_'t_s_group'.sql @@ -0,0 +1,13 @@ +drop table if exists t_s_group; + +create table if not exists t_s_group +( + id bigint not null primary key, + name varchar(30) not null comment '用户组名', + enable int not null comment '启用', + create_time datetime not null default (utc_timestamp()) comment '创建时间', + update_time datetime not null default (utc_timestamp()) comment '修改时间', + deleted bigint not null default 0, + version int not null default 0, + constraint t_s_group_unique unique (name, deleted) +) comment '系统-用户组表'; \ No newline at end of file diff --git a/src/main/resources/db/migration/master/V1_0_0_231029__Add_table_'t_r_user_group'.sql b/src/main/resources/db/migration/master/V1_0_0_231029__Add_table_'t_r_user_group'.sql new file mode 100644 index 0000000..969c3a7 --- /dev/null +++ b/src/main/resources/db/migration/master/V1_0_0_231029__Add_table_'t_r_user_group'.sql @@ -0,0 +1,10 @@ +drop table if exists t_r_user_group; + +create table if not exists t_r_user_group +( + id bigint not null primary key, + user_id bigint not null comment '用户', + group_id bigint not null comment '用户组', + deleted bigint not null default 0, + version int not null default 0 +) comment '中间表-系统-用户-用户组'; \ No newline at end of file diff --git a/src/main/resources/db/migration/master/V1_0_0_231030__Add_table_'t_s_role'.sql b/src/main/resources/db/migration/master/V1_0_0_231030__Add_table_'t_s_role'.sql new file mode 100644 index 0000000..d553aea --- /dev/null +++ b/src/main/resources/db/migration/master/V1_0_0_231030__Add_table_'t_s_role'.sql @@ -0,0 +1,13 @@ +drop table if exists t_s_role; + +create table if not exists t_s_role +( + id bigint not null primary key, + name varchar(20) not null comment '角色名', + enable int not null comment '启用', + create_time datetime not null default (utc_timestamp()) comment '创建时间', + update_time datetime not null default (utc_timestamp()) comment '修改时间', + deleted bigint not null default 0, + version int not null default 0, + constraint t_s_role_unique unique (name, deleted) +) comment '系统-角色表'; \ No newline at end of file diff --git a/src/main/resources/db/migration/master/V1_0_0_231031__Add_table_'t_r_role_group'.sql b/src/main/resources/db/migration/master/V1_0_0_231031__Add_table_'t_r_role_group'.sql new file mode 100644 index 0000000..ba976d0 --- /dev/null +++ b/src/main/resources/db/migration/master/V1_0_0_231031__Add_table_'t_r_role_group'.sql @@ -0,0 +1,10 @@ +drop table if exists t_r_role_group; + +create table if not exists t_r_role_group +( + id bigint not null primary key, + role_id bigint not null comment '角色', + group_id bigint not null comment '用户组', + deleted bigint not null default 0, + version int not null default 0 +) comment '中间表-系统-角色-用户组'; \ No newline at end of file diff --git a/src/main/resources/db/migration/master/V1_0_0_231101__Add_table_'t_r_user_role'.sql b/src/main/resources/db/migration/master/V1_0_0_231101__Add_table_'t_r_user_role'.sql new file mode 100644 index 0000000..8703912 --- /dev/null +++ b/src/main/resources/db/migration/master/V1_0_0_231101__Add_table_'t_r_user_role'.sql @@ -0,0 +1,10 @@ +drop table if exists t_r_user_role; + +create table if not exists t_r_user_role +( + id bigint not null primary key, + user_id bigint not null comment '用户', + role_id bigint not null comment '角色', + deleted bigint not null default 0, + version int not null default 0 +) comment '中间表-系统-用户-角色'; \ No newline at end of file diff --git a/src/main/resources/db/migration/master/V1_0_0_231102__Add_table_'t_r_power_role'.sql b/src/main/resources/db/migration/master/V1_0_0_231102__Add_table_'t_r_power_role'.sql new file mode 100644 index 0000000..81bc1cc --- /dev/null +++ b/src/main/resources/db/migration/master/V1_0_0_231102__Add_table_'t_r_power_role'.sql @@ -0,0 +1,10 @@ +drop table if exists t_r_power_role; + +create table if not exists t_r_power_role +( + id bigint not null primary key, + power_id bigint not null comment '权限', + role_id bigint not null comment '角色', + deleted bigint not null default 0, + version int not null default 0 +) comment '中间表-系统-权限-角色'; \ No newline at end of file diff --git a/src/main/resources/db/migration/master/V1_0_0_231103__Add_table_'t_s_module'.sql b/src/main/resources/db/migration/master/V1_0_0_231103__Add_table_'t_s_module'.sql new file mode 100644 index 0000000..b859553 --- /dev/null +++ b/src/main/resources/db/migration/master/V1_0_0_231103__Add_table_'t_s_module'.sql @@ -0,0 +1,7 @@ +drop table if exists t_s_module; + +create table if not exists t_s_module +( + id bigint not null primary key, + name varchar(100) not null comment '模块名' +) comment '系统-模块表'; \ No newline at end of file diff --git a/src/main/resources/db/migration/master/V1_0_0_231104__Add_table_'t_s_user_info'.sql b/src/main/resources/db/migration/master/V1_0_0_231104__Add_table_'t_s_user_info'.sql new file mode 100644 index 0000000..b2599f3 --- /dev/null +++ b/src/main/resources/db/migration/master/V1_0_0_231104__Add_table_'t_s_user_info'.sql @@ -0,0 +1,16 @@ +drop table if exists t_s_user_info; + +create table if not exists t_s_user_info +( + id bigint not null primary key, + user_id bigint not null comment '用户ID', + nickname varchar(50) not null comment '昵称', + avatar text null comment '头像', + email varchar(100) not null comment '邮箱', + create_time datetime not null default (utc_timestamp()) comment '创建时间', + update_time datetime not null default (utc_timestamp()) comment '修改时间', + deleted bigint not null default 0, + version int not null default 0, + constraint t_s_user_info_unique_user_id unique (user_id, deleted), + constraint t_s_user_info_unique_email unique (email, deleted) +) comment '系统-用户资料表'; \ No newline at end of file diff --git a/src/main/resources/db/migration/master/V1_0_0_240103__Add_table_‘t_s_sensitive_word'.sql b/src/main/resources/db/migration/master/V1_0_0_240103__Add_table_‘t_s_sensitive_word'.sql new file mode 100644 index 0000000..5177ab7 --- /dev/null +++ b/src/main/resources/db/migration/master/V1_0_0_240103__Add_table_‘t_s_sensitive_word'.sql @@ -0,0 +1,12 @@ +drop table if exists t_s_sensitive_word; + +create table if not exists t_s_sensitive_word +( + id bigint not null primary key, + word varchar(400) not null comment '词', + use_for varchar(50) null comment '用于', + enable int not null default 1 comment '启用', + deleted bigint not null default 0, + version int not null default 0, + constraint t_s_sensitive_word_unique_word unique (word, deleted) +) comment '系统-敏感词表'; \ No newline at end of file diff --git a/src/main/resources/db/migration/master/V1_0_0_240115__Add_table_'t_b_tool_main'.sql b/src/main/resources/db/migration/master/V1_0_0_240115__Add_table_'t_b_tool_main'.sql new file mode 100644 index 0000000..1b396f2 --- /dev/null +++ b/src/main/resources/db/migration/master/V1_0_0_240115__Add_table_'t_b_tool_main'.sql @@ -0,0 +1,25 @@ +drop table if exists t_b_tool_main; + +create table if not exists t_b_tool_main +( + id bigint not null primary key, + name varchar(50) not null comment '工具名', + tool_id varchar(50) not null comment '工具 ID', + icon text not null comment '图标', + description varchar(500) null comment '简介', + base_id bigint not null comment '基板 ID', + author_id bigint not null comment '作者 ID', + ver varchar(20) not null comment '版本', + keywords varchar(500) not null comment '关键字', + source_id bigint not null comment '源码 ID', + dist_id bigint not null comment '产物 ID', + entry_point varchar(64) not null default 'main.tsx' comment '入口文件', + publish bigint not null default 0 comment '发布', + review varchar(10) not null default 'NONE' comment '审核', + create_time datetime not null default (utc_timestamp()) comment '创建时间', + update_time datetime not null default (utc_timestamp()) comment '修改时间', + deleted bigint not null default 0, + version int not null default 0, + constraint t_b_tool_main_unique_tool_id_ver unique (tool_id, author_id, ver, deleted), + constraint t_b_tool_main_unique_tool_id_publish unique (tool_id, author_id, publish, deleted) +) comment '工具-主表'; \ No newline at end of file diff --git a/src/main/resources/db/migration/master/V1_0_0_240116__Add_table_'t_b_tool_category'.sql b/src/main/resources/db/migration/master/V1_0_0_240116__Add_table_'t_b_tool_category'.sql new file mode 100644 index 0000000..21a15d5 --- /dev/null +++ b/src/main/resources/db/migration/master/V1_0_0_240116__Add_table_'t_b_tool_category'.sql @@ -0,0 +1,13 @@ +drop table if exists t_b_tool_category; + +create table if not exists t_b_tool_category +( + id bigint not null primary key, + name varchar(50) not null comment '工具类别名', + enable int not null default 1 comment '启用', + create_time datetime not null default (utc_timestamp()) comment '创建时间', + update_time datetime not null default (utc_timestamp()) comment '修改时间', + deleted bigint not null default 0, + version int not null default 0, + constraint t_tool_category_name unique (name, deleted) +) comment '工具-类别表'; \ No newline at end of file diff --git a/src/main/resources/db/migration/master/V1_0_0_240117__Add_table_'t_r_tool_main_category'.sql b/src/main/resources/db/migration/master/V1_0_0_240117__Add_table_'t_r_tool_main_category'.sql new file mode 100644 index 0000000..c711b56 --- /dev/null +++ b/src/main/resources/db/migration/master/V1_0_0_240117__Add_table_'t_r_tool_main_category'.sql @@ -0,0 +1,10 @@ +drop table if exists t_r_tool_main_category; + +create table if not exists t_r_tool_main_category +( + id bigint not null primary key, + tool_id bigint not null comment '工具', + category_id bigint not null comment '类别', + deleted bigint not null default 0, + version int not null default 0 +) comment '中间表-工具-主表-类别'; \ No newline at end of file diff --git a/src/main/resources/db/migration/master/V1_0_0_240118__Add_table_'t_b_tool_data'.sql b/src/main/resources/db/migration/master/V1_0_0_240118__Add_table_'t_b_tool_data'.sql new file mode 100644 index 0000000..f05e75a --- /dev/null +++ b/src/main/resources/db/migration/master/V1_0_0_240118__Add_table_'t_b_tool_data'.sql @@ -0,0 +1,11 @@ +drop table if exists t_b_tool_data; + +create table if not exists t_b_tool_data +( + id bigint not null primary key, + data mediumtext not null comment '数据', + create_time datetime not null default (utc_timestamp()) comment '创建时间', + update_time datetime not null default (utc_timestamp()) comment '修改时间', + deleted bigint not null default 0, + version int not null default 0 +) comment '工具-数据表'; \ No newline at end of file diff --git a/src/main/resources/db/migration/master/V1_0_0_240119__Add_table_'t_b_tool_template'.sql b/src/main/resources/db/migration/master/V1_0_0_240119__Add_table_'t_b_tool_template'.sql new file mode 100644 index 0000000..0d442a9 --- /dev/null +++ b/src/main/resources/db/migration/master/V1_0_0_240119__Add_table_'t_b_tool_template'.sql @@ -0,0 +1,16 @@ +drop table if exists t_b_tool_template; + +create table if not exists t_b_tool_template +( + id bigint not null primary key, + name varchar(40) not null comment '模板名', + base_id bigint not null comment '基板 ID', + source_id bigint not null comment '源码 ID', + entry_point varchar(64) not null default 'main.tsx' comment '入口文件', + enable int not null default 1 comment '启用', + create_time datetime not null default (utc_timestamp()) comment '创建时间', + update_time datetime not null default (utc_timestamp()) comment '修改时间', + deleted bigint not null default 0, + version int not null default 0, + constraint t_b_tool_template_unique_name unique (name, deleted) +) comment '工具-模板表' \ No newline at end of file diff --git a/src/main/resources/db/migration/master/V1_0_0_240120__Add_table_'t_b_tool_base'.sql b/src/main/resources/db/migration/master/V1_0_0_240120__Add_table_'t_b_tool_base'.sql new file mode 100644 index 0000000..9225778 --- /dev/null +++ b/src/main/resources/db/migration/master/V1_0_0_240120__Add_table_'t_b_tool_base'.sql @@ -0,0 +1,15 @@ +drop table if exists t_b_tool_base; + +create table if not exists t_b_tool_base +( + id bigint not null primary key, + name varchar(20) not null comment '基板名', + source_id bigint not null comment '源码 ID', + dist_id bigint not null comment '产物 ID', + compiled int not null default 0 comment '已编译', + create_time datetime not null default (utc_timestamp()) comment '创建时间', + update_time datetime not null default (utc_timestamp()) comment '修改时间', + deleted bigint not null default 0, + version int not null default 0, + constraint t_b_tool_base_unique_name unique (name, deleted) +) \ No newline at end of file diff --git a/src/main/resources/db/migration/sqlite/V1_0_0_231212__Add_table_'t_l_sys_log'.sql b/src/main/resources/db/migration/sqlite/V1_0_0_231212__Add_table_'t_l_sys_log'.sql new file mode 100644 index 0000000..a49c66c --- /dev/null +++ b/src/main/resources/db/migration/sqlite/V1_0_0_231212__Add_table_'t_l_sys_log'.sql @@ -0,0 +1,20 @@ +drop table if exists t_l_sys_log; + +create table t_l_sys_log -- 本地-系统日志表 +( + id integer not null, + log_type text not null, -- 日志类型 + operate_user_id integer not null, -- 操作用户 + operate_time text not null default (strftime('%Y-%m-%d %H:%M:%f', 'now')), -- 操作时间 + request_uri text default null, -- 请求 URI + request_method text default null, -- 请求方式 + request_params text, -- 请求参数 + request_ip text not null, -- 请求 IP + request_server_address text not null, -- 请求服务器地址 + exception integer not null default 0, -- 是否异常 + exception_info text, -- 异常信息 + start_time text not null, -- 开始时间 + end_time text not null, -- 结束时间 + execute_time integer default null, -- 执行时间 + user_agent text default null -- 用户代理 +); \ No newline at end of file diff --git a/src/main/resources/db/migration/sqlite/V1_0_0_231213__Add_table_'t_l_event_log'.sql b/src/main/resources/db/migration/sqlite/V1_0_0_231213__Add_table_'t_l_event_log'.sql new file mode 100644 index 0000000..d729c85 --- /dev/null +++ b/src/main/resources/db/migration/sqlite/V1_0_0_231213__Add_table_'t_l_event_log'.sql @@ -0,0 +1,9 @@ +drop table if exists t_l_event_log; + +create table if not exists t_l_event_log -- 本地-事件日志表 +( + id integer not null primary key, + event text not null, -- 事件, + operate_user_id integer not null, -- 操作用户 + operate_time text not null default (strftime('%Y-%m-%d %H:%M:%f', 'now')) -- 操作时间 +); \ No newline at end of file diff --git a/src/main/resources/db/migration/sqlite/V1_0_0_231214__Add_table_'t_l_statistics_log'.sql b/src/main/resources/db/migration/sqlite/V1_0_0_231214__Add_table_'t_l_statistics_log'.sql new file mode 100644 index 0000000..2fb9390 --- /dev/null +++ b/src/main/resources/db/migration/sqlite/V1_0_0_231214__Add_table_'t_l_statistics_log'.sql @@ -0,0 +1,9 @@ +drop table if exists t_l_statistics_log; + +create table if not exists t_l_statistics_log -- 本地-统计日志表 +( + id integer not null primary key, + key text not null, -- 记录键 + value text not null, -- 记录值 + record_time text not null default (strftime('%Y-%m-%d %H:%M:%f', 'now')) -- 记录时间 +) \ No newline at end of file diff --git a/src/main/resources/mapper/permission/FuncMapper.xml b/src/main/resources/mapper/permission/FuncMapper.xml new file mode 100644 index 0000000..ef0e20e --- /dev/null +++ b/src/main/resources/mapper/permission/FuncMapper.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/main/resources/mapper/permission/GroupMapper.xml b/src/main/resources/mapper/permission/GroupMapper.xml new file mode 100644 index 0000000..74d97b9 --- /dev/null +++ b/src/main/resources/mapper/permission/GroupMapper.xml @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/permission/MenuMapper.xml b/src/main/resources/mapper/permission/MenuMapper.xml new file mode 100644 index 0000000..5b9e6de --- /dev/null +++ b/src/main/resources/mapper/permission/MenuMapper.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/main/resources/mapper/permission/ModuleMapper.xml b/src/main/resources/mapper/permission/ModuleMapper.xml new file mode 100644 index 0000000..1b344eb --- /dev/null +++ b/src/main/resources/mapper/permission/ModuleMapper.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/main/resources/mapper/permission/OperationMapper.xml b/src/main/resources/mapper/permission/OperationMapper.xml new file mode 100644 index 0000000..5f4bf6f --- /dev/null +++ b/src/main/resources/mapper/permission/OperationMapper.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/main/resources/mapper/permission/PowerMapper.xml b/src/main/resources/mapper/permission/PowerMapper.xml new file mode 100644 index 0000000..bb5286d --- /dev/null +++ b/src/main/resources/mapper/permission/PowerMapper.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/main/resources/mapper/permission/PowerRoleMapper.xml b/src/main/resources/mapper/permission/PowerRoleMapper.xml new file mode 100644 index 0000000..7cc22a5 --- /dev/null +++ b/src/main/resources/mapper/permission/PowerRoleMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/resources/mapper/permission/RoleGroupMapper.xml b/src/main/resources/mapper/permission/RoleGroupMapper.xml new file mode 100644 index 0000000..4125e6e --- /dev/null +++ b/src/main/resources/mapper/permission/RoleGroupMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/resources/mapper/permission/RoleMapper.xml b/src/main/resources/mapper/permission/RoleMapper.xml new file mode 100644 index 0000000..caeaf51 --- /dev/null +++ b/src/main/resources/mapper/permission/RoleMapper.xml @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/permission/UserGroupMapper.xml b/src/main/resources/mapper/permission/UserGroupMapper.xml new file mode 100644 index 0000000..49b30ef --- /dev/null +++ b/src/main/resources/mapper/permission/UserGroupMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/main/resources/mapper/permission/UserInfoMapper.xml b/src/main/resources/mapper/permission/UserInfoMapper.xml new file mode 100644 index 0000000..de8ac7a --- /dev/null +++ b/src/main/resources/mapper/permission/UserInfoMapper.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/permission/UserMapper.xml b/src/main/resources/mapper/permission/UserMapper.xml new file mode 100644 index 0000000..40cb1fb --- /dev/null +++ b/src/main/resources/mapper/permission/UserMapper.xml @@ -0,0 +1,340 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/UserMapper.xml b/src/main/resources/mapper/permission/UserRoleMapper.xml similarity index 67% rename from src/main/resources/mapper/UserMapper.xml rename to src/main/resources/mapper/permission/UserRoleMapper.xml index cecc32c..5906666 100644 --- a/src/main/resources/mapper/UserMapper.xml +++ b/src/main/resources/mapper/permission/UserRoleMapper.xml @@ -1,5 +1,5 @@ - + diff --git a/src/main/resources/mapper/system/SysLogMapper.xml b/src/main/resources/mapper/system/SysLogMapper.xml new file mode 100644 index 0000000..d746aa7 --- /dev/null +++ b/src/main/resources/mapper/system/SysLogMapper.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/tool/EditMapper.xml b/src/main/resources/mapper/tool/EditMapper.xml new file mode 100644 index 0000000..9f7aeb4 --- /dev/null +++ b/src/main/resources/mapper/tool/EditMapper.xml @@ -0,0 +1,211 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/tool/ManagementMapper.xml b/src/main/resources/mapper/tool/ManagementMapper.xml new file mode 100644 index 0000000..1debeda --- /dev/null +++ b/src/main/resources/mapper/tool/ManagementMapper.xml @@ -0,0 +1,261 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/tool/StoreMapper.xml b/src/main/resources/mapper/tool/StoreMapper.xml new file mode 100644 index 0000000..1eefde7 --- /dev/null +++ b/src/main/resources/mapper/tool/StoreMapper.xml @@ -0,0 +1,108 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/tool/ToolBaseMapper.xml b/src/main/resources/mapper/tool/ToolBaseMapper.xml new file mode 100644 index 0000000..2994493 --- /dev/null +++ b/src/main/resources/mapper/tool/ToolBaseMapper.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/tool/ToolCategoryMapper.xml b/src/main/resources/mapper/tool/ToolCategoryMapper.xml new file mode 100644 index 0000000..5be8646 --- /dev/null +++ b/src/main/resources/mapper/tool/ToolCategoryMapper.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/tool/ToolDataMapper.xml b/src/main/resources/mapper/tool/ToolDataMapper.xml new file mode 100644 index 0000000..cb72ea3 --- /dev/null +++ b/src/main/resources/mapper/tool/ToolDataMapper.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/src/main/resources/mapper/tool/ToolTemplateMapper.xml b/src/main/resources/mapper/tool/ToolTemplateMapper.xml new file mode 100644 index 0000000..b25a8eb --- /dev/null +++ b/src/main/resources/mapper/tool/ToolTemplateMapper.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/templates/email-password-changed-cn.vm b/src/main/resources/templates/email-password-changed-cn.vm new file mode 100644 index 0000000..aba67ca --- /dev/null +++ b/src/main/resources/templates/email-password-changed-cn.vm @@ -0,0 +1,78 @@ + + + + + + + 您的密码已更改 + + + +
+
+
密 码 已 更 改
+
${username},您好:
+
您在 ${appName}(${appUrl}) 的密码已更改,操作 + IP 地址为 [${ipAddress}]。如果不是您自己的操作,请尽快检查您的账号! +
+
此邮件由系统自动发送,请勿回复!
+
+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/email-retrieve-password-cn.vm b/src/main/resources/templates/email-retrieve-password-cn.vm new file mode 100644 index 0000000..d520710 --- /dev/null +++ b/src/main/resources/templates/email-retrieve-password-cn.vm @@ -0,0 +1,90 @@ + + + + + + + 找回您的密码 + + + +
+
+
找 回 密 码
+
${username},您好:
+
您正在找回 ${appName}(${appUrl}) 的密码,操作 + IP 地址为 [${ipAddress}],如果是您自己的操作,请在 两小时内 点击下面的按钮找回您的密码: +
+ +
如果以上按钮无法点击,请复制此链接到浏览器地址栏中访问:${retrieveUrl}
+
如果并非本人操作,请忽略该邮件
+
此邮件由系统自动发送,请勿回复!
+
+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/email-verify-account-cn.vm b/src/main/resources/templates/email-verify-account-cn.vm new file mode 100644 index 0000000..ead9e3a --- /dev/null +++ b/src/main/resources/templates/email-verify-account-cn.vm @@ -0,0 +1,89 @@ + + + + + + + 验证您的账号 + + + +
+
+
账 号 激 活
+
${username},您好:
+
感谢注册 ${appName}(${appUrl}),在继续使用之前,我们需要确定您的电子邮箱地址的有效性,请在 + 两小时内 点击下面的按钮帮助我们验证: +
+ +
如果以上按钮无法点击,请复制此链接到浏览器地址栏中访问:${verifyUrl} +
+
此邮件由系统自动发送,请勿回复!
+
+
+ + \ No newline at end of file diff --git a/src/test/kotlin/top/fatweb/api/FatWebApiApplicationTests.kt b/src/test/kotlin/top/fatweb/api/FatWebApiApplicationTests.kt deleted file mode 100644 index 5ed443f..0000000 --- a/src/test/kotlin/top/fatweb/api/FatWebApiApplicationTests.kt +++ /dev/null @@ -1,23 +0,0 @@ -package top.fatweb.api - -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test -import org.junit.jupiter.api.extension.ExtendWith -import org.springframework.test.context.junit.jupiter.SpringExtension -import top.fatweb.api.constant.SecurityConstants -import top.fatweb.api.util.JwtUtil - -@ExtendWith(SpringExtension::class) -class FatWebApiApplicationTests { - - @Test - fun removePrefixTest() { - assertEquals("12312", "Bearer 12312".removePrefix(SecurityConstants.tokenPrefix)) - } - - @Test - fun jwtTest() { - val jwt = JwtUtil.createJwt("User") - assertEquals("User", jwt?.let { JwtUtil.parseJwt(it).subject }) - } -} diff --git a/src/test/kotlin/top/fatweb/oxygen/api/OxygenApiApplicationTests.kt b/src/test/kotlin/top/fatweb/oxygen/api/OxygenApiApplicationTests.kt new file mode 100644 index 0000000..660eae7 --- /dev/null +++ b/src/test/kotlin/top/fatweb/oxygen/api/OxygenApiApplicationTests.kt @@ -0,0 +1,54 @@ +package top.fatweb.oxygen.api + +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith +import org.slf4j.Logger +import org.slf4j.LoggerFactory +import org.springframework.test.context.junit.jupiter.SpringExtension +import top.fatweb.oxygen.api.properties.SecurityProperties +import top.fatweb.oxygen.api.util.ByteUtil +import top.fatweb.oxygen.api.util.JwtUtil +import top.fatweb.oxygen.api.util.StrUtil + + +@ExtendWith(SpringExtension::class) +class OxygenApiApplicationTests { + private val logger: Logger = LoggerFactory.getLogger(this::class.java) + + @Test + fun removePrefixTest() { + assertEquals("12312", "Bearer 12312".removePrefix(SecurityProperties.tokenPrefix)) + } + + @Test + fun jwtTest() { + val jwt = JwtUtil.createJwt("User") + assertEquals("User", jwt?.let { JwtUtil.parseJwt(it).subject }) + } + + /* + @Test + fun generatePassword() { + val passwordEncoder = BCryptPasswordEncoder() + logger.info(passwordEncoder.encode("admin@dev")) + } + */ + + @Test + fun byteUtilTest() { + assertEquals("512B", ByteUtil.formatByteSize(512)) + assertEquals("512KiB", ByteUtil.formatByteSize(512 * 1024)) + assertEquals("1.5MiB", ByteUtil.formatByteSize(1 * 1024 * 1024 + 512 * 1024)) + } + + @Test + fun upperToUnderLetterTest() { + assertEquals("create_time", StrUtil.upperToUnderLetter("createTime")) + } + + @Test + fun underToUpperLetterTest() { + assertEquals("createTime", StrUtil.underToUpperLetter("create_time")) + } +}