Commit 14aed9e0 by Antonio Rueda

Revisión de imports y creación de caché para acelerar autenticacones

parent 08da552f
## Test de carga del API REST con LOCUST
Es necesario tener python 3 y la herramienta LOCUST. Puede instalarse mediante
`pip3 install locust`.
Revisar fichero locust.py con los tests a realizar. Ejecutar `locust`
en esta carpeta desde la línea de comandos y lanzar la herramienta
web de testing en http://localhost:8089.
No preview for this file type
import time
from locust import FastHttpUser, task
from random import randint
import requests
"""
class TestCargaUjaCoin(FastHttpUser):
usuario = "23389229D"
cuenta = "2546556012"
auth_info = (usuario, "secret")
@task(4)
def leer_info_usuario(self):
self.client.get(f"/ujacoin/clientes/{self.usuario}", auth = self.auth_info)
@task(4)
def leer_info_cuenta(self):
self.client.get(f"/ujacoin/clientes/{self.usuario}/cuentas/{self.cuenta}", auth = self.auth_info)
@task(1)
def ingresar_1_euro(self):
self.client.post(f"/ujacoin/clientes/{self.usuario}/cuentas/{self.cuenta}/movimientos",
json={"tipo": "ingreso", "numTarjeta": "4111111111111111", "numCuenta": "5729089977", "importe": "1.0"}, auth = self.auth_info)
"""
class TestCargaUjaCoin(FastHttpUser):
def on_start(self):
usuario_creado = False
while not usuario_creado:
random_dni = randint(1000000, 9999999)
self.dni_usuario = f"3{random_dni}D"
self.clave_usuario = "secret"
self.auth = (self.dni_usuario, self.clave_usuario)
# Crear usuario con dni y nombre aleatorio
response = self.client.post("/ujacoin/clientes", json={
"dni": self.dni_usuario,
"nombre": f"Usuario{random_dni} España España",
"fNacimiento": "1980-01-01",
"direccion": "Av Madrid, 1 - Jaén",
"tlf": "611111111",
"email": "user@gmail.com",
"clave": self.clave_usuario
})
# En caso de éxito guardar cuenta y crear tarjeta
if response.status_code == requests.codes.created:
self.cuenta_usuario = response.json().get("num")
random_tarjeta = randint(10000000000000, 99999999999999)
self.tarjeta_usuario = f"55{random_tarjeta}"
self.client.post(f"/ujacoin/clientes/{self.dni_usuario}/tarjetas", json={
"num": self.tarjeta_usuario,
"titular": f"Usuario{random_dni} España España",
"fechaCaducidad": "2024-01-01",
"cvc": "123"
}, auth = self.auth)
usuario_creado = True
@task(5)
def leer_info_usuario(self):
self.client.get(f"/ujacoin/clientes/{self.dni_usuario}", auth = self.auth)
@task(1)
def ingresar_1_euro(self):
self.client.post(f"/ujacoin/clientes/{self.dni_usuario}/cuentas/{self.cuenta_usuario}/movimientos",
json={"tipo": "ingreso", "numTarjeta": self.tarjeta_usuario, "numCuenta": self.cuenta_usuario, "importe": "1.0"}, auth = self.auth)
@task(5)
def leer_info_cuenta(self):
self.client.get(f"/ujacoin/clientes/{self.dni_usuario}/cuentas/{self.cuenta_usuario}", auth = self.auth)
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
<properties> <properties>
<exec.vmArgs></exec.vmArgs> <exec.vmArgs></exec.vmArgs>
<exec.args>${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}</exec.args> <exec.args>${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}</exec.args>
<exec.appArgs></exec.appArgs> <exec.appArgs>-server</exec.appArgs>
<exec.mainClass>es.ujaen.dae.ujacoin.app.UjaCoinApp</exec.mainClass> <exec.mainClass>es.ujaen.dae.ujacoin.app.UjaCoinApp</exec.mainClass>
<exec.executable>java</exec.executable> <exec.executable>java</exec.executable>
</properties> </properties>
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
<properties> <properties>
<exec.vmArgs>-agentlib:jdwp=transport=dt_socket,server=n,address=${jpda.address}</exec.vmArgs> <exec.vmArgs>-agentlib:jdwp=transport=dt_socket,server=n,address=${jpda.address}</exec.vmArgs>
<exec.args>${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}</exec.args> <exec.args>${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}</exec.args>
<exec.appArgs></exec.appArgs> <exec.appArgs>-server</exec.appArgs>
<exec.mainClass>es.ujaen.dae.ujacoin.app.UjaCoinApp</exec.mainClass> <exec.mainClass>es.ujaen.dae.ujacoin.app.UjaCoinApp</exec.mainClass>
<exec.executable>java</exec.executable> <exec.executable>java</exec.executable>
<jpda.listen>true</jpda.listen> <jpda.listen>true</jpda.listen>
...@@ -56,7 +56,7 @@ ...@@ -56,7 +56,7 @@
<exec.args>${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}</exec.args> <exec.args>${exec.vmArgs} -classpath %classpath ${exec.mainClass} ${exec.appArgs}</exec.args>
<exec.mainClass>es.ujaen.dae.ujacoin.app.UjaCoinApp</exec.mainClass> <exec.mainClass>es.ujaen.dae.ujacoin.app.UjaCoinApp</exec.mainClass>
<exec.executable>java</exec.executable> <exec.executable>java</exec.executable>
<exec.appArgs></exec.appArgs> <exec.appArgs>-server</exec.appArgs>
</properties> </properties>
</action> </action>
</actions> </actions>
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.5</version> <version>2.6.1</version>
</parent> </parent>
<dependencies> <dependencies>
...@@ -31,23 +31,22 @@ ...@@ -31,23 +31,22 @@
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId> <artifactId>spring-boot-starter-undertow</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>mysql</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>mysql-connector-java</artifactId> <artifactId>spring-boot-starter-security</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency> </dependency>
<dependency> <dependency>
...@@ -66,7 +65,29 @@ ...@@ -66,7 +65,29 @@
<artifactId>junit-jupiter</artifactId> <artifactId>junit-jupiter</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<!-- <scope>test</scope> -->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
......
...@@ -3,19 +3,22 @@ package es.ujaen.dae.ujacoin.app; ...@@ -3,19 +3,22 @@ package es.ujaen.dae.ujacoin.app;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.cache.annotation.EnableCaching;
/** /**
* Clase principal * Clase principal
*
* @author ajrueda * @author ajrueda
*/ */
@SpringBootApplication(scanBasePackages={ @SpringBootApplication(scanBasePackages = {
"es.ujaen.dae.ujacoin.servicios", "es.ujaen.dae.ujacoin.servicios",
"es.ujaen.dae.ujacoin.repositorios", "es.ujaen.dae.ujacoin.repositorios",
"es.ujaen.dae.ujacoin.controladoresREST", "es.ujaen.dae.ujacoin.controladoresREST",
"es.ujaen.dae.ujacoin.seguridad" "es.ujaen.dae.ujacoin.seguridad"
}) })
@EntityScan(basePackages="es.ujaen.dae.ujacoin.entidades") @EntityScan(basePackages = "es.ujaen.dae.ujacoin.entidades")
public class UjaCoinApp { @EnableCaching
public class UjaCoinApp {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
// Creación de servidor // Creación de servidor
SpringApplication.run(UjaCoinApp.class, args); SpringApplication.run(UjaCoinApp.class, args);
......
...@@ -15,6 +15,7 @@ import es.ujaen.dae.ujacoin.entidades.movimientos.Movimiento; ...@@ -15,6 +15,7 @@ import es.ujaen.dae.ujacoin.entidades.movimientos.Movimiento;
import es.ujaen.dae.ujacoin.excepciones.ClienteNoRegistrado; import es.ujaen.dae.ujacoin.excepciones.ClienteNoRegistrado;
import es.ujaen.dae.ujacoin.excepciones.ClienteYaRegistrado; import es.ujaen.dae.ujacoin.excepciones.ClienteYaRegistrado;
import es.ujaen.dae.ujacoin.excepciones.SaldoInsuficienteParaOperacion; import es.ujaen.dae.ujacoin.excepciones.SaldoInsuficienteParaOperacion;
import es.ujaen.dae.ujacoin.excepciones.TarjetaNoRegistrada;
import es.ujaen.dae.ujacoin.excepciones.TarjetaYaRegistrada; import es.ujaen.dae.ujacoin.excepciones.TarjetaYaRegistrada;
import es.ujaen.dae.ujacoin.servicios.ServicioUjaCoin; import es.ujaen.dae.ujacoin.servicios.ServicioUjaCoin;
import java.time.LocalDateTime; import java.time.LocalDateTime;
...@@ -59,7 +60,7 @@ public class ControladorREST { ...@@ -59,7 +60,7 @@ public class ControladorREST {
@ResponseStatus(HttpStatus.NOT_FOUND) @ResponseStatus(HttpStatus.NOT_FOUND)
public void handlerClienteNoRegistrado(ClienteNoRegistrado e) { public void handlerClienteNoRegistrado(ClienteNoRegistrado e) {
} }
/** Creación de clientes */ /** Creación de clientes */
@PostMapping("/clientes") @PostMapping("/clientes")
ResponseEntity<DTOCuenta> altaCliente(@RequestBody DTOCliente cliente) { ResponseEntity<DTOCuenta> altaCliente(@RequestBody DTOCliente cliente) {
...@@ -72,6 +73,12 @@ public class ControladorREST { ...@@ -72,6 +73,12 @@ public class ControladorREST {
} }
} }
// Just for testing
@GetMapping("/clientes/hola")
String hola() {
return "Hola";
}
/** Login de clientes (temporal hasta incluir autenticación mediante Spring Security */ /** Login de clientes (temporal hasta incluir autenticación mediante Spring Security */
@GetMapping("/clientes/{dni}") @GetMapping("/clientes/{dni}")
ResponseEntity<DTOCliente> verCliente(@PathVariable String dni) { ResponseEntity<DTOCliente> verCliente(@PathVariable String dni) {
...@@ -164,6 +171,9 @@ public class ControladorREST { ...@@ -164,6 +171,9 @@ public class ControladorREST {
catch(SaldoInsuficienteParaOperacion e) { catch(SaldoInsuficienteParaOperacion e) {
return ResponseEntity.status(HttpStatus.PRECONDITION_FAILED).build(); return ResponseEntity.status(HttpStatus.PRECONDITION_FAILED).build();
} }
catch(TarjetaNoRegistrada t) {
return ResponseEntity.status(HttpStatus.FAILED_DEPENDENCY).build();
}
return ResponseEntity.status(HttpStatus.CREATED).build(); return ResponseEntity.status(HttpStatus.CREATED).build();
} }
......
/* /*
* To change this license header, choose License Headers in Project Properties. * To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates * To change this template file, choose Tools | Templates
* and open the template in the editor. * and open the template in the editor.
......
...@@ -8,8 +8,11 @@ package es.ujaen.dae.ujacoin.repositorios; ...@@ -8,8 +8,11 @@ package es.ujaen.dae.ujacoin.repositorios;
import es.ujaen.dae.ujacoin.entidades.Cliente; import es.ujaen.dae.ujacoin.entidades.Cliente;
import es.ujaen.dae.ujacoin.entidades.Tarjeta; import es.ujaen.dae.ujacoin.entidades.Tarjeta;
import java.util.Optional; import java.util.Optional;
import java.util.logging.Logger;
import javax.persistence.EntityManager; import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext; import javax.persistence.PersistenceContext;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
...@@ -24,15 +27,18 @@ public class RepositorioClientes { ...@@ -24,15 +27,18 @@ public class RepositorioClientes {
@PersistenceContext @PersistenceContext
EntityManager em; EntityManager em;
@Cacheable("clientes")
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true) @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
public Optional<Cliente> buscar(String dni) { public Optional<Cliente> buscar(String dni) {
return Optional.ofNullable(em.find(Cliente.class, dni)); return Optional.ofNullable(em.find(Cliente.class, dni));
} }
@CacheEvict(value="clientes", key = "#cliente.dni")
public void guardar(Cliente cliente) { public void guardar(Cliente cliente) {
em.persist(cliente); em.persist(cliente);
} }
@CacheEvict(value="clientes", key = "#cliente.dni")
public void nuevaTarjeta(Cliente cliente, Tarjeta tarjeta) { public void nuevaTarjeta(Cliente cliente, Tarjeta tarjeta) {
em.persist(tarjeta); em.persist(tarjeta);
...@@ -40,6 +46,7 @@ public class RepositorioClientes { ...@@ -40,6 +46,7 @@ public class RepositorioClientes {
cliente.nuevaTarjeta(tarjeta); cliente.nuevaTarjeta(tarjeta);
} }
@CacheEvict(value="clientes", key = "#cliente.dni")
public void actualizar(Cliente cliente) { public void actualizar(Cliente cliente) {
em.merge(cliente); em.merge(cliente);
} }
......
...@@ -7,6 +7,8 @@ package es.ujaen.dae.ujacoin.seguridad; ...@@ -7,6 +7,8 @@ package es.ujaen.dae.ujacoin.seguridad;
import es.ujaen.dae.ujacoin.entidades.Cliente; import es.ujaen.dae.ujacoin.entidades.Cliente;
import es.ujaen.dae.ujacoin.servicios.ServicioUjaCoin; import es.ujaen.dae.ujacoin.servicios.ServicioUjaCoin;
import java.util.Optional;
import java.util.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
......
...@@ -5,13 +5,15 @@ ...@@ -5,13 +5,15 @@
*/ */
package es.ujaen.dae.ujacoin.seguridad; package es.ujaen.dae.ujacoin.seguridad;
import es.ujaen.dae.ujacoin.util.CachedBCryptPasswordEncoder;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.config.http.SessionCreationPolicy;
/** /**
* Proveedor de datos de seguridad de UJaCoin * Proveedor de datos de seguridad de UJaCoin
...@@ -23,10 +25,14 @@ public class ServicioSeguridadUjaCoin extends WebSecurityConfigurerAdapter { ...@@ -23,10 +25,14 @@ public class ServicioSeguridadUjaCoin extends WebSecurityConfigurerAdapter {
@Autowired @Autowired
ServicioDatosCliente servicioDatosCliente; ServicioDatosCliente servicioDatosCliente;
@Autowired
CacheManager cacheManager;
@Override @Override
public void configure(AuthenticationManagerBuilder auth) throws Exception { public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(servicioDatosCliente) auth.userDetailsService(servicioDatosCliente)
.passwordEncoder(new BCryptPasswordEncoder()); .passwordEncoder(new CachedBCryptPasswordEncoder(cacheManager.getCache("claves")));
//.passwordEncoder(new BCryptPasswordEncoder());
//auth.inMemoryAuthentication() //auth.inMemoryAuthentication()
// .withUser("ujacoin").roles("CLIENTE").password("{noop}secret"); // .withUser("ujacoin").roles("CLIENTE").password("{noop}secret");
...@@ -34,13 +40,19 @@ public class ServicioSeguridadUjaCoin extends WebSecurityConfigurerAdapter { ...@@ -34,13 +40,19 @@ public class ServicioSeguridadUjaCoin extends WebSecurityConfigurerAdapter {
@Override @Override
protected void configure(HttpSecurity httpSecurity) throws Exception { protected void configure(HttpSecurity httpSecurity) throws Exception {
// Desactivar cualquier soporte de sesión
httpSecurity.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
httpSecurity.csrf().disable(); httpSecurity.csrf().disable();
// Activar seguridad HTTP Basic
httpSecurity.httpBasic(); httpSecurity.httpBasic();
// httpSecurity.authorizeRequests().antMatchers("/ujacoin/**").permitAll();
// Definir protección por URL
httpSecurity.authorizeRequests().antMatchers(HttpMethod.POST, "/ujacoin/clientes").permitAll();
httpSecurity.authorizeRequests().antMatchers(HttpMethod.POST, "/ujacoin/clientes").anonymous();
// Permitir el acceso de un cliente sólo a sus recursos asociados (datos personales, cuentas, tarjetas, etc.) // Permitir el acceso de un cliente sólo a sus recursos asociados (datos personales, cuentas, tarjetas, etc.)
httpSecurity.authorizeRequests().antMatchers("/ujacoin/clientes/{dni}/**") httpSecurity.authorizeRequests().antMatchers("/ujacoin/clientes/{dni}/**").access("hasRole('CLIENTE') and #dni == principal.username");
.access("hasRole('CLIENTE') and #dni == principal.username");
} }
} }
...@@ -25,6 +25,8 @@ import javax.validation.constraints.NotNull; ...@@ -25,6 +25,8 @@ import javax.validation.constraints.NotNull;
import javax.validation.constraints.Past; import javax.validation.constraints.Past;
import javax.validation.constraints.Positive; import javax.validation.constraints.Positive;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
...@@ -44,6 +46,9 @@ public class ServicioUjaCoin { ...@@ -44,6 +46,9 @@ public class ServicioUjaCoin {
@Autowired @Autowired
RepositorioCuentas repositorioCuentas; RepositorioCuentas repositorioCuentas;
@Autowired
CacheManager cacheManager;
public ServicioUjaCoin() { public ServicioUjaCoin() {
} }
...@@ -53,12 +58,13 @@ public class ServicioUjaCoin { ...@@ -53,12 +58,13 @@ public class ServicioUjaCoin {
* @return la cuenta asociada al cliente * @return la cuenta asociada al cliente
*/ */
public Cuenta altaCliente(@NotNull @Valid Cliente cliente) { public Cuenta altaCliente(@NotNull @Valid Cliente cliente) {
if (repositorioClientes.buscar(cliente.getDni()).isPresent()) { Optional<Cliente> test = repositorioClientes.buscar(cliente.getDni());
if (test.isPresent()) {
throw new ClienteYaRegistrado(); throw new ClienteYaRegistrado();
} }
repositorioClientes.guardar(cliente); repositorioClientes.guardar(cliente);
// Crear y registrar cuenta // Crear y registrar cuenta
Cuenta cuenta = crearCuenta(cliente); Cuenta cuenta = crearCuenta(cliente);
repositorioCuentas.guardar(cuenta); repositorioCuentas.guardar(cuenta);
...@@ -102,6 +108,7 @@ public class ServicioUjaCoin { ...@@ -102,6 +108,7 @@ public class ServicioUjaCoin {
* @param dni el DNI delcliente * @param dni el DNI delcliente
* @return la cuenta creada * @return la cuenta creada
*/ */
@CacheEvict(value="clientes", key = "#dni")
public Cuenta crearCuenta(@NotBlank String dni) { public Cuenta crearCuenta(@NotBlank String dni) {
Cliente cliente = repositorioClientes.buscar(dni).orElseThrow(ClienteNoRegistrado::new); Cliente cliente = repositorioClientes.buscar(dni).orElseThrow(ClienteNoRegistrado::new);
...@@ -117,6 +124,7 @@ public class ServicioUjaCoin { ...@@ -117,6 +124,7 @@ public class ServicioUjaCoin {
* @param tarjeta la tarjeta a registrar * @param tarjeta la tarjeta a registrar
*/ */
// @Transactional // @Transactional
@CacheEvict(value="clientes", key = "#dni")
public void registrarTarjeta(@NotBlank String dni, @NotNull @Valid Tarjeta tarjeta) { public void registrarTarjeta(@NotBlank String dni, @NotNull @Valid Tarjeta tarjeta) {
Cliente cliente = repositorioClientes.buscar(dni).orElseThrow(ClienteNoRegistrado::new); Cliente cliente = repositorioClientes.buscar(dni).orElseThrow(ClienteNoRegistrado::new);
cliente.verTarjeta(tarjeta.getNum()).ifPresent(x -> { throw new TarjetaYaRegistrada(); } ); cliente.verTarjeta(tarjeta.getNum()).ifPresent(x -> { throw new TarjetaYaRegistrada(); } );
......
/*
* Click nbfs://nbhost/SystemFileSystem/Templates/Licenses/license-default.txt to change this license
* Click nbfs://nbhost/SystemFileSystem/Templates/Classes/Class.java to edit this template
*/
package es.ujaen.dae.ujacoin.util;
import org.springframework.cache.Cache;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
*
* @author ajrueda
*/
public class CachedBCryptPasswordEncoder extends BCryptPasswordEncoder {
Cache cache;
public CachedBCryptPasswordEncoder(Cache cache) {
super();
this.cache = cache;
}
public CachedBCryptPasswordEncoder(Cache cache, int strength) {
super(strength);
this.cache = cache;
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
CharSequence cachedMatch = cache.get(encodedPassword, CharSequence.class);
if (cachedMatch != null && cachedMatch.equals(rawPassword)) {
return true;
}
boolean result = super.matches(rawPassword, encodedPassword);
if (result == true) {
cache.put(encodedPassword, rawPassword);
}
return result;
}
}
...@@ -5,4 +5,5 @@ spring.datasource.url: jdbc:h2:mem:ujacoin_test;MODE=MYSQL;DATABASE_TO_LOWER=TRU ...@@ -5,4 +5,5 @@ spring.datasource.url: jdbc:h2:mem:ujacoin_test;MODE=MYSQL;DATABASE_TO_LOWER=TRU
spring.jpa.properties.javax.persistence.schema-generation.database.action: drop-and-create spring.jpa.properties.javax.persistence.schema-generation.database.action: drop-and-create
spring.cache.type: NONE
## Fichero de configuración para UjaCoin ## Fichero de configuración para UjaCoin
spring.datasource.url: jdbc:mysql://localhost:33060/ujacoin ## MySQL local
spring.datasource.username: ujacoin # spring.datasource.url: jdbc:mysql://localhost:33060/ujacoin
spring.datasource.password: secret # spring.datasource.username: ujacoin
# spring.datasource.password: secret
## H2 embedded
spring.datasource.url: jdbc:h2:file:~/data/ujacoin;MODE=MYSQL;DATABASE_TO_LOWER=TRUE;DB_CLOSE_DELAY=-1
spring.jpa.properties.javax.persistence.schema-generation.database.action: drop-and-create spring.jpa.properties.javax.persistence.schema-generation.database.action: drop-and-create
spring.data.jpa.repositories.bootstrap-mode: default spring.data.jpa.repositories.bootstrap-mode: default
spring.jpa.open-in-view: false
#spring.cache.type: NONE
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
<cache name="clientes"
maxElementsInMemory="100"
eternal="false"
overflowToDisk="false" />
<cache name="claves"
maxElementsInMemory="100"
eternal="false"
timeToIdleSeconds="600"
timeToLiveSeconds="600"
overflowToDisk="false" />
</ehcache>
\ No newline at end of file
...@@ -13,12 +13,14 @@ import java.time.LocalDate; ...@@ -13,12 +13,14 @@ import java.time.LocalDate;
import java.util.List; import java.util.List;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import org.assertj.core.api.Assertions; import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.boot.web.server.LocalServerPort; import org.springframework.boot.web.server.LocalServerPort;
import org.springframework.cache.CacheManager;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
...@@ -39,9 +41,9 @@ public class ControladorRESTTest { ...@@ -39,9 +41,9 @@ public class ControladorRESTTest {
@Autowired @Autowired
MappingJackson2HttpMessageConverter springBootJacksonConverter; MappingJackson2HttpMessageConverter springBootJacksonConverter;
TestRestTemplate restTemplate; TestRestTemplate restTemplate;
/** /**
* Crear un TestRestTemplate para las pruebas * Crear un TestRestTemplate para las pruebas
*/ */
...@@ -53,7 +55,7 @@ public class ControladorRESTTest { ...@@ -53,7 +55,7 @@ public class ControladorRESTTest {
restTemplate = new TestRestTemplate(restTemplateBuilder); restTemplate = new TestRestTemplate(restTemplateBuilder);
} }
/** /**
* Intento de creación de un cliente inválido * Intento de creación de un cliente inválido
*/ */
......
...@@ -18,9 +18,11 @@ import java.util.concurrent.Executors; ...@@ -18,9 +18,11 @@ import java.util.concurrent.Executors;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import javax.validation.ConstraintViolationException; import javax.validation.ConstraintViolationException;
import org.assertj.core.api.Assertions; import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cache.CacheManager;
import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.MethodMode; import org.springframework.test.annotation.DirtiesContext.MethodMode;
import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ActiveProfiles;
...@@ -36,7 +38,7 @@ public class ServicioUjaCoinTest { ...@@ -36,7 +38,7 @@ public class ServicioUjaCoinTest {
@Autowired @Autowired
ServicioUjaCoin servicioUjaCoin; ServicioUjaCoin servicioUjaCoin;
@Test @Test
public void testAccesoServicioUjaCoin() { public void testAccesoServicioUjaCoin() {
Assertions.assertThat(servicioUjaCoin).isNotNull(); Assertions.assertThat(servicioUjaCoin).isNotNull();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment