2023-11-19 19:26:59 +01:00
|
|
|
package BurguillosInfo::Controller::UserConquer;
|
|
|
|
|
|
|
|
use v5.34.1;
|
|
|
|
|
|
|
|
use strict;
|
|
|
|
use warnings;
|
|
|
|
|
|
|
|
use utf8;
|
|
|
|
|
|
|
|
use Mojo::Base 'Mojolicious::Controller', '-signatures';
|
|
|
|
|
|
|
|
use UUID::URandom qw/create_uuid_string/;
|
|
|
|
use Crypt::Bcrypt qw/bcrypt bcrypt_check/;
|
|
|
|
use Crypt::URandom qw/urandom/;
|
2023-11-19 23:14:02 +01:00
|
|
|
use JSON;
|
2023-11-19 19:26:59 +01:00
|
|
|
|
|
|
|
use BurguillosInfo::Schema;
|
|
|
|
|
|
|
|
my $username_minimum_chars = 3;
|
|
|
|
my $username_maximum_chars = 15;
|
|
|
|
my $password_minimum_chars = 8;
|
|
|
|
my $password_maximum_chars = 4096;
|
|
|
|
|
2023-12-31 20:43:53 +01:00
|
|
|
sub get_self ($self) {
|
2023-11-20 20:20:04 +01:00
|
|
|
my $user = $self->current_user;
|
2023-12-31 20:43:53 +01:00
|
|
|
if ( !defined $user ) {
|
|
|
|
return $self->_renderError( 401, 'No estás loggeado.' );
|
2023-11-20 20:20:04 +01:00
|
|
|
}
|
2023-12-31 20:43:53 +01:00
|
|
|
return $self->render( json => $user->serialize_to_owner, status => 200 );
|
2023-11-20 20:20:04 +01:00
|
|
|
}
|
|
|
|
|
2023-11-19 19:26:59 +01:00
|
|
|
sub create ($self) {
|
2023-11-19 23:14:02 +01:00
|
|
|
my $input = $self->_expectJson;
|
|
|
|
if ( !defined $input ) {
|
|
|
|
return;
|
2023-11-19 19:26:59 +01:00
|
|
|
}
|
|
|
|
my $username = $input->{username};
|
|
|
|
my $password = $input->{password};
|
|
|
|
my $repeat_password = $input->{repeat_password};
|
|
|
|
return
|
|
|
|
unless $self->_createCheckInput( $username, $password, $repeat_password );
|
2023-11-19 23:14:02 +01:00
|
|
|
return $self->_createUser( $username, $password );
|
|
|
|
}
|
|
|
|
|
|
|
|
sub _expectJson ($self) {
|
|
|
|
my $input;
|
|
|
|
eval { $input = $self->req->json; };
|
|
|
|
if ($@) {
|
|
|
|
say STDERR $@;
|
2023-12-31 20:43:53 +01:00
|
|
|
$self->_renderError( 400, 'Se esperaba JSON.' );
|
2023-11-19 23:14:02 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
return $input;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub login ($self) {
|
|
|
|
my $input = $self->_expectJson;
|
|
|
|
if ( !defined $input ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
my $username = $input->{username};
|
|
|
|
my $password = $input->{password};
|
|
|
|
|
|
|
|
my $resultset_conquer_user =
|
|
|
|
BurguillosInfo::Schema->Schema->resultset('ConquerUser');
|
|
|
|
my @tentative_users =
|
|
|
|
$resultset_conquer_user->search( { username => $username } );
|
|
|
|
my $tentative_user = $tentative_users[0];
|
2023-12-31 20:43:53 +01:00
|
|
|
if ( !defined $tentative_user ) {
|
|
|
|
$self->_renderError( 401, 'El usuario especificado no existe.' );
|
2023-11-19 23:14:02 +01:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ( !bcrypt_check( $password, $tentative_user->encrypted_password ) ) {
|
|
|
|
$self->_renderError( 401, 'Contraseña incorrecta.' );
|
|
|
|
return;
|
|
|
|
}
|
2023-11-20 20:20:04 +01:00
|
|
|
my $user = $tentative_user;
|
|
|
|
$self->set_current_user($user);
|
2023-11-19 23:14:02 +01:00
|
|
|
$self->render(
|
|
|
|
json => {
|
|
|
|
success => $JSON::true
|
|
|
|
},
|
|
|
|
status => 200
|
|
|
|
);
|
2023-11-19 19:26:59 +01:00
|
|
|
}
|
|
|
|
|
2023-12-31 20:43:53 +01:00
|
|
|
sub setCoordinates ($self) {
|
|
|
|
my $input = $self->_expectJson;
|
|
|
|
my $user = $self->current_user;
|
|
|
|
if ( !defined $user ) {
|
|
|
|
return $self->render(
|
|
|
|
status => 401,
|
|
|
|
json => {
|
|
|
|
error => 'Debes estar loggeado para cambiar tus'
|
|
|
|
. ' coordenadas.',
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if ( !defined $input ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ( ref $input ne 'ARRAY' && scalar $input->@* == 2 ) {
|
|
|
|
return $self->render(
|
|
|
|
status => 400,
|
|
|
|
json => {
|
|
|
|
error => 'Mal formato de coordenadas, debe ser '
|
|
|
|
. 'un array de exactamente 2 números reales.',
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
$user->coordinates($input);
|
|
|
|
$user->update;
|
|
|
|
return $self->render(
|
|
|
|
status => 200,
|
|
|
|
json => {
|
|
|
|
ok => $JSON::true,
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-11-19 19:26:59 +01:00
|
|
|
sub _createUser ( $self, $username, $password ) {
|
|
|
|
my $user;
|
|
|
|
my $uuid = create_uuid_string();
|
|
|
|
my $new_salt = urandom(16);
|
|
|
|
my $encrypted_password = bcrypt $password, '2b', 12, $new_salt;
|
|
|
|
eval {
|
|
|
|
$user = BurguillosInfo::Schema->Schema->resultset('ConquerUser')->new(
|
|
|
|
{
|
|
|
|
uuid => $uuid,
|
|
|
|
encrypted_password => $encrypted_password,
|
|
|
|
username => $username
|
|
|
|
}
|
|
|
|
);
|
2023-12-31 20:43:53 +01:00
|
|
|
$user->coordinates( [ 0, 0 ] );
|
2023-11-19 19:26:59 +01:00
|
|
|
$user->insert;
|
|
|
|
};
|
|
|
|
if ($@) {
|
|
|
|
if ( $@ =~ /Key \((.*?)\)=\((.*?)\) already exists\./ ) {
|
2023-11-19 23:14:02 +01:00
|
|
|
return $self->_renderError( 400,
|
|
|
|
"La clave $1 ($2) ya existe en la base de datos.",
|
2023-11-19 19:26:59 +01:00
|
|
|
);
|
|
|
|
}
|
|
|
|
say STDERR $@;
|
2023-11-19 23:14:02 +01:00
|
|
|
return $self->_renderError( 400,
|
2023-11-19 19:26:59 +01:00
|
|
|
'No se pudo crear el usuario por razones desconocidas.' );
|
|
|
|
}
|
2023-11-19 23:14:02 +01:00
|
|
|
$self->render( status => 200, json => $user->serialize_to_owner );
|
2023-11-19 19:26:59 +01:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2023-11-19 23:14:02 +01:00
|
|
|
sub _renderError ( $self, $status, $message ) {
|
2023-11-19 19:26:59 +01:00
|
|
|
$self->render( status => $status, json => { error => $message } );
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub _createCheckInput ( $self, $username, $password, $repeat_password ) {
|
|
|
|
if ( !defined $username
|
|
|
|
|| $username !~
|
|
|
|
/^(?:\w|\d|[ÑÁÉÍÓÚñáéíóú ]){$username_minimum_chars,$username_maximum_chars}$/
|
|
|
|
)
|
|
|
|
{
|
2023-11-19 23:14:02 +01:00
|
|
|
return $self->_renderError( 400,
|
2023-11-19 19:26:59 +01:00
|
|
|
"Username invalido, las reglas son tamaño entre $username_minimum_chars y $username_maximum_chars"
|
|
|
|
. ' carácteres y solo se podrán usar letras, números y espacios.'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if ( !defined $password
|
|
|
|
|| $password eq $username
|
|
|
|
|| $password !~ /^.{$password_minimum_chars,$password_maximum_chars}$/
|
|
|
|
|| $password =~ /^\d+$/ )
|
|
|
|
{
|
2023-11-19 23:14:02 +01:00
|
|
|
return $self->_renderError(
|
2023-11-19 19:26:59 +01:00
|
|
|
400,
|
|
|
|
'Contraseña invalida, las reglas son la contraseña debe ser'
|
|
|
|
. ' distinta al nombre de usuario, la contraseña debe tener entre'
|
|
|
|
. " $password_minimum_chars y $password_maximum_chars carácteres"
|
|
|
|
. ' (Tu contraseña no se guardará en texto plano, el límite de'
|
|
|
|
. " $password_maximum_chars caracteres es para evitar denegaciones"
|
|
|
|
. ' de servicio), la contraseña no puede estar compuesta solo de números.',
|
|
|
|
);
|
|
|
|
}
|
|
|
|
if ( !defined $repeat_password || $password ne $repeat_password ) {
|
2023-11-19 23:14:02 +01:00
|
|
|
$self->_renderError(
|
2023-11-19 19:26:59 +01:00
|
|
|
400,
|
|
|
|
'El campo de repetir contraseña debe coincidir de forma'
|
|
|
|
. ' totalmente exacta con el campo de contraseña para asegurar'
|
|
|
|
. ' que podrás recordar la contraseña y/o que no has cometido'
|
|
|
|
. ' ningún error, si pierdes el acceso a tu cuenta no podrás'
|
|
|
|
. ' recuperarlo de ningún modo.',
|
|
|
|
);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
1;
|