Adding a few dao and model to use the data defined in the database migration
Also some tests are added.
This commit is contained in:
parent
39c8bcbc89
commit
1bcb9bf973
@ -15,8 +15,8 @@ package MY {
|
||||
my $return = $self->SUPER::top_targets(@_);
|
||||
$return = [ split /\n/, $return ];
|
||||
for my $i ( keys @$return ) {
|
||||
$return->[$i] .= ' install_frontend'
|
||||
if $return->[$i] =~ /^all :/;
|
||||
$return->[$i] .= ' install_frontend_and_migrations'
|
||||
if $return->[$i] =~ /^install :/;
|
||||
}
|
||||
return join "\n", @$return;
|
||||
}
|
||||
@ -24,7 +24,7 @@ package MY {
|
||||
sub postamble {
|
||||
return
|
||||
"\n"
|
||||
. "install_frontend:\n"
|
||||
. "install_frontend_and_migrations:\n"
|
||||
. "\tif [ ! -e lib/BeastBB/public ]; then "
|
||||
. "mkdir -pv lib/BeastBB/public; " . "fi;"
|
||||
. "if [ ! -e lib/BeastBB/templates ]; then "
|
||||
|
3
cpanfile
3
cpanfile
@ -8,3 +8,6 @@ requires 'Params::ValidationCompiler';
|
||||
requires 'Types::Standard';
|
||||
requires 'Crypt::Bcrypt::Easy';
|
||||
requires 'DateTime';
|
||||
requires 'DateTime::Format::ISO8601';
|
||||
requires 'Test::Most';
|
||||
requires 'Test::MockModule';
|
||||
|
@ -19,6 +19,7 @@ use BeastBB::Constants (
|
||||
);
|
||||
use BeastBB::ConfigWriter;
|
||||
use BeastBB::Database;
|
||||
use BeastBB::Response;
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
@ -48,6 +49,14 @@ sub PrepareHelpers {
|
||||
return $database;
|
||||
}
|
||||
);
|
||||
$self->helper(
|
||||
logged_user => sub {
|
||||
my $self = shift;
|
||||
my $session = $self->session;
|
||||
return BeastBB::Response->new( is_error => 1, error_message => 'User is not logged in.');
|
||||
my $username = $session->{username};
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
@ -60,6 +69,7 @@ sub PrepareSecrets {
|
||||
sub PrepareRoutes {
|
||||
my $self = shift;
|
||||
my $routes = $self->routes;
|
||||
|
||||
@{ $self->renderer->paths() } =
|
||||
( Mojo::File::curfile->dirname->child('BeastBB')->child('templates')
|
||||
->to_string );
|
||||
@ -68,11 +78,31 @@ sub PrepareRoutes {
|
||||
->to_string );
|
||||
print Data::Dumper::Dumper $self->renderer->paths;
|
||||
if ( !exists $self->config->{finished_install} ) {
|
||||
$routes->get('/')->to('install#welcome');
|
||||
$routes->post('/install/database')->to('install#install_database');
|
||||
$routes->post('/install/admin_user_create')
|
||||
->to('install#admin_user_create');
|
||||
$self->PrepareInstallationRoutes;
|
||||
return;
|
||||
}
|
||||
|
||||
$self->PrepareCommonRoutes;
|
||||
}
|
||||
|
||||
sub PrepareCommonRoutes {
|
||||
my $self = shift;
|
||||
my $routes = $self->routes;
|
||||
|
||||
$routes->get('/')->to('Main#Index');
|
||||
$routes->get('/login')->to('Main#GetLogin');
|
||||
$routes->post('/login')->to('Main#Login');
|
||||
$routes->post('/logout')->to('Main#Logout');
|
||||
}
|
||||
|
||||
sub PrepareInstallationRoutes {
|
||||
my $self = shift;
|
||||
my $routes = $self->routes;
|
||||
|
||||
$routes->get('/')->to('install#welcome');
|
||||
$routes->post('/install/database')->to('install#install_database');
|
||||
$routes->post('/install/admin_user_create')
|
||||
->to('install#admin_user_create');
|
||||
}
|
||||
|
||||
sub PrepareConfig {
|
||||
|
@ -85,7 +85,7 @@ sub admin_user_create {
|
||||
repeat_password => $repeat_password
|
||||
);
|
||||
my $user_manager = BeastBB::DAO::UserManager->new( app => $self );
|
||||
my $response_create_user = $user_manager->CreateUser(
|
||||
my $response_create_user = $user_manager->Create(
|
||||
username => $username,
|
||||
matrix_address => $matrix_address,
|
||||
password => $password,
|
||||
|
15
lib/BeastBB/Controller/Main.pm
Normal file
15
lib/BeastBB/Controller/Main.pm
Normal file
@ -0,0 +1,15 @@
|
||||
package BeastBB::Controller::Main;
|
||||
|
||||
use 5.30.3;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Mojo::Base 'Mojolicious::Controller';
|
||||
|
||||
sub Index {
|
||||
my $self = shift;
|
||||
$self->stash( session => $self->session );
|
||||
$self->render;
|
||||
}
|
||||
1;
|
160
lib/BeastBB/DAO/GroupManager.pm
Normal file
160
lib/BeastBB/DAO/GroupManager.pm
Normal file
@ -0,0 +1,160 @@
|
||||
package BeastBB::DAO::GroupManager;
|
||||
|
||||
use 5.32.1;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Carp;
|
||||
|
||||
use Params::ValidationCompiler 'validation_for';
|
||||
use Types::Standard qw/Bool Str Int/;
|
||||
|
||||
use BeastBB::Response;
|
||||
|
||||
{
|
||||
my $validator = validation_for(
|
||||
params => {
|
||||
app => { type => IsClassTypeGenerator('Mojolicious::Controller') },
|
||||
}
|
||||
);
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my %params = $validator->(@_);
|
||||
return bless \%params, $class;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
my $validator = validation_for(
|
||||
params => {
|
||||
id_group => { type => Int, optional => 1 },
|
||||
groupname => { type => Str, optional => 1 },
|
||||
recover_privileges => { type => Bool, default => 0 },
|
||||
}
|
||||
);
|
||||
|
||||
sub Get {
|
||||
my $self = shift;
|
||||
|
||||
my %params = $validator->(@_);
|
||||
my ( $id_group, $groupname, $recover_privileges ) =
|
||||
@params{ 'id_group', 'groupname', 'recover_privileges' };
|
||||
|
||||
$self->_CheckGetRequirements(
|
||||
( ( defined $id_group ) ? ( id_group => $id_group ) : () ),
|
||||
( ( defined $groupname ) ? ( groupname => $groupname ) : () )
|
||||
);
|
||||
|
||||
my $maybe_group_hash = $self->_RecoverGroupFromDatabase(
|
||||
( ( defined $id_group ) ? ( id_group => $id_group ) : () ),
|
||||
( ( defined $groupname ) ? ( groupname => $groupname ) : () )
|
||||
);
|
||||
|
||||
return $maybe_group_hash if $maybe_group_hash->IsError;
|
||||
$group_hash = $maybe_group_hash;
|
||||
my $group = BeastBB::Model::Group->new(%$group_hash);
|
||||
|
||||
my $privileges;
|
||||
if ($recover_privileges) {
|
||||
$self->RecoverPrivilegesGroup( group => $group );
|
||||
}
|
||||
|
||||
return BeastBB::Response->new( content => $group );
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
my $validator = validation_for(
|
||||
id_group => { type => Int, optional => 1 },
|
||||
groupname => { type => Str, optional => 1 },
|
||||
);
|
||||
|
||||
sub _CheckGetRequirements {
|
||||
my $self = shift;
|
||||
my %params = $validator->(@_);
|
||||
|
||||
my ( $id_group, $groupname, ) = @params{ 'id_group', 'groupname', };
|
||||
|
||||
confess "${class}::Get should be used passing id_group xor groupname."
|
||||
unless ( defined $id_group xor defined $groupname );
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
my $validator = validation_for(
|
||||
params => {
|
||||
id_group => { type => Int, optional => 1 },
|
||||
groupname => { type => Str, optional => 1 },
|
||||
}
|
||||
);
|
||||
|
||||
sub _RecoverGroupFromDatabase {
|
||||
my $self = shift;
|
||||
my %params = $validator->(@_);
|
||||
|
||||
my $id_group = $params{id_group};
|
||||
my $groupname = $params{groupname};
|
||||
|
||||
my $app = $self->_App;
|
||||
my $database = $app->db;
|
||||
my $pg = $database->Pg->db;
|
||||
|
||||
my $selected_group = $pg->select(
|
||||
'group',
|
||||
[ 'id_group', 'groupname' ],
|
||||
{
|
||||
( ( defined $id_group ) ? ( id_group => $id_group ) : () ),
|
||||
( ( defined $groupname ) ? ( groupname => $groupname ) : () )
|
||||
}
|
||||
);
|
||||
if ( !$selected_group->rows ) {
|
||||
return BeastBB::Response->new(
|
||||
is_error => 1,
|
||||
error_message => 'No such group.'
|
||||
);
|
||||
}
|
||||
return BeastBB::Response->new( content => $selected_group->hash );
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
my $validator = validation_for(
|
||||
params => {
|
||||
group => { type => IsClassTypeGenerator('BeastBB::Model::Group') },
|
||||
}
|
||||
);
|
||||
|
||||
sub RecoverPrivilegesGroup {
|
||||
my $self = shift;
|
||||
my %params = $validator->(@_);
|
||||
my $group = $params{group};
|
||||
my $id_group = $group->IdGroup;
|
||||
|
||||
my $app = $self->_App;
|
||||
my $database = $app->db;
|
||||
my $pg = $database->Pg->db;
|
||||
|
||||
my $selected_privileges = $pg->query(
|
||||
'SELECT privilege.name'
|
||||
. ' FROM group_privilege'
|
||||
. ' INNER JOIN privilege USING (id_privilege)'
|
||||
. ' WHERE id_group=?',
|
||||
$id_group
|
||||
);
|
||||
if ( $selected_privileges->rows ) {
|
||||
my $hashes_privileges = $selected_privileges->hashes;
|
||||
$privileges =
|
||||
{ map { $_->{name} => 1 } @$hashes_privileges };
|
||||
}
|
||||
$privileges //= {};
|
||||
$group->Privileges($privileges);
|
||||
return $group;
|
||||
}
|
||||
}
|
||||
|
||||
sub _App {
|
||||
return $self->{app};
|
||||
}
|
||||
1;
|
@ -1,10 +1,11 @@
|
||||
package BeastBB::DAO::UserManager;
|
||||
|
||||
use 5.32.1;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Data::Dumper;
|
||||
use Carp;
|
||||
|
||||
use Params::ValidationCompiler 'validation_for';
|
||||
use Types::Standard qw/Bool Str/;
|
||||
@ -13,8 +14,11 @@ use Crypt::Bcrypt::Easy;
|
||||
use Const::Fast;
|
||||
use DateTime;
|
||||
|
||||
use BeastBB::Types ( '$MATRIX_ADDRESS_REGEX', 'IsClassTypeGenerator' );
|
||||
use BeastBB::DAO::Response;
|
||||
use BeastBB::Types (
|
||||
'$MATRIX_ADDRESS_REGEX', 'IsClassTypeGenerator',
|
||||
'$MATRIX_ADDRESS_TYPE'
|
||||
);
|
||||
use BeastBB::Response;
|
||||
|
||||
const my $MINIMUM_PASSWORD_LENGHT => 8;
|
||||
|
||||
@ -32,6 +36,135 @@ const my $MINIMUM_PASSWORD_LENGHT => 8;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
my $validator = validation_for(
|
||||
params => {
|
||||
id_user => { type => Int, optional => 1 },
|
||||
username => { type => Str, optional => 1 },
|
||||
matrix_address => { type => $MATRIX_ADDRESS_TYPE, optional => 1 },
|
||||
recover_group => { type => Bool, default => 0 },
|
||||
}
|
||||
);
|
||||
|
||||
sub Get {
|
||||
my $self = shift;
|
||||
|
||||
my %params = $validator->(@_);
|
||||
|
||||
my $id_user = $params{id_user};
|
||||
my $username = $params{username};
|
||||
my $matrix_address = $params{matrix_address};
|
||||
my $recover_group = $params{recover_group};
|
||||
|
||||
confess
|
||||
'You should pass id_user xor matrix_address xor username to Get.'
|
||||
unless ( defined $id_user xor defined $username
|
||||
xor defined $matrix_address );
|
||||
|
||||
my $maybe_user_hash = $self->_RecoverUserFromDatabase(
|
||||
( ( defined $id_user ) ? ( id_user => $id_user ) : () ),
|
||||
( ( defined $username ) ? ( username => $username ) : () ),
|
||||
(
|
||||
( defined $matrix_address )
|
||||
? ( matrix_address => $matrix_address )
|
||||
: ()
|
||||
)
|
||||
);
|
||||
return $maybe_user_hash if $maybe_user_hash->IsError;
|
||||
$user_hash = $maybe_user_hash->Content;
|
||||
my $id_group = delete $user_hash->{id_group};
|
||||
my $user = BeastBB::Model::User->new(%$user_hash);
|
||||
|
||||
if ($recover_group) {
|
||||
my $maybe_recovered_group =
|
||||
$self->_RecoverUserGroup( id_group => $id_group, user => $user );
|
||||
return $maybe_recovered_group if $maybe_recovered_group->IsError;
|
||||
}
|
||||
return BeastBB::Response->new( content => $user );
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
my $validator = validation_for(
|
||||
params => {
|
||||
id_group => { type => Int },
|
||||
user => { type => IsClassTypeGenerator('BeastBB::Model::User') },
|
||||
}
|
||||
);
|
||||
|
||||
sub _RecoverUserGroup {
|
||||
my $self = shift;
|
||||
my %params = $validator->(@_);
|
||||
|
||||
my $id_group = $params{id_group};
|
||||
my $user = $params{user};
|
||||
my $app = $self->_App;
|
||||
|
||||
my $group_manager = BeastBB::DAO::GroupManager->new( app => $app );
|
||||
my $maybe_group = $group_manager->Get( id_group => $id_group );
|
||||
if ( $maybe_group->IsError ) {
|
||||
return $maybe_group;
|
||||
}
|
||||
my $group = $maybe_group->Content;
|
||||
$user->Group($group);
|
||||
return BeastBB::Response->new;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
my $validator = validation_for(
|
||||
params => {
|
||||
id_user => { type => Int, optional => 1 },
|
||||
username => { type => Str, optional => 1 },
|
||||
matrix_address => { type => $MATRIX_ADDRESS_TYPE, optional => 1 },
|
||||
}
|
||||
|
||||
);
|
||||
|
||||
sub _RecoverUserFromDatabase {
|
||||
my $self = shift;
|
||||
my %params = $validator->(@_);
|
||||
|
||||
my $app = $self->_App;
|
||||
my $database = $app->db;
|
||||
my $pg = $database->Pg->db;
|
||||
|
||||
my ( $id_user, $username, $matrix_address ) =
|
||||
@params{ 'id_user', 'username', 'matrix_address' };
|
||||
|
||||
my $results = $pg->select(
|
||||
'user',
|
||||
[
|
||||
'id_user', 'username', 'matrix_address', 'password_bcrypt',
|
||||
'is_confirmed', 'creation_date', 'id_group', 'last_connection',
|
||||
],
|
||||
{
|
||||
( ( defined $id_user ) ? ( id_user => $id_user ) : () ),
|
||||
( ( defined $username ) ? ( username => $username ) : () ),
|
||||
(
|
||||
( defined $matrix_address )
|
||||
? ( matrix_address => $matrix_address )
|
||||
: ()
|
||||
)
|
||||
}
|
||||
);
|
||||
if ( !$results->rows ) {
|
||||
return BeastBB::Response->new(
|
||||
is_error => 1,
|
||||
error_message => 'No such user found.',
|
||||
);
|
||||
}
|
||||
my $user_hash = $results->hash;
|
||||
$user_hash->{creation_date} = DateTime::Format::ISO8601->parse_datetime(
|
||||
$user_hash->{creation_date} );
|
||||
$user_hash->{last_connection} =
|
||||
DateTime::Format::ISO8601->parse_datetime(
|
||||
$user_hash->{last_connection} );
|
||||
|
||||
return BeastBB::Response( content => $user_hash );
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
my $validator = validation_for(
|
||||
params => {
|
||||
@ -44,7 +177,7 @@ const my $MINIMUM_PASSWORD_LENGHT => 8;
|
||||
}
|
||||
);
|
||||
|
||||
sub CreateUser {
|
||||
sub Create {
|
||||
my $self = shift;
|
||||
my %params = $validator->(@_);
|
||||
my (
|
||||
@ -72,7 +205,7 @@ const my $MINIMUM_PASSWORD_LENGHT => 8;
|
||||
my $result =
|
||||
$pg->select( 'group', 'id_group', { groupname => $groupname } );
|
||||
if ( !$result->rows ) {
|
||||
return BeastBB::DAO::Response->new(
|
||||
return BeastBB::Response->new(
|
||||
is_error => 1,
|
||||
error_message => "Unable to find the group $groupname."
|
||||
);
|
||||
@ -96,14 +229,13 @@ const my $MINIMUM_PASSWORD_LENGHT => 8;
|
||||
}
|
||||
);
|
||||
if ( !$result_create_user->rows ) {
|
||||
return BeastBB::DAO::Response->new(
|
||||
return BeastBB::Response->new(
|
||||
is_error => 1,
|
||||
error_message => "Unable to create user $username.",
|
||||
);
|
||||
}
|
||||
return BeastBB::DAO::Response->new(
|
||||
content => $result_create_user->hash->{id_user}
|
||||
);
|
||||
return BeastBB::Response->new(
|
||||
content => $result_create_user->hash->{id_user} );
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,7 +287,7 @@ const my $MINIMUM_PASSWORD_LENGHT => 8;
|
||||
if ( $password ne $repeat_password ) {
|
||||
$error_message = 'Password and repeat password not matching.';
|
||||
}
|
||||
return BeastBB::DAO::Response->new(
|
||||
return BeastBB::Response->new(
|
||||
(
|
||||
( defined $error_message )
|
||||
? (
|
||||
@ -183,7 +315,7 @@ const my $MINIMUM_PASSWORD_LENGHT => 8;
|
||||
if ( $password =~ /^\d+$/ ) {
|
||||
$error_message = "Password is numeric, it is not allowed.";
|
||||
}
|
||||
return BeastBB::DAO::Response->new(
|
||||
return BeastBB::Response->new(
|
||||
(
|
||||
( defined $error_message )
|
||||
? (
|
||||
@ -212,7 +344,7 @@ const my $MINIMUM_PASSWORD_LENGHT => 8;
|
||||
$error_message =
|
||||
"Password has less than $MINIMUM_PASSWORD_LENGHT characters.";
|
||||
}
|
||||
return BeastBB::DAO::Response->new(
|
||||
return BeastBB::Response->new(
|
||||
(
|
||||
( defined $error_message )
|
||||
? (
|
||||
@ -239,7 +371,7 @@ const my $MINIMUM_PASSWORD_LENGHT => 8;
|
||||
if ( $matrix_address !~ /$MATRIX_ADDRESS_REGEX/ ) {
|
||||
$error_message = "This does not look like a Matrix address.";
|
||||
}
|
||||
return BeastBB::DAO::Response->new(
|
||||
return BeastBB::Response->new(
|
||||
(
|
||||
( defined $error_message )
|
||||
? (
|
||||
|
102
lib/BeastBB/Model/Group.pm
Normal file
102
lib/BeastBB/Model/Group.pm
Normal file
@ -0,0 +1,102 @@
|
||||
package BeastBB::Model::Group;
|
||||
use 5.32.1;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Params::ValidationCompiler 'validation_for';
|
||||
use Types::Standard qw/Int Str HashRef Bool/;
|
||||
|
||||
use BeastBB::Response;
|
||||
|
||||
{
|
||||
my $validator = validation_for(
|
||||
params => {
|
||||
id_group => { type => Int, optional => 1 },
|
||||
groupname => { type => Str },
|
||||
privileges => { type => HashRef [Bool], optional => 1 },
|
||||
}
|
||||
);
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my %params = $validator->(@_);
|
||||
return bless \%params, $class;
|
||||
}
|
||||
}
|
||||
|
||||
sub Hash {
|
||||
my $self = shift;
|
||||
my $maybe_id_group = $self->IdGroup;
|
||||
my $maybe_privileges = $self->Privileges;
|
||||
return {
|
||||
(
|
||||
( !$maybe_id_group->IsError )
|
||||
? ( id_group => $maybe_id_group->Content )
|
||||
: ()
|
||||
),
|
||||
(
|
||||
( !$maybe_privileges->IsError )
|
||||
? ( privileges => $maybe_privileges->Content )
|
||||
: ()
|
||||
),
|
||||
groupname => $self->{groupname},
|
||||
};
|
||||
}
|
||||
|
||||
sub IdGroup {
|
||||
my $self = shift;
|
||||
my $id_group = $self->{id_group};
|
||||
return BeastBB::Response->new(
|
||||
is_error => 1,
|
||||
error_message => 'No id group set to this model.'
|
||||
) if !defined $id_group;
|
||||
return BeastBB::Response->new( content => $id_group );
|
||||
}
|
||||
|
||||
{
|
||||
my $validator = validation_for(
|
||||
params => [
|
||||
{ type => Int },
|
||||
]
|
||||
);
|
||||
|
||||
sub SetIdGroup {
|
||||
my $self = shift;
|
||||
my %params = $validator->(@_);
|
||||
my $id_group = shift;
|
||||
$self->{id_group} = $id_group;
|
||||
}
|
||||
}
|
||||
|
||||
sub Groupname {
|
||||
my $self = shift;
|
||||
return $self->{groupname};
|
||||
}
|
||||
|
||||
{
|
||||
my $validator = validation_for(
|
||||
params => [
|
||||
{ type => HashRef [Bool], optional => 1 },
|
||||
],
|
||||
);
|
||||
|
||||
sub Privileges {
|
||||
my $self = shift;
|
||||
@_ = $validator->(@_);
|
||||
|
||||
if (@_) {
|
||||
$self->{privileges} = shift;
|
||||
}
|
||||
|
||||
if ( !defined $self->{privileges} ) {
|
||||
return BeastBB::Response->new(
|
||||
is_error => 1,
|
||||
error_message => 'Privileges not recovered yet for this group.'
|
||||
);
|
||||
}
|
||||
return BeastBB::Response->new( content => $self->{privileges} );
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
217
lib/BeastBB/Model/User.pm
Normal file
217
lib/BeastBB/Model/User.pm
Normal file
@ -0,0 +1,217 @@
|
||||
package BeastBB::Model::User;
|
||||
|
||||
use 5.32.1;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Params::ValidationCompiler 'validation_for';
|
||||
use Types::Standard qw/Str Bool Int/;
|
||||
|
||||
use BeastBB::Types qw/$MATRIX_ADDRESS_TYPE IsClassTypeGenerator/;
|
||||
use BeastBB::Response;
|
||||
|
||||
{
|
||||
my $validator = validation_for(
|
||||
params => {
|
||||
id_user => { type => Int, optional => 1 },
|
||||
group => {
|
||||
type => IsClassTypeGenerator('BeastBB::Model::Group'),
|
||||
optional => 1
|
||||
},
|
||||
username => { type => Str },
|
||||
matrix_address => { type => Str },
|
||||
password_bcrypt => { type => Str },
|
||||
is_confirmed => { type => Bool, default => 0 },
|
||||
creation_date => {
|
||||
type => IsClassTypeGenerator('DateTime'),
|
||||
default => sub { return DateTime->now }
|
||||
},
|
||||
last_connection => {
|
||||
type => IsClassTypeGenerator('DateTime'),
|
||||
default => sub { return DateTime->now }
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
my %params = $validator->(@_);
|
||||
return bless \%params, $class;
|
||||
}
|
||||
}
|
||||
|
||||
sub Hash {
|
||||
my $self = shift;
|
||||
return {
|
||||
(
|
||||
( !$self->IdUser->IsError )
|
||||
? ( id_user => $self->IdUser->Content )
|
||||
: ()
|
||||
),
|
||||
(
|
||||
( !$self->Group->IsError )
|
||||
? ( group => $self->Group->Content->hash )
|
||||
: ()
|
||||
),
|
||||
username => $self->Username,
|
||||
matrix_address => $self->MatrixAddress,
|
||||
password_bcrypt => $self->PasswordBcrypt,
|
||||
is_confirmed => $self->IsConfirmed,
|
||||
creation_date => $self->CreationDate,
|
||||
last_connection => $self->LastConnection,
|
||||
};
|
||||
}
|
||||
|
||||
{
|
||||
my $validator = validation_for(
|
||||
params => [
|
||||
{
|
||||
type => IsClassTypeGenerator('BeastBB::Model::Group'),
|
||||
optional => 1
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
sub Group {
|
||||
my $self = shift;
|
||||
@_ = $validator->(@_);
|
||||
|
||||
if (@_) {
|
||||
$self->{group} = shift;
|
||||
}
|
||||
|
||||
if ( !defined $self->{group} ) {
|
||||
return BeastBB::Response->new(
|
||||
is_error => 1,
|
||||
error_message => 'No group recovered for this user.',
|
||||
);
|
||||
}
|
||||
return BeastBB::Model::Group->new(
|
||||
content => $self->{group},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
sub IdUser {
|
||||
my $self = shift;
|
||||
my $id_user = $self->{id_user};
|
||||
return BeastBB::Response->new(
|
||||
is_error => 1,
|
||||
error_message => 'Id user not set for this user model.'
|
||||
) if !defined $id_user;
|
||||
return BeastBB::Response->new( content => $self->{id_user} );
|
||||
}
|
||||
|
||||
{
|
||||
my $validator = validation_for(
|
||||
params => [
|
||||
{ type => Int },
|
||||
]
|
||||
);
|
||||
|
||||
sub SetIdUser {
|
||||
my $self = shift;
|
||||
@_ = $validator->(@_);
|
||||
$self->{id_user} = shift;
|
||||
}
|
||||
}
|
||||
|
||||
sub Username {
|
||||
my $self = shift;
|
||||
return $self->{username};
|
||||
}
|
||||
|
||||
{
|
||||
my $validator =
|
||||
validation_for(
|
||||
params => [ { type => $MATRIX_ADDRESS_TYPE, optional => 1 } ] );
|
||||
|
||||
sub MatrixAddress {
|
||||
my $self = shift;
|
||||
@_ = $validator->(@_);
|
||||
if (@_) {
|
||||
$self->{matrix_address} = shift;
|
||||
}
|
||||
return $self->{matrix_address};
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
my $validator = validation_for(
|
||||
params => [
|
||||
{
|
||||
type => Str,
|
||||
optional => 1
|
||||
}
|
||||
]
|
||||
);
|
||||
|
||||
sub PasswordBcrypt {
|
||||
my $self = shift;
|
||||
@_ = $validator->(@_);
|
||||
if (@_) {
|
||||
$self->{password_bcrypt} = shift;
|
||||
}
|
||||
return $self->{password_bcrypt};
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
my $validator = validation_for(
|
||||
params => [
|
||||
{
|
||||
type => Bool,
|
||||
optional => 1
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
sub IsConfirmed {
|
||||
my $self = shift;
|
||||
@_ = $validator->(@_);
|
||||
if (@_) {
|
||||
$self->{is_confirmed} = shift;
|
||||
}
|
||||
return $self->{is_confirmed};
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
my $validator = validation_for(
|
||||
params => [
|
||||
{
|
||||
type => IsClassTypeGenerator('DateTime'),
|
||||
optional => 1
|
||||
}
|
||||
],
|
||||
);
|
||||
|
||||
sub CreationDate {
|
||||
my $self = shift;
|
||||
if (@_) {
|
||||
$self->{creation_date} = shift;
|
||||
}
|
||||
return $self->{creation_date};
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
my $validator = validation_for(
|
||||
params => [
|
||||
{
|
||||
type => IsClassTypeGenerator('DateTime'),
|
||||
optional => 1
|
||||
}
|
||||
],
|
||||
);
|
||||
|
||||
sub LastConnection {
|
||||
my $self = shift;
|
||||
if (@_) {
|
||||
$self->{last_connection} = shift;
|
||||
}
|
||||
return $self->{last_connection};
|
||||
}
|
||||
}
|
||||
1;
|
@ -1,4 +1,4 @@
|
||||
package BeastBB::DAO::Response;
|
||||
package BeastBB::Response;
|
||||
|
||||
use 5.32.1;
|
||||
|
@ -24,7 +24,7 @@ create table "user" (
|
||||
is_confirmed BOOLEAN DEFAULT false,
|
||||
creation_date TIMESTAMP NOT NULL,
|
||||
id_group BIGINT NOT NULL,
|
||||
last_connection TIMESTAMP,
|
||||
last_connection TIMESTAMP NOT NULL,
|
||||
FOREIGN KEY (id_group) REFERENCES "group" (id_group)
|
||||
);
|
||||
|
||||
|
62
t/Model/00-user.t
Normal file
62
t/Model/00-user.t
Normal file
@ -0,0 +1,62 @@
|
||||
use 5.32.1;
|
||||
|
||||
use Test::Most tests => 7;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Const::Fast;
|
||||
use Crypt::Bcrypt::Easy;
|
||||
use DateTime;
|
||||
use Scalar::Util 'blessed';
|
||||
|
||||
const my %REQUIRED_FIELDS_USER => (
|
||||
username => 'example_username',
|
||||
matrix_address => '@example_username:example_host.com',
|
||||
password_bcrypt => bcrypt->crypt('example_password'),
|
||||
is_confirmed => 1,
|
||||
creation_date => DateTime->new( year => 2021, month => 06, day => 3 ),
|
||||
last_connection => DateTime->now,
|
||||
);
|
||||
{
|
||||
use_ok 'BeastBB::Model::User';
|
||||
}
|
||||
|
||||
{
|
||||
my $user = BeastBB::Model::User->new(%REQUIRED_FIELDS_USER);
|
||||
ok defined $user && $user->isa('BeastBB::Model::User'),
|
||||
'This user is made of BeastBB::Model::User.';
|
||||
my $user_hash = $user->Hash;
|
||||
%$user_hash = map {
|
||||
my $value = $user_hash->{$_};
|
||||
(
|
||||
$_ => (
|
||||
( blessed $value && $value->isa('DateTime') )
|
||||
? "$value"
|
||||
: $value
|
||||
)
|
||||
)
|
||||
} keys %$user_hash;
|
||||
is_deeply $user_hash, \%REQUIRED_FIELDS_USER, 'User has the expected hash.';
|
||||
}
|
||||
|
||||
{
|
||||
my $user = BeastBB::Model::User->new(%REQUIRED_FIELDS_USER);
|
||||
ok $user->IdUser->IsError, 'Id user can not be retrieved before set.';
|
||||
$user->SetIdUser(1);
|
||||
ok !$user->IdUser->IsError, 'Id user can be retrieved after set.';
|
||||
is $user->IdUser->Content, 1, 'Id user can be set on runtime.';
|
||||
my $user_hash = $user->Hash;
|
||||
%$user_hash = map {
|
||||
my $value = $user_hash->{$_};
|
||||
(
|
||||
$_ => (
|
||||
( blessed $value && $value->isa('DateTime') )
|
||||
? "$value"
|
||||
: $value
|
||||
)
|
||||
)
|
||||
} keys %$user_hash;
|
||||
is_deeply $user_hash, { %REQUIRED_FIELDS_USER, id_user => 1 },
|
||||
'User has the expected hash with id set after creation.';
|
||||
}
|
22
t/Model/01-group.t
Normal file
22
t/Model/01-group.t
Normal file
@ -0,0 +1,22 @@
|
||||
use 5.32.1;
|
||||
|
||||
use Test::Most tests => 3;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Const::Fast;
|
||||
|
||||
const my %REQUIRED_FIELDS_GROUP => ( groupname => 'example_group' );
|
||||
|
||||
{
|
||||
use_ok 'BeastBB::Model::Group';
|
||||
}
|
||||
|
||||
{
|
||||
my $group = BeastBB::Model::Group->new(%REQUIRED_FIELDS_GROUP);
|
||||
ok $group->isa('BeastBB::Model::Group'),
|
||||
'Group is made of BeastBB::Model::Group.';
|
||||
is_deeply $group->Hash, \%REQUIRED_FIELDS_GROUP,
|
||||
'The generated hash of group is correct.';
|
||||
}
|
1
templates/main/Index.html.ep
Normal file
1
templates/main/Index.html.ep
Normal file
@ -0,0 +1 @@
|
||||
<h1>Hello world</h1>
|
Loading…
Reference in New Issue
Block a user