use of eu.bcvsolutions.idm.core.api.dto.DefaultResultModel in project CzechIdMng by bcvsolutions.
the class DefaultEntityEventManager method putToQueue.
/**
* Try put event to queue - event is put into queue, only if it's not executed synchronously.
* If event is executed synchronously, then {@link EventContext} is returned, {@code null} is returned otherwise.
*
* @param entityEvent
* @return
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
private EventContext<?> putToQueue(IdmEntityEventDto entityEvent) {
if (entityEvent.getPriority() == PriorityType.IMMEDIATE) {
LOG.trace("Event type [{}] for owner with id [{}] will be executed synchronously.", entityEvent.getEventType(), entityEvent.getOwnerId());
// we don't persist events and their states
return process(new CoreEvent<>(EntityEventType.EXECUTE, entityEvent));
}
if (!eventConfiguration.isAsynchronous()) {
LOG.trace("Event type [{}] for owner with id [{}] will be executed synchronously, asynchronous event processing [{}] is disabled.", entityEvent.getEventType(), entityEvent.getOwnerId(), EventConfiguration.PROPERTY_EVENT_ASYNCHRONOUS_ENABLED);
// synchronous processing
return process(new CoreEvent<>(EntityEventType.EXECUTE, entityEvent));
}
//
// get enabled processors, which listen given event (conditional is evaluated)
final EntityEvent<?> event = toEvent(entityEvent);
List<EntityEventProcessor> listenProcessors = getEnabledProcessors(event).stream().filter(processor -> processor.conditional(event)).collect(Collectors.toList());
if (listenProcessors.isEmpty()) {
LOG.debug("Event type [{}] for owner with id [{}] will not be executed, no enabled processor is registered.", entityEvent.getEventType(), entityEvent.getOwnerId());
// return empty context - nothing is processed
return new DefaultEventContext<>();
}
//
// evaluate event priority by registered processors
PriorityType priority = evaluatePriority(event, listenProcessors);
if (priority != null && priority.getPriority() < entityEvent.getPriority().getPriority()) {
entityEvent.setPriority(priority);
}
// registered processors voted about event will be processed synchronously
if (entityEvent.getPriority() == PriorityType.IMMEDIATE) {
LOG.trace("Event type [{}] for owner with id [{}] will be executed synchronously.", entityEvent.getEventType(), entityEvent.getOwnerId());
// synchronous processing
// we don't persist events and their states
process(new CoreEvent<>(EntityEventType.EXECUTE, entityEvent));
}
//
// TODO: send notification only when event fails
// notification - info about registered (asynchronous) processors
// Map<String, Object> parameters = new LinkedHashMap<>();
// parameters.put("eventType", entityEvent.getEventType());
// parameters.put("ownerId", entityEvent.getOwnerId());
// parameters.put("instanceId", entityEvent.getInstanceId());
// parameters.put("processors", registeredProcessors
// .stream()
// .map(DefaultEntityEventManager.this::toDto)
// .collect(Collectors.toList()));
// notificationManager.send(
// CoreModuleDescriptor.TOPIC_EVENT,
// new IdmMessageDto
// .Builder()
// .setLevel(NotificationLevel.INFO)
// .setModel(new DefaultResultModel(CoreResultCode.EVENT_ACCEPTED, parameters))
// .build());
//
// persist event - asynchronous processing
entityEvent = entityEventService.save(entityEvent);
addEventCache(entityEvent.getId(), entityEvent.getTransactionId());
// not processed - persisted into queue
return null;
}
use of eu.bcvsolutions.idm.core.api.dto.DefaultResultModel in project CzechIdMng by bcvsolutions.
the class DefaultIdmTreeNodeServiceIntegrationTest method testRecountAutomaticRoleWithMissingContent.
@Test
public void testRecountAutomaticRoleWithMissingContent() {
// create state with missing content
IdmEntityStateDto state = new IdmEntityStateDto();
UUID ownerId = UUID.randomUUID();
state.setOwnerId(ownerId);
state.setOwnerType(entityStateManager.getOwnerType(IdmRoleTreeNodeDto.class));
state.setResult(new OperationResultDto.Builder(OperationState.BLOCKED).setModel(new DefaultResultModel(CoreResultCode.AUTOMATIC_ROLE_SKIPPED)).build());
entityStateManager.saveState(null, state);
//
state = new IdmEntityStateDto();
state.setOwnerId(ownerId);
state.setOwnerType(entityStateManager.getOwnerType(IdmRoleTreeNodeDto.class));
state.setResult(new OperationResultDto.Builder(OperationState.BLOCKED).setModel(new DefaultResultModel(CoreResultCode.AUTOMATIC_ROLE_SKIPPED)).build());
entityStateManager.saveState(null, state);
//
// recount skipped automatic roles
LongRunningFutureTask<Boolean> executor = longRunningTaskManager.execute(new ProcessSkippedAutomaticRoleByTreeTaskExecutor());
IdmLongRunningTaskDto longRunningTask = longRunningTaskManager.getLongRunningTask(executor);
Assert.assertTrue(longRunningTask.getWarningItemCount() > 0);
}
use of eu.bcvsolutions.idm.core.api.dto.DefaultResultModel in project CzechIdMng by bcvsolutions.
the class AbstractProvisioningExecutor method changePassword.
@Override
public List<OperationResult> changePassword(DTO dto, PasswordChangeDto passwordChange) {
Assert.notNull(dto, "DTO is required.");
Assert.notNull(dto.getId(), "Password can be changed, when dto is already persisted.");
Assert.notNull(passwordChange, "Password change dto is required.");
List<SysProvisioningOperationDto> preparedOperations = new ArrayList<>();
//
EntityAccountFilter filter = this.createEntityAccountFilter();
filter.setEntityId(dto.getId());
List<? extends EntityAccountDto> entityAccountList = getEntityAccountService().find(filter, null).getContent();
if (entityAccountList == null) {
return Collections.<OperationResult>emptyList();
}
// Distinct by accounts
List<UUID> accountIds = new ArrayList<>();
entityAccountList.stream().filter(entityAccount -> {
if (!entityAccount.isOwnership()) {
return false;
}
if (passwordChange.isAll()) {
// Add all account supports change password
if (entityAccount.getAccount() == null) {
return false;
}
// Check if system for this account support change password
AccAccountFilter accountFilter = new AccAccountFilter();
accountFilter.setSupportChangePassword(Boolean.TRUE);
accountFilter.setId(entityAccount.getAccount());
List<AccAccountDto> accountsChecked = accountService.find(accountFilter, null).getContent();
if (accountsChecked.size() == 1) {
return true;
}
return false;
} else {
return passwordChange.getAccounts().contains(entityAccount.getAccount().toString());
}
}).forEach(entityAccount -> {
if (!accountIds.contains(entityAccount.getAccount())) {
accountIds.add(entityAccount.getAccount());
}
});
//
// Is possible that some account has disabled password attributes
List<OperationResult> notExecutedPasswordChanged = new ArrayList<>();
//
List<AccAccountDto> accounts = new ArrayList<>();
accountIds.forEach(accountId -> {
AccAccountDto account = accountService.get(accountId);
// Skip account in protection
if (account.isInProtection()) {
// Skip this iteration
return;
}
//
accounts.add(account);
// find UID from system entity or from account
SysSystemDto system = DtoUtils.getEmbedded(account, AccAccount_.system);
if (account.getSystemEntity() == null) {
throw new SystemEntityNotFoundException(AccResultCode.PROVISIONING_PASSWORD_SYSTEM_ENTITY_NOT_FOUND, String.valueOf(account.getUid()), system.getCode());
}
SysSystemEntityDto systemEntity = systemEntityService.get(account.getSystemEntity());
//
// Find mapped attributes (include overloaded attributes)
List<AttributeMapping> finalAttributes = resolveMappedAttributes(account, dto, system, systemEntity.getEntityType());
if (CollectionUtils.isEmpty(finalAttributes)) {
return;
}
// We try find __PASSWORD__ attribute in mapped attributes
AttributeMapping mappedAttribute = finalAttributes.stream().filter((attribute) -> {
SysSchemaAttributeDto schemaAttributeDto = getSchemaAttribute(attribute);
return ProvisioningService.PASSWORD_SCHEMA_PROPERTY_NAME.equals(schemaAttributeDto.getName());
}).findFirst().orElse(null);
//
// get all another passwords, list with all passwords (included primary password marked as __PASSWORD__)
SysSystemMappingDto systemMappingDto = getMapping(system, systemEntity.getEntityType());
List<SysSystemAttributeMappingDto> passwordAttributes = attributeMappingService.getAllPasswordAttributes(system.getId(), systemMappingDto.getId());
//
// create account object with all another password
Map<ProvisioningAttributeDto, Object> accountObjectWithAnotherPassword = new HashMap<>(passwordAttributes.size());
for (AttributeMapping passwordAttribute : passwordAttributes) {
// all password attributes contains also main __PASSWORD__ the attribute must be skipped
if (mappedAttribute != null && mappedAttribute.equals(passwordAttribute)) {
continue;
}
GuardedString transformPassword = transformPassword(passwordChange.getNewPassword(), passwordAttribute, systemEntity.getUid(), dto);
SysSchemaAttributeDto schemaAttribute = schemaAttributeService.get(passwordAttribute.getSchemaAttribute());
ProvisioningAttributeDto passwordProvisiongAttributeDto = ProvisioningAttributeDto.createProvisioningAttributeKey(passwordAttribute, schemaAttribute.getName(), schemaAttribute.getClassType());
accountObjectWithAnotherPassword.put(passwordProvisiongAttributeDto, transformPassword);
}
// for this account doesn't exist mapped attribute as password
if (accountObjectWithAnotherPassword.isEmpty() && mappedAttribute == null) {
// Beware we cant use AccAccountDto from acc module, in core is checked by this
notExecutedPasswordChanged.add(new OperationResult.Builder(OperationState.NOT_EXECUTED).setModel(new DefaultResultModel(CoreResultCode.PASSWORD_CHANGE_ACCOUNT_FAILED, ImmutableMap.of(IdmAccountDto.PARAMETER_NAME, createResultAccount(account, system)))).build());
// for this account is this failed password change
return;
}
//
// add all account attributes => standard provisioning
SysProvisioningOperationDto additionalProvisioningOperation = null;
// resolve another attributes that must be sent together with password
List<AttributeMapping> additionalPasswordChangeAttributes = resolveAdditionalPasswordChangeAttributes(account, dto, system, systemEntity.getEntityType());
if (!additionalPasswordChangeAttributes.isEmpty()) {
additionalProvisioningOperation = prepareProvisioning(systemEntity, dto, dto.getId(), ProvisioningOperationType.UPDATE, additionalPasswordChangeAttributes);
}
// add another password
if (!accountObjectWithAnotherPassword.isEmpty()) {
if (additionalProvisioningOperation == null) {
// if additional operation is null create one
additionalProvisioningOperation = prepareProvisioningOperationForAdditionalPassword(systemEntity, dto, dto.getId(), ProvisioningOperationType.UPDATE, systemMappingDto, accountObjectWithAnotherPassword);
} else {
// if additional operation exists just add all account object with additional passwords
additionalProvisioningOperation.getProvisioningContext().getAccountObject().putAll(accountObjectWithAnotherPassword);
}
}
//
// password change operation
SysProvisioningOperationDto operation;
if (provisioningExecutor.getConfiguration().isSendPasswordAttributesTogether() && additionalProvisioningOperation != null) {
// all attributes including another password attributes will be sent with password one provisioning operation
operation = additionalProvisioningOperation;
//
if (mappedAttribute != null) {
// Main password attribute isn't mapped
// transform password value trough transformation
GuardedString transformPassword = transformPassword(passwordChange.getNewPassword(), mappedAttribute, systemEntity.getUid(), dto);
//
// add wish for password
SysSchemaAttributeDto schemaAttributeDto = schemaAttributeService.get(mappedAttribute.getSchemaAttribute());
ProvisioningAttributeDto passwordAttribute = ProvisioningAttributeDto.createProvisioningAttributeKey(mappedAttribute, schemaAttributeDto.getName(), schemaAttributeDto.getClassType());
//
// newly isn't needed check if password is constant or etc.
//
operation.getProvisioningContext().getAccountObject().put(passwordAttribute, transformPassword);
}
//
// do provisioning for additional attributes and password
// together
preparedOperations.add(operation);
} else {
//
if (mappedAttribute != null) {
// Main password attribute isn't mapped
// transform password value trough transformation
GuardedString transformPassword = transformPassword(passwordChange.getNewPassword(), mappedAttribute, systemEntity.getUid(), dto);
//
operation = prepareProvisioningForAttribute(systemEntity, mappedAttribute, transformPassword, ProvisioningOperationType.UPDATE, dto);
preparedOperations.add(operation);
}
// do provisioning for additional attributes and passwords in second
if (additionalProvisioningOperation != null) {
preparedOperations.add(additionalProvisioningOperation);
}
}
});
//
// execute prepared operations
List<OperationResult> results = preparedOperations.stream().map(operation -> {
SysProvisioningOperationDto result = provisioningExecutor.executeSync(operation);
Map<String, Object> parameters = new LinkedHashMap<String, Object>();
AccAccountDto account = accounts.stream().filter(a -> {
return a.getRealUid().equals(result.getSystemEntityUid()) && a.getSystem().equals(operation.getSystem());
}).findFirst().get();
SysSystemDto system = DtoUtils.getEmbedded(account, AccAccount_.system);
//
parameters.put(IdmAccountDto.PARAMETER_NAME, createResultAccount(account, system));
//
if (result.getResult().getState() == OperationState.EXECUTED) {
// Add success changed password account
return new OperationResult.Builder(OperationState.EXECUTED).setModel(new DefaultResultModel(CoreResultCode.PASSWORD_CHANGE_ACCOUNT_SUCCESS, parameters)).build();
}
OperationResult changeResult = new OperationResult.Builder(result.getResult().getState()).setModel(new DefaultResultModel(CoreResultCode.PASSWORD_CHANGE_ACCOUNT_FAILED, parameters)).build();
changeResult.setCause(result.getResult().getCause());
changeResult.setCode(result.getResult().getCode());
return changeResult;
}).collect(Collectors.toList());
//
// add not executed changed from prepare stage
results.addAll(notExecutedPasswordChanged);
return results;
}
use of eu.bcvsolutions.idm.core.api.dto.DefaultResultModel in project CzechIdMng by bcvsolutions.
the class DefaultAccAccountManagementService method deleteIdentityAccount.
@Override
@Transactional
public void deleteIdentityAccount(EntityEvent<IdmIdentityRoleDto> event) {
Assert.notNull(event, "Event is required.");
IdmIdentityRoleDto identityRole = event.getContent();
Assert.notNull(identityRole, "Identity role is required.");
Assert.notNull(identityRole, "Identity role identifier is required.");
//
boolean skipPropagate = event.getBooleanProperty(IdmAccountDto.SKIP_PROPAGATE);
boolean bulk = event.getRootId() != null && entityEventManager.isRunnable(event.getRootId()) && !// check parent event is not role request
entityEventManager.getEvent(event.getRootId()).getOwnerType().equals(entityEventManager.getOwnerType(IdmRoleRequestDto.class));
if (!skipPropagate && !bulk) {
// role is deleted without request or without any parent ... we need to remove account synchronously
List<UUID> accountIds = deleteIdentityAccount(identityRole);
// We needs accounts which were connected to deleted identity-role in next
// processor (we want to execute provisioning only for that accounts)
event.getProperties().put(ACCOUNT_IDS_FOR_DELETED_IDENTITY_ROLE, (Serializable) accountIds);
return;
}
// Role is deleted in bulk (e.g. role request) - account management has to be called outside
// we just mark identity account to be deleted and remove identity role
AccIdentityAccountFilter filter = new AccIdentityAccountFilter();
filter.setIdentityRoleId(identityRole.getId());
//
identityAccountService.find(filter, null).getContent().forEach(identityAccount -> {
//
// Set relation on identity-role to null
identityAccount.setIdentityRole(null);
if (bulk) {
// For bulk create entity state for identity account.
IdmEntityStateDto stateDeleted = new IdmEntityStateDto();
stateDeleted.setSuperOwnerId(identityAccount.getIdentity());
stateDeleted.setResult(new OperationResultDto.Builder(OperationState.RUNNING).setModel(new DefaultResultModel(CoreResultCode.DELETED)).build());
entityStateManager.saveState(identityAccount, stateDeleted);
} else {
// Noting identity-accounts for delayed delete and account management
notingIdentityAccountForDelayedAcm(event, identityAccount, IdmAccountDto.IDENTITY_ACCOUNT_FOR_DELAYED_ACM);
}
identityAccountService.save(identityAccount);
});
// If default creation of accounts is disabled for this role-system (or system is in a cross-domain group), then relation between identity
// and account may not exist. In this scenario we have to made provisioning too.
// So we try to find these role-systems and its accounts.
SysRoleSystemFilter roleSystemForProvisioningFilter = new SysRoleSystemFilter();
roleSystemForProvisioningFilter.setRoleId(identityRole.getRole());
roleSystemService.find(roleSystemForProvisioningFilter, null).getContent().stream().filter(roleSystem -> {
if (!roleSystem.isCreateAccountByDefault()) {
return true;
} else {
SysSystemGroupSystemFilter systemGroupSystemFilter = new SysSystemGroupSystemFilter();
systemGroupSystemFilter.setCrossDomainsGroupsForRoleSystemId(roleSystem.getId());
if (systemGroupSystemService.count(systemGroupSystemFilter) >= 1 && (identityRole.getRoleSystem() == null || roleSystem.getId().equals(identityRole.getRoleSystem()))) {
// -> Provisioning should be made.
return true;
}
}
return false;
}).forEach(roleSystem -> {
IdmIdentityContractDto contractDto = lookupService.lookupEmbeddedDto(identityRole, IdmIdentityRole_.identityContract);
AccIdentityAccountFilter identityAccountFilter = new AccIdentityAccountFilter();
identityAccountFilter.setSystemId(roleSystem.getSystem());
identityAccountFilter.setIdentityId(contractDto.getIdentity());
identityAccountService.find(identityAccountFilter, null).getContent().forEach(identityAccount -> {
// Noting identity-accounts for delayed additional provisioning.
notingIdentityAccountForDelayedAcm(event, identityAccount, IdmAccountDto.ACCOUNT_FOR_ADDITIONAL_PROVISIONING);
});
});
}
use of eu.bcvsolutions.idm.core.api.dto.DefaultResultModel in project CzechIdMng by bcvsolutions.
the class AbstractSchedulableStatefulExecutor method processCandidate.
private Optional<OperationResult> processCandidate(DTO candidate, boolean dryRun) {
if (isInProcessedQueue(candidate)) {
// item was processed earlier - just drop the count by one
// FIXME: this is confusing => task ends with 0 count, if all items are skipped (processed before)
--count;
return Optional.empty();
}
// Is not possible to get real cause from UnexpectedRollbackException,
// so result has to be evaluated inside before this exception is catch.
List<Optional<OperationResult>> results = new ArrayList<>(1);
//
if (dryRun) {
if (!supportsDryRun()) {
throw new DryRunNotSupportedException(getName());
}
// dry run mode - operation is not executed with dry run code (no content)
results.add(Optional.of(new OperationResult.Builder(OperationState.NOT_EXECUTED).setModel(new DefaultResultModel(CoreResultCode.DRY_RUN)).build()));
} else if (requireNewTransaction()) {
TransactionTemplate template = new TransactionTemplate(platformTransactionManager);
template.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
//
try {
template.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
results.add(processItemInternal(candidate));
}
});
} catch (UnexpectedRollbackException ex) {
// Just log for sure ... exception solved in new transaction, but this lower transaction is marked as roll-back.
LOG.debug("Statefull process [{}] processed item [{}] failed", getClass().getSimpleName(), candidate, ex);
}
} else {
results.add(this.processItemInternal(candidate));
}
//
++counter;
Optional<OperationResult> result;
if (!results.isEmpty()) {
result = results.get(0);
if (result == null) {
// null can be returned simply => empty result
result = Optional.empty();
}
} else {
result = Optional.empty();
}
//
if (result.isPresent()) {
OperationResult opResult = result.get();
this.logItemProcessed(candidate, opResult);
if (OperationState.isSuccessful(opResult.getState())) {
this.addToProcessedQueue(candidate, opResult);
}
LOG.debug("Statefull process [{}] intermediate result: [{}], count: [{}/{}]", getClass().getSimpleName(), opResult.getState(), count, counter);
if (!continueOnException() && opResult.getException() != null) {
ResultCodeException resultCodeException;
if (opResult.getException() instanceof ResultCodeException) {
resultCodeException = (ResultCodeException) opResult.getException();
} else {
resultCodeException = new ResultCodeException(CoreResultCode.LONG_RUNNING_TASK_ITEM_FAILED, ImmutableMap.of("referencedEntityId", candidate.getId()), opResult.getException());
}
LOG.error("[" + resultCodeException.getId() + "] ", resultCodeException);
//
throw resultCodeException;
}
} else {
LOG.debug("Statefull process [{}] processed item [{}] without result.", getClass().getSimpleName(), candidate);
}
//
return result;
}
Aggregations