Adding endpoint to add services.

This commit is contained in:
sergiotarxz 2021-11-13 03:15:18 +01:00
parent 42f234e103
commit 0c945e1177
2 changed files with 158 additions and 27 deletions

View File

@ -32,14 +32,35 @@ sub dbh {
run_migrations($dbh); run_migrations($dbh);
$migrations_run = 1; $migrations_run = 1;
} }
return $dbh;
} }
sub run_migrations { sub run_migrations {
my $dbh = shift; my $dbh = shift;
my $current_migration = _get_current_migration_number($dbh);
say $current_migration;
say scalar @migrations;
if ($current_migration < scalar @migrations) {
my @needed_migrations = @migrations[$current_migration .. $#migrations];
for my $migration (@needed_migrations) {
$dbh->do($migration);
if (!(0+$dbh->do('UPDATE options SET value = ? WHERE key = "migration"', undef, ++$current_migration))) {
$dbh->do('INSERT INTO options (key, value) VALUES ("migration", ?)', undef, $current_migration);
}
}
}
}
sub _get_current_migration_number {
my $dbh = shift;
local $dbh->{RaiseError} = 0;
my $migration = $dbh->selectrow_hashref(<<'EOF', {}); my $migration = $dbh->selectrow_hashref(<<'EOF', {});
SELECT value FROM options WHERE key = 'migration' SELECT value FROM options WHERE key = 'migration'
EOF EOF
my $value = 0;
if (defined $migration) {
$value = $migration->{value};
}
return $value;
} }
1; 1;

View File

@ -7,13 +7,56 @@ use warnings;
use Data::Dumper; use Data::Dumper;
use Socket qw/SOL_SOCKET SO_PEERCRED/; use Socket qw/SOL_SOCKET SO_PEERCRED/;
use List::Util qw/any/;
use Carp qw/carp/;
use Params::ValidationCompiler qw/validation_for/; use Params::ValidationCompiler qw/validation_for/;
use Types::Standard qw/Object HashRef Str/; use Types::Standard qw/Object HashRef Str/;
use Try::Tiny;
use Cualsea::MessageManager; use Cualsea::MessageManager;
use Cualsea::Server::DB;
my %commands = { sub handle_add {
my %params = @_;
my $name = $params{name};
my $init = $params{init};
my $pidfile = $params{pidfile};
my $binpath = $params{binpath};
if ( !-e $binpath || $init ne 'sysvinit' || !_validate_init_name($name) )
{
return {
is_error => 1,
desc => "Parameters didn't pass contraints on add",
status => 400
};
}
my $dbh = Cualsea::Server::DB->dbh();
eval {
$dbh->do( << 'EOF', undef, $name, $init, $pidfile, $binpath );
INSERT INTO services (name, init, pidfile, binpath) VALUES (?, ?, ?, ?);
EOF
};
if ($@) {
if ($@ =~ /UNIQUE/i) {
my $return_value = {
status => 400,
is_error => 1,
desc => 'Endpoint already exists.',
};
return $return_value;
}
carp $@;
}
return {
is_error => 0,
desc => "Succesful creation of init service $name.",
status => 200
};
}
my %COMMANDS = (
add => { add => {
params => [ params => [
'name', 'name',
@ -29,11 +72,10 @@ my %commands = {
binpath => { type => Str }, binpath => { type => Str },
} }
), ),
handle => \&handle_add,
}, },
del => { del => {
params => [ params => ['name'],
'name'
],
validator => validation_for( validator => validation_for(
params => { params => {
name => { type => Str }, name => { type => Str },
@ -42,14 +84,10 @@ my %commands = {
}, },
report => { report => {
params => [], params => [],
validator => validation_for( validator => sub { },
params => {},
),
}, },
start => { start => {
params => [ params => ['name'],
'name',
],
validator => validation_for( validator => validation_for(
params => { params => {
name => { type => Str }, name => { type => Str },
@ -57,9 +95,7 @@ my %commands = {
), ),
}, },
stop => { stop => {
params => [ params => ['name'],
'name',
],
validator => validation_for( validator => validation_for(
params => { params => {
name => { type => Str }, name => { type => Str },
@ -67,16 +103,32 @@ my %commands = {
), ),
}, },
restart => { restart => {
params => [ params => ['name'],
'name',
],
validator => validation_for( validator => validation_for(
params => { params => {
name => { type => Str }, name => { type => Str },
} }
), ),
} }
);
sub _validate_init_name {
my $init_name = shift;
if ( $init_name =~ /^\.$/ ) {
return 0;
}
if ( $init_name =~ /^\.\.$/ ) {
return 0;
}
if ( $init_name =~ /\// ) {
return 0;
}
if ( !-e "/etc/init.d/$init_name" ) {
return 0;
}
return 1;
} }
sub new { sub new {
my $class = shift; my $class = shift;
return bless {}, $class; return bless {}, $class;
@ -102,7 +154,65 @@ sub new {
$self->write_malformed( message_manager => $message_manager ); $self->write_malformed( message_manager => $message_manager );
return; return;
} }
$message_manager->write_message( message => $message ); $message_manager->write_message(
message => $self->_handle_command( message => $message ) );
}
}
{
my $validator = validation_for(
params => {
message => { type => HashRef },
}
);
sub _handle_command {
my $self = shift;
my %params = $validator->(@_);
my $message = $params{message};
my $command = $message->{command};
my $params = $message->{arguments} // [];
say "Got parameters:";
say Data::Dumper::Dumper $params;
if ( !exists $COMMANDS{$command} ) {
return { is_error => 1, status => 404 };
}
my $command_info = $COMMANDS{$command};
my $params_info = $command_info->{params};
print Data::Dumper::Dumper $params_info;
# We want to forget about $params arrayref
# and previous hash as soon as possible.
%params = ();
for my $param_info_index ( scalar @$params_info ? (0..$#$params_info) : () ) {
my $param_info = $params_info->[$param_info_index];
# May not come defined,
if ( $param_info_index > scalar $#$params ) {
last;
}
say "$param_info => @{[$params->[$param_info_index]]}";
$params{$param_info} = $params->[$param_info_index];
}
my $validator = $command_info->{validator};
my $return_error;
try {
$validator->(%params);
}
catch {
$return_error = { is_error => 1, status => 400, desc => $_->error };
};
if ( defined $return_error ) {
return $return_error;
}
my $handle = $command_info->{handle};
if ( !defined $handle ) {
return { is_error => 1, status => 501 };
}
return $handle->(%params);
} }
} }
@ -117,11 +227,11 @@ sub new {
my $self = shift; my $self = shift;
my %params = $validator->(@_); my %params = $validator->(@_);
my $socket = $params{socket}; my $socket = $params{socket};
my ($pid, $uid, $gid) = unpack 'LLL', $socket->sockopt(SO_PEERCRED); my ( $pid, $uid, $gid ) = unpack 'LLL', $socket->sockopt(SO_PEERCRED);
my $user = getpwuid($uid); my $user = getpwuid($uid);
while (my ($name, undef, undef, $members) = getgrent()) { while ( my ( $name, undef, undef, $members ) = getgrent() ) {
if ($name eq 'cualsea') { if ( $name eq 'cualsea' ) {
return List::Util::any { $_ eq $user } split ',', $members; return any { $_ eq $user } split ',', $members;
last; last;
} }
} }