Implement update tool

This commit is contained in:
2024-02-01 16:51:20 +08:00
parent 1ce60d1bfb
commit 04587fbb7a
27 changed files with 204 additions and 75 deletions

View File

@@ -7,6 +7,7 @@ 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
@@ -83,10 +84,13 @@ class EditController(
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Operation(summary = "更新工具")
@Operation(summary = "升级工具")
@PatchMapping
fun upgrade(@RequestBody @Valid toolUpgradeParam: ToolUpgradeParam): ResponseResult<ToolVo> =
ResponseResult.databaseSuccess(ResponseCode.DATABASE_UPDATE_SUCCESS, data = editService.upgrade(toolUpgradeParam))
ResponseResult.databaseSuccess(
ResponseCode.DATABASE_UPDATE_SUCCESS,
data = editService.upgrade(toolUpgradeParam)
)
/**
* Get personal tool
@@ -113,6 +117,17 @@ class EditController(
data = editService.detail(username, toolId, ver)
)
/**
* Update tool
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Operation(summary = "更新工具")
@PutMapping
fun update(@RequestBody @Valid toolUpdateParam: ToolUpdateParam) =
ResponseResult.databaseSuccess(ResponseCode.DATABASE_UPDATE_SUCCESS, data = editService.update(toolUpdateParam))
/**
* Delete tool
*

View File

@@ -59,6 +59,9 @@ enum class ResponseCode(val code: Int) {
DATABASE_NO_RECORD_FOUND(BusinessCode.DATABASE, 52),
TOOL_ILLEGAL_VERSION(BusinessCode.TOOL, 50),
TOOL_UNDER_REVIEW(BusinessCode.TOOL, 51),
TOOL_HAS_UNPUBLISHED_VERSION(BusinessCode.TOOL, 52),
TOOL_HAS_BEEN_PUBLISHED(BusinessCode.TOOL, 53),
API_AVATAR_SUCCESS(BusinessCode.API_AVATAR, 0),
API_AVATAR_ERROR(BusinessCode.API_AVATAR, 50);

View File

@@ -1,3 +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)

View File

@@ -1,3 +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)

View File

@@ -1,3 +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)

View File

@@ -1,3 +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)

View File

@@ -1,3 +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")

View File

@@ -1,3 +1,10 @@
package top.fatweb.oxygen.api.exception
class MatchSensitiveWordException: RuntimeException("Match sensitive word")
/**
* Match sensitive word exception
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see RuntimeException
*/
class MatchSensitiveWordException : RuntimeException("Match sensitive word")

View File

@@ -5,5 +5,6 @@ package top.fatweb.oxygen.api.exception
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see RuntimeException
*/
class RequestTooFrequent: RuntimeException("Request too frequent")
class RequestTooFrequentException: RuntimeException("Request too frequent")

View File

@@ -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")

View File

@@ -1,3 +0,0 @@
package top.fatweb.oxygen.api.exception
class ToolHasPublish : RuntimeException("The tool has been published and cannot be modified")

View File

@@ -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")

View File

@@ -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")

View File

@@ -61,7 +61,7 @@ class ExceptionHandler {
ResponseResult.fail(ResponseCode.SYSTEM_ARGUMENT_NOT_VALID, errorMessage, null)
}
is RequestTooFrequent -> {
is RequestTooFrequentException -> {
logger.debug(e.localizedMessage, e)
ResponseResult.fail(ResponseCode.SYSTEM_REQUEST_TOO_FREQUENT, e.localizedMessage, null)
}
@@ -217,6 +217,21 @@ class ExceptionHandler {
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 ToolHasUnpublishedVersionException -> {
logger.debug(e.localizedMessage, e)
ResponseResult.fail(ResponseCode.TOOL_HAS_UNPUBLISHED_VERSION, 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)

View File

@@ -27,5 +27,5 @@ interface EditMapper : BaseMapper<Tool> {
@Param("toolId") toolId: String,
@Param("ver") ver: String,
@Param("operator") operator: String?
): Tool?
): List<Tool>?
}

View File

@@ -1,6 +1,7 @@
package top.fatweb.oxygen.api.param.permission.group
import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.constraints.NotEmpty
/**
* Delete group parameters
@@ -17,5 +18,6 @@ data class GroupDeleteParam(
* @since 1.0.0
*/
@Schema(description = "用户组 ID 列表", required = true)
val ids: List<Long>
@field: NotEmpty(message = "Ids can not be empty")
val ids: List<Long>?
)

View File

@@ -1,6 +1,7 @@
package top.fatweb.oxygen.api.param.permission.role
import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.constraints.NotEmpty
/**
* Delete role parameters
@@ -17,5 +18,6 @@ data class RoleDeleteParam(
* @since 1.0.0
*/
@Schema(description = "角色 ID 列表", required = true)
val ids: List<Long>
@field: NotEmpty(message = "Ids can not be empty")
val ids: List<Long>?
)

View File

@@ -1,6 +1,7 @@
package top.fatweb.oxygen.api.param.permission.user
import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.constraints.NotEmpty
/**
* Delete user parameters
@@ -17,5 +18,6 @@ data class UserDeleteParam(
* @since 1.0.0
*/
@Schema(description = "用户 ID 列表", required = true)
val ids: List<Long>
@field: NotEmpty(message = "Ids can not be empty")
val ids: List<Long>?
)

View File

@@ -86,7 +86,7 @@ data class ToolCreateParam(
*/
@Schema(description = "关键词", required = true)
@field: NotEmpty(message = "Keywords can not be empty")
val keywords: List<String>,
val keywords: List<String>?,
/**
* Categories
@@ -96,5 +96,5 @@ data class ToolCreateParam(
*/
@Schema(description = "类别", required = true)
@field: NotEmpty(message = "Categories can not be empty")
val categories: List<Long>
val categories: List<Long>?
)

View File

@@ -2,7 +2,6 @@ package top.fatweb.oxygen.api.param.tool
import io.swagger.v3.oas.annotations.media.Schema
import jakarta.validation.constraints.NotNull
import jakarta.validation.constraints.Pattern
/**
* Update tool parameters
@@ -10,6 +9,7 @@ import jakarta.validation.constraints.Pattern
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(description = "更新工具请求参数")
data class ToolUpdateParam(
/**
* ID
@@ -31,17 +31,13 @@ data class ToolUpdateParam(
val name: String?,
/**
* Tool ID
* Icon
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(description = "工具唯一 ID", example = "tool_a")
@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?,
@Schema(description = "图标")
val icon: String?,
/**
* Description
@@ -52,34 +48,6 @@ data class ToolUpdateParam(
@Schema(description = "简介")
val description: String?,
/**
* Author ID
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(description = "作者 ID")
val authorId: Long?,
/**
* Version
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(description = "版本", example = "1.0.3")
@field: Pattern(regexp = "^\\d+\\.\\d+\\.\\d+\$", message = "Ver can only match '<number>.<number>.<number>'")
val ver: String?,
/**
* Privately
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(description = "私有", allowableValues = ["true", "false"])
val privately: Boolean?,
/**
* Keywords
*
@@ -87,7 +55,7 @@ data class ToolUpdateParam(
* @since 1.0.0
*/
@Schema(description = "关键词")
val keywords: List<String>,
val keywords: List<String>?,
/**
* Categories
@@ -96,7 +64,7 @@ data class ToolUpdateParam(
* @since 1.0.0
*/
@Schema(description = "类别")
val categories: List<Long>,
val categories: List<Long>?,
/**
* Source
@@ -105,14 +73,5 @@ data class ToolUpdateParam(
* @since 1.0.0
*/
@Schema(description = "源码")
val source: String?,
/**
* Dist
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(description = "产物")
val dist: String?
val source: String?
)

View File

@@ -10,7 +10,7 @@ import jakarta.validation.constraints.Pattern
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(description = "更新工具请求参数")
@Schema(description = "升级工具请求参数")
data class ToolUpgradeParam(
/**
* Tool ID

View File

@@ -106,7 +106,7 @@ class AuthenticationServiceImpl(
if (LocalDateTime.ofInstant(Instant.ofEpochMilli(user.verify!!.split("-").first().toLong()), ZoneOffset.UTC)
.isAfter(LocalDateTime.now(ZoneOffset.UTC).minusMinutes(5))
) {
throw RequestTooFrequent()
throw RequestTooFrequentException()
}
user.verify =
@@ -158,7 +158,7 @@ class AuthenticationServiceImpl(
if (LocalDateTime.ofInstant(Instant.ofEpochMilli(it.split("-").first().toLong()), ZoneOffset.UTC)
.isAfter(LocalDateTime.now(ZoneOffset.UTC).minusMinutes(5))
) {
throw RequestTooFrequent()
throw RequestTooFrequentException()
}
}

View File

@@ -144,7 +144,7 @@ class GroupServiceImpl(
override fun delete(groupDeleteParam: GroupDeleteParam) {
baseMapper.deleteBatchIds(groupDeleteParam.ids)
rRoleGroupService.remove(KtQueryWrapper(RRoleGroup()).`in`(RRoleGroup::groupId, groupDeleteParam.ids))
offlineUser(*groupDeleteParam.ids.toLongArray())
offlineUser(*groupDeleteParam.ids!!.toLongArray())
}
private fun offlineUser(vararg groupIds: Long) {

View File

@@ -151,7 +151,7 @@ class RoleServiceImpl(
override fun delete(roleDeleteParam: RoleDeleteParam) {
baseMapper.deleteBatchIds(roleDeleteParam.ids)
rPowerRoleService.remove(KtQueryWrapper(RPowerRole()).`in`(RPowerRole::roleId, roleDeleteParam.ids))
offlineUser(*roleDeleteParam.ids.toLongArray())
offlineUser(*roleDeleteParam.ids!!.toLongArray())
}
private fun getFullPowerIds(powerIds: List<Long>): Set<Long> {

View File

@@ -276,7 +276,7 @@ class UserServiceImpl(
@Transactional
override fun delete(userDeleteParam: UserDeleteParam) {
val ids = userDeleteParam.ids.filter { it != 0L }
val ids = userDeleteParam.ids!!.filter { it != 0L }
if (ids.isEmpty()) {
return
}

View File

@@ -9,8 +9,7 @@ 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.*
import top.fatweb.oxygen.api.mapper.tool.EditMapper
import top.fatweb.oxygen.api.param.tool.ToolCreateParam
import top.fatweb.oxygen.api.param.tool.ToolUpdateParam
@@ -81,7 +80,7 @@ class EditServiceImpl(
this.save(tool)
toolCreateParam.categories.forEach {
toolCreateParam.categories!!.forEach {
toolCategoryService.getById(it) ?: throw NoRecordFoundException()
rToolCategoryService.save(RToolCategory().apply {
toolId = tool.id
@@ -95,6 +94,12 @@ class EditServiceImpl(
@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(".")
@@ -141,7 +146,57 @@ class EditServiceImpl(
@Transactional
override fun update(toolUpdateParam: ToolUpdateParam): ToolVo {
TODO("Not yet implemented")
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<Long>()
val removeCategories = HashSet<Long>()
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
})
}
toolDataService.updateById(ToolData().apply {
id = tool.sourceId
data = toolUpdateParam.source
})
}
return this.getOne(tool.id!!)
}
override fun get(): List<ToolVo> =
@@ -152,9 +207,12 @@ class EditServiceImpl(
if (username == "!" && WebUtil.getLoginUserId() == null) {
throw NoRecordFoundException()
}
val toolList = baseMapper.detail(username, toolId, ver, WebUtil.getLoginUsername())
if (toolList.isNullOrEmpty()) {
throw NoRecordFoundException()
}
return baseMapper.detail(username, toolId, ver, WebUtil.getLoginUsername())?.let(ToolConverter::toolToToolVo)
?: throw NoRecordFoundException()
return toolList.first().let(ToolConverter::toolToToolVo)
}
@Transactional