|
|
@@ -0,0 +1,295 @@
|
|
|
+package com.malk.benteler.service;
|
|
|
+
|
|
|
+import com.malk.benteler.dto.EiamBatchItemResult;
|
|
|
+import com.malk.benteler.dto.EiamBatchOperation;
|
|
|
+import com.malk.benteler.dto.EiamBatchResult;
|
|
|
+import com.malk.benteler.dto.EiamBatchStage;
|
|
|
+import com.malk.benteler.dto.EiamCreateUserItem;
|
|
|
+import com.malk.benteler.dto.EiamDeleteUserItem;
|
|
|
+import com.malk.benteler.dto.EiamUpdateUserItem;
|
|
|
+import com.malk.server.common.McException;
|
|
|
+import com.malk.server.eiam.EiamApiResponse;
|
|
|
+import com.malk.server.eiam.EiamConf;
|
|
|
+import com.malk.server.eiam.EiamCustomField;
|
|
|
+import com.malk.service.eiam.EiamClient_User;
|
|
|
+import com.malk.service.eiam.EiamService;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 本特勒 EIAM 批量业务编排。
|
|
|
+ */
|
|
|
+@Service
|
|
|
+public class EiamLocalService {
|
|
|
+
|
|
|
+ private final EiamService eiamService;
|
|
|
+ private final EiamClient_User eiamClientUser;
|
|
|
+ private final EiamConf eiamConf;
|
|
|
+
|
|
|
+ public EiamLocalService(EiamService eiamService, EiamClient_User eiamClientUser,
|
|
|
+ EiamConf eiamConf) {
|
|
|
+ this.eiamService = eiamService;
|
|
|
+ this.eiamClientUser = eiamClientUser;
|
|
|
+ this.eiamConf = eiamConf;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 批量创建用户,单条失败不中断后续条目。
|
|
|
+ *
|
|
|
+ * @param items 创建条目
|
|
|
+ * @return 批量结果
|
|
|
+ */
|
|
|
+ public EiamBatchResult batchCreate(List<EiamCreateUserItem> items) {
|
|
|
+ validateBatch(items);
|
|
|
+ String token = eiamService.getAccessToken();
|
|
|
+ List<EiamBatchItemResult> results = new ArrayList<>();
|
|
|
+ for (int index = 0; index < items.size(); index++) {
|
|
|
+ results.add(createOne(token, items.get(index), index));
|
|
|
+ }
|
|
|
+ return EiamBatchResult.of(EiamBatchOperation.CREATE, results);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 批量更新用户,支持账户属性和主组织变更。
|
|
|
+ *
|
|
|
+ * @param items 更新条目
|
|
|
+ * @return 批量结果
|
|
|
+ */
|
|
|
+ public EiamBatchResult batchUpdate(List<EiamUpdateUserItem> items) {
|
|
|
+ validateBatch(items);
|
|
|
+ String token = eiamService.getAccessToken();
|
|
|
+ List<EiamBatchItemResult> results = new ArrayList<>();
|
|
|
+ for (int index = 0; index < items.size(); index++) {
|
|
|
+ results.add(updateOne(token, items.get(index), index));
|
|
|
+ }
|
|
|
+ return EiamBatchResult.of(EiamBatchOperation.UPDATE, results);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 批量删除用户,单条失败不中断后续条目。
|
|
|
+ *
|
|
|
+ * @param items 删除条目
|
|
|
+ * @return 批量结果
|
|
|
+ */
|
|
|
+ public EiamBatchResult batchDelete(List<EiamDeleteUserItem> items) {
|
|
|
+ validateBatch(items);
|
|
|
+ String token = eiamService.getAccessToken();
|
|
|
+ List<EiamBatchItemResult> results = new ArrayList<>();
|
|
|
+ for (int index = 0; index < items.size(); index++) {
|
|
|
+ results.add(deleteOne(token, items.get(index), index));
|
|
|
+ }
|
|
|
+ return EiamBatchResult.of(EiamBatchOperation.DELETE, results);
|
|
|
+ }
|
|
|
+
|
|
|
+ private EiamBatchItemResult createOne(String token, EiamCreateUserItem item, int index) {
|
|
|
+ EiamBatchStage stage = EiamBatchStage.VALIDATE;
|
|
|
+ try {
|
|
|
+ validateCreateItem(item);
|
|
|
+ stage = EiamBatchStage.CREATE_USER;
|
|
|
+ EiamApiResponse response = eiamClientUser.createUser(token, eiamConf.getInstanceId(),
|
|
|
+ eiamConf.getApplicationId(), item.getUsername(),
|
|
|
+ item.getPrimaryOrganizationalUnitId(), createBody(item));
|
|
|
+ assertEiamSuccess(response);
|
|
|
+ if (StringUtils.isBlank(response.getUserId())) {
|
|
|
+ throw new McException("EIAM_EMPTY_USER_ID", "CreateUser 成功响应缺少 userId");
|
|
|
+ }
|
|
|
+ return success(index, item.getFormInstanceId(), item.getUsername(), response.getUserId());
|
|
|
+ } catch (RuntimeException ex) {
|
|
|
+ return failure(index, item == null ? null : item.getFormInstanceId(),
|
|
|
+ item == null ? null : item.getUsername(), null, stage, ex, false);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private EiamBatchItemResult updateOne(String token, EiamUpdateUserItem item, int index) {
|
|
|
+ EiamBatchStage stage = EiamBatchStage.VALIDATE;
|
|
|
+ boolean patchCompleted = false;
|
|
|
+ try {
|
|
|
+ validateUpdateItem(item);
|
|
|
+ Map<String, Object> patchBody = updateBody(item);
|
|
|
+ if (!patchBody.isEmpty()) {
|
|
|
+ stage = EiamBatchStage.PATCH_USER;
|
|
|
+ assertEiamSuccess(eiamClientUser.patchUser(token, eiamConf.getInstanceId(),
|
|
|
+ eiamConf.getApplicationId(), item.getUserId(), patchBody));
|
|
|
+ patchCompleted = true;
|
|
|
+ }
|
|
|
+ if (StringUtils.isNotBlank(item.getPrimaryOrganizationalUnitId())) {
|
|
|
+ stage = EiamBatchStage.SET_PRIMARY_ORG;
|
|
|
+ assertEiamSuccess(eiamClientUser.setUserPrimaryOrganizationalUnit(token,
|
|
|
+ eiamConf.getInstanceId(), eiamConf.getApplicationId(), item.getUserId(),
|
|
|
+ item.getPrimaryOrganizationalUnitId()));
|
|
|
+ }
|
|
|
+ return success(index, item.getFormInstanceId(), userKey(item), item.getUserId());
|
|
|
+ } catch (RuntimeException ex) {
|
|
|
+ return failure(index, item == null ? null : item.getFormInstanceId(),
|
|
|
+ item == null ? null : userKey(item), item == null ? null : item.getUserId(),
|
|
|
+ stage, ex, patchCompleted && stage == EiamBatchStage.SET_PRIMARY_ORG);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private EiamBatchItemResult deleteOne(String token, EiamDeleteUserItem item, int index) {
|
|
|
+ EiamBatchStage stage = EiamBatchStage.VALIDATE;
|
|
|
+ try {
|
|
|
+ validateFormInstanceId(item == null ? null : item.getFormInstanceId());
|
|
|
+ if (item == null || StringUtils.isBlank(item.getUserId())) {
|
|
|
+ throw new McException("EIAM_ITEM_INVALID", "userId 不能为空");
|
|
|
+ }
|
|
|
+ stage = EiamBatchStage.DELETE_USER;
|
|
|
+ assertEiamSuccess(eiamClientUser.deleteUser(token, eiamConf.getInstanceId(),
|
|
|
+ eiamConf.getApplicationId(), item.getUserId()));
|
|
|
+ return success(index, item.getFormInstanceId(), deleteUserKey(item), item.getUserId());
|
|
|
+ } catch (RuntimeException ex) {
|
|
|
+ return failure(index, item == null ? null : item.getFormInstanceId(),
|
|
|
+ item == null ? null : deleteUserKey(item), item == null ? null : item.getUserId(),
|
|
|
+ stage, ex, false);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, Object> createBody(EiamCreateUserItem item) {
|
|
|
+ Map<String, Object> body = new HashMap<>();
|
|
|
+ putIfNotBlank(body, "displayName", item.getDisplayName());
|
|
|
+ String phoneNumber = StringUtils.defaultIfBlank(item.getPhoneNumber(), item.getUsername());
|
|
|
+ putIfNotBlank(body, "phoneNumber", phoneNumber);
|
|
|
+ if (StringUtils.isNotBlank(phoneNumber)) {
|
|
|
+ body.put("phoneRegion", StringUtils.defaultIfBlank(item.getPhoneRegion(), "86"));
|
|
|
+ body.put("phoneNumberVerified", true);
|
|
|
+ }
|
|
|
+ putIfNotBlank(body, "email", item.getEmail());
|
|
|
+ if (StringUtils.isNotBlank(item.getEmail())) {
|
|
|
+ body.put("emailVerified", false);
|
|
|
+ }
|
|
|
+ putIfNotBlank(body, "description", item.getDescription());
|
|
|
+ if (item.getCustomFields() != null) {
|
|
|
+ body.put("customFields", item.getCustomFields());
|
|
|
+ }
|
|
|
+ Map<String, Object> passwordConfig = new HashMap<>();
|
|
|
+ passwordConfig.put("passwordInitializationPolicyPriority", "custom");
|
|
|
+ passwordConfig.put("passwordForcedUpdateStatus", "enabled");
|
|
|
+ // prd 客户不接收初始密码通知,用户首次登录时通过重置密码流程完成密码设置。
|
|
|
+ passwordConfig.put("passwordInitializationType", "random");
|
|
|
+ body.put("passwordInitializationConfig", passwordConfig);
|
|
|
+ return body;
|
|
|
+ }
|
|
|
+
|
|
|
+ private Map<String, Object> updateBody(EiamUpdateUserItem item) {
|
|
|
+ Map<String, Object> body = new HashMap<>();
|
|
|
+ putIfNotBlank(body, "username", item.getUsername());
|
|
|
+ putIfNotBlank(body, "displayName", item.getDisplayName());
|
|
|
+ putIfNotBlank(body, "phoneNumber", item.getPhoneNumber());
|
|
|
+ if (StringUtils.isNotBlank(item.getPhoneNumber())) {
|
|
|
+ body.put("phoneRegion", StringUtils.defaultIfBlank(item.getPhoneRegion(), "86"));
|
|
|
+ body.put("phoneNumberVerified", true);
|
|
|
+ }
|
|
|
+ putIfNotBlank(body, "email", item.getEmail());
|
|
|
+ if (StringUtils.isNotBlank(item.getEmail())) {
|
|
|
+ body.put("emailVerified", false);
|
|
|
+ }
|
|
|
+ if (item.getCustomFields() != null) {
|
|
|
+ body.put("customFields", item.getCustomFields());
|
|
|
+ }
|
|
|
+ return body;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void validateCreateItem(EiamCreateUserItem item) {
|
|
|
+ validateFormInstanceId(item == null ? null : item.getFormInstanceId());
|
|
|
+ if (item == null || StringUtils.isBlank(item.getUsername())) {
|
|
|
+ throw new McException("EIAM_ITEM_INVALID", "username 不能为空");
|
|
|
+ }
|
|
|
+ if (StringUtils.isBlank(item.getDisplayName())) {
|
|
|
+ throw new McException("EIAM_ITEM_INVALID", "displayName 不能为空");
|
|
|
+ }
|
|
|
+ if (StringUtils.isBlank(item.getPrimaryOrganizationalUnitId())) {
|
|
|
+ throw new McException("EIAM_ITEM_INVALID", "primaryOrganizationalUnitId 不能为空");
|
|
|
+ }
|
|
|
+ // prd 新增账号必须完整携带宜搭主表和人员子表中的 EIAM 自定义字段。
|
|
|
+ validateRequiredCustomField(item, "department", "iDaaS 部门名称");
|
|
|
+ validateRequiredCustomField(item, "company_name", "所属公司");
|
|
|
+ validateRequiredCustomField(item, "company_code", "公司代码");
|
|
|
+ validateRequiredCustomField(item, "job_title", "职位");
|
|
|
+ }
|
|
|
+
|
|
|
+ private void validateRequiredCustomField(EiamCreateUserItem item, String fieldName,
|
|
|
+ String displayName) {
|
|
|
+ if (item.getCustomFields() != null) {
|
|
|
+ for (EiamCustomField field : item.getCustomFields()) {
|
|
|
+ if (field != null && StringUtils.equals(fieldName, field.getFieldName())
|
|
|
+ && StringUtils.isNotBlank(field.getFieldValue())) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ throw new McException("EIAM_ITEM_INVALID", displayName + " 不能为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ private void validateUpdateItem(EiamUpdateUserItem item) {
|
|
|
+ validateFormInstanceId(item == null ? null : item.getFormInstanceId());
|
|
|
+ if (item == null || StringUtils.isBlank(item.getUserId())) {
|
|
|
+ throw new McException("EIAM_ITEM_INVALID", "userId 不能为空");
|
|
|
+ }
|
|
|
+ if (updateBody(item).isEmpty() && StringUtils.isBlank(item.getPrimaryOrganizationalUnitId())) {
|
|
|
+ throw new McException("EIAM_ITEM_INVALID", "更新内容不能为空");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void validateBatch(List<?> items) {
|
|
|
+ if (items == null || items.isEmpty()) {
|
|
|
+ throw new McException("EIAM_BATCH_EMPTY", "items 不能为空");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void validateFormInstanceId(String formInstanceId) {
|
|
|
+ if (StringUtils.isBlank(formInstanceId)) {
|
|
|
+ throw new McException("EIAM_ITEM_INVALID", "formInstanceId 不能为空");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void assertEiamSuccess(EiamApiResponse response) {
|
|
|
+ if (response == null) {
|
|
|
+ throw new McException("EIAM_EMPTY_RESPONSE", "EIAM 响应为空");
|
|
|
+ }
|
|
|
+ String code = StringUtils.defaultIfBlank(response.getCode(), response.getError());
|
|
|
+ if (StringUtils.isBlank(code)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ String message = StringUtils.defaultIfBlank(response.getMessage(), response.getErrorDescription());
|
|
|
+ throw new McException(code, StringUtils.defaultIfBlank(message, "EIAM 调用失败"));
|
|
|
+ }
|
|
|
+
|
|
|
+ private EiamBatchItemResult success(int index, String formInstanceId, String userKey,
|
|
|
+ String userId) {
|
|
|
+ return EiamBatchItemResult.builder().index(index).formInstanceId(formInstanceId)
|
|
|
+ .userKey(userKey).userId(userId).success(true).stage(EiamBatchStage.COMPLETED)
|
|
|
+ .code("SUCCESS").message("执行成功").build();
|
|
|
+ }
|
|
|
+
|
|
|
+ private EiamBatchItemResult failure(int index, String formInstanceId, String userKey,
|
|
|
+ String userId, EiamBatchStage stage, RuntimeException ex,
|
|
|
+ boolean partialUpdate) {
|
|
|
+ String code = ex instanceof McException ? ((McException) ex).getCode() : "EIAM_CALL_ERROR";
|
|
|
+ String message = StringUtils.defaultIfBlank(ex.getMessage(), "EIAM 调用失败");
|
|
|
+ if (partialUpdate) {
|
|
|
+ message = "账户属性可能已更新;" + message;
|
|
|
+ }
|
|
|
+ return EiamBatchItemResult.builder().index(index).formInstanceId(formInstanceId)
|
|
|
+ .userKey(userKey).userId(userId).success(false).stage(stage)
|
|
|
+ .code(code).message(message).build();
|
|
|
+ }
|
|
|
+
|
|
|
+ private void putIfNotBlank(Map<String, Object> target, String key, String value) {
|
|
|
+ if (StringUtils.isNotBlank(value)) {
|
|
|
+ target.put(key, value);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private String userKey(EiamUpdateUserItem item) {
|
|
|
+ return StringUtils.defaultIfBlank(item.getUsername(), item.getUserId());
|
|
|
+ }
|
|
|
+
|
|
|
+ private String deleteUserKey(EiamDeleteUserItem item) {
|
|
|
+ return StringUtils.defaultIfBlank(item.getUsername(), item.getUserId());
|
|
|
+ }
|
|
|
+}
|