Skip to content
Permalink
Browse files Browse the repository at this point in the history
[MAPR] Setted responses retention time on fake requests
  • Loading branch information
mapalomar committed Oct 9, 2020
1 parent 74b3b9c commit c37f816
Show file tree
Hide file tree
Showing 7 changed files with 176 additions and 0 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Expand Up @@ -4,6 +4,15 @@ All notable changes to this project will be documented in this file.

## [Unrelease]

### Added

- Setted responses retention time on fake requests
- Added aspect configuration

### Fixed

- Fixed messages in aspects.

## [1.1.2.RELEASE] - 2020-10-09

### Added
Expand Down
Expand Up @@ -133,3 +133,10 @@ application:
validation:
url: ${TAN_VALIDATION_URL:}
enabled: ${TAN_VALIDATION_ENABLED:false}
response:
retention:
enabled: ${RESPONSE_RETENTION_ENABLED:false}
time:
exposed: ${RESPONSE_RETENTION_TIME_EXPOSED:1000} # milliseconds
log:
enabled: ${LOGGABLE_ENABLED:false}
Expand Up @@ -10,6 +10,7 @@
package org.dpppt.backend.sdk.ws.controller;

import com.fasterxml.jackson.core.JsonProcessingException;

import io.jsonwebtoken.Jwts;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
Expand All @@ -20,6 +21,7 @@
import org.dpppt.backend.sdk.data.gaen.GAENDataService;
import org.dpppt.backend.sdk.model.gaen.*;
import org.dpppt.backend.sdk.ws.radarcovid.annotation.Loggable;
import org.dpppt.backend.sdk.ws.radarcovid.annotation.ResponseRetention;
import org.dpppt.backend.sdk.ws.security.ValidateRequest;
import org.dpppt.backend.sdk.ws.security.ValidateRequest.InvalidDateException;
import org.dpppt.backend.sdk.ws.security.signature.ProtoSignature;
Expand Down Expand Up @@ -100,6 +102,7 @@ public GaenController(GAENDataService dataService, FakeKeyService fakeKeyService

@PostMapping(value = "/exposed")
@Loggable
@ResponseRetention(time = "application.response.retention.time.exposed")
@Transactional
@Operation(description = "Send exposed keys to server - includes a fix for the fact that GAEN doesn't give access to the current day's exposed key")
@ApiResponses(value = {
Expand Down
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2020 Gobierno de España
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* SPDX-License-Identifier: MPL-2.0
*/
package org.dpppt.backend.sdk.ws.radarcovid.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Retention(value=RetentionPolicy.RUNTIME)
@Target(value={ElementType.CONSTRUCTOR, ElementType.METHOD})
public @interface ResponseRetention {

/**
* Environment property with response retention time, in milliseconds
*/
String time();
}
@@ -0,0 +1,89 @@
/*
* Copyright (c) 2020 Gobierno de España
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* SPDX-License-Identifier: MPL-2.0
*/
package org.dpppt.backend.sdk.ws.radarcovid.config;

import java.util.Arrays;

import org.apache.commons.lang3.math.NumberUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.dpppt.backend.sdk.ws.radarcovid.annotation.ResponseRetention;
import org.dpppt.backend.sdk.ws.radarcovid.exception.RadarCovidServerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

/**
* Aspect in charge of controlling the minimum response time of a service.
*/
@Configuration
@ConditionalOnProperty(name = "application.response.retention.enabled", havingValue = "true", matchIfMissing = true)
public class ResponseRetentionAspectConfiguration {

private static final Logger log = LoggerFactory.getLogger("org.dpppt.backend.sdk.ws.radarcovid.annotation.ResponseRetention");

@Autowired
private Environment environment;

@Aspect
@Component
public class ControllerTimeResponseControlAspect {

@Pointcut("@annotation(responseRetention)")
public void annotationPointCutDefinition(ResponseRetention responseRetention){
}

@Around("execution(@org.dpppt.backend.sdk.ws.radarcovid.annotation.ResponseRetention * *..controller..*(..)) && annotationPointCutDefinition(responseRetention)")
public Object logAround(ProceedingJoinPoint joinPoint, ResponseRetention responseRetention) throws Throwable {

log.debug("************************* INIT TIME RESPONSE CONTROL *********************************");
long start = System.currentTimeMillis();
try {
String className = joinPoint.getSignature().getDeclaringTypeName();
String methodName = joinPoint.getSignature().getName();
Object result = joinPoint.proceed();
long elapsedTime = System.currentTimeMillis() - start;
long responseRetentionTimeMillis = getTimeMillis(responseRetention.time());
log.debug("Controller : Controller {}.{} () execution time : {} ms", className, methodName, elapsedTime);
if (elapsedTime < responseRetentionTimeMillis) {
Thread.sleep(responseRetentionTimeMillis - elapsedTime);
}
elapsedTime = System.currentTimeMillis() - start;
log.debug("Controller : Controller {}.{} () NEW execution time : {} ms", className, methodName, elapsedTime);
log.debug("************************* END TIME RESPONSE CONTROL **********************************");
return result;

} catch (IllegalArgumentException e) {
log.error("Controller : Illegal argument {} in {} ()", Arrays.toString(joinPoint.getArgs()),
joinPoint.getSignature().getName());
log.debug("************************* END TIME RESPONSE CONTROL **********************************");
throw e;
}
}

private long getTimeMillis(String timeMillisString) {
String stringValue = environment.getProperty(timeMillisString);
if (NumberUtils.isCreatable(stringValue)) {
return Long.parseLong(stringValue);
} else {
throw new RadarCovidServerException(HttpStatus.INTERNAL_SERVER_ERROR,
"Invalid timeMillisString value \"" + timeMillisString + "\" - not found or cannot parse into long");
}
}
}

}
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2020 Gobierno de España
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* SPDX-License-Identifier: MPL-2.0
*/
package org.dpppt.backend.sdk.ws.radarcovid.exception;

import org.springframework.http.HttpStatus;


public class RadarCovidServerException extends RuntimeException {

private final HttpStatus httpStatus;

/**
* The Constructor for the Exception class.
*
* @param httpStatus the state of the server
* @param message the message
*/
public RadarCovidServerException(HttpStatus httpStatus, String message) {
super(message);
this.httpStatus = httpStatus;
}

public HttpStatus getHttpStatus() {
return httpStatus;
}

}
Expand Up @@ -133,3 +133,10 @@ application:
validation:
url: ${TAN_VALIDATION_URL:}
enabled: ${TAN_VALIDATION_ENABLED:false}
response:
retention:
enabled: ${RESPONSE_RETENTION_ENABLED:true}
time:
exposed: ${RESPONSE_RETENTION_TIME_EXPOSED:1000} # milliseconds
log:
enabled: ${LOGGABLE_ENABLED:true}

0 comments on commit c37f816

Please sign in to comment.