暂存提交

This commit is contained in:
2026-07-31 18:10:32 +08:00
parent e834482717
commit 9a37657148
35 changed files with 435 additions and 44 deletions
@@ -92,7 +92,8 @@ public class MerchantTenantController {
@PreAuthorize("hasAuthority('merchant:member:create')")
public ApiResponse<MemberResponse> addMember(@Valid @RequestBody CreateMemberRequest request,
@AuthenticationPrincipal AuthenticatedUser user) {
return ApiResponse.success(memberService.create(TenantGuard.tenant(user, "MERCHANT"), request));
return ApiResponse.success(memberService.create(TenantGuard.tenant(user, "MERCHANT"), request,
user.permissions()));
}
@PutMapping("/members/{membershipId:\\d+}")
@@ -100,7 +101,8 @@ public class MerchantTenantController {
@Operation(summary = "编辑企业成员及角色")
public ApiResponse<MemberResponse> updateMember(@PathVariable Long membershipId,
@Valid @RequestBody UpdateMemberRequest request, @AuthenticationPrincipal AuthenticatedUser user) {
return ApiResponse.success(memberService.update(TenantGuard.tenant(user, "MERCHANT"), membershipId, request));
return ApiResponse.success(memberService.update(TenantGuard.tenant(user, "MERCHANT"), membershipId, request,
user.permissions()));
}
@PutMapping("/members/{membershipId:\\d+}/status")
@@ -18,13 +18,16 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** 企业成员闭环服务,账号凭据归 auth-service,人员档案与租户关系归 IAM。 */
@Service
public class MemberService {
private static final String GRANT_ROLE_PERMISSION = "merchant:member:grant-role";
private static final Logger log = LoggerFactory.getLogger(MemberService.class);
private final MemberRepository repository;
private final IamRoleMapper roleMapper;
@@ -49,8 +52,9 @@ public class MemberService {
@Transactional
@BusinessAudit(event = "MEMBER_CREATE", resourceType = "MEMBERSHIP", resourceId = "#request.username", description = "新增企业成员")
public MemberResponse create(long tenantId, CreateMemberRequest request) {
public MemberResponse create(long tenantId, CreateMemberRequest request, Set<String> operatorPermissions) {
rejectOwnerMutation(request.memberType());
requireGrantRoleIfChanged(List.of(), request.roleIds(), operatorPermissions);
validateRoles(tenantId, request.roleIds());
validateMemberNo(tenantId, request.memberNo(), null);
long authId = IdWorker.getId();
@@ -84,11 +88,14 @@ public class MemberService {
@Transactional
@BusinessAudit(event = "MEMBER_UPDATE", resourceType = "MEMBERSHIP", resourceId = "#membershipId", description = "编辑企业成员")
public MemberResponse update(long tenantId, Long membershipId, UpdateMemberRequest request) {
public MemberResponse update(long tenantId, Long membershipId, UpdateMemberRequest request,
Set<String> operatorPermissions) {
rejectOwnerMutation(request.memberType());
IamMembership membership = required(tenantId, membershipId);
List<Long> currentRoleIds = repository.findRoleIds(tenantId, membershipId);
requireGrantRoleIfChanged(currentRoleIds, request.roleIds(), operatorPermissions);
validateRoles(tenantId, request.roleIds());
validateMemberNo(tenantId, request.memberNo(), membershipId);
IamMembership membership = required(tenantId, membershipId);
if ("OWNER".equals(membership.getMemberType())) {
throw new BizException(ResultCode.FORBIDDEN, "企业所有者不允许通过成员管理接口编辑");
}
@@ -171,6 +178,13 @@ public class MemberService {
throw new BizException(ResultCode.FORBIDDEN, "禁止分配其他租户、其他应用或已停用角色");
}
}
private void requireGrantRoleIfChanged(List<Long> currentRoleIds, List<Long> requestedRoleIds,
Set<String> operatorPermissions) {
if (!new HashSet<>(currentRoleIds).equals(new HashSet<>(requestedRoleIds))
&& (operatorPermissions == null || !operatorPermissions.contains(GRANT_ROLE_PERMISSION))) {
throw new BizException(ResultCode.FORBIDDEN, "变更成员角色需要 merchant:member:grant-role 权限");
}
}
private void rejectOwnerMutation(String memberType) {
if ("OWNER".equals(memberType)) {
throw new BizException(ResultCode.FORBIDDEN, "不能通过成员管理接口创建或转让企业所有者");
+11
View File
@@ -29,3 +29,14 @@ baiyue:
jwt-secret: ${JWT_SECRET:change-me-to-at-least-32-bytes-long-before-start}
internal-service-token: ${INTERNAL_SERVICE_TOKEN:change-me-to-an-internal-token-at-least-32-bytes-long}
management.endpoints.web.exposure.include: health,info,prometheus
logging:
file:
name: "${LOGGING_FILE_NAME:${LOG_PATH:./logs}/${spring.application.name}.log}"
logback:
rollingpolicy:
file-name-pattern: "${LOGGING_ROLLING_FILE_NAME_PATTERN:${LOG_PATH:./logs}/${spring.application.name}.%d{yyyy-MM-dd}.%i.log.gz}"
max-file-size: "${LOGGING_ROLLING_MAX_FILE_SIZE:100MB}"
max-history: "${LOGGING_ROLLING_MAX_HISTORY:30}"
total-size-cap: "${LOGGING_ROLLING_TOTAL_SIZE_CAP:5GB}"
clean-history-on-start: "${LOGGING_ROLLING_CLEAN_HISTORY_ON_START:false}"