forked from github/cool-admin-java
feat: 多组织功能 - 实体/Service/Controller/拦截器/租户隔离
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
package com.cool.core.request;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
@@ -81,7 +82,17 @@ public class RequestParamsFilter implements Filter {
|
||||
}
|
||||
}
|
||||
// app端,userId 为当前登录的用户id
|
||||
case APP -> requestParams.set("userId", CoolSecurityUtil.getCurrentUserId());
|
||||
case APP -> {
|
||||
requestParams.set("userId", CoolSecurityUtil.getCurrentUserId());
|
||||
// App端:从tokenInfo中读取orgId作为tenantId,实现组织级数据隔离
|
||||
Object jwtObj = requestParams.get("tokenInfo");
|
||||
if (jwtObj instanceof Map) {
|
||||
Object orgId = ((Map<?, ?>) jwtObj).get("orgId");
|
||||
if (ObjUtil.isNotNull(orgId)) {
|
||||
requestParams.set("tenantId", Convert.toLong(orgId));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return CoolSecurityUtil.getTenantId(requestParams);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
package com.cool.core.security;
|
||||
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.cool.core.exception.CoolException;
|
||||
import com.cool.core.util.CoolSecurityUtil;
|
||||
import com.cool.modules.org.entity.AppOrgEntity;
|
||||
import com.cool.modules.org.entity.AppOrgModuleEntity;
|
||||
import com.cool.modules.org.entity.AppOrgUserEntity;
|
||||
import com.cool.modules.org.service.AppOrgModuleService;
|
||||
import com.cool.modules.org.service.AppOrgUserService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
@Component
|
||||
@Order(3)
|
||||
@RequiredArgsConstructor
|
||||
public class AppOrgAuthFilter extends OncePerRequestFilter {
|
||||
|
||||
private final AppOrgUserService appOrgUserService;
|
||||
private final AppOrgModuleService appOrgModuleService;
|
||||
|
||||
private static final Map<String, String> MODULE_PATH_MAP = Map.of(
|
||||
"/app/fruit/", "fruit",
|
||||
"/app/zoo/", "zoo",
|
||||
"/app/order/", "order",
|
||||
"/app/book/", "book",
|
||||
"/app/ticket/", "ticket"
|
||||
);
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain chain) throws ServletException, IOException {
|
||||
String uri = request.getRequestURI();
|
||||
|
||||
if (!uri.startsWith("/app/") || uri.startsWith("/app/org/") || uri.startsWith("/app/user/") || uri.startsWith("/app/base/") || uri.startsWith("/app/dict/")) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
if (com.cool.core.enums.UserTypeEnum.APP != CoolSecurityUtil.getCurrentUserType()) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
String moduleKey = resolveModuleKey(uri);
|
||||
if (moduleKey == null) {
|
||||
chain.doFilter(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
Long userId = CoolSecurityUtil.getCurrentUserId();
|
||||
String orgIdStr = request.getHeader("X-Org-Id");
|
||||
if (StrUtil.isBlank(orgIdStr)) {
|
||||
throw new CoolException("缺少组织信息", 403);
|
||||
}
|
||||
|
||||
Long orgId;
|
||||
try {
|
||||
orgId = Long.parseLong(orgIdStr);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new CoolException("无效的组织ID", 403);
|
||||
}
|
||||
|
||||
if (!appOrgUserService.isOrgMember(userId, orgId)) {
|
||||
throw new CoolException("未加入该组织", 403);
|
||||
}
|
||||
|
||||
if (!appOrgModuleService.isModuleAuthorized(orgId, moduleKey)) {
|
||||
throw new CoolException("该组织未授权此模块", 403);
|
||||
}
|
||||
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
|
||||
private String resolveModuleKey(String uri) {
|
||||
for (Map.Entry<String, String> entry : MODULE_PATH_MAP.entrySet()) {
|
||||
if (uri.startsWith(entry.getKey())) {
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,7 @@ public class JwtSecurityConfig {
|
||||
// 用户详情
|
||||
final private UserDetailsService userDetailsService;
|
||||
final private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
|
||||
final private AppOrgAuthFilter appOrgAuthFilter;
|
||||
// 401
|
||||
final private EntryPointUnauthorizedHandler entryPointUnauthorizedHandler;
|
||||
// 403
|
||||
@@ -72,6 +73,8 @@ public class JwtSecurityConfig {
|
||||
.sessionManagement(conf -> conf.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
|
||||
.addFilterBefore(jwtAuthenticationTokenFilter,
|
||||
UsernamePasswordAuthenticationFilter.class)
|
||||
.addFilterAfter(appOrgAuthFilter,
|
||||
JwtAuthenticationTokenFilter.class)
|
||||
.exceptionHandling(config -> {
|
||||
config.authenticationEntryPoint(entryPointUnauthorizedHandler);
|
||||
config.accessDeniedHandler(restAccessDeniedHandler);
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.cool.modules.fruit.controller.admin;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.base.BaseController;
|
||||
import com.cool.modules.fruit.entity.FruitGoodsEntity;
|
||||
import com.cool.modules.fruit.service.FruitGoodsService;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "水果管理", description = "水果商品管理")
|
||||
@CoolRestController(api = {"add", "delete", "update", "page", "info"})
|
||||
public class AdminFruitGoodsController extends BaseController<FruitGoodsService, FruitGoodsEntity> {
|
||||
|
||||
@Override
|
||||
protected void init(HttpServletRequest request, JSONObject requestParams) {
|
||||
setPageOption(createOp());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.cool.modules.fruit.controller.app;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.request.R;
|
||||
import com.cool.core.util.CoolSecurityUtil;
|
||||
import com.cool.modules.fruit.entity.FruitGoodsEntity;
|
||||
import com.cool.modules.fruit.service.FruitGoodsService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "水果", description = "App端水果")
|
||||
@CoolRestController
|
||||
public class AppFruitGoodsController {
|
||||
|
||||
private final FruitGoodsService fruitGoodsService;
|
||||
|
||||
@Operation(summary = "水果列表")
|
||||
@GetMapping("/list")
|
||||
public R list(@RequestAttribute JSONObject requestParams) {
|
||||
return R.ok(fruitGoodsService.list(requestParams, null));
|
||||
}
|
||||
|
||||
@Operation(summary = "水果详情")
|
||||
@GetMapping("/detail")
|
||||
public R detail(@RequestAttribute JSONObject requestParams) {
|
||||
Long id = requestParams.getLong("id");
|
||||
return R.ok(fruitGoodsService.info(id));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.cool.modules.fruit.entity;
|
||||
|
||||
import com.cool.core.base.TenantEntity;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.cool.core.annotation.ColumnDefine;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(value = "fruit_goods", comment = "水果商品表")
|
||||
public class FruitGoodsEntity extends TenantEntity<FruitGoodsEntity> {
|
||||
|
||||
@ColumnDefine(comment = "商品名称", notNull = true)
|
||||
private String name;
|
||||
|
||||
@ColumnDefine(comment = "价格")
|
||||
private Double price;
|
||||
|
||||
@ColumnDefine(comment = "单位")
|
||||
private String unit;
|
||||
|
||||
@ColumnDefine(comment = "图片")
|
||||
private String image;
|
||||
|
||||
@ColumnDefine(comment = "描述", type = "text")
|
||||
private String description;
|
||||
|
||||
@ColumnDefine(comment = "分类ID", type = "bigint")
|
||||
private Long categoryId;
|
||||
|
||||
@ColumnDefine(comment = "状态 0:下架 1:上架", defaultValue = "1")
|
||||
private Integer status;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.cool.modules.fruit.mapper;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.cool.modules.fruit.entity.FruitGoodsEntity;
|
||||
|
||||
public interface FruitGoodsMapper extends BaseMapper<FruitGoodsEntity> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.cool.modules.fruit.service;
|
||||
|
||||
import com.cool.core.base.BaseService;
|
||||
import com.cool.modules.fruit.entity.FruitGoodsEntity;
|
||||
|
||||
public interface FruitGoodsService extends BaseService<FruitGoodsEntity> {
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.cool.modules.fruit.service.impl;
|
||||
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.modules.fruit.entity.FruitGoodsEntity;
|
||||
import com.cool.modules.fruit.mapper.FruitGoodsMapper;
|
||||
import com.cool.modules.fruit.service.FruitGoodsService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class FruitGoodsServiceImpl extends BaseServiceImpl<FruitGoodsMapper, FruitGoodsEntity> implements
|
||||
FruitGoodsService {
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.cool.modules.order.controller.admin;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.base.BaseController;
|
||||
import com.cool.modules.order.entity.OrderInfoEntity;
|
||||
import com.cool.modules.order.service.OrderInfoService;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "订单管理", description = "订单信息管理")
|
||||
@CoolRestController(api = {"delete", "update", "page", "info"}, cname = "orderInfo")
|
||||
public class AdminOrderInfoController extends BaseController<OrderInfoService, OrderInfoEntity> {
|
||||
|
||||
@Override
|
||||
protected void init(HttpServletRequest request, JSONObject requestParams) {
|
||||
setPageOption(createOp());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.cool.modules.order.controller.app;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.request.R;
|
||||
import com.cool.modules.order.entity.OrderInfoEntity;
|
||||
import com.cool.modules.order.service.OrderInfoService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "订单", description = "App端订单")
|
||||
@CoolRestController
|
||||
public class AppOrderInfoController {
|
||||
|
||||
private final OrderInfoService orderInfoService;
|
||||
|
||||
@Operation(summary = "订单列表")
|
||||
@GetMapping("/list")
|
||||
public R list(@RequestAttribute JSONObject requestParams) {
|
||||
return R.ok(orderInfoService.list(requestParams, null));
|
||||
}
|
||||
|
||||
@Operation(summary = "订单详情")
|
||||
@GetMapping("/detail")
|
||||
public R detail(@RequestAttribute JSONObject requestParams) {
|
||||
Long id = requestParams.getLong("id");
|
||||
return R.ok(orderInfoService.info(id));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.cool.modules.order.entity;
|
||||
|
||||
import com.cool.core.base.TenantEntity;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.cool.core.annotation.ColumnDefine;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(value = "order_info", comment = "订单信息表")
|
||||
public class OrderInfoEntity extends TenantEntity<OrderInfoEntity> {
|
||||
|
||||
@ColumnDefine(comment = "订单号", notNull = true)
|
||||
private String orderNo;
|
||||
|
||||
@ColumnDefine(comment = "用户ID", type = "bigint")
|
||||
private Long userId;
|
||||
|
||||
@ColumnDefine(comment = "订单金额")
|
||||
private BigDecimal amount;
|
||||
|
||||
@ColumnDefine(comment = "状态 0:待支付 1:已支付 2:已完成 3:已取消", defaultValue = "0")
|
||||
private Integer status;
|
||||
|
||||
@ColumnDefine(comment = "备注", type = "text")
|
||||
private String remark;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.cool.modules.order.mapper;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.cool.modules.order.entity.OrderInfoEntity;
|
||||
|
||||
public interface OrderInfoMapper extends BaseMapper<OrderInfoEntity> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.cool.modules.order.service;
|
||||
|
||||
import com.cool.core.base.BaseService;
|
||||
import com.cool.modules.order.entity.OrderInfoEntity;
|
||||
|
||||
public interface OrderInfoService extends BaseService<OrderInfoEntity> {
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.cool.modules.order.service.impl;
|
||||
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.modules.order.entity.OrderInfoEntity;
|
||||
import com.cool.modules.order.mapper.OrderInfoMapper;
|
||||
import com.cool.modules.order.service.OrderInfoService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class OrderInfoServiceImpl extends BaseServiceImpl<OrderInfoMapper, OrderInfoEntity> implements
|
||||
OrderInfoService {
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.cool.modules.org.controller.admin;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.base.BaseController;
|
||||
import com.cool.core.request.R;
|
||||
import com.cool.modules.org.entity.AppModuleEntity;
|
||||
import com.cool.modules.org.service.AppModuleService;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "模块市场", description = "功能模块管理")
|
||||
@CoolRestController(api = {"add", "delete", "update", "page", "info"})
|
||||
public class AdminAppModuleController extends BaseController<AppModuleService, AppModuleEntity> {
|
||||
|
||||
@Override
|
||||
protected void init(HttpServletRequest request, JSONObject requestParams) {
|
||||
setPageOption(createOp());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.cool.modules.org.controller.admin;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.base.BaseController;
|
||||
import com.cool.core.request.R;
|
||||
import com.cool.modules.org.entity.AppOrgEntity;
|
||||
import com.cool.modules.org.service.AppOrgService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "组织管理", description = "组织管理")
|
||||
@CoolRestController(api = {"delete", "update", "page", "info"}, cname = "org")
|
||||
public class AdminAppOrgController extends BaseController<AppOrgService, AppOrgEntity> {
|
||||
|
||||
private final AppOrgService appOrgService;
|
||||
|
||||
@Override
|
||||
protected void init(HttpServletRequest request, JSONObject requestParams) {
|
||||
setPageOption(createOp());
|
||||
}
|
||||
|
||||
@Operation(summary = "创建组织")
|
||||
@PostMapping("/add")
|
||||
public R add(@RequestBody JSONObject requestParams) {
|
||||
AppOrgEntity entity = requestParams.toBean(AppOrgEntity.class);
|
||||
appOrgService.createOrg(requestParams, entity);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "授权模块")
|
||||
@PostMapping("/authorizeModules")
|
||||
public R authorizeModules(@RequestBody JSONObject requestParams) {
|
||||
Long orgId = requestParams.getLong("orgId");
|
||||
List<String> moduleKeys = requestParams.getBeanList("moduleKeys", String.class);
|
||||
appOrgService.authorizeModules(orgId, moduleKeys);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "切换组织")
|
||||
@PostMapping("/switch")
|
||||
public R switchOrg(@RequestBody JSONObject requestParams) {
|
||||
Long orgId = requestParams.getLong("orgId");
|
||||
Long userId = com.cool.core.util.CoolSecurityUtil.getCurrentUserId();
|
||||
appOrgService.switchOrg(userId, orgId, true);
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.cool.modules.org.controller.admin;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.base.BaseController;
|
||||
import com.cool.modules.org.entity.AppOrgModuleEntity;
|
||||
import com.cool.modules.org.service.AppOrgModuleService;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "组织模块授权", description = "组织模块授权管理")
|
||||
@CoolRestController(api = {"add", "delete", "update", "list"}, cname = "orgModule")
|
||||
public class AdminAppOrgModuleController extends BaseController<AppOrgModuleService, AppOrgModuleEntity> {
|
||||
|
||||
@Override
|
||||
protected void init(HttpServletRequest request, JSONObject requestParams) {
|
||||
setListOption(createOp());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.cool.modules.org.controller.admin;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.base.BaseController;
|
||||
import com.cool.core.request.R;
|
||||
import com.cool.modules.org.entity.AppOrgUserEntity;
|
||||
import com.cool.modules.org.service.AppOrgUserService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "组织成员管理", description = "组织成员管理")
|
||||
@CoolRestController(api = {"page", "list", "update", "delete"}, cname = "orgUser")
|
||||
public class AdminAppOrgUserController extends BaseController<AppOrgUserService, AppOrgUserEntity> {
|
||||
|
||||
private final AppOrgUserService appOrgUserService;
|
||||
|
||||
@Override
|
||||
protected void init(HttpServletRequest request, JSONObject requestParams) {
|
||||
setPageOption(createOp());
|
||||
}
|
||||
|
||||
@Operation(summary = "获取组织成员列表")
|
||||
@PostMapping("/memberList")
|
||||
public R memberList(@RequestAttribute JSONObject requestParams) {
|
||||
Long orgId = requestParams.getLong("orgId");
|
||||
List<Map<String, Object>> members = appOrgUserService.getMemberListByOrgId(orgId);
|
||||
return R.ok(members);
|
||||
}
|
||||
|
||||
@Operation(summary = "提升/降级App端管理员")
|
||||
@PostMapping("/changeRole")
|
||||
public R changeRole(@RequestBody JSONObject requestParams) {
|
||||
Long orgUserId = requestParams.getLong("id");
|
||||
String role = requestParams.getStr("role");
|
||||
AppOrgUserEntity orgUser = appOrgUserService.getById(orgUserId);
|
||||
com.cool.core.exception.CoolPreconditions.checkEmpty(orgUser, "记录不存在");
|
||||
orgUser.setRole(role);
|
||||
appOrgUserService.update(orgUser);
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.cool.modules.org.controller.app;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.request.R;
|
||||
import com.cool.core.util.CoolSecurityUtil;
|
||||
import com.cool.modules.org.service.AppOrgService;
|
||||
import com.cool.modules.org.service.AppOrgUserService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "组织", description = "App端组织管理")
|
||||
@CoolRestController
|
||||
public class AppOrgController {
|
||||
|
||||
private final AppOrgService appOrgService;
|
||||
private final AppOrgUserService appOrgUserService;
|
||||
|
||||
@Operation(summary = "获取已加入的组织列表")
|
||||
@GetMapping("/list")
|
||||
public R list() {
|
||||
Long userId = CoolSecurityUtil.getCurrentUserId();
|
||||
List<Map<String, Object>> orgList = appOrgUserService.getOrgListByUserId(userId);
|
||||
return R.ok(orgList);
|
||||
}
|
||||
|
||||
@Operation(summary = "通过邀请码加入组织")
|
||||
@PostMapping("/join")
|
||||
public R join(@RequestBody JSONObject requestParams) {
|
||||
Long userId = CoolSecurityUtil.getCurrentUserId();
|
||||
String inviteCode = requestParams.getStr("inviteCode");
|
||||
appOrgUserService.joinOrg(userId, inviteCode);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "通过orgId加入组织")
|
||||
@PostMapping("/joinById")
|
||||
public R joinById(@RequestBody JSONObject requestParams) {
|
||||
Long userId = CoolSecurityUtil.getCurrentUserId();
|
||||
Long orgId = requestParams.getLong("orgId");
|
||||
appOrgUserService.joinOrgById(userId, orgId);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "退出组织")
|
||||
@PostMapping("/quit")
|
||||
public R quit(@RequestBody JSONObject requestParams) {
|
||||
Long userId = CoolSecurityUtil.getCurrentUserId();
|
||||
Long orgId = requestParams.getLong("orgId");
|
||||
appOrgUserService.quitOrg(userId, orgId);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@Operation(summary = "切换组织")
|
||||
@PostMapping("/switch")
|
||||
public R switchOrg(@RequestBody JSONObject requestParams) {
|
||||
Long userId = CoolSecurityUtil.getCurrentUserId();
|
||||
Long orgId = requestParams.getLong("orgId");
|
||||
Object result = appOrgService.switchOrg(userId, orgId, false);
|
||||
return R.ok(result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.cool.modules.org.controller.app;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.exception.CoolPreconditions;
|
||||
import com.cool.core.request.R;
|
||||
import com.cool.core.util.CoolSecurityUtil;
|
||||
import com.cool.modules.org.service.AppOrgUserService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "组织成员", description = "App端组织成员管理")
|
||||
@CoolRestController
|
||||
public class AppOrgUserController {
|
||||
|
||||
private final AppOrgUserService appOrgUserService;
|
||||
|
||||
@Operation(summary = "获取组织成员列表")
|
||||
@PostMapping("/memberList")
|
||||
public R memberList(@RequestBody JSONObject requestParams) {
|
||||
Long orgId = requestParams.getLong("orgId");
|
||||
Long userId = CoolSecurityUtil.getCurrentUserId();
|
||||
CoolPreconditions.check(!appOrgUserService.isOrgMember(userId, orgId), "无权查看该组织成员");
|
||||
List<Map<String, Object>> members = appOrgUserService.getMemberListByOrgId(orgId);
|
||||
return R.ok(members);
|
||||
}
|
||||
|
||||
@Operation(summary = "审批成员加入")
|
||||
@PostMapping("/approve")
|
||||
public R approve(@RequestBody JSONObject requestParams) {
|
||||
Long orgId = requestParams.getLong("orgId");
|
||||
Long targetUserId = requestParams.getLong("userId");
|
||||
Boolean approved = requestParams.getBool("approved", true);
|
||||
Long adminUserId = CoolSecurityUtil.getCurrentUserId();
|
||||
appOrgUserService.approve(adminUserId, orgId, targetUserId, approved);
|
||||
return R.ok();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package com.cool.modules.org.entity;
|
||||
|
||||
import com.cool.core.base.BaseEntity;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.cool.core.annotation.ColumnDefine;
|
||||
import com.tangzc.mybatisflex.autotable.annotation.UniIndex;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(value = "app_module", comment = "功能模块注册表")
|
||||
public class AppModuleEntity extends BaseEntity<AppModuleEntity> {
|
||||
|
||||
@UniIndex
|
||||
@ColumnDefine(comment = "模块标识", notNull = true)
|
||||
private String moduleKey;
|
||||
|
||||
@ColumnDefine(comment = "模块名称", notNull = true)
|
||||
private String name;
|
||||
|
||||
@ColumnDefine(comment = "模块图标")
|
||||
private String icon;
|
||||
|
||||
@ColumnDefine(comment = "模块描述", type = "text")
|
||||
private String description;
|
||||
|
||||
@ColumnDefine(comment = "关联的admin菜单ID列表", type = "text")
|
||||
private String menuIds;
|
||||
|
||||
@ColumnDefine(comment = "关联的App页面路由配置", type = "text")
|
||||
private String appPages;
|
||||
|
||||
@ColumnDefine(comment = "要求的最低App版本号")
|
||||
private String minAppVersion;
|
||||
|
||||
@ColumnDefine(comment = "状态 0:禁用 1:启用", defaultValue = "1")
|
||||
private Integer status;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package com.cool.modules.org.entity;
|
||||
|
||||
import com.cool.core.base.BaseEntity;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.cool.core.annotation.ColumnDefine;
|
||||
import com.tangzc.mybatisflex.autotable.annotation.UniIndex;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(value = "app_org", comment = "组织表")
|
||||
public class AppOrgEntity extends BaseEntity<AppOrgEntity> {
|
||||
|
||||
@ColumnDefine(comment = "组织名称", notNull = true)
|
||||
private String name;
|
||||
|
||||
@ColumnDefine(comment = "组织类型")
|
||||
private String type;
|
||||
|
||||
@ColumnDefine(comment = "组织图标/Logo")
|
||||
private String icon;
|
||||
|
||||
@ColumnDefine(comment = "组织简介", type = "text")
|
||||
private String description;
|
||||
|
||||
@UniIndex
|
||||
@ColumnDefine(comment = "邀请码")
|
||||
private String inviteCode;
|
||||
|
||||
@ColumnDefine(comment = "加入方式 0:自由加入 1:需审批", defaultValue = "0")
|
||||
private Integer joinType;
|
||||
|
||||
@ColumnDefine(comment = "状态 0:禁用 1:启用", defaultValue = "1")
|
||||
private Integer status;
|
||||
|
||||
@ColumnDefine(comment = "Admin端组织管理员userId", type = "bigint")
|
||||
private Long adminUserId;
|
||||
|
||||
@ColumnDefine(comment = "组织级扩展配置", type = "text")
|
||||
private String config;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.cool.modules.org.entity;
|
||||
|
||||
import com.cool.core.base.BaseEntity;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.cool.core.annotation.ColumnDefine;
|
||||
import com.tangzc.mybatisflex.autotable.annotation.UniIndex;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.dromara.autotable.annotation.Index;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(value = "app_org_module", comment = "组织模块关联表")
|
||||
public class AppOrgModuleEntity extends BaseEntity<AppOrgModuleEntity> {
|
||||
|
||||
@Index
|
||||
@ColumnDefine(comment = "组织ID", type = "bigint", notNull = true)
|
||||
private Long orgId;
|
||||
|
||||
@Index
|
||||
@ColumnDefine(comment = "模块标识", notNull = true)
|
||||
private String moduleKey;
|
||||
|
||||
@ColumnDefine(comment = "组织级模块配置", type = "text")
|
||||
private String config;
|
||||
|
||||
@ColumnDefine(comment = "状态 0:禁用 1:启用", defaultValue = "1")
|
||||
private Integer status;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.cool.modules.org.entity;
|
||||
|
||||
import com.cool.core.base.BaseEntity;
|
||||
import com.mybatisflex.annotation.Column;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.cool.core.annotation.ColumnDefine;
|
||||
import com.tangzc.mybatisflex.autotable.annotation.UniIndex;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.dromara.autotable.annotation.Index;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(value = "app_org_user", comment = "组织用户关联表")
|
||||
public class AppOrgUserEntity extends BaseEntity<AppOrgUserEntity> {
|
||||
|
||||
@Index
|
||||
@ColumnDefine(comment = "组织ID", type = "bigint", notNull = true)
|
||||
private Long orgId;
|
||||
|
||||
@Index
|
||||
@ColumnDefine(comment = "App用户ID", type = "bigint", notNull = true)
|
||||
private Long userId;
|
||||
|
||||
@ColumnDefine(comment = "角色 member/admin", defaultValue = "member")
|
||||
private String role;
|
||||
|
||||
@ColumnDefine(comment = "状态 0:待审批 1:已加入 2:已拒绝 3:已退出", defaultValue = "0")
|
||||
private Integer status;
|
||||
|
||||
@ColumnDefine(comment = "加入时间")
|
||||
private Date joinTime;
|
||||
|
||||
@Column(ignore = true)
|
||||
private String orgName;
|
||||
|
||||
@Column(ignore = true)
|
||||
private String nickName;
|
||||
|
||||
@Column(ignore = true)
|
||||
private String avatarUrl;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.cool.modules.org.mapper;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.cool.modules.org.entity.AppModuleEntity;
|
||||
|
||||
public interface AppModuleMapper extends BaseMapper<AppModuleEntity> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.cool.modules.org.mapper;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.cool.modules.org.entity.AppOrgEntity;
|
||||
|
||||
public interface AppOrgMapper extends BaseMapper<AppOrgEntity> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.cool.modules.org.mapper;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.cool.modules.org.entity.AppOrgModuleEntity;
|
||||
|
||||
public interface AppOrgModuleMapper extends BaseMapper<AppOrgModuleEntity> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.cool.modules.org.mapper;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.cool.modules.org.entity.AppOrgUserEntity;
|
||||
|
||||
public interface AppOrgUserMapper extends BaseMapper<AppOrgUserEntity> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.cool.modules.org.service;
|
||||
|
||||
import com.cool.core.base.BaseService;
|
||||
import com.cool.modules.org.entity.AppModuleEntity;
|
||||
|
||||
public interface AppModuleService extends BaseService<AppModuleEntity> {
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.cool.modules.org.service;
|
||||
|
||||
import com.cool.core.base.BaseService;
|
||||
import com.cool.modules.org.entity.AppOrgModuleEntity;
|
||||
import java.util.List;
|
||||
|
||||
public interface AppOrgModuleService extends BaseService<AppOrgModuleEntity> {
|
||||
|
||||
List<String> getModuleKeysByOrgId(Long orgId);
|
||||
|
||||
boolean isModuleAuthorized(Long orgId, String moduleKey);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.cool.modules.org.service;
|
||||
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.base.BaseService;
|
||||
import com.cool.modules.org.entity.AppOrgEntity;
|
||||
import java.util.List;
|
||||
|
||||
public interface AppOrgService extends BaseService<AppOrgEntity> {
|
||||
|
||||
void createOrg(JSONObject requestParams, AppOrgEntity entity);
|
||||
|
||||
void authorizeModules(Long orgId, List<String> moduleKeys);
|
||||
|
||||
Dict switchOrg(Long userId, Long orgId, boolean isAdmin);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.cool.modules.org.service;
|
||||
|
||||
import com.cool.core.base.BaseService;
|
||||
import com.cool.modules.org.entity.AppOrgUserEntity;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface AppOrgUserService extends BaseService<AppOrgUserEntity> {
|
||||
|
||||
void joinOrg(Long userId, String inviteCode);
|
||||
|
||||
void joinOrgById(Long userId, Long orgId);
|
||||
|
||||
void quitOrg(Long userId, Long orgId);
|
||||
|
||||
void approve(Long adminUserId, Long orgId, Long targetUserId, boolean approved);
|
||||
|
||||
List<Map<String, Object>> getOrgListByUserId(Long userId);
|
||||
|
||||
List<Map<String, Object>> getMemberListByOrgId(Long orgId);
|
||||
|
||||
boolean isOrgAdmin(Long userId, Long orgId);
|
||||
|
||||
boolean isOrgMember(Long userId, Long orgId);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.cool.modules.org.service.impl;
|
||||
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.modules.org.mapper.AppModuleMapper;
|
||||
import com.cool.modules.org.entity.AppModuleEntity;
|
||||
import com.cool.modules.org.service.AppModuleService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class AppModuleServiceImpl extends BaseServiceImpl<AppModuleMapper, AppModuleEntity> implements
|
||||
AppModuleService {
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.cool.modules.org.service.impl;
|
||||
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.modules.org.entity.AppOrgModuleEntity;
|
||||
import com.cool.modules.org.mapper.AppOrgModuleMapper;
|
||||
import com.cool.modules.org.service.AppOrgModuleService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class AppOrgModuleServiceImpl extends BaseServiceImpl<AppOrgModuleMapper, AppOrgModuleEntity> implements
|
||||
AppOrgModuleService {
|
||||
|
||||
@Override
|
||||
public List<String> getModuleKeysByOrgId(Long orgId) {
|
||||
List<AppOrgModuleEntity> modules = list(QueryWrapper.create()
|
||||
.eq(AppOrgModuleEntity::getOrgId, orgId)
|
||||
.eq(AppOrgModuleEntity::getStatus, 1));
|
||||
return modules.stream()
|
||||
.map(AppOrgModuleEntity::getModuleKey)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isModuleAuthorized(Long orgId, String moduleKey) {
|
||||
AppOrgModuleEntity module = getOne(QueryWrapper.create()
|
||||
.eq(AppOrgModuleEntity::getOrgId, orgId)
|
||||
.eq(AppOrgModuleEntity::getModuleKey, moduleKey)
|
||||
.eq(AppOrgModuleEntity::getStatus, 1));
|
||||
return module != null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
package com.cool.modules.org.service.impl;
|
||||
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.core.cache.CoolCache;
|
||||
import com.cool.core.enums.UserTypeEnum;
|
||||
import com.cool.core.exception.CoolPreconditions;
|
||||
import com.cool.core.security.jwt.JwtTokenUtil;
|
||||
import com.cool.core.security.jwt.JwtUser;
|
||||
import com.cool.modules.base.entity.sys.BaseSysRoleEntity;
|
||||
import com.cool.modules.base.entity.sys.BaseSysUserRoleEntity;
|
||||
import com.cool.modules.base.mapper.sys.BaseSysRoleMapper;
|
||||
import com.cool.modules.base.mapper.sys.BaseSysUserMapper;
|
||||
import com.cool.modules.base.mapper.sys.BaseSysUserRoleMapper;
|
||||
import com.cool.modules.base.service.sys.BaseSysPermsService;
|
||||
import com.cool.modules.org.entity.AppModuleEntity;
|
||||
import com.cool.modules.org.entity.AppOrgEntity;
|
||||
import com.cool.modules.org.entity.AppOrgModuleEntity;
|
||||
import com.cool.modules.org.mapper.AppOrgMapper;
|
||||
import com.cool.modules.org.mapper.AppModuleMapper;
|
||||
import com.cool.modules.org.service.AppOrgModuleService;
|
||||
import com.cool.modules.org.service.AppOrgService;
|
||||
import com.cool.modules.org.service.AppOrgUserService;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import com.mybatisflex.core.tenant.TenantManager;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AppOrgServiceImpl extends BaseServiceImpl<AppOrgMapper, AppOrgEntity> implements
|
||||
AppOrgService {
|
||||
|
||||
private final AppModuleMapper appModuleMapper;
|
||||
private final BaseSysRoleMapper baseSysRoleMapper;
|
||||
private final BaseSysUserRoleMapper baseSysUserRoleMapper;
|
||||
private final BaseSysUserMapper baseSysUserMapper;
|
||||
private final BaseSysPermsService baseSysPermsService;
|
||||
private final AppOrgModuleService appOrgModuleService;
|
||||
private final AppOrgUserService appOrgUserService;
|
||||
private final CoolCache coolCache;
|
||||
private final JwtTokenUtil jwtTokenUtil;
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void createOrg(JSONObject requestParams, AppOrgEntity entity) {
|
||||
entity.setInviteCode(generateInviteCode());
|
||||
this.add(entity);
|
||||
|
||||
Long orgId = entity.getId();
|
||||
|
||||
BaseSysRoleEntity role = new BaseSysRoleEntity();
|
||||
role.setName(entity.getName() + "管理员");
|
||||
role.setLabel("org_admin_" + orgId);
|
||||
role.setRemark("组织[" + entity.getName() + "]自动创建的管理角色");
|
||||
role.setStatus(1);
|
||||
role.setTenantId(orgId);
|
||||
TenantManager.withoutTenantCondition(() -> {
|
||||
baseSysRoleMapper.insertSelective(role);
|
||||
});
|
||||
|
||||
if (entity.getAdminUserId() != null) {
|
||||
BaseSysUserRoleEntity userRole = new BaseSysUserRoleEntity();
|
||||
userRole.setUserId(entity.getAdminUserId());
|
||||
userRole.setRoleId(role.getId());
|
||||
TenantManager.withoutTenantCondition(() -> {
|
||||
baseSysUserRoleMapper.insertSelective(userRole);
|
||||
});
|
||||
|
||||
com.cool.modules.base.entity.sys.BaseSysUserEntity adminUser = baseSysUserMapper.selectOneById(entity.getAdminUserId());
|
||||
if (adminUser != null) {
|
||||
adminUser.setTenantId(orgId);
|
||||
TenantManager.withoutTenantCondition(() -> {
|
||||
baseSysUserMapper.update(adminUser);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (requestParams != null) {
|
||||
List<String> moduleKeys = requestParams.getBeanList("moduleKeys", String.class);
|
||||
if (moduleKeys != null && !moduleKeys.isEmpty()) {
|
||||
authorizeModules(orgId, moduleKeys);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void authorizeModules(Long orgId, List<String> moduleKeys) {
|
||||
QueryWrapper qw = QueryWrapper.create()
|
||||
.eq(AppOrgModuleEntity::getOrgId, orgId);
|
||||
appOrgModuleService.remove(qw);
|
||||
|
||||
for (String moduleKey : moduleKeys) {
|
||||
AppModuleEntity module = appModuleMapper.selectOneByQuery(
|
||||
QueryWrapper.create().eq(AppModuleEntity::getModuleKey, moduleKey)
|
||||
);
|
||||
CoolPreconditions.checkEmpty(module, "模块{}不存在", moduleKey);
|
||||
|
||||
AppOrgModuleEntity orgModule = new AppOrgModuleEntity();
|
||||
orgModule.setOrgId(orgId);
|
||||
orgModule.setModuleKey(moduleKey);
|
||||
orgModule.setStatus(1);
|
||||
appOrgModuleService.add(orgModule);
|
||||
}
|
||||
|
||||
BaseSysRoleEntity role = TenantManager.withoutTenantCondition(() ->
|
||||
baseSysRoleMapper.selectOneByQuery(
|
||||
QueryWrapper.create().eq(BaseSysRoleEntity::getLabel, "org_admin_" + orgId)
|
||||
)
|
||||
);
|
||||
if (role != null) {
|
||||
List<Long> menuIds = new java.util.ArrayList<>();
|
||||
for (String moduleKey : moduleKeys) {
|
||||
AppModuleEntity module = appModuleMapper.selectOneByQuery(
|
||||
QueryWrapper.create().eq(AppModuleEntity::getModuleKey, moduleKey)
|
||||
);
|
||||
if (module != null && StrUtil.isNotBlank(module.getMenuIds())) {
|
||||
cn.hutool.json.JSONArray arr = new cn.hutool.json.JSONArray(module.getMenuIds());
|
||||
for (Object o : arr) {
|
||||
menuIds.add(Long.valueOf(o.toString()));
|
||||
}
|
||||
}
|
||||
}
|
||||
baseSysPermsService.updatePerms(role.getId(), menuIds.toArray(new Long[0]), null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dict switchOrg(Long userId, Long orgId, boolean isAdmin) {
|
||||
if (isAdmin) {
|
||||
BaseSysUserRoleEntity userRole = baseSysUserRoleMapper.selectOneByQuery(
|
||||
QueryWrapper.create().eq(BaseSysUserRoleEntity::getUserId, userId)
|
||||
);
|
||||
CoolPreconditions.checkEmpty(userRole, "无权切换到该组织");
|
||||
|
||||
BaseSysRoleEntity role = baseSysRoleMapper.selectOneById(userRole.getRoleId());
|
||||
CoolPreconditions.checkEmpty(role, "角色不存在");
|
||||
CoolPreconditions.check(!orgId.equals(role.getTenantId()), "无权切换到该组织");
|
||||
} else {
|
||||
CoolPreconditions.check(!appOrgUserService.isOrgMember(userId, orgId), "未加入该组织");
|
||||
}
|
||||
|
||||
AppOrgEntity org = this.getById(orgId);
|
||||
CoolPreconditions.checkEmpty(org, "组织不存在");
|
||||
CoolPreconditions.check(org.getStatus() == 0, "组织已停用");
|
||||
|
||||
if (!isAdmin) {
|
||||
Dict tokenInfo = Dict.create()
|
||||
.set("userType", UserTypeEnum.APP.name())
|
||||
.set("userId", userId)
|
||||
.set("orgId", orgId);
|
||||
String token = jwtTokenUtil.generateToken(tokenInfo);
|
||||
String refreshToken = jwtTokenUtil.generateRefreshToken(tokenInfo);
|
||||
|
||||
JwtUser jwtUser = new JwtUser(userId,
|
||||
List.of(new SimpleGrantedAuthority("ROLE_" + UserTypeEnum.APP.name())),
|
||||
true);
|
||||
coolCache.set("app:userDetails:" + userId, jwtUser);
|
||||
|
||||
return Dict.create()
|
||||
.set("token", token)
|
||||
.set("expire", jwtTokenUtil.getExpire())
|
||||
.set("refreshToken", refreshToken)
|
||||
.set("refreshExpire", jwtTokenUtil.getRefreshExpire())
|
||||
.set("orgId", orgId);
|
||||
}
|
||||
return Dict.create().set("orgId", orgId);
|
||||
}
|
||||
|
||||
private String generateInviteCode() {
|
||||
String code;
|
||||
do {
|
||||
code = RandomUtil.randomStringUpper(6);
|
||||
} while (this.getOne(
|
||||
QueryWrapper.create().eq(AppOrgEntity::getInviteCode, code)
|
||||
) != null);
|
||||
return code;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
package com.cool.modules.org.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ObjUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.core.exception.CoolPreconditions;
|
||||
import com.cool.modules.org.entity.AppOrgEntity;
|
||||
import com.cool.modules.org.entity.AppOrgModuleEntity;
|
||||
import com.cool.modules.org.entity.AppOrgUserEntity;
|
||||
import com.cool.modules.org.mapper.AppOrgMapper;
|
||||
import com.cool.modules.org.mapper.AppOrgUserMapper;
|
||||
import com.cool.modules.org.service.AppOrgModuleService;
|
||||
import com.cool.modules.org.service.AppOrgUserService;
|
||||
import com.cool.modules.user.entity.UserInfoEntity;
|
||||
import com.cool.modules.user.mapper.UserInfoMapper;
|
||||
import com.mybatisflex.core.query.QueryWrapper;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AppOrgUserServiceImpl extends BaseServiceImpl<AppOrgUserMapper, AppOrgUserEntity> implements
|
||||
AppOrgUserService {
|
||||
|
||||
private final AppOrgModuleService appOrgModuleService;
|
||||
private final UserInfoMapper userInfoMapper;
|
||||
private final AppOrgMapper appOrgMapper;
|
||||
|
||||
@Override
|
||||
public void joinOrg(Long userId, String inviteCode) {
|
||||
CoolPreconditions.check(StrUtil.isBlank(inviteCode), "邀请码不能为空");
|
||||
|
||||
AppOrgEntity orgEntity = appOrgMapper.selectOneByQuery(
|
||||
QueryWrapper.create().eq(AppOrgEntity::getInviteCode, inviteCode)
|
||||
);
|
||||
CoolPreconditions.checkEmpty(orgEntity, "邀请码无效");
|
||||
CoolPreconditions.check(orgEntity.getStatus() == 0, "组织已停用");
|
||||
|
||||
joinOrgById(userId, orgEntity.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void joinOrgById(Long userId, Long orgId) {
|
||||
AppOrgUserEntity existing = getOne(QueryWrapper.create()
|
||||
.eq(AppOrgUserEntity::getOrgId, orgId)
|
||||
.eq(AppOrgUserEntity::getUserId, userId));
|
||||
CoolPreconditions.check(existing != null && existing.getStatus() == 1, "已加入该组织");
|
||||
CoolPreconditions.check(existing != null && existing.getStatus() == 0, "已申请加入,等待审批");
|
||||
|
||||
AppOrgEntity orgEntity = appOrgMapper.selectOneById(orgId);
|
||||
CoolPreconditions.checkEmpty(orgEntity, "组织不存在");
|
||||
CoolPreconditions.check(orgEntity.getStatus() == 0, "组织已停用");
|
||||
|
||||
AppOrgUserEntity orgUser = new AppOrgUserEntity();
|
||||
orgUser.setOrgId(orgId);
|
||||
orgUser.setUserId(userId);
|
||||
orgUser.setRole("member");
|
||||
|
||||
if (orgEntity.getJoinType() == 0) {
|
||||
orgUser.setStatus(1);
|
||||
orgUser.setJoinTime(new java.util.Date());
|
||||
} else {
|
||||
orgUser.setStatus(0);
|
||||
}
|
||||
|
||||
if (existing != null) {
|
||||
orgUser.setId(existing.getId());
|
||||
this.update(orgUser);
|
||||
} else {
|
||||
this.add(orgUser);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void quitOrg(Long userId, Long orgId) {
|
||||
AppOrgUserEntity orgUser = getOne(QueryWrapper.create()
|
||||
.eq(AppOrgUserEntity::getOrgId, orgId)
|
||||
.eq(AppOrgUserEntity::getUserId, userId)
|
||||
.eq(AppOrgUserEntity::getStatus, 1));
|
||||
CoolPreconditions.checkEmpty(orgUser, "未加入该组织");
|
||||
|
||||
orgUser.setStatus(3);
|
||||
this.update(orgUser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void approve(Long adminUserId, Long orgId, Long targetUserId, boolean approved) {
|
||||
CoolPreconditions.check(!isOrgAdmin(adminUserId, orgId), "无审批权限");
|
||||
|
||||
AppOrgUserEntity orgUser = getOne(QueryWrapper.create()
|
||||
.eq(AppOrgUserEntity::getOrgId, orgId)
|
||||
.eq(AppOrgUserEntity::getUserId, targetUserId)
|
||||
.eq(AppOrgUserEntity::getStatus, 0));
|
||||
CoolPreconditions.checkEmpty(orgUser, "无待审批记录");
|
||||
|
||||
orgUser.setStatus(approved ? 1 : 2);
|
||||
if (approved) {
|
||||
orgUser.setJoinTime(new java.util.Date());
|
||||
}
|
||||
this.update(orgUser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Map<String, Object>> getOrgListByUserId(Long userId) {
|
||||
List<AppOrgUserEntity> orgUsers = list(QueryWrapper.create()
|
||||
.eq(AppOrgUserEntity::getUserId, userId)
|
||||
.eq(AppOrgUserEntity::getStatus, 1));
|
||||
|
||||
List<Map<String, Object>> result = new ArrayList<>();
|
||||
for (AppOrgUserEntity ou : orgUsers) {
|
||||
Map<String, Object> item = new HashMap<>();
|
||||
item.put("orgId", ou.getOrgId());
|
||||
item.put("role", ou.getRole());
|
||||
item.put("joinTime", ou.getJoinTime());
|
||||
|
||||
AppOrgEntity org = appOrgMapper.selectOneById(ou.getOrgId());
|
||||
if (org != null) {
|
||||
item.put("name", org.getName());
|
||||
item.put("icon", org.getIcon());
|
||||
item.put("type", org.getType());
|
||||
item.put("status", org.getStatus());
|
||||
}
|
||||
|
||||
// Get modules
|
||||
List<String> moduleKeys = appOrgModuleService.getModuleKeysByOrgId(ou.getOrgId());
|
||||
item.put("modules", moduleKeys);
|
||||
|
||||
result.add(item);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Map<String, Object>> getMemberListByOrgId(Long orgId) {
|
||||
List<AppOrgUserEntity> orgUsers = list(QueryWrapper.create()
|
||||
.eq(AppOrgUserEntity::getOrgId, orgId)
|
||||
.eq(AppOrgUserEntity::getStatus, 1));
|
||||
|
||||
List<Map<String, Object>> result = new ArrayList<>();
|
||||
for (AppOrgUserEntity ou : orgUsers) {
|
||||
Map<String, Object> item = new HashMap<>();
|
||||
item.put("id", ou.getId());
|
||||
item.put("userId", ou.getUserId());
|
||||
item.put("role", ou.getRole());
|
||||
item.put("joinTime", ou.getJoinTime());
|
||||
|
||||
UserInfoEntity user = userInfoMapper.selectOneById(ou.getUserId());
|
||||
if (user != null) {
|
||||
item.put("nickName", user.getNickName());
|
||||
item.put("avatarUrl", user.getAvatarUrl());
|
||||
item.put("phone", user.getPhone());
|
||||
}
|
||||
result.add(item);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOrgAdmin(Long userId, Long orgId) {
|
||||
AppOrgUserEntity orgUser = getOne(QueryWrapper.create()
|
||||
.eq(AppOrgUserEntity::getOrgId, orgId)
|
||||
.eq(AppOrgUserEntity::getUserId, userId)
|
||||
.eq(AppOrgUserEntity::getStatus, 1)
|
||||
.eq(AppOrgUserEntity::getRole, "admin"));
|
||||
return orgUser != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOrgMember(Long userId, Long orgId) {
|
||||
AppOrgUserEntity orgUser = getOne(QueryWrapper.create()
|
||||
.eq(AppOrgUserEntity::getOrgId, orgId)
|
||||
.eq(AppOrgUserEntity::getUserId, userId)
|
||||
.eq(AppOrgUserEntity::getStatus, 1));
|
||||
return orgUser != null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package com.cool.modules.zoo.controller.admin;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.base.BaseController;
|
||||
import com.cool.modules.zoo.entity.ZooAnimalEntity;
|
||||
import com.cool.modules.zoo.service.ZooAnimalService;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "动物管理", description = "动物信息管理")
|
||||
@CoolRestController(api = {"add", "delete", "update", "page", "info"})
|
||||
public class AdminZooAnimalController extends BaseController<ZooAnimalService, ZooAnimalEntity> {
|
||||
|
||||
@Override
|
||||
protected void init(HttpServletRequest request, JSONObject requestParams) {
|
||||
setPageOption(createOp());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.cool.modules.zoo.controller.app;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import com.cool.core.annotation.CoolRestController;
|
||||
import com.cool.core.request.R;
|
||||
import com.cool.modules.zoo.entity.ZooAnimalEntity;
|
||||
import com.cool.modules.zoo.service.ZooAnimalService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestAttribute;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "动物", description = "App端动物")
|
||||
@CoolRestController
|
||||
public class AppZooAnimalController {
|
||||
|
||||
private final ZooAnimalService zooAnimalService;
|
||||
|
||||
@Operation(summary = "动物列表")
|
||||
@GetMapping("/list")
|
||||
public R list(@RequestAttribute JSONObject requestParams) {
|
||||
return R.ok(zooAnimalService.list(requestParams, null));
|
||||
}
|
||||
|
||||
@Operation(summary = "动物详情")
|
||||
@GetMapping("/detail")
|
||||
public R detail(@RequestAttribute JSONObject requestParams) {
|
||||
Long id = requestParams.getLong("id");
|
||||
return R.ok(zooAnimalService.info(id));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.cool.modules.zoo.entity;
|
||||
|
||||
import com.cool.core.base.TenantEntity;
|
||||
import com.mybatisflex.annotation.Table;
|
||||
import com.cool.core.annotation.ColumnDefine;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(value = "zoo_animal", comment = "动物信息表")
|
||||
public class ZooAnimalEntity extends TenantEntity<ZooAnimalEntity> {
|
||||
|
||||
@ColumnDefine(comment = "动物名称", notNull = true)
|
||||
private String name;
|
||||
|
||||
@ColumnDefine(comment = "分类")
|
||||
private String category;
|
||||
|
||||
@ColumnDefine(comment = "展区")
|
||||
private String area;
|
||||
|
||||
@ColumnDefine(comment = "图片")
|
||||
private String image;
|
||||
|
||||
@ColumnDefine(comment = "描述", type = "text")
|
||||
private String description;
|
||||
|
||||
@ColumnDefine(comment = "状态 0:离开 1:展出", defaultValue = "1")
|
||||
private Integer status;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.cool.modules.zoo.mapper;
|
||||
|
||||
import com.mybatisflex.core.BaseMapper;
|
||||
import com.cool.modules.zoo.entity.ZooAnimalEntity;
|
||||
|
||||
public interface ZooAnimalMapper extends BaseMapper<ZooAnimalEntity> {
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.cool.modules.zoo.service;
|
||||
|
||||
import com.cool.core.base.BaseService;
|
||||
import com.cool.modules.zoo.entity.ZooAnimalEntity;
|
||||
|
||||
public interface ZooAnimalService extends BaseService<ZooAnimalEntity> {
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package com.cool.modules.zoo.service.impl;
|
||||
|
||||
import com.cool.core.base.BaseServiceImpl;
|
||||
import com.cool.modules.zoo.entity.ZooAnimalEntity;
|
||||
import com.cool.modules.zoo.mapper.ZooAnimalMapper;
|
||||
import com.cool.modules.zoo.service.ZooAnimalService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
public class ZooAnimalServiceImpl extends BaseServiceImpl<ZooAnimalMapper, ZooAnimalEntity> implements
|
||||
ZooAnimalService {
|
||||
}
|
||||
@@ -153,7 +153,7 @@ cool:
|
||||
queue-capacity-multiplier: 3
|
||||
multi-tenant:
|
||||
# 是否开启多租户,默认关闭
|
||||
enable: false
|
||||
enable: true
|
||||
# AutoTable配置,根据实体类自动生成表
|
||||
auto-table:
|
||||
show-banner: false
|
||||
|
||||
Reference in New Issue
Block a user