Search in sources :

Example 1 with AppEvent

use of org.eclipse.vorto.repository.core.events.AppEvent in project vorto by eclipse.

the class ModelRepository method removeModel.

@Override
public void removeModel(ModelId modelId) {
    doInSession(session -> {
        try {
            ModelInfo modelResource = this.getById(modelId);
            if (modelResource == null) {
                throw new ModelNotFoundException("Cannot find '" + modelId.getPrettyFormat() + "' in '" + session.getWorkspace().getName() + "'");
            }
            if (modelResource.getReferencedBy() != null && !modelResource.getReferencedBy().isEmpty()) {
                throw new ModelReferentialIntegrityException("Cannot remove model because it is referenced by other model(s)", modelResource.getReferencedBy());
            }
            ModelIdHelper modelIdHelper = new ModelIdHelper(modelId);
            Item item = session.getItem(modelIdHelper.getFullPath());
            item.remove();
            session.save();
            eventPublisher.publishEvent(new AppEvent(this, modelId, null, EventType.MODEL_DELETED));
            return null;
        } catch (AccessDeniedException e) {
            throw new NotAuthorizedException(modelId, e);
        }
    });
}
Also used : AppEvent(org.eclipse.vorto.repository.core.events.AppEvent) ModelIdHelper(org.eclipse.vorto.repository.core.impl.utils.ModelIdHelper) NotAuthorizedException(org.eclipse.vorto.repository.web.core.exceptions.NotAuthorizedException)

Example 2 with AppEvent

use of org.eclipse.vorto.repository.core.events.AppEvent in project vorto by eclipse.

the class ModelRepository method doAttachFileInSession.

private boolean doAttachFileInSession(ModelId modelId, FileContent fileContent, IUserContext userContext, Session session, Tag[] tags) throws RepositoryException {
    try {
        ModelIdHelper modelIdHelper = new ModelIdHelper(modelId);
        Node modelFolderNode = session.getNode(modelIdHelper.getFullPath());
        Node attachmentFolderNode;
        if (!modelFolderNode.hasNode(ATTACHMENTS_NODE)) {
            attachmentFolderNode = modelFolderNode.addNode(ATTACHMENTS_NODE, NT_FOLDER);
        } else {
            attachmentFolderNode = modelFolderNode.getNode(ATTACHMENTS_NODE);
        }
        String[] tagIds = Arrays.stream(tags).filter(Objects::nonNull).map(Tag::getId).collect(Collectors.toList()).toArray(new String[tags.length]);
        // purposes), removes the tag from all other attachments
        if (Arrays.asList(tags).contains(TAG_DISPLAY_IMAGE)) {
            NodeIterator attachments = attachmentFolderNode.getNodes();
            while (attachments.hasNext()) {
                Node next = attachments.nextNode();
                Property attachmentTags = next.getProperty(VORTO_TAGS);
                Value[] attachmentTagsValuesFiltered = Arrays.stream(attachmentTags.getValues()).filter(v -> {
                    try {
                        return !v.getString().equals(TAG_DISPLAY_IMAGE.getId());
                    // swallowing here
                    } catch (RepositoryException re) {
                        return false;
                    }
                }).toArray(Value[]::new);
                next.setProperty(VORTO_TAGS, attachmentTagsValuesFiltered);
            }
        }
        Node contentNode;
        if (attachmentFolderNode.hasNode(fileContent.getFileName())) {
            Node attachmentNode = attachmentFolderNode.getNode(fileContent.getFileName());
            attachmentNode.addMixin(VORTO_META);
            attachmentNode.setProperty(VORTO_TAGS, tagIds, PropertyType.STRING);
            contentNode = (Node) attachmentNode.getPrimaryItem();
        } else {
            Node attachmentNode = attachmentFolderNode.addNode(fileContent.getFileName(), NT_FILE);
            attachmentNode.addMixin(VORTO_META);
            attachmentNode.setProperty(VORTO_TAGS, tagIds, PropertyType.STRING);
            contentNode = attachmentNode.addNode(JCR_CONTENT, NT_RESOURCE);
        }
        Binary binary = session.getValueFactory().createBinary(new ByteArrayInputStream(fileContent.getContent()));
        contentNode.setProperty(JCR_DATA, binary);
        session.save();
        eventPublisher.publishEvent(new AppEvent(this, getById(modelId), userContext, EventType.MODEL_UPDATED));
        return true;
    } catch (AccessDeniedException e) {
        throw new NotAuthorizedException(modelId, e);
    }
}
Also used : DependencyManager(org.eclipse.vorto.repository.core.impl.utils.DependencyManager) java.util(java.util) EventType(org.eclipse.vorto.repository.core.events.EventType) javax.jcr.query(javax.jcr.query) AppEvent(org.eclipse.vorto.repository.core.events.AppEvent) Function(java.util.function.Function) ModelLink(org.eclipse.vorto.repository.web.api.v1.dto.ModelLink) Model(org.eclipse.vorto.core.api.model.model.Model) Logger(org.apache.log4j.Logger) Lists(com.google.common.collect.Lists) ObjectMapperFactory(org.eclipse.vorto.plugin.generator.adapter.ObjectMapperFactory) ByteArrayInputStream(java.io.ByteArrayInputStream) IModelWorkspace(org.eclipse.vorto.utilities.reader.IModelWorkspace) ApplicationEventPublisher(org.springframework.context.ApplicationEventPublisher) org.eclipse.vorto.repository.core(org.eclipse.vorto.repository.core) ModelState(org.eclipse.vorto.repository.workflow.ModelState) ModelParserFactory(org.eclipse.vorto.repository.core.impl.parser.ModelParserFactory) Attachment(org.eclipse.vorto.repository.core.Attachment) PrivilegeService(org.eclipse.vorto.repository.services.PrivilegeService) ApplicationEventPublisherAware(org.springframework.context.ApplicationEventPublisherAware) ModelSearchUtil(org.eclipse.vorto.repository.core.impl.utils.ModelSearchUtil) ModelIdHelper(org.eclipse.vorto.repository.core.impl.utils.ModelIdHelper) ModelReferencesHelper(org.eclipse.vorto.repository.core.impl.utils.ModelReferencesHelper) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) NotAuthorizedException(org.eclipse.vorto.repository.web.core.exceptions.NotAuthorizedException) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) IOException(java.io.IOException) ModelId(org.eclipse.vorto.model.ModelId) ValidationException(org.eclipse.vorto.repository.core.impl.validation.ValidationException) Namespace(org.eclipse.vorto.repository.domain.Namespace) Collectors(java.util.stream.Collectors) ModelType(org.eclipse.vorto.model.ModelType) NamespaceService(org.eclipse.vorto.repository.services.NamespaceService) IOUtils(org.apache.commons.io.IOUtils) ChangeSet(org.eclipse.vorto.model.refactor.ChangeSet) RefactoringTask(org.eclipse.vorto.model.refactor.RefactoringTask) AttachmentValidator(org.eclipse.vorto.repository.core.impl.validation.AttachmentValidator) ModelWorkspaceReader(org.eclipse.vorto.utilities.reader.ModelWorkspaceReader) NewNamespacesNotSupersetException(org.eclipse.vorto.repository.tenant.NewNamespacesNotSupersetException) ModelUtils(org.eclipse.vorto.repository.utils.ModelUtils) IModelParser(org.eclipse.vorto.repository.core.impl.parser.IModelParser) javax.jcr(javax.jcr) InputStream(java.io.InputStream) NotAuthorizedException(org.eclipse.vorto.repository.web.core.exceptions.NotAuthorizedException) AppEvent(org.eclipse.vorto.repository.core.events.AppEvent) ModelIdHelper(org.eclipse.vorto.repository.core.impl.utils.ModelIdHelper) ByteArrayInputStream(java.io.ByteArrayInputStream)

Example 3 with AppEvent

use of org.eclipse.vorto.repository.core.events.AppEvent in project vorto by eclipse.

the class UserService method delete.

/**
 * Deletes the given {@link User} and their namespace-role associations, as acted by the given
 * acting {@link User}.<br/>
 * This can fail for a number of reasons:
 * <ul>
 *   <li>
 *     The acting {@link User} does not have the {@literal sysadmin} repository role, or is not
 *     the same {@link User} as the target.
 *   </li>
 *   <li>
 *     The target {@link User} owns a {@link org.eclipse.vorto.repository.domain.Namespace} - in
 *     which case, ownership should be given to another {@link User} before deleting.
 *   </li>
 *   <li>
 *     The target {@link User} is the only one listed with namespace role {@literal namespace_admin}
 *     on one or more {@link org.eclipse.vorto.repository.domain.Namespace}s - in which case, the
 *     role should be given to at least one other {@link User} before deleting.
 *   </li>
 * </ul>
 * Failures above will throw checked exceptions. <br/>
 * It is also possible that this method will fail by returning {@code false}, should the target
 * {@link User} simply not exist.
 *
 * @param actor
 * @param target
 * @return
 */
@Transactional(rollbackFor = { OperationForbiddenException.class, DoesNotExistException.class })
public boolean delete(User actor, User target) throws OperationForbiddenException, DoesNotExistException {
    // boilerplate null validation
    ServiceValidationUtil.validateNulls(actor, target);
    if (cache.withUser(target).getUser() == null) {
        LOGGER.info("Attempting to delete a user that does not exist. ");
        return false;
    }
    // authorizing actor
    userUtil.authorizeActorAsTargetOrSysadmin(actor, target);
    // checking if only admin in any namespace
    if (userNamespaceRoleService.isOnlyAdminInAnyNamespace(actor, target)) {
        throw new OperationForbiddenException("User is the only administrator of at least one namespace - aborting delete operation.");
    }
    // retrieving namespaces target manages
    Collection<Namespace> namespacesManagedByTarget = userNamespaceRoleService.getNamespacesAndRolesByUser(actor, target).entrySet().stream().filter(e -> e.getValue().contains(userNamespaceRoleService.namespaceAdminRole())).map(Entry::getKey).collect(Collectors.toSet());
    // target owns at least one namespace - failing
    if (!namespacesManagedByTarget.isEmpty()) {
        throw new OperationForbiddenException("User is administrator in at least one namespace. Ownership must change before user can be deleted. Aborting operation.");
    }
    // collecting target user's e-mail address if any
    DeleteAccountMessage message = null;
    if (target.hasEmailAddress()) {
        message = new DeleteAccountMessage(target);
    }
    // firstly, publish the user deleted event - this way, the models are all anonymized while the
    // user and their namespace associations are still there
    eventPublisher.publishEvent(new AppEvent(this, target.getUsername(), EventType.USER_DELETED));
    // then, retrie namespaces where target has any role
    Collection<Namespace> namespacesWhereTargetHasAnyRole = userNamespaceRoleService.getNamespaces(actor, target);
    // and remove association for all namespaces
    for (Namespace namespace : namespacesWhereTargetHasAnyRole) {
        userNamespaceRoleService.deleteAllRoles(actor, target, namespace, false);
    }
    // finally, delete target user
    userRepository.delete(target);
    // and send them a message if possible
    if (message != null) {
        notificationService.sendNotification(message);
    }
    return true;
}
Also used : AppEvent(org.eclipse.vorto.repository.core.events.AppEvent) OperationForbiddenException(org.eclipse.vorto.repository.services.exceptions.OperationForbiddenException) Namespace(org.eclipse.vorto.repository.domain.Namespace) DeleteAccountMessage(org.eclipse.vorto.repository.notification.message.DeleteAccountMessage) Transactional(org.springframework.transaction.annotation.Transactional)

Example 4 with AppEvent

use of org.eclipse.vorto.repository.core.events.AppEvent in project vorto by eclipse.

the class NamespaceService method create.

// namespace operations
/**
 * This creates a new namespace with the given name, setting the given target {@link User} as
 * owner, and giving them all available roles on that namespace. <br/>
 * The difference between the actor and target users is that depending on the repository roles of
 * the actor user, some operations may not succeed.<br/>
 * For instance, if the actor and target are the same user (typical situation when a user
 * requests to create their own namespace), but the user is not a sysadmin and already has a
 * private namespace, the creation would fail (one private namespace per user). <br/>
 * However, if the actor was sysadmin and creating, e.g. an official namespace for a target user
 * who happens to already have a private namespace, the operation should succeed. <br/>
 * The operation can fail the given {@link User} or namespace name are invalid. <br/>
 * Examples of invalid {@link User} or namespace are:
 * <ul>
 *   <li>
 *     The user is {@code null}, has a {@code null} user name, or does not exist.
 *   </li>
 *   <li>
 *     The namespace name is {@code null}, empty, does not conform to naming standards (lowercase
 *     ASCII alphanumerics, dots as separators, underscores allowed).
 *   </li>
 *   <li>
 *     A namespace with that name already exists.
 *   </li>
 * </ul>
 * This method is invoked in two distinct cases:
 * <ol>
 *   <li>
 *     A user creates their own private namespace.
 *   </li>
 *   <li>
 *     A sysadmin creates an official namespace for any user, including themselves.
 *   </li>
 * </ol>
 * This method only deals with creating namespaces. <br/>
 *
 * @param actor
 * @param target
 * @param namespaceName
 * @return
 * @throws IllegalArgumentException
 * @throws DoesNotExistException
 * @throws CollisionException
 * @throws NameSyntaxException
 */
@Transactional(rollbackFor = { DoesNotExistException.class, CollisionException.class, NameSyntaxException.class, PrivateNamespaceQuotaExceededException.class, OperationForbiddenException.class })
public Namespace create(User actor, User target, String namespaceName) throws IllegalArgumentException, DoesNotExistException, CollisionException, NameSyntaxException, PrivateNamespaceQuotaExceededException, OperationForbiddenException {
    // boilerplate null validation
    ServiceValidationUtil.validate(actor, target);
    ServiceValidationUtil.validateNulls(namespaceName);
    // lightweight validation of required properties
    ServiceValidationUtil.validateNulls(actor.getId(), target.getId());
    if (namespaceName.trim().isEmpty()) {
        throw new NameSyntaxException(String.format("Namespace name is empty - aborting namespace creation.", namespaceName));
    }
    // pattern-based namespace name validation
    if (!VALID_NAMESPACE_NAME.matcher(namespaceName).matches()) {
        throw new NameSyntaxException(String.format("[%s] is not a valid namespace name - aborting namespace creation.", namespaceName));
    }
    // namespace collision validation
    if (cache.namespace(namespaceName).isPresent()) {
        throw new CollisionException(String.format("A namespace with name [%s] already exists - aborting namespace creation.", namespaceName));
    }
    // actor is not sysadmin - need to enforce quota validation and private namespace notation
    if (!userRepositoryRoleService.isSysadmin(actor)) {
        if (!namespaceName.startsWith(PRIVATE_NAMESPACE_PREFIX)) {
            throw new NameSyntaxException(String.format("[%s] is an invalid name for a private namespace - aborting namespace creation.", namespaceName));
        }
        verifyPrivateNamespaceQuota(actor, target);
    }
    // persists the new namespace
    Namespace namespace = new Namespace();
    namespace.setName(namespaceName);
    namespace.setWorkspaceId(UUID.randomUUID().toString().replace("-", ""));
    namespaceRepository.save(namespace);
    userNamespaceRoleService.setAllRoles(actor, target, namespace, true);
    // making cache stale so it will load the newly created namespace upon next usage within request
    cache.stale();
    // application event handling
    eventPublisher.publishEvent(new AppEvent(this, target.getUsername(), UserContext.user(target.getUsername(), namespace.getWorkspaceId()), EventType.NAMESPACE_ADDED));
    return namespace;
}
Also used : AppEvent(org.eclipse.vorto.repository.core.events.AppEvent) CollisionException(org.eclipse.vorto.repository.services.exceptions.CollisionException) NameSyntaxException(org.eclipse.vorto.repository.services.exceptions.NameSyntaxException) Namespace(org.eclipse.vorto.repository.domain.Namespace) Transactional(org.springframework.transaction.annotation.Transactional)

Example 5 with AppEvent

use of org.eclipse.vorto.repository.core.events.AppEvent in project vorto by eclipse.

the class ModelRepository method updateProperty.

private ModelId updateProperty(ModelId modelId, NodeConsumer nodeConsumer) {
    return doInSession(session -> {
        try {
            Node folderNode = createNodeForModelId(session, modelId);
            Node fileNode = folderNode.getNodes(FILE_NODES).hasNext() ? folderNode.getNodes(FILE_NODES).nextNode() : null;
            nodeConsumer.accept(fileNode);
            fileNode.addMixin(MIX_LAST_MODIFIED);
            session.save();
            eventPublisher.publishEvent(new AppEvent(this, getBasicInfo(modelId), null, EventType.MODEL_UPDATED));
            return modelId;
        } catch (AccessDeniedException e) {
            throw new NotAuthorizedException(modelId, e);
        }
    });
}
Also used : AppEvent(org.eclipse.vorto.repository.core.events.AppEvent) NotAuthorizedException(org.eclipse.vorto.repository.web.core.exceptions.NotAuthorizedException)

Aggregations

AppEvent (org.eclipse.vorto.repository.core.events.AppEvent)9 NotAuthorizedException (org.eclipse.vorto.repository.web.core.exceptions.NotAuthorizedException)5 Namespace (org.eclipse.vorto.repository.domain.Namespace)3 Transactional (org.springframework.transaction.annotation.Transactional)3 JsonProcessingException (com.fasterxml.jackson.core.JsonProcessingException)2 ByteArrayInputStream (java.io.ByteArrayInputStream)2 IOException (java.io.IOException)2 javax.jcr (javax.jcr)2 ModelIdHelper (org.eclipse.vorto.repository.core.impl.utils.ModelIdHelper)2 ValidationException (org.eclipse.vorto.repository.core.impl.validation.ValidationException)2 User (org.eclipse.vorto.repository.domain.User)2 DeleteAccountMessage (org.eclipse.vorto.repository.notification.message.DeleteAccountMessage)2 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)1 Lists (com.google.common.collect.Lists)1 InputStream (java.io.InputStream)1 java.util (java.util)1 Function (java.util.function.Function)1 Collectors (java.util.stream.Collectors)1 javax.jcr.query (javax.jcr.query)1 IOUtils (org.apache.commons.io.IOUtils)1