AmberDB
view release on metacpan or search on metacpan
lib/AmberDB/Base.pm view on Meta::CPAN
my $local_file = "$local_dir/sess_$token";
if ( open my $lfh, '>', $local_file ) {
require JSON::PP;
print $lfh JSON::PP::encode_json($data);
close $lfh;
}
return 1;
}
sub _delete_session {
my ( $self, $token ) = @_;
return unless defined $token && length $token;
my $sf = $self->session_file($token);
unlink $sf if $sf && -f $sf;
my $local_file = ".amberdb/session/sess_$token";
unlink $local_file if -f $local_file;
}
# my $val_or_token = $adb->connect([$key | %args]);
# ---------------------------------------------------------------------
sub connect {
my ( $self, @args ) = @_;
# 1. Single scalar argument: attribute getter -> $adb->connect('database')
if ( @args == 1 && !ref( $args[0] ) ) {
my $k = $args[0];
$k = 'database' if $k eq 'dbase' || $k eq 'dbname';
$k = 'username' if $k eq 'user' || $k eq 'usr';
$k = 'password' if $k eq 'pass' || $k eq 'passwd';
return $self->{_connect}->{$k} // '';
}
# If called with no args and already connected with valid token, return active token
if ( !@args && defined $self->{_connect}->{token} && length $self->{_connect}->{token} ) {
return $self->{_connect}->{token};
}
# 2. Connection / Authentication Action -> $adb->connect(%args) or $adb->connect()
my %opts = ( @args == 1 && ref( $args[0] ) eq 'HASH' ) ? %{ $args[0] } : @args;
my $token = delete $opts{token} // delete $opts{tok};
my $database = delete $opts{database} // delete $opts{dbase} // delete $opts{dbname} // delete $opts{db} // $self->{_connect}->{database};
my $username = delete $opts{username} // delete $opts{user} // delete $opts{usr} // $self->{_connect}->{username};
my $password = delete $opts{password} // delete $opts{pass} // delete $opts{passwd} // $self->{_connect}->{password};
# Sub-case A: Resume session via token
if ( defined $token && length $token ) {
my $sess = $self->_load_session($token);
if ( $sess && ref($sess) eq 'HASH' ) {
$self->{_connect}->{token} = $token;
$self->{_connect}->{database} = $sess->{connect}->{database} // $sess->{database} // $self->{_connect}->{database} // '';
$self->{_connect}->{username} = $sess->{connect}->{username} // $sess->{username} // $self->{_connect}->{username} // 'user_system';
$self->{_connect}->{password} = $sess->{connect}->{password} // $sess->{password} // '';
$self->{_cfg}->{user} = $self->{_connect}->{username};
return $token;
}
return undef;
}
# Sub-case B: Authenticate credentials & generate session token
my $connect_cfg = $self->_load_connect_config();
# Dbase dir leaf name as default database if not specified
if ( !defined $database || !length $database ) {
if ( $connect_cfg && $connect_cfg->{database} ) {
$database = $connect_cfg->{database};
}
else {
my $dbase_dir = $self->path('dbase_dir') || ".";
my ($leaf) = $dbase_dir =~ m{([^/\\\\]+)[/\\\\]*$};
$database = $leaf // 'amberdb';
}
}
$username //= 'cli';
$password //= '';
# Bootstrap connect.pl on first connection if missing or empty
if ( !$connect_cfg || !ref($connect_cfg->{users}) || !keys %{ $connect_cfg->{users} } ) {
$connect_cfg = {
database => $database,
created_at => time(),
users => {
$username => {
shadow => ( defined $password && length $password ) ? $self->hash_password($password) : '',
role => 'admin',
},
web => {
shadow => '',
role => 'web',
},
cli => {
shadow => '',
role => 'cli',
},
},
};
$self->_save_connect_config($connect_cfg);
}
else {
# Check database mismatch if specified
if ( $connect_cfg->{database} && $database && lc($connect_cfg->{database}) ne lc($database) ) {
croak "[AMBERDB_AUTH_ERROR] Database mismatch: requested '$database' but store is '$connect_cfg->{database}'";
}
$database = $connect_cfg->{database} if $connect_cfg->{database};
# Check user
my $user_info = $connect_cfg->{users}->{$username};
if ( !$user_info ) {
croak "[AMBERDB_AUTH_ERROR] User '$username' not authorized for database '$database'";
}
# Auto-upgrade plain text password in connect.pl to shadow if present
if ( exists $user_info->{password} && defined $user_info->{password} && length $user_info->{password} ) {
my $plain = delete $user_info->{password};
$user_info->{shadow} = $self->hash_password($plain);
$self->_save_connect_config($connect_cfg);
}
# Password check:
( run in 2.160 seconds using v1.01-cache-2.11-cpan-007c89162af )