use of eu.bcvsolutions.idm.core.model.event.IdentityContractEvent in project CzechIdMng by bcvsolutions.
the class EntityEventProcessorUnitTest method testSuppotsAll.
@Test
public void testSuppotsAll() {
EntityEventProcessor<?> processor = new EventProcessorBase();
assertTrue(processor.supports(new IdentityEvent(IdentityEventType.UPDATE, new IdmIdentityDto())));
assertTrue(processor.supports(new IdentityEvent(IdentityEventType.DELETE, new IdmIdentityDto())));
assertTrue(processor.supports(new IdentityContractEvent(IdentityContractEventType.DELETE, new IdmIdentityContractDto())));
assertTrue(processor.supports(new CoreEvent<IdmIdentityDto>(CustomType.SAVE, new IdmIdentityDto())));
assertTrue(processor.supports(new CoreEvent<>(CustomType.CUSTOM, new IdmIdentityDto())));
assertTrue(processor.supports(new CoreEvent<IdmIdentityContractDto>(IdentityContractEventType.UPDATE, new IdmIdentityContractDto())));
}
use of eu.bcvsolutions.idm.core.model.event.IdentityContractEvent 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) {
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(IdmAutomaticRoleAttributeService.SKIP_RECALCULATION, Boolean.TRUE);
IdmIdentityContractDto contract = contractService.publish(event).getContent();
if (entity.getEmbedded().containsKey(SYNC_CONTRACT_FIELD)) {
SyncIdentityContractDto syncContract = (SyncIdentityContractDto) entity.getEmbedded().get(SYNC_CONTRACT_FIELD);
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.core.model.event.IdentityContractEvent in project CzechIdMng by bcvsolutions.
the class IdentityContractSyncTest method checkContractInvalidTest.
@Test
public /**
* HR process are not executed during sync. If contract is invalid, then HR
* process disable the Identity. But in the sync we need skip this
* functionality.
*/
void checkContractInvalidTest() {
SysSystemDto system = initData();
Assert.assertNotNull(system);
AbstractSysSyncConfigDto config = doCreateSyncConfig(system);
Assert.assertTrue(config instanceof SysSyncContractConfigDto);
((SysSyncContractConfigDto) config).setStartOfHrProcesses(false);
syncConfigService.save(config);
IdmIdentityDto ownerOne = helper.createIdentity(CONTRACT_OWNER_ONE);
IdmIdentityDto ownerTwo = helper.createIdentity(CONTRACT_OWNER_TWO);
helper.createIdentity(CONTRACT_LEADER_ONE);
contractService.findAllByIdentity(ownerOne.getId()).forEach(contract -> {
IdentityContractEvent event = new IdentityContractEvent(IdentityContractEventType.DELETE, contract);
event.getProperties().put(IdmIdentityContractService.SKIP_HR_PROCESSES, Boolean.TRUE);
contractService.publish(event);
});
contractService.findAllByIdentity(ownerTwo.getId()).forEach(contract -> {
IdentityContractEvent event = new IdentityContractEvent(IdentityContractEventType.DELETE, contract);
event.getProperties().put(IdmIdentityContractService.SKIP_HR_PROCESSES, Boolean.TRUE);
contractService.publish(event);
});
IdmIdentityContractFilter contractFilter = new IdmIdentityContractFilter();
contractFilter.setProperty(IdmIdentityContract_.position.getName());
contractFilter.setValue("1");
Assert.assertEquals(0, contractService.find(contractFilter, null).getTotalElements());
contractFilter.setValue("2");
Assert.assertEquals(0, contractService.find(contractFilter, null).getTotalElements());
// Change resources (set to invalid) .. must be call in transaction
this.getBean().initContractCheckInvalidTest();
helper.startSynchronization(config);
SysSyncLogDto log = checkSyncLog(config, SynchronizationActionType.CREATE_ENTITY, 2);
Assert.assertFalse(log.isRunning());
Assert.assertFalse(log.isContainsError());
contractFilter.setValue("1");
List<IdmIdentityContractDto> contractsOne = contractService.find(contractFilter, null).getContent();
Assert.assertEquals(1, contractsOne.size());
Assert.assertFalse(contractsOne.get(0).isValid());
contractFilter.setValue("3");
List<IdmIdentityContractDto> contractsThree = contractService.find(contractFilter, null).getContent();
Assert.assertEquals(1, contractsThree.size());
Assert.assertTrue(contractsThree.get(0).isValid());
// HR processes was not started, identity have to be in "incorrect" state
ownerOne = identityService.getByUsername(CONTRACT_OWNER_ONE);
Assert.assertFalse(ownerOne.isDisabled());
ownerTwo = identityService.getByUsername(CONTRACT_OWNER_TWO);
Assert.assertFalse(ownerTwo.isDisabled());
// Delete log
syncLogService.delete(log);
}
use of eu.bcvsolutions.idm.core.model.event.IdentityContractEvent in project CzechIdMng by bcvsolutions.
the class DefaultContractSliceManager method recalculateContractSlice.
@Override
public void recalculateContractSlice(IdmContractSliceDto slice, IdmContractSliceDto originalSlice, Map<String, Serializable> eventProperties) {
boolean forceRecalculateCurrentUsingSlice = false;
Object forceRecalculateCurrentUsingSliceAsObject = eventProperties.get(IdmContractSliceService.FORCE_RECALCULATE_CURRENT_USING_SLICE);
if (forceRecalculateCurrentUsingSliceAsObject == null) {
forceRecalculateCurrentUsingSlice = false;
} else if (forceRecalculateCurrentUsingSliceAsObject instanceof Boolean) {
forceRecalculateCurrentUsingSlice = (Boolean) forceRecalculateCurrentUsingSliceAsObject;
} else {
forceRecalculateCurrentUsingSlice = false;
}
boolean recalculateUsingAsContract = false;
if (slice.getIdentity() != null) {
UUID parentContract = slice.getParentContract();
// null (will be recalculated)
if (originalSlice != null && !Objects.equal(originalSlice.getContractCode(), slice.getContractCode())) {
slice.setParentContract(null);
// When external code changed, link or create new contract is required
parentContract = null;
}
if (originalSlice != null && !Objects.equal(originalSlice.getParentContract(), slice.getParentContract())) {
slice.setParentContract(null);
slice.setUsingAsContract(false);
}
if (parentContract == null) {
slice = linkOrCreateContract(slice, eventProperties);
} else {
// Update contract by that slice
if (slice.isUsingAsContract()) {
// Validity of slice was changed, slice cannot be using for update the contract
if (originalSlice != null && !Objects.equal(originalSlice.getValidFrom(), slice.getValidFrom())) {
recalculateUsingAsContract = true;
} else {
IdmIdentityContractDto contract = contractService.get(parentContract);
this.getBean().updateContractBySlice(contract, slice, eventProperties);
}
}
}
}
UUID parentContract = slice.getParentContract();
if (originalSlice == null) {
// Slice is new, we want to recalculate "Is using as contract" field.
recalculateUsingAsContract = true;
}
// Recalculate on change of 'parentContract' field
boolean parentContractChanged = false;
if (originalSlice != null && !Objects.equal(originalSlice.getParentContract(), slice.getParentContract())) {
UUID originalParentContract = originalSlice.getParentContract();
// Parent contract was changed ... we need recalculate parent contract for
// original slice
parentContractChanged = true;
if (originalParentContract != null) {
IdmIdentityContractDto originalContract = contractService.get(originalParentContract);
// Find other slices for original contract
IdmContractSliceFilter sliceFilter = new IdmContractSliceFilter();
sliceFilter.setParentContract(originalParentContract);
List<IdmContractSliceDto> originalSlices = contractSliceService.find(sliceFilter, null).getContent();
if (!originalSlices.isEmpty()) {
IdmContractSliceDto originalNextSlice = this.getBean().findNextSlice(originalSlice, originalSlices);
IdmContractSliceDto originalSliceToUpdate = originalNextSlice;
if (originalNextSlice != null) {
// Next slice exists, update valid-till on previous slice by that slice
IdmContractSliceDto originalPreviousSlice = this.getBean().findPreviousSlice(originalNextSlice, originalSlices);
if (originalPreviousSlice != null) {
originalPreviousSlice.setValidTill(originalNextSlice.getValidFrom().minusDays(1));
originalSliceToUpdate = originalPreviousSlice;
}
} else {
// Next slice does not exists. I means original slice was last. Set valid-till
// on previous slice to null.
IdmContractSliceDto originalPreviousSlice = this.getBean().findPreviousSlice(originalSlice, originalSlices);
if (originalPreviousSlice != null && this.getBean().findNextSlice(originalPreviousSlice, originalSlices) == null) {
originalPreviousSlice.setValidTill(null);
originalSliceToUpdate = originalPreviousSlice;
}
}
// Save with force recalculation
contractSliceService.publish(new ContractSliceEvent(ContractSliceEventType.UPDATE, originalSliceToUpdate, ImmutableMap.of(IdmContractSliceService.FORCE_RECALCULATE_CURRENT_USING_SLICE, Boolean.TRUE)));
} else {
// Parent contract was changed and old contract does not have next slice, we
// have to delete him.
// Delete contract
contractService.publish(new IdentityContractEvent(IdentityContractEventType.DELETE, originalContract, ImmutableMap.copyOf(eventProperties))).getContent();
}
}
// Parent contract was changed, want to recalculate "Is using as contract"
// field.
recalculateUsingAsContract = true;
}
// contract
if (originalSlice == null || parentContractChanged || (originalSlice != null && !Objects.equal(originalSlice.getValidFrom(), slice.getValidFrom()))) {
// slice
if (parentContract != null) {
// Find other slices for parent contract
List<IdmContractSliceDto> slices = this.getBean().findAllSlices(parentContract);
if (!slices.isEmpty()) {
// Update validity till on this slice and on previous slice
recalculateValidTill(slice, slices);
// original slice)
if (originalSlice != null) {
IdmContractSliceDto nextSliceForOriginalSlice = this.getBean().findNextSlice(originalSlice, slices);
if (nextSliceForOriginalSlice == null) {
// Next slice not exists, it means original slice was last
IdmContractSliceDto previousSliceForOriginalSlice = this.getBean().findPreviousSlice(originalSlice, slices);
if (previousSliceForOriginalSlice != null && this.getBean().findNextSlice(previousSliceForOriginalSlice, slices) == null) {
previousSliceForOriginalSlice.setValidTill(null);
// Save with skip this processor
saveWithoutRecalculate(previousSliceForOriginalSlice);
}
}
}
}
}
// Validity from was changed, want to recalculate "Is using as contract" field.
recalculateUsingAsContract = true;
}
if (recalculateUsingAsContract || forceRecalculateCurrentUsingSlice) {
IdmContractSliceFilter sliceFilter = new IdmContractSliceFilter();
sliceFilter.setParentContract(parentContract);
sliceFilter.setUsingAsContract(Boolean.TRUE);
IdmContractSliceDto shouldBeSetAsUsing = this.getBean().findValidSlice(parentContract);
if (shouldBeSetAsUsing != null) {
Map<String, Serializable> clonedProperties = new HashMap<>(eventProperties);
if (clonedProperties.containsKey(IdmContractSliceService.FORCE_RECALCULATE_CURRENT_USING_SLICE)) {
clonedProperties.remove(IdmContractSliceService.FORCE_RECALCULATE_CURRENT_USING_SLICE);
}
shouldBeSetAsUsing = this.getBean().setSliceAsCurrentlyUsing(shouldBeSetAsUsing, clonedProperties);
if (slice.equals(shouldBeSetAsUsing)) {
// If that slice should be using as contract, then we using returned instance
// (instead the reload slice from DB)
slice = shouldBeSetAsUsing;
}
}
}
// Check if is slice new or contract valid till field was changed.
if (originalSlice == null || (!Objects.equal(originalSlice.getContractValidTill(), slice.getContractValidTill()))) {
// If is slice last, then will be to slice valid till copy date of contract
// valid till
boolean isSliceLast = this.getBean().findNextSlice(slice, this.getBean().findAllSlices(parentContract)) == null ? true : false;
if (isSliceLast) {
slice.setValidTill(null);
saveWithoutRecalculate(slice);
}
}
}
use of eu.bcvsolutions.idm.core.model.event.IdentityContractEvent in project CzechIdMng by bcvsolutions.
the class DefaultContractSliceManager method updateContractBySlice.
@Override
@Transactional
public IdmIdentityContractDto updateContractBySlice(IdmIdentityContractDto contract, IdmContractSliceDto slice, Map<String, Serializable> eventProperties) {
Assert.notNull(contract, "Contract is required.");
Assert.notNull(slice, "Contract slice cannot be null!");
Assert.notNull(slice.getIdentity(), "Contract slice identity is required.");
Assert.isTrue(slice.isUsingAsContract(), "Contract slice has to be actualy used for contract.");
boolean isNew = contractService.isNew(contract);
// Update all slice attributes
convertSliceToContract(slice, contract);
// Check if is protection interval activated and whether we need resolve him
int protectionInterval = contractSliceConfiguration.getProtectionInterval();
if (!isNew && protectionInterval > 0 && slice.getContractValidTill() != null) {
resolveProtectionInterval(slice, contract, protectionInterval);
}
// Save contract
ImmutableMap<String, Serializable> parameters = new ImmutableMap.Builder<String, Serializable>().putAll(eventProperties).put(ContractSliceManager.SKIP_CHECK_FOR_SLICES, Boolean.TRUE).build();
EventContext<IdmIdentityContractDto> publishContext = contractService.publish(new IdentityContractEvent(isNew ? IdentityContractEventType.CREATE : IdentityContractEventType.UPDATE, contract, parameters));
IdmIdentityContractDto savedContract = publishContext.getContent();
// We need to flag recalculation for contract immediately to prevent e.g. synchronization ends before flag is created by NOTIFY event asynchronously.
if (getBooleanProperty(AutomaticRoleManager.SKIP_RECALCULATION, eventProperties)) {
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());
}
entityStateManager.createState(savedContract, OperationState.BLOCKED, CoreResultCode.AUTOMATIC_ROLE_SKIPPED, properties);
}
// Copy guarantees
copyGuarantees(slice, savedContract);
return savedContract;
}
Aggregations