use of eu.bcvsolutions.idm.acc.domain.SynchronizationContext in project CzechIdMng by bcvsolutions.
the class TreeSynchronizationExecutor method process.
@Override
public AbstractSysSyncConfigDto process(UUID synchronizationConfigId) {
// Clear cache
cacheManager.evictCache(CACHE_NAME);
// Validate and create basic context
SynchronizationContext context = this.validate(synchronizationConfigId);
AbstractSysSyncConfigDto config = context.getConfig();
SysSystemDto system = context.getSystem();
IcConnectorConfiguration connectorConfig = context.getConnectorConfig();
SysSystemMappingDto systemMapping = systemMappingService.get(context.getConfig().getSystemMapping());
SysSchemaObjectClassDto schemaObjectClassDto = schemaObjectClassService.get(systemMapping.getObjectClass());
IcObjectClass objectClass = new IcObjectClassImpl(schemaObjectClassDto.getObjectClassName());
// Load last token
Object lastToken = config.isReconciliation() ? null : config.getToken();
// Create basic synchronization log
SysSyncLogDto log = new SysSyncLogDto();
log.setSynchronizationConfig(config.getId());
log.setStarted(ZonedDateTime.now());
log.setRunning(true);
log.setToken(lastToken != null ? lastToken.toString() : null);
log.addToLog(MessageFormat.format("Synchronization was started in {0}.", log.getStarted()));
// List of all accounts with full IC object (used in tree sync)
Map<String, IcConnectorObject> accountsMap = new HashMap<>();
longRunningTaskExecutor.setCounter(0L);
try {
log = synchronizationLogService.save(log);
List<SysSyncActionLogDto> actionsLog = new ArrayList<>();
// Add logs to context
context.addLog(log).addActionLogs(actionsLog);
if (config.getTokenAttribute() == null && !config.isReconciliation()) {
throw new ProvisioningException(AccResultCode.SYNCHRONIZATION_TOKEN_ATTRIBUTE_NOT_FOUND);
}
TreeResultsHandler resultHandler = new TreeResultsHandler(accountsMap);
// We have to search all data for tree
IcFilter filter = null;
log.addToLog(MessageFormat.format("Start search with filter {0}.", "NONE"));
log = synchronizationLogService.save(log);
connectorFacade.search(systemService.getConnectorInstance(system), connectorConfig, objectClass, filter, resultHandler);
// Execute sync for this tree and searched accounts
processTreeSync(context, accountsMap);
log = context.getLog();
// Sync is correctly ends if wasn't cancelled
if (log.isRunning()) {
log = syncCorrectlyEnded(log, context);
}
//
synchronizationConfigService.save(config);
} catch (Exception e) {
String message = "Error during synchronization";
log.addToLog(message);
log.setContainsError(true);
log.addToLog(Throwables.getStackTraceAsString(e));
LOG.error(message, e);
} finally {
log.setRunning(false);
log.setEnded(ZonedDateTime.now());
log = synchronizationLogService.save(log);
//
longRunningTaskExecutor.setCount(longRunningTaskExecutor.getCounter());
longRunningTaskExecutor.updateState();
// Clear cache
cacheManager.evictCache(CACHE_NAME);
}
return config;
}
use of eu.bcvsolutions.idm.acc.domain.SynchronizationContext in project CzechIdMng by bcvsolutions.
the class TreeSynchronizationExecutor method processTreeSync.
/**
* Execute sync for tree and given accounts.
*
* @param context
* @param accountsMap
*/
private void processTreeSync(SynchronizationContext context, Map<String, IcConnectorObject> accountsMap) {
AbstractSysSyncConfigDto config = context.getConfig();
SystemEntityType entityType = context.getEntityType();
SysSystemDto system = context.getSystem();
List<SysSystemAttributeMappingDto> mappedAttributes = context.getMappedAttributes();
SysSyncLogDto log = context.getLog();
List<SysSyncActionLogDto> actionsLog = context.getActionLogs();
AttributeMapping tokenAttribute = context.getTokenAttribute();
// Find UID/PARENT/CODE attribute
SysSystemAttributeMappingDto uidAttribute = attributeHandlingService.getUidAttribute(mappedAttributes, system);
SysSystemAttributeMappingDto parentAttribute = getAttributeByIdmProperty(PARENT_FIELD, mappedAttributes);
SysSystemAttributeMappingDto codeAttribute = getAttributeByIdmProperty(CODE_FIELD, mappedAttributes);
if (parentAttribute == null) {
LOG.warn("Parent attribute is not specified! Organization tree will not be recomputed.");
}
if (codeAttribute == null) {
LOG.warn("Code attribute is not specified!");
}
// Find all roots
Collection<String> roots = findRoots(parentAttribute, accountsMap, config, context);
if (roots.isEmpty()) {
log.addToLog("No roots to synchronization found!");
} else {
log.addToLog(MessageFormat.format("We found [{0}] roots: [{1}]", roots.size(), roots));
}
if (parentAttribute == null) {
// just alias all accounts as roots and process
roots.addAll(accountsMap.keySet());
}
Set<String> accountsUseInTreeList = new HashSet<>(roots.size());
for (String root : roots) {
accountsUseInTreeList.add(root);
IcConnectorObject account = accountsMap.get(root);
SynchronizationContext itemContext = cloneItemContext(context);
//
itemContext.addUid(//
root).addIcObject(//
account).addAccount(//
null).addTokenAttribute(//
tokenAttribute).addGeneratedUid(//
null);
boolean result = handleIcObject(itemContext);
if (!result) {
return;
}
if (parentAttribute != null) {
Object uidValueParent = this.getValueByMappedAttribute(uidAttribute, account.getAttributes(), context);
processChildren(parentAttribute, uidValueParent, uidAttribute, accountsMap, accountsUseInTreeList, itemContext, roots);
}
}
if (config.isReconciliation()) {
// We do reconciliation (find missing account)
startReconciliation(entityType, accountsUseInTreeList, config, system, log, actionsLog);
}
}
use of eu.bcvsolutions.idm.acc.domain.SynchronizationContext in project CzechIdMng by bcvsolutions.
the class ContractSynchronizationExecutor method fillEntity.
/**
* Fill entity with attributes from IC module (by mapped attributes).
*
* @param mappedAttributes
* @param uid
* @param icAttributes
* @param entity
* @param create
* (is create or update entity situation)
* @param context
* @return
*/
protected IdmIdentityContractDto fillEntity(List<SysSystemAttributeMappingDto> mappedAttributes, String uid, List<IcAttribute> icAttributes, IdmIdentityContractDto dto, boolean create, SynchronizationContext context) {
mappedAttributes.stream().filter(attribute -> {
// Skip disabled attributes
// Skip extended attributes (we need update/ create entity first)
// Skip confidential attributes (we need update/ create entity
// first)
boolean fastResult = !attribute.isDisabledAttribute() && attribute.isEntityAttribute() && !attribute.isConfidentialAttribute();
if (!fastResult) {
return false;
}
// Can be value set by attribute strategy?
return this.canSetValue(uid, attribute, dto, create);
}).forEach(attribute -> {
String attributeProperty = attribute.getIdmPropertyName();
Object transformedValue = getValueByMappedAttribute(attribute, icAttributes, context);
// they), but to the embedded map.
if (CONTRACT_GUARANTEES_FIELD.equals(attributeProperty)) {
SyncIdentityContractDto syncIdentityContractDto = (SyncIdentityContractDto) dto.getEmbedded().get(SYNC_CONTRACT_FIELD);
if (transformedValue instanceof SyncIdentityContractDto) {
SyncIdentityContractDto transformedValueSyncIdentityContract = (SyncIdentityContractDto) transformedValue;
if (syncIdentityContractDto == null) {
dto.getEmbedded().put(SYNC_CONTRACT_FIELD, transformedValueSyncIdentityContract);
} else {
syncIdentityContractDto.setGuarantees(transformedValueSyncIdentityContract.getGuarantees());
}
} else if (syncIdentityContractDto == null) {
dto.getEmbedded().put(SYNC_CONTRACT_FIELD, new SyncIdentityContractDto());
}
// Check if new guarantees are different than current guarantees.
syncIdentityContractDto = (SyncIdentityContractDto) dto.getEmbedded().get(SYNC_CONTRACT_FIELD);
if (syncIdentityContractDto != null && !context.isEntityDifferent()) {
List<IdmIdentityDto> newGuarantees = syncIdentityContractDto.getGuarantees();
if (!isGuaranteesSame(dto, newGuarantees)) {
// Guarantees are different
context.setIsEntityDifferent(true);
addToItemLog(context.getLogItem(), MessageFormat.format("Value of entity attribute [{0}] was changed. Entity in IdM will be updated.", attributeProperty));
}
}
return;
}
// they), but to the embedded map.
if (CONTRACT_POSITIONS_FIELD.equals(attributeProperty)) {
SyncIdentityContractDto syncIdentityContractDto = (SyncIdentityContractDto) dto.getEmbedded().get(SYNC_CONTRACT_FIELD);
if (transformedValue instanceof SyncIdentityContractDto) {
if (syncIdentityContractDto == null) {
dto.getEmbedded().put(SYNC_CONTRACT_FIELD, (SyncIdentityContractDto) transformedValue);
} else {
syncIdentityContractDto.setPositions(((SyncIdentityContractDto) transformedValue).getPositions());
}
} else if (syncIdentityContractDto == null) {
dto.getEmbedded().put(SYNC_CONTRACT_FIELD, new SyncIdentityContractDto());
}
// Check if new positions are different than current positions.
syncIdentityContractDto = (SyncIdentityContractDto) dto.getEmbedded().get(SYNC_CONTRACT_FIELD);
if (syncIdentityContractDto != null && !context.isEntityDifferent()) {
List<IdmTreeNodeDto> newPositions = syncIdentityContractDto.getPositions();
if (!isPositionsSame(dto, newPositions)) {
// Positions are different
context.setIsEntityDifferent(true);
addToItemLog(context.getLogItem(), MessageFormat.format("Value of entity attribute [{0}] was changed. Entity in IdM will be updated.", attributeProperty));
}
}
return;
}
// Set transformed value from target system to entity
setEntityValue(uid, dto, context, attribute, attributeProperty, transformedValue);
});
return dto;
}
use of eu.bcvsolutions.idm.acc.domain.SynchronizationContext in project CzechIdMng by bcvsolutions.
the class ContractSynchronizationExecutor method save.
/**
* Save entity
*
* @param entity
* @param skipProvisioning
* @return
*/
@Override
protected IdmIdentityContractDto save(IdmIdentityContractDto entity, boolean skipProvisioning, SynchronizationContext context) {
if (entity.getIdentity() == null) {
throw new ProvisioningException(AccResultCode.SYNCHRONIZATION_IDM_FIELD_CANNOT_BE_NULL, ImmutableMap.of("property", CONTRACT_IDENTITY_FIELD));
}
EntityEvent<IdmIdentityContractDto> event = new IdentityContractEvent(contractService.isNew(entity) ? IdentityContractEventType.CREATE : IdentityContractEventType.UPDATE, entity, ImmutableMap.of(ProvisioningService.SKIP_PROVISIONING, skipProvisioning));
// We do not want execute HR processes for every contract. We need start
// them for every identity only once.
// For this we skip them now. HR processes must be start after whole
// sync finished (by using dependent scheduled task)!
event.getProperties().put(IdmIdentityContractService.SKIP_HR_PROCESSES, Boolean.TRUE);
//
// We don't want recalculate automatic role by attribute recalculation for every
// contract.
// Recalculation will be started only once.
event.getProperties().put(AutomaticRoleManager.SKIP_RECALCULATION, Boolean.TRUE);
EventContext<IdmIdentityContractDto> publishContext = contractService.publish(event);
IdmIdentityContractDto contract = publishContext.getContent();
// We need to flag recalculation for contract immediately to prevent synchronization ends before flag is created by NOTIFY event asynchronously.
Map<String, Serializable> properties = new HashMap<>();
EventResult<IdmIdentityContractDto> lastResult = publishContext.getLastResult();
if (lastResult != null) {
// original contract as property
properties.put(EntityEvent.EVENT_PROPERTY_ORIGINAL_SOURCE, lastResult.getEvent().getOriginalSource());
}
if (contract.isValidNowOrInFuture()) {
entityStateManager.createState(contract, OperationState.BLOCKED, CoreResultCode.AUTOMATIC_ROLE_SKIPPED, properties);
} else {
entityStateManager.createState(contract, OperationState.BLOCKED, CoreResultCode.AUTOMATIC_ROLE_SKIPPED_INVALID_CONTRACT, properties);
}
//
if (entity.getEmbedded().containsKey(SYNC_CONTRACT_FIELD)) {
SyncIdentityContractDto syncContract = (SyncIdentityContractDto) entity.getEmbedded().get(SYNC_CONTRACT_FIELD);
// Positions
IdmContractPositionFilter positionFilter = new IdmContractPositionFilter();
positionFilter.setIdentityContractId(contract.getId());
List<IdmContractPositionDto> currentPositions = contractPositionService.find(positionFilter, null).getContent();
// Search positions to delete
List<IdmContractPositionDto> positionsToDelete = currentPositions.stream().filter(position -> {
return position.getWorkPosition() != null && !syncContract.getPositions().contains(new IdmTreeNodeDto(position.getWorkPosition()));
}).collect(Collectors.toList());
// Search positions to add
List<IdmTreeNodeDto> positionsToAdd = syncContract.getPositions().stream().filter(position -> {
return !currentPositions.stream().filter(currentPosition -> {
return position.getId().equals(currentPosition.getWorkPosition());
}).findFirst().isPresent();
}).collect(Collectors.toList());
// Create new positions
positionsToAdd.forEach(position -> {
IdmContractPositionDto contractPosition = new IdmContractPositionDto();
contractPosition.setIdentityContract(contract.getId());
contractPosition.setWorkPosition(position.getId());
//
EntityEvent<IdmContractPositionDto> positionEvent = new ContractPositionEvent(ContractPositionEventType.CREATE, contractPosition, ImmutableMap.of(ProvisioningService.SKIP_PROVISIONING, skipProvisioning, AutomaticRoleManager.SKIP_RECALCULATION, Boolean.TRUE));
contractPosition = contractPositionService.publish(positionEvent).getContent();
// We need to flag recalculation for contract immediately to prevent synchronization ends before flag is created by NOTIFY event asynchronously.
if (contract.isValidNowOrInFuture()) {
entityStateManager.createState(contractPosition, OperationState.BLOCKED, CoreResultCode.AUTOMATIC_ROLE_SKIPPED, null);
}
});
// Delete positions - should be after new positions are created (prevent to drop and create => delete is sync).
positionsToDelete.forEach(position -> {
EntityEvent<IdmContractPositionDto> positionEvent = new ContractPositionEvent(ContractPositionEventType.DELETE, position, ImmutableMap.of(ProvisioningService.SKIP_PROVISIONING, skipProvisioning, AutomaticRoleManager.SKIP_RECALCULATION, Boolean.TRUE));
contractPositionService.publish(positionEvent);
});
// Guarantees
IdmContractGuaranteeFilter guaranteeFilter = new IdmContractGuaranteeFilter();
guaranteeFilter.setIdentityContractId(contract.getId());
List<IdmContractGuaranteeDto> currentGuarantees = guaranteeService.find(guaranteeFilter, null).getContent();
// Search guarantees to delete
List<IdmContractGuaranteeDto> guaranteesToDelete = currentGuarantees.stream().filter(sysImplementer -> {
return sysImplementer.getGuarantee() != null && !syncContract.getGuarantees().contains(new IdmIdentityDto(sysImplementer.getGuarantee()));
}).collect(Collectors.toList());
// Search guarantees to add
List<IdmIdentityDto> guaranteesToAdd = syncContract.getGuarantees().stream().filter(identity -> {
return !currentGuarantees.stream().filter(currentGuarrantee -> {
return identity.getId().equals(currentGuarrantee.getGuarantee());
}).findFirst().isPresent();
}).collect(Collectors.toList());
// Delete guarantees
guaranteesToDelete.forEach(guarantee -> {
EntityEvent<IdmContractGuaranteeDto> guaranteeEvent = new ContractGuaranteeEvent(ContractGuaranteeEventType.DELETE, guarantee, ImmutableMap.of(ProvisioningService.SKIP_PROVISIONING, skipProvisioning));
guaranteeService.publish(guaranteeEvent);
});
// Create new guarantees
guaranteesToAdd.forEach(identity -> {
IdmContractGuaranteeDto guarantee = new IdmContractGuaranteeDto();
guarantee.setIdentityContract(contract.getId());
guarantee.setGuarantee(identity.getId());
//
EntityEvent<IdmContractGuaranteeDto> guaranteeEvent = new ContractGuaranteeEvent(ContractGuaranteeEventType.CREATE, guarantee, ImmutableMap.of(ProvisioningService.SKIP_PROVISIONING, skipProvisioning));
guaranteeService.publish(guaranteeEvent);
});
}
return contract;
}
use of eu.bcvsolutions.idm.acc.domain.SynchronizationContext in project CzechIdMng by bcvsolutions.
the class DefaultSynchronizationService method resolveMissingAccountSituation.
@Override
public SysSyncItemLogDto resolveMissingAccountSituation(String uid, SystemEntityType entityType, UUID accountId, UUID configId, String actionType) {
Assert.notNull(uid, "Uid is required.");
Assert.notNull(entityType, "Entity type is required.");
Assert.notNull(configId, "Configuration identifier is required.");
Assert.notNull(actionType, "Action type is required.");
Assert.notNull(accountId, "Account identifier is required.");
AbstractSysSyncConfigDto config = synchronizationConfigService.get(configId);
SysSystemMappingDto mapping = systemMappingService.get(config.getSystemMapping());
AccAccountDto account = accountService.get(accountId);
SysSchemaObjectClassDto sysSchemaObjectClassDto = schemaObjectClassService.get(mapping.getObjectClass());
SysSystemDto system = DtoUtils.getEmbedded(sysSchemaObjectClassDto, SysSchemaObjectClass_.system);
SysSyncItemLogDto itemLog = new SysSyncItemLogDto();
SynchronizationContext context = new SynchronizationContext();
//
context.addUid(uid).addSystem(//
system).addConfig(//
config).addEntityType(//
entityType).addAccount(//
account).addLogItem(//
itemLog);
getSyncExecutor(entityType, configId).resolveMissingAccountSituation(ReconciliationMissingAccountActionType.valueOf(actionType), context);
return itemLog;
}
Aggregations