refactor(system/client): 完善客户端管理

This commit is contained in:
2024-12-27 21:54:10 +08:00
parent 144251b21e
commit 229bd9becf
9 changed files with 105 additions and 110 deletions

View File

@@ -45,6 +45,12 @@ public class OnlineUserQuery implements Serializable {
@Schema(description = "用户昵称", example = "张三")
private String nickname;
/**
* 客户端 ID
*/
@Schema(description = "客户端 ID", example = "ef51c9a3e9046c4f2ea45142c8a8344a")
private String clientId;
/**
* 登录时间
*/

View File

@@ -68,6 +68,18 @@ public class OnlineUserResp implements Serializable {
@Schema(description = "昵称", example = "张三")
private String nickname;
/**
* 客户端类型
*/
@Schema(description = "客户端类型", example = "PC")
private String clientType;
/**
* 客户端 ID
*/
@Schema(description = "客户端 ID", example = "ef51c9a3e9046c4f2ea45142c8a8344a")
private String clientId;
/**
* 登录 IP
*/

View File

@@ -73,18 +73,20 @@ public class OnlineUserServiceImpl implements OnlineUserService {
for (Map.Entry<Long, List<String>> entry : tokenMap.entrySet()) {
Long userId = entry.getKey();
UserContext userContext = UserContextHolder.getContext(userId);
if (null == userContext || !this.isMatchNickname(query.getNickname(), userContext)) {
if (null == userContext || !this.isMatchNickname(query.getNickname(), userContext) || !this
.isMatchClientId(query.getClientId(), userContext)) {
continue;
}
List<Date> loginTimeList = query.getLoginTime();
entry.getValue().parallelStream().forEach(token -> {
UserExtraContext extraContext = UserContextHolder.getExtraContext(token);
if (this.isMatchLoginTime(loginTimeList, extraContext.getLoginTime())) {
OnlineUserResp resp = BeanUtil.copyProperties(userContext, OnlineUserResp.class);
BeanUtil.copyProperties(extraContext, resp);
resp.setToken(token);
list.add(resp);
if (!this.isMatchLoginTime(loginTimeList, extraContext.getLoginTime())) {
return;
}
OnlineUserResp resp = BeanUtil.copyProperties(userContext, OnlineUserResp.class);
BeanUtil.copyProperties(extraContext, resp);
resp.setToken(token);
list.add(resp);
});
}
// 设置排序
@@ -121,6 +123,20 @@ public class OnlineUserServiceImpl implements OnlineUserService {
.getNickname(userContext.getId()), nickname);
}
/**
* 是否匹配客户端 ID
*
* @param clientId 客户端 ID
* @param userContext 用户上下文信息
* @return 是否匹配客户端 ID
*/
private boolean isMatchClientId(String clientId, UserContext userContext) {
if (StrUtil.isBlank(clientId)) {
return true;
}
return Objects.equals(userContext.getClientId(), clientId);
}
/**
* 是否匹配登录时间
*

View File

@@ -1,87 +0,0 @@
/*
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package top.continew.admin.system.model.resp;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import top.continew.admin.common.base.BaseDetailResp;
import top.continew.admin.common.enums.DisEnableStatusEnum;
import java.io.Serial;
import java.util.List;
/**
* 客户端详情信息
*
* @author KAI
* @since 2024/12/03 16:04
*/
@Data
@Schema(description = "客户端详情信息")
public class ClientDetailResp extends BaseDetailResp {
@Serial
private static final long serialVersionUID = 1L;
/**
* 客户端ID
*/
@Schema(description = "客户端ID")
private String clientId;
/**
* 客户端Key
*/
@Schema(description = "客户端Key")
private String clientKey;
/**
* 客户端秘钥
*/
@Schema(description = "客户端秘钥")
private String clientSecret;
/**
* 登录类型
*/
@Schema(description = "登录类型")
private List<String> authType;
/**
* 客户端类型
*/
@Schema(description = "客户端类型")
private String clientType;
/**
* Token最低活跃频率-1为不限制
*/
@Schema(description = "Token最低活跃频率-1为不限制")
private Integer activeTimeout;
/**
* Token有效期默认30天单位
*/
@Schema(description = "Token有效期默认30天单位")
private Integer timeout;
/**
* 状态
*/
@Schema(description = "状态", example = "1")
private DisEnableStatusEnum status;
}

View File

@@ -72,13 +72,13 @@ public class ClientResp extends BaseDetailResp {
* Token 最低活跃频率(单位:秒,-1不限制永不冻结
*/
@Schema(description = "Token 最低活跃频率(单位:秒,-1不限制永不冻结", example = "1800")
private Integer activeTimeout;
private Long activeTimeout;
/**
* Token 有效期(单位:秒,-1永不过期
*/
@Schema(description = "Token 有效期(单位:秒,-1永不过期", example = "86400")
private Integer timeout;
private Long timeout;
/**
* 状态

View File

@@ -18,8 +18,10 @@ package top.continew.admin.system.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.crypto.digest.DigestUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import top.continew.admin.auth.enums.AuthTypeEnum;
import top.continew.admin.auth.model.query.OnlineUserQuery;
import top.continew.admin.auth.service.OnlineUserService;
import top.continew.admin.system.mapper.ClientMapper;
import top.continew.admin.system.model.entity.ClientDO;
import top.continew.admin.system.model.query.ClientQuery;
@@ -27,7 +29,7 @@ import top.continew.admin.system.model.req.ClientReq;
import top.continew.admin.system.model.resp.ClientResp;
import top.continew.admin.system.service.ClientService;
import top.continew.starter.core.constant.StringConstants;
import top.continew.starter.core.validation.ValidationUtils;
import top.continew.starter.core.validation.CheckUtils;
import top.continew.starter.extension.crud.service.BaseServiceImpl;
import java.util.List;
@@ -40,8 +42,11 @@ import java.util.List;
* @since 2024/12/03 16:04
*/
@Service
@RequiredArgsConstructor
public class ClientServiceImpl extends BaseServiceImpl<ClientMapper, ClientDO, ClientResp, ClientResp, ClientQuery, ClientReq> implements ClientService {
private final OnlineUserService onlineUserService;
@Override
public void beforeAdd(ClientReq req) {
String clientId = DigestUtil.md5Hex(req.getClientKey() + StringConstants.COLON + req.getClientSecret());
@@ -50,13 +55,13 @@ public class ClientServiceImpl extends BaseServiceImpl<ClientMapper, ClientDO, C
@Override
public void beforeDelete(List<Long> ids) {
// 查询如果删除客户端记录以后是否还存在账号认证的方式,不存在则不允许删除
List<ClientDO> clientList = baseMapper.lambdaQuery()
.in(ClientDO::getId, ids)
.like(ClientDO::getAuthType, AuthTypeEnum.ACCOUNT.getValue())
.list();
ValidationUtils.throwIfEmpty(clientList, "请至少保留 [{}] 认证类型", AuthTypeEnum.ACCOUNT.getDescription());
super.beforeDelete(ids);
// 如果还存在在线用户,则不能删除
OnlineUserQuery query = new OnlineUserQuery();
for (Long id : ids) {
ClientDO client = this.getById(id);
query.setClientId(client.getClientId());
CheckUtils.throwIfNotEmpty(onlineUserService.list(query), "客户端 [{}] 还存在在线用户,不能删除", client.getClientKey());
}
}
@Override

View File

@@ -300,14 +300,15 @@ CREATE TABLE IF NOT EXISTS `sys_client` (
`client_id` varchar(50) NOT NULL COMMENT '客户端ID',
`client_key` varchar(255) NOT NULL COMMENT '客户端Key',
`client_secret` varchar(255) NOT NULL COMMENT '客户端秘钥',
`auth_type` json DEFAULT NULL COMMENT '认证类型',
`auth_type` json NOT NULL COMMENT '认证类型',
`client_type` varchar(50) NOT NULL COMMENT '客户端类型',
`active_timeout` int DEFAULT '-1' COMMENT 'Token最低活跃频率-1不限制)',
`timeout` int DEFAULT '2592000' COMMENT 'Token有效期默认30天单位:秒)',
`active_timeout` bigint(20) DEFAULT -1 COMMENT 'Token最低活跃频率单位:秒,-1不限制,永不冻结',
`timeout` bigint(20) DEFAULT 2592000 COMMENT 'Token有效期单位-1永不过期',
`status` tinyint(1) UNSIGNED NOT NULL DEFAULT 1 COMMENT '状态1启用2禁用',
`create_user` bigint(20) NOT NULL COMMENT '创建人',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_user` bigint(20) DEFAULT NULL COMMENT '修改人',
`update_time` datetime DEFAULT NULL COMMENT '修改时间',
PRIMARY KEY (`id`)
PRIMARY KEY (`id`),
UNIQUE INDEX `uk_client_id`(`client_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客户端表';

View File

@@ -76,6 +76,13 @@ VALUES
(1114, '修改', 1110, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:storage:update', 4, 1, 1, NOW()),
(1115, '删除', 1110, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:storage:delete', 5, 1, 1, NOW()),
( 1180, '客户端管理', 1000, 2, '/system/client', 'SystemClient', 'system/client/index', NULL, 'mobile', false, false, false, NULL, 9, 1, 1, NOW()),
(1181, '列表', 1180, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:client:list', 1, 1, 1, NOW()),
(1182, '详情', 1180, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:client:detail', 2, 1, 1, NOW()),
(1183, '新增', 1180, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:client:add', 3, 1, 1, NOW()),
(1184, '修改', 1180, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:client:update', 4, 1, 1, NOW()),
(1185, '删除', 1180, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:client:delete', 5, 1, 1, NOW()),
(1190, '系统配置', 1000, 2, '/system/config', 'SystemConfig', 'system/config/index', NULL, 'config', false, false, false, NULL, 999, 1, 1, NOW()),
(1191, '查看', 1190, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:config:list', 1, 1, 1, NOW()),
(1192, '修改', 1190, 3, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'system:config:update', 2, 1, 1, NOW()),
@@ -150,7 +157,8 @@ INSERT INTO "sys_dict"
("id", "name", "code", "description", "is_system", "create_user", "create_time")
VALUES
(1, '公告类型', 'notice_type', NULL, true, 1, NOW()),
(2, '消息类型', 'message_type', NULL, true, 1, NOW());
(2, '消息类型', 'message_type', NULL, true, 1, NOW()),
(3, '客户端类型', 'client_type', NULL, true, 1, NOW());
INSERT INTO "sys_dict_item"
("id", "label", "value", "color", "sort", "description", "status", "dict_id", "create_user", "create_time")
@@ -158,7 +166,10 @@ VALUES
(1, '通知', '1', 'blue', 1, NULL, 1, 1, 1, NOW()),
(2, '活动', '2', 'orangered', 2, NULL, 1, 1, 1, NOW()),
(3, '安全消息', '1', 'blue', 1, NULL, 1, 2, 1, NOW()),
(4, '活动消息', '2', 'orangered', 2, NULL, 1, 2, 1, NOW());
(4, '活动消息', '2', 'orangered', 2, NULL, 1, 2, 1, NOW()),
(5, '桌面端', 'PC', 'blue', 1, NULL, 1, 3, 1, NOW()),
(6, '安卓', 'ANDROID', '#148628', 2, NULL, 1, 3, 1, NOW()),
(7, '小程序', 'XCX', '#7930AD', 3, NULL, 1, 3, 1, NOW());
-- 初始化默认用户和角色关联数据
INSERT INTO "sys_user_role"

View File

@@ -490,3 +490,34 @@ COMMENT ON COLUMN "sys_file"."update_user" IS '修改人';
COMMENT ON COLUMN "sys_file"."update_time" IS '修改时间';
COMMENT ON TABLE "sys_file" IS '文件表';
CREATE TABLE IF NOT EXISTS "sys_client" (
"id" int8 NOT NULL,
"client_id" varchar(50) NOT NULL,
"client_key" varchar(255) NOT NULL,
"client_secret" varchar(255) NOT NULL,
"auth_type" json NOT NULL,
"client_type" varchar(50) NOT NULL,
"active_timeout" int8 NOT NULL DEFAULT -1,
"timeout" int8 NOT NULL DEFAULT 2592000,
"status" int2 NOT NULL DEFAULT 1,
"create_user" int8 NOT NULL,
"create_time" timestamp NOT NULL,
"update_user" int8 DEFAULT NULL,
"update_time" timestamp DEFAULT NULL,
PRIMARY KEY ("id")
);
CREATE UNIQUE INDEX "uk_client_client_id" ON "sys_client" ("client_id");
COMMENT ON COLUMN "sys_client"."id" IS 'ID';
COMMENT ON COLUMN "sys_client"."client_id" IS '客户端ID';
COMMENT ON COLUMN "sys_client"."client_key" IS '客户端Key';
COMMENT ON COLUMN "sys_client"."client_secret" IS '客户端秘钥';
COMMENT ON COLUMN "sys_client"."auth_type" IS '认证类型';
COMMENT ON COLUMN "sys_client"."client_type" IS '客户端类型';
COMMENT ON COLUMN "sys_client"."active_timeout" IS 'Token最低活跃频率单位-1不限制永不冻结';
COMMENT ON COLUMN "sys_client"."timeout" IS 'Token有效期单位-1永不过期';
COMMENT ON COLUMN "sys_client"."status" IS '状态1启用2禁用';
COMMENT ON COLUMN "sys_client"."create_user" IS '创建人';
COMMENT ON COLUMN "sys_client"."create_time" IS '创建时间';
COMMENT ON COLUMN "sys_client"."update_user" IS '修改人';
COMMENT ON COLUMN "sys_client"."update_time" IS '修改时间';
COMMENT ON TABLE "sys_client" IS '客户端表';