This commit is contained in:
wujinliang
2026-08-27 21:48:47 +08:00
parent daf0ee2acd
commit 9d54c57b7c
38 changed files with 432 additions and 37 deletions
@@ -41,7 +41,13 @@ public class NotificationRecipientResolver {
if (user != null && "ACTIVE".equals(user.getStatus())) unique.put(item.getId(), new ResolvedRecipient(
item.getTenantId(), item.getId(), item.getUserId(), user.getDisplayName(), item.getTenantId() == 0 ? "PLATFORM" : "MERCHANT"));
});
if (unique.isEmpty()) fail("NOTIFICATION_RECIPIENT_EMPTY");
if (unique.isEmpty()) {
if (request.recipientType() == com.baiyue.iam.notification.dto.NotificationDtos.RecipientType.TENANT_ROLE
|| request.recipientType() == com.baiyue.iam.notification.dto.NotificationDtos.RecipientType.PLATFORM_ROLE) {
fail("该角色下暂无可接收消息的有效用户,请先为角色分配启用中的成员");
}
fail("未找到可接收消息的有效成员,请检查用户 ID 和目标企业");
}
return List.copyOf(unique.values());
}
@@ -49,7 +55,7 @@ public class NotificationRecipientResolver {
var role = roles.selectOne(new LambdaQueryWrapper<com.baiyue.iam.entity.IamRole>()
.eq(com.baiyue.iam.entity.IamRole::getTenantId, request.tenantId())
.eq(com.baiyue.iam.entity.IamRole::getRoleCode, request.roleCode()).eq(com.baiyue.iam.entity.IamRole::getStatus,"ACTIVE").last("LIMIT 1"));
if (role == null) fail("NOTIFICATION_RECIPIENT_FORBIDDEN");
if (role == null) fail("角色编码不存在,请检查角色编码是否正确");
List<Long> ids = membershipRoles.selectList(new LambdaQueryWrapper<com.baiyue.iam.entity.IamMembershipRole>()
.eq(com.baiyue.iam.entity.IamMembershipRole::getTenantId,request.tenantId())
.eq(com.baiyue.iam.entity.IamMembershipRole::getRoleId,role.getId())).stream()
@@ -29,7 +29,7 @@ public class RbacRepository {
public IamRole findRole(Long id, long tenantId, String appCode) {
return roleMapper.selectOne(new LambdaQueryWrapper<IamRole>()
.eq(IamRole::getId, id).eq(IamRole::getTenantId, tenantId)
.eq(IamRole::getId, id).in(IamRole::getTenantId, List.of(0L, tenantId))
.eq(IamRole::getAppCode, appCode));
}
@@ -80,7 +80,7 @@ public class RbacRepository {
public List<IamRole> findRoles(long tenantId, String appCode) {
return roleMapper.selectList(new LambdaQueryWrapper<IamRole>()
.eq(IamRole::getTenantId, tenantId).eq(IamRole::getAppCode, appCode)
.in(IamRole::getTenantId, List.of(0L, tenantId)).eq(IamRole::getAppCode, appCode)
.orderByAsc(IamRole::getRoleCode));
}
@@ -109,7 +109,7 @@ public class RbacRepository {
public Set<Long> findRolePermissionIds(long tenantId, Long roleId) {
List<IamRolePermission> rows = rolePermissionMapper.selectList(
new LambdaQueryWrapper<IamRolePermission>()
.eq(IamRolePermission::getTenantId, tenantId)
.in(IamRolePermission::getTenantId, List.of(0L, tenantId))
.eq(IamRolePermission::getRoleId, roleId)
.orderByAsc(IamRolePermission::getPermissionId));
Set<Long> result = new LinkedHashSet<>();
@@ -64,7 +64,8 @@ public class MemberService {
List<Long> roleIds = repository.findRoleIds(tenantId, membership.getId());
List<String> roleNames = roleIds.stream()
.map(roleMapper::selectById)
.filter(role -> role != null && Long.valueOf(tenantId).equals(role.getTenantId()))
.filter(role -> role != null && "MERCHANT".equals(role.getAppCode())
&& (Long.valueOf(tenantId).equals(role.getTenantId()) || Long.valueOf(0L).equals(role.getTenantId())))
.map(IamRole::getRoleName)
.toList();
return new PlatformCustomerMemberDtos.MemberResponse(membership.getId(), user.getId(),
@@ -85,3 +85,10 @@ INSERT IGNORE INTO iam_role_permission (tenant_id, role_id, permission_id, creat
SELECT 0, r.id, p.id, CURRENT_TIMESTAMP(3)
FROM iam_permission p JOIN iam_role r ON r.tenant_id=0 AND r.app_code='PLATFORM' AND r.status='ACTIVE'
WHERE p.tenant_id=0 AND p.permission_code LIKE 'platform:notification%' AND r.role_code='PLATFORM_ADMIN';
-- All active platform employee roles can receive and read their own inbox messages.
INSERT IGNORE INTO iam_role_permission (tenant_id, role_id, permission_id, created_at)
SELECT 0, r.id, p.id, CURRENT_TIMESTAMP(3)
FROM iam_permission p JOIN iam_role r ON r.tenant_id=0 AND r.app_code='PLATFORM' AND r.status='ACTIVE'
WHERE p.tenant_id=0
AND p.permission_code IN ('platform:notification:view','platform:notification:read','platform:notification:read-all');
@@ -145,7 +145,7 @@ components:
tenantId: {type: integer, format: int64, minimum: 0}
templateCode: {type: string, maxLength: 64}
recipientType: {type: string, enum: [USER, MEMBERSHIP, TENANT_ROLE, TENANT_ALL, PLATFORM_ROLE]}
recipientIds: {type: array, minItems: 1, maxItems: 1000, items: {type: integer, format: int64}, description: Required for USER or MEMBERSHIP; forbidden for role/all recipient types.}
recipientIds: {type: array, minItems: 1, maxItems: 1000, items: {type: integer, format: int64}, description: Required for USER or MEMBERSHIP; forbidden for role/all recipient types. For a specified enterprise member, pass the user's ID and use USER; membership IDs are reserved for explicit membership-level calls.}
roleCode: {type: string, minLength: 1, maxLength: 64, description: Required for TENANT_ROLE or PLATFORM_ROLE; forbidden otherwise.}
variables: {type: object, maxProperties: 32, additionalProperties: {type: string, maxLength: 2000}}
scheduledAt: {type: string, format: date-time, nullable: true}