package com.crm.auth.security;
import com.crm.base.security.DataVisibility;
import com.crm.base.security.DataVisibilityContext;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* 权限解析结果:一次 resolve 拿齐一个用户的三份授权事实(ADR-0011)。
*
*
不可变。纯取值对象——装载 {@link DataVisibilityContext} 是请求生命周期所有者
* (JWT 过滤器)的职责,本对象不产生副作用。
*
*
* - {@link #getVisibility()} 数据可见性(部门集合 + 档位 + 子树展开)
* - {@link #getPermCodes()} 权限码并集(停用权限点已全局断路,不进并集)
* - {@link #getRoleCodes()} 角色编码集合
*
*/
public final class PermissionGrant {
/** Spring Security 角色 authority 前缀(hasRole('X') 实际匹配 ROLE_X) */
private static final String ROLE_PREFIX = "ROLE_";
private final DataVisibility visibility;
private final Set permCodes;
private final Set roleCodes;
public PermissionGrant(DataVisibility visibility, Set permCodes, Set roleCodes) {
this.visibility = visibility;
this.permCodes = permCodes == null ? Set.of() : Set.copyOf(permCodes);
this.roleCodes = roleCodes == null ? Set.of() : Set.copyOf(roleCodes);
}
public DataVisibility getVisibility() {
return visibility;
}
/** 权限码并集:button 节点 perms 的去重集合,已排除停用权限点 */
public Set getPermCodes() {
return permCodes;
}
/** 角色编码集合(原样,不带 ROLE_ 前缀约定) */
public Set getRoleCodes() {
return roleCodes;
}
/**
* 合成 Spring Security authorities:权限码原样注入;角色编码幂等归一到 ROLE_ 前缀
* (已带前缀的不重复加),使 hasAuthority / hasRole 各自按约定匹配。
* 前缀约定由本模块保证,调用方与 DB 数据无需理解它。
*/
public List asAuthorities() {
List authorities = new ArrayList<>(permCodes.size() + roleCodes.size());
permCodes.forEach(perm -> authorities.add(new SimpleGrantedAuthority(perm)));
roleCodes.forEach(role -> authorities.add(new SimpleGrantedAuthority(normalizeRole(role))));
return List.copyOf(authorities);
}
private static String normalizeRole(String roleCode) {
return roleCode.startsWith(ROLE_PREFIX) ? roleCode : ROLE_PREFIX + roleCode;
}
}