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 io.swagger.v3.oas.annotations.Operation
import jakarta.validation.Valid import jakarta.validation.Valid
import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.*
import org.springframework.web.bind.annotation.PathVariable
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.annotation.BaseController
import top.fatweb.oxygen.api.entity.common.ResponseCode import top.fatweb.oxygen.api.entity.common.ResponseCode
import top.fatweb.oxygen.api.entity.common.ResponseResult import top.fatweb.oxygen.api.entity.common.ResponseResult
import top.fatweb.oxygen.api.param.tool.ToolCreateParam 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.service.tool.IEditService
import top.fatweb.oxygen.api.vo.tool.ToolCategoryVo import top.fatweb.oxygen.api.vo.tool.ToolCategoryVo
import top.fatweb.oxygen.api.vo.tool.ToolTemplateVo import top.fatweb.oxygen.api.vo.tool.ToolTemplateVo
@@ -79,6 +77,17 @@ class EditController(
fun create(@RequestBody @Valid toolCreateParam: ToolCreateParam): ResponseResult<ToolVo> = fun create(@RequestBody @Valid toolCreateParam: ToolCreateParam): ResponseResult<ToolVo> =
ResponseResult.databaseSuccess(ResponseCode.DATABASE_INSERT_SUCCESS, data = editService.create(toolCreateParam)) 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 * Get personal tool
* *
@@ -103,4 +112,16 @@ class EditController(
ResponseCode.DATABASE_SELECT_SUCCESS, ResponseCode.DATABASE_SELECT_SUCCESS,
data = editService.detail(username, toolId, ver) 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), DATABASE(300),
/**
* Tool
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
TOOL(400),
/** /**
* Avatar API * Avatar API
* *

View File

@@ -58,6 +58,8 @@ enum class ResponseCode(val code: Int) {
DATABASE_DUPLICATE_KEY(BusinessCode.DATABASE, 51), DATABASE_DUPLICATE_KEY(BusinessCode.DATABASE, 51),
DATABASE_NO_RECORD_FOUND(BusinessCode.DATABASE, 52), DATABASE_NO_RECORD_FOUND(BusinessCode.DATABASE, 52),
TOOL_ILLEGAL_VERSION(BusinessCode.TOOL, 50),
API_AVATAR_SUCCESS(BusinessCode.API_AVATAR, 0), API_AVATAR_SUCCESS(BusinessCode.API_AVATAR, 0),
API_AVATAR_ERROR(BusinessCode.API_AVATAR, 50); 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) 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 */ /* Other */
is MatchSensitiveWordException -> { is MatchSensitiveWordException -> {
logger.debug(e.localizedMessage, e) 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 @Transactional
override fun resend() { override fun resend() {
val user = userService.getById(WebUtil.getLoginUserId()) ?: throw AccessDeniedException("Access Denied") val user = userService.getById(WebUtil.getLoginUserId())
user.verify ?: throw NoVerificationRequiredException() user.verify ?: throw NoVerificationRequiredException()
@@ -124,7 +124,7 @@ class AuthenticationServiceImpl(
@EventLogRecord(EventLog.Event.VERIFY) @EventLogRecord(EventLog.Event.VERIFY)
@Transactional @Transactional
override fun verify(verifyParam: VerifyParam) { 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() user.verify ?: throw NoVerificationRequiredException()
if (LocalDateTime.ofInstant(Instant.ofEpochMilli(user.verify!!.split("-").first().toLong()), ZoneOffset.UTC) if (LocalDateTime.ofInstant(Instant.ofEpochMilli(user.verify!!.split("-").first().toLong()), ZoneOffset.UTC)
.isBefore(LocalDateTime.now(ZoneOffset.UTC).minusHours(2)) || user.verify != verifyParam.code .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.entity.tool.Tool
import top.fatweb.oxygen.api.param.tool.ToolCreateParam import top.fatweb.oxygen.api.param.tool.ToolCreateParam
import top.fatweb.oxygen.api.param.tool.ToolUpdateParam 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.ToolCategoryVo
import top.fatweb.oxygen.api.vo.tool.ToolTemplateVo import top.fatweb.oxygen.api.vo.tool.ToolTemplateVo
import top.fatweb.oxygen.api.vo.tool.ToolVo import top.fatweb.oxygen.api.vo.tool.ToolVo
@@ -51,6 +52,7 @@ interface IEditService : IService<Tool> {
/** /**
* Get tool by ID * Get tool by ID
* *
* @param
* @author FatttSnake, fatttsnake@gmail.com * @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0 * @since 1.0.0
*/ */
@@ -64,6 +66,16 @@ interface IEditService : IService<Tool> {
*/ */
fun create(toolCreateParam: ToolCreateParam): ToolVo 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 * Update tool
* *
@@ -87,4 +99,12 @@ interface IEditService : IService<Tool> {
* @since 1.0.0 * @since 1.0.0
*/ */
fun detail(username: String, toolId: String, ver: String): ToolVo 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.kotlin.KtQueryWrapper
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
import org.springframework.dao.DuplicateKeyException
import org.springframework.stereotype.Service import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional import org.springframework.transaction.annotation.Transactional
import top.fatweb.oxygen.api.converter.tool.ToolCategoryConverter import top.fatweb.oxygen.api.converter.tool.ToolCategoryConverter
import top.fatweb.oxygen.api.converter.tool.ToolConverter import top.fatweb.oxygen.api.converter.tool.ToolConverter
import top.fatweb.oxygen.api.converter.tool.ToolTemplateConverter import top.fatweb.oxygen.api.converter.tool.ToolTemplateConverter
import top.fatweb.oxygen.api.entity.tool.* 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.NoRecordFoundException
import top.fatweb.oxygen.api.exception.UserNotFoundException
import top.fatweb.oxygen.api.mapper.tool.EditMapper import top.fatweb.oxygen.api.mapper.tool.EditMapper
import top.fatweb.oxygen.api.param.tool.ToolCreateParam import top.fatweb.oxygen.api.param.tool.ToolCreateParam
import top.fatweb.oxygen.api.param.tool.ToolUpdateParam 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.service.tool.*
import top.fatweb.oxygen.api.util.WebUtil import top.fatweb.oxygen.api.util.WebUtil
import top.fatweb.oxygen.api.vo.tool.ToolCategoryVo import top.fatweb.oxygen.api.vo.tool.ToolCategoryVo
@@ -49,11 +51,15 @@ class EditServiceImpl(
.map(ToolCategoryConverter::toolCategoryToToolCategoryVo) .map(ToolCategoryConverter::toolCategoryToToolCategoryVo)
override fun getOne(id: Long): ToolVo = override fun getOne(id: Long): ToolVo =
baseMapper.selectOne(id, WebUtil.getLoginUserId() ?: throw UserNotFoundException()) baseMapper.selectOne(id, WebUtil.getLoginUserId()!!)
?.let(ToolConverter::toolToToolVo) ?: throw NoRecordFoundException() ?.let(ToolConverter::toolToToolVo) ?: throw NoRecordFoundException()
@Transactional @Transactional
override fun create(toolCreateParam: ToolCreateParam): ToolVo { 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 template = this.getTemplate(toolCreateParam.templateId!!)
val newSource = ToolData().apply { data = template.source!!.data } val newSource = ToolData().apply { data = template.source!!.data }
val newDist = ToolData().apply { data = "" } val newDist = ToolData().apply { data = "" }
@@ -65,11 +71,12 @@ class EditServiceImpl(
icon = toolCreateParam.icon icon = toolCreateParam.icon
description = toolCreateParam.description description = toolCreateParam.description
baseId = template.base!!.id baseId = template.base!!.id
authorId = WebUtil.getLoginUserId() ?: throw UserNotFoundException() authorId = WebUtil.getLoginUserId()!!
ver = toolCreateParam.ver!!.split(".").map(String::toLong).joinToString(".") ver = toolCreateParam.ver!!.split(".").map(String::toLong).joinToString(".")
keywords = toolCreateParam.keywords keywords = toolCreateParam.keywords
sourceId = newSource.id sourceId = newSource.id
distId = newDist.id distId = newDist.id
entryPoint = template.entryPoint
} }
this.save(tool) this.save(tool)
@@ -85,13 +92,60 @@ class EditServiceImpl(
return this.getOne(tool.id!!) 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 @Transactional
override fun update(toolUpdateParam: ToolUpdateParam): ToolVo { override fun update(toolUpdateParam: ToolUpdateParam): ToolVo {
TODO("Not yet implemented") TODO("Not yet implemented")
} }
override fun get(): List<ToolVo> = override fun get(): List<ToolVo> =
baseMapper.selectPersonal(WebUtil.getLoginUserId() ?: throw UserNotFoundException()) baseMapper.selectPersonal(WebUtil.getLoginUserId()!!)
.map(ToolConverter::toolToToolVo) .map(ToolConverter::toolToToolVo)
override fun detail(username: String, toolId: String, ver: String): ToolVo { 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) return baseMapper.detail(username, toolId, ver, WebUtil.getLoginUsername())?.let(ToolConverter::toolToToolVo)
?: throw NoRecordFoundException() ?: 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)
}
} }

View File

@@ -125,7 +125,7 @@
on tbtc.id = trtmc.category_id on tbtc.id = trtmc.category_id
where t_b_tool_main.deleted = 0 where t_b_tool_main.deleted = 0
and t_b_tool_main.author_id = #{userId} and t_b_tool_main.author_id = #{userId}
order by t_b_tool_main.tool_id desc order by t_b_tool_main.id desc
</select> </select>
<select id="detail" resultMap="toolWithDataMap"> <select id="detail" resultMap="toolWithDataMap">
@@ -208,9 +208,11 @@
</choose> </choose>
</where> </where>
order by t_b_tool_main.id desc order by t_b_tool_main.id desc
limit 1
</select> </select>
<resultMap id="toolTemplateWithBaseDataMap" type="toolTemplate" extends="top.fatweb.oxygen.api.mapper.tool.ToolTemplateMapper.toolTemplateWithDataMap"> <resultMap id="toolTemplateWithBaseDataMap" type="toolTemplate"
extends="top.fatweb.oxygen.api.mapper.tool.ToolTemplateMapper.toolTemplateWithDataMap">
<association property="base"> <association property="base">
<id property="id" column="tool_template_base_id"/> <id property="id" column="tool_template_base_id"/>
<result property="name" column="tool_template_base_name"/> <result property="name" column="tool_template_base_name"/>
@@ -236,8 +238,9 @@
<result property="createTime" column="tool_create_time"/> <result property="createTime" column="tool_create_time"/>
<result property="deleted" column="tool_deleted"/> <result property="deleted" column="tool_deleted"/>
<result property="version" column="tool_version"/> <result property="version" column="tool_version"/>
<collection property="keywords" ofType="string" column="tool_keywords"/> <result property="keywords" column="tool_keywords" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
<collection property="categories" resultMap="top.fatweb.oxygen.api.mapper.tool.ToolCategoryMapper.toolCategoryMap"/> <collection property="categories"
resultMap="top.fatweb.oxygen.api.mapper.tool.ToolCategoryMapper.toolCategoryMap"/>
</resultMap> </resultMap>
<resultMap id="toolWithAuthor" type="tool" extends="toolMap"> <resultMap id="toolWithAuthor" type="tool" extends="toolMap">