Commit de6e3ef3 by Antonio Rueda

Autenticación básica HTTP mediante Spring Security para acceso al API.

parent 9e6ce320
...@@ -34,6 +34,11 @@ ...@@ -34,6 +34,11 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId> <groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId> <artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope> <scope>runtime</scope>
......
...@@ -11,7 +11,8 @@ import org.springframework.boot.autoconfigure.domain.EntityScan; ...@@ -11,7 +11,8 @@ import org.springframework.boot.autoconfigure.domain.EntityScan;
@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"
}) })
@EntityScan(basePackages="es.ujaen.dae.ujacoin.entidades") @EntityScan(basePackages="es.ujaen.dae.ujacoin.entidades")
public class UjaCoinApp { public class UjaCoinApp {
......
...@@ -74,8 +74,8 @@ public class ControladorREST { ...@@ -74,8 +74,8 @@ public class ControladorREST {
/** 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> loginCliente(@PathVariable String dni, @RequestParam String clave) { ResponseEntity<DTOCliente> verCliente(@PathVariable String dni) {
Optional<Cliente> cliente = servicios.loginCliente(dni, clave); Optional<Cliente> cliente = servicios.verCliente(dni);
return cliente return cliente
.map(c -> ResponseEntity.ok(new DTOCliente(c))) .map(c -> ResponseEntity.ok(new DTOCliente(c)))
.orElse(ResponseEntity.notFound().build()); .orElse(ResponseEntity.notFound().build());
......
package es.ujaen.dae.ujacoin.entidades; package es.ujaen.dae.ujacoin.entidades;
import es.ujaen.dae.ujacoin.util.ExprReg; import es.ujaen.dae.ujacoin.util.ExprReg;
import es.ujaen.dae.ujacoin.util.CodificadorMd5; import es.ujaen.dae.ujacoin.util.CodificadorPassword;
import java.io.Serializable; import java.io.Serializable;
import java.time.LocalDate; import java.time.LocalDate;
import java.util.ArrayList; import java.util.ArrayList;
...@@ -80,7 +80,8 @@ public class Cliente implements Serializable { ...@@ -80,7 +80,8 @@ public class Cliente implements Serializable {
this.tlf = tlf; this.tlf = tlf;
this.email = email; this.email = email;
this.clave = (clave != null ? CodificadorMd5.codificar(clave) : null); this.clave = (clave != null ? CodificadorPassword.codificar(clave) : null);
// this.clave = clave;
tarjetas = new ArrayList<>(); tarjetas = new ArrayList<>();
cuentas = new ArrayList<>(); cuentas = new ArrayList<>();
...@@ -116,7 +117,12 @@ public class Cliente implements Serializable { ...@@ -116,7 +117,12 @@ public class Cliente implements Serializable {
* @return * @return
*/ */
public boolean claveValida(String clave) { public boolean claveValida(String clave) {
return this.clave.equals(CodificadorMd5.codificar(clave)); return CodificadorPassword.igual(clave, this.clave);
//return this.clave.equals(clave);
}
public String getClave() {
return clave;
} }
/** /**
......
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package es.ujaen.dae.ujacoin.seguridad;
import es.ujaen.dae.ujacoin.entidades.Cliente;
import es.ujaen.dae.ujacoin.servicios.ServicioUjaCoin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
/**
* Servicio que proporciona los datos del cliente
* @author ajrueda
*/
@Service
public class ServicioDatosCliente implements UserDetailsService {
@Autowired
ServicioUjaCoin servicioUjaCoin;
PasswordEncoder encoder;
public ServicioDatosCliente() {
encoder = new BCryptPasswordEncoder();
}
PasswordEncoder getEncoder() {
return encoder;
}
@Override
public UserDetails loadUserByUsername(String dni) throws UsernameNotFoundException {
Cliente cliente = servicioUjaCoin.verCliente(dni)
.orElseThrow(() -> new UsernameNotFoundException(""));
return User.withUsername(cliente.getDni())
.roles("CLIENTE").password(cliente.getClave())
.build();
}
}
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package es.ujaen.dae.ujacoin.seguridad;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
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.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
/**
* Proveedor de datos de seguridad de UJaCoin
*
* @author ajrueda
*/
@Configuration
@EnableWebSecurity
public class ServicioSeguridadUjaCoin extends WebSecurityConfigurerAdapter {
@Autowired
ServicioDatosCliente servicioDatosCliente;
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(servicioDatosCliente)
.passwordEncoder(new BCryptPasswordEncoder());
// auth.inMemoryAuthentication()
// .withUser("ujacoin").roles("CLIENTE").password("{noop}secret");
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.csrf().disable();
httpSecurity.httpBasic();
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.)
httpSecurity.authorizeRequests().antMatchers("/ujacoin/clientes/{dni}/**")
.access("hasRole('CLIENTE') and #dni == principal.username");
}
}
...@@ -83,6 +83,21 @@ public class ServicioUjaCoin { ...@@ -83,6 +83,21 @@ public class ServicioUjaCoin {
} }
/** /**
* Realiza un login de un cliente
* @param dni el DNI del cliente
* @param clave la clave de acceso
* @return el objeto de la clase Cliente asociado
*/
@Transactional
public Optional<Cliente> verCliente(@NotBlank String dni) {
Optional<Cliente> clienteLogin = repositorioClientes.buscar(dni);
// Asegurarnos de que se devuelve el cliente con los datos precargados
clienteLogin.ifPresent(c -> c.verCuentas().size());
return clienteLogin;
}
/**
* Crear una cuenta adicional para el cliente * Crear una cuenta adicional para el cliente
* @param dni el DNI delcliente * @param dni el DNI delcliente
* @return la cuenta creada * @return la cuenta creada
......
package es.ujaen.dae.ujacoin.util; package es.ujaen.dae.ujacoin.util;
import java.security.MessageDigest; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
/** /**
* Codificador sencillo para contraseñas basado en Md5 (no seguro) * Codificador sencillo para contraseñas basado en Md5 (no seguro)
* @author ajrueda * @author ajrueda
*/ */
public class CodificadorMd5 { public class CodificadorPassword {
static BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
private CodificadorMd5() { private CodificadorPassword() {
} }
public static String codificar(String cadena) { public static String codificar(String cadena) {
/*
String cadenaCodificada = null; String cadenaCodificada = null;
try { try {
...@@ -25,6 +26,11 @@ public class CodificadorMd5 { ...@@ -25,6 +26,11 @@ public class CodificadorMd5 {
// No debe ocurrir puesto que MD5 es un algoritmo que existe en la // No debe ocurrir puesto que MD5 es un algoritmo que existe en la
// implementación Java estándar // implementación Java estándar
} }
return cadenaCodificada; */
return encoder.encode(cadena);
}
public static boolean igual(String password, String passwordCodificado) {
return encoder.matches(password, passwordCodificado);
} }
} }
...@@ -26,7 +26,8 @@ import org.springframework.http.ResponseEntity; ...@@ -26,7 +26,8 @@ import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
/** /**
* Test para controlador REST de clientes * Test para controlador REST de clientes
*
* @author ajrueda * @author ajrueda
*/ */
@SpringBootTest(classes = es.ujaen.dae.ujacoin.app.UjaCoinApp.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @SpringBootTest(classes = es.ujaen.dae.ujacoin.app.UjaCoinApp.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
...@@ -36,24 +37,26 @@ public class ControladorRESTTest { ...@@ -36,24 +37,26 @@ public class ControladorRESTTest {
ServicioLimpiadoBaseDatos limpiadorBaseDatos; ServicioLimpiadoBaseDatos limpiadorBaseDatos;
@LocalServerPort @LocalServerPort
int localPort; int localPort;
@Autowired @Autowired
MappingJackson2HttpMessageConverter springBootJacksonConverter; MappingJackson2HttpMessageConverter springBootJacksonConverter;
TestRestTemplate restTemplate; RestTemplateBuilder restTemplateBuilder;
/** Crear un TestRestTemplate para las pruebas */ /**
* Crear un TestRestTemplate para las pruebas
*/
@PostConstruct @PostConstruct
void crearRestTemplate() { void crearRestTemplateBuilder() {
RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder() restTemplateBuilder = new RestTemplateBuilder()
.rootUri("http://localhost:" + localPort + "/ujacoin") .rootUri("http://localhost:" + localPort + "/ujacoin")
.additionalMessageConverters(List.of(springBootJacksonConverter)); .additionalMessageConverters(List.of(springBootJacksonConverter));
}
restTemplate = new TestRestTemplate(restTemplateBuilder);
} /**
* Intento de creación de un cliente inválido
/** Intento de creación de un cliente inválido */ */
@Test @Test
public void testAltaClienteInvalido() { public void testAltaClienteInvalido() {
// Cliente con e-mail incorrecto!!! // Cliente con e-mail incorrecto!!!
...@@ -65,17 +68,20 @@ public class ControladorRESTTest { ...@@ -65,17 +68,20 @@ public class ControladorRESTTest {
"988674533", "988674533",
"jeegmail.com", "jeegmail.com",
"clave"); "clave");
TestRestTemplate restTemplate = new TestRestTemplate(restTemplateBuilder);
ResponseEntity<DTOCuenta> respuesta = restTemplate.postForEntity( ResponseEntity<DTOCuenta> respuesta = restTemplate.postForEntity(
"/clientes", "/clientes",
cliente, cliente,
DTOCuenta.class DTOCuenta.class
); );
Assertions.assertThat(respuesta.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); Assertions.assertThat(respuesta.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
} }
/** test de alta y login de cliente */ /**
* test de alta y login de cliente
*/
@Test @Test
public void testAltaYLoginClienteCuenta() { public void testAltaYLoginClienteCuenta() {
DTOCliente cliente = new DTOCliente( DTOCliente cliente = new DTOCliente(
...@@ -87,27 +93,33 @@ public class ControladorRESTTest { ...@@ -87,27 +93,33 @@ public class ControladorRESTTest {
"jee@gmail.com", "jee@gmail.com",
"clave"); "clave");
TestRestTemplate restTemplate = new TestRestTemplate(restTemplateBuilder);
ResponseEntity<DTOCuenta> respuestaAlta = restTemplate.postForEntity( ResponseEntity<DTOCuenta> respuestaAlta = restTemplate.postForEntity(
"/clientes", "/clientes",
cliente, cliente,
DTOCuenta.class DTOCuenta.class
); );
Assertions.assertThat(respuestaAlta.getStatusCode()).isEqualTo(HttpStatus.CREATED); Assertions.assertThat(respuestaAlta.getStatusCode()).isEqualTo(HttpStatus.CREATED);
ResponseEntity<DTOCliente> respuestaLogin = restTemplate.getForEntity( TestRestTemplate restTemplateAutenticado = new TestRestTemplate(restTemplateBuilder.basicAuthentication(cliente.getDni(), cliente.getClave()));
"/clientes/{dni}?clave={clave}",
DTOCliente.class, ResponseEntity<DTOCliente> respuestaLogin = restTemplateAutenticado
cliente.getDni(), cliente.getClave() .getForEntity(
); "/clientes/{dni}",
DTOCliente.class,
cliente.getDni(), cliente.getClave()
);
Assertions.assertThat(respuestaLogin.getStatusCode()).isEqualTo(HttpStatus.OK); Assertions.assertThat(respuestaLogin.getStatusCode()).isEqualTo(HttpStatus.OK);
DTOCliente clienteLogin = respuestaLogin.getBody(); DTOCliente clienteLogin = respuestaLogin.getBody();
Assertions.assertThat(clienteLogin.getDni()).isEqualTo(cliente.getDni()); Assertions.assertThat(clienteLogin.getDni()).isEqualTo(cliente.getDni());
} }
/** Creación de cuenta adicional */ /**
* Creación de cuenta adicional
*/
@Test @Test
public void testCuentaAdicional() { public void testCuentaAdicional() {
DTOCliente cliente = new DTOCliente( DTOCliente cliente = new DTOCliente(
...@@ -119,36 +131,42 @@ public class ControladorRESTTest { ...@@ -119,36 +131,42 @@ public class ControladorRESTTest {
"jee@gmail.com", "jee@gmail.com",
"clave"); "clave");
TestRestTemplate restTemplate = new TestRestTemplate(restTemplateBuilder);
restTemplate.postForEntity( restTemplate.postForEntity(
"/clientes", "/clientes",
cliente, cliente,
DTOCuenta.class DTOCuenta.class
); );
ResponseEntity<DTOCuenta> respuesta = restTemplate.postForEntity( TestRestTemplate restTemplateAutenticado = new TestRestTemplate(restTemplateBuilder.basicAuthentication(cliente.getDni(), cliente.getClave()));
"/clientes/{dni}/cuentas", ResponseEntity<DTOCuenta> respuesta = restTemplateAutenticado
null, .postForEntity(
DTOCuenta.class, "/clientes/{dni}/cuentas",
cliente.getDni() null,
); DTOCuenta.class,
cliente.getDni()
);
Assertions.assertThat(respuesta.getStatusCode()).isEqualTo(HttpStatus.CREATED); Assertions.assertThat(respuesta.getStatusCode()).isEqualTo(HttpStatus.CREATED);
DTOCuenta[] cuentas = restTemplate.getForEntity( DTOCuenta[] cuentas = restTemplateAutenticado
"/clientes/{dni}/cuentas", .getForEntity(
DTOCuenta[].class, "/clientes/{dni}/cuentas",
cliente.getDni() DTOCuenta[].class,
).getBody(); cliente.getDni()
).getBody();
Assertions.assertThat(cuentas).hasSize(2); Assertions.assertThat(cuentas).hasSize(2);
Assertions.assertThat(cuentas[0].getNum()).isNotEqualTo(cuentas[1].getNum()); Assertions.assertThat(cuentas[0].getNum()).isNotEqualTo(cuentas[1].getNum());
} }
/** Test de creación de tarjeta */ /**
* Test de creación de tarjeta
*/
@Test @Test
public void testAnadirTarjetaACliente() { public void testAnadirTarjetaACliente() {
// Registrar cliente // Registrar cliente
DTOCliente cliente = new DTOCliente( DTOCliente cliente = new DTOCliente(
"11995667D", "11995667D",
"Juan España España", "Juan España España",
LocalDate.of(1990, 11, 1), LocalDate.of(1990, 11, 1),
...@@ -157,39 +175,46 @@ public class ControladorRESTTest { ...@@ -157,39 +175,46 @@ public class ControladorRESTTest {
"jee@gmail.com", "jee@gmail.com",
"clave"); "clave");
TestRestTemplate restTemplate = new TestRestTemplate(restTemplateBuilder);
restTemplate.postForEntity("/clientes", cliente, DTOCuenta.class); restTemplate.postForEntity("/clientes", cliente, DTOCuenta.class);
DTOTarjeta tarjeta = new DTOTarjeta("4111111111111111", cliente.getNombre(), LocalDate.of(2022, 12, 1), "365"); DTOTarjeta tarjeta = new DTOTarjeta("4111111111111111", cliente.getNombre(), LocalDate.of(2022, 12, 1), "365");
ResponseEntity<DTOTarjeta> respuesta = restTemplate.postForEntity(
"/clientes/{dni}/tarjetas", TestRestTemplate restTemplateAutenticado = new TestRestTemplate(restTemplateBuilder.basicAuthentication(cliente.getDni(), cliente.getClave()));
tarjeta, ResponseEntity<DTOTarjeta> respuesta = restTemplateAutenticado
DTOTarjeta.class, .postForEntity(
cliente.getDni() "/clientes/{dni}/tarjetas",
); tarjeta,
DTOTarjeta.class,
cliente.getDni()
);
Assertions.assertThat(respuesta.getStatusCode()).isEqualTo(HttpStatus.CREATED); Assertions.assertThat(respuesta.getStatusCode()).isEqualTo(HttpStatus.CREATED);
respuesta = restTemplate.getForEntity( respuesta = restTemplateAutenticado
"/clientes/{dni}/tarjetas/{num}", .getForEntity(
DTOTarjeta.class, "/clientes/{dni}/tarjetas/{num}",
cliente.getDni(), DTOTarjeta.class,
tarjeta.getNum() cliente.getDni(),
); tarjeta.getNum()
);
Assertions.assertThat(respuesta.getStatusCode()).isEqualTo(HttpStatus.OK); Assertions.assertThat(respuesta.getStatusCode()).isEqualTo(HttpStatus.OK);
DTOTarjeta tarjetaRecibida = respuesta.getBody(); DTOTarjeta tarjetaRecibida = respuesta.getBody();
Assertions.assertThat(tarjetaRecibida.getNum()).isEqualTo(tarjeta.getNum()); Assertions.assertThat(tarjetaRecibida.getNum()).isEqualTo(tarjeta.getNum());
Assertions.assertThat(tarjetaRecibida.getTitular()).isEqualTo(tarjeta.getTitular()); Assertions.assertThat(tarjetaRecibida.getTitular()).isEqualTo(tarjeta.getTitular());
Assertions.assertThat(tarjetaRecibida.getFechaCaducidad()).isEqualTo(tarjeta.getFechaCaducidad()); Assertions.assertThat(tarjetaRecibida.getFechaCaducidad()).isEqualTo(tarjeta.getFechaCaducidad());
Assertions.assertThat(tarjetaRecibida.getCvc()).isEqualTo(tarjeta.getCvc()); Assertions.assertThat(tarjetaRecibida.getCvc()).isEqualTo(tarjeta.getCvc());
} }
/** Test de ingreso en cuenta */ /**
* Test de ingreso en cuenta
*/
@Test @Test
public void testIngreso() { public void testIngreso() {
// Registrar cliente // Registrar cliente
DTOCliente cliente = new DTOCliente( DTOCliente cliente = new DTOCliente(
"11995667D", "11995667D",
"Juan España España", "Juan España España",
LocalDate.of(1990, 11, 1), LocalDate.of(1990, 11, 1),
...@@ -197,65 +222,72 @@ public class ControladorRESTTest { ...@@ -197,65 +222,72 @@ public class ControladorRESTTest {
"988674533", "988674533",
"jee@gmail.com", "jee@gmail.com",
"clave" "clave"
); );
TestRestTemplate restTemplate = new TestRestTemplate(restTemplateBuilder);
DTOCuenta cuenta = restTemplate.postForEntity( DTOCuenta cuenta = restTemplate.postForEntity(
"/clientes", "/clientes",
cliente, cliente,
DTOCuenta.class DTOCuenta.class
).getBody(); ).getBody();
DTOTarjeta tarjeta = new DTOTarjeta( DTOTarjeta tarjeta = new DTOTarjeta(
"4111111111111111", "4111111111111111",
cliente.getNombre(), cliente.getNombre(),
LocalDate.of(2022, 12, 1), LocalDate.of(2022, 12, 1),
"365" "365"
); );
restTemplate.postForEntity( TestRestTemplate restTemplateAutenticado = new TestRestTemplate(restTemplateBuilder.basicAuthentication(cliente.getDni(), cliente.getClave()));
"/clientes/{dni}/tarjetas", restTemplateAutenticado
tarjeta, .postForEntity(
DTOTarjeta.class, "/clientes/{dni}/tarjetas",
cliente.getDni() tarjeta,
); DTOTarjeta.class,
cliente.getDni()
);
// Realizar ingreso y comprobar estado de la cuenta // Realizar ingreso y comprobar estado de la cuenta
DTOMovimiento ingreso = DTOMovimiento.ingreso(tarjeta.getNum(), 1000); DTOMovimiento ingreso = DTOMovimiento.ingreso(tarjeta.getNum(), 1000);
ResponseEntity<Void> respuestaRegistroMovimiento = restTemplate.postForEntity( ResponseEntity<Void> respuestaRegistroMovimiento = restTemplateAutenticado
"/clientes/{dni}/cuentas/{num}/movimientos", .postForEntity(
ingreso, "/clientes/{dni}/cuentas/{num}/movimientos",
Void.class, ingreso,
cliente.getDni(), cuenta.getNum() Void.class,
); cliente.getDni(), cuenta.getNum()
);
Assertions.assertThat(respuestaRegistroMovimiento.getStatusCode()).isEqualTo(HttpStatus.CREATED); Assertions.assertThat(respuestaRegistroMovimiento.getStatusCode()).isEqualTo(HttpStatus.CREATED);
// Refrescar estado de la cuenta y comprobar saldo // Refrescar estado de la cuenta y comprobar saldo
cuenta = restTemplate.getForObject("/clientes/{dni}/cuentas/{num}", cuenta = restTemplateAutenticado
DTOCuenta.class, .getForObject("/clientes/{dni}/cuentas/{num}",
cliente.getDni(), cuenta.getNum()); DTOCuenta.class,
cliente.getDni(), cuenta.getNum());
Assertions.assertThat(cuenta.getSaldo()).isEqualTo(1000); Assertions.assertThat(cuenta.getSaldo()).isEqualTo(1000);
ResponseEntity<DTOMovimiento[]> respuestaListadoMovimientos = restTemplate.getForEntity( ResponseEntity<DTOMovimiento[]> respuestaListadoMovimientos = restTemplateAutenticado
"/clientes/{dni}/cuentas/{num}/movimientos", .getForEntity(
DTOMovimiento[].class, "/clientes/{dni}/cuentas/{num}/movimientos",
cliente.getDni(), cuenta.getNum() DTOMovimiento[].class,
); cliente.getDni(), cuenta.getNum()
);
DTOMovimiento[] movimientos = respuestaListadoMovimientos.getBody(); DTOMovimiento[] movimientos = respuestaListadoMovimientos.getBody();
Assertions.assertThat(movimientos).hasSize(1); Assertions.assertThat(movimientos).hasSize(1);
Assertions.assertThat(movimientos[0].getTipo()).isEqualTo(DTOMovimiento.INGRESO); Assertions.assertThat(movimientos[0].getTipo()).isEqualTo(DTOMovimiento.INGRESO);
Assertions.assertThat(movimientos[0].getImporte()).isEqualTo(ingreso.getImporte()); Assertions.assertThat(movimientos[0].getImporte()).isEqualTo(ingreso.getImporte());
} }
/** Test de transferencia entre cuentas */ /**
* Test de transferencia entre cuentas
*/
@Test @Test
public void testTransferencia() { public void testTransferencia() {
// Registrar cliente // Registrar cliente
DTOCliente cliente = new DTOCliente( DTOCliente cliente = new DTOCliente(
"11995667D", "11995667D",
"Juan España España", "Juan España España",
LocalDate.of(1990, 11, 1), LocalDate.of(1990, 11, 1),
...@@ -263,37 +295,39 @@ public class ControladorRESTTest { ...@@ -263,37 +295,39 @@ public class ControladorRESTTest {
"988674533", "988674533",
"jee@gmail.com", "jee@gmail.com",
"clave" "clave"
); );
TestRestTemplate restTemplate = new TestRestTemplate(restTemplateBuilder);
DTOCuenta cuentaOrigen = restTemplate.postForEntity( DTOCuenta cuentaOrigen = restTemplate.postForEntity(
"/clientes", "/clientes",
cliente, cliente,
DTOCuenta.class DTOCuenta.class
).getBody(); ).getBody();
DTOTarjeta tarjeta = new DTOTarjeta( DTOTarjeta tarjeta = new DTOTarjeta(
"4111111111111111", "4111111111111111",
cliente.getNombre(), cliente.getNombre(),
LocalDate.of(2022, 12, 1), LocalDate.of(2022, 12, 1),
"365" "365"
); );
restTemplate.postForEntity( TestRestTemplate restTemplateAutenticado1 = new TestRestTemplate(restTemplateBuilder.basicAuthentication(cliente.getDni(), cliente.getClave()));
"/clientes/{dni}/tarjetas", restTemplateAutenticado1.postForEntity(
tarjeta, "/clientes/{dni}/tarjetas",
DTOTarjeta.class, tarjeta,
DTOTarjeta.class,
cliente.getDni() cliente.getDni()
); );
// Realizar ingreso y comprobar estado de la cuenta // Realizar ingreso y comprobar estado de la cuenta
DTOMovimiento ingreso = DTOMovimiento.ingreso(tarjeta.getNum(), 1000); DTOMovimiento ingreso = DTOMovimiento.ingreso(tarjeta.getNum(), 1000);
restTemplate.postForEntity( restTemplateAutenticado1.postForEntity(
"/clientes/{dni}/cuentas/{num}/movimientos", "/clientes/{dni}/cuentas/{num}/movimientos",
ingreso, ingreso,
Void.class, Void.class,
cliente.getDni(), cuentaOrigen.getNum() cliente.getDni(), cuentaOrigen.getNum()
); );
// Crear segundo cliente // Crear segundo cliente
DTOCliente cliente2 = new DTOCliente( DTOCliente cliente2 = new DTOCliente(
"99207668E", "99207668E",
...@@ -302,61 +336,65 @@ public class ControladorRESTTest { ...@@ -302,61 +336,65 @@ public class ControladorRESTTest {
"Cl La Paz, 20 - Jaén", "Cl La Paz, 20 - Jaén",
"670701570", "670701570",
"pjj@gmail.com", "pjj@gmail.com",
"clavezzz"); "clavezzz"
);
DTOCuenta cuentaDestino = restTemplate.postForEntity( DTOCuenta cuentaDestino = restTemplate.postForEntity(
"/clientes", "/clientes",
cliente2, cliente2,
DTOCuenta.class DTOCuenta.class
).getBody(); ).getBody();
// Realizar transferencia // Realizar transferencia
DTOMovimiento transferencia = DTOMovimiento.transferencia(cuentaDestino.getNum(), 500); DTOMovimiento transferencia = DTOMovimiento.transferencia(cuentaDestino.getNum(), 500);
restTemplate.postForEntity( restTemplateAutenticado1.postForEntity(
"/clientes/{dni}/cuentas/{num}/movimientos", "/clientes/{dni}/cuentas/{num}/movimientos",
transferencia, transferencia,
Void.class, Void.class,
cliente.getDni(), cuentaOrigen.getNum() cliente.getDni(), cuentaOrigen.getNum()
); );
// Refrescar cuenta origen y destino // Refrescar cuenta origen y destino
// Refrescar estados de la cuentas y comprobar saldos // Refrescar estados de la cuentas y comprobar saldos
cuentaOrigen = restTemplate.getForObject("/clientes/{dni}/cuentas/{num}", cuentaOrigen = restTemplateAutenticado1.getForObject("/clientes/{dni}/cuentas/{num}",
DTOCuenta.class, DTOCuenta.class,
cliente.getDni(), cuentaOrigen.getNum()); cliente.getDni(), cuentaOrigen.getNum());
Assertions.assertThat(cuentaOrigen.getSaldo()).isEqualTo(500); Assertions.assertThat(cuentaOrigen.getSaldo()).isEqualTo(500);
cuentaDestino = restTemplate.getForObject("/clientes/{dni}/cuentas/{num}", TestRestTemplate restTemplateAutenticado2 = new TestRestTemplate(restTemplateBuilder.basicAuthentication(cliente2.getDni(), cliente2.getClave()));
DTOCuenta.class, cuentaDestino = restTemplateAutenticado2.getForObject("/clientes/{dni}/cuentas/{num}",
DTOCuenta.class,
cliente2.getDni(), cuentaDestino.getNum()); cliente2.getDni(), cuentaDestino.getNum());
Assertions.assertThat(cuentaDestino.getSaldo()).isEqualTo(500); Assertions.assertThat(cuentaDestino.getSaldo()).isEqualTo(500);
// Listar movimientos de la cuenta origen // Listar movimientos de la cuenta origen
DTOMovimiento[] movimientos = restTemplate.getForEntity( DTOMovimiento[] movimientos = restTemplateAutenticado1.getForEntity(
"/clientes/{dni}/cuentas/{num}/movimientos", "/clientes/{dni}/cuentas/{num}/movimientos",
DTOMovimiento[].class, DTOMovimiento[].class,
cliente.getDni(), cuentaOrigen.getNum() cliente.getDni(), cuentaOrigen.getNum()
).getBody(); ).getBody();
Assertions.assertThat(movimientos).hasSize(2); Assertions.assertThat(movimientos).hasSize(2);
Assertions.assertThat(movimientos[1].getTipo()).isEqualTo(DTOMovimiento.TRANSFERENCIA_EMITIDA); Assertions.assertThat(movimientos[1].getTipo()).isEqualTo(DTOMovimiento.TRANSFERENCIA_EMITIDA);
// Listar movimientos de la cuenta destino // Listar movimientos de la cuenta destino
movimientos = restTemplate.getForEntity( movimientos = restTemplateAutenticado2.getForEntity(
"/clientes/{dni}/cuentas/{num}/movimientos", "/clientes/{dni}/cuentas/{num}/movimientos",
DTOMovimiento[].class, DTOMovimiento[].class,
cliente2.getDni(), cuentaDestino.getNum() cliente2.getDni(), cuentaDestino.getNum()
).getBody(); ).getBody();
Assertions.assertThat(movimientos).hasSize(1); Assertions.assertThat(movimientos).hasSize(1);
Assertions.assertThat(movimientos[0].getTipo()).isEqualTo(DTOMovimiento.TRANSFERENCIA_RECIBIDA); Assertions.assertThat(movimientos[0].getTipo()).isEqualTo(DTOMovimiento.TRANSFERENCIA_RECIBIDA);
} }
/** Reintegro sin saldo suficiente */ /**
* Reintegro sin saldo suficiente
*/
@Test @Test
public void testReintegroSinSaldo() { public void testReintegroSinSaldo() {
// Registrar cliente // Registrar cliente
DTOCliente cliente = new DTOCliente( DTOCliente cliente = new DTOCliente(
"11995667D", "11995667D",
"Juan España España", "Juan España España",
LocalDate.of(1990, 11, 1), LocalDate.of(1990, 11, 1),
...@@ -364,64 +402,68 @@ public class ControladorRESTTest { ...@@ -364,64 +402,68 @@ public class ControladorRESTTest {
"988674533", "988674533",
"jee@gmail.com", "jee@gmail.com",
"clave" "clave"
); );
TestRestTemplate restTemplate = new TestRestTemplate(restTemplateBuilder);
DTOCuenta cuenta = restTemplate.postForEntity( DTOCuenta cuenta = restTemplate.postForEntity(
"/clientes", "/clientes",
cliente, cliente,
DTOCuenta.class DTOCuenta.class
).getBody(); ).getBody();
DTOTarjeta tarjeta = new DTOTarjeta( DTOTarjeta tarjeta = new DTOTarjeta(
"4111111111111111", "4111111111111111",
cliente.getNombre(), cliente.getNombre(),
LocalDate.of(2022, 12, 1), LocalDate.of(2022, 12, 1),
"365" "365"
); );
restTemplate.postForEntity( TestRestTemplate restTemplateAutenticado = new TestRestTemplate(restTemplateBuilder.basicAuthentication(cliente.getDni(), cliente.getClave()));
"/clientes/{dni}/tarjetas", restTemplateAutenticado.postForEntity(
tarjeta, "/clientes/{dni}/tarjetas",
DTOTarjeta.class, tarjeta,
DTOTarjeta.class,
cliente.getDni() cliente.getDni()
); );
// Realizar ingreso en cuenta // Realizar ingreso en cuenta
DTOMovimiento ingreso = DTOMovimiento.ingreso(tarjeta.getNum(), 1000); DTOMovimiento ingreso = DTOMovimiento.ingreso(tarjeta.getNum(), 1000);
restTemplate.postForEntity( restTemplateAutenticado.postForEntity(
"/clientes/{dni}/cuentas/{num}/movimientos", "/clientes/{dni}/cuentas/{num}/movimientos",
ingreso, ingreso,
Void.class, Void.class,
cliente.getDni(), cuenta.getNum() cliente.getDni(), cuenta.getNum()
); );
// Primer reintegro correcto // Primer reintegro correcto
DTOMovimiento reintegro = DTOMovimiento.reintegro(tarjeta.getNum(), 1000); DTOMovimiento reintegro = DTOMovimiento.reintegro(tarjeta.getNum(), 1000);
ResponseEntity<Void> respuesta = restTemplate.postForEntity( ResponseEntity<Void> respuesta = restTemplateAutenticado.postForEntity(
"/clientes/{dni}/cuentas/{num}/movimientos", "/clientes/{dni}/cuentas/{num}/movimientos",
reintegro, reintegro,
Void.class, Void.class,
cliente.getDni(), cuenta.getNum() cliente.getDni(), cuenta.getNum()
); );
Assertions.assertThat(respuesta.getStatusCode()).isEqualTo(HttpStatus.CREATED); Assertions.assertThat(respuesta.getStatusCode()).isEqualTo(HttpStatus.CREATED);
// No hay saldo suficiente para el segundo reintegro // No hay saldo suficiente para el segundo reintegro
respuesta = restTemplate.postForEntity( respuesta = restTemplateAutenticado.postForEntity(
"/clientes/{dni}/cuentas/{num}/movimientos", "/clientes/{dni}/cuentas/{num}/movimientos",
reintegro, reintegro,
Void.class, Void.class,
cliente.getDni(), cuenta.getNum() cliente.getDni(), cuenta.getNum()
); );
Assertions.assertThat(respuesta.getStatusCode()).isEqualTo(HttpStatus.PRECONDITION_FAILED);
} Assertions.assertThat(respuesta.getStatusCode()).isEqualTo(HttpStatus.PRECONDITION_FAILED);
}
/** Test de listado de movimientos con paginación */
/**
* Test de listado de movimientos con paginación
*/
@Test @Test
public void testListadoMovimientosPaginado() { public void testListadoMovimientosPaginado() {
// Registrar cliente // Registrar cliente
DTOCliente cliente = new DTOCliente( DTOCliente cliente = new DTOCliente(
"11995667D", "11995667D",
"Juan España España", "Juan España España",
LocalDate.of(1990, 11, 1), LocalDate.of(1990, 11, 1),
...@@ -429,82 +471,83 @@ public class ControladorRESTTest { ...@@ -429,82 +471,83 @@ public class ControladorRESTTest {
"988674533", "988674533",
"jee@gmail.com", "jee@gmail.com",
"clave" "clave"
); );
TestRestTemplate restTemplate = new TestRestTemplate(restTemplateBuilder);
DTOCuenta cuenta = restTemplate.postForEntity( DTOCuenta cuenta = restTemplate.postForEntity(
"/clientes", "/clientes",
cliente, cliente,
DTOCuenta.class DTOCuenta.class
).getBody(); ).getBody();
DTOTarjeta tarjeta = new DTOTarjeta( DTOTarjeta tarjeta = new DTOTarjeta(
"4111111111111111", "4111111111111111",
cliente.getNombre(), cliente.getNombre(),
LocalDate.of(2022, 12, 1), LocalDate.of(2022, 12, 1),
"365" "365"
); );
restTemplate.postForEntity( TestRestTemplate restTemplateAutenticado = new TestRestTemplate(restTemplateBuilder.basicAuthentication(cliente.getDni(), cliente.getClave()));
"/clientes/{dni}/tarjetas", restTemplateAutenticado.postForEntity(
tarjeta, "/clientes/{dni}/tarjetas",
DTOTarjeta.class, tarjeta,
DTOTarjeta.class,
cliente.getDni() cliente.getDni()
); );
// Realizar ingreso en cuenta // Realizar ingreso en cuenta
DTOMovimiento ingreso = DTOMovimiento.ingreso(tarjeta.getNum(), 1000); DTOMovimiento ingreso = DTOMovimiento.ingreso(tarjeta.getNum(), 1000);
float[] importeIngresos = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120}; float[] importeIngresos = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120};
for (float importe: importeIngresos) { for (float importe : importeIngresos) {
restTemplate.postForEntity( restTemplateAutenticado.postForEntity(
"/clientes/{dni}/cuentas/{num}/movimientos", "/clientes/{dni}/cuentas/{num}/movimientos",
DTOMovimiento.ingreso(tarjeta.getNum(), importe), DTOMovimiento.ingreso(tarjeta.getNum(), importe),
Void.class, Void.class,
cliente.getDni(), cuenta.getNum() cliente.getDni(), cuenta.getNum()
); );
} }
// Obtener primera página (10 elementos) // Obtener primera página (10 elementos)
ResponseEntity<DTOMovimiento[]> respuesta1 = restTemplate.getForEntity( ResponseEntity<DTOMovimiento[]> respuesta1 = restTemplateAutenticado.getForEntity(
"/clientes/{dni}/cuentas/{num}/movimientos", "/clientes/{dni}/cuentas/{num}/movimientos",
DTOMovimiento[].class, DTOMovimiento[].class,
cliente.getDni(), cuenta.getNum() cliente.getDni(), cuenta.getNum()
); );
DTOMovimiento[] movimientos = respuesta1.getBody(); DTOMovimiento[] movimientos = respuesta1.getBody();
Assertions.assertThat(movimientos).hasSize(10); Assertions.assertThat(movimientos).hasSize(10);
Assertions.assertThat(movimientos[0].getImporte()).isEqualTo(10); Assertions.assertThat(movimientos[0].getImporte()).isEqualTo(10);
// Obtener segunda página (2 selementos) // Obtener segunda página (2 selementos)
ResponseEntity<DTOMovimiento[]> respuesta2 = restTemplate.getForEntity( ResponseEntity<DTOMovimiento[]> respuesta2 = restTemplateAutenticado.getForEntity(
"/clientes/{dni}/cuentas/{num}/movimientos?pag=2", "/clientes/{dni}/cuentas/{num}/movimientos?pag=2",
DTOMovimiento[].class, DTOMovimiento[].class,
cliente.getDni(), cuenta.getNum() cliente.getDni(), cuenta.getNum()
); );
movimientos = respuesta2.getBody(); movimientos = respuesta2.getBody();
Assertions.assertThat(movimientos).hasSize(2); Assertions.assertThat(movimientos).hasSize(2);
Assertions.assertThat(movimientos[0].getImporte()).isEqualTo(110); Assertions.assertThat(movimientos[0].getImporte()).isEqualTo(110);
// Obtener primera página con 5 elementos solo // Obtener primera página con 5 elementos solo
ResponseEntity<DTOMovimiento[]> respuesta3 = restTemplate.getForEntity( ResponseEntity<DTOMovimiento[]> respuesta3 = restTemplateAutenticado.getForEntity(
"/clientes/{dni}/cuentas/{num}/movimientos?pag=1&num=5", "/clientes/{dni}/cuentas/{num}/movimientos?pag=1&num=5",
DTOMovimiento[].class, DTOMovimiento[].class,
cliente.getDni(), cuenta.getNum() cliente.getDni(), cuenta.getNum()
); );
movimientos = respuesta3.getBody(); movimientos = respuesta3.getBody();
Assertions.assertThat(movimientos).hasSize(5); Assertions.assertThat(movimientos).hasSize(5);
Assertions.assertThat(movimientos[0].getImporte()).isEqualTo(10); Assertions.assertThat(movimientos[0].getImporte()).isEqualTo(10);
} }
@BeforeEach @BeforeEach
void limpiarBaseDatos() { void limpiarBaseDatos() {
limpiadorBaseDatos.limpiar(); limpiadorBaseDatos.limpiar();
} }
} }
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