mirror of
https://github.com/continew-org/continew-admin.git
synced 2025-09-09 08:57:16 +08:00
feat(plugin/tenant): 新增多租户插件模块 (#175)
This commit is contained in:
@@ -55,4 +55,5 @@ public interface AppService extends BaseService<AppResp, AppDetailResp, AppQuery
|
||||
* @return 应用信息
|
||||
*/
|
||||
AppDO getByAccessKey(String accessKey);
|
||||
|
||||
}
|
21
continew-plugin/continew-plugin-tenant/pom.xml
Normal file
21
continew-plugin/continew-plugin-tenant/pom.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>top.continew.admin</groupId>
|
||||
<artifactId>continew-plugin</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>continew-plugin-tenant</artifactId>
|
||||
<description>多租户插件</description>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>top.continew.admin</groupId>
|
||||
<artifactId>continew-system</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* 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.tenant.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.dev33.satoken.annotation.SaIgnore;
|
||||
import cn.dev33.satoken.annotation.SaMode;
|
||||
import cn.hutool.core.collection.ListUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import top.continew.admin.common.base.controller.BaseController;
|
||||
import top.continew.admin.common.config.properties.TenantProperties;
|
||||
import top.continew.admin.common.util.SecureUtils;
|
||||
import top.continew.admin.system.model.entity.MenuDO;
|
||||
import top.continew.admin.system.model.entity.user.UserDO;
|
||||
import top.continew.admin.system.model.req.user.UserPasswordResetReq;
|
||||
import top.continew.admin.system.service.*;
|
||||
import top.continew.admin.tenant.model.entity.TenantDO;
|
||||
import top.continew.admin.tenant.model.query.TenantQuery;
|
||||
import top.continew.admin.tenant.model.req.TenantLoginUserInfoReq;
|
||||
import top.continew.admin.tenant.model.req.TenantReq;
|
||||
import top.continew.admin.tenant.model.resp.*;
|
||||
import top.continew.admin.tenant.service.TenantDbConnectService;
|
||||
import top.continew.admin.tenant.service.TenantPackageService;
|
||||
import top.continew.admin.tenant.service.TenantService;
|
||||
import top.continew.starter.core.util.ExceptionUtils;
|
||||
import top.continew.starter.core.util.validation.CheckUtils;
|
||||
import top.continew.starter.core.util.validation.ValidationUtils;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
import top.continew.starter.extension.crud.model.entity.BaseIdDO;
|
||||
import top.continew.admin.common.base.model.resp.BaseResp;
|
||||
import top.continew.starter.extension.crud.model.req.IdsReq;
|
||||
import top.continew.starter.extension.crud.model.resp.IdResp;
|
||||
import top.continew.starter.extension.tenant.TenantHandler;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 租户管理 API
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/11/26 17:20
|
||||
*/
|
||||
@Tag(name = "租户管理 API")
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
@CrudRequestMapping(value = "/tenant/user", api = {Api.PAGE, Api.GET, Api.CREATE, Api.UPDATE, Api.DELETE})
|
||||
public class TenantController extends BaseController<TenantService, TenantResp, TenantDetailResp, TenantQuery, TenantReq> {
|
||||
|
||||
private final TenantProperties tenantProperties;
|
||||
private final DeptService deptService;
|
||||
private final MenuService menuService;
|
||||
private final TenantPackageService packageService;
|
||||
private final RoleService roleService;
|
||||
private final UserService userService;
|
||||
private final TenantSysDataService tenantSysDataService;
|
||||
private final RoleMenuService roleMenuService;
|
||||
private final TenantDbConnectService dbConnectService;
|
||||
|
||||
@GetMapping("/common")
|
||||
@SaIgnore
|
||||
@Operation(summary = "多租户通用信息查询", description = "多租户通用信息查询")
|
||||
public TenantCommonResp common() {
|
||||
TenantCommonResp commonResp = new TenantCommonResp();
|
||||
commonResp.setIsEnabled(tenantProperties.isEnabled());
|
||||
commonResp.setAvailableList(baseService.getAvailableList());
|
||||
return commonResp;
|
||||
}
|
||||
|
||||
@Override
|
||||
@DSTransactional
|
||||
public IdResp<Long> create(TenantReq req) {
|
||||
//套餐菜单
|
||||
TenantPackageDetailResp detailResp = packageService.get(req.getPackageId());
|
||||
CheckUtils.throwIf(detailResp.getMenuIds().isEmpty(), "该套餐无可用菜单");
|
||||
List<MenuDO> menuRespList = menuService.listByIds(detailResp.getMenuIds());
|
||||
//租户添加
|
||||
IdResp<Long> baseIdResp = super.create(req);
|
||||
//在租户中执行数据插入
|
||||
SpringUtil.getBean(TenantHandler.class).execute(baseIdResp.getId(), () -> {
|
||||
//租户部门初始化
|
||||
Long deptId = deptService.initTenantDept(req.getName());
|
||||
//租户菜单初始化
|
||||
menuService.menuInit(menuRespList, 0L, 0L);
|
||||
//租户角色初始化
|
||||
Long roleId = roleService.initTenantRole();
|
||||
//角色绑定菜单
|
||||
roleMenuService.add(menuService.listAll(baseIdResp.getId()).stream().map(BaseResp::getId).toList(), roleId);
|
||||
//管理用户初始化
|
||||
Long userId = userService.initTenantUser(req.getUsername(), req.getPassword(), deptId);
|
||||
//用户绑定角色
|
||||
roleService.assignToUsers(roleId, ListUtil.of(userId));
|
||||
//租户绑定用户
|
||||
baseService.bindUser(baseIdResp.getId(), userId);
|
||||
});
|
||||
return baseIdResp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete(Long id) {
|
||||
SpringUtil.getBean(TenantHandler.class).execute(id, () -> {
|
||||
//系统数据清除
|
||||
tenantSysDataService.clear();
|
||||
});
|
||||
super.delete(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void batchDelete(@Valid IdsReq ids) {
|
||||
for (Long id : ids.getIds()) {
|
||||
//在租户中执行数据清除
|
||||
SpringUtil.getBean(TenantHandler.class).execute(id, () -> {
|
||||
//系统数据清除
|
||||
tenantSysDataService.clear();
|
||||
});
|
||||
}
|
||||
super.batchDelete(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取租户管理账号用户名
|
||||
*/
|
||||
@GetMapping("/loginUser/{tenantId}")
|
||||
@Operation(summary = "获取租户管理账号信息", description = "获取租户管理账号信息")
|
||||
@SaCheckPermission("tenant:user:editLoginUserInfo")
|
||||
public String loginUserInfo(@PathVariable Long tenantId) {
|
||||
TenantDO tenantDO = baseService.getTenantById(tenantId);
|
||||
CheckUtils.throwIfNull(tenantDO, "租户不存在");
|
||||
StringBuilder username = new StringBuilder();
|
||||
SpringUtil.getBean(TenantHandler.class).execute(tenantDO.getId(), () -> {
|
||||
UserDO userDO = userService.getById(tenantDO.getUserId());
|
||||
CheckUtils.throwIfNull(userDO, "租户管理用户不存在");
|
||||
username.append(userDO.getUsername());
|
||||
});
|
||||
return username.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 租户管理账号信息更新
|
||||
*/
|
||||
@PutMapping("/loginUser")
|
||||
@Operation(summary = "租户管理账号信息更新", description = "租户管理账号信息更新")
|
||||
@SaCheckPermission("tenant:user:editLoginUserInfo")
|
||||
@DSTransactional
|
||||
public void editLoginUserInfo(@Validated @RequestBody TenantLoginUserInfoReq req) {
|
||||
TenantDO tenantDO = baseService.getTenantById(req.getTenantId());
|
||||
CheckUtils.throwIfNull(tenantDO, "租户不存在");
|
||||
SpringUtil.getBean(TenantHandler.class).execute(tenantDO.getId(), () -> {
|
||||
UserDO userDO = userService.getById(tenantDO.getUserId());
|
||||
CheckUtils.throwIfNull(userDO, "用户不存在");
|
||||
//修改用户名
|
||||
if (!req.getUsername().equals(userDO.getUsername())) {
|
||||
userService.update(Wrappers.lambdaUpdate(UserDO.class)
|
||||
.set(UserDO::getUsername, req.getUsername())
|
||||
.eq(BaseIdDO::getId, userDO.getId()));
|
||||
}
|
||||
//修改密码
|
||||
if (StrUtil.isNotEmpty(req.getPassword())) {
|
||||
String password = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(req.getPassword()));
|
||||
ValidationUtils.throwIfNull(password, "新密码解密失败");
|
||||
UserPasswordResetReq passwordResetReq = new UserPasswordResetReq();
|
||||
passwordResetReq.setNewPassword(password);
|
||||
userService.resetPassword(passwordResetReq, userDO.getId());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有租户套餐
|
||||
*/
|
||||
@GetMapping("/all/package")
|
||||
@Operation(summary = "查询所有租户套餐", description = "查询所有租户套餐")
|
||||
@SaCheckPermission(value = {"tenant:user:add", "tenant:user:update"}, mode = SaMode.OR)
|
||||
public List<TenantPackageResp> packageList() {
|
||||
return packageService.list(null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有数据库连接
|
||||
*/
|
||||
@GetMapping("/all/dbConnect")
|
||||
@Operation(summary = "获取租户数据连接列表", description = "获取租户数据连接列表")
|
||||
@SaCheckPermission(value = {"tenant:user:add", "tenant:user:update"}, mode = SaMode.OR)
|
||||
public List<TenantDbConnectResp> dbConnectList() {
|
||||
return dbConnectService.list(null, null);
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.tenant.controller;
|
||||
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import top.continew.admin.common.base.controller.BaseController;
|
||||
import top.continew.admin.tenant.model.query.TenantDbConnectQuery;
|
||||
import top.continew.admin.tenant.model.req.TenantDbConnectReq;
|
||||
import top.continew.admin.tenant.model.resp.TenantDbConnectDetailResp;
|
||||
import top.continew.admin.tenant.model.resp.TenantDbConnectResp;
|
||||
import top.continew.admin.tenant.service.TenantDbConnectService;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
|
||||
/**
|
||||
* 租户数据连接管理 API
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/12/12 19:13
|
||||
*/
|
||||
@Tag(name = "租户数据连接管理 API")
|
||||
@RestController
|
||||
@CrudRequestMapping(value = "/tenant/dbConnect", api = {Api.PAGE, Api.GET, Api.CREATE, Api.UPDATE, Api.DELETE})
|
||||
public class TenantDbConnectController extends BaseController<TenantDbConnectService, TenantDbConnectResp, TenantDbConnectDetailResp, TenantDbConnectQuery, TenantDbConnectReq> {}
|
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* 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.tenant.controller;
|
||||
|
||||
import cn.dev33.satoken.annotation.SaCheckPermission;
|
||||
import cn.hutool.core.lang.tree.Tree;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import top.continew.admin.common.base.controller.BaseController;
|
||||
import top.continew.admin.common.config.properties.TenantProperties;
|
||||
import top.continew.admin.common.constant.CacheConstants;
|
||||
import top.continew.admin.common.enums.DisEnableStatusEnum;
|
||||
import top.continew.admin.system.model.entity.MenuDO;
|
||||
import top.continew.admin.system.model.query.MenuQuery;
|
||||
import top.continew.admin.system.service.MenuService;
|
||||
import top.continew.admin.tenant.model.entity.TenantDO;
|
||||
import top.continew.admin.tenant.model.query.TenantPackageQuery;
|
||||
import top.continew.admin.tenant.model.req.TenantPackageReq;
|
||||
import top.continew.admin.tenant.model.resp.TenantPackageDetailResp;
|
||||
import top.continew.admin.tenant.model.resp.TenantPackageResp;
|
||||
import top.continew.admin.tenant.service.TenantPackageService;
|
||||
import top.continew.admin.tenant.service.TenantService;
|
||||
import top.continew.starter.cache.redisson.util.RedisUtils;
|
||||
import top.continew.starter.core.constant.StringConstants;
|
||||
import top.continew.starter.extension.crud.annotation.CrudRequestMapping;
|
||||
import top.continew.starter.extension.crud.enums.Api;
|
||||
import top.continew.starter.extension.tenant.TenantHandler;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 租户套餐管理 API
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/11/26 11:25
|
||||
*/
|
||||
@Tag(name = "租户套餐管理 API")
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
@CrudRequestMapping(value = "/tenant/package", api = {Api.LIST, Api.PAGE, Api.GET, Api.CREATE, Api.UPDATE, Api.DELETE})
|
||||
public class TenantPackageController extends BaseController<TenantPackageService, TenantPackageResp, TenantPackageDetailResp, TenantPackageQuery, TenantPackageReq> {
|
||||
|
||||
private final MenuService menuService;
|
||||
private final TenantProperties tenantProperties;
|
||||
private final TenantService tenantService;
|
||||
|
||||
@GetMapping("/menuTree")
|
||||
@SaCheckPermission("tenant:package:get")
|
||||
@Operation(summary = "获取租户套餐菜单", description = "获取租户套餐菜单")
|
||||
public List<Tree<Long>> menuTree() {
|
||||
MenuQuery query = new MenuQuery();
|
||||
//必须是启用状态的菜单
|
||||
query.setStatus(DisEnableStatusEnum.ENABLE);
|
||||
//过滤掉租户不能使用的菜单
|
||||
query.setExcludeMenuIdList(tenantProperties.getIgnoreMenus());
|
||||
return menuService.tree(query, null, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
@DSTransactional
|
||||
public void update(TenantPackageReq req, Long id) {
|
||||
//查询套餐对应的租户
|
||||
List<TenantDO> tenantDOList = tenantService.list(Wrappers.lambdaQuery(TenantDO.class)
|
||||
.eq(TenantDO::getPackageId, id));
|
||||
if (!tenantDOList.isEmpty()) {
|
||||
TenantPackageDetailResp detail = baseService.get(id);
|
||||
List<Long> oldMenuIds = detail.getMenuIds();
|
||||
List<Long> newMenuIds = Arrays.stream(req.getMenuIds()).toList();
|
||||
//删除的菜单
|
||||
List<Long> deleteMenuIds = new ArrayList<>(oldMenuIds);
|
||||
deleteMenuIds.removeAll(newMenuIds);
|
||||
//如果有删除的菜单则绑定了套餐的租户对应的菜单也会删除
|
||||
if (!deleteMenuIds.isEmpty()) {
|
||||
List<MenuDO> deleteMenus = menuService.listByIds(deleteMenuIds);
|
||||
tenantDOList.forEach(tenantDO -> SpringUtil.getBean(TenantHandler.class)
|
||||
.execute(tenantDO.getId(), () -> menuService.deleteTenantMenus(deleteMenus)));
|
||||
}
|
||||
//新增的菜单
|
||||
List<Long> addMenuIds = new ArrayList<>(newMenuIds);
|
||||
addMenuIds.removeAll(oldMenuIds);
|
||||
//如果有新增的菜单则绑定了套餐的租户对应的菜单也会新增
|
||||
if (!addMenuIds.isEmpty()) {
|
||||
List<MenuDO> addMenus = menuService.listByIds(addMenuIds);
|
||||
for (MenuDO addMenu : addMenus) {
|
||||
MenuDO pMenu = addMenu.getParentId() != 0 ? menuService.getById(addMenu.getParentId()) : null;
|
||||
tenantDOList.forEach(tenantDO -> SpringUtil.getBean(TenantHandler.class)
|
||||
.execute(tenantDO.getId(), () -> menuService.addTenantMenu(addMenu, pMenu)));
|
||||
}
|
||||
RedisUtils.deleteByPattern(CacheConstants.ROLE_MENU_KEY_PREFIX + StringConstants.ASTERISK);
|
||||
}
|
||||
}
|
||||
super.update(req, id);
|
||||
}
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.tenant.mapper;
|
||||
|
||||
import top.continew.admin.tenant.model.entity.TenantDbConnectDO;
|
||||
import top.continew.starter.data.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* 租户数据连接 Mapper
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/12/12 19:13
|
||||
*/
|
||||
public interface TenantDbConnectMapper extends BaseMapper<TenantDbConnectDO> {}
|
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.tenant.mapper;
|
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS;
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Constants;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
import top.continew.admin.common.constant.SysConstants;
|
||||
import top.continew.admin.tenant.model.entity.TenantDO;
|
||||
import top.continew.admin.tenant.model.resp.TenantResp;
|
||||
import top.continew.starter.data.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* 租户 Mapper
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/11/26 17:20
|
||||
*/
|
||||
@DS(SysConstants.DEFAULT_DATASOURCE)
|
||||
@Mapper
|
||||
public interface TenantMapper extends BaseMapper<TenantDO> {
|
||||
|
||||
@Select("SELECT sys_tenant.*,sys_tenant_package.`name` as package_name FROM sys_tenant\n" + "LEFT JOIN sys_tenant_package ON sys_tenant.package_id = sys_tenant_package.id\n" + "${ew.getCustomSqlSegment}")
|
||||
IPage<TenantResp> listTenant(IPage page, @Param(Constants.WRAPPER) Wrapper wrapper);
|
||||
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.tenant.mapper;
|
||||
|
||||
import top.continew.starter.data.mapper.BaseMapper;
|
||||
import top.continew.admin.tenant.model.entity.TenantPackageDO;
|
||||
|
||||
/**
|
||||
* 租户套餐 Mapper
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/11/26 11:25
|
||||
*/
|
||||
public interface TenantPackageMapper extends BaseMapper<TenantPackageDO> {
|
||||
}
|
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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.tenant.model.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import top.continew.admin.common.base.model.entity.BaseDO;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 租户实体
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/11/26 17:20
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_tenant")
|
||||
public class TenantDO extends BaseDO {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 租户名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 绑定的域名
|
||||
*/
|
||||
private String domain;
|
||||
|
||||
/**
|
||||
* 租户套餐编号
|
||||
*/
|
||||
private Long packageId;
|
||||
|
||||
/**
|
||||
* 状态(1:启用;2:禁用)
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 租户过期时间
|
||||
*/
|
||||
private LocalDateTime expireTime;
|
||||
|
||||
/**
|
||||
* 用户ID
|
||||
*/
|
||||
private Long userId;
|
||||
|
||||
/**
|
||||
* 租户编号
|
||||
*/
|
||||
private String tenantSn;
|
||||
|
||||
/**
|
||||
* 隔离级别
|
||||
*/
|
||||
private Integer isolationLevel;
|
||||
|
||||
/**
|
||||
* 数据连接ID
|
||||
*/
|
||||
private Long dbConnectId;
|
||||
}
|
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.tenant.model.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import top.continew.admin.common.base.model.entity.BaseDO;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 租户数据连接实体
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/12/12 19:13
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_tenant_db_connect")
|
||||
public class TenantDbConnectDO extends BaseDO {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 连接名称
|
||||
*/
|
||||
private String connectName;
|
||||
|
||||
/**
|
||||
* 连接类型
|
||||
*/
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 连接主机地址
|
||||
*/
|
||||
private String host;
|
||||
|
||||
/**
|
||||
* 连接端口
|
||||
*/
|
||||
private Integer port;
|
||||
|
||||
/**
|
||||
* 连接用户名
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 连接密码
|
||||
*/
|
||||
private String password;
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.tenant.model.entity;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import top.continew.admin.common.base.model.entity.BaseDO;
|
||||
|
||||
/**
|
||||
* 租户套餐实体
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/11/26 11:25
|
||||
*/
|
||||
@Data
|
||||
@TableName("sys_tenant_package")
|
||||
public class TenantPackageDO extends BaseDO {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 套餐名称
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 关联的菜单ids
|
||||
*/
|
||||
private String menuIds;
|
||||
|
||||
/**
|
||||
* 菜单选择是否父子节点关联
|
||||
*/
|
||||
private Boolean menuCheckStrictly;
|
||||
|
||||
/**
|
||||
* 状态(1:启用;2:禁用)
|
||||
*/
|
||||
private Integer status;
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.tenant.model.enums;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import top.continew.starter.core.exception.BusinessException;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum TenantConnectTypeEnum {
|
||||
|
||||
MYSQL;
|
||||
|
||||
public static TenantConnectTypeEnum getByOrdinal(Integer ordinal) {
|
||||
for (TenantConnectTypeEnum item : TenantConnectTypeEnum.values()) {
|
||||
if (item.ordinal() == ordinal) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
throw new BusinessException("未知的连接类型");
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.tenant.model.query;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.*;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import top.continew.starter.data.annotation.Query;
|
||||
import top.continew.starter.data.enums.QueryType;
|
||||
|
||||
/**
|
||||
* 租户数据连接查询条件
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/12/12 19:13
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "租户数据连接查询条件")
|
||||
public class TenantDbConnectQuery implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 连接名称
|
||||
*/
|
||||
@Schema(description = "连接名称")
|
||||
@Query(type = QueryType.EQ)
|
||||
private String connectName;
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.tenant.model.query;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.*;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import top.continew.starter.data.annotation.Query;
|
||||
import top.continew.starter.data.enums.QueryType;
|
||||
|
||||
/**
|
||||
* 租户套餐查询条件
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/11/26 11:25
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "租户套餐查询条件")
|
||||
public class TenantPackageQuery implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 套餐名称
|
||||
*/
|
||||
@Schema(description = "套餐名称")
|
||||
@Query(type = QueryType.EQ)
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 状态(1:启用;2:禁用)
|
||||
*/
|
||||
@Schema(description = "状态(1:启用;2:禁用)")
|
||||
@Query(type = QueryType.EQ)
|
||||
private Integer status;
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.tenant.model.query;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import top.continew.starter.data.annotation.Query;
|
||||
import top.continew.starter.data.enums.QueryType;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 租户查询条件
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/11/26 17:20
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "租户查询条件")
|
||||
public class TenantQuery implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 租户名称
|
||||
*/
|
||||
@Schema(description = "租户名称")
|
||||
@Query(type = QueryType.LIKE)
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 租户套餐编号
|
||||
*/
|
||||
@Schema(description = "租户套餐编号")
|
||||
@Query(type = QueryType.EQ)
|
||||
private Long packageId;
|
||||
|
||||
}
|
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.tenant.model.req;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* 创建或修改租户数据连接参数
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/12/12 19:13
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "创建或修改租户数据连接参数")
|
||||
public class TenantDbConnectReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 连接名称
|
||||
*/
|
||||
@Schema(description = "连接名称")
|
||||
@NotBlank(message = "连接名称不能为空")
|
||||
@Length(max = 128, message = "连接名称长度不能超过 {max} 个字符")
|
||||
private String connectName;
|
||||
|
||||
/**
|
||||
* 连接类型
|
||||
*/
|
||||
@Schema(description = "连接类型")
|
||||
@NotNull(message = "连接类型不能为空")
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 连接主机地址
|
||||
*/
|
||||
@Schema(description = "连接主机地址")
|
||||
@NotBlank(message = "连接主机地址不能为空")
|
||||
@Length(max = 128, message = "连接主机地址长度不能超过 {max} 个字符")
|
||||
private String host;
|
||||
|
||||
/**
|
||||
* 连接端口
|
||||
*/
|
||||
@Schema(description = "连接端口")
|
||||
@NotNull(message = "连接端口不能为空")
|
||||
private Integer port;
|
||||
|
||||
/**
|
||||
* 连接用户名
|
||||
*/
|
||||
@Schema(description = "连接用户名")
|
||||
@NotBlank(message = "连接用户名不能为空")
|
||||
@Length(max = 128, message = "连接用户名长度不能超过 {max} 个字符")
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 连接密码
|
||||
*/
|
||||
@Schema(description = "连接密码")
|
||||
@NotBlank(message = "连接密码不能为空")
|
||||
@Length(max = 128, message = "连接密码长度不能超过 {max} 个字符")
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@Schema(hidden = true)
|
||||
private Long id;
|
||||
}
|
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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.tenant.model.req;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @description: 租户登录用户信息
|
||||
* @author: 小熊
|
||||
* @create: 2024-12-02 20:41
|
||||
*/
|
||||
@Data
|
||||
public class TenantLoginUserInfoReq implements Serializable {
|
||||
|
||||
/**
|
||||
* 租户id
|
||||
*/
|
||||
@NotNull(message = "租户ID不能为空")
|
||||
private Long tenantId;
|
||||
|
||||
/**
|
||||
* 登录用户名
|
||||
*/
|
||||
@NotEmpty(message = "登录用户名不能为空")
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 登录密码
|
||||
*/
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@Schema(hidden = true)
|
||||
private Long id;
|
||||
}
|
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.tenant.model.req;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.*;
|
||||
|
||||
import jakarta.validation.constraints.*;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
/**
|
||||
* 创建或修改租户套餐参数
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/11/26 11:25
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "创建或修改租户套餐参数")
|
||||
public class TenantPackageReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 套餐名称
|
||||
*/
|
||||
@Schema(description = "套餐名称")
|
||||
@NotBlank(message = "套餐名称不能为空")
|
||||
@Length(max = 64, message = "套餐名称长度不能超过 {max} 个字符")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 关联的菜单ids
|
||||
*/
|
||||
@Schema(description = "关联的菜单ids")
|
||||
private Long[] menuIds;
|
||||
|
||||
/**
|
||||
* 菜单选择是否父子节点关联
|
||||
*/
|
||||
@Schema(description = "菜单选择是否父子节点关联")
|
||||
private Boolean menuCheckStrictly;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
@Schema(description = "状态")
|
||||
@NotNull(message = "状态不能为空")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@Schema(hidden = true)
|
||||
private Long id;
|
||||
}
|
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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.tenant.model.req;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.constraints.Future;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Pattern;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
import top.continew.admin.common.constant.RegexConstants;
|
||||
import top.continew.starter.extension.crud.validation.CrudValidationGroup;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 创建或修改租户参数
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/11/26 17:20
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "创建或修改租户参数")
|
||||
public class TenantReq implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 租户名称
|
||||
*/
|
||||
@Schema(description = "租户名称")
|
||||
@NotBlank(message = "租户名称不能为空")
|
||||
@Length(max = 64, message = "租户名称长度不能超过 {max} 个字符")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 绑定的域名
|
||||
*/
|
||||
@Schema(description = "绑定的域名")
|
||||
@Length(max = 128, message = "绑定的域名长度不能超过 {max} 个字符")
|
||||
private String domain;
|
||||
|
||||
/**
|
||||
* 租户套餐编号
|
||||
*/
|
||||
@Schema(description = "租户套餐编号")
|
||||
@NotNull(message = "租户套餐编号不能为空")
|
||||
private Long packageId;
|
||||
|
||||
/**
|
||||
* 状态(1:启用;2:禁用)
|
||||
*/
|
||||
@Schema(description = "状态")
|
||||
@NotNull(message = "状态不能为空")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 租户过期时间
|
||||
*/
|
||||
@Schema(description = "租户过期时间")
|
||||
@Future(message = "过期时间必须是未来时间")
|
||||
private LocalDateTime expireTime;
|
||||
|
||||
/**
|
||||
* 用户名
|
||||
*/
|
||||
@Schema(description = "用户名", example = "zhangsan")
|
||||
@NotBlank(message = "用户名不能为空", groups = CrudValidationGroup.Create.class)
|
||||
@Pattern(regexp = RegexConstants.USERNAME, message = "用户名长度为 4-64 个字符,支持大小写字母、数字、下划线,以字母开头")
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 密码(加密)
|
||||
*/
|
||||
@Schema(description = "密码(加密)", example = "E7c72TH+LDxKTwavjM99W1MdI9Lljh79aPKiv3XB9MXcplhm7qJ1BJCj28yaflbdVbfc366klMtjLIWQGqb0qw==")
|
||||
@NotBlank(message = "密码不能为空", groups = CrudValidationGroup.Create.class)
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* 租户编号
|
||||
*/
|
||||
private String tenantSn;
|
||||
|
||||
/**
|
||||
* 隔离级别
|
||||
*/
|
||||
@Schema(description = "隔离级别")
|
||||
@NotNull(message = "隔离级别不能为空", groups = CrudValidationGroup.Create.class)
|
||||
private Integer isolationLevel;
|
||||
|
||||
/**
|
||||
* 数据连接ID
|
||||
*/
|
||||
@Schema(description = "数据连接ID")
|
||||
private Long dbConnectId;
|
||||
|
||||
/**
|
||||
* ID
|
||||
*/
|
||||
@Schema(hidden = true)
|
||||
private Long id;
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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.tenant.model.resp;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class TenantAvailableResp {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
private String domain;
|
||||
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.tenant.model.resp;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @description: 租户通用信息返回
|
||||
* @author: 小熊
|
||||
* @create: 2024-11-28 09:53
|
||||
*/
|
||||
@Data
|
||||
public class TenantCommonResp {
|
||||
|
||||
/**
|
||||
* 是否开启了多租户
|
||||
*/
|
||||
private Boolean isEnabled;
|
||||
|
||||
/**
|
||||
* 可用租户列表
|
||||
*/
|
||||
private List<TenantAvailableResp> availableList;
|
||||
|
||||
}
|
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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.tenant.model.resp;
|
||||
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import top.continew.admin.common.base.model.resp.BaseDetailResp;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 租户数据连接详情信息
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/12/12 19:13
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@Schema(description = "租户数据连接详情信息")
|
||||
public class TenantDbConnectDetailResp extends BaseDetailResp {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 连接名称
|
||||
*/
|
||||
@Schema(description = "连接名称")
|
||||
@ExcelProperty(value = "连接名称")
|
||||
private String connectName;
|
||||
|
||||
/**
|
||||
* 连接类型
|
||||
*/
|
||||
@Schema(description = "连接类型")
|
||||
@ExcelProperty(value = "连接类型")
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 连接主机地址
|
||||
*/
|
||||
@Schema(description = "连接主机地址")
|
||||
@ExcelProperty(value = "连接主机地址")
|
||||
private String host;
|
||||
|
||||
/**
|
||||
* 连接端口
|
||||
*/
|
||||
@Schema(description = "连接端口")
|
||||
@ExcelProperty(value = "连接端口")
|
||||
private Integer port;
|
||||
|
||||
/**
|
||||
* 连接用户名
|
||||
*/
|
||||
@Schema(description = "连接用户名")
|
||||
@ExcelProperty(value = "连接用户名")
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* 连接密码
|
||||
*/
|
||||
@Schema(description = "连接密码")
|
||||
@ExcelProperty(value = "连接密码")
|
||||
private String password;
|
||||
}
|
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.tenant.model.resp;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import top.continew.admin.common.base.model.resp.BaseResp;
|
||||
|
||||
import java.io.Serial;
|
||||
|
||||
/**
|
||||
* 租户数据连接信息
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/12/12 19:13
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "租户数据连接信息")
|
||||
public class TenantDbConnectResp extends BaseResp {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 连接名称
|
||||
*/
|
||||
@Schema(description = "连接名称")
|
||||
private String connectName;
|
||||
|
||||
/**
|
||||
* 连接类型
|
||||
*/
|
||||
@Schema(description = "连接类型")
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* 连接主机地址
|
||||
*/
|
||||
@Schema(description = "连接主机地址")
|
||||
private String host;
|
||||
|
||||
/**
|
||||
* 连接端口
|
||||
*/
|
||||
@Schema(description = "连接端口")
|
||||
private Integer port;
|
||||
|
||||
/**
|
||||
* 连接用户名
|
||||
*/
|
||||
@Schema(description = "连接用户名")
|
||||
private String username;
|
||||
|
||||
}
|
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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.tenant.model.resp;
|
||||
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import top.continew.admin.common.base.model.resp.BaseDetailResp;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 租户详情信息
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/11/26 17:20
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@Schema(description = "租户详情信息")
|
||||
public class TenantDetailResp extends BaseDetailResp {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 租户名称
|
||||
*/
|
||||
@Schema(description = "租户名称")
|
||||
@ExcelProperty(value = "租户名称")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 绑定的域名
|
||||
*/
|
||||
@Schema(description = "绑定的域名")
|
||||
@ExcelProperty(value = "绑定的域名")
|
||||
private String domain;
|
||||
|
||||
/**
|
||||
* 租户套餐编号
|
||||
*/
|
||||
@Schema(description = "租户套餐编号")
|
||||
@ExcelProperty(value = "租户套餐编号")
|
||||
private Long packageId;
|
||||
|
||||
/**
|
||||
* 状态(1:启用;2:禁用)
|
||||
*/
|
||||
@Schema(description = "状态(1:启用;2:禁用)")
|
||||
@ExcelProperty(value = "状态(1:启用;2:禁用)")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 租户过期时间
|
||||
*/
|
||||
@Schema(description = "租户过期时间")
|
||||
@ExcelProperty(value = "租户过期时间")
|
||||
private LocalDateTime expireTime;
|
||||
|
||||
/**
|
||||
* 绑定的套餐名称
|
||||
*/
|
||||
@Schema(description = "绑定的套餐名称")
|
||||
private String packageName;
|
||||
|
||||
/**
|
||||
* 套餐关联的菜单
|
||||
*/
|
||||
@Schema(description = "关联的菜单ids")
|
||||
private List<Long> menuIds;
|
||||
|
||||
/**
|
||||
* 租户编号
|
||||
*/
|
||||
private String tenantSn;
|
||||
|
||||
/**
|
||||
* 租户绑定的管理用户id
|
||||
*/
|
||||
private Long userId;
|
||||
}
|
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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.tenant.model.resp;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.time.*;
|
||||
import java.util.List;
|
||||
|
||||
import cn.idev.excel.annotation.ExcelProperty;
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import top.continew.admin.common.base.model.resp.BaseDetailResp;
|
||||
import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
|
||||
|
||||
/**
|
||||
* 租户套餐详情信息
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/11/26 11:25
|
||||
*/
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
@Schema(description = "租户套餐详情信息")
|
||||
public class TenantPackageDetailResp extends BaseDetailResp {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 套餐名称
|
||||
*/
|
||||
@Schema(description = "套餐名称")
|
||||
@ExcelProperty(value = "套餐名称")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 关联的菜单ids
|
||||
*/
|
||||
@Schema(description = "关联的菜单ids")
|
||||
@ExcelProperty(value = "关联的菜单ids")
|
||||
private List<Long> menuIds;
|
||||
|
||||
/**
|
||||
* 菜单选择是否父子节点关联
|
||||
*/
|
||||
@Schema(description = "菜单选择是否父子节点关联")
|
||||
@ExcelProperty(value = "菜单选择是否父子节点关联")
|
||||
private Boolean menuCheckStrictly;
|
||||
|
||||
/**
|
||||
* 状态(1:启用;2:禁用)
|
||||
*/
|
||||
@Schema(description = "状态(1:启用;2:禁用)")
|
||||
@ExcelProperty(value = "状态(1:启用;2:禁用)")
|
||||
private Integer status;
|
||||
}
|
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.tenant.model.resp;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.time.*;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
|
||||
import top.continew.admin.common.base.model.resp.BaseResp;
|
||||
|
||||
/**
|
||||
* 租户套餐信息
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/11/26 11:25
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "租户套餐信息")
|
||||
public class TenantPackageResp extends BaseResp {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 套餐名称
|
||||
*/
|
||||
@Schema(description = "套餐名称")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 关联的菜单ids
|
||||
*/
|
||||
@Schema(description = "关联的菜单ids")
|
||||
private List<Long> menuIds;
|
||||
|
||||
/**
|
||||
* 菜单选择是否父子节点关联
|
||||
*/
|
||||
@Schema(description = "菜单选择是否父子节点关联")
|
||||
private Boolean menuCheckStrictly;
|
||||
|
||||
/**
|
||||
* 状态(1:启用;2:禁用)
|
||||
*/
|
||||
@Schema(description = "状态(1:启用;2:禁用)")
|
||||
private Integer status;
|
||||
}
|
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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.tenant.model.resp;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import top.continew.admin.common.base.model.resp.BaseResp;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 租户信息
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/11/26 17:20
|
||||
*/
|
||||
@Data
|
||||
@Schema(description = "租户信息")
|
||||
public class TenantResp extends BaseResp {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
/**
|
||||
* 租户名称
|
||||
*/
|
||||
@Schema(description = "租户名称")
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* 绑定的域名
|
||||
*/
|
||||
@Schema(description = "绑定的域名")
|
||||
private String domain;
|
||||
|
||||
/**
|
||||
* 租户套餐编号
|
||||
*/
|
||||
@Schema(description = "租户套餐编号")
|
||||
private Long packageId;
|
||||
|
||||
/**
|
||||
* 状态(1:启用;2:禁用)
|
||||
*/
|
||||
@Schema(description = "状态(1:启用;2:禁用)")
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 租户过期时间
|
||||
*/
|
||||
@Schema(description = "租户过期时间")
|
||||
private LocalDateTime expireTime;
|
||||
|
||||
/**
|
||||
* 绑定的套餐名称
|
||||
*/
|
||||
@Schema(description = "绑定的套餐名称")
|
||||
private String packageName;
|
||||
|
||||
/**
|
||||
* 租户编号
|
||||
*/
|
||||
private String tenantSn;
|
||||
|
||||
/**
|
||||
* 隔离级别
|
||||
*/
|
||||
@Schema(description = "隔离级别")
|
||||
private Integer isolationLevel;
|
||||
|
||||
/**
|
||||
* 数据连接ID
|
||||
*/
|
||||
@Schema(description = "数据连接ID")
|
||||
private Long dbConnectId;
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.tenant.service;
|
||||
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import top.continew.admin.common.base.service.BaseService;
|
||||
import top.continew.admin.tenant.model.query.TenantDbConnectQuery;
|
||||
import top.continew.admin.tenant.model.req.TenantDbConnectReq;
|
||||
import top.continew.admin.tenant.model.resp.TenantDbConnectDetailResp;
|
||||
import top.continew.admin.tenant.model.resp.TenantDbConnectResp;
|
||||
|
||||
/**
|
||||
* 租户数据连接业务接口
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/12/12 19:13
|
||||
*/
|
||||
public interface TenantDbConnectService extends BaseService<TenantDbConnectResp, TenantDbConnectDetailResp, TenantDbConnectQuery, TenantDbConnectReq> {
|
||||
|
||||
JdbcTemplate getConnectJdbcTemplateById(Long id);
|
||||
|
||||
}
|
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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.tenant.service;
|
||||
|
||||
import top.continew.admin.common.base.service.BaseService;
|
||||
import top.continew.admin.tenant.model.query.TenantPackageQuery;
|
||||
import top.continew.admin.tenant.model.req.TenantPackageReq;
|
||||
import top.continew.admin.tenant.model.resp.TenantPackageDetailResp;
|
||||
import top.continew.admin.tenant.model.resp.TenantPackageResp;
|
||||
|
||||
/**
|
||||
* 租户套餐业务接口
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/11/26 11:25
|
||||
*/
|
||||
public interface TenantPackageService extends BaseService<TenantPackageResp, TenantPackageDetailResp, TenantPackageQuery, TenantPackageReq> {}
|
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* 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.tenant.service;
|
||||
|
||||
import top.continew.admin.common.base.service.BaseService;
|
||||
import top.continew.admin.tenant.model.entity.TenantDO;
|
||||
import top.continew.admin.tenant.model.query.TenantQuery;
|
||||
import top.continew.admin.tenant.model.req.TenantReq;
|
||||
import top.continew.admin.tenant.model.resp.TenantAvailableResp;
|
||||
import top.continew.admin.tenant.model.resp.TenantDetailResp;
|
||||
import top.continew.admin.tenant.model.resp.TenantResp;
|
||||
import top.continew.starter.data.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 租户业务接口
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/11/26 17:20
|
||||
*/
|
||||
public interface TenantService extends BaseService<TenantResp, TenantDetailResp, TenantQuery, TenantReq>, IService<TenantDO> {
|
||||
|
||||
/**
|
||||
* 获取所有可用的租户列表
|
||||
*/
|
||||
List<TenantAvailableResp> getAvailableList();
|
||||
|
||||
/**
|
||||
* 租户绑定用户
|
||||
*/
|
||||
void bindUser(Long tenantId, Long userId);
|
||||
|
||||
/**
|
||||
* 检查租户状态
|
||||
*/
|
||||
void checkStatus();
|
||||
|
||||
/**
|
||||
* 根据id获取租户DO
|
||||
*/
|
||||
TenantDO getTenantById(Long id);
|
||||
|
||||
/**
|
||||
* 根据用户id获取租户信息
|
||||
*/
|
||||
TenantDO getTenantByUserId(Long userId);
|
||||
|
||||
}
|
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* 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.tenant.service.impl;
|
||||
|
||||
import com.alicp.jetcache.anno.Cached;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import top.continew.admin.common.base.service.BaseServiceImpl;
|
||||
import top.continew.admin.common.constant.CacheConstants;
|
||||
import top.continew.admin.tenant.mapper.TenantDbConnectMapper;
|
||||
import top.continew.admin.tenant.mapper.TenantMapper;
|
||||
import top.continew.admin.tenant.model.entity.TenantDO;
|
||||
import top.continew.admin.tenant.model.entity.TenantDbConnectDO;
|
||||
import top.continew.admin.tenant.model.enums.TenantConnectTypeEnum;
|
||||
import top.continew.admin.tenant.model.query.TenantDbConnectQuery;
|
||||
import top.continew.admin.tenant.model.req.TenantDbConnectReq;
|
||||
import top.continew.admin.tenant.model.resp.TenantDbConnectDetailResp;
|
||||
import top.continew.admin.tenant.model.resp.TenantDbConnectResp;
|
||||
import top.continew.admin.tenant.service.TenantDbConnectService;
|
||||
import top.continew.admin.tenant.util.DbConnectUtil;
|
||||
import top.continew.starter.cache.redisson.util.RedisUtils;
|
||||
import top.continew.starter.core.util.validation.CheckUtils;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 租户数据连接业务实现
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/12/12 19:13
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class TenantDbConnectServiceImpl extends BaseServiceImpl<TenantDbConnectMapper, TenantDbConnectDO, TenantDbConnectResp, TenantDbConnectDetailResp, TenantDbConnectQuery, TenantDbConnectReq> implements TenantDbConnectService {
|
||||
|
||||
private final TenantMapper tenantMapper;
|
||||
|
||||
@Override
|
||||
@Cached(name = CacheConstants.DB_CONNECT_KEY_PREFIX, key = "#id")
|
||||
public TenantDbConnectDetailResp get(Long id) {
|
||||
return super.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeCreate(TenantDbConnectReq req) {
|
||||
TenantConnectTypeEnum connectTypeEnum = TenantConnectTypeEnum.getByOrdinal(req.getType());
|
||||
if (TenantConnectTypeEnum.MYSQL.equals(connectTypeEnum)) {
|
||||
DbConnectUtil.getMysqlDataSource(req.getHost(), req.getPort(), req.getUsername(), req
|
||||
.getPassword(), null, null);
|
||||
checkRepeat(req, null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证重复数据
|
||||
*/
|
||||
private void checkRepeat(TenantDbConnectReq req, Long id) {
|
||||
CheckUtils.throwIf(baseMapper.exists(Wrappers.lambdaQuery(TenantDbConnectDO.class)
|
||||
.eq(TenantDbConnectDO::getHost, req.getHost())
|
||||
.eq(TenantDbConnectDO::getPort, req.getPort())
|
||||
.eq(TenantDbConnectDO::getUsername, req.getUsername())
|
||||
.ne(id != null, TenantDbConnectDO::getId, id)), "数据库连接已存在");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeUpdate(TenantDbConnectReq req, Long id) {
|
||||
TenantConnectTypeEnum connectTypeEnum = TenantConnectTypeEnum.getByOrdinal(req.getType());
|
||||
if (TenantConnectTypeEnum.MYSQL.equals(connectTypeEnum)) {
|
||||
DbConnectUtil.getMysqlDataSource(req.getHost(), req.getPort(), req.getUsername(), req
|
||||
.getPassword(), null, null);
|
||||
checkRepeat(req, id);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeDelete(List<Long> ids) {
|
||||
CheckUtils.throwIf(tenantMapper.selectCount(Wrappers.lambdaQuery(TenantDO.class)
|
||||
.in(TenantDO::getDbConnectId, ids)) > 0, "存在关联租户无法删除");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterUpdate(TenantDbConnectReq req, TenantDbConnectDO entity) {
|
||||
RedisUtils.delete(CacheConstants.DB_CONNECT_KEY_PREFIX + entity.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterDelete(List<Long> ids) {
|
||||
ids.forEach(id -> RedisUtils.delete(CacheConstants.DB_CONNECT_KEY_PREFIX + id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdbcTemplate getConnectJdbcTemplateById(Long id) {
|
||||
TenantDbConnectDetailResp dbConnectReq = get(id);
|
||||
TenantConnectTypeEnum connectTypeEnum = TenantConnectTypeEnum.getByOrdinal(dbConnectReq.getType());
|
||||
if (TenantConnectTypeEnum.MYSQL.equals(connectTypeEnum)) {
|
||||
DataSource dataSource = DbConnectUtil.getMysqlDataSource(dbConnectReq.getHost(), dbConnectReq
|
||||
.getPort(), dbConnectReq.getUsername(), dbConnectReq.getPassword(), null, null);
|
||||
return new JdbcTemplate(dataSource);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.tenant.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.json.JSONArray;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import top.continew.admin.common.base.service.BaseServiceImpl;
|
||||
import top.continew.admin.tenant.mapper.TenantMapper;
|
||||
import top.continew.admin.tenant.mapper.TenantPackageMapper;
|
||||
import top.continew.admin.tenant.model.entity.TenantDO;
|
||||
import top.continew.admin.tenant.model.entity.TenantPackageDO;
|
||||
import top.continew.admin.tenant.model.query.TenantPackageQuery;
|
||||
import top.continew.admin.tenant.model.req.TenantPackageReq;
|
||||
import top.continew.admin.tenant.model.resp.TenantPackageDetailResp;
|
||||
import top.continew.admin.tenant.model.resp.TenantPackageResp;
|
||||
import top.continew.admin.tenant.service.TenantPackageService;
|
||||
import top.continew.starter.core.util.validation.CheckUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 租户套餐业务实现
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/11/26 11:25
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class TenantPackageServiceImpl extends BaseServiceImpl<TenantPackageMapper, TenantPackageDO, TenantPackageResp, TenantPackageDetailResp, TenantPackageQuery, TenantPackageReq> implements TenantPackageService {
|
||||
|
||||
private final TenantMapper tenantMapper;
|
||||
|
||||
@Override
|
||||
public TenantPackageDetailResp get(Long id) {
|
||||
TenantPackageDO tenantPackageDO = getById(id);
|
||||
TenantPackageDetailResp packageDetailResp = BeanUtil
|
||||
.copyProperties(tenantPackageDO, TenantPackageDetailResp.class);
|
||||
packageDetailResp.setMenuIds(new JSONArray(tenantPackageDO.getMenuIds()).toList(Long.class));
|
||||
fill(packageDetailResp);
|
||||
return packageDetailResp;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeCreate(TenantPackageReq req) {
|
||||
CheckUtils.throwIf(baseMapper.selectCount(Wrappers.lambdaQuery(TenantPackageDO.class)
|
||||
.eq(TenantPackageDO::getName, req.getName())) > 0, "租户套餐名称不能重复");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void beforeDelete(List<Long> ids) {
|
||||
CheckUtils.throwIf(tenantMapper.selectCount(Wrappers.lambdaQuery(TenantDO.class)
|
||||
.in(TenantDO::getPackageId, ids)) > 0, "存在关联租户无法删除");
|
||||
}
|
||||
}
|
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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.tenant.service.impl;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
import top.continew.admin.common.constant.SysConstants;
|
||||
import top.continew.admin.common.enums.DisEnableStatusEnum;
|
||||
import top.continew.admin.tenant.model.entity.TenantDO;
|
||||
import top.continew.admin.tenant.model.resp.TenantDbConnectDetailResp;
|
||||
import top.continew.admin.tenant.service.TenantDbConnectService;
|
||||
import top.continew.admin.tenant.service.TenantService;
|
||||
import top.continew.admin.tenant.util.DbConnectUtil;
|
||||
import top.continew.starter.core.util.validation.CheckUtils;
|
||||
import top.continew.starter.extension.tenant.config.TenantDataSource;
|
||||
import top.continew.starter.extension.tenant.config.TenantProvider;
|
||||
import top.continew.starter.extension.tenant.context.TenantContext;
|
||||
import top.continew.starter.extension.tenant.enums.TenantIsolationLevel;
|
||||
|
||||
/**
|
||||
* @description: 租户数据源提供者实现
|
||||
* @author: 小熊
|
||||
* @create: 2024-12-12 15:35
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class TenantProviderImpl implements TenantProvider {
|
||||
|
||||
private final TenantService tenantService;
|
||||
private final TenantDbConnectService tenantDbConnectService;
|
||||
|
||||
@Override
|
||||
public TenantContext getByTenantId(String tenantId, boolean verify) {
|
||||
TenantContext context = new TenantContext();
|
||||
if (StrUtil.isNotEmpty(tenantId) && !SysConstants.DEFAULT_TENANT.equals(tenantId)) {
|
||||
Long longTenantId = Long.valueOf(tenantId);
|
||||
TenantDO tenantDO = tenantService.getTenantById(longTenantId);
|
||||
CheckUtils.throwIfNull(tenantDO, "租户[{}]不存在", tenantId);
|
||||
CheckUtils.throwIf(verify && DisEnableStatusEnum.DISABLE.getValue()
|
||||
.equals(tenantDO.getStatus()), "租户[{}]已被禁用", tenantId);
|
||||
context.setTenantId(longTenantId);
|
||||
TenantIsolationLevel isolationLevel = TenantIsolationLevel.DATASOURCE.ordinal() == tenantDO
|
||||
.getIsolationLevel() ? TenantIsolationLevel.DATASOURCE : TenantIsolationLevel.LINE;
|
||||
context.setIsolationLevel(isolationLevel);
|
||||
if (isolationLevel.equals(TenantIsolationLevel.DATASOURCE)) {
|
||||
TenantDbConnectDetailResp dbConnectReq = tenantDbConnectService.get(tenantDO.getDbConnectId());
|
||||
String dbName = SysConstants.TENANT_DB_PREFIX + tenantDO.getTenantSn();
|
||||
HikariConfig hikariConfig = DbConnectUtil.formatHikariConfig(dbConnectReq.getHost(), dbConnectReq
|
||||
.getPort(), dbConnectReq.getUsername(), dbConnectReq.getPassword(), dbName, DbConnectUtil
|
||||
.getDefaultMysqlConnectParameter());
|
||||
TenantDataSource source = new TenantDataSource();
|
||||
source.setPoolName(tenantId);
|
||||
source.setDriverClassName(hikariConfig.getDriverClassName());
|
||||
source.setUrl(hikariConfig.getJdbcUrl());
|
||||
source.setUsername(hikariConfig.getUsername());
|
||||
source.setPassword(hikariConfig.getPassword());
|
||||
context.setDataSource(source);
|
||||
}
|
||||
} else {
|
||||
context.setTenantId(Long.valueOf(SysConstants.DEFAULT_TENANT));
|
||||
context.setIsolationLevel(TenantIsolationLevel.LINE);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* 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.tenant.service.impl;
|
||||
|
||||
import cn.hutool.core.bean.BeanUtil;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.io.resource.ClassPathResource;
|
||||
import cn.hutool.core.io.resource.Resource;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONArray;
|
||||
import com.alicp.jetcache.anno.Cached;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import top.continew.admin.common.base.service.BaseServiceImpl;
|
||||
import top.continew.admin.common.config.properties.TenantProperties;
|
||||
import top.continew.admin.common.constant.CacheConstants;
|
||||
import top.continew.admin.common.constant.SysConstants;
|
||||
import top.continew.admin.common.enums.DisEnableStatusEnum;
|
||||
import top.continew.admin.tenant.mapper.TenantMapper;
|
||||
import top.continew.admin.tenant.mapper.TenantPackageMapper;
|
||||
import top.continew.admin.tenant.model.entity.TenantDO;
|
||||
import top.continew.admin.tenant.model.entity.TenantPackageDO;
|
||||
import top.continew.admin.tenant.model.query.TenantQuery;
|
||||
import top.continew.admin.tenant.model.req.TenantReq;
|
||||
import top.continew.admin.tenant.model.resp.TenantAvailableResp;
|
||||
import top.continew.admin.tenant.model.resp.TenantDetailResp;
|
||||
import top.continew.admin.tenant.model.resp.TenantResp;
|
||||
import top.continew.admin.tenant.service.TenantDbConnectService;
|
||||
import top.continew.admin.tenant.service.TenantService;
|
||||
import top.continew.starter.cache.redisson.util.RedisUtils;
|
||||
import top.continew.starter.core.util.validation.CheckUtils;
|
||||
import top.continew.starter.core.util.validation.ValidationUtils;
|
||||
import top.continew.starter.extension.crud.model.entity.BaseIdDO;
|
||||
import top.continew.starter.extension.crud.model.query.PageQuery;
|
||||
import top.continew.starter.extension.crud.model.resp.PageResp;
|
||||
import top.continew.starter.extension.tenant.context.TenantContextHolder;
|
||||
import top.continew.starter.extension.tenant.enums.TenantIsolationLevel;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 租户业务实现
|
||||
*
|
||||
* @author 小熊
|
||||
* @since 2024/11/26 17:20
|
||||
*/
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class TenantServiceImpl extends BaseServiceImpl<TenantMapper, TenantDO, TenantResp, TenantDetailResp, TenantQuery, TenantReq> implements TenantService {
|
||||
|
||||
private final TenantPackageMapper packageMapper;
|
||||
private final TenantProperties tenantProperties;
|
||||
private final TenantDbConnectService dbConnectService;
|
||||
|
||||
@Override
|
||||
protected void beforeCreate(TenantReq req) {
|
||||
//租户名称不能重复
|
||||
ValidationUtils.throwIf(baseMapper.exists(Wrappers.lambdaQuery(TenantDO.class)
|
||||
.eq(TenantDO::getName, req.getName())), "重复的租户名称");
|
||||
//录入随机的六位租户编号
|
||||
req.setTenantSn(generateTenantSn());
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成六位随机不重复的编号
|
||||
*/
|
||||
private String generateTenantSn() {
|
||||
String tenantSn;
|
||||
do {
|
||||
tenantSn = RandomUtil.randomString(RandomUtil.BASE_CHAR_NUMBER_LOWER, 6);
|
||||
} while (baseMapper.exists(Wrappers.lambdaQuery(TenantDO.class).eq(TenantDO::getTenantSn, tenantSn)));
|
||||
return tenantSn;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterCreate(TenantReq req, TenantDO entity) {
|
||||
//数据源级别的租户需要创建数据库
|
||||
if (entity.getIsolationLevel().equals(TenantIsolationLevel.DATASOURCE.ordinal())) {
|
||||
JdbcTemplate jdbcTemplate = dbConnectService.getConnectJdbcTemplateById(entity.getDbConnectId());
|
||||
String dbName = SysConstants.TENANT_DB_PREFIX + entity.getTenantSn();
|
||||
//建库
|
||||
jdbcTemplate.execute(StrUtil
|
||||
.format("CREATE DATABASE {} CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;", dbName));
|
||||
jdbcTemplate.execute(StrUtil.format("USE {};", dbName));
|
||||
//建表
|
||||
Resource resource = new ClassPathResource("db/changelog/mysql/tenant_table.sql");
|
||||
String tableSql = resource.readUtf8Str();
|
||||
Arrays.stream(tableSql.split(";"))
|
||||
.map(String::trim)
|
||||
.filter(sql -> !sql.isEmpty())
|
||||
.forEach(jdbcTemplate::execute);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<TenantAvailableResp> getAvailableList() {
|
||||
List<TenantDO> tenantDOS = baseMapper.selectList(Wrappers.lambdaQuery(TenantDO.class)
|
||||
.select(TenantDO::getName, BaseIdDO::getId, TenantDO::getDomain)
|
||||
.eq(TenantDO::getStatus, DisEnableStatusEnum.ENABLE.getValue())
|
||||
.and(t -> t.isNull(TenantDO::getExpireTime).or().ge(TenantDO::getExpireTime, DateUtil.date())));
|
||||
return BeanUtil.copyToList(tenantDOS, TenantAvailableResp.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResp<TenantResp> page(TenantQuery query, PageQuery pageQuery) {
|
||||
QueryWrapper queryWrapper = Wrappers.query(TenantQuery.class)
|
||||
.eq(query.getPackageId() != null, "package_id", query.getPackageId())
|
||||
.like(StrUtil.isNotEmpty(query.getName()), "sys_tenant.name", query.getName());
|
||||
this.sort(queryWrapper, pageQuery);
|
||||
IPage<TenantResp> list = baseMapper.listTenant(new Page<>(pageQuery.getPage(), pageQuery
|
||||
.getSize()), queryWrapper);
|
||||
PageResp<TenantResp> pageResp = PageResp.build(list, TenantResp.class);
|
||||
return pageResp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TenantDetailResp get(Long id) {
|
||||
TenantDetailResp detailResp = new TenantDetailResp();
|
||||
TenantDO tenantDO = getById(id);
|
||||
if (tenantDO != null) {
|
||||
BeanUtil.copyProperties(tenantDO, detailResp);
|
||||
TenantPackageDO packageDO = packageMapper.selectById(tenantDO.getPackageId());
|
||||
if (packageDO != null) {
|
||||
detailResp.setPackageName(packageDO.getName());
|
||||
detailResp.setMenuIds(new JSONArray(packageDO.getMenuIds()).toList(Long.class));
|
||||
}
|
||||
}
|
||||
fill(detailResp);
|
||||
return detailResp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindUser(Long tenantId, Long userId) {
|
||||
update(Wrappers.lambdaUpdate(TenantDO.class).set(TenantDO::getUserId, userId).eq(BaseIdDO::getId, tenantId));
|
||||
TenantDO entity = getById(tenantId);
|
||||
RedisUtils.set(CacheConstants.TENANT_KEY + tenantId, entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkStatus() {
|
||||
if (tenantProperties.isEnabled()) {
|
||||
Long tenantId = TenantContextHolder.getTenantId();
|
||||
CheckUtils.throwIfNull(tenantId, "未选择租户");
|
||||
if (tenantId != 0) {
|
||||
TenantDO tenantDO = baseMapper.selectById(tenantId);
|
||||
CheckUtils.throwIfNull(tenantDO, "租户不存在");
|
||||
CheckUtils.throwIfNotEqual(DisEnableStatusEnum.ENABLE.getValue(), tenantDO.getStatus(), "此租户已被禁用");
|
||||
//租户过期
|
||||
CheckUtils.throwIf(tenantDO.getExpireTime() != null && tenantDO.getExpireTime()
|
||||
.isBefore(DateUtil.date().toLocalDateTime()), "租户已过期");
|
||||
//套餐状态
|
||||
TenantPackageDO packageDO = packageMapper.selectById(tenantDO.getPackageId());
|
||||
CheckUtils.throwIfNull(tenantDO, "套餐不存在");
|
||||
CheckUtils.throwIfNotEqual(DisEnableStatusEnum.ENABLE.getValue(), packageDO.getStatus(), "此租户套餐已被禁用");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Cached(name = CacheConstants.TENANT_KEY, key = "#id")
|
||||
public TenantDO getTenantById(Long id) {
|
||||
return baseMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterUpdate(TenantReq req, TenantDO entity) {
|
||||
RedisUtils.set(CacheConstants.TENANT_KEY + entity.getId(), entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void afterDelete(List<Long> ids) {
|
||||
ids.forEach(id -> RedisUtils.delete(CacheConstants.TENANT_KEY + id));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public TenantDO getTenantByUserId(Long userId) {
|
||||
return baseMapper.selectOne(Wrappers.lambdaQuery(TenantDO.class).eq(TenantDO::getUserId, userId));
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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.tenant.util;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.spring.SpringUtil;
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import top.continew.starter.core.exception.BusinessException;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @description: 数据连接工具类
|
||||
* @author: 小熊
|
||||
* @create: 2024-12-15 18:54
|
||||
*/
|
||||
public class DbConnectUtil {
|
||||
|
||||
/**
|
||||
* 格式化HikariConfig
|
||||
*/
|
||||
public static HikariConfig formatHikariConfig(String host,
|
||||
Integer port,
|
||||
String username,
|
||||
String password,
|
||||
String dbName,
|
||||
Map<String, String> parameter) {
|
||||
String activeProfile = SpringUtil.getActiveProfile();
|
||||
String jdbcUrl = StrUtil.format("jdbc:mysql://{}:{}", host, port);
|
||||
String driverClassName = "com.mysql.cj.jdbc.Driver";
|
||||
if ("dev".equals(activeProfile)) {
|
||||
jdbcUrl = StrUtil.format("jdbc:p6spy:mysql://{}:{}", host, port);
|
||||
driverClassName = "com.p6spy.engine.spy.P6SpyDriver";
|
||||
}
|
||||
if (StrUtil.isNotEmpty(dbName)) {
|
||||
jdbcUrl = StrUtil.format("{}/{}", jdbcUrl, dbName);
|
||||
}
|
||||
if (parameter != null) {
|
||||
jdbcUrl = StrUtil.format("{}?{}", jdbcUrl, MapUtil.join(parameter, "&", "="));
|
||||
}
|
||||
HikariConfig configuration = new HikariConfig();
|
||||
configuration.setJdbcUrl(jdbcUrl);
|
||||
configuration.setDriverClassName(driverClassName);
|
||||
configuration.setUsername(username);
|
||||
configuration.setPassword(password);
|
||||
configuration.setConnectionTimeout(3000L);
|
||||
return configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证mysql连接有效性并返回数据源
|
||||
*/
|
||||
public static DataSource getMysqlDataSource(String host,
|
||||
Integer port,
|
||||
String username,
|
||||
String password,
|
||||
String dbName,
|
||||
Map<String, String> parameter) {
|
||||
try {
|
||||
DataSource dataSource = new HikariDataSource(formatHikariConfig(host, port, username, password, dbName, parameter));
|
||||
Connection connection = dataSource.getConnection();
|
||||
connection.close();
|
||||
return dataSource;
|
||||
} catch (Exception e) {
|
||||
throw new BusinessException("数据库连接失败,请检查基础配置信息");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认的mysql连接参数
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static Map<String, String> getDefaultMysqlConnectParameter() {
|
||||
Map<String, String> parameter = new HashMap<>();
|
||||
parameter.put("serverTimezone", "Asia/Shanghai");
|
||||
parameter.put("useUnicode", "true");
|
||||
parameter.put("characterEncoding", "utf8");
|
||||
parameter.put("useSSL", "false");
|
||||
parameter.put("allowMultiQueries", "true");
|
||||
parameter.put("autoReconnect", "true");
|
||||
parameter.put("maxReconnects", "10");
|
||||
parameter.put("failOverReadOnly", "false");
|
||||
return parameter;
|
||||
}
|
||||
|
||||
}
|
@@ -19,6 +19,7 @@
|
||||
<module>continew-plugin-schedule</module>
|
||||
<module>continew-plugin-open</module>
|
||||
<module>continew-plugin-generator</module>
|
||||
<module>continew-plugin-tenant</module>
|
||||
</modules>
|
||||
|
||||
<dependencies>
|
||||
|
Reference in New Issue
Block a user