refactor Setting

This commit is contained in:
Timi
2026-04-28 10:22:19 +08:00
parent 4e7f340cc6
commit 0625c17716
43 changed files with 798 additions and 725 deletions

View File

@@ -128,10 +128,15 @@
</repositories>
<dependencies>
<dependency>
<groupId>com.imyeyu.java</groupId>
<artifactId>timi-java</artifactId>
<version>0.0.3</version>
</dependency>
<dependency>
<groupId>com.imyeyu.spring</groupId>
<artifactId>timi-spring</artifactId>
<version>0.0.10</version>
<version>0.0.12</version>
</dependency>
<dependency>
<groupId>com.imyeyu.network</groupId>

View File

@@ -1,6 +1,6 @@
package com.imyeyu.api.annotation;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.entity.Setting;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -17,8 +17,34 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
public @interface EnableSetting {
/** @return 配置键 */
SettingKey value();
/**
*
*
* @author 夜雨
* @since 2026-04-27 14:45
*/
enum Logic {
AND,
OR
}
Setting.Module.User[] user() default {};
Setting.Module.Comment[] comment() default {};
Setting.Module.ForeverMC[] foreverMC() default {};
Setting.Module.Music[] music() default {};
Setting.Module.Journal[] journal() default {};
Setting.Module.TempFile[] tempFile() default {};
Setting.Module.System[] system() default {};
Logic logic() default Logic.AND;
/** @return 未启用配置时响应消息语言映射键 */
String message() default "service.offline";

View File

@@ -1,17 +1,20 @@
package com.imyeyu.api.annotation;
import com.imyeyu.api.modules.common.service.SettingService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.api.modules.common.service.SettingService;
import org.springframework.context.annotation.Lazy;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/**
* 启用配置注解处理器
*
@@ -24,16 +27,28 @@ public class EnableSettingInterceptor implements HandlerInterceptor {
private final SettingService service;
public boolean preHandle(@NonNull HttpServletRequest req, @NonNull HttpServletResponse resp, @NonNull Object handler) {
public boolean preHandle(@NonNull HttpServletRequest req, @NonNull HttpServletResponse resp, @NonNull Object handler) throws InvocationTargetException, IllegalAccessException {
if (handler instanceof HandlerMethod handlerMethod) {
EnableSetting annotation = handlerMethod.getMethodAnnotation(EnableSetting.class);
if (annotation == null) {
return true;
}
if (service.is(annotation.value())) {
return true;
EnableSetting.Logic logic = annotation.logic();
List<Boolean> valueList = new ArrayList<>();
for (Method method : annotation.getClass().getMethods()) {
if (method.getName().equals("message")) {
continue;
}
Enum<?>[] enums = (Enum<?>[]) method.invoke(annotation);
for (Enum<?> anEnum : enums) {
valueList.add(service.is(anEnum));
}
}
if (logic == EnableSetting.Logic.AND) {
return valueList.stream().allMatch(Boolean::booleanValue);
} else {
return valueList.stream().anyMatch(Boolean::booleanValue);
}
throw new TimiException(TimiCode.ERROR_SERVICE_OFF, annotation.message());
}
return true;
}

View File

@@ -1,12 +1,12 @@
package com.imyeyu.api.modules.blog.util;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.api.config.RedisConfig;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.api.modules.common.entity.User;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.api.modules.common.service.UserService;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.spring.TimiSpring;
import com.imyeyu.spring.util.Redis;
import com.imyeyu.spring.util.RedisSerializers;
@@ -24,7 +24,7 @@ import java.util.Objects;
/**
* Redis 令牌缓存
*
* <p>一级缓存 Session二级缓存 Redis有效期为 {@link SettingKey#TTL_USER_TOKEN} 天,每次触发
* <p>一级缓存 Session二级缓存 Redis有效期为 {@link com.imyeyu.api.modules.common.entity.Setting.Module.User#TOKEN_TTL} 天,每次触发
* 二级缓存获取时会刷新这个时间,即指定天数内不再访问则视为登出
*
* @author 夜雨
@@ -47,12 +47,12 @@ public class UserToken {
}
public Long set(String token, Long userId) {
long ttl = Time.D * settingService.getAsInt(SettingKey.TTL_USER_TOKEN);
long ttl = settingService.getAsTime(Setting.Module.User.TOKEN_TTL);
// 会话
TimiSpring.setSessionAttr(token, userId);
// 跨站 Cookie
Cookie cookie = Objects.requireNonNullElse(TimiSpring.getCookie("Token"), new Cookie("Token", token));
cookie.setDomain(settingService.getAsString(SettingKey.DOMAIN_ROOT));
cookie.setDomain(settingService.getAsString(Setting.Module.Domain.ROOT));
cookie.setPath("/");
cookie.setSecure(true);
cookie.setMaxAge((int) (ttl / 1000));
@@ -136,7 +136,7 @@ public class UserToken {
TimiSpring.removeSessionAttr(token);
// 清除跨站 Cookie
Cookie cookie = new Cookie("Token", "DIED");
cookie.setDomain(settingService.getAsString(SettingKey.DOMAIN_ROOT));
cookie.setDomain(settingService.getAsString(Setting.Module.Domain.ROOT));
cookie.setPath("/");
cookie.setSecure(true);
cookie.setMaxAge(0);

View File

@@ -1,191 +0,0 @@
package com.imyeyu.api.modules.common.bean;
/**
* 系统设置
*
* @author 夜雨
* @since 2021-07-20 21:46
*/
public enum SettingKey {
// ---------- 通用 ----------
RUN_ENV,
PUBLIC_RESOURCES,
/** 启用注册 */
ENABLE_REGISTER,
/** 启用登录 */
ENABLE_LOGIN,
/** 启用评论 */
ENABLE_COMMENT,
/** 启用测试 */
ENABLE_DEBUG,
/** 启用账号数据更新User 和 UserProfile */
ENABLE_USER_UPDATE,
/** 启用灰色滤镜 */
ENABLE_GRAY_FILTER,
TEMP_FILE_PATH,
// ---------- ICP 备案号 ----------
ICP_IMYEYU_COM,
// ---------- 域名 ----------
DOMAIN_ROOT,
DOMAIN_API,
DOMAIN_GIT,
DOMAIN_BLOG,
DOMAIN_SPACE,
DOMAIN_RESOURCE,
DOMAIN_DOWNLOAD,
DOMAIN_FOREVER_MC,
// ---------- ForeverMC ----------
/** 启用登录服务 */
FMC_PLAYER_LOGIN_ENABLE,
/** 最多绑定玩家数量 */
FMC_MAX_BIND,
/** 闪烁标语 */
FMC_SPLASHES,
/** 启动器背景 */
FMC_BG,
FMC_BGM,
FMC_BG_SWIPER,
/** JRE 列表 */
FMC_JRE,
/** 辅助登录模组 */
FMC_LOGIN_FABRIC,
/** 启用图片地图上传 */
FMC_ENABLE_IMAGE_MAP_UPLOAD,
/** 玩家登录令牌有效期(天) */
FMC_PLAYER_LOGIN_TOKEN_TTL,
/** 服务器与数据中心的通信令牌 */
FMC_SERVER_TOKEN,
// ---------- 生存时间 ----------
TTL_USER_TOKEN,
TTL_SETTING,
TTL_MULTILINGUAL,
// ---------- 多语言翻译 ----------
MULTILINGUAL_TRANSLATE_API,
MULTILINGUAL_TRANSLATE_APP_ID,
MULTILINGUAL_TRANSLATE_KEY,
// ---------- 账单 ----------
BILL_API_TOKEN,
// ---------- Git ----------
GIT_API,
GIT_ABOUT_ARTICLE,
GIT_REPO_PATH,
// ---------- 远程音乐 ----------
MUSIC_MAX_FRAME_LENGTH,
MUSIC_PLAYER_PORT,
MUSIC_PLAYER_IP,
MUSIC_CONTROLLER_PORT,
MUSIC_CONTROLLER_IP,
MUSIC_CONTROLLER_URI,
// ---------- 日记 ----------
JOURNAL_KEY,
JOURNAL_APP_ID,
JOURNAL_APP_SECRET,
JOURNAL_MEMO,
JOURNAL_OPEN_ID_WHITE_LIST,
// ---------- 临时文件 ----------
/** 临时文件最小缓存时间 */
TEMP_FILE_TTL_MIN,
/** 临时文件最长缓存时间 */
TEMP_FILE_TTL_MAX,
/** 临时文件默认缓存时间 */
TEMP_FILE_TTL_DEFAULT,
/** 已过期的临时文件保留时间 */
TEMP_FILE_RESIDUE_TIME,
/** 每个 IP 限制有效临时文件容量 */
TEMP_FILE_LIMIT,
// ---------- 系统 ----------
SYSTEM_FILE_BASE,
SYSTEM_FILE_TYPE,
SYSTEM_FILE_SYNC,
/** 文件过滤(通过密钥类型) */
SYSTEM_FILE_FILTER,
SYSTEM_STATUS_RATE,
SYSTEM_STATUS_LIMIT,
SYSTEM_STATUS_NETWORK_MAC,
SYSTEM_TERMINAL_TTL,
SYSTEM_TERMINAL_FILTERS,
/** 一般密钥 */
SYSTEM_API_KEY,
/** 超级密钥 */
SYSTEM_API_SUPER_KEY,
SYSTEM_REBOOT_COMMAND,
}

View File

@@ -0,0 +1,35 @@
package com.imyeyu.api.modules.common.bean;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
*
*
* @author 夜雨
* @since 2026-04-24 00:59
*/
@Getter
@AllArgsConstructor
public enum SettingModule {
COMMON("通用"),
DOMAIN("域名"),
FOREVER_MC("Forever MC"),
MULTILINGUAL("多语言环境"),
GIT("Git"),
MUSIC("远程音乐"),
JOURNAL("糕雨日记"),
TEMP_FILE("临时文件"),
SYSTEM("系统");
final String title;
}

View File

@@ -3,9 +3,9 @@ package com.imyeyu.api.modules.common.controller;
import com.imyeyu.api.annotation.CaptchaValid;
import com.imyeyu.api.annotation.EnableSetting;
import com.imyeyu.api.bean.CaptchaFrom;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.entity.Comment;
import com.imyeyu.api.modules.common.entity.CommentReply;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.api.modules.common.service.CommentReplyService;
import com.imyeyu.api.modules.common.service.CommentService;
import com.imyeyu.spring.annotation.AOPLog;
@@ -39,7 +39,7 @@ public class CommentController {
@AOPLog
@CaptchaValid(CaptchaFrom.COMMENT)
@EnableSetting(value = SettingKey.ENABLE_COMMENT, message = "comment.off_service")
@EnableSetting(comment = Setting.Module.Comment.ENABLE, message = "comment.off_service")
@RequestRateLimit
@PostMapping("/create")
public void create(@Valid @RequestBody CaptchaData<Comment> captchaData) {
@@ -59,7 +59,7 @@ public class CommentController {
*/
@AOPLog
@CaptchaValid(CaptchaFrom.COMMENT_REPLY)
@EnableSetting(value = SettingKey.ENABLE_COMMENT, message = "comment.off_service")
@EnableSetting(comment = Setting.Module.Comment.ENABLE, message = "comment.off_service")
@RequestRateLimit
@PostMapping("/reply/create")
public void createReply(@Valid @RequestBody CaptchaData<CommentReply> request) {

View File

@@ -1,11 +1,8 @@
package com.imyeyu.api.modules.common.controller;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.imyeyu.api.bean.CaptchaFrom;
import com.imyeyu.api.modules.common.bean.ImageType;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.entity.Attachment;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.api.modules.common.entity.Task;
@@ -70,9 +67,9 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* 系统接口
@@ -240,64 +237,40 @@ public class CommonController {
}
@RequestRateLimit
@GetMapping("/setting/{key}")
public String settingByKey(@PathVariable("key") String key, @RequestParam(value = "as", required = false) Setting.Type asType) throws JsonProcessingException {
Setting setting = settingService.getByKey(SettingKey.valueOf(key.toUpperCase()));
@GetMapping("/setting")
public String settingByKey(@RequestParam String module, @RequestParam String key) throws ClassNotFoundException {
Setting setting = settingService.getByKey(SettingService.fromModuleKey(module, key));
if (setting.isPrivate()) {
throw new TimiException(TimiCode.PERMISSION_ERROR);
}
String result = setting.getValue();
if (asType == null) {
return result;
}
switch (asType) {
case JSON -> {
if (setting.getType() == Setting.Type.YAML) {
Map<String, Object> obj = yaml.load(setting.getValue());
result = jackson.writeValueAsString(obj);
}
}
case YAML -> {
if (setting.getType() == Setting.Type.JSON) {
Map<String, Object> obj = jackson.readValue(setting.getValue(), new TypeReference<>() {});
result = yaml.dump(obj);
}
}
}
return result;
return setting.getValue();
}
@RequestRateLimit
@PostMapping("/setting/map")
public Map<SettingKey, String> mapSettingByKeys(@RequestBody Map<SettingKey, Map<String, Object>> settingMap) throws JsonProcessingException {
List<Setting> result = settingService.listByKeys(new ArrayList<>(settingMap.keySet()));
for (int i = 0; i < result.size(); i++) {
Setting setting = result.get(i);
public Map<String, Map<String, String>> mapSettingByKeys(@RequestBody Map<String, List<String>> moduleKeyMap) {
List<Enum<?>> keyList = new ArrayList<>();
moduleKeyMap.forEach((k, v) -> {
try {
for (String key : v) {
keyList.add(SettingService.fromModuleKey(k, key));
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
});
Map<String, Map<String, String>> result = new HashMap<>();
List<Setting> settingList = settingService.listByKeys(keyList);
for (Setting setting : settingList) {
if (setting.isPrivate()) {
throw new TimiException(TimiCode.PERMISSION_ERROR);
}
Map<String, Object> args = settingMap.get(setting.getKey());
if (args == null) {
continue;
if (!result.containsKey(setting.getModule())) {
result.put(setting.getKey(), new HashMap<>());
}
if (args.containsKey("as")) {
switch (Ref.toType(Setting.Type.class, args.get("as").toString())) {
case JSON -> {
if (setting.getType() == Setting.Type.YAML) {
Map<String, Object> obj = new Yaml().load(setting.getValue());
setting.setValue(jackson.writeValueAsString(obj));
result.get(setting.getModule()).put(setting.getKey(), setting.getValue());
}
}
case YAML -> {
if (setting.getType() == Setting.Type.JSON) {
Map<String, Object> obj = jackson.readValue(setting.getValue(), new TypeReference<>() {});
setting.setValue(new Yaml().dump(obj));
}
}
}
}
}
return result.stream().collect(Collectors.toMap(Setting::getKey, Setting::getValue));
return result;
}
@AOPLog

View File

@@ -3,9 +3,9 @@ package com.imyeyu.api.modules.common.controller;
import com.imyeyu.api.annotation.CaptchaValid;
import com.imyeyu.api.annotation.EnableSetting;
import com.imyeyu.api.bean.CaptchaFrom;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.entity.Comment;
import com.imyeyu.api.modules.common.entity.CommentReply;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.api.modules.common.entity.UserConfig;
import com.imyeyu.api.modules.common.entity.UserPrivacy;
import com.imyeyu.api.modules.common.service.CommentReplyService;
@@ -71,7 +71,7 @@ public class UserController implements TimiJava {
*/
@AOPLog
@CaptchaValid(CaptchaFrom.REGISTER)
@EnableSetting(value = SettingKey.ENABLE_REGISTER, message = "user.register.off_service")
@EnableSetting(user = Setting.Module.User.ENABLE_REGISTER, message = "user.register.off_service")
@RequestRateLimit(value = 1, lifeCycle = 60)
@PostMapping("/register")
public LoginResponse register(@Valid @RequestBody CaptchaData<RegisterRequest> request) {
@@ -86,7 +86,7 @@ public class UserController implements TimiJava {
*/
@AOPLog
@CaptchaValid(CaptchaFrom.LOGIN)
@EnableSetting(value = SettingKey.ENABLE_LOGIN, message = "user.login.off_service")
@EnableSetting(user = Setting.Module.User.ENABLE_LOGIN, message = "user.login.off_service")
@RequestRateLimit
@PostMapping("/login")
public LoginResponse login(@Valid @RequestBody CaptchaData<LoginRequest> request) {
@@ -99,7 +99,7 @@ public class UserController implements TimiJava {
* @return 登录数据
*/
@AOPLog
@EnableSetting(value = SettingKey.ENABLE_LOGIN, message = "user.login.off_service")
@EnableSetting(user = Setting.Module.User.ENABLE_LOGIN, message = "user.login.off_service")
@RequestRateLimit
@PostMapping("/login/token")
public LoginResponse login4Token() {
@@ -207,7 +207,7 @@ public class UserController implements TimiJava {
*/
@AOPLog
@RequiredToken
@EnableSetting(value = SettingKey.ENABLE_USER_UPDATE, message = "user.data.off_service")
@EnableSetting(user = Setting.Module.User.ENABLE_PROFILE_UPDATE, message = "user.data.off_service")
@RequestRateLimit
@PostMapping("/profile/update")
public void updateProfile(@Valid UserRequest data) {

View File

@@ -1,10 +1,13 @@
package com.imyeyu.api.modules.common.entity;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.spring.annotation.table.Id;
import com.fasterxml.jackson.databind.JsonNode;
import com.imyeyu.spring.annotation.table.Transient;
import com.imyeyu.spring.entity.Creatable;
import com.imyeyu.spring.entity.Entity;
import com.imyeyu.spring.entity.Updatable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* 系统配置
@@ -13,7 +16,9 @@ import lombok.Data;
* @since 2021-07-20 21:46
*/
@Data
public class Setting implements Creatable, Updatable {
@NoArgsConstructor
@EqualsAndHashCode(callSuper = true)
public class Setting extends Entity implements Creatable, Updatable {
/**
*
@@ -21,31 +26,377 @@ public class Setting implements Creatable, Updatable {
* @author 夜雨
* @since 2025-01-10 17:08
*/
public enum Type {
INTEGER,
public enum ValueType {
/** 字符串 */
STRING,
JSON,
/** 单选 */
SELECT_RADIO,
YAML,
/** 多选 */
SELECT_CHECKBOX,
/** 整数 */
INTEGER,
/** 颜色 */
COLOR,
/** 浮点数 */
FLOAT,
/** 日期 */
DATE,
/** 日期时间 */
DATETIME,
/** 时间 */
TIME,
/** 时长 */
DURATION,
/** 布尔值 */
BOOLEAN,
/** JSON 列表 */
JSON_LIST,
/** JSON 对象 */
JSON_OBJECT
}
@Id
private SettingKey key;
private String module;
private String key;
private String value;
private Type type;
private ValueType valueType;
private JsonNode valueArgs;
private boolean isPrivate;
private Long createdAt;
@Transient
private Enum<?> keyRaw;
private Long updatedAt;
public Setting(Enum<?> key) {
setKeyRaw(key);
}
public Setting(Enum<?> key, Object value, ValueType valueType) {
setKeyRaw(key);
this.value = value.toString();
this.valueType = valueType;
}
public void setKeyRaw(Enum<?> key) {
this.keyRaw = key;
this.module = key.getClass().getSimpleName().toUpperCase();
this.key = key.toString();
}
public boolean isPublic() {
return !isPrivate;
}
public boolean is(Enum<?> anEnum) {
return anEnum.getClass().getSimpleName().toUpperCase().equals(module) && anEnum.toString().equals(key);
}
/**
*
*
* @author 夜雨
* @since 2026-04-24 14:23
*/
public static final class Module {
/**
*
*
* @author 夜雨
* @since 2026-04-24 15:39
*/
public enum Common {
/** 微信收款码 */
WECHAT_RECEIVE_QR_CODE
}
/**
* 域名
*
* @author 夜雨
* @since 2026-04-26 17:18
*/
public enum Domain {
ROOT,
API,
GIT,
BLOG,
SPACE,
FOREVER_MC
}
/**
*
*
* @author 夜雨
* @since 2026-04-24 15:14
*/
public enum Blog {
}
/**
*
*
* @author 夜雨
* @since 2026-04-24 15:03
*/
public enum User {
/** 启用登录 */
ENABLE_LOGIN,
/** 启用注册 */
ENABLE_REGISTER,
/** 允许数据更新 */
ENABLE_PROFILE_UPDATE,
/** 默认头像 */
DEFAULT_AVATAR,
/** 默认封面 */
DEFAULT_WRAPPER,
/** 令牌有效期 */
TOKEN_TTL
}
/**
*
*
* @author 夜雨
* @since 2026-04-24 15:21
*/
public enum Comment {
/** 启用服务 */
ENABLE
}
/**
*
*
* @author 夜雨
* @since 2026-04-24 15:03
*/
public enum ICP {
IMYEYU_COM
}
/**
*
*
* @author 夜雨
* @since 2026-04-24 15:01
*/
public enum ForeverMC {
PLAYER_BIND_MAX,
LOGIN_TOKEN_TTL
}
/**
*
*
* @author 夜雨
* @since 2026-04-24 14:57
*/
public enum Multilingual {
/** 翻译 API */
TRANSLATE_API,
/** 翻译 AppId */
TRANSLATE_APP_ID,
/** 翻译密钥 */
TRANSLATE_KEY,
/** 翻译计划任务表达式 */
TRANSLATE_CORN,
/** 缓存时长 */
CACHE_TTL
}
/**
*
*
* @author 夜雨
* @since 2026-04-24 14:55
*/
public enum Gitea {
/** 接口地址 */
API,
/** 关于页面所属文章 ID */
ABOUT_ARTICLE_ID,
/** 仓库文件地址 */
REPOSITORY_PATH
}
/**
*
*
* @author 夜雨
* @since 2026-04-24 14:52
*/
public enum Music {
/** 启用服务 */
ENABLE,
/** 通信消息最大帧长度 */
MAX_FRAME_LENGTH,
/** 受控端 IP */
PLAYER_IP,
/** 受控端端口 */
PLAYER_PORT,
/** 控制端 IP */
CONTROLLER_IP,
/** 控制端端口 */
CONTROLLER_PORT,
/** 控制端入口地址 */
CONTROLLER_URI,
}
/**
*
*
* @author 夜雨
* @since 2026-04-24 14:49
*/
public enum Journal {
/** 启用服务 */
ENABLE,
/** 访问密钥 */
KEY,
/** 微信小程序 AppId */
APP_ID,
/** 微信小程序 AppSecret */
APP_SECRET,
/** 备忘录内容 */
MEMO,
/** 高权限访问 OpenID 白名单(应付审核) */
OPEN_ID_WHITE_LIST
}
/**
*
*
* @author 夜雨
* @since 2026-04-24 14:47
*/
public enum TempFile {
/** 启用服务 */
ENABLE,
/** 最小缓存时长 */
TTL_MIN,
/** 默认缓存时长 */
TTL_DEFAULT,
/** 最大缓存时长 */
TTL_MAX,
/** 已过期文件残留时长 */
RESIDUE_TTL,
/** 每个 IP 限制有效临时文件容量 */
LIMIT_SIZE_OF_IP
}
/**
*
*
* @author 夜雨
* @since 2026-04-27 14:35
*/
public enum FileSync {
ENABLE,
CRON,
}
/**
*
*
* @author 夜雨
* @since 2026-04-24 14:23
*/
public enum System {
/** 一般密钥 */
API_KEY,
/** 超级密钥 */
API_KEY_SUPER,
/** 状态采集数据量 */
STATUS_LIMIT,
/** 状态采集网卡 */
STATUS_NETWORK_MAC,
/** 状态采集频率 */
STATUS_RATE,
/** 终端指令过滤 */
TERMINAL_FILTERS,
/** 终端会话有效时长 */
TERMINAL_TTL,
/** 文件系统基准路径 */
FILE_BASE_PATH,
/** 设置缓存时长 */
SETTING_TTL,
/** 哀悼滤镜 */
ENABLE_MOURN_FILTER,
}
}
}

View File

@@ -1,6 +1,5 @@
package com.imyeyu.api.modules.common.mapper;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.spring.mapper.BaseMapper;
import org.apache.ibatis.annotations.Select;
@@ -13,10 +12,7 @@ import java.util.List;
* @author 夜雨
* @since 2021-07-20 22:26
*/
public interface SettingMapper extends BaseMapper<Setting, String> {
@Select("SELECT * FROM `setting` WHERE `key` = #{key}")
Setting selectByKey(SettingKey key);
public interface SettingMapper extends BaseMapper<Setting, Long> {
@Select("SELECT * FROM `setting`")
List<Setting> listAll();

View File

@@ -4,13 +4,14 @@ import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.spring.service.UpdatableService;
import com.imyeyu.java.ref.Ref;
import com.imyeyu.spring.service.BaseService;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
/**
* 系统配置服务
@@ -18,15 +19,21 @@ import java.util.List;
* @author 夜雨
* @since 2021-07-20 22:06
*/
public interface SettingService extends UpdatableService<Setting> {
public interface SettingService extends BaseService<Setting, Long> {
default List<Setting> listByKeys(SettingKey... keys) {
@SuppressWarnings("unchecked")
static <T extends Enum<?>> T fromModuleKey(String module, String key) throws ClassNotFoundException {
Class<?> moduleClass = Class.forName(String.format("com.imyeyu.api.modules.common.entity.Setting$Module$%s", module));
return Ref.toType((Class<T>) moduleClass, key);
}
default List<Setting> listByKeys(Enum<?>... keys) {
return listByKeys(Arrays.asList(keys));
}
List<Setting> listByKeys(List<SettingKey> keyList);
List<Setting> listByKeys(List<Enum<?>> keyList);
Setting getByKey(SettingKey key);
Setting getByKey(Enum<?> key);
/**
* 获取指定类型配置值字符串
@@ -34,13 +41,15 @@ public interface SettingService extends UpdatableService<Setting> {
* @param key 键
* @return 配置值
*/
String getAsString(SettingKey key);
String getAsString(Enum<?> key);
int getAsInt(SettingKey key);
int getAsInt(Enum<?> key);
long getAsLong(SettingKey key);
long getAsLong(Enum<?> key);
double getAsDouble(SettingKey key);
double getAsDouble(Enum<?> key);
long getAsTime(Enum<?> key);
/**
* 获取为布尔值
@@ -49,7 +58,7 @@ public interface SettingService extends UpdatableService<Setting> {
* @return 配置值
* @throws TimiException 服务异常
*/
boolean is(SettingKey key);
boolean is(Enum<?> key);
/**
* 获取为布尔值,并取反
@@ -58,23 +67,23 @@ public interface SettingService extends UpdatableService<Setting> {
* @return 配置值
* @throws TimiException 服务异常
*/
boolean not(SettingKey key);
boolean not(Enum<?> key);
JsonNode getAsJsonNode(SettingKey key);
JsonNode getAsJsonNode(Enum<?> key);
ObjectNode getAsJsonObject(SettingKey key);
ObjectNode getAsJsonObject(Enum<?> key);
ArrayNode getAsArrayNode(SettingKey key);
ArrayNode getAsArrayNode(Enum<?> key);
<T> T fromJson(SettingKey key, Class<T> clazz);
Set<String> getAsSet(Enum<?> key);
<T> T fromJson(SettingKey key, TypeReference<T> typeReference);
List<String> getAsList(Enum<?> key);
<T> T fromYaml(SettingKey key, Class<T> clazz);
<T> T fromJson(Enum<?> key, Class<T> clazz);
<T> T fromJson(Enum<?> key, TypeReference<T> typeReference);
<T> T fromYaml(Enum<?> key, Class<T> clazz);
List<Setting> listAll();
void clearCache(SettingKey key);
void flushCache();
}

View File

@@ -1,10 +1,10 @@
package com.imyeyu.api.modules.common.service.implement;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.Language;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.entity.Multilingual;
import com.imyeyu.api.modules.common.mapper.MultilingualMapper;
import com.imyeyu.api.modules.common.service.MultilingualService;
@@ -66,7 +66,7 @@ public class MultilingualServiceImplement extends AbstractEntityService<Multilin
if (result == null) {
throw new TimiException(TimiCode.RESULT_NULL).msgKey("TODO not found language");
}
redisLanguage.set(id, result, Time.D * settingService.getAsInt(SettingKey.TTL_MULTILINGUAL));
redisLanguage.set(id, result, settingService.getAsTime(Setting.Module.Multilingual.CACHE_TTL));
}
return result.getValue(language);
}
@@ -80,7 +80,7 @@ public class MultilingualServiceImplement extends AbstractEntityService<Multilin
log.warn("not found language for key: {}", key);
return key;
}
long ttl = Time.D * settingService.getAsInt(SettingKey.TTL_MULTILINGUAL);
long ttl = settingService.getAsTime(Setting.Module.Multilingual.CACHE_TTL);
redisLanguage.set(result.getId(), result, ttl);
redisLanguageMap.set(result.getKey(), result.getId(), ttl);
return result.getValue(language);

View File

@@ -6,24 +6,27 @@ import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.api.modules.common.mapper.SettingMapper;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.CallbackArg;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.spring.mapper.BaseMapper;
import com.imyeyu.spring.service.AbstractEntityService;
import com.imyeyu.spring.util.Redis;
import com.imyeyu.utils.Time;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.yaml.snakeyaml.Yaml;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* 系统配置服务实现
@@ -34,30 +37,57 @@ import java.util.List;
@Slf4j
@Service
@RequiredArgsConstructor
public class SettingServiceImplement extends AbstractEntityService<Setting, String> implements SettingService {
public class SettingServiceImplement extends AbstractEntityService<Setting, Long> implements SettingService {
/** 缓存键模板参数module, key */
private static final String CACHE_KEY_TMPL = "%s:%s";
private final SettingMapper mapper;
private final Redis<String, String> redisSetting;
private final ObjectMapper jackson;
@PostConstruct
private void initialize() {
CallbackArg<Setting> createIfNotExist = setting -> {
Setting dbSetting = mapper.selectByExample(new Setting(setting.getKeyRaw()));
if (dbSetting == null) {
create(setting);
}
};
createIfNotExist.handler(new Setting(Setting.Module.System.SETTING_TTL, "10m", Setting.ValueType.DURATION));
createIfNotExist.handler(new Setting(Setting.Module.System.API_KEY, "[]", Setting.ValueType.JSON_LIST));
createIfNotExist.handler(new Setting(Setting.Module.System.API_KEY_SUPER, "[]", Setting.ValueType.JSON_LIST));
createIfNotExist.handler(new Setting(Setting.Module.System.STATUS_RATE, 3000, Setting.ValueType.INTEGER));
createIfNotExist.handler(new Setting(Setting.Module.System.STATUS_LIMIT, 2048, Setting.ValueType.INTEGER));
createIfNotExist.handler(new Setting(Setting.Module.System.STATUS_NETWORK_MAC, "", Setting.ValueType.STRING));
createIfNotExist.handler(new Setting(Setting.Module.Music.ENABLE, false, Setting.ValueType.BOOLEAN));
createIfNotExist.handler(new Setting(Setting.Module.Journal.KEY, "[]", Setting.ValueType.JSON_LIST));
createIfNotExist.handler(new Setting(Setting.Module.Journal.OPEN_ID_WHITE_LIST, "[]", Setting.ValueType.JSON_LIST));
}
@PostConstruct
private void postConstruct() {
redisSetting.flushAll();
}
@Override
protected BaseMapper<Setting, String> mapper() {
protected BaseMapper<Setting, Long> mapper() {
return mapper;
}
@Override
public void update(Setting setting) {
super.update(setting);
clearCache(setting.getKey());
redisSetting.destroy(CACHE_KEY_TMPL.formatted(setting.getModule(), setting.getKey()));
}
public Setting getByKey(SettingKey key) {
public Setting getByKey(Enum<?> key) {
if (key == null) {
throw new TimiException(TimiCode.ARG_MISS).msgKey("key can not be null");
}
String cacheValue = redisSetting.get(key.toString());
String cacheKey = CACHE_KEY_TMPL.formatted(key.getClass().getSimpleName().toUpperCase(), key.toString());
String cacheValue = redisSetting.get(cacheKey);
if (TimiJava.isNotEmpty(cacheValue)) {
try {
return jackson.readValue(cacheValue, Setting.class);
@@ -65,19 +95,21 @@ public class SettingServiceImplement extends AbstractEntityService<Setting, Stri
throw new TimiException(TimiCode.ERROR, "read setting cache error", e);
}
}
Setting setting = mapper.selectByKey(key);
Setting setting = mapper.selectByExample(new Setting(key));
TimiException.required(setting, "not found setting: %s.%s".formatted(key.getClass().getName(), key));
if (TimiJava.isEmpty(setting.getValue())) {
// 无需缓存
return setting;
}
int settingTTL;
if (key == SettingKey.TTL_SETTING) {
settingTTL = Integer.parseInt(setting.getValue());
long settingTTL;
if (setting.is(Setting.Module.System.SETTING_TTL)) {
settingTTL = Time.parseToMS(setting.getValue());
} else {
settingTTL = Integer.parseInt(getByKey(SettingKey.TTL_SETTING).getValue());
settingTTL = Time.parseToMS(getByKey(Setting.Module.System.SETTING_TTL).getValue());
}
if (0 < settingTTL) {
try {
redisSetting.set(key.toString(), jackson.writeValueAsString(setting), Time.M * settingTTL);
redisSetting.set(key.toString(), jackson.writeValueAsString(setting), settingTTL);
} catch (JsonProcessingException e) {
throw new TimiException(TimiCode.ERROR, "write setting cache error", e);
}
@@ -86,46 +118,51 @@ public class SettingServiceImplement extends AbstractEntityService<Setting, Stri
}
@Override
public List<Setting> listByKeys(List<SettingKey> keyList) {
public List<Setting> listByKeys(List<Enum<?>> keyList) {
List<Setting> result = new ArrayList<>();
for (int i = 0; i < keyList.size(); i++) {
result.add(getByKey(keyList.get(i)));
for (Enum<?> anEnum : keyList) {
result.add(getByKey(anEnum));
}
return result;
}
@Override
public String getAsString(SettingKey key) {
public String getAsString(Enum<?> key) {
return getByKey(key).getValue();
}
@Override
public int getAsInt(SettingKey key) {
public int getAsInt(Enum<?> key) {
return Integer.parseInt(getAsString(key));
}
@Override
public long getAsLong(SettingKey key) {
public long getAsLong(Enum<?> key) {
return Long.parseLong(getAsString(key));
}
@Override
public double getAsDouble(SettingKey key) {
public double getAsDouble(Enum<?> key) {
return Double.parseDouble(getAsString(key));
}
@Override
public boolean is(SettingKey key) {
public long getAsTime(Enum<?> key) {
return Time.parseToMS(getAsString(key));
}
@Override
public boolean is(Enum<?> key) {
return Boolean.parseBoolean(getAsString(key));
}
@Override
public boolean not(SettingKey key) {
public boolean not(Enum<?> key) {
return !is(key);
}
@Override
public JsonNode getAsJsonNode(SettingKey key) {
public JsonNode getAsJsonNode(Enum<?> key) {
try {
return jackson.readTree(getAsString(key));
} catch (JsonProcessingException e) {
@@ -134,17 +171,27 @@ public class SettingServiceImplement extends AbstractEntityService<Setting, Stri
}
@Override
public ObjectNode getAsJsonObject(SettingKey key) {
public ObjectNode getAsJsonObject(Enum<?> key) {
return (ObjectNode) getAsJsonNode(key);
}
@Override
public ArrayNode getAsArrayNode(SettingKey key) {
public ArrayNode getAsArrayNode(Enum<?> key) {
return (ArrayNode) getAsJsonNode(key);
}
@Override
public <T> T fromJson(SettingKey key, Class<T> clazz) {
public Set<String> getAsSet(Enum<?> key) {
return new HashSet<>(getAsList(key));
}
@Override
public List<String> getAsList(Enum<?> key) {
return getAsArrayNode(key).valueStream().map(JsonNode::asText).toList();
}
@Override
public <T> T fromJson(Enum<?> key, Class<T> clazz) {
try {
return jackson.treeToValue(getAsJsonNode(key), clazz);
} catch (JsonProcessingException e) {
@@ -153,11 +200,11 @@ public class SettingServiceImplement extends AbstractEntityService<Setting, Stri
}
@Override
public <T> T fromJson(SettingKey key, TypeReference<T> typeReference) {
public <T> T fromJson(Enum<?> key, TypeReference<T> typeReference) {
return jackson.convertValue(getAsJsonNode(key), typeReference);
}
public <T> T fromYaml(SettingKey key, Class<T> clazz) {
public <T> T fromYaml(Enum<?> key, Class<T> clazz) {
return new Yaml().loadAs(getAsString(key), clazz);
}
@@ -165,14 +212,4 @@ public class SettingServiceImplement extends AbstractEntityService<Setting, Stri
public List<Setting> listAll() {
return mapper.listAll();
}
@Override
public void clearCache(SettingKey key) {
redisSetting.destroy(key.toString());
}
@Override
public void flushCache() {
redisSetting.flushAll();
}
}

View File

@@ -1,6 +1,6 @@
package com.imyeyu.api.modules.common.service.implement;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.entity.Attachment;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.api.modules.common.service.AttachmentService;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.api.modules.common.service.TempFileService;
@@ -33,15 +33,15 @@ public class TempFileServiceImplement implements TempFileService {
private final AttachmentService attachmentService;
public List<TempFileResponse> store(List<MultipartFile> files, Long ttl) throws TimiException {
String ttlMinStr = settingService.getAsString(SettingKey.TEMP_FILE_TTL_MIN);
String ttlMaxStr = settingService.getAsString(SettingKey.TEMP_FILE_TTL_MAX);
String limitStr = settingService.getAsString(SettingKey.TEMP_FILE_LIMIT);
String ttlMinStr = settingService.getAsString(Setting.Module.TempFile.TTL_MIN);
String ttlMaxStr = settingService.getAsString(Setting.Module.TempFile.TTL_MAX);
String limitStr = settingService.getAsString(Setting.Module.TempFile.LIMIT_SIZE_OF_IP);
long minTTL = Time.parseToMS(ttlMinStr);
long maxTTL = Time.parseToMS(ttlMaxStr);
long defaultTTL = Time.parseToMS(settingService.getAsString(SettingKey.TEMP_FILE_TTL_DEFAULT));
long defaultTTL = Time.parseToMS(settingService.getAsString(Setting.Module.TempFile.TTL_DEFAULT));
long limit = IOSize.parse(limitStr);
long residueTime = Time.parseToMS(settingService.getAsString(SettingKey.TEMP_FILE_RESIDUE_TIME));
long residueTime = Time.parseToMS(settingService.getAsString(Setting.Module.TempFile.RESIDUE_TTL));
ttl = TimiJava.defaultIfNull(ttl, defaultTTL);
TimiException.requiredTrue(minTTL < ttl && ttl <= maxTTL, String.format("ttl must be between %s and %s", ttlMinStr, ttlMaxStr));
@@ -65,9 +65,7 @@ public class TempFileServiceImplement implements TempFileService {
long deletedAt = Time.now() + ttl;
long destroyAt = deletedAt + residueTime;
for (int i = 0; i < files.size(); i++) {
MultipartFile file = files.get(i);
for (MultipartFile file : files) {
Attachment attach = new Attachment();
attach.setBizType(Attachment.BizType.TEMP_FILE);
attach.setName(file.getOriginalFilename());

View File

@@ -3,8 +3,8 @@ package com.imyeyu.api.modules.common.task;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.entity.Multilingual;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.api.modules.common.service.MultilingualService;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.java.TimiJava;
@@ -131,8 +131,8 @@ public class MultilingualTranslateTask {
private synchronized Map<String, String> doTranslate(String text, BaiduLanguage to) throws Exception {
String random = String.valueOf(Time.now());
String appId = settingService.getAsString(SettingKey.MULTILINGUAL_TRANSLATE_APP_ID);
String key = settingService.getAsString(SettingKey.MULTILINGUAL_TRANSLATE_KEY);
String appId = settingService.getAsString(Setting.Module.Multilingual.TRANSLATE_APP_ID);
String key = settingService.getAsString(Setting.Module.Multilingual.TRANSLATE_KEY);
ArgMap<String, Object> args = new ArgMap<>();
args.put("q", text);
@@ -142,7 +142,7 @@ public class MultilingualTranslateTask {
args.put("salt", random);
args.put("sign", Digest.md5(appId + text + random + key));
String response = Request.post(settingService.getAsString(SettingKey.MULTILINGUAL_TRANSLATE_API))
String response = Request.post(settingService.getAsString(Setting.Module.Multilingual.TRANSLATE_API))
.bodyForm(args.toNameValuePair())
.execute()
.returnContent()

View File

@@ -1,9 +1,9 @@
package com.imyeyu.api.modules.git.bean.gitea;
import com.imyeyu.java.TimiJava;
import com.imyeyu.api.TimiServerAPI;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.java.TimiJava;
import com.imyeyu.utils.Encoder;
import com.imyeyu.utils.StringInterpolator;
@@ -13,7 +13,7 @@ import java.util.Map;
* @author 夜雨
* @since 2025-06-26 16:04
*/
public enum API {
public enum GiteaAPI {
REPO_LIST("/api/v1/repos/search"),
@@ -36,7 +36,7 @@ public enum API {
final String uri;
API(String uri) {
GiteaAPI(String uri) {
this.uri = uri;
}
@@ -48,7 +48,7 @@ public enum API {
public String buildURL(Map<String, Object> argsURI, Map<String, Object> argsURL) {
SettingService settingService = TimiServerAPI.applicationContext.getBean(SettingService.class);
StringBuilder url = new StringBuilder();
url.append(settingService.getAsString(SettingKey.GIT_API));
url.append(settingService.getAsString(Setting.Module.Gitea.API));
url.append(INTERPOLATOR.inject(uri, argsURI));
if (TimiJava.isNotEmpty(argsURL)) {
url.append("?");

View File

@@ -1,13 +1,13 @@
package com.imyeyu.api.modules.git.controller;
import lombok.RequiredArgsConstructor;
import com.imyeyu.api.annotation.EnableSetting;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.api.modules.git.entity.Developer;
import com.imyeyu.api.modules.git.service.DeveloperService;
import com.imyeyu.spring.annotation.AOPLog;
import com.imyeyu.spring.annotation.RequestRateLimit;
import com.imyeyu.spring.annotation.RequiredToken;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -34,7 +34,7 @@ public class DeveloperController {
@AOPLog
@RequiredToken
@EnableSetting(value = SettingKey.ENABLE_USER_UPDATE, message = "user.data.off_service")
@EnableSetting(user = Setting.Module.User.ENABLE_PROFILE_UPDATE, message = "user.data.off_service")
@RequestRateLimit
@PostMapping("/update")
public void update(@RequestBody Developer developer) {

View File

@@ -3,21 +3,21 @@ package com.imyeyu.api.modules.git.service.implement;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.network.Network;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.api.modules.common.service.UserService;
import com.imyeyu.api.modules.git.bean.gitea.API;
import com.imyeyu.api.modules.git.bean.gitea.Branch;
import com.imyeyu.api.modules.git.bean.gitea.File;
import com.imyeyu.api.modules.git.bean.gitea.GiteaAPI;
import com.imyeyu.api.modules.git.bean.gitea.GiteaResponse;
import com.imyeyu.api.modules.git.bean.gitea.Repository;
import com.imyeyu.api.modules.git.service.RepositoryService;
import com.imyeyu.api.modules.gitea.entity.User;
import com.imyeyu.api.modules.gitea.service.GiteaService;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.network.Network;
import com.imyeyu.spring.bean.Page;
import com.imyeyu.spring.bean.PageResult;
import jakarta.activation.MimetypesFileTypeMap;
@@ -72,7 +72,7 @@ public class RepositoryServiceImplement implements RepositoryService {
@Override
public PageResult<Repository> page(Page page) {
try {
ClassicHttpResponse resp = (ClassicHttpResponse) Request.get(API.REPO_LIST.buildURL(null, new HashMap<>() {{
ClassicHttpResponse resp = (ClassicHttpResponse) Request.get(GiteaAPI.REPO_LIST.buildURL(null, new HashMap<>() {{
put("uid", owner.getId());
put("sort", "updated");
put("order", "desc");
@@ -95,7 +95,7 @@ public class RepositoryServiceImplement implements RepositoryService {
@Override
public Repository get(String repoName) {
try {
String respText = Request.get(API.REPO_GET.buildURL(new HashMap<>() {{
String respText = Request.get(GiteaAPI.REPO_GET.buildURL(new HashMap<>() {{
put("owner", owner.getName());
put("repoName", repoName);
}})).execute().returnContent().asString();
@@ -109,7 +109,7 @@ public class RepositoryServiceImplement implements RepositoryService {
@Override
public List<Branch> listBranches(String repoName) {
try {
String respText = Request.get(API.REPO_BRANCHES_LIST.buildURL(new HashMap<>() {{
String respText = Request.get(GiteaAPI.REPO_BRANCHES_LIST.buildURL(new HashMap<>() {{
put("owner", owner.getName());
put("repoName", repoName);
}})).execute().returnContent().asString();
@@ -123,7 +123,7 @@ public class RepositoryServiceImplement implements RepositoryService {
@Override
public List<File> listFile(String repoName, String branch, String path) {
try {
String respText = Request.get(API.REPO_FILE_LIST.buildURL(new HashMap<>() {{
String respText = Request.get(GiteaAPI.REPO_FILE_LIST.buildURL(new HashMap<>() {{
put("owner", owner.getName());
put("repoName", repoName);
put("path", path);
@@ -152,7 +152,7 @@ public class RepositoryServiceImplement implements RepositoryService {
@Override
public InputStream getFileRaw(String repoName, String branch, String path) {
try {
ClassicHttpResponse resp = (ClassicHttpResponse) Request.get(API.REPO_FILE_RAW.buildURL(new HashMap<>() {{
ClassicHttpResponse resp = (ClassicHttpResponse) Request.get(GiteaAPI.REPO_FILE_RAW.buildURL(new HashMap<>() {{
put("owner", owner.getName());
put("repoName", repoName);
put("path", path);
@@ -169,7 +169,7 @@ public class RepositoryServiceImplement implements RepositoryService {
@Override
public String getFileMimeType(String repoName, String branch, String path) {
try {
String repoPath = settingService.getAsString(SettingKey.GIT_REPO_PATH);
String repoPath = settingService.getAsString(Setting.Module.Gitea.REPOSITORY_PATH);
if (TimiJava.isEmpty(repoPath)) {
// 根据文件名猜测
return new MimetypesFileTypeMap().getContentType(Network.uriFileName(path));
@@ -210,7 +210,7 @@ public class RepositoryServiceImplement implements RepositoryService {
@Override
public InputStream getArchive(String repoName, String branch) {
try {
ClassicHttpResponse resp = (ClassicHttpResponse) Request.get(API.REPO_ARCHIVE.buildURL(new HashMap<>() {{
ClassicHttpResponse resp = (ClassicHttpResponse) Request.get(GiteaAPI.REPO_ARCHIVE.buildURL(new HashMap<>() {{
put("owner", owner.getName());
put("repoName", repoName);
put("archiveFormat", "%s.tar.gz".formatted(branch));

View File

@@ -4,8 +4,8 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.imyeyu.api.bean.PreviewPage;
import com.imyeyu.api.bean.wechat.InitCodeResponse;
import com.imyeyu.api.modules.common.bean.MediaAttach;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.entity.Attachment;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.api.modules.common.service.AttachmentService;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.api.modules.journal.bean.RequiredUploadPermission;
@@ -68,8 +68,8 @@ public class JournalController {
public String initOpenId(@RequestBody String code) {
try {
ArgMap<String, String> args = new ArgMap<>();
args.put("appid", settingService.getAsString(SettingKey.JOURNAL_APP_ID));
args.put("secret", settingService.getAsString(SettingKey.JOURNAL_APP_SECRET));
args.put("appid", settingService.getAsString(Setting.Module.Journal.APP_ID));
args.put("secret", settingService.getAsString(Setting.Module.Journal.APP_SECRET));
args.put("js_code", code);
args.put("grant_type", "authorization_code");
String response = org.apache.hc.client5.http.fluent.Request.get(args.toURL("https://api.weixin.qq.com/sns/jscode2session"))

View File

@@ -1,6 +1,5 @@
package com.imyeyu.api.modules.journal.controller;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.api.modules.journal.bean.RequiredUploadPermission;
@@ -26,13 +25,13 @@ public class ToolController {
@GetMapping("/memo")
public String getMemo() {
return settingService.getAsString(SettingKey.JOURNAL_MEMO);
return settingService.getAsString(Setting.Module.Journal.MEMO);
}
@RequiredUploadPermission
@PostMapping("/memo/update")
public void updateMemo(@RequestBodyValue String data) {
Setting setting = settingService.getByKey(SettingKey.JOURNAL_MEMO);
Setting setting = settingService.getByKey(Setting.Module.Journal.MEMO);
setting.setValue(data);
settingService.update(setting);
}

View File

@@ -1,6 +1,6 @@
package com.imyeyu.api.modules.journal.util;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.api.modules.journal.bean.RequiredUploadPermission;
import com.imyeyu.java.TimiJava;
@@ -36,8 +36,8 @@ public class JournalAPIInterceptor implements HandlerInterceptor {
@PostConstruct
private void postConstruct() {
keys = Set.of(settingService.getAsString(SettingKey.JOURNAL_KEY).split(","));
openIds = Set.of(settingService.getAsString(SettingKey.JOURNAL_OPEN_ID_WHITE_LIST).split(","));
keys = settingService.getAsSet(Setting.Module.Journal.KEY);
openIds = settingService.getAsSet(Setting.Module.Journal.OPEN_ID_WHITE_LIST);
}
public boolean preHandle(@NonNull HttpServletRequest req, @NonNull HttpServletResponse resp, @NonNull Object handler) {

View File

@@ -1,13 +1,9 @@
package com.imyeyu.api.modules.minecraft.annotation;
import com.imyeyu.api.modules.common.service.SettingService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.spring.TimiSpring;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
@@ -41,9 +37,9 @@ public class RequiredFMCServerTokenInterceptor implements HandlerInterceptor {
if (requiredFMCServerToken == null) {
return true;
}
if (!settingService.getAsString(SettingKey.FMC_SERVER_TOKEN).equals(TimiSpring.getToken())) {
throw new TimiException(TimiCode.ARG_MISS).msgKey("token.illegal");
}
// if (!settingService.getAsString(SettingKey.FMC_SERVER_TOKEN).equals(TimiSpring.getToken())) {
// throw new TimiException(TimiCode.ARG_MISS).msgKey("token.illegal");
// }
return true;
}
return true;

View File

@@ -1,18 +1,16 @@
package com.imyeyu.api.modules.minecraft.controller;
import com.imyeyu.api.modules.blog.util.UserToken;
import com.imyeyu.api.modules.minecraft.service.FMCImageMapService;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.spring.annotation.AOPLog;
import com.imyeyu.spring.annotation.RequestRateLimit;
import com.imyeyu.spring.annotation.RequiredToken;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.extern.slf4j.Slf4j;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.api.annotation.EnableSetting;
import com.imyeyu.api.modules.blog.util.UserToken;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.minecraft.service.FMCImageMapService;
import com.imyeyu.spring.annotation.AOPLog;
import com.imyeyu.spring.annotation.RequestRateLimit;
import com.imyeyu.spring.annotation.RequiredToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
@@ -50,7 +48,6 @@ public class MinecraftController {
*/
@AOPLog
@RequiredToken
@EnableSetting(value = SettingKey.FMC_ENABLE_IMAGE_MAP_UPLOAD, message = "minecraft.fmc_image_map.off_service")
@RequestRateLimit
@PostMapping("/imagemap/upload")
public String uploadFMCImageMap(@NotNull @RequestParam("request") MultipartFile file) {

View File

@@ -1,25 +1,23 @@
package com.imyeyu.api.modules.minecraft.controller;
import jakarta.annotation.PostConstruct;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.api.annotation.EnableSetting;
import com.imyeyu.api.config.RedisConfig;
import com.imyeyu.api.modules.blog.util.UserToken;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.service.UserService;
import com.imyeyu.api.modules.minecraft.entity.MinecraftPlayer;
import com.imyeyu.api.modules.minecraft.service.PlayerService;
import com.imyeyu.api.modules.minecraft.vo.TokenRequest;
import com.imyeyu.api.modules.minecraft.vo.TokenResponse;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.spring.annotation.AOPLog;
import com.imyeyu.spring.annotation.RequestRateLimit;
import com.imyeyu.spring.annotation.RequiredToken;
import com.imyeyu.spring.util.Redis;
import com.imyeyu.spring.util.RedisSerializers;
import jakarta.annotation.PostConstruct;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
@@ -62,7 +60,6 @@ public class PlayerController {
* @return true 为已绑定
*/
@RequestRateLimit
@EnableSetting(value = SettingKey.FMC_PLAYER_LOGIN_ENABLE, message = "登录服务未启用")
@GetMapping("/bound/{name}")
public boolean isBound(@PathVariable("name") String name) {
return service.getByName(name) != null;
@@ -110,7 +107,6 @@ public class PlayerController {
@AOPLog
@RequestRateLimit
@EnableSetting(value = SettingKey.FMC_PLAYER_LOGIN_ENABLE, message = "登录服务未启用")
@PostMapping("/login")
public TokenResponse login(@RequestBody Long playerId, @RequestHeader("Token") String token) {
return service.login(playerId, token);
@@ -118,7 +114,6 @@ public class PlayerController {
@AOPLog
@RequestRateLimit
@EnableSetting(value = SettingKey.FMC_PLAYER_LOGIN_ENABLE, message = "登录服务未启用")
@PostMapping("/login/token")
public TokenResponse genLoginToken(@Valid @RequestBody TokenRequest request) {
return service.genLoginToken(request);

View File

@@ -1,9 +1,7 @@
package com.imyeyu.api.modules.minecraft.service.implement;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.api.config.RedisConfig;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.api.modules.common.entity.User;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.api.modules.common.service.UserService;
@@ -12,6 +10,8 @@ import com.imyeyu.api.modules.minecraft.mapper.PlayerMapper;
import com.imyeyu.api.modules.minecraft.service.PlayerService;
import com.imyeyu.api.modules.minecraft.vo.TokenRequest;
import com.imyeyu.api.modules.minecraft.vo.TokenResponse;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.spring.TimiSpring;
import com.imyeyu.spring.mapper.BaseMapper;
import com.imyeyu.spring.service.AbstractEntityService;
@@ -62,11 +62,12 @@ public class PlayerServiceImplement extends AbstractEntityService<MinecraftPlaye
}
// 自查重
List<MinecraftPlayer> playerList = listByUserId(player.getUserId());
if (settingService.getAsInt(SettingKey.FMC_MAX_BIND) <= playerList.size()) {
throw new TimiException(TimiCode.RESULT_BAD).msgKey("已达到最大绑定数量:%s 个".formatted(settingService.getAsInt(SettingKey.FMC_MAX_BIND)));
int maxValue = settingService.getAsInt(Setting.Module.ForeverMC.PLAYER_BIND_MAX);
if (maxValue <= playerList.size()) {
throw new TimiException(TimiCode.RESULT_BAD).msgKey("已达到最大绑定数量:%s 个".formatted(maxValue));
}
for (int i = 0; i < playerList.size(); i++) {
if (playerList.get(i).getName().equals(player.getName())) {
for (MinecraftPlayer minecraftPlayer : playerList) {
if (minecraftPlayer.getName().equals(player.getName())) {
throw new TimiException(TimiCode.RESULT_BAD).msgKey("已绑定此玩家名称");
}
}
@@ -113,7 +114,7 @@ public class PlayerServiceImplement extends AbstractEntityService<MinecraftPlaye
mapper.update(player);
String playerToken = UUID.randomUUID().toString();
long ttl = settingService.getAsInt(SettingKey.FMC_PLAYER_LOGIN_TOKEN_TTL) * Time.D;
long ttl = settingService.getAsTime(Setting.Module.ForeverMC.LOGIN_TOKEN_TTL);
redis.set(playerToken, playerId, ttl);
return new TokenResponse(userId, playerToken, Time.now() + ttl);
}
@@ -135,7 +136,8 @@ public class PlayerServiceImplement extends AbstractEntityService<MinecraftPlaye
user = userService.get(playerByName.getUserId());
}
if (user == null) {
throw new TimiException(TimiCode.RESULT_NULL).msgKey("未注册或绑定此玩家昵称,请到 https://%s 进行注册或绑定".formatted(settingService.getAsString(SettingKey.DOMAIN_SPACE)));
String spaceDomain = settingService.getAsString(Setting.Module.Domain.SPACE);
throw new TimiException(TimiCode.RESULT_NULL).msgKey("未注册或绑定此玩家昵称,请到 https://%s 进行注册或绑定".formatted(spaceDomain));
}
if (user.isBanning()) {
throw new TimiException(TimiCode.RESULT_BAN).msgKey("账号封禁中");
@@ -144,7 +146,7 @@ public class PlayerServiceImplement extends AbstractEntityService<MinecraftPlaye
throw new TimiException(TimiCode.ARG_BAD).msgKey("密码错误");
}
String token = UUID.randomUUID().toString();
long ttl = settingService.getAsInt(SettingKey.FMC_PLAYER_LOGIN_TOKEN_TTL) * Time.D;
long ttl = settingService.getAsTime(Setting.Module.ForeverMC.LOGIN_TOKEN_TTL);
redis.set(token, user.getId(), ttl);
return new TokenResponse(user.getId(), token, Time.now() + ttl);
}

View File

@@ -1,5 +1,9 @@
package com.imyeyu.api.modules.music.runner;
import com.imyeyu.api.config.CORSConfig;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.api.modules.music.handler.ControllerMessageHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFutureListener;
@@ -24,10 +28,6 @@ import io.netty.handler.stream.ChunkedWriteHandler;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import com.imyeyu.api.config.CORSConfig;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.api.modules.music.handler.ControllerMessageHandler;
import org.springframework.beans.BeansException;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
@@ -63,6 +63,10 @@ public class ControllerBootstrapRunner implements ApplicationRunner, Application
}
public void run(ApplicationArguments args) {
if (settingService.not(Setting.Module.Music.ENABLE)) {
return;
}
final DefaultFullHttpResponse NFP = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.NOT_FOUND);
final DefaultFullHttpResponse BRP = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST);
@@ -72,7 +76,7 @@ public class ControllerBootstrapRunner implements ApplicationRunner, Application
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(boss, worker);
bootstrap.channel(NioServerSocketChannel.class);
bootstrap.localAddress(new InetSocketAddress(settingService.getAsInt(SettingKey.MUSIC_CONTROLLER_PORT)));
bootstrap.localAddress(new InetSocketAddress(settingService.getAsInt(Setting.Module.Music.CONTROLLER_PORT)));
bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
@@ -86,7 +90,7 @@ public class ControllerBootstrapRunner implements ApplicationRunner, Application
@Override
public void channelRead(ChannelHandlerContext ctx, Object obj) throws Exception {
if (obj instanceof FullHttpRequest req) {
if (!req.uri().equals(settingService.getAsString(SettingKey.MUSIC_CONTROLLER_URI))) {
if (!req.uri().equals(settingService.getAsString(Setting.Module.Music.CONTROLLER_URI))) {
// 访问的路径不是 Web Socket 的端点地址,响应 404
ctx.channel().writeAndFlush(NFP).addListener(ChannelFutureListener.CLOSE);
return;
@@ -108,10 +112,10 @@ public class ControllerBootstrapRunner implements ApplicationRunner, Application
});
pipeline.addLast(new WebSocketServerCompressionHandler());
pipeline.addLast(new WebSocketServerProtocolHandler(
settingService.getAsString(SettingKey.MUSIC_CONTROLLER_URI),
settingService.getAsString(Setting.Module.Music.CONTROLLER_URI),
null,
true,
settingService.getAsInt(SettingKey.MUSIC_MAX_FRAME_LENGTH)
settingService.getAsInt(Setting.Module.Music.MAX_FRAME_LENGTH)
)
);
@@ -120,7 +124,7 @@ public class ControllerBootstrapRunner implements ApplicationRunner, Application
}
});
channel = bootstrap.bind().sync().channel();
log.info("TimiMusicRC controller service startup with " + settingService.getAsString(SettingKey.MUSIC_CONTROLLER_IP));
log.info("TimiMusicRC controller service startup with {}", settingService.getAsString(Setting.Module.Music.CONTROLLER_IP));
} catch (Exception e) {
log.error("TimiMusicRC controller service startup error", e);
}

View File

@@ -1,5 +1,8 @@
package com.imyeyu.api.modules.music.runner;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.api.modules.music.handler.PlayerMessageHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
@@ -12,9 +15,6 @@ import io.netty.handler.codec.string.StringDecoder;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.api.modules.music.handler.PlayerMessageHandler;
import org.springframework.beans.BeansException;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
@@ -50,19 +50,22 @@ public class PlayerBootstrapRunner implements ApplicationRunner, ApplicationList
}
public void run(ApplicationArguments args) {
if (settingService.not(Setting.Module.Music.ENABLE)) {
return;
}
ServerBootstrap bootstrap = new ServerBootstrap();
boss = new NioEventLoopGroup();
worker = new NioEventLoopGroup();
try {
bootstrap.group(boss, worker);
bootstrap.channel(NioServerSocketChannel.class);
bootstrap.localAddress(new InetSocketAddress(settingService.getAsInt(SettingKey.MUSIC_PLAYER_PORT)));
bootstrap.localAddress(new InetSocketAddress(settingService.getAsInt(Setting.Module.Music.PLAYER_PORT)));
bootstrap.childHandler(new ChannelInitializer<>() {
@Override
protected void initChannel(Channel ch) {
ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(
settingService.getAsInt(SettingKey.MUSIC_MAX_FRAME_LENGTH),
settingService.getAsInt(Setting.Module.Music.MAX_FRAME_LENGTH),
0,
4,
0,
@@ -77,7 +80,7 @@ public class PlayerBootstrapRunner implements ApplicationRunner, ApplicationList
channel = bootstrap.bind().sync().channel();
log.info("TimiMusicRC player service startup with " + settingService.getAsString(SettingKey.MUSIC_PLAYER_IP));
log.info("TimiMusicRC player service startup with {}", settingService.getAsString(Setting.Module.Music.PLAYER_IP));
} catch (Exception e) {
log.error("TimiMusicRC player service startup error", e);
}

View File

@@ -1,11 +1,11 @@
package com.imyeyu.api.modules.system.bean;
import com.imyeyu.api.TimiServerAPI;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.api.TimiServerAPI;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.service.SettingService;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.Getter;
@@ -174,7 +174,7 @@ public class ServerFile implements Serializable {
name = file.getName();
absolutePath = file.getAbsolutePath().replaceAll("\\\\", "/");
SettingService settingService = TimiServerAPI.applicationContext.getBean(SettingService.class);
absolutePath = absolutePath.substring(settingService.getAsString(SettingKey.SYSTEM_FILE_BASE).length());
absolutePath = absolutePath.substring(settingService.getAsString(Setting.Module.System.FILE_BASE_PATH).length());
modifiedAt = file.lastModified();
isFile = file.isFile();

View File

@@ -1,11 +1,6 @@
package com.imyeyu.api.modules.system.controller;
import com.imyeyu.io.IO;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.network.Network;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.api.modules.common.entity.Tag;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.api.modules.common.service.TagService;
@@ -23,6 +18,11 @@ import com.imyeyu.api.modules.system.task.async.FileUnZipAsyncTask;
import com.imyeyu.api.modules.system.task.async.FileZipAsyncTask;
import com.imyeyu.api.modules.system.util.ResourceHandler;
import com.imyeyu.api.modules.system.vo.ListFileToRequest;
import com.imyeyu.io.IO;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.network.Network;
import com.imyeyu.spring.TimiSpring;
import com.imyeyu.spring.annotation.AOPLog;
import com.imyeyu.spring.annotation.IgnoreGlobalReturn;
@@ -51,6 +51,7 @@ import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.RandomAccessFile;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -187,7 +188,7 @@ public class FileController implements TimiJava, OS.FileSystem {
public void read(HttpServletRequest req, HttpServletResponse resp) {
try {
String path = req.getServletPath().substring("/system/file/read".length());
path = settingService.getAsString(SettingKey.SYSTEM_FILE_BASE) + path;
path = settingService.getAsString(Setting.Module.System.FILE_BASE_PATH) + path;
if (TimiJava.isEmpty(path)) {
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
@@ -239,7 +240,7 @@ public class FileController implements TimiJava, OS.FileSystem {
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
path = settingService.getAsString(SettingKey.SYSTEM_FILE_BASE) + path;
path = settingService.getAsString(Setting.Module.System.FILE_BASE_PATH) + path;
File file = new File(path);
if (!file.exists()) {
log.warn("preview a not exist file: {}", path);
@@ -466,8 +467,8 @@ public class FileController implements TimiJava, OS.FileSystem {
public void download(HttpServletResponse resp) {
try {
String path = TimiSpring.cutURIStartAt("/system/file/download");
path = settingService.getAsString(SettingKey.SYSTEM_FILE_BASE) + path;
File file = new File(path);
path = settingService.getAsString(Setting.Module.System.FILE_BASE_PATH) + path;
File file = Paths.get(URI.create(path)).toFile();
service.checkAccessPermission(file.getAbsolutePath());
String mimeType = new Tika().detect(file);

View File

@@ -0,0 +1,19 @@
package com.imyeyu.api.modules.system.controller;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
/**
*
*
* @author 夜雨
* @since 2026-04-23 16:31
*/
@Slf4j
@RequiredArgsConstructor
@RequestMapping("/system/setting")
public class SettingController {
}

View File

@@ -3,15 +3,11 @@ package com.imyeyu.api.modules.system.controller;
import com.imyeyu.api.modules.common.entity.Attachment;
import com.imyeyu.api.modules.common.service.AttachmentService;
import com.imyeyu.api.modules.system.service.StatusService;
import com.imyeyu.api.modules.system.service.SystemService;
import com.imyeyu.api.modules.system.vo.SystemStatusHistoryView;
import com.imyeyu.api.modules.system.vo.SystemStatusSnapshotView;
import com.imyeyu.api.modules.system.vo.TempAttachRequest;
import com.imyeyu.io.IO;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.spring.annotation.AOPLog;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
@@ -38,7 +34,6 @@ import java.util.concurrent.Semaphore;
public class SystemController {
private final StatusService statusService;
private final SystemService service;
private final AttachmentService attachmentService;
private final Semaphore updateSemaphore = new Semaphore(1);
@@ -71,68 +66,6 @@ public class SystemController {
return statusService.getStatusHistory(window, metrics);
}
/**
* 更新系统
*
* @param file 更新文件
*/
@AOPLog
@PostMapping("/update")
public void update(@NotNull @RequestParam("file") MultipartFile file) {
if (updateSemaphore.tryAcquire()) {
try {
service.update(file);
} finally {
updateSemaphore.release();
}
} else {
throw new TimiException(TimiCode.ERROR_SERVICE_OFF).msgKey("TODO updating");
}
}
/**
* 恢复系统
*/
@AOPLog
@RequestMapping("/restore")
public void restore() {
if (restoreSemaphore.tryAcquire()) {
try {
service.restore();
} finally {
restoreSemaphore.release();
}
} else {
throw new TimiException(TimiCode.ERROR_SERVICE_OFF).msgKey("TODO updating");
}
}
/**
* 关闭系统
*/
@AOPLog
@RequestMapping("/shutdown")
public void shutdown() {
service.shutdown();
}
/**
* 重启系统
*/
@AOPLog
@RequestMapping("/reboot")
public void reboot() {
if (rebootSemaphore.tryAcquire()) {
try {
service.reboot();
} finally {
rebootSemaphore.release();
}
} else {
throw new TimiException(TimiCode.ERROR_SERVICE_OFF).msgKey("TODO rebooting");
}
}
/**
* 上传临时附件
*

View File

@@ -1,18 +0,0 @@
package com.imyeyu.api.modules.system.service;
import org.springframework.web.multipart.MultipartFile;
/**
* @author 夜雨
* @version 2024-03-13 00:44
*/
public interface SystemService {
void update(MultipartFile file);
void restore();
void shutdown();
void reboot();
}

View File

@@ -1,26 +1,22 @@
package com.imyeyu.api.modules.system.service.implement;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.api.modules.system.bean.ServerFile;
import com.imyeyu.api.modules.system.bean.TransferFile;
import com.imyeyu.api.modules.system.service.AsyncTaskService;
import com.imyeyu.api.modules.system.service.FileService;
import com.imyeyu.api.modules.system.util.SystemAPIInterceptor;
import com.imyeyu.io.IO;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.api.modules.system.bean.FileSyncConfig;
import com.imyeyu.api.modules.system.bean.ServerFile;
import com.imyeyu.api.modules.system.bean.TransferFile;
import com.imyeyu.api.modules.system.entity.AsyncTask;
import com.imyeyu.api.modules.system.service.AsyncTaskService;
import com.imyeyu.api.modules.system.service.FileService;
import com.imyeyu.api.modules.system.task.async.FileSyncTask;
import com.imyeyu.api.modules.system.util.SystemAPIInterceptor;
import com.imyeyu.utils.Decoder;
import com.imyeyu.utils.OS;
import jakarta.annotation.PostConstruct;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.config.CronTask;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.stereotype.Service;
@@ -33,7 +29,6 @@ import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import java.util.Map;
/**
* 文件服务,不可直接使用入参路径
@@ -70,30 +65,30 @@ public class FileServiceImplement implements TimiJava, FileService {
@PostConstruct
private void fileSyncPostConstruct() {
FileSyncConfig config = settingService.fromYaml(SettingKey.SYSTEM_FILE_SYNC, FileSyncConfig.class);
if (config.isEnable()) {
scheduledTaskRegistrar.scheduleCronTask(new CronTask(() -> {
Map<String, FileSyncConfig.Task> tasks = config.getTasks();
configTask: for (Map.Entry<String, FileSyncConfig.Task> item : tasks.entrySet()) {
if (item.getValue().isEnable()) {
List<AbstractAsyncTask> runningTaskList = asyncTaskService.listAll();
for (int i = 0; i < runningTaskList.size(); i++) {
AbstractAsyncTask runningTask = runningTaskList.get(i);
if (runningTask.getType() == AsyncTask.Type.FILE_SYNC && runningTask.getName().equals(item.getKey())) {
continue configTask;
}
}
FileSyncTask task = new FileSyncTask(item.getKey(), item.getValue());
asyncTaskService.addAsyncTask(task);
}
}
}, config.getCron()));
}
// FileSyncConfig config = settingService.fromYaml(SettingKey.SYSTEM_FILE_SYNC, FileSyncConfig.class);
// if (config.isEnable()) {
// scheduledTaskRegistrar.scheduleCronTask(new CronTask(() -> {
// Map<String, FileSyncConfig.Task> tasks = config.getTasks();
// configTask: for (Map.Entry<String, FileSyncConfig.Task> item : tasks.entrySet()) {
// if (item.getValue().isEnable()) {
// List<AbstractAsyncTask> runningTaskList = asyncTaskService.listAll();
// for (int i = 0; i < runningTaskList.size(); i++) {
// AbstractAsyncTask runningTask = runningTaskList.get(i);
// if (runningTask.getType() == AsyncTask.Type.FILE_SYNC && runningTask.getName().equals(item.getKey())) {
// continue configTask;
// }
// }
// FileSyncTask task = new FileSyncTask(item.getKey(), item.getValue());
// asyncTaskService.addAsyncTask(task);
// }
// }
// }, config.getCron()));
// }
}
@PostConstruct
private void fileFilterPostConstruct() {
option = settingService.fromYaml(SettingKey.SYSTEM_FILE_FILTER, FilterOption.class);
// option = settingService.fromYaml(SettingKey.SYSTEM_FILE_FILTER, FilterOption.class);
}
@Override
@@ -262,7 +257,7 @@ public class FileServiceImplement implements TimiJava, FileService {
}
private String getPath(String path) {
String basePath = settingService.getAsString(SettingKey.SYSTEM_FILE_BASE);
String basePath = settingService.getAsString(Setting.Module.System.FILE_BASE_PATH);
if (TimiJava.isEmpty(path)) {
return basePath;
}

View File

@@ -1,6 +1,6 @@
package com.imyeyu.api.modules.system.service.implement;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.api.modules.system.bean.ServerStatus;
import com.imyeyu.api.modules.system.service.StatusService;
@@ -33,7 +33,7 @@ public class StatusServiceImplement implements StatusService {
@Override
public SystemStatusSnapshotView getStatus(String metrics) {
long serverTime = Time.now();
int sampleRateMs = settingService.getAsInt(SettingKey.SYSTEM_STATUS_RATE);
int sampleRateMs = settingService.getAsInt(Setting.Module.System.STATUS_RATE);
EnumSet<Metric> selectedMetrics = parseMetrics(metrics);
synchronized (serverStatus) {
@@ -48,7 +48,7 @@ public class StatusServiceImplement implements StatusService {
@Override
public SystemStatusHistoryView getStatusHistory(String window, String metrics) {
long serverTime = Time.now();
int sampleRateMs = settingService.getAsInt(SettingKey.SYSTEM_STATUS_RATE);
int sampleRateMs = settingService.getAsInt(Setting.Module.System.STATUS_RATE);
EnumSet<Metric> selectedMetrics = parseMetrics(metrics);
synchronized (serverStatus) {
@@ -261,7 +261,7 @@ public class StatusServiceImplement implements StatusService {
*/
private long parseWindowMs(String window, int sampleRateMs) {
if (window == null || window.isBlank()) {
return (long) settingService.getAsInt(SettingKey.SYSTEM_STATUS_LIMIT) * sampleRateMs;
return (long) settingService.getAsInt(Setting.Module.System.STATUS_LIMIT) * sampleRateMs;
}
String normalized = window.trim().toLowerCase(Locale.ROOT);
@@ -277,7 +277,7 @@ public class StatusServiceImplement implements StatusService {
try {
return Math.max(sampleRateMs, Long.parseLong(valueText) * unit);
} catch (NumberFormatException e) {
return (long) settingService.getAsInt(SettingKey.SYSTEM_STATUS_LIMIT) * sampleRateMs;
return (long) settingService.getAsInt(Setting.Module.System.STATUS_LIMIT) * sampleRateMs;
}
}

View File

@@ -1,73 +0,0 @@
package com.imyeyu.api.modules.system.service.implement;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import com.imyeyu.io.IO;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.api.TimiServerAPI;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.api.modules.system.service.SystemService;
import com.imyeyu.utils.OS;
import org.springframework.boot.SpringApplication;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.naming.NoPermissionException;
import java.io.IOException;
/**
* @author 夜雨
* @version 2024-03-13 00:45
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class SystemServiceImplement implements SystemService {
private final SettingService settingService;
@Override
public void update(MultipartFile file) {
try {
IO.toFile(IO.file("timi-server-api.jar"), file.getInputStream());
} catch (NoPermissionException | IOException e) {
log.error("update core error", e);
throw new TimiException(TimiCode.ERROR).msgKey("TODO update core error");
}
}
@Override
public void restore() {
try {
IO.copy(IO.file("default.jar"), IO.file("timi-server-api.jar").getAbsolutePath());
} catch (NoPermissionException | IOException e) {
log.error("restore core error", e);
throw new TimiException(TimiCode.ERROR).msgKey("TODO restore core error");
}
}
@Override
public void shutdown() {
if (TimiServerAPI.applicationContext instanceof AbstractApplicationContext ctx) {
ctx.close();
}
}
@Async
@Override
public void reboot() {
if (TimiServerAPI.applicationContext instanceof AbstractApplicationContext ctx) {
String command = settingService.getAsString(SettingKey.SYSTEM_REBOOT_COMMAND);
if (TimiJava.isEmpty(command)) {
throw new TimiException(TimiCode.ERROR_NPE_VARIABLE).msgKey("TODO not support reboot");
}
OS.runAfterShutdown(command);
SpringApplication.exit(ctx);
}
}
}

View File

@@ -1,29 +1,31 @@
package com.imyeyu.api.modules.system.service.implement;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.CallbackArg;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.api.modules.system.bean.TerminalPipe;
import com.imyeyu.api.modules.system.service.TerminalService;
import com.imyeyu.api.modules.system.vo.terminal.ExecCommand;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.CallbackArg;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.spring.TimiSpring;
import com.imyeyu.utils.OS;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
/**
* 指令服务
@@ -50,7 +52,8 @@ public class TerminalServiceImplement implements TerminalService, TimiJava, OS.F
@PostConstruct
private void postConstruct() {
execLogFilters.addAll(List.of(settingService.getAsString(SettingKey.SYSTEM_TERMINAL_FILTERS).split(",")));
// ArrayNode array = settingService.getAsArrayNode(Setting.Module.System.TERMINAL_FILTERS);
// execLogFilters.addAll(array.valueStream().map(JsonNode::asText).collect(Collectors.toSet()));
}
@Override

View File

@@ -1,6 +1,6 @@
package com.imyeyu.api.modules.system.task;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.api.modules.system.bean.ServerStatus;
import com.imyeyu.api.modules.system.task.status.StatusCollectContext;
@@ -63,10 +63,10 @@ public class ServerStatusTask implements SchedulingConfigurer {
collector.collect(context);
}
status.getUpdateAxis().addLast(context.getCollectAt());
if (settingService.getAsInt(SettingKey.SYSTEM_STATUS_LIMIT) < status.getUpdateAxis().size()) {
if (settingService.getAsInt(Setting.Module.System.STATUS_LIMIT) < status.getUpdateAxis().size()) {
status.getUpdateAxis().pollFirst();
}
}
}, triggerContext -> new CronTrigger("0/%s * * * * ?".formatted(settingService.getAsInt(SettingKey.SYSTEM_STATUS_RATE) / 1000)).nextExecution(triggerContext));
}, triggerContext -> new CronTrigger("0/%s * * * * ?".formatted(settingService.getAsInt(Setting.Module.System.STATUS_RATE) / 1000)).nextExecution(triggerContext));
}
}

View File

@@ -1,12 +1,12 @@
package com.imyeyu.api.modules.system.task;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.api.modules.system.bean.TerminalPipe;
import com.imyeyu.api.modules.system.service.TerminalService;
import com.imyeyu.utils.Time;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
@@ -30,10 +30,10 @@ public class TerminalTask {
private void run() {
service.listTerminalPipe().entrySet().removeIf(entry -> {
if (entry.getValue().getStatus() == TerminalPipe.Status.DIED) {
log.info("kill the died terminal session: " + entry.getKey());
log.info("kill the died terminal session: {}", entry.getKey());
return true;
}
long diedAt = entry.getValue().getLastExecAt() + Time.M * settingService.getAsInt(SettingKey.SYSTEM_TERMINAL_TTL);
long diedAt = entry.getValue().getLastExecAt() + settingService.getAsTime(Setting.Module.System.TERMINAL_TTL);
if (diedAt < Time.now()) {
entry.getValue().destroy();
log.info("kill the timeout terminal session [DIED at: {}]: {}", Time.toDateTime(diedAt), entry.getKey());

View File

@@ -1,6 +1,6 @@
package com.imyeyu.api.modules.system.task.status;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.entity.Setting;
import java.util.Deque;
@@ -22,7 +22,7 @@ public abstract class AbstractDequeStatusCollector implements StatusCollector {
*/
protected <T> void putDeque(StatusCollectContext context, Deque<T> deque, T value) {
deque.addLast(value);
if (context.getSettingService().getAsInt(SettingKey.SYSTEM_STATUS_LIMIT) < deque.size()) {
if (context.getSettingService().getAsInt(Setting.Module.System.STATUS_LIMIT) < deque.size()) {
deque.pollFirst();
}
}

View File

@@ -1,10 +1,9 @@
package com.imyeyu.api.modules.system.task.status.collector;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.api.modules.system.task.status.AbstractDequeStatusCollector;
import com.imyeyu.api.modules.system.task.status.StatusCollectContext;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.librealsense.context;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import oshi.hardware.NetworkIF;
@@ -25,7 +24,7 @@ public class NetworkStatusCollector extends AbstractDequeStatusCollector {
@Override
public void initialize(StatusCollectContext context) {
List<NetworkIF> networkIFs = context.getHardware().getNetworkIFs();
String targetMac = context.getSettingService().getAsString(SettingKey.SYSTEM_STATUS_NETWORK_MAC);
String targetMac = context.getSettingService().getAsString(Setting.Module.System.STATUS_NETWORK_MAC);
for (NetworkIF networkIF : networkIFs) {
if (networkIF.getMacaddr().equals(targetMac)) {
networkIF.updateAttributes();
@@ -42,8 +41,8 @@ public class NetworkStatusCollector extends AbstractDequeStatusCollector {
@Override
public void collect(StatusCollectContext context) {
String targetMac = context.getSettingService().getAsString(SettingKey.SYSTEM_STATUS_NETWORK_MAC);
int sampleRateMs = context.getSettingService().getAsInt(SettingKey.SYSTEM_STATUS_RATE);
String targetMac = context.getSettingService().getAsString(Setting.Module.System.STATUS_NETWORK_MAC);
int sampleRateMs = context.getSettingService().getAsInt(Setting.Module.System.STATUS_RATE);
for (NetworkIF networkIF : context.getHardware().getNetworkIFs()) {
if (networkIF.getMacaddr().equals(targetMac)) {
networkIF.updateAttributes();

View File

@@ -1,9 +1,9 @@
package com.imyeyu.api.modules.system.util;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.java.TimiJava;
import com.imyeyu.java.bean.timi.TimiCode;
import com.imyeyu.java.bean.timi.TimiException;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.spring.TimiSpring;
import jakarta.servlet.http.HttpServletRequest;
@@ -33,8 +33,8 @@ public class SystemAPIInterceptor implements HandlerInterceptor {
if (TimiJava.isEmpty(key)) {
key = req.getParameter("token");
}
String dbKey = settingService.getAsString(SettingKey.SYSTEM_API_KEY);
String dbSuperKey = settingService.getAsString(SettingKey.SYSTEM_API_SUPER_KEY);
String dbKey = settingService.getAsString(Setting.Module.System.API_KEY);
String dbSuperKey = settingService.getAsString(Setting.Module.System.API_KEY_SUPER);
if (dbSuperKey.equals(key)) {
TimiSpring.setRequestAttr(IS_SUPER_KEY, true);
return true;

View File

@@ -1,18 +1,11 @@
package com.imyeyu.api.util;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.imyeyu.api.modules.common.bean.SettingKey;
import com.imyeyu.api.modules.common.entity.Multilingual;
import com.imyeyu.api.modules.common.entity.Setting;
import com.imyeyu.api.modules.common.service.SettingService;
import com.imyeyu.api.modules.system.bean.ServerFile;
import com.imyeyu.java.ref.Ref;
import com.imyeyu.java.TimiJava;
import com.imyeyu.lang.mapper.AbstractLanguageMapper;
import com.imyeyu.spring.TimiSpring;
import com.imyeyu.spring.util.GlobalReturnHandler;
import com.imyeyu.spring.util.Redis;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.jgit.api.ArchiveCommand;
@@ -23,10 +16,7 @@ import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* SpringBoot 启动事件,主要输出基本参数,避免混淆运行环境
@@ -57,7 +47,6 @@ public class InitApplication implements ApplicationRunner {
private final SettingService settingService;
private final RedisMultilingual redisMultilingual;
private final GlobalReturnHandler globalReturnHandler;
private final Redis<Long, Multilingual> redisLanguage;
private void logBaseInfo() {
log.info("JDBC URL: {}", jdbcURL);
@@ -65,7 +54,7 @@ public class InitApplication implements ApplicationRunner {
log.info("System Setting:");
List<Setting> settings = settingService.listAll();
for (Setting setting : settings) {
String value = Objects.requireNonNullElse(setting.getValue(), "");
String value = TimiJava.defaultIfEmpty(setting.getValue(), "");
if (64 < value.length()) {
value = value.substring(0, 64) + "..";
}
@@ -86,38 +75,13 @@ public class InitApplication implements ApplicationRunner {
});
}
private void initFileType() {
ObjectNode items = settingService.getAsJsonObject(SettingKey.SYSTEM_FILE_TYPE);
String[] extensions;
ArrayNode extensionsArray;
JsonNode itemObject;
List<String> extensionsList;
for (Map.Entry<String, JsonNode> item : (Iterable<Map.Entry<String, JsonNode>>) items::fields) {
ServerFile.FileType fileType = Ref.toType(ServerFile.FileType.class, item.getKey());
itemObject = item.getValue();
extensionsList = new ArrayList<>();
extensionsArray = (ArrayNode) itemObject.get("extensions");
for (JsonNode extensionNode : extensionsArray) {
if (extensionNode.isObject()) {
extensionsList.add(extensionNode.path("value").asText());
} else {
extensionsList.add(extensionNode.asText());
}
}
extensions = new String[extensionsList.size()];
// 设置扩展名所属文件类型
fileType.setExtensions(extensionsList.toArray(extensions));
}
}
@Override
public void run(ApplicationArguments args) throws Exception {
Method[] methods = getClass().getDeclaredMethods();
for (int i = 0; i < methods.length; i++) {
if (!methods[i].getName().equals("run") && !methods[i].getName().contains("$")) {
methods[i].setAccessible(true);
methods[i].invoke(this);
for (Method method : methods) {
if (!method.getName().equals("run") && !method.getName().contains("$")) {
method.setAccessible(true);
method.invoke(this);
}
}
}