burguillos.info/lib/BurguillosInfo/Controller/UserConquer.pm

196 lines
5.8 KiB
Perl
Raw Normal View History

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;