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 )