Add sensitive word filter

This commit is contained in:
2024-01-04 17:55:41 +08:00
parent f3b63ce17d
commit 3b9111392e
21 changed files with 466 additions and 9 deletions

View File

@@ -3,18 +3,21 @@ package top.fatweb.oxygen.api.controller.system
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.security.access.prepost.PreAuthorize 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.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.PutMapping import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.RequestBody 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.ResponseResult import top.fatweb.oxygen.api.entity.common.ResponseResult
import top.fatweb.oxygen.api.param.system.BaseSettingsParam import top.fatweb.oxygen.api.param.system.*
import top.fatweb.oxygen.api.param.system.MailSendParam import top.fatweb.oxygen.api.service.system.ISensitiveWordService
import top.fatweb.oxygen.api.param.system.MailSettingsParam
import top.fatweb.oxygen.api.service.system.ISettingsService import top.fatweb.oxygen.api.service.system.ISettingsService
import top.fatweb.oxygen.api.vo.system.BaseSettingsVo import top.fatweb.oxygen.api.vo.system.BaseSettingsVo
import top.fatweb.oxygen.api.vo.system.MailSettingsVo import top.fatweb.oxygen.api.vo.system.MailSettingsVo
import top.fatweb.oxygen.api.vo.system.SensitiveWordVo
/** /**
* System settings controller * System settings controller
@@ -25,7 +28,8 @@ import top.fatweb.oxygen.api.vo.system.MailSettingsVo
*/ */
@BaseController(path = ["/system/settings"], name = "系统设置", description = "系统设置相关接口") @BaseController(path = ["/system/settings"], name = "系统设置", description = "系统设置相关接口")
class SettingsController( class SettingsController(
private val settingsService: ISettingsService private val settingsService: ISettingsService,
private val sensitiveWordService: ISensitiveWordService
) { ) {
/** /**
* Get base settings * Get base settings
@@ -97,4 +101,58 @@ class SettingsController(
settingsService.sendMail(mailSendParam) settingsService.sendMail(mailSendParam)
return ResponseResult.success() return ResponseResult.success()
} }
/**
* Get sensitive word settings
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Operation(summary = "获取敏感词配置")
@GetMapping("/sensitive")
@PreAuthorize("hasAnyAuthority('system:settings:query:sensitive')")
fun getSensitive(): ResponseResult<List<SensitiveWordVo>> =
ResponseResult.databaseSuccess(ResponseCode.DATABASE_SELECT_SUCCESS, data = sensitiveWordService.get())
/**
* Add sensitive word
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Operation(summary = "添加敏感词")
@PostMapping("/sensitive")
@PreAuthorize("hasAnyAuthority('system:settings:modify:sensitive')")
fun addSensitive(@RequestBody @Valid sensitiveWordAddParam: SensitiveWordAddParam): ResponseResult<Nothing> {
sensitiveWordService.add(sensitiveWordAddParam)
return ResponseResult.databaseSuccess(ResponseCode.DATABASE_INSERT_SUCCESS)
}
/**
* Update sensitive word
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Operation(summary = "修改敏感词")
@PutMapping("/sensitive")
@PreAuthorize("hasAnyAuthority('system:settings:modify:sensitive')")
fun updateSensitive(@RequestBody sensitiveWordUpdateParam: SensitiveWordUpdateParam): ResponseResult<Nothing> {
sensitiveWordService.update(sensitiveWordUpdateParam)
return ResponseResult.databaseSuccess(ResponseCode.DATABASE_UPDATE_SUCCESS)
}
/**
* Delete sensitive word
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Operation(summary = "删除敏感词")
@DeleteMapping("/sensitive/{id}")
@PreAuthorize("hasAnyAuthority('system:settings:modify:sensitive')")
fun deleteSensitive(@PathVariable id: Long): ResponseResult<Nothing> {
sensitiveWordService.delete(id)
return ResponseResult.databaseSuccess(ResponseCode.DATABASE_DELETE_SUCCESS)
}
} }

View File

@@ -0,0 +1,26 @@
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 {
fun sensitiveWordToSensitiveWordVo(sensitiveWord: SensitiveWord) = SensitiveWordVo(
id = sensitiveWord.id,
word = sensitiveWord.word,
useFor = sensitiveWord.useFor?.map(SensitiveWord.Use::valueOf)?.toSet(),
enable = sensitiveWord.enable == 1
)
fun sensitiveWordAddParamToSensitiveWord(sensitiveWordAddParam: SensitiveWordAddParam) = SensitiveWord().apply {
word = sensitiveWordAddParam.word
useFor = sensitiveWordAddParam.useFor.map(SensitiveWord.Use::code).toSet()
enable = if (sensitiveWordAddParam.enable) 1 else 0
}
}

View File

@@ -15,6 +15,7 @@ enum class ResponseCode(val code: Int) {
SYSTEM_ARGUMENT_NOT_VALID(BusinessCode.SYSTEM, 53), SYSTEM_ARGUMENT_NOT_VALID(BusinessCode.SYSTEM, 53),
SYSTEM_INVALID_CAPTCHA_CODE(BusinessCode.SYSTEM, 54), SYSTEM_INVALID_CAPTCHA_CODE(BusinessCode.SYSTEM, 54),
SYSTEM_REQUEST_TOO_FREQUENT(BusinessCode.SYSTEM, 55), SYSTEM_REQUEST_TOO_FREQUENT(BusinessCode.SYSTEM, 55),
SYSTEM_MATCH_SENSITIVE_WORD(BusinessCode.SYSTEM, 56),
PERMISSION_LOGIN_SUCCESS(BusinessCode.PERMISSION, 0), PERMISSION_LOGIN_SUCCESS(BusinessCode.PERMISSION, 0),
PERMISSION_PASSWORD_CHANGE_SUCCESS(BusinessCode.PERMISSION, 1), PERMISSION_PASSWORD_CHANGE_SUCCESS(BusinessCode.PERMISSION, 1),

View File

@@ -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_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<String>? = 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)"
}
}

View File

@@ -0,0 +1,3 @@
package top.fatweb.oxygen.api.exception
class MatchSensitiveWordException: RuntimeException("Match sensitive word")

View File

@@ -8,6 +8,7 @@ import org.slf4j.LoggerFactory
import org.springframework.dao.DuplicateKeyException import org.springframework.dao.DuplicateKeyException
import org.springframework.http.converter.HttpMessageNotReadableException import org.springframework.http.converter.HttpMessageNotReadableException
import org.springframework.jdbc.BadSqlGrammarException import org.springframework.jdbc.BadSqlGrammarException
import org.springframework.jdbc.UncategorizedSQLException
import org.springframework.security.access.AccessDeniedException import org.springframework.security.access.AccessDeniedException
import org.springframework.security.authentication.* import org.springframework.security.authentication.*
import org.springframework.web.HttpRequestMethodNotSupportedException import org.springframework.web.HttpRequestMethodNotSupportedException
@@ -43,6 +44,7 @@ class ExceptionHandler {
@ExceptionHandler(value = [Exception::class]) @ExceptionHandler(value = [Exception::class])
fun exceptionHandler(e: Exception): ResponseResult<*> { fun exceptionHandler(e: Exception): ResponseResult<*> {
return when (e) { return when (e) {
/* Request */
is HttpRequestMethodNotSupportedException, is NoResourceFoundException -> { is HttpRequestMethodNotSupportedException, is NoResourceFoundException -> {
logger.debug(e.localizedMessage, e) logger.debug(e.localizedMessage, e)
ResponseResult.fail(ResponseCode.SYSTEM_REQUEST_ILLEGAL, e.localizedMessage, null) ResponseResult.fail(ResponseCode.SYSTEM_REQUEST_ILLEGAL, e.localizedMessage, null)
@@ -64,6 +66,7 @@ class ExceptionHandler {
ResponseResult.fail(ResponseCode.SYSTEM_REQUEST_TOO_FREQUENT, e.localizedMessage, null) ResponseResult.fail(ResponseCode.SYSTEM_REQUEST_TOO_FREQUENT, e.localizedMessage, null)
} }
/* Authentication */
is InsufficientAuthenticationException -> { is InsufficientAuthenticationException -> {
logger.debug(e.localizedMessage, e) logger.debug(e.localizedMessage, e)
ResponseResult.fail(ResponseCode.PERMISSION_UNAUTHORIZED, e.localizedMessage, null) ResponseResult.fail(ResponseCode.PERMISSION_UNAUTHORIZED, e.localizedMessage, null)
@@ -162,7 +165,7 @@ class ExceptionHandler {
ResponseResult.fail(ResponseCode.SYSTEM_INVALID_CAPTCHA_CODE, e.localizedMessage, null) ResponseResult.fail(ResponseCode.SYSTEM_INVALID_CAPTCHA_CODE, e.localizedMessage, null)
} }
/* SQL */
is BadSqlGrammarException -> { is BadSqlGrammarException -> {
logger.debug(e.localizedMessage, e) logger.debug(e.localizedMessage, e)
ResponseResult.fail(ResponseCode.DATABASE_EXECUTE_ERROR, "Incorrect SQL syntax", null) ResponseResult.fail(ResponseCode.DATABASE_EXECUTE_ERROR, "Incorrect SQL syntax", null)
@@ -178,6 +181,23 @@ class ExceptionHandler {
ResponseResult.fail(ResponseCode.DATABASE_NO_RECORD_FOUND, e.localizedMessage, null) 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)
}
/* Other */
is MatchSensitiveWordException -> {
logger.debug(e.localizedMessage, e)
ResponseResult.fail(ResponseCode.SYSTEM_MATCH_SENSITIVE_WORD, e.localizedMessage, null)
}
/* API */
is AvatarException -> { is AvatarException -> {
logger.debug(e.localizedMessage, e) logger.debug(e.localizedMessage, e)
ResponseResult.fail(ResponseCode.API_AVATAR_ERROR, e.localizedMessage, null) ResponseResult.fail(ResponseCode.API_AVATAR_ERROR, e.localizedMessage, null)

View File

@@ -0,0 +1,14 @@
package top.fatweb.oxygen.api.mapper.system
import com.baomidou.mybatisplus.core.mapper.BaseMapper
import org.apache.ibatis.annotations.Mapper
import top.fatweb.oxygen.api.entity.system.SensitiveWord
/**
* Sensitive word mapper
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Mapper
interface SensitiveWordMapper : BaseMapper<SensitiveWord>

View File

@@ -54,7 +54,7 @@ open class AvatarBaseParam {
* @author FatttSnake, fatttsnake@gmail.com * @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0 * @since 1.0.0
*/ */
@Schema(defaultValue = "颜色列表", example = "#FFFFFFAA") @Schema(description = "颜色列表", example = "#FFFFFFAA")
var colors: List<String>? = null var colors: List<String>? = null
/** /**
@@ -63,7 +63,7 @@ open class AvatarBaseParam {
* @author FatttSnake, fatttsnake@gmail.com * @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0 * @since 1.0.0
*/ */
@Schema(defaultValue = "背景颜色", example = "#FFFFFFAA") @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") @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 var background: String? = null
} }

View File

@@ -10,6 +10,7 @@ import io.swagger.v3.oas.annotations.media.Schema
* @author FatttSnake, fatttsnake@gmail.com * @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0 * @since 1.0.0
*/ */
@Schema(description = "用户活跃信息请求参数")
data class ActiveInfoGetParam( data class ActiveInfoGetParam(
/** /**
* Scope * Scope

View File

@@ -10,6 +10,7 @@ import io.swagger.v3.oas.annotations.media.Schema
* @author FatttSnake, fatttsnake@gmail.com * @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0 * @since 1.0.0
*/ */
@Schema(description = "在线信息请求参数")
data class OnlineInfoGetParam( data class OnlineInfoGetParam(
/** /**
* Scope * Scope

View File

@@ -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<SensitiveWord.Use> = emptySet(),
/**
* Enable
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(description = "启用", allowableValues = ["true", "false"], defaultValue = "true")
val enable: Boolean = true
)

View File

@@ -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<Long> = emptySet()
)

View File

@@ -26,6 +26,7 @@ import top.fatweb.oxygen.api.service.api.v1.IAvatarService
import top.fatweb.oxygen.api.service.permission.IAuthenticationService import top.fatweb.oxygen.api.service.permission.IAuthenticationService
import top.fatweb.oxygen.api.service.permission.IUserInfoService import top.fatweb.oxygen.api.service.permission.IUserInfoService
import top.fatweb.oxygen.api.service.permission.IUserService 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.BaseSettings
import top.fatweb.oxygen.api.settings.SettingsOperator import top.fatweb.oxygen.api.settings.SettingsOperator
import top.fatweb.oxygen.api.util.JwtUtil import top.fatweb.oxygen.api.util.JwtUtil
@@ -60,6 +61,7 @@ class AuthenticationServiceImpl(
private val turnstileApi: TurnstileApi, private val turnstileApi: TurnstileApi,
private val userService: IUserService, private val userService: IUserService,
private val userInfoService: IUserInfoService, private val userInfoService: IUserInfoService,
private val sensitiveWordService: ISensitiveWordService,
private val avatarService: IAvatarService private val avatarService: IAvatarService
) : IAuthenticationService { ) : IAuthenticationService {
private val logger: Logger = LoggerFactory.getLogger(this::class.java) private val logger: Logger = LoggerFactory.getLogger(this::class.java)
@@ -68,6 +70,7 @@ class AuthenticationServiceImpl(
@Transactional @Transactional
override fun register(request: HttpServletRequest, registerParam: RegisterParam): RegisterVo { override fun register(request: HttpServletRequest, registerParam: RegisterParam): RegisterVo {
verifyCaptcha(registerParam.captchaCode!!) verifyCaptcha(registerParam.captchaCode!!)
sensitiveWordService.checkSensitiveWord(registerParam.username!!)
val user = User().apply { val user = User().apply {
username = registerParam.username username = registerParam.username
@@ -132,6 +135,7 @@ class AuthenticationServiceImpl(
if (verifyParam.nickname.isNullOrBlank() || verifyParam.avatar.isNullOrBlank()) { if (verifyParam.nickname.isNullOrBlank() || verifyParam.avatar.isNullOrBlank()) {
throw AccountNeedInitException() throw AccountNeedInitException()
} }
sensitiveWordService.checkSensitiveWord(verifyParam.nickname)
userService.update( userService.update(
KtUpdateWrapper(User()).eq(User::id, user.id).set(User::verify, null) KtUpdateWrapper(User()).eq(User::id, user.id).set(User::verify, null)

View File

@@ -11,5 +11,12 @@ import top.fatweb.oxygen.api.entity.system.EventLog
* @since 1.0.0 * @since 1.0.0
*/ */
interface IEventLogService : IService<EventLog> { interface IEventLogService : IService<EventLog> {
/**
* Save event
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see EventLogRecord
*/
fun saveEvent(annotation: EventLogRecord, userId: Long) fun saveEvent(annotation: EventLogRecord, userId: Long)
} }

View File

@@ -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<SensitiveWord> {
/**
* Get sensitive word settings
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
* @see SensitiveWordVo
*/
fun get(): List<SensitiveWordVo>
/**
* 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)
}

View File

@@ -12,6 +12,12 @@ import top.fatweb.oxygen.api.entity.system.EventLog
import top.fatweb.oxygen.api.mapper.system.EventLogMapper import top.fatweb.oxygen.api.mapper.system.EventLogMapper
import top.fatweb.oxygen.api.service.system.IEventLogService import top.fatweb.oxygen.api.service.system.IEventLogService
/**
* Event log service implement
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@DS("sqlite") @DS("sqlite")
@Service @Service
class EventLogServiceImpl : ServiceImpl<EventLogMapper, EventLog>(), IEventLogService { class EventLogServiceImpl : ServiceImpl<EventLogMapper, EventLog>(), IEventLogService {

View File

@@ -0,0 +1,66 @@
package top.fatweb.oxygen.api.service.system.impl
import com.baomidou.dynamic.datasource.annotation.DS
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
*/
@DS("sqlite")
@Service
class SensitiveWordServiceImpl : ServiceImpl<SensitiveWordMapper, SensitiveWord>(), ISensitiveWordService {
@Transactional(propagation = Propagation.REQUIRES_NEW)
override fun get(): List<SensitiveWordVo> = 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 ?: let { return@forEach }
try {
if (Regex(it, RegexOption.IGNORE_CASE).matches(str)) {
throw MatchSensitiveWordException()
}
} catch (e: MatchSensitiveWordException) {
throw e
} catch (_: Exception) {
}
}
}
}

View File

@@ -7,6 +7,12 @@ import top.fatweb.oxygen.api.entity.system.StatisticsLog
import top.fatweb.oxygen.api.mapper.system.StatisticsLogMapper import top.fatweb.oxygen.api.mapper.system.StatisticsLogMapper
import top.fatweb.oxygen.api.service.system.IStatisticsLogService import top.fatweb.oxygen.api.service.system.IStatisticsLogService
/**
* Statistics log service implement
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@DS("sqlite") @DS("sqlite")
@Service @Service
class StatisticsLogServiceImpl : ServiceImpl<StatisticsLogMapper, StatisticsLog>(), IStatisticsLogService class StatisticsLogServiceImpl : ServiceImpl<StatisticsLogMapper, StatisticsLog>(), IStatisticsLogService

View File

@@ -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<SensitiveWord.Use>?,
/**
* Enable
*
* @author FatttSnake, fatttsnake@gmail.com
* @since 1.0.0
*/
@Schema(description = "启用")
val enable: Boolean
)

View File

@@ -63,8 +63,10 @@ insert into t_power (id, type_id)
(1520101, 4), (1520101, 4),
(1530101, 4), (1530101, 4),
(1530102, 4), (1530102, 4),
(1530103, 4),
(1530301, 4), (1530301, 4),
(1530302, 4) (1530302, 4),
(1530303, 4)
as new_value as new_value
on duplicate key update type_id = new_value.type_id; on duplicate key update type_id = new_value.type_id;
@@ -139,8 +141,10 @@ insert into t_operation(id, name, code, func_id)
(1520101, '全部', 'system:log:query:all', 1520100), (1520101, '全部', 'system:log:query:all', 1520100),
(1530101, '基础', 'system:settings:query:base', 1530100), (1530101, '基础', 'system:settings:query:base', 1530100),
(1530102, '邮件', 'system:settings:query:mail', 1530100), (1530102, '邮件', 'system:settings:query:mail', 1530100),
(1530103, '敏感词', 'system:settings:query:sensitive', 1530100),
(1530301, '基础', 'system:settings:modify:base', 1530300), (1530301, '基础', 'system:settings:modify:base', 1530300),
(1530302, '邮件', 'system:settings:modify:mail', 1530300) as new_value (1530302, '邮件', 'system:settings:modify:mail', 1530300),
(1530303, '敏感词', 'system:settings:modify:sensitive', 1530300) as new_value
on duplicate key update name=new_value.name, on duplicate key update name=new_value.name,
code=new_value.code, code=new_value.code,
func_id=new_value.func_id; func_id=new_value.func_id;

View File

@@ -0,0 +1,9 @@
drop table if exists t_sensitive_word;
create table if not exists t_sensitive_word -- 敏感词表
(
id integer not null primary key,
word text not null unique, -- 词
use_for text null, -- 用于
enable integer not null default 1 -- 启用
);