Add tool upgrade api

This commit is contained in:
2024-01-30 19:24:44 +08:00
parent 835fa7c27f
commit 7aca58f1de
10 changed files with 226 additions and 58 deletions

View File

@@ -2,14 +2,12 @@ package top.fatweb.oxygen.api.controller.tool
import io.swagger.v3.oas.annotations.Operation
import jakarta.validation.Valid
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.RequestBody
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.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
@@ -79,6 +77,17 @@ class EditController(
fun create(@RequestBody @Valid toolCreateParam: ToolCreateParam): ResponseResult<ToolVo> =
ResponseResult.databaseSuccess(ResponseCode.DATABASE_INSERT_SUCCESS, data = editService.create(toolCreateParam))
/**
* Upgrade tool
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Operation(summary = "更新工具")
@PatchMapping
fun upgrade(@RequestBody @Valid toolUpgradeParam: ToolUpgradeParam): ResponseResult<ToolVo> =
ResponseResult.databaseSuccess(ResponseCode.DATABASE_UPDATE_SUCCESS, data = editService.upgrade(toolUpgradeParam))
/**
* Get personal tool
*
@@ -103,4 +112,16 @@ class EditController(
ResponseCode.DATABASE_SELECT_SUCCESS,
data = editService.detail(username, toolId, ver)
)
/**
* Delete tool
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Operation(summary = "删除工具")
@DeleteMapping("/{id}")
fun delete(@PathVariable id: Long): ResponseResult<Nothing> =
if (editService.delete(id)) ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS)
else ResponseResult.databaseFail(ResponseCode.DATABASE_DELETE_FAILED)
}

View File

@@ -31,6 +31,14 @@ enum class BusinessCode(val code: Int) {
*/
DATABASE(300),
/**
* Tool
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
TOOL(400),
/**
* Avatar API
*

View File

@@ -58,6 +58,8 @@ enum class ResponseCode(val code: Int) {
DATABASE_DUPLICATE_KEY(BusinessCode.DATABASE, 51),
DATABASE_NO_RECORD_FOUND(BusinessCode.DATABASE, 52),
TOOL_ILLEGAL_VERSION(BusinessCode.TOOL, 50),
API_AVATAR_SUCCESS(BusinessCode.API_AVATAR, 0),
API_AVATAR_ERROR(BusinessCode.API_AVATAR, 50);

View File

@@ -0,0 +1,3 @@
package top.fatweb.oxygen.api.exception
class IllegalVersionException : RuntimeException("Illegal Version")

View File

@@ -211,6 +211,12 @@ class ExceptionHandler {
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)
}
/* Other */
is MatchSensitiveWordException -> {
logger.debug(e.localizedMessage, e)

View File

@@ -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 '<number>.<number>.<number>'")
val ver: String?
)

View File

@@ -99,7 +99,7 @@ class AuthenticationServiceImpl(
@Transactional
override fun resend() {
val user = userService.getById(WebUtil.getLoginUserId()) ?: throw AccessDeniedException("Access Denied")
val user = userService.getById(WebUtil.getLoginUserId())
user.verify ?: throw NoVerificationRequiredException()
@@ -124,7 +124,7 @@ class AuthenticationServiceImpl(
@EventLogRecord(EventLog.Event.VERIFY)
@Transactional
override fun verify(verifyParam: VerifyParam) {
val user = userService.getById(WebUtil.getLoginUserId()) ?: throw AccessDeniedException("Access Denied")
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

View File

@@ -4,6 +4,7 @@ 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
@@ -51,6 +52,7 @@ interface IEditService : IService<Tool> {
/**
* Get tool by ID
*
* @param
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@@ -64,6 +66,16 @@ interface IEditService : IService<Tool> {
*/
fun create(toolCreateParam: ToolCreateParam): ToolVo
/**
* Upgrade tool
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see ToolUpgradeParam
* @see ToolVo
*/
fun upgrade(toolUpgradeParam: ToolUpgradeParam): ToolVo
/**
* Update tool
*
@@ -87,4 +99,12 @@ interface IEditService : IService<Tool> {
* @since 1.0.0
*/
fun detail(username: String, toolId: String, ver: String): ToolVo
/**
* Delete tool
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
fun delete(id: Long): Boolean
}

View File

@@ -2,17 +2,19 @@ package top.fatweb.oxygen.api.service.tool.impl
import com.baomidou.mybatisplus.extension.kotlin.KtQueryWrapper
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.IllegalVersionException
import top.fatweb.oxygen.api.exception.NoRecordFoundException
import top.fatweb.oxygen.api.exception.UserNotFoundException
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
@@ -49,11 +51,15 @@ class EditServiceImpl(
.map(ToolCategoryConverter::toolCategoryToToolCategoryVo)
override fun getOne(id: Long): ToolVo =
baseMapper.selectOne(id, WebUtil.getLoginUserId() ?: throw UserNotFoundException())
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 = "" }
@@ -65,11 +71,12 @@ class EditServiceImpl(
icon = toolCreateParam.icon
description = toolCreateParam.description
baseId = template.base!!.id
authorId = WebUtil.getLoginUserId() ?: throw UserNotFoundException()
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)
@@ -85,13 +92,60 @@ class EditServiceImpl(
return this.getOne(tool.id!!)
}
@Transactional
override fun upgrade(toolUpgradeParam: ToolUpgradeParam): ToolVo {
val originalTool = this.detail("!", toolUpgradeParam.toolId!!, "latest")
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 {
TODO("Not yet implemented")
}
override fun get(): List<ToolVo> =
baseMapper.selectPersonal(WebUtil.getLoginUserId() ?: throw UserNotFoundException())
baseMapper.selectPersonal(WebUtil.getLoginUserId()!!)
.map(ToolConverter::toolToToolVo)
override fun detail(username: String, toolId: String, ver: String): ToolVo {
@@ -102,4 +156,16 @@ class EditServiceImpl(
return baseMapper.detail(username, toolId, ver, WebUtil.getLoginUsername())?.let(ToolConverter::toolToToolVo)
?: throw NoRecordFoundException()
}
@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)
}
}