Search in sources :

Example 46 with DefaultResultModel

use of eu.bcvsolutions.idm.core.api.dto.DefaultResultModel in project CzechIdMng by bcvsolutions.

the class DefaultEntityEventManager method executeEvent.

@Override
@Transactional
public void executeEvent(IdmEntityEventDto event) {
    Assert.notNull(event, "Event is reqired to be event executed.");
    Assert.notNull(event.getOwnerId(), "Event owner identifier is reqired to be event executed.");
    if (!eventConfiguration.isAsynchronous()) {
        // synchronous processing
        // we don't persist events and their states
        process(new CoreEvent<>(EntityEventType.EXECUTE, event));
        return;
    }
    if (event.getPriority() == PriorityType.IMMEDIATE) {
        // synchronous processing
        // we don't persist events and their states
        // TODO: what about running event with the same owner? And events in queue for the same owner => no locking now, last wins
        process(new CoreEvent<>(EntityEventType.EXECUTE, event));
        return;
    }
    // 
    if (runningOwnerEvents.putIfAbsent(event.getOwnerId(), event.getId()) != null) {
        LOG.debug("Previous event [{}] for owner with id [{}] is currently processed.", runningOwnerEvents.get(event.getOwnerId()), event.getOwnerId());
        // event will be processed in another scheduling
        return;
    }
    // check super owner is not processed
    UUID superOwnerId = event.getSuperOwnerId();
    if (superOwnerId != null && !superOwnerId.equals(event.getOwnerId())) {
        if (runningOwnerEvents.putIfAbsent(superOwnerId, event.getId()) != null) {
            LOG.debug("Previous event [{}] for super owner with id [{}] is currently processed.", runningOwnerEvents.get(superOwnerId), superOwnerId);
            runningOwnerEvents.remove(event.getOwnerId());
            // event will be processed in another scheduling
            return;
        }
    }
    // execute event in new thread asynchronously
    try {
        eventConfiguration.getExecutor().execute(new Runnable() {

            @Override
            @SuppressWarnings("unchecked")
            public void run() {
                // run as event creator
                securityService.setAuthentication(new IdmJwtAuthentication(new IdmIdentityDto(event.getCreatorId(), event.getCreator()), new IdmIdentityDto(event.getOriginalCreatorId(), event.getOriginalCreator()), null, ZonedDateTime.now(), Lists.newArrayList(IdmAuthorityUtils.getAdminAuthority()), null));
                // run under original transaction id - asynchronous processing continue the "user" transaction
                TransactionContextHolder.setContext(new TransactionContext(event.getTransactionId()));
                // 
                LOG.debug("Executing event under user [{}] (admin authorities) and transaction [{}]", securityService.getUsername(), TransactionContextHolder.getContext().getTransactionId());
                // 
                try {
                    process(new CoreEvent<>(EntityEventType.EXECUTE, event));
                } catch (Exception ex) {
                    // all processor should persist their own entity state (see AbstractEntityEventProcessor)
                    // event result is persisted here
                    OperationState resultState = OperationState.EXCEPTION;
                    ResultModel resultModel;
                    if (ex instanceof ResultCodeException) {
                        ResultCodeException resultCodeException = (ResultCodeException) ex;
                        resultModel = resultCodeException.getError().getError();
                        if (resultCodeException.getStatus() == HttpStatus.ACCEPTED) {
                            // => concrete information is preserved in model to know, what happen
                            resultState = OperationState.EXECUTED;
                        }
                    } else {
                        resultModel = new DefaultResultModel(CoreResultCode.EVENT_EXECUTE_FAILED, ImmutableMap.of("eventId", event.getId(), "eventType", String.valueOf(event.getEventType()), "ownerId", String.valueOf(event.getOwnerId()), "instanceId", String.valueOf(event.getInstanceId())));
                    }
                    saveResult(event.getId(), new OperationResultDto.Builder(resultState).setCause(ex).setModel(resultModel).build());
                    // 
                    ExceptionUtils.log(LOG, resultModel, ex);
                    // We check if owner service supports this feature (implements ExceptionProcessable).
                    try {
                        Class<?> ownerClass = Class.forName(event.getOwnerType());
                        ReadDtoService<?, ?> dtoService = lookupService.getDtoService((Class<? extends Identifiable>) ownerClass);
                        if (dtoService instanceof ExceptionProcessable) {
                            ExceptionProcessable<?> exceptionProcessable = (ExceptionProcessable<?>) dtoService;
                            // Propagate the exception
                            exceptionProcessable.processException(event.getOwnerId(), ex);
                        }
                    } catch (ClassNotFoundException e) {
                        // Only to the log
                        LOG.error(e.getLocalizedMessage(), e);
                    }
                } finally {
                    LOG.trace("Event [{}] ends for owner with id [{}].", event.getId(), event.getOwnerId());
                    removeRunningEvent(event);
                }
            }
        });
        // 
        LOG.trace("Running event [{}] for owner with id [{}].", event.getId(), event.getOwnerId());
    } catch (RejectedExecutionException ex) {
        // thread pool queue is full - wait for another try
        removeRunningEvent(event);
    }
}
Also used : DefaultResultModel(eu.bcvsolutions.idm.core.api.dto.DefaultResultModel) ResultCodeException(eu.bcvsolutions.idm.core.api.exception.ResultCodeException) DefaultResultModel(eu.bcvsolutions.idm.core.api.dto.DefaultResultModel) ResultModel(eu.bcvsolutions.idm.core.api.dto.ResultModel) EventContentDeletedException(eu.bcvsolutions.idm.core.api.exception.EventContentDeletedException) ResultCodeException(eu.bcvsolutions.idm.core.api.exception.ResultCodeException) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) RejectedExecutionException(java.util.concurrent.RejectedExecutionException) CoreEvent(eu.bcvsolutions.idm.core.api.event.CoreEvent) TransactionContext(eu.bcvsolutions.idm.core.api.domain.TransactionContext) IdmJwtAuthentication(eu.bcvsolutions.idm.core.security.api.domain.IdmJwtAuthentication) UUID(java.util.UUID) IdmIdentityDto(eu.bcvsolutions.idm.core.api.dto.IdmIdentityDto) ExceptionProcessable(eu.bcvsolutions.idm.core.security.api.service.ExceptionProcessable) OperationState(eu.bcvsolutions.idm.core.api.domain.OperationState) Transactional(org.springframework.transaction.annotation.Transactional)

Example 47 with DefaultResultModel

use of eu.bcvsolutions.idm.core.api.dto.DefaultResultModel in project CzechIdMng by bcvsolutions.

the class DefaultEntityEventManager method getCreatedEvents.

/**
 * Called from scheduler - concurrency is prevented.
 * Returns events to process sorted by priority 7 / 3 (high / normal).
 * Immediate priority is executed synchronously.
 * Cancel duplicate events (same type, owner and props) - last event is returned
 *
 * @param instanceId
 * @return
 */
protected List<IdmEntityEventDto> getCreatedEvents(String instanceId) {
    Assert.notNull(instanceId, "Server instance identifier is required.");
    // 
    // already running owners are excluded (super owner is excluded too)
    List<UUID> exceptOwnerIds = Lists.newArrayList(runningOwnerEvents.keySet());
    // prevent sql queue size is exceeded
    exceptOwnerIds = exceptOwnerIds.subList(0, exceptOwnerIds.size() > 500 ? 500 : exceptOwnerIds.size());
    // 
    // load created events - high priority
    ZonedDateTime executeDate = ZonedDateTime.now();
    Page<IdmEntityEventDto> highEvents = entityEventService.findToExecute(instanceId, executeDate, PriorityType.HIGH, exceptOwnerIds, PageRequest.of(0, eventConfiguration.getBatchSize(), new Sort(Direction.ASC, Auditable.PROPERTY_CREATED)));
    // load created events - low priority
    Page<IdmEntityEventDto> normalEvents = entityEventService.findToExecute(instanceId, executeDate, PriorityType.NORMAL, exceptOwnerIds, PageRequest.of(0, eventConfiguration.getBatchSize(), new Sort(Direction.ASC, Auditable.PROPERTY_CREATED)));
    // merge events
    List<IdmEntityEventDto> events = new ArrayList<>();
    events.addAll(highEvents.getContent());
    events.addAll(normalEvents.getContent());
    // sort by created date
    events.sort(new CreatedComparator());
    // 
    // cancel duplicates - by owner => properties has to be the same
    // execute the first event for each owner only - preserve events order
    Map<UUID, IdmEntityEventDto> distinctEvents = new LinkedHashMap<>();
    events.forEach(event -> {
        if (!distinctEvents.containsKey(event.getOwnerId())) {
            // the first event
            distinctEvents.put(event.getOwnerId(), event);
        } else {
            // cancel duplicate older event
            IdmEntityEventDto olderEvent = distinctEvents.get(event.getOwnerId());
            if (isDuplicate(olderEvent, event)) {
                // try to set higher priority
                if (olderEvent.getPriority() == PriorityType.HIGH) {
                    event.setPriority(PriorityType.HIGH);
                }
                distinctEvents.put(event.getOwnerId(), event);
                // 
                LOG.debug(new DefaultResultModel(CoreResultCode.EVENT_DUPLICATE_CANCELED, ImmutableMap.of("eventId", olderEvent.getId(), "eventType", String.valueOf(olderEvent.getEventType()), "ownerId", String.valueOf(olderEvent.getOwnerId()), "instanceId", String.valueOf(olderEvent.getInstanceId()), "neverEventId", event.getId())).toString());
                // 
                IdmEntityEventFilter eventFilter = new IdmEntityEventFilter();
                eventFilter.setParentId(olderEvent.getId());
                if (entityEventService.find(eventFilter, PageRequest.of(0, 1)).getTotalElements() == 0) {
                    deleteEvent(olderEvent);
                }
            }
        }
    });
    // 
    // sort by priority
    events = distinctEvents.values().stream().sorted((o1, o2) -> {
        return Integer.compare(o1.getPriority().getPriority(), o2.getPriority().getPriority());
    }).collect(Collectors.toList());
    int normalCount = events.stream().filter(e -> e.getPriority() == PriorityType.NORMAL).collect(Collectors.toList()).size();
    int maxNormalCount = eventConfiguration.getBatchSize() / 3;
    int highMaximum = normalCount > maxNormalCount ? (eventConfiguration.getBatchSize() - maxNormalCount) : (eventConfiguration.getBatchSize() - normalCount);
    // evaluate priority => high 70 / low 30
    int highCounter = 0;
    List<IdmEntityEventDto> prioritizedEvents = new ArrayList<>();
    for (IdmEntityEventDto event : events) {
        if (event.getPriority() == PriorityType.HIGH) {
            if (highCounter < highMaximum) {
                prioritizedEvents.add(event);
                highCounter++;
            }
        } else {
            // normal priority remains only
            if (prioritizedEvents.size() >= eventConfiguration.getBatchSize()) {
                break;
            }
            prioritizedEvents.add(event);
        }
    }
    // 
    return prioritizedEvents;
}
Also used : DefaultResultModel(eu.bcvsolutions.idm.core.api.dto.DefaultResultModel) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) ZonedDateTime(java.time.ZonedDateTime) CreatedComparator(eu.bcvsolutions.idm.core.api.domain.comparator.CreatedComparator) Sort(org.springframework.data.domain.Sort) UUID(java.util.UUID) IdmEntityEventFilter(eu.bcvsolutions.idm.core.api.dto.filter.IdmEntityEventFilter) IdmEntityEventDto(eu.bcvsolutions.idm.core.api.dto.IdmEntityEventDto)

Example 48 with DefaultResultModel

use of eu.bcvsolutions.idm.core.api.dto.DefaultResultModel in project CzechIdMng by bcvsolutions.

the class ProcessSkippedAutomaticRoleByTreeTaskExecutor method processItem.

@Override
public Optional<OperationResult> processItem(IdmEntityStateDto state) {
    // check state is already processed by ProcessAutomaticRoleByTreeTaskExecutor
    // => automatic role recount can be skipped multiple times for the same automatic role.
    UUID ownerId = state.getOwnerId();
    state = entityStateService.get(state);
    if (state == null) {
        LOG.debug("Automatic roles for owner [{}] was already processed.", ownerId);
        // we need some result - counter / count will match.
        return Optional.of(new OperationResult.Builder(OperationState.EXECUTED).build());
    }
    // 
    if (processedOwnerIds.contains(ownerId)) {
        LOG.debug("Automatic roles for owner [{}] was already processed, delete state only.", ownerId);
        // 
        entityStateManager.deleteState(state);
        // Item will be deleted only - we need some result - counter / count will match.
        return Optional.of(new OperationResult.Builder(OperationState.EXECUTED).build());
    }
    // 
    // process automatic role on state owner
    LOG.debug("Process automatic roles for contract [{}].", ownerId);
    // 
    IdmRoleTreeNodeDto automaticRole = lookupService.lookupDto(IdmRoleTreeNodeDto.class, ownerId);
    if (automaticRole == null) {
        getItemService().createLogItem(state, new OperationResult.Builder(OperationState.NOT_EXECUTED).setModel(new DefaultResultModel(CoreResultCode.CONTENT_DELETED, ImmutableMap.of("ownerId", ownerId, "ownerType", entityEventManager.getOwnerType(IdmRoleTreeNodeDto.class)))).build(), this.getLongRunningTaskId());
        // delete state only
        entityStateManager.deleteState(state);
    } else {
        ProcessAutomaticRoleByTreeTaskExecutor automaticRoleTask = AutowireHelper.createBean(ProcessAutomaticRoleByTreeTaskExecutor.class);
        automaticRoleTask.setAutomaticRoles(Lists.newArrayList(automaticRole.getId()));
        // invalid roles will be removed, after LRT end (prevent drop and create target account)
        automaticRoleTask.setRemoveNotProcessedIdentityRoles(false);
        automaticRoleTask.setRequireNewTransaction(true);
        // exception is thrown and logged otherwise
        longRunningTaskManager.executeSync(automaticRoleTask);
        processedRoleRequests.addAll(automaticRoleTask.getProcessedRoleRequests());
        processedAutomaticRoles.add(ownerId);
        // 
        getItemService().createLogItem(automaticRole, new OperationResult.Builder(OperationState.EXECUTED).build(), this.getLongRunningTaskId());
    }
    // 
    processedOwnerIds.add(ownerId);
    // Log added manually above - log processed contract / position instead of deleted entity state.
    return Optional.empty();
}
Also used : IdmRoleTreeNodeDto(eu.bcvsolutions.idm.core.api.dto.IdmRoleTreeNodeDto) DefaultResultModel(eu.bcvsolutions.idm.core.api.dto.DefaultResultModel) OperationResult(eu.bcvsolutions.idm.core.api.entity.OperationResult) UUID(java.util.UUID)

Example 49 with DefaultResultModel

use of eu.bcvsolutions.idm.core.api.dto.DefaultResultModel in project CzechIdMng by bcvsolutions.

the class RemoveRoleCompositionTaskExecutor method processItem.

@Override
public Optional<OperationResult> processItem(IdmIdentityRoleDto identityRole) {
    try {
        // create request
        IdmIdentityContractDto contract = DtoUtils.getEmbedded(identityRole, IdmIdentityRole_.identityContract);
        UUID identityId = contract.getIdentity();
        IdmRoleRequestDto roleRequest = new IdmRoleRequestDto();
        roleRequest.setState(RoleRequestState.CONCEPT);
        // without approval
        roleRequest.setExecuteImmediately(true);
        roleRequest.setApplicant(identityId);
        roleRequest.setRequestedByType(RoleRequestedByType.AUTOMATICALLY);
        roleRequest = roleRequestService.save(roleRequest);
        // create concepts
        createConcepts(roleRequest, new ArrayList<>(), identityRole);
        // start event with skip check authorities
        RoleRequestEvent requestEvent = new RoleRequestEvent(RoleRequestEventType.EXCECUTE, roleRequest);
        requestEvent.getProperties().put(IdmIdentityRoleService.SKIP_CHECK_AUTHORITIES, Boolean.TRUE);
        // prevent to start asynchronous event before previous update event is completed.
        requestEvent.setSuperOwnerId(identityId);
        // 
        roleRequestService.startRequestInternal(requestEvent);
        // 
        return Optional.of(new OperationResult.Builder(OperationState.EXECUTED).build());
    } catch (Exception ex) {
        return Optional.of(new OperationResult.Builder(OperationState.EXCEPTION).setModel(new DefaultResultModel(CoreResultCode.ROLE_COMPOSITION_ASSIGNED_ROLE_REMOVAL_FAILED, ImmutableMap.of("identityRole", identityRole.getId().toString()))).setCause(ex).build());
    }
}
Also used : DefaultResultModel(eu.bcvsolutions.idm.core.api.dto.DefaultResultModel) OperationResult(eu.bcvsolutions.idm.core.api.entity.OperationResult) RoleRequestEvent(eu.bcvsolutions.idm.core.model.event.RoleRequestEvent) UUID(java.util.UUID) IdmIdentityContractDto(eu.bcvsolutions.idm.core.api.dto.IdmIdentityContractDto) IdmRoleRequestDto(eu.bcvsolutions.idm.core.api.dto.IdmRoleRequestDto) ResultCodeException(eu.bcvsolutions.idm.core.api.exception.ResultCodeException) EntityNotFoundException(eu.bcvsolutions.idm.core.api.exception.EntityNotFoundException) AcceptedException(eu.bcvsolutions.idm.core.api.exception.AcceptedException)

Example 50 with DefaultResultModel

use of eu.bcvsolutions.idm.core.api.dto.DefaultResultModel in project CzechIdMng by bcvsolutions.

the class PasswordExpiredTaskExecutor method processItem.

@Override
public Optional<OperationResult> processItem(IdmPasswordDto dto) {
    if (!expiration.isAfter(dto.getValidTill())) {
        // skip the same date (valid till filter <=) - just info into lrt. Will be processed next day.
        return Optional.of(new OperationResult.Builder(OperationState.NOT_EXECUTED).setModel(new DefaultResultModel(CoreResultCode.PASSWORD_EXPIRATION_TODAY_INFO)).build());
    }
    // 
    IdmIdentityDto identity = getLookupService().lookupEmbeddedDto(dto, IdmPassword_.identity);
    LOG.info("Publishing [{}] event to identity [{}], password expired in [{}]", IdentityEventType.PASSWORD_EXPIRED, identity.getUsername(), dto.getValidTill());
    try {
        entityEventManager.process(new IdentityEvent(IdentityEventType.PASSWORD_EXPIRED, identity));
        return Optional.of(new OperationResult.Builder(OperationState.EXECUTED).build());
    } catch (Exception ex) {
        LOG.error("Publishing [{}] event to identity [{}], password expired in [{}] failed", IdentityEventType.PASSWORD_EXPIRED, dto.getIdentity(), dto.getValidTill(), ex);
        return Optional.of(new OperationResult.Builder(OperationState.EXCEPTION).setCause(ex).build());
    }
}
Also used : DefaultResultModel(eu.bcvsolutions.idm.core.api.dto.DefaultResultModel) IdentityEvent(eu.bcvsolutions.idm.core.model.event.IdentityEvent) OperationResult(eu.bcvsolutions.idm.core.api.entity.OperationResult) IdmIdentityDto(eu.bcvsolutions.idm.core.api.dto.IdmIdentityDto)

Aggregations

DefaultResultModel (eu.bcvsolutions.idm.core.api.dto.DefaultResultModel)104 ResultModel (eu.bcvsolutions.idm.core.api.dto.ResultModel)52 UUID (java.util.UUID)48 OperationResultDto (eu.bcvsolutions.idm.core.api.dto.OperationResultDto)40 OperationResult (eu.bcvsolutions.idm.core.api.entity.OperationResult)35 ResultCodeException (eu.bcvsolutions.idm.core.api.exception.ResultCodeException)25 IdmEntityStateDto (eu.bcvsolutions.idm.core.api.dto.IdmEntityStateDto)24 DefaultEventResult (eu.bcvsolutions.idm.core.api.event.DefaultEventResult)21 IdmIdentityDto (eu.bcvsolutions.idm.core.api.dto.IdmIdentityDto)19 HashMap (java.util.HashMap)19 IdmRoleDto (eu.bcvsolutions.idm.core.api.dto.IdmRoleDto)18 OperationState (eu.bcvsolutions.idm.core.api.domain.OperationState)16 IdmRoleRequestDto (eu.bcvsolutions.idm.core.api.dto.IdmRoleRequestDto)16 Autowired (org.springframework.beans.factory.annotation.Autowired)16 IdmIdentityContractDto (eu.bcvsolutions.idm.core.api.dto.IdmIdentityContractDto)15 List (java.util.List)15 IdmConceptRoleRequestDto (eu.bcvsolutions.idm.core.api.dto.IdmConceptRoleRequestDto)14 Set (java.util.Set)14 ImmutableMap (com.google.common.collect.ImmutableMap)13 CoreResultCode (eu.bcvsolutions.idm.core.api.domain.CoreResultCode)13