burguillos.info/lib/BurguillosInfo/Controller/UserConquer.pm
2023-11-20 20:20:04 +01:00

161 lines
4.9 KiB
Perl

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/;
use JSON;
use BurguillosInfo::Schema;
my $username_minimum_chars = 3;
my $username_maximum_chars = 15;
my $password_minimum_chars = 8;
my $password_maximum_chars = 4096;
sub get_self($self) {
my $user = $self->current_user;
if (!defined $user) {
return $self->_renderError(401, 'No estás loggeado.');
}
return $self->render(json => $user->serialize_to_owner, status => 200);
}
sub create ($self) {
my $input = $self->_expectJson;
if ( !defined $input ) {
return;
}
my $username = $input->{username};
my $password = $input->{password};
my $repeat_password = $input->{repeat_password};
return
unless $self->_createCheckInput( $username, $password, $repeat_password );
return $self->_createUser( $username, $password );
}
sub _expectJson ($self) {
my $input;
eval { $input = $self->req->json; };
if ($@) {
say STDERR $@;
$self->_renderError(400, 'Se esperaba JSON.');
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];
if (!defined $tentative_user) {
$self->_renderError(401, 'El usuario especificado no existe.');
return;
}
if ( !bcrypt_check( $password, $tentative_user->encrypted_password ) ) {
$self->_renderError( 401, 'Contraseña incorrecta.' );
return;
}
my $user = $tentative_user;
$self->set_current_user($user);
$self->render(
json => {
success => $JSON::true
},
status => 200
);
}
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
}
);
$user->insert;
};
if ($@) {
if ( $@ =~ /Key \((.*?)\)=\((.*?)\) already exists\./ ) {
return $self->_renderError( 400,
"La clave $1 ($2) ya existe en la base de datos.",
);
}
say STDERR $@;
return $self->_renderError( 400,
'No se pudo crear el usuario por razones desconocidas.' );
}
$self->render( status => 200, json => $user->serialize_to_owner );
return 1;
}
sub _renderError ( $self, $status, $message ) {
$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}$/
)
{
return $self->_renderError( 400,
"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+$/ )
{
return $self->_renderError(
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 ) {
$self->_renderError(
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;