Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
Adrian
/
EjemploDAE2020
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
99e81ed9
authored
Dec 21, 2020
by
Adrian
Browse files
Options
_('Browse Files')
Download
Email Patches
Plain Diff
Añadida seguridad en la interfaz RestAPI
parent
68ee1644
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
155 additions
and
29 deletions
pom.xml
src/main/java/es/ujaen/dae/ujacoin/beans/Mapeador.java
src/main/java/es/ujaen/dae/ujacoin/beans/ServicioRestAPI.java
src/main/java/es/ujaen/dae/ujacoin/beans/ServicioSeguridad.java
src/main/java/es/ujaen/dae/ujacoin/beans/ServicioUjaBankImpl.java
src/main/java/es/ujaen/dae/ujacoin/beans/RepositorioClientes.java → src/main/java/es/ujaen/dae/ujacoin/beans/repositories/RepositorioClientes.java
src/main/java/es/ujaen/dae/ujacoin/beans/RepositorioCuentas.java → src/main/java/es/ujaen/dae/ujacoin/beans/repositories/RepositorioCuentas.java
src/main/java/es/ujaen/dae/ujacoin/beans/RepositorioMovimientos.java → src/main/java/es/ujaen/dae/ujacoin/beans/repositories/RepositorioMovimientos.java
src/main/java/es/ujaen/dae/ujacoin/beans/RepositorioTarjetas.java → src/main/java/es/ujaen/dae/ujacoin/beans/repositories/RepositorioTarjetas.java
src/main/java/es/ujaen/dae/ujacoin/entidadesDTO/ClienteDTO.java → src/main/java/es/ujaen/dae/ujacoin/entidades/DTO/ClienteDTO.java
src/main/java/es/ujaen/dae/ujacoin/entidadesDTO/CuentaDTO.java → src/main/java/es/ujaen/dae/ujacoin/entidades/DTO/CuentaDTO.java
src/main/java/es/ujaen/dae/ujacoin/entidadesDTO/MovimientoDTO.java → src/main/java/es/ujaen/dae/ujacoin/entidades/DTO/MovimientoDTO.java
src/main/java/es/ujaen/dae/ujacoin/entidadesDTO/TarjetaDTO.java → src/main/java/es/ujaen/dae/ujacoin/entidades/DTO/TarjetaDTO.java
src/main/java/es/ujaen/dae/ujacoin/interfaces/ServicioUjaBank.java
src/main/resources/application.properties
src/main/resources/ujaCoinAll.p12
pom.xml
View file @
99e81ed9
...
...
@@ -34,7 +34,6 @@
<artifactId>
sqlite-jdbc
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-web
</artifactId>
...
...
@@ -46,6 +45,11 @@
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-starter-security
</artifactId>
</dependency>
<dependency>
<groupId>
mysql
</groupId>
<artifactId>
mysql-connector-java
</artifactId>
</dependency>
...
...
src/main/java/es/ujaen/dae/ujacoin/beans/Mapeador.java
View file @
99e81ed9
...
...
@@ -8,9 +8,9 @@ package es.ujaen.dae.ujacoin.beans;
import
es.ujaen.dae.ujacoin.entidades.Cliente
;
import
es.ujaen.dae.ujacoin.entidades.Cuenta
;
import
es.ujaen.dae.ujacoin.entidades.Tarjeta
;
import
es.ujaen.dae.ujacoin.entidadesDTO.ClienteDTO
;
import
es.ujaen.dae.ujacoin.entidadesDTO.CuentaDTO
;
import
es.ujaen.dae.ujacoin.entidadesDTO.TarjetaDTO
;
import
es.ujaen.dae.ujacoin.entidades
.
DTO.ClienteDTO
;
import
es.ujaen.dae.ujacoin.entidades
.
DTO.CuentaDTO
;
import
es.ujaen.dae.ujacoin.entidades
.
DTO.TarjetaDTO
;
import
java.time.LocalDate
;
import
org.springframework.hateoas.Link
;
import
org.springframework.hateoas.server.mvc.ControllerLinkBuilder
;
...
...
@@ -34,11 +34,11 @@ public class Mapeador {
cliente
.
getClave
());
for
(
String
cuenta
:
cliente
.
getCuentasAsociadas
().
keySet
())
{
clienteDTO
.
a
ñ
adirCuenta
(
ControllerLinkBuilder
.
linkTo
(
ControllerLinkBuilder
.
methodOn
(
ServicioRestAPI
.
class
).
detalleCuenta
(
cliente
.
getDni
(),
cuenta
,
cliente
.
getClave
()
)).
withSelfRel
());
clienteDTO
.
a
ñ
adirCuenta
(
ControllerLinkBuilder
.
linkTo
(
ControllerLinkBuilder
.
methodOn
(
ServicioRestAPI
.
class
).
detalleCuenta
(
cliente
.
getDni
(),
cuenta
)).
withSelfRel
());
}
for
(
Tarjeta
tarjeta
:
cliente
.
getTarjetasAsociadas
().
values
())
{
clienteDTO
.
a
ñ
adirCuenta
(
ControllerLinkBuilder
.
linkTo
(
ControllerLinkBuilder
.
methodOn
(
ServicioRestAPI
.
class
).
detalleTarjeta
(
cliente
.
getDni
(),
tarjeta
.
getIdentificador
()
,
cliente
.
getClave
()
)).
withSelfRel
());
clienteDTO
.
a
ñ
adirCuenta
(
ControllerLinkBuilder
.
linkTo
(
ControllerLinkBuilder
.
methodOn
(
ServicioRestAPI
.
class
).
detalleTarjeta
(
cliente
.
getDni
(),
tarjeta
.
getIdentificador
())).
withSelfRel
());
}
return
clienteDTO
;
...
...
src/main/java/es/ujaen/dae/ujacoin/beans/ServicioRestAPI.java
View file @
99e81ed9
...
...
@@ -8,13 +8,16 @@ package es.ujaen.dae.ujacoin.beans;
import
es.ujaen.dae.ujacoin.entidades.Cliente
;
import
es.ujaen.dae.ujacoin.entidades.Cuenta
;
import
es.ujaen.dae.ujacoin.entidades.Tarjeta
;
import
es.ujaen.dae.ujacoin.entidadesDTO.ClienteDTO
;
import
es.ujaen.dae.ujacoin.entidadesDTO.CuentaDTO
;
import
es.ujaen.dae.ujacoin.entidadesDTO.TarjetaDTO
;
import
es.ujaen.dae.ujacoin.entidades
.
DTO.ClienteDTO
;
import
es.ujaen.dae.ujacoin.entidades
.
DTO.CuentaDTO
;
import
es.ujaen.dae.ujacoin.entidades
.
DTO.TarjetaDTO
;
import
java.util.List
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.http.HttpStatus
;
import
org.springframework.http.ResponseEntity
;
import
org.springframework.security.core.Authentication
;
import
org.springframework.security.core.context.SecurityContextHolder
;
import
org.springframework.security.core.userdetails.UserDetails
;
import
org.springframework.web.bind.annotation.GetMapping
;
import
org.springframework.web.bind.annotation.PathVariable
;
import
org.springframework.web.bind.annotation.RequestMapping
;
...
...
@@ -43,13 +46,21 @@ public class ServicioRestAPI {
}
@GetMapping
(
"/clientes/{dni}"
)
public
ResponseEntity
<
ClienteDTO
>
loginCliente
(
@PathVariable
String
dni
,
@RequestParam
(
defaultValue
=
""
)
String
pass
)
{
public
ResponseEntity
<
ClienteDTO
>
loginCliente
(
@PathVariable
String
dni
)
{
if
(
dni
!=
null
&&
""
.
equals
(
dni
)
&&
pass
!=
null
&&
""
.
equals
(
pass
)
)
{
if
(
dni
!=
null
&&
""
.
equals
(
dni
))
{
return
new
ResponseEntity
<>(
HttpStatus
.
BAD_REQUEST
);
}
Cliente
cliente
=
ujaBank
.
loginCliente
(
dni
,
pass
);
String
username
=
SecurityContextHolder
.
getContext
().
getAuthentication
().
getName
();
boolean
admin
=
SecurityContextHolder
.
getContext
().
getAuthentication
().
getAuthorities
()
.
stream
().
anyMatch
(
r
->
r
.
getAuthority
().
equals
(
"ROLE_ADMIN"
));
if
(!
admin
&&
!
username
.
equals
(
dni
))
{
return
new
ResponseEntity
<>(
HttpStatus
.
NOT_FOUND
);
}
Cliente
cliente
=
ujaBank
.
loginCliente
(
dni
);
if
(
cliente
==
null
)
{
return
new
ResponseEntity
<>(
HttpStatus
.
NOT_FOUND
);
...
...
@@ -59,14 +70,22 @@ public class ServicioRestAPI {
}
@GetMapping
(
"/
ujacoin/clientes/{dni}/cuentas/{num}
}"
)
public
ResponseEntity
<
CuentaDTO
>
detalleCuenta
(
@PathVariable
String
dni
,
@PathVariable
String
num
,
@RequestParam
(
defaultValue
=
""
)
String
pass
)
{
@GetMapping
(
"/
clientes/{dni}/cuentas/{num
}"
)
public
ResponseEntity
<
CuentaDTO
>
detalleCuenta
(
@PathVariable
String
dni
,
@PathVariable
String
num
)
{
if
(
dni
!=
null
&&
""
.
equals
(
dni
)
&&
num
!=
null
&&
""
.
equals
(
num
)
&&
pass
!=
null
&&
""
.
equals
(
pass
)
)
{
if
(
dni
!=
null
&&
""
.
equals
(
dni
)
&&
num
!=
null
&&
""
.
equals
(
num
))
{
return
new
ResponseEntity
<>(
HttpStatus
.
BAD_REQUEST
);
}
Cliente
cliente
=
ujaBank
.
loginCliente
(
dni
,
pass
);
String
username
=
SecurityContextHolder
.
getContext
().
getAuthentication
().
getName
();
boolean
admin
=
SecurityContextHolder
.
getContext
().
getAuthentication
().
getAuthorities
()
.
stream
().
anyMatch
(
r
->
r
.
getAuthority
().
equals
(
"ROLE_ADMIN"
));
if
(!
admin
&&
!
username
.
equals
(
dni
))
{
return
new
ResponseEntity
<>(
HttpStatus
.
NOT_FOUND
);
}
Cliente
cliente
=
ujaBank
.
loginCliente
(
dni
);
if
(
cliente
==
null
)
{
return
new
ResponseEntity
<>(
HttpStatus
.
FORBIDDEN
);
...
...
@@ -90,14 +109,22 @@ public class ServicioRestAPI {
}
@GetMapping
(
"/
ujacoin/clientes/{dni}/tarjetas/{num}
}"
)
public
ResponseEntity
<
TarjetaDTO
>
detalleTarjeta
(
@PathVariable
String
dni
,
@PathVariable
int
num
,
@RequestParam
(
defaultValue
=
""
)
String
pass
)
{
@GetMapping
(
"/
clientes/{dni}/tarjetas/{num
}"
)
public
ResponseEntity
<
TarjetaDTO
>
detalleTarjeta
(
@PathVariable
String
dni
,
@PathVariable
int
num
)
{
if
(
dni
!=
null
&&
""
.
equals
(
dni
)
&&
pass
!=
null
&&
""
.
equals
(
pass
)
)
{
if
(
dni
!=
null
&&
""
.
equals
(
dni
)
&&
num
>
0
)
{
return
new
ResponseEntity
<>(
HttpStatus
.
BAD_REQUEST
);
}
Cliente
cliente
=
ujaBank
.
loginCliente
(
dni
,
pass
);
String
username
=
SecurityContextHolder
.
getContext
().
getAuthentication
().
getName
();
boolean
admin
=
SecurityContextHolder
.
getContext
().
getAuthentication
().
getAuthorities
()
.
stream
().
anyMatch
(
r
->
r
.
getAuthority
().
equals
(
"ROLE_ADMIN"
));
if
(!
admin
&&
!
username
.
equals
(
dni
))
{
return
new
ResponseEntity
<>(
HttpStatus
.
NOT_FOUND
);
}
Cliente
cliente
=
ujaBank
.
loginCliente
(
dni
);
if
(
cliente
==
null
)
{
return
new
ResponseEntity
<>(
HttpStatus
.
FORBIDDEN
);
...
...
src/main/java/es/ujaen/dae/ujacoin/beans/ServicioSeguridad.java
0 → 100644
View file @
99e81ed9
/*
* 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
.
beans
;
import
javax.sql.DataSource
;
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.password.NoOpPasswordEncoder
;
import
org.springframework.security.crypto.password.PasswordEncoder
;
/**
*
* @author adria
*/
@Configuration
@EnableWebSecurity
public
class
ServicioSeguridad
extends
WebSecurityConfigurerAdapter
{
@Autowired
DataSource
dataSource
;
@Override
protected
void
configure
(
AuthenticationManagerBuilder
auth
)
throws
Exception
{
auth
.
inMemoryAuthentication
().
withUser
(
"alluque"
).
password
(
"{noop}1234qwas"
).
roles
(
"ADMIN"
);
auth
.
jdbcAuthentication
().
passwordEncoder
(
NoOpPasswordEncoder
.
getInstance
()).
dataSource
(
dataSource
)
.
usersByUsernameQuery
(
"select dni, clave, true from cliente where dni=?"
)
.
authoritiesByUsernameQuery
(
"select dni, 'USER' from cliente where dni=?"
)
.
rolePrefix
(
"ROLE_"
);
}
@Override
protected
void
configure
(
HttpSecurity
http
)
throws
Exception
{
http
.
csrf
().
disable
();
http
.
httpBasic
();
http
.
authorizeRequests
().
antMatchers
(
"/ujacoin/clientes"
).
hasRole
(
"ADMIN"
);
http
.
authorizeRequests
().
antMatchers
(
HttpMethod
.
POST
,
"/ujacoin/clientes/{dni:[a-zA-z0-9]+}/cuentas"
).
hasRole
(
"ADMIN"
);
http
.
authorizeRequests
().
antMatchers
(
HttpMethod
.
DELETE
,
"/ujacoin/clientes/{dni:[\\d+]}/cuentas/{num:[\\d+]}"
).
hasRole
(
"ADMIN"
);
http
.
authorizeRequests
().
antMatchers
(
"/ujacoin/clientes/**"
).
hasAnyRole
(
"USER"
,
"ADMIN"
);
http
.
authorizeRequests
().
antMatchers
(
"/ujacoin/enteros/**"
).
permitAll
();
http
.
authorizeRequests
().
antMatchers
(
"/**"
).
denyAll
();
}
}
src/main/java/es/ujaen/dae/ujacoin/beans/ServicioUjaBankImpl.java
View file @
99e81ed9
...
...
@@ -5,6 +5,10 @@
*/
package
es
.
ujaen
.
dae
.
ujacoin
.
beans
;
import
es.ujaen.dae.ujacoin.beans.repositories.RepositorioCuentas
;
import
es.ujaen.dae.ujacoin.beans.repositories.RepositorioClientes
;
import
es.ujaen.dae.ujacoin.beans.repositories.RepositorioMovimientos
;
import
es.ujaen.dae.ujacoin.beans.repositories.RepositorioTarjetas
;
import
es.ujaen.dae.ujacoin.entidades.Cliente
;
import
es.ujaen.dae.ujacoin.entidades.Cuenta
;
import
es.ujaen.dae.ujacoin.entidades.Tarjeta
;
...
...
@@ -14,6 +18,8 @@ import es.ujaen.dae.ujacoin.excepciones.UsuarioYaExistente;
import
es.ujaen.dae.ujacoin.interfaces.ServicioUjaBank
;
import
java.util.ArrayList
;
import
java.util.Random
;
import
javax.persistence.EntityManager
;
import
javax.persistence.PersistenceContext
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.dao.DataAccessResourceFailureException
;
import
org.springframework.dao.EmptyResultDataAccessException
;
...
...
@@ -28,6 +34,9 @@ public class ServicioUjaBankImpl implements ServicioUjaBank {
public
static
Random
rand
=
new
Random
();
@PersistenceContext
EntityManager
em
;
@Autowired
private
RepositorioClientes
repoClientes
;
...
...
@@ -74,9 +83,21 @@ public class ServicioUjaBankImpl implements ServicioUjaBank {
}
@Override
public
Cliente
loginCliente
(
String
dni
)
{
try
{
return
repoClientes
.
buscar
(
dni
);
}
catch
(
EmptyResultDataAccessException
e
)
{
return
null
;
}
}
@Override
@Transactional
public
ArrayList
<
Tarjeta
>
listaTarjetas
(
Cliente
cliente
)
{
Cliente
clienteEnlazado
=
repoClientes
.
em
.
merge
(
cliente
);
Cliente
clienteEnlazado
=
em
.
merge
(
cliente
);
return
new
ArrayList
<>(
clienteEnlazado
.
getTarjetasAsociadas
().
values
());
}
...
...
src/main/java/es/ujaen/dae/ujacoin/beans/RepositorioClientes.java
→
src/main/java/es/ujaen/dae/ujacoin/beans/
repositories/
RepositorioClientes.java
View file @
99e81ed9
...
...
@@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package
es
.
ujaen
.
dae
.
ujacoin
.
beans
;
package
es
.
ujaen
.
dae
.
ujacoin
.
beans
.
repositories
;
import
es.ujaen.dae.ujacoin.entidades.Cliente
;
import
javax.persistence.EntityManager
;
...
...
src/main/java/es/ujaen/dae/ujacoin/beans/RepositorioCuentas.java
→
src/main/java/es/ujaen/dae/ujacoin/beans/
repositories/
RepositorioCuentas.java
View file @
99e81ed9
...
...
@@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package
es
.
ujaen
.
dae
.
ujacoin
.
beans
;
package
es
.
ujaen
.
dae
.
ujacoin
.
beans
.
repositories
;
import
es.ujaen.dae.ujacoin.entidades.Cliente
;
import
es.ujaen.dae.ujacoin.entidades.Cuenta
;
...
...
src/main/java/es/ujaen/dae/ujacoin/beans/RepositorioMovimientos.java
→
src/main/java/es/ujaen/dae/ujacoin/beans/
repositories/
RepositorioMovimientos.java
View file @
99e81ed9
...
...
@@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package
es
.
ujaen
.
dae
.
ujacoin
.
beans
;
package
es
.
ujaen
.
dae
.
ujacoin
.
beans
.
repositories
;
import
es.ujaen.dae.ujacoin.entidades.Cuenta
;
import
es.ujaen.dae.ujacoin.entidades.Movimiento
;
...
...
src/main/java/es/ujaen/dae/ujacoin/beans/RepositorioTarjetas.java
→
src/main/java/es/ujaen/dae/ujacoin/beans/
repositories/
RepositorioTarjetas.java
View file @
99e81ed9
...
...
@@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package
es
.
ujaen
.
dae
.
ujacoin
.
beans
;
package
es
.
ujaen
.
dae
.
ujacoin
.
beans
.
repositories
;
import
es.ujaen.dae.ujacoin.entidades.Cliente
;
import
es.ujaen.dae.ujacoin.entidades.Tarjeta
;
...
...
src/main/java/es/ujaen/dae/ujacoin/entidadesDTO/ClienteDTO.java
→
src/main/java/es/ujaen/dae/ujacoin/entidades
/
DTO/ClienteDTO.java
View file @
99e81ed9
...
...
@@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package
es
.
ujaen
.
dae
.
ujacoin
.
entidadesDTO
;
package
es
.
ujaen
.
dae
.
ujacoin
.
entidades
.
DTO
;
import
java.time.LocalDate
;
import
java.util.ArrayList
;
...
...
src/main/java/es/ujaen/dae/ujacoin/entidadesDTO/CuentaDTO.java
→
src/main/java/es/ujaen/dae/ujacoin/entidades
/
DTO/CuentaDTO.java
View file @
99e81ed9
...
...
@@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package
es
.
ujaen
.
dae
.
ujacoin
.
entidadesDTO
;
package
es
.
ujaen
.
dae
.
ujacoin
.
entidades
.
DTO
;
import
es.ujaen.dae.ujacoin.entidades.Cliente
;
...
...
src/main/java/es/ujaen/dae/ujacoin/entidadesDTO/MovimientoDTO.java
→
src/main/java/es/ujaen/dae/ujacoin/entidades
/
DTO/MovimientoDTO.java
View file @
99e81ed9
...
...
@@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package
es
.
ujaen
.
dae
.
ujacoin
.
entidadesDTO
;
package
es
.
ujaen
.
dae
.
ujacoin
.
entidades
.
DTO
;
import
es.ujaen.dae.ujacoin.util.TipoMovimiento
;
import
java.time.LocalDateTime
;
...
...
src/main/java/es/ujaen/dae/ujacoin/entidadesDTO/TarjetaDTO.java
→
src/main/java/es/ujaen/dae/ujacoin/entidades
/
DTO/TarjetaDTO.java
View file @
99e81ed9
...
...
@@ -3,7 +3,7 @@
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package
es
.
ujaen
.
dae
.
ujacoin
.
entidadesDTO
;
package
es
.
ujaen
.
dae
.
ujacoin
.
entidades
.
DTO
;
import
java.time.LocalDate
;
import
java.util.Random
;
...
...
src/main/java/es/ujaen/dae/ujacoin/interfaces/ServicioUjaBank.java
View file @
99e81ed9
...
...
@@ -34,6 +34,14 @@ public interface ServicioUjaBank {
public
Cliente
loginCliente
(
String
dni
,
String
clave
);
/**
* Devuelve un cliente por DNI usado por REST
*
* @param dni Dni del cliente
* @return Cliente si las credenciales son válidas, Null si no
*/
public
Cliente
loginCliente
(
String
dni
);
/**
* Lista las tarjetas asociadas a un cliente
*
* @param cliente cliente
...
...
src/main/resources/application.properties
View file @
99e81ed9
...
...
@@ -6,3 +6,10 @@ spring.datasource.driver-class-name = com.mysql.cj.jdbc.Driver
spring.datasource.username
=
DAE2020G9
spring.datasource.password
=
DAE2020G9
server.port
=
8080
server.ssl.key-store
=
classpath:ujaCoinAll.p12
server.ssl.key-store-password
=
1234qwas
server.ssl.keyStoreType
=
PKCS12
server.ssl.keyAlias
=
tomcat
src/main/resources/ujaCoinAll.p12
0 → 100644
View file @
99e81ed9
No preview for this file type
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment