Finishing 5 minutes installation.
This commit is contained in:
parent
557ff979c8
commit
39c8bcbc89
@ -29,7 +29,10 @@ package MY {
|
|||||||
. "mkdir -pv lib/BeastBB/public; " . "fi;"
|
. "mkdir -pv lib/BeastBB/public; " . "fi;"
|
||||||
. "if [ ! -e lib/BeastBB/templates ]; then "
|
. "if [ ! -e lib/BeastBB/templates ]; then "
|
||||||
. "mkdir -pv lib/BeastBB/templates; " . "fi; "
|
. "mkdir -pv lib/BeastBB/templates; " . "fi; "
|
||||||
|
. "if [ ! -e lib/BeastBB/migrations ]; then "
|
||||||
|
. "mkdir -pv lib/BeastBB/migrations; " . "fi; "
|
||||||
. "cp -rfv templates/* lib/BeastBB/templates/; "
|
. "cp -rfv templates/* lib/BeastBB/templates/; "
|
||||||
. "cp -rfv public/* lib/BeastBB/public/; ";
|
. "cp -rfv public/* lib/BeastBB/public/; "
|
||||||
|
. "cp -rfv migrations/* lib/BeastBB/migrations/; ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
6
cpanfile
6
cpanfile
@ -3,4 +3,8 @@ requires 'Mojo::Pg';
|
|||||||
requires 'ExtUtils::MakeMaker';
|
requires 'ExtUtils::MakeMaker';
|
||||||
requires 'Crypt::URandom';
|
requires 'Crypt::URandom';
|
||||||
requires 'DBD::Pg';
|
requires 'DBD::Pg';
|
||||||
|
requires 'Const::Fast';
|
||||||
|
requires 'Params::ValidationCompiler';
|
||||||
|
requires 'Types::Standard';
|
||||||
|
requires 'Crypt::Bcrypt::Easy';
|
||||||
|
requires 'DateTime';
|
||||||
|
@ -12,10 +12,13 @@ use Mojo::File;
|
|||||||
|
|
||||||
use Const::Fast;
|
use Const::Fast;
|
||||||
use Params::ValidationCompiler 'validation_for';
|
use Params::ValidationCompiler 'validation_for';
|
||||||
use Crypt::URandom 'urandom';
|
|
||||||
|
|
||||||
use BeastBB::Constants ( '$HOME_DIR', '$HOME_CONFIG_DIR', '$CONFIG_FILE', '$SECRET_DEFAULT_SIZE' );
|
use BeastBB::Constants (
|
||||||
|
'$HOME_DIR', '$HOME_CONFIG_DIR', '$CONFIG_FILE',
|
||||||
|
'$SECRET_DEFAULT_SIZE'
|
||||||
|
);
|
||||||
use BeastBB::ConfigWriter;
|
use BeastBB::ConfigWriter;
|
||||||
|
use BeastBB::Database;
|
||||||
|
|
||||||
sub new {
|
sub new {
|
||||||
my $class = shift;
|
my $class = shift;
|
||||||
@ -28,9 +31,26 @@ sub startup {
|
|||||||
$self->PrepareConfig;
|
$self->PrepareConfig;
|
||||||
$self->PrepareSecrets;
|
$self->PrepareSecrets;
|
||||||
$self->PrepareRoutes;
|
$self->PrepareRoutes;
|
||||||
|
$self->PrepareHelpers;
|
||||||
return $self;
|
return $self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub PrepareHelpers {
|
||||||
|
my $self = shift;
|
||||||
|
my $database;
|
||||||
|
$self->helper(
|
||||||
|
db => sub {
|
||||||
|
if ( !defined $database ) {
|
||||||
|
my $config = $self->config;
|
||||||
|
$database =
|
||||||
|
BeastBB::Database->NewFromConfig( config => $config->{db} );
|
||||||
|
}
|
||||||
|
return $database;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
sub PrepareSecrets {
|
sub PrepareSecrets {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $config = $self->config;
|
my $config = $self->config;
|
||||||
@ -47,9 +67,11 @@ sub PrepareRoutes {
|
|||||||
( Mojo::File::curfile->dirname->child('BeastBB')->child('public')
|
( Mojo::File::curfile->dirname->child('BeastBB')->child('public')
|
||||||
->to_string );
|
->to_string );
|
||||||
print Data::Dumper::Dumper $self->renderer->paths;
|
print Data::Dumper::Dumper $self->renderer->paths;
|
||||||
if ( !exists $self->config->{installed} ) {
|
if ( !exists $self->config->{finished_install} ) {
|
||||||
$routes->get('/')->to('install#welcome');
|
$routes->get('/')->to('install#welcome');
|
||||||
$routes->post('/install/database')->to('install#install_database');
|
$routes->post('/install/database')->to('install#install_database');
|
||||||
|
$routes->post('/install/admin_user_create')
|
||||||
|
->to('install#admin_user_create');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,10 +9,11 @@ use Mojo::Base 'Mojolicious::Controller';
|
|||||||
use Mojo::URL;
|
use Mojo::URL;
|
||||||
|
|
||||||
use Params::ValidationCompiler 'validation_for';
|
use Params::ValidationCompiler 'validation_for';
|
||||||
use Types::Standard qw/HashRef/;
|
use Types::Standard qw/Str HashRef/;
|
||||||
|
|
||||||
use BeastBB::Database;
|
use BeastBB::Database;
|
||||||
use BeastBB::ConfigWriter;
|
use BeastBB::ConfigWriter;
|
||||||
|
use BeastBB::DAO::UserManager;
|
||||||
use BeastBB::Constants ('$CONFIG_FILE');
|
use BeastBB::Constants ('$CONFIG_FILE');
|
||||||
|
|
||||||
sub welcome {
|
sub welcome {
|
||||||
@ -27,7 +28,10 @@ sub install_database {
|
|||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
if ( exists $self->config->{db} ) {
|
if ( exists $self->config->{db} ) {
|
||||||
|
$self->code(404);
|
||||||
|
$self->render( text => 'This endpoint no longer has sense.' );
|
||||||
}
|
}
|
||||||
|
|
||||||
my $config_db;
|
my $config_db;
|
||||||
my $user = $self->param('username');
|
my $user = $self->param('username');
|
||||||
my $password = $self->param('password');
|
my $password = $self->param('password');
|
||||||
@ -56,14 +60,93 @@ sub install_database {
|
|||||||
my $error_url = Mojo::URL->new('/')->query( error => $@ );
|
my $error_url = Mojo::URL->new('/')->query( error => $@ );
|
||||||
$self->redirect_to($error_url);
|
$self->redirect_to($error_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->config->{db} = $config_db;
|
$self->config->{db} = $config_db;
|
||||||
local $Data::Dumper::Terse = 1;
|
local $Data::Dumper::Terse = 1;
|
||||||
my $config_writer =
|
my $config_writer =
|
||||||
BeastBB::ConfigWriter->new( config_file => $CONFIG_FILE );
|
BeastBB::ConfigWriter->new( config_file => $CONFIG_FILE );
|
||||||
$config_writer->WriteToConfigFile( content => Data::Dumper::Dumper $self->config );
|
$config_writer->WriteToConfigFile(
|
||||||
|
content => Data::Dumper::Dumper $self->config );
|
||||||
$self->redirect_to('/');
|
$self->redirect_to('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub admin_user_create {
|
||||||
|
my $self = shift;
|
||||||
|
my $username = $self->param('username');
|
||||||
|
my $matrix_address = $self->param('matrix_address');
|
||||||
|
my $password = $self->param('password');
|
||||||
|
my $repeat_password = $self->param('repeat_password');
|
||||||
|
my $config = $self->config;
|
||||||
|
|
||||||
|
$self->CheckDefinedParametersAdminCreation(
|
||||||
|
username => $username,
|
||||||
|
matrix_address => $matrix_address,
|
||||||
|
password => $password,
|
||||||
|
repeat_password => $repeat_password
|
||||||
|
);
|
||||||
|
my $user_manager = BeastBB::DAO::UserManager->new( app => $self );
|
||||||
|
my $response_create_user = $user_manager->CreateUser(
|
||||||
|
username => $username,
|
||||||
|
matrix_address => $matrix_address,
|
||||||
|
password => $password,
|
||||||
|
repeat_password => $repeat_password,
|
||||||
|
is_confirmed => 1,
|
||||||
|
groupname => 'admin',
|
||||||
|
);
|
||||||
|
if ( $response_create_user->IsError ) {
|
||||||
|
my $error_url = Mojo::URL->new('/')
|
||||||
|
->query( error => $response_create_user->ErrorMessage );
|
||||||
|
$self->redirect_to($error_url);
|
||||||
|
}
|
||||||
|
|
||||||
|
my $config_writer =
|
||||||
|
BeastBB::ConfigWriter->new( config_file => $CONFIG_FILE );
|
||||||
|
$config->{finished_install} = 1;
|
||||||
|
local $Data::Dumper::Terse = 1;
|
||||||
|
$config_writer->WriteToConfigFile(
|
||||||
|
content => Data::Dumper::Dumper $self->config );
|
||||||
|
$self->redirect_to('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
my $validator = validation_for(
|
||||||
|
params => {
|
||||||
|
username => { type => Str },
|
||||||
|
matrix_address => { type => Str },
|
||||||
|
password => { type => Str },
|
||||||
|
repeat_password => { type => Str },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
sub CheckDefinedParametersAdminCreation {
|
||||||
|
my $self = shift;
|
||||||
|
my %params = $validator->(@_);
|
||||||
|
my ( $username, $matrix_address, $password, $repeat_password ) =
|
||||||
|
@params{
|
||||||
|
'username', 'matrix_address', 'password',
|
||||||
|
'repeat_password'
|
||||||
|
};
|
||||||
|
if (
|
||||||
|
!$self->AreAllParametersAreDefined(
|
||||||
|
$username, $matrix_address, $password, $repeat_password
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
my $error_url = Mojo::URL->new('/')
|
||||||
|
->query( error => 'Not all required arguments were passed.' );
|
||||||
|
$self->redirect_to($error_url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub AreAllParametersAreDefined {
|
||||||
|
my $self = shift;
|
||||||
|
for my $param (@_) {
|
||||||
|
return 0 if !defined $param;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
my $validator =
|
my $validator =
|
||||||
validation_for( params => { config => { type => HashRef } } );
|
validation_for( params => { config => { type => HashRef } } );
|
||||||
|
69
lib/BeastBB/DAO/Response.pm
Normal file
69
lib/BeastBB/DAO/Response.pm
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package BeastBB::DAO::Response;
|
||||||
|
|
||||||
|
use 5.32.1;
|
||||||
|
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use Carp qw/confess cluck/;
|
||||||
|
|
||||||
|
use Params::ValidationCompiler 'validation_for';
|
||||||
|
use Types::Standard qw/Bool Str Any/;
|
||||||
|
|
||||||
|
{
|
||||||
|
my $validator = validation_for(
|
||||||
|
params => {
|
||||||
|
is_error => { type => Bool, default => 0 },
|
||||||
|
content => { type => Any, optional => 1 },
|
||||||
|
error_message => { type => Str, optional => 1 },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
sub new {
|
||||||
|
my $class = shift;
|
||||||
|
my %params = $validator->(@_);
|
||||||
|
my $is_error = $params{is_error};
|
||||||
|
my $content;
|
||||||
|
my $error_message;
|
||||||
|
|
||||||
|
if ( exists $params{content} ) {
|
||||||
|
$content = $params{content};
|
||||||
|
}
|
||||||
|
if ( exists $params{error_message} ) {
|
||||||
|
$error_message = $params{error_message};
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($is_error) {
|
||||||
|
cluck 'Error should not have content, stripping it.'
|
||||||
|
if defined $content;
|
||||||
|
cluck 'You should pass a error message on error.'
|
||||||
|
if !defined $error_message;
|
||||||
|
return bless {
|
||||||
|
is_error => 1,
|
||||||
|
error_message => $error_message // '',
|
||||||
|
}, $class;
|
||||||
|
}
|
||||||
|
return bless { content => $content }, $class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub IsError {
|
||||||
|
my $self = shift;
|
||||||
|
return $self->{is_error};
|
||||||
|
}
|
||||||
|
|
||||||
|
sub ErrorMessage {
|
||||||
|
my $self = shift;
|
||||||
|
if ( !$self->IsError ) {
|
||||||
|
confess 'This is not an error.';
|
||||||
|
}
|
||||||
|
return $self->{error_message};
|
||||||
|
}
|
||||||
|
|
||||||
|
sub Content {
|
||||||
|
my $self = shift;
|
||||||
|
if ( $self->IsError ) {
|
||||||
|
confess 'Attempt to get content from error.';
|
||||||
|
}
|
||||||
|
return $self->{content};
|
||||||
|
}
|
@ -1,2 +1,260 @@
|
|||||||
package BeastBB::DAO::UserManager;
|
package BeastBB::DAO::UserManager;
|
||||||
|
|
||||||
|
use 5.32.1;
|
||||||
|
use strict;
|
||||||
|
use warnings;
|
||||||
|
|
||||||
|
use Data::Dumper;
|
||||||
|
|
||||||
|
use Params::ValidationCompiler 'validation_for';
|
||||||
|
use Types::Standard qw/Bool Str/;
|
||||||
|
|
||||||
|
use Crypt::Bcrypt::Easy;
|
||||||
|
use Const::Fast;
|
||||||
|
use DateTime;
|
||||||
|
|
||||||
|
use BeastBB::Types ( '$MATRIX_ADDRESS_REGEX', 'IsClassTypeGenerator' );
|
||||||
|
use BeastBB::DAO::Response;
|
||||||
|
|
||||||
|
const my $MINIMUM_PASSWORD_LENGHT => 8;
|
||||||
|
|
||||||
|
{
|
||||||
|
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 => {
|
||||||
|
username => { type => Str },
|
||||||
|
matrix_address => { type => Str },
|
||||||
|
password => { type => Str },
|
||||||
|
repeat_password => { type => Str },
|
||||||
|
is_confirmed => { type => Bool },
|
||||||
|
groupname => { type => Str },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
sub CreateUser {
|
||||||
|
my $self = shift;
|
||||||
|
my %params = $validator->(@_);
|
||||||
|
my (
|
||||||
|
$username, $matrix_address, $password, $repeat_password,
|
||||||
|
$is_confirmed, $groupname
|
||||||
|
)
|
||||||
|
= @params{
|
||||||
|
'username', 'matrix_address', 'password',
|
||||||
|
'repeat_password', 'is_confirmed', 'groupname'
|
||||||
|
};
|
||||||
|
my $app = $self->_App;
|
||||||
|
my $database = $app->db;
|
||||||
|
my $pg = $database->Pg->db;
|
||||||
|
|
||||||
|
my $response_check_user_creation_requeriments =
|
||||||
|
$self->CheckUserCreationRequeriments(
|
||||||
|
matrix_address => $matrix_address,
|
||||||
|
password => $password,
|
||||||
|
repeat_password => $repeat_password
|
||||||
|
);
|
||||||
|
|
||||||
|
return $response_check_user_creation_requeriments
|
||||||
|
if $response_check_user_creation_requeriments->IsError;
|
||||||
|
|
||||||
|
my $result =
|
||||||
|
$pg->select( 'group', 'id_group', { groupname => $groupname } );
|
||||||
|
if ( !$result->rows ) {
|
||||||
|
return BeastBB::DAO::Response->new(
|
||||||
|
is_error => 1,
|
||||||
|
error_message => "Unable to find the group $groupname."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
my $id_group = $result->hash->{id_group};
|
||||||
|
|
||||||
|
my $result_create_user = $pg->insert(
|
||||||
|
'user',
|
||||||
|
{
|
||||||
|
username => $username,
|
||||||
|
password_bcrypt => bcrypt->crypt($password),
|
||||||
|
matrix_address => $matrix_address,
|
||||||
|
is_confirmed => $is_confirmed ? 1 : 0,
|
||||||
|
creation_date => "" . DateTime->now,
|
||||||
|
last_connection => "" . DateTime->now,
|
||||||
|
id_group => $id_group,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
returning => ['id_user'],
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if ( !$result_create_user->rows ) {
|
||||||
|
return BeastBB::DAO::Response->new(
|
||||||
|
is_error => 1,
|
||||||
|
error_message => "Unable to create user $username.",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return BeastBB::DAO::Response->new(
|
||||||
|
content => $result_create_user->hash->{id_user}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
my $validator = validation_for(
|
||||||
|
params => {
|
||||||
|
matrix_address => { type => Str },
|
||||||
|
password => { type => Str },
|
||||||
|
repeat_password => { type => Str },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
sub CheckUserCreationRequeriments {
|
||||||
|
my $self = shift;
|
||||||
|
my %params = $validator->(@_);
|
||||||
|
my ( $matrix_address, $password, $repeat_password ) =
|
||||||
|
@params{ 'matrix_address', 'password', 'repeat_password' };
|
||||||
|
my $response =
|
||||||
|
$self->CheckMatrixAddress( matrix_address => $matrix_address );
|
||||||
|
return $response if $response->IsError;
|
||||||
|
$response = $self->CheckPasswordLength( password => $password );
|
||||||
|
return $response if $response->IsError;
|
||||||
|
$response = $self->CheckPasswordNotOnlyNumeric( password => $password );
|
||||||
|
return $response if $response->IsError;
|
||||||
|
$response = $self->CheckTwoPasswordsEqual(
|
||||||
|
password => $password,
|
||||||
|
repeat_password => $repeat_password
|
||||||
|
);
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
my $validator = validation_for(
|
||||||
|
params => {
|
||||||
|
password => { type => Str },
|
||||||
|
repeat_password => { type => Str },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
sub CheckTwoPasswordsEqual {
|
||||||
|
my $self = shift;
|
||||||
|
my %params = $validator->(@_);
|
||||||
|
my $password = $params{password};
|
||||||
|
my $repeat_password = $params{repeat_password};
|
||||||
|
|
||||||
|
my $error_message;
|
||||||
|
|
||||||
|
if ( $password ne $repeat_password ) {
|
||||||
|
$error_message = 'Password and repeat password not matching.';
|
||||||
|
}
|
||||||
|
return BeastBB::DAO::Response->new(
|
||||||
|
(
|
||||||
|
( defined $error_message )
|
||||||
|
? (
|
||||||
|
is_error => 1,
|
||||||
|
error_message => $error_message
|
||||||
|
)
|
||||||
|
: ()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
my $validator = validation_for(
|
||||||
|
params => {
|
||||||
|
password => { type => Str },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
sub CheckPasswordNotOnlyNumeric {
|
||||||
|
my $self = shift;
|
||||||
|
my %params = $validator->(@_);
|
||||||
|
my $password = $params{'password'};
|
||||||
|
my $error_message;
|
||||||
|
if ( $password =~ /^\d+$/ ) {
|
||||||
|
$error_message = "Password is numeric, it is not allowed.";
|
||||||
|
}
|
||||||
|
return BeastBB::DAO::Response->new(
|
||||||
|
(
|
||||||
|
( defined $error_message )
|
||||||
|
? (
|
||||||
|
is_error => 1,
|
||||||
|
error_message => $error_message
|
||||||
|
)
|
||||||
|
: ()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
my $validator = validation_for(
|
||||||
|
params => {
|
||||||
|
password => { type => Str },
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
sub CheckPasswordLength {
|
||||||
|
my $self = shift;
|
||||||
|
my %params = $validator->(@_);
|
||||||
|
my $password = $params{'password'};
|
||||||
|
my $error_message;
|
||||||
|
if ( !length($password) > $MINIMUM_PASSWORD_LENGHT ) {
|
||||||
|
$error_message =
|
||||||
|
"Password has less than $MINIMUM_PASSWORD_LENGHT characters.";
|
||||||
|
}
|
||||||
|
return BeastBB::DAO::Response->new(
|
||||||
|
(
|
||||||
|
( defined $error_message )
|
||||||
|
? (
|
||||||
|
is_error => 1,
|
||||||
|
error_message => $error_message
|
||||||
|
)
|
||||||
|
: ()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
my $validator = validation_for(
|
||||||
|
params => { matrix_address => { type => Str } },
|
||||||
|
);
|
||||||
|
|
||||||
|
sub CheckMatrixAddress {
|
||||||
|
my $self = shift;
|
||||||
|
my %params = $validator->(@_);
|
||||||
|
my $matrix_address = $params{matrix_address};
|
||||||
|
my $error_message;
|
||||||
|
if ( $matrix_address !~ /$MATRIX_ADDRESS_REGEX/ ) {
|
||||||
|
$error_message = "This does not look like a Matrix address.";
|
||||||
|
}
|
||||||
|
return BeastBB::DAO::Response->new(
|
||||||
|
(
|
||||||
|
( defined $error_message )
|
||||||
|
? (
|
||||||
|
is_error => 1,
|
||||||
|
error_message => $error_message
|
||||||
|
)
|
||||||
|
: ()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub _App {
|
||||||
|
my $self = shift;
|
||||||
|
return $self->{app};
|
||||||
|
}
|
||||||
1;
|
1;
|
||||||
|
@ -9,6 +9,7 @@ use Params::ValidationCompiler 'validation_for';
|
|||||||
use Types::Standard qw( HashRef Str );
|
use Types::Standard qw( HashRef Str );
|
||||||
|
|
||||||
use Mojo::Pg;
|
use Mojo::Pg;
|
||||||
|
use Mojo::Pg::Migrations;
|
||||||
|
|
||||||
{
|
{
|
||||||
my $validator = validation_for(
|
my $validator = validation_for(
|
||||||
@ -16,10 +17,10 @@ use Mojo::Pg;
|
|||||||
);
|
);
|
||||||
|
|
||||||
sub NewFromConfig {
|
sub NewFromConfig {
|
||||||
my $class = shift;
|
my $class = shift;
|
||||||
my %params = $validator->(@_);
|
my %params = $validator->(@_);
|
||||||
my $config = $params{config};
|
my $config = $params{config};
|
||||||
$config = {%$config};
|
$config = {%$config};
|
||||||
my $user = delete $config->{user};
|
my $user = delete $config->{user};
|
||||||
my $password = delete $config->{password};
|
my $password = delete $config->{password};
|
||||||
my %other_params = %$config;
|
my %other_params = %$config;
|
||||||
@ -30,8 +31,7 @@ use Mojo::Pg;
|
|||||||
join ';',
|
join ';',
|
||||||
(
|
(
|
||||||
map {
|
map {
|
||||||
"$_="
|
"$_=" . $class->_SingleQuoteString( $other_params{$_} )
|
||||||
. $class->_SingleQuoteString( $other_params{$_} )
|
|
||||||
} keys %other_params
|
} keys %other_params
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@ -59,6 +59,10 @@ use Mojo::Pg;
|
|||||||
$self->Pg->username($user) if defined $user;
|
$self->Pg->username($user) if defined $user;
|
||||||
$self->Pg->password($password) if defined $password;
|
$self->Pg->password($password) if defined $password;
|
||||||
$self->Pg->dsn($dsn);
|
$self->Pg->dsn($dsn);
|
||||||
|
$self->Pg->migrations->from_dir(
|
||||||
|
Mojo::File::curfile->dirname->child('migrations')
|
||||||
|
->to_string );
|
||||||
|
$self->Pg->auto_migrate(1);
|
||||||
return $self;
|
return $self;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,21 @@ use warnings;
|
|||||||
use Exporter qw/import/;
|
use Exporter qw/import/;
|
||||||
use Scalar::Util qw/blessed/;
|
use Scalar::Util qw/blessed/;
|
||||||
use Type::Tiny;
|
use Type::Tiny;
|
||||||
our @EXPORT_OK = qw( &IsClassTypeGenerator );
|
|
||||||
|
use Const::Fast;
|
||||||
|
|
||||||
|
our @EXPORT_OK = ( '&IsClassTypeGenerator', '$MATRIX_ADDRESS_REGEX', '$MATRIX_ADDRESS_TYPE' );
|
||||||
|
|
||||||
|
const our $MATRIX_ADDRESS_REGEX => qr/^@\w+:(\w|\.)+\.(\w+)$/;
|
||||||
|
|
||||||
|
|
||||||
|
const our $MATRIX_ADDRESS_TYPE => Type::Tiny->new(
|
||||||
|
name => "MatrixAddressChecker",
|
||||||
|
constraint => sub {
|
||||||
|
my $matrix_address = shift;
|
||||||
|
return 1 if $matrix_address =~ /$MATRIX_ADDRESS_REGEX/;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
my %generated_classes;
|
my %generated_classes;
|
||||||
|
|
||||||
@ -21,6 +35,7 @@ sub IsClassTypeGenerator {
|
|||||||
constraint => sub {
|
constraint => sub {
|
||||||
my $item_to_test = shift;
|
my $item_to_test = shift;
|
||||||
return 1 if blessed $item_to_test && $item_to_test->isa($class);
|
return 1 if blessed $item_to_test && $item_to_test->isa($class);
|
||||||
|
return 0;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,8 @@
|
|||||||
DROP INDEX username_index_users;
|
DROP INDEX index_user;
|
||||||
DROP INDEX matrix_address_index_users;
|
DROP INDEX index_group;
|
||||||
DROP TABLE users;
|
DROP INDEX index_privileges;
|
||||||
|
|
||||||
|
DROP TABLE "user";
|
||||||
|
DROP TABLE "group_privilege";
|
||||||
|
DROP TABLE "group";
|
||||||
|
DROP TABLE "privilege";
|
||||||
|
@ -1,10 +1,45 @@
|
|||||||
create table users (
|
create table "group" (
|
||||||
id SERIAL PRIMARY KEY,
|
id_group BIGSERIAL PRIMARY KEY,
|
||||||
username TEXT UNIQUE,
|
groupname TEXT UNIQUE
|
||||||
matrix_address TEXT UNIQUE,
|
|
||||||
is_confirmed INT[1] DEFAULT false,
|
|
||||||
"privileges" HSTORE
|
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE INDEX username_index_users ON users username;
|
create table privilege (
|
||||||
CREATE INDEX matrix_address_index_users ON users matrix_address;
|
id_privilege BIGSERIAL PRIMARY KEY,
|
||||||
|
name TEXT UNIQUE
|
||||||
|
);
|
||||||
|
|
||||||
|
create table group_privilege (
|
||||||
|
id_group BIGINT,
|
||||||
|
id_privilege BIGINT,
|
||||||
|
PRIMARY KEY (id_group, id_privilege),
|
||||||
|
FOREIGN KEY (id_group) REFERENCES "group" (id_group),
|
||||||
|
FOREIGN KEY (id_privilege) REFERENCES "privilege" (id_privilege)
|
||||||
|
);
|
||||||
|
|
||||||
|
create table "user" (
|
||||||
|
id_user BIGSERIAL PRIMARY KEY,
|
||||||
|
username TEXT UNIQUE NOT NULL,
|
||||||
|
matrix_address TEXT UNIQUE NOT NULL,
|
||||||
|
password_bcrypt TEXT NOT NULL,
|
||||||
|
is_confirmed BOOLEAN DEFAULT false,
|
||||||
|
creation_date TIMESTAMP NOT NULL,
|
||||||
|
id_group BIGINT NOT NULL,
|
||||||
|
last_connection TIMESTAMP,
|
||||||
|
FOREIGN KEY (id_group) REFERENCES "group" (id_group)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX index_user ON "user" (username, matrix_address);
|
||||||
|
CREATE INDEX index_group ON "group" (groupname);
|
||||||
|
CREATE INDEX index_privileges ON "privilege" (name);
|
||||||
|
|
||||||
|
INSERT INTO privilege (name) VALUES ( 'CREATE_USER' ), ( 'DELETE_USER' ), ( 'LIST_USERS' ), ( 'UPDATE_USERS' );
|
||||||
|
INSERT INTO "group" (groupname) VALUES ( 'admin' );
|
||||||
|
INSERT INTO group_privilege (id_group, id_privilege)
|
||||||
|
SELECT
|
||||||
|
(
|
||||||
|
SELECT id_group from "group" where groupname='admin'
|
||||||
|
) as id_group,
|
||||||
|
id_privilege
|
||||||
|
FROM privilege
|
||||||
|
WHERE name in ( 'create_user', 'delete_user', 'list_users', 'update_users' );
|
||||||
|
|
||||||
|
@ -3,7 +3,9 @@
|
|||||||
<script src="js/install/welcome.js"></script>
|
<script src="js/install/welcome.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
% if ( !defined $config->{db} ) {
|
% if ( defined $config->{finished_install} && $config->{finished_install} ) {
|
||||||
|
<h1>Congrats, installation just finished, restart the Mojolicious server to access it.</h1>
|
||||||
|
% } elsif ( !defined $config->{db} ) {
|
||||||
<h1>Welcome to the 1 minute BeastBB installation.</h1>
|
<h1>Welcome to the 1 minute BeastBB installation.</h1>
|
||||||
<h2>Please introduce your Postgresql database details.</h2>
|
<h2>Please introduce your Postgresql database details.</h2>
|
||||||
<p>Blank fields will be attempted to be guess to sane value if posible</p>
|
<p>Blank fields will be attempted to be guess to sane value if posible</p>
|
||||||
@ -12,18 +14,45 @@
|
|||||||
% }
|
% }
|
||||||
|
|
||||||
<form method="POST" action="/install/database">
|
<form method="POST" action="/install/database">
|
||||||
<h3>Username.</h3>
|
<label for="username"><h3>Username.</h3></label>
|
||||||
<label for="username"><input type="text" name="username"/></label>
|
<input type="text" name="username"/>
|
||||||
<label for"password"><h3>Password.</h3></label>
|
|
||||||
|
<label for="password"><h3>Password.</h3></label>
|
||||||
<input type="password" name="password" id="postgres_password"/>
|
<input type="password" name="password" id="postgres_password"/>
|
||||||
<br>
|
<br/>
|
||||||
<a href="#" id="change_readable_password">Click here to toggle readable/unreadable the password</a>
|
<a href="#" id="change_readable_password">Click here to toggle readable/unreadable the password</a>
|
||||||
|
|
||||||
<label for="host"><h3>Host</h3></label>
|
<label for="host"><h3>Host</h3></label>
|
||||||
<input type="text" name="host"/>
|
<input type="text" name="host"/>
|
||||||
|
|
||||||
<label for="port"><h3>Port</h3></label>
|
<label for="port"><h3>Port</h3></label>
|
||||||
<input type="number" name="port"/>
|
<input type="number" name="port"/>
|
||||||
|
|
||||||
<label for="dbname"><h3>Database Name</h3></label>
|
<label for="dbname"><h3>Database Name</h3></label>
|
||||||
<input type="text" name="dbname"/>
|
<input type="text" name="dbname"/>
|
||||||
|
|
||||||
|
<input type="submit" value="Submit"/>
|
||||||
|
</form>
|
||||||
|
% } else {
|
||||||
|
<h2>Tell me the details about your new admin user before we migrate the database.</h2>
|
||||||
|
% if ( defined $error ) {
|
||||||
|
<p style="color: red;"><%= $error %></p>
|
||||||
|
% }
|
||||||
|
<form action="/install/admin_user_create" method="post">
|
||||||
|
<label for="username"><h3>Username.</h3></label>
|
||||||
|
<input type="text" name="username"/>
|
||||||
|
|
||||||
|
<label for="matrix_address"><h3>Matrix address.</h3></label>
|
||||||
|
<input type="text" name="matrix_address"/>
|
||||||
|
|
||||||
|
<label for="password"><h3>Password.</h3></label>
|
||||||
|
<input type="password" name="password" id="postgres_password"/>
|
||||||
|
<br/>
|
||||||
|
<a href="#" id="change_readable_password">Click here to toggle readable/unreadable the password</a>
|
||||||
|
|
||||||
|
<label for="repeat_password"><h3>Repeat password.</h3></label>
|
||||||
|
<input type="repeat_password" name="repeat_password" id="postgres_password"/>
|
||||||
|
|
||||||
<input type="submit" value="Submit"/>
|
<input type="submit" value="Submit"/>
|
||||||
</form>
|
</form>
|
||||||
% }
|
% }
|
||||||
|
Loading…
Reference in New Issue
Block a user