| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486 |
- package com.inspur.customer.service.keycloak;
- import com.alibaba.cola.dto.PageResponse;
- import com.alibaba.cola.dto.Response;
- import com.alibaba.cola.dto.SingleResponse;
- import com.google.common.collect.Lists;
- import com.inspur.customer.client.keycloak.KeycloakService;
- import com.inspur.customer.client.org.SmsbDepartmentUserService;
- import com.inspur.customer.constant.Constant;
- import com.inspur.customer.object.keycloak.KeycloakUserCO;
- import com.inspur.customer.object.keycloak.SwitchDTO;
- import com.inspur.customer.object.keycloak.UsersRoleMappingDTO;
- import com.inspur.customer.object.org.SmsbDepartmentCmd;
- import com.inspur.customer.object.org.SmsbUserAdd;
- import com.inspur.customer.object.wechat.Pair;
- import lombok.extern.slf4j.Slf4j;
- import org.apache.dubbo.config.annotation.DubboReference;
- import org.apache.dubbo.config.annotation.DubboService;
- import org.keycloak.admin.client.resource.GroupResource;
- import org.keycloak.admin.client.resource.GroupsResource;
- import org.keycloak.admin.client.resource.RealmResource;
- import org.keycloak.admin.client.resource.RoleScopeResource;
- import org.keycloak.admin.client.resource.UserResource;
- import org.keycloak.representations.idm.ClientRepresentation;
- import org.keycloak.representations.idm.CredentialRepresentation;
- import org.keycloak.representations.idm.GroupRepresentation;
- import org.keycloak.representations.idm.RoleRepresentation;
- import org.keycloak.representations.idm.UserRepresentation;
- import org.springframework.cache.annotation.CacheEvict;
- import org.springframework.cache.annotation.Cacheable;
- import org.springframework.util.CollectionUtils;
- import org.springframework.util.StringUtils;
- import javax.annotation.Resource;
- import java.time.LocalDateTime;
- import java.util.*;
- import java.util.concurrent.atomic.AtomicReference;
- import java.util.stream.Collectors;
- import java.util.stream.Stream;
- @Slf4j
- @DubboService
- public class KeycloakServiceImpl implements KeycloakService {
- @Resource
- private RealmResource realmResource;
- @DubboReference
- private SmsbDepartmentUserService userService;
- @Override
- @Cacheable(value = "smsb:users")
- public Map<String, String> getUserMap() {
- Map<String, String> userMap = new HashMap<>();
- realmResource.users().list().forEach(user ->{
- if (user.getFirstName() != null && user.getLastName() != null && !"".equals(user.getLastName())) {
- user.setUsername(user.getLastName() + user.getFirstName());
- }
- userMap.put(user.getId(),user.getUsername());
- });
- return userMap;
- }
- @CacheEvict(value = "smsb:users" , allEntries = true)
- public void clearUserMapCache(){
- log.info("users map cache clear:{}",LocalDateTime.now() );
- }
- /**
- * get users in role (xuzhou environment)
- * @param role role
- * @return users
- */
- @Override
- public List<KeycloakUserCO> getUsersInRole(String role) {
- List<KeycloakUserCO> keycloakUserCos = new ArrayList<>();
- realmResource.roles().get(role).getRoleUserMembers().forEach(user -> {
- log.info("name: {}", user.getUsername());
- KeycloakUserCO keycloakUserCo = new KeycloakUserCO();
- keycloakUserCo.setId(user.getId());
- keycloakUserCo.setEmail(user.getEmail());
- Map<String, List<String>> attributes = user.getAttributes();
- if (attributes != null) {
- keycloakUserCo.setPhone(attributes.get("phone"));
- keycloakUserCo.setWechat(attributes.get("wechat"));
- keycloakUserCo.setWechatApplet(attributes.get("wechat-applet-openid"));
- }
- keycloakUserCos.add(keycloakUserCo);
- });
- return keycloakUserCos;
- }
- /**
- * get users by ids
- * according to device's related users is no too much, temporary use that way to get users
- * @deprecated
- * @param userIds ids
- * @return users
- */
- @Override
- public List<KeycloakUserCO> getUsersByIds(List<String> userIds) {
- List<KeycloakUserCO> keycloakUserCos = new ArrayList<>(userIds.size());
- userIds.forEach(id -> {
- UserRepresentation userRepresentation = realmResource.users().get(id).toRepresentation();
- if (userRepresentation != null) {
- KeycloakUserCO keycloakUserCo = new KeycloakUserCO();
- keycloakUserCo.setId(userRepresentation.getId());
- keycloakUserCo.setUsername(userRepresentation.getUsername());
- keycloakUserCo.setEmail(userRepresentation.getEmail());
- Map<String, List<String>> attributes = userRepresentation.getAttributes();
- if (attributes != null) {
- keycloakUserCo.setPhone(attributes.get("phone"));
- keycloakUserCo.setWechat(attributes.get("wechat"));
- keycloakUserCo.setWechatApplet(attributes.get("wechat-applet-openid"));
- }
- keycloakUserCos.add(keycloakUserCo);
- }
- });
- return keycloakUserCos;
- }
- @Override
- public Boolean checkUserRole(String userId, String role) {
- AtomicReference<Boolean> result = new AtomicReference<>(false);
- List<RoleRepresentation> roles = realmResource.users().get(userId).roles().getAll().getRealmMappings();
- log.info("userId:{},roles:{}",userId , roles);
- roles.forEach(n ->{
- if(n.getName().equalsIgnoreCase(role)){
- result.set(true);
- }
- });
- return result.get();
- }
- @Override
- public void updateAttribute(String userId ,String property , String value) {
- KeycloakUserCO userCO = new KeycloakUserCO();
- userCO.setId(userId);
- if(Objects.nonNull(property) && property.equals("wechat")){
- userCO.setWechat(Collections.singletonList(value));
- }else if(Objects.nonNull(property) && property.equals("wechat-applet-openid")){
- userCO.setWechatAppletOpenId(value);
- }
- userService.updateUserAttribute(userCO);
- UserResource user = realmResource.users().get(userId);
- UserRepresentation userRepresentation = user.toRepresentation();
- if (userRepresentation.getAttributes() == null) {
- userRepresentation.setAttributes(new HashMap<>());
- }
- userRepresentation.getAttributes().put(property, Collections.singletonList(value));
- user.update(userRepresentation);
- }
- @Override
- public List<String> getAttrByGroupPath(String groupPath, String key) {
- GroupRepresentation groupRepresentation = realmResource.getGroupByPath(groupPath);
- if (groupRepresentation != null) {
- Map<String, List<String>> attributes = groupRepresentation.getAttributes();
- return attributes != null ? attributes.get(key) : Collections.emptyList();
- }
- return Collections.emptyList();
- }
- @Override
- public List<KeycloakUserCO> getGroupSupervisor(String group) {
- return getUserByRoleAndGroup(group, "ROLE_OPERATION_SUPERVISOR");
- }
- @Override
- public List<KeycloakUserCO> getSuperAdmin() {
- return realmResource.roles().get("ROLE_SUPER_ADMIN").getRoleUserMembers()
- .stream()
- .map(this::transfer)
- .collect(Collectors.toList());
- }
- @Override
- public List<KeycloakUserCO> getAllRoleAdmin() {
- return realmResource.roles().get("ROLE_ADMIN").getRoleUserMembers()
- .stream()
- .map(this::transfer)
- .collect(Collectors.toList());
- }
- @Override
- public List<KeycloakUserCO> getAllRoleOperationSupervisor() {
- return realmResource.roles().get("ROLE_OPERATION_SUPERVISOR").getRoleUserMembers()
- .stream()
- .map(this::transfer)
- .collect(Collectors.toList());
- }
- @Override
- public List<KeycloakUserCO> getGroupAdmin(String group) {
- return getUserByRoleAndGroup(group, "ROLE_ADMIN");
- }
- @Override
- public String getSingleAttrByGroupPath(String group, String key) {
- List<String> list = getAttrByGroupPath(group, key);
- if (CollectionUtils.isEmpty(list)) {
- return null;
- } else {
- return list.get(0);
- }
- }
- @Override
- public List<KeycloakUserCO> searchUserByAttrEntry(List<Pair> pairList) {
- String search = pairList.stream()
- .filter(t -> Objects.nonNull(t) && Objects.nonNull(t.getKey()) && Objects.nonNull(t.getValue()))
- .map(t -> t.getKey() + ":" + t.getValue())
- .collect(Collectors.joining(" "));
- return realmResource.users().searchByAttributes(search).stream().map(this::transfer).collect(Collectors.toList());
- }
- @Override
- public List<String> getUserGroupPathList(String userId) {
- return realmResource.users().get(userId).groups().stream().map(GroupRepresentation::getPath).collect(Collectors.toList());
- }
- @Override
- public List<String> getUserRealmRoles(String userId) {
- return realmResource
- .users()
- .get(userId)
- .roles()
- .getAll()
- .getRealmMappings()
- .stream()
- .map(RoleRepresentation::getName)
- .collect(Collectors.toList());
- }
- @Override
- public Map<String, List<String>> getUserClientRoles(String userId) {
- Map<String, List<String>> resultMap = new HashMap<>();
- List<ClientRepresentation> clientList = realmResource.clients().findAll();
- for (ClientRepresentation clientRepresentation : clientList) {
- String clientId = clientRepresentation.getClientId();
- List<RoleRepresentation> roleList = realmResource.users().get(userId).roles().clientLevel(clientRepresentation.getId()).listEffective();
- if (!roleList.isEmpty()) {
- resultMap.put(clientId, roleList.stream().map(RoleRepresentation::getName).collect(Collectors.toList()));
- }
- }
- return resultMap;
- }
- @Override
- public void changePassword(String userId, String newPassword) {
- CredentialRepresentation cr = new CredentialRepresentation();
- cr.setType(CredentialRepresentation.PASSWORD);
- cr.setValue(newPassword);
- realmResource.users().get(userId).resetPassword(cr);
- }
- private List<KeycloakUserCO> getUserByRoleAndGroup(String group, String role) {
- if (!StringUtils.hasText(group) || !StringUtils.hasText(role)) {
- return Collections.emptyList();
- }
- List<UserRepresentation> members = realmResource.groups().group(realmResource.getGroupByPath(group).getId()).members();
- Set<String> set = realmResource.roles().get(role).getRoleUserMembers().stream().map(UserRepresentation::getId).collect(Collectors.toSet());
- return members.stream().filter(t -> set.contains(t.getId())).map(this::transfer).collect(Collectors.toList());
- }
- private KeycloakUserCO transfer(UserRepresentation userRepresentation) {
- if (userRepresentation == null) {
- return null;
- }
- KeycloakUserCO keycloakUserCo = new KeycloakUserCO();
- keycloakUserCo.setId(userRepresentation.getId());
- keycloakUserCo.setUsername(userRepresentation.getUsername());
- keycloakUserCo.setEmail(userRepresentation.getEmail());
- Map<String, List<String>> attributes = userRepresentation.getAttributes();
- if (attributes != null) {
- keycloakUserCo.setPhone(attributes.get("phone"));
- keycloakUserCo.setWechat(attributes.get("wechat"));
- keycloakUserCo.setWechatApplet(attributes.get("wechat-applet-openid"));
- }
- return keycloakUserCo;
- }
- @Override
- public Response addKeycloakGroup(String id , GroupRepresentation groupRepresentation) {
- return SingleResponse.of(realmResource.groups().group(id).subGroup(groupRepresentation).getDate());
- }
- @Override
- public Response updateKeycloakGroup(String id, GroupRepresentation groupRepresentation) {
- realmResource.groups().group(id).update(groupRepresentation);
- return SingleResponse.buildSuccess();
- }
- @Override
- public Response removeGroup(String id) {
- realmResource.groups().group(id).remove();
- return SingleResponse.buildSuccess();
- }
- @Override
- public SingleResponse addKeyClaokUser(SmsbUserAdd user) {
- UserRepresentation userRepresentation = new UserRepresentation();
- userRepresentation.setUsername(user.getUsername());
- userRepresentation.setGroups(Collections.singletonList(user.getTenant()));
- userRepresentation.setEnabled(Boolean.TRUE);
- userRepresentation.setCredentials(user.getCredentials());
- userRepresentation.setFirstName(user.getName());
- if(Objects.nonNull(getUserIdByName(userRepresentation.getUsername()))){
- return SingleResponse.buildFailure("400","该用户名已存在!");
- }
- javax.ws.rs.core.Response response = realmResource.users().create(userRepresentation);
- log.info("create keycloak user response status:{}", response.getStatus());
- Optional.ofNullable(response.getStatusInfo()).ifPresent(t -> log.info(t.getReasonPhrase()));
- int status = response.getStatus();
- if(status != 201){
- return SingleResponse.buildFailure("400","账号创建失败!");
- }
- return SingleResponse.of(getUserIdByName(userRepresentation.getUsername()));
- }
- /**
- * 通过用户名获取用户id
- *
- * @param username
- * @return
- */
- private String getUserIdByName(String username){
- Optional<String> optional = realmResource.users().search(username)
- .stream().filter(user -> user.getUsername().equals(username))
- .map(UserRepresentation::getId)
- .findFirst();
- return optional.isEmpty()?null:optional.get();
- }
- @Override
- @CacheEvict(value = "smsb:users" , allEntries = true)
- public Response updateUser(String userId, Object representation, Integer operateType) {
- UserResource userResource = realmResource.users().get(userId);
- UserRepresentation user = userResource.toRepresentation();
- switch (operateType) {
- case Constant.ENABLE:
- SwitchDTO switchDTO = (SwitchDTO) representation;
- user.setEnabled(switchDTO.getEnabled());
- break;
- case Constant.RESET_PASSWORD:
- CredentialRepresentation credential = (CredentialRepresentation) representation;
- user.setCredentials(Stream.of(credential).collect(Collectors.toList()));
- break;
- case Constant.RESET_ATTRIBUTE:
- UserRepresentation userRepresentation = (UserRepresentation) representation;
- user.setEmail(Optional.ofNullable(userRepresentation.getEmail()).orElse(null));
- user.setFirstName(userRepresentation.getFirstName());
- user.setAttributes(userRepresentation.getAttributes());
- break;
- case Constant.UPDATE_USER_FIRSTNAME:
- user.setFirstName((String) representation);
- break;
- default:
- break;
- }
- userResource.update(user);
- return SingleResponse.buildSuccess();
- }
- @Override
- @CacheEvict(value = "smsb:users" , allEntries = true)
- public Response removeUser(String userId) {
- realmResource.users().get(userId).remove();
- return Response.buildSuccess();
- }
- @Override
- public Response regrouping(String userId, String groupId) {
- UserResource userResource = realmResource.users().get(userId);
- List<GroupRepresentation> groups = userResource.groups();
- // 移除
- groups.forEach(groupRepresentation-> userResource.leaveGroup(groupRepresentation.getId()));
- // 添加
- GroupsResource initGroups = realmResource.groups();
- List<String> targetGroups = Arrays.stream(initGroups.group(groupId).toRepresentation().getPath().split("/")).filter(Objects::nonNull).collect(Collectors.toList());
- getGroupId(targetGroups ,initGroups.groups()).forEach(userResource::joinGroup);
- return SingleResponse.buildSuccess();
- }
- private List<String> getGroupId(List<String> targetGroups , List<GroupRepresentation> groups){
- List<String> groupIds = Lists.newArrayList();
- GroupRepresentation group = groups.stream().filter(ele -> targetGroups.contains(ele.getName())).findFirst().get();
- groupIds.add(group.getId());
- if(!CollectionUtils.isEmpty(group.getSubGroups())){
- groupIds.addAll(getGroupId(targetGroups , group.getSubGroups()));
- }
- return groupIds;
- }
- public List<RoleRepresentation> getRoles() {
- return realmResource.roles().list();
- }
- public List<RoleRepresentation> getUserRoles(String userId) {
- return realmResource.users().get(userId).roles().getAll().getRealmMappings();
- }
- @Override
- public Response roleMapping(UsersRoleMappingDTO usersRoleMappingDTO) {
- RoleScopeResource roleScopeResource = realmResource.users().get(usersRoleMappingDTO.getUserId()).roles().realmLevel();
- roleScopeResource.add(Optional.ofNullable(usersRoleMappingDTO.getAddRoleList()).orElse(Lists.newArrayList()));
- roleScopeResource.remove(Optional.ofNullable(usersRoleMappingDTO.getRemoveRoleList()).orElse(Lists.newArrayList()));
- return SingleResponse.buildSuccess();
- }
- @Override
- public Response queryUserCredentials(String userId) {
- return SingleResponse.of(realmResource.users().get(userId).credentials());
- }
- @Override
- public Response removeUserCredentials(String userId , String credentialId) {
- realmResource.users().get(userId).removeCredential(credentialId);
- return SingleResponse.buildSuccess();
- }
- @Override
- public Response addKeycloakTenant(GroupRepresentation groupRepresentation) {
- return SingleResponse.of(realmResource.groups().add(groupRepresentation).getDate());
- }
- @Override
- public Boolean isExitTargetRole(String userId ,String role) {
- List<String> roleList = realmResource.users().get(userId).roles().realmLevel().listAll()
- .stream().map(RoleRepresentation::getName).collect(Collectors.toList());
- return roleList.contains(role);
- }
- @Override
- @Cacheable(value = "msr:user:tenant", key = "#userId")
- public String queryUserTenant(String userId) {
- List<GroupRepresentation> groupList = realmResource.users().get(userId).groups()
- .stream()
- .sorted(Comparator.comparing(i -> i.getPath().length()))
- .collect(Collectors.toList());
- return CollectionUtils.isEmpty(groupList) ? "" : groupList.stream().findFirst().get().getPath();
- }
- @Override
- public Boolean addAttributesByUserId(String userId, String key, List<String> values) {
- UserResource userResource = realmResource.users().get(userId);
- UserRepresentation user = userResource.toRepresentation();
- Map<String, List<String>> attributes = Optional.ofNullable(user.getAttributes()).orElse(new HashMap<>());
- attributes.put(key ,values);
- user.setAttributes(attributes);
- userResource.update(user);
- return Boolean.TRUE;
- }
- @Override
- public PageResponse<UserRepresentation> getUserListByIds(SmsbDepartmentCmd departmentCmd , List<String> userId) {
- if(CollectionUtils.isEmpty(userId)){
- GroupResource groupResource = realmResource.groups()
- .group(realmResource.getGroupByPath(departmentCmd.getTenant()).getId());
- log.info("查询分页参数:first:{},max:{}",departmentCmd.getOffset() ,departmentCmd.getPageSize());
- return PageResponse.of(
- groupResource.members(departmentCmd.getOffset() ,departmentCmd.getPageSize())
- , groupResource.members().size() ,departmentCmd.getPageSize() ,departmentCmd.getPageIndex());
- }else{
- List<UserRepresentation> userRepresentations = realmResource.groups()
- .group(realmResource.getGroupByPath(departmentCmd.getTenant()).getId())
- .members()
- .stream()
- .filter(i -> userId.contains(i.getId()))
- .collect(Collectors.toList());
- return PageResponse.of(userRepresentations ,0 ,0,0);
- }
- }
- @Override
- public List<String> queryWechatByRole(String role) {
- List<String> openIds = Lists.newArrayList();
- realmResource.roles().get(role).getRoleUserMembers().forEach(user->{
- Map<String, List<String>> attributes = user.getAttributes();
- if (attributes != null && attributes.get("wechat") != null) {
- openIds.addAll(attributes.get("wechat"));
- }
- });
- return openIds;
- }
- }
|