Concierge-Auth

 view release on metacpan or  search on metacpan

examples/07-error-handling.pl  view on Meta::CPAN


print "\n--- Context-Sensitive Return Values ---\n";

print "Scalar vs List context behavior:\n";

# Test in scalar context
my $scalar_result = $auth->setPwd('newuser', 'password123');
printf "Scalar context: %s (type: %s)\n", 
       $scalar_result, ref($scalar_result) || 'scalar';

# Test in list context  
my ($list_success, $list_message) = $auth->setPwd('newuser2', 'password123');
printf "List context: success=%s, message='%s'\n", $list_success, $list_message;

# Clean up test users
$auth->deleteID('newuser');
$auth->deleteID('newuser2');

print "\n--- Defensive Programming Examples ---\n";

sub safe_user_registration {
    my ($auth, $username, $password) = @_;
    
    # Validate inputs before attempting operation
    eval {
        $auth->validateID($username);
        $auth->validatePwd($password);
    };
    
    if ($@) {
        my $error = $@;
        chomp $error;
        return (0, "Validation failed: $error");
    }
    
    # Check if user already exists
    if ($auth->checkID($username)) {
        return (0, "User already exists");
    }
    
    # Attempt registration
    my ($success, $message) = $auth->setPwd($username, $password);
    
    return ($success, $message);
}

sub safe_user_authentication {
    my ($auth, $username, $password) = @_;
    
    # Basic input validation
    return (0, "Username required") unless defined $username && length $username;
    return (0, "Password required") unless defined $password && length $password;
    
    # Validate inputs
    eval {
        $auth->validateID($username);
        $auth->validatePwd($password);
    };
    
    if ($@) {
        return (0, "Invalid credentials format");
    }
    
    # Check if user exists first
    unless ($auth->checkID($username)) {
        return (0, "Invalid credentials");
    }
    
    # Attempt authentication
    my $authenticated = $auth->checkPwd($username, $password);
    
    return $authenticated ? (1, "Authentication successful") : (0, "Invalid credentials");
}

print "Defensive programming demonstration:\n";

# Test safe registration
my @test_registrations = (
    ['validuser', 'validpassword123', 'should succeed'],
    ['', 'validpassword123', 'should fail - empty username'],
    ['validuser2', 'short', 'should fail - short password'],  
    ['invalid user', 'validpassword123', 'should fail - invalid username'],
    ['validuser', 'validpassword123', 'should fail - duplicate user'],
);

for my $test (@test_registrations) {
    my ($username, $password, $expected) = @$test;
    my ($success, $message) = safe_user_registration($auth, $username, $password);
    
    printf "  Register %-15s: %s (%s)\n",
           "'$username'",
           $success ? "✓ success" : "✗ failed - $message",
           $expected;
}

print "\nAuthentication with defensive validation:\n";

my @test_authentications = (
    ['validuser', 'validpassword123', 'should succeed'],
    ['validuser', 'wrongpassword', 'should fail - wrong password'],
    ['', 'validpassword123', 'should fail - empty username'],
    ['validuser', '', 'should fail - empty password'],
    ['nonexistent', 'anypassword', 'should fail - user not found'],
    ['invalid user', 'anypassword', 'should fail - invalid username format'],
);

for my $test (@test_authentications) {
    my ($username, $password, $expected) = @$test;
    my ($success, $message) = safe_user_authentication($auth, $username, $password);
    
    printf "  Auth %-15s: %s (%s)\n",
           "'$username'",
           $success ? "✓ success" : "✗ failed - $message",
           $expected;
}

print "\n=== Error Handling Complete ===\n";

__END__

=head1 ERROR HANDLING STRATEGIES

=head2 Exception vs Return Values

Concierge::Auth uses two error handling patterns:

B<Exceptions> (die/croak):
- Input validation methods (validateID, validatePwd)
- Internal errors (file I/O failures)
- Programming errors (missing required parameters)

B<Return Values> (success/failure with message):

examples/07-error-handling.pl  view on Meta::CPAN


=head2 Input Validation Rules

B<User IDs>:
- Length: 2-32 characters
- Characters: letters, numbers, dots, underscores, at-signs, hyphens
- Cannot be empty or undefined

B<Passwords>:
- Length: 8-72 characters (bcrypt limit)
- Any characters allowed including Unicode
- Cannot be empty or undefined

=head1 DEFENSIVE PROGRAMMING PATTERN

    use Concierge::Auth;
    
    sub register_user {
        my ($username, $password) = @_;
        
        # Validate inputs first
        eval {
            $auth->validateID($username);
            $auth->validatePwd($password);
        };
        
        if ($@) {
            return {
                success => 0,
                error   => 'Invalid input format',
                details => $@
            };
        }
        
        # Check business rules
        if ($auth->checkID($username)) {
            return {
                success => 0,
                error   => 'Username already taken'
            };
        }
        
        # Attempt operation
        my ($success, $message) = $auth->setPwd($username, $password);
        
        return {
            success => $success,
            error   => $success ? undef : $message,
            message => $success ? 'User registered successfully' : undef
        };
    }

=head1 SECURITY CONSIDERATIONS

=over 4

=item * Never expose validation error details to prevent enumeration

=item * Log failed authentication attempts for monitoring

=item * Use consistent error messages for invalid credentials

=item * Implement rate limiting to prevent brute force attacks

=item * Sanitize all user input before logging

=back

=head1 SEE ALSO

L<Concierge::Auth>, 08-advanced-usage.pl, 01-basic-authentication.pl

=cut



( run in 0.593 second using v1.01-cache-2.11-cpan-d06a3f9ecfd )