All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.gravitee.rest.api.service.impl.AuditServiceImpl Maven / Gradle / Ivy

There is a newer version: 3.10.0
Show newest version
/**
 * Copyright (C) 2015 The Gravitee team (http://gravitee.io)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package io.gravitee.rest.api.service.impl;

import static io.gravitee.rest.api.service.impl.MetadataServiceImpl.getDefaultReferenceId;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.github.fge.jsonpatch.diff.JsonDiff;
import io.gravitee.common.data.domain.MetadataPage;
import io.gravitee.common.data.domain.Page;
import io.gravitee.repository.exceptions.TechnicalException;
import io.gravitee.repository.management.api.*;
import io.gravitee.repository.management.api.search.AuditCriteria.Builder;
import io.gravitee.repository.management.api.search.builder.PageableBuilder;
import io.gravitee.repository.management.model.*;
import io.gravitee.rest.api.idp.api.authentication.UserDetails;
import io.gravitee.rest.api.model.UserEntity;
import io.gravitee.rest.api.model.audit.AuditEntity;
import io.gravitee.rest.api.model.audit.AuditQuery;
import io.gravitee.rest.api.service.AuditService;
import io.gravitee.rest.api.service.UserService;
import io.gravitee.rest.api.service.common.GraviteeContext;
import io.gravitee.rest.api.service.common.RandomString;
import io.gravitee.rest.api.service.exceptions.TechnicalManagementException;
import io.gravitee.rest.api.service.exceptions.UserNotFoundException;
import java.util.*;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

/**
 * @author Nicolas GERAUD (nicolas.geraud at graviteesource.com)
 * @author Florent CHAMFROY (florent.chamfroy at graviteesource.com)
 * @author GraviteeSource Team
 */
@Component
public class AuditServiceImpl extends AbstractService implements AuditService {

    private final Logger LOGGER = LoggerFactory.getLogger(AuditServiceImpl.class);

    @Autowired
    private AuditRepository auditRepository;

    @Autowired
    private PageRepository pageRepository;

    @Autowired
    private PlanRepository planRepository;

    @Autowired
    private MetadataRepository metadataRepository;

    @Autowired
    private GroupRepository groupRepository;

    @Autowired
    private ApiRepository apiRepository;

    @Autowired
    private ApplicationRepository applicationRepository;

    @Autowired
    @Lazy
    private UserService userService;

    @Autowired
    private ObjectMapper mapper;

    @Override
    public MetadataPage search(AuditQuery query) {
        Builder criteria = new Builder().from(query.getFrom()).to(query.getTo());

        if (query.isCurrentEnvironmentLogsOnly()) {
            criteria.references(Audit.AuditReferenceType.ENVIRONMENT, Collections.singletonList(GraviteeContext.getCurrentEnvironment()));
        } else if (query.isCurrentOrganizationLogsOnly()) {
            criteria.references(Audit.AuditReferenceType.ORGANIZATION, Collections.singletonList(GraviteeContext.getCurrentOrganization()));
        } else if (query.getApiIds() != null && !query.getApiIds().isEmpty()) {
            criteria.references(Audit.AuditReferenceType.API, query.getApiIds());
        } else if (query.getApplicationIds() != null && !query.getApplicationIds().isEmpty()) {
            criteria.references(Audit.AuditReferenceType.APPLICATION, query.getApplicationIds());
        }

        if (query.getEvents() != null && !query.getEvents().isEmpty()) {
            criteria.events(query.getEvents());
        }

        Page auditPage = auditRepository.search(
            criteria.build(),
            new PageableBuilder().pageNumber(query.getPage() - 1).pageSize(query.getSize()).build()
        );

        List content = auditPage.getContent().stream().map(this::convert).collect(Collectors.toList());

        return new MetadataPage<>(content, query.getPage(), query.getSize(), auditPage.getTotalElements(), getMetadata(content));
    }

    private Map getMetadata(List content) {
        Map metadata = new HashMap<>();
        for (AuditEntity auditEntity : content) {
            //add user's display name
            String metadataKey = "USER:" + auditEntity.getUser() + ":name";
            try {
                UserEntity user = userService.findById(auditEntity.getUser());
                metadata.put(metadataKey, user.getDisplayName());
            } catch (TechnicalManagementException e) {
                LOGGER.error("Error finding metadata {}", auditEntity.getUser());
            } catch (UserNotFoundException unfe) {
                metadata.put(metadataKey, auditEntity.getUser());
            }

            if (Audit.AuditReferenceType.API.name().equals(auditEntity.getReferenceType())) {
                metadataKey = "API:" + auditEntity.getReferenceId() + ":name";
                if (!metadata.containsKey(metadataKey)) {
                    try {
                        Optional optApi = apiRepository.findById(auditEntity.getReferenceId());
                        if (optApi.isPresent()) {
                            metadata.put(metadataKey, optApi.get().getName());
                        }
                    } catch (TechnicalException e) {
                        LOGGER.error("Error finding metadata {}", metadataKey);
                        metadata.put(metadataKey, auditEntity.getReferenceId());
                    }
                }
            } else if (Audit.AuditReferenceType.APPLICATION.name().equals(auditEntity.getReferenceType())) {
                metadataKey = "APPLICATION:" + auditEntity.getReferenceId() + ":name";
                if (!metadata.containsKey(metadataKey)) {
                    try {
                        Optional optApp = applicationRepository.findById(auditEntity.getReferenceId());
                        if (optApp.isPresent()) {
                            metadata.put(metadataKey, optApp.get().getName());
                        }
                    } catch (TechnicalException e) {
                        LOGGER.error("Error finding metadata {}", metadataKey);
                        metadata.put(metadataKey, auditEntity.getReferenceId());
                    }
                }
            }

            //add property metadata
            String name;
            if (auditEntity.getProperties() != null) {
                for (Map.Entry property : auditEntity.getProperties().entrySet()) {
                    metadataKey = new StringJoiner(":").add(property.getKey()).add(property.getValue()).add("name").toString();
                    if (!metadata.containsKey(metadataKey)) {
                        name = property.getValue();
                        try {
                            switch (Audit.AuditProperties.valueOf(property.getKey())) {
                                case API:
                                    Optional optApi = apiRepository.findById(property.getValue());
                                    if (optApi.isPresent()) {
                                        name = optApi.get().getName();
                                    }
                                    break;
                                case APPLICATION:
                                    Optional optApp = applicationRepository.findById(property.getValue());
                                    if (optApp.isPresent()) {
                                        name = optApp.get().getName();
                                    }
                                    break;
                                case PAGE:
                                    Optional optPage = pageRepository.findById(
                                        property.getValue()
                                    );
                                    if (optPage.isPresent()) {
                                        name = optPage.get().getName();
                                    }
                                    break;
                                case PLAN:
                                    Optional optPlan = planRepository.findById(property.getValue());
                                    if (optPlan.isPresent()) {
                                        name = optPlan.get().getName();
                                    }
                                    break;
                                case METADATA:
                                    MetadataReferenceType refType = (
                                            Audit.AuditReferenceType.API.name().equals(auditEntity.getReferenceType())
                                        )
                                        ? MetadataReferenceType.API
                                        : (Audit.AuditReferenceType.APPLICATION.name().equals(auditEntity.getReferenceType()))
                                            ? MetadataReferenceType.APPLICATION
                                            : MetadataReferenceType.DEFAULT;
                                    String refId = refType.equals(MetadataReferenceType.DEFAULT)
                                        ? getDefaultReferenceId()
                                        : auditEntity.getReferenceId();

                                    Optional optMetadata = metadataRepository.findById(property.getValue(), refId, refType);
                                    if (optMetadata.isPresent()) {
                                        name = optMetadata.get().getName();
                                    }
                                    break;
                                case GROUP:
                                    Optional optGroup = groupRepository.findById(property.getValue());
                                    if (optGroup.isPresent()) {
                                        name = optGroup.get().getName();
                                    }
                                    break;
                                case USER:
                                    try {
                                        UserEntity user = userService.findById(property.getValue());
                                        name = user.getDisplayName();
                                    } catch (UserNotFoundException unfe) {
                                        name = property.getValue();
                                    }
                                default:
                                    break;
                            }
                        } catch (TechnicalException e) {
                            LOGGER.error("Error finding metadata {}", metadataKey);
                            name = property.getValue();
                        }
                        metadata.put(metadataKey, name);
                    }
                }
            }
        }
        return metadata;
    }

    @Override
    public void createApiAuditLog(
        String apiId,
        Map properties,
        Audit.AuditEvent event,
        Date createdAt,
        Object oldValue,
        Object newValue
    ) {
        createAuditLog(Audit.AuditReferenceType.API, apiId, properties, event, createdAt, oldValue, newValue);
    }

    @Override
    public void createApplicationAuditLog(
        String applicationId,
        Map properties,
        Audit.AuditEvent event,
        Date createdAt,
        Object oldValue,
        Object newValue
    ) {
        createAuditLog(Audit.AuditReferenceType.APPLICATION, applicationId, properties, event, createdAt, oldValue, newValue);
    }

    @Override
    public void createEnvironmentAuditLog(
        Map properties,
        Audit.AuditEvent event,
        Date createdAt,
        Object oldValue,
        Object newValue
    ) {
        createAuditLog(
            Audit.AuditReferenceType.ENVIRONMENT,
            GraviteeContext.getCurrentEnvironment(),
            properties,
            event,
            createdAt,
            oldValue,
            newValue
        );
    }

    @Override
    public void createOrganizationAuditLog(
        Map properties,
        Audit.AuditEvent event,
        Date createdAt,
        Object oldValue,
        Object newValue
    ) {
        createAuditLog(
            Audit.AuditReferenceType.ORGANIZATION,
            GraviteeContext.getCurrentOrganization(),
            properties,
            event,
            createdAt,
            oldValue,
            newValue
        );
    }

    @Async
    @Override
    public void createAuditLog(
        Audit.AuditReferenceType referenceType,
        String referenceId,
        Map properties,
        Audit.AuditEvent event,
        Date createdAt,
        Object oldValue,
        Object newValue
    ) {
        Audit audit = new Audit();
        audit.setId(RandomString.generate());
        audit.setCreatedAt(createdAt == null ? new Date() : createdAt);

        final UserDetails authenticatedUser = getAuthenticatedUser();
        final String user;
        if (authenticatedUser != null && "token".equals(authenticatedUser.getSource())) {
            user =
                userService.findById(authenticatedUser.getUsername()).getDisplayName() +
                " - (using token \"" +
                authenticatedUser.getSourceId() +
                "\")";
        } else {
            user = getAuthenticatedUsernameOrSystem();
        }
        audit.setUser(user);

        if (properties != null) {
            Map stringStringMap = new HashMap<>(properties.size());
            properties.forEach((auditProperties, s) -> stringStringMap.put(auditProperties.name(), s));
            audit.setProperties(stringStringMap);
        }

        audit.setReferenceType(referenceType);
        audit.setReferenceId(referenceId);
        audit.setEvent(event.name());

        ObjectNode oldNode = oldValue == null
            ? mapper.createObjectNode()
            : mapper.convertValue(oldValue, ObjectNode.class).remove(Arrays.asList("updatedAt", "createdAt"));
        ObjectNode newNode = newValue == null
            ? mapper.createObjectNode()
            : mapper.convertValue(newValue, ObjectNode.class).remove(Arrays.asList("updatedAt", "createdAt"));

        audit.setPatch(JsonDiff.asJson(oldNode, newNode).toString());

        try {
            auditRepository.create(audit);
        } catch (TechnicalException e) {
            LOGGER.error("Error occurs during the creation of an Audit Log {}.", e);
        }
    }

    private AuditEntity convert(Audit audit) {
        AuditEntity auditEntity = new AuditEntity();

        auditEntity.setReferenceType(audit.getReferenceType().name());
        auditEntity.setReferenceId(audit.getReferenceId());
        auditEntity.setEvent(audit.getEvent());
        auditEntity.setProperties(audit.getProperties());
        auditEntity.setUser(audit.getUser());
        auditEntity.setId(audit.getId());
        auditEntity.setPatch(audit.getPatch());
        auditEntity.setCreatedAt(audit.getCreatedAt());

        return auditEntity;
    }

    private String getAuthenticatedUsernameOrSystem() {
        return isAuthenticated() ? getAuthenticatedUsername() : "system";
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy