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

com.sap.cds.repackaged.audit.client.impl.AuditLogMessageImpl Maven / Gradle / Ivy

There is a newer version: 3.2.0
Show newest version
package com.sap.cds.repackaged.audit.client.impl;

import static com.sap.cds.repackaged.audit.client.impl.Utils.IDP_VALUE;
import static com.sap.cds.repackaged.audit.client.impl.Utils.OAUTH2_PLAN;
import static com.sap.cds.repackaged.audit.client.impl.Utils.PROVIDER_VALUE;
import static com.sap.cds.repackaged.audit.client.impl.Utils.SUBSCRIBER_VALUE;
import static com.sap.cds.repackaged.audit.client.impl.Utils.USER_VALUE;

import java.time.Instant;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.sap.cds.repackaged.audit.api.AuditLogMessage;
import com.sap.cds.repackaged.audit.api.exception.AuditLogNotAvailableException;
import com.sap.cds.repackaged.audit.api.exception.AuditLogWriteException;
import com.sap.xs.audit.message.ValidationError;
import com.sap.xs.audit.message.utils.JsonParserUtils;

public abstract class AuditLogMessageImpl implements AuditLogMessage {

    protected static Logger LOGGER = LoggerFactory.getLogger(AuditLogMessageImpl.class);

    private static final String ALREADY_LOGGED = "Audit message has already been logged. No changes possible.";
    protected static final String ALREADY_LOGGED_WARNING = "Audit message ignored as it has already been persisted successfully.";
    private static final String SUBSCRIBER_URL_TEMPLATE_PATH = "https://%s.%s";

    protected boolean alreadyPrepared = false;
    protected boolean alreadyLogged = false;
    protected String endpoint;
    protected T message;
    protected Instant eventTime;
    protected AuditLogMessageFactoryImpl factory;
    protected Communicator communicator;

    @Deprecated
    public AuditLogMessageImpl(AuditLogMessageFactoryImpl factory) {
        this.factory = factory;
        this.communicator = factory.getCommunicator();
    }

    public AuditLogMessageImpl(Communicator communicator) {
        this.communicator = communicator;
    }

    protected void ensureNotLogged() throws IllegalStateException {
        if (alreadyPrepared || alreadyLogged) {
            throw new IllegalStateException(ALREADY_LOGGED);
        }
    }

    public String serializeMessage() throws AuditLogWriteException {
        try {
            return JsonParserUtils.serializeMessage(message);
        } catch (JsonProcessingException e) {
            throw new AuditLogWriteException("Cannot serialize audit message " + e);
        }
    }

    protected String serializeMessage(Object message) throws AuditLogWriteException {
        try {
            return JsonParserUtils.serializeMessage(message);
        } catch (JsonProcessingException e) {
            throw new AuditLogWriteException("Cannot serialize audit message " + e);
        }
    }

    @Override
    public void log() throws AuditLogNotAvailableException, AuditLogWriteException {
        if (alreadyLogged) {
            LOGGER.warn(ALREADY_LOGGED_WARNING);
            return;
        }
        if (message.getUser() == null || USER_VALUE.equals(message.getUser())) {
            String user = Utils.getUser();
            message.setUser(user != null ? user : communicator.getClientId());
        }

        if (eventTime == null) {
            eventTime = Instant.now();
        }
        
        message.setTime(eventTime);

        try {
            validateUser(message.getUser());
            validateIdentityProvider(message.getIdentityProvider());
            validateTenant(message.getTenant());
            message.validate();
        } catch (ValidationError e) {
            throw new AuditLogWriteException("Audit log message cannot be validated. " + e.getMessage(), message.getErrors());
        }

        communicator.send(serializeMessage(), endpoint, message.getSubscriberTokenIssuer());
        alreadyLogged = true;
    }

    @Override
    public void setUser(String user) {
        ensureNotLogged();
        message.setUser(user);
    }

    @Override
    public void setIdentityProvider(String idp) {
        ensureNotLogged();
        message.setIdentityProvider(idp);
    }

    @Override
    public void setTenant(String tenant) {
        ensureNotLogged();
        message.setTenant(tenant);
    }

    @Override
    public void setTenant(String tenant, String subscriberTokenIssuer) {
        ensureNotLogged();
        message.setSubscriberTokenIssuer(subscriberTokenIssuer);
        message.setTenant(tenant);
    }

    @Override
    public void setTenantBySubscriberSubdomain(String subdomain) {
        ensureNotLogged();
        String uaaDomain = communicator.getUaaDomain();
        String subscriberTokenIssuer = String.format(SUBSCRIBER_URL_TEMPLATE_PATH, subdomain, uaaDomain);
        message.setSubscriberTokenIssuer(subscriberTokenIssuer);
        message.setTenant(SUBSCRIBER_VALUE);
    }

    @Override
    public void addCustomDetails(String key, Object value) {
        ensureNotLogged();
        message.addCustomDetails(key, value);
    }

    @Override
    public void setEventTime(Instant time) {
        this.eventTime = time;
    }

    /**
     * @deprecated Use com.sap.cds.repackaged.audit.api.AuditLogMessage.setEventTime instead
     * @param time
     */
    @Deprecated
    public void setTime(Instant time) {
        message.setTime(time);
    }

    /**
     * @deprecated The UUID is always automatically generated by the service and can't be changed.
     * @param uuid
     */

    @Deprecated
    public void setUuid(String uuid) {
        message.setUuid(uuid);
    }

    private void validateUser(String user) throws ValidationError {
        String plan = communicator.getServicePlan();
        if (OAUTH2_PLAN.equals(plan) && isUserValueInvalid(user)) {
            throw new ValidationError("The user field of the Audit log message should not be empty for the 'oauth2' scenario!");
        }
    }

    private void validateIdentityProvider(String identityProvider) throws ValidationError {
        String plan = communicator.getServicePlan();
        if (OAUTH2_PLAN.equals(plan) && isIdPValueInvalid(identityProvider)) {
            throw new ValidationError("The identityProvider field of the Audit log message is invaid for the 'oauth2' scenario!");
        }
    }

    private void validateTenant(String tenant) throws ValidationError {
        String plan = communicator.getServicePlan();
        if (OAUTH2_PLAN.equals(plan) && isTenantValueInvalid(tenant)) {
            throw new ValidationError("The tenant field of the Audit log message is invaid for the 'oauth2' scenario!");
        }
    }

    private boolean isTenantValueInvalid(String tenant) {
        return !(PROVIDER_VALUE.equals(tenant) || SUBSCRIBER_VALUE.equals(tenant));
    }

    private boolean isUserValueInvalid(String user) {
        if (user != null) {
            return user.trim()
                    .isEmpty();
        }

        return true;
    }

    private boolean isIdPValueInvalid(String identityProvider) {
        return !(identityProvider == null || IDP_VALUE.equals(identityProvider));
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy