Apache2-ASP

 view release on metacpan or  search on metacpan

lib/Apache2/ASP/Manual/BestPractices.pod  view on Meta::CPAN

C<site1::user::logout>

=back

=head1 FILE UPLOADS

Just inherit from L<Apache2::ASP::MediaManager> unless you need more control.

See the documentation for L<Apache2::ASP::MediaManager> for more information.

=head1 VALIDATION

Apache2::ASP supports - but does not provide - server-side validation.  In fact,
it is recommended that all validation is performed on the server, in one way or
another.

AJAX may be your preferred means of doing form validations and such, which Apache2::ASP
fully supports.  Apache2::ASP simply does not B<require> the use of AJAX or any other
idiom.

=head2 How-To

The recommended form validation idiom for Apache2::ASP is as follows:

B<The Form>:

  <%
    if( my $args = delete($Session->{__lastArgs}) )
    {
      $Form->{$_} = $args->{$_} foreach keys(%$args);
    }# end if()
    
    my $errors = delete($Session->{validation_errors}) || { };
    my $errLabel = sub {
      my $name = shift;
      return unless $errors->{$name};
  %><span class="field_error"><%= $Server->HTMLEncode( $errors->{$name} ) %></span><%
    };
  %>
  
  <%
    if( my $msg = delete($Session->{msg}) ) {
  %>
  <div class="message"><%= $Server->HTMLEncode( $msg ) %></div>
  <%
    }# end if()
  %>
  
  <%
    if( $errors->{general} ) {
  %>
  <div class="general_error"><%= $Server->HTMLEncode( $errors->{general} ) %></div>
  <%
    }# end if()
  %>
  
  <form action="/handlers/site1.user.login" method="post">
    <input type="text" name="username" value="<%= $Server->HTMLEncode( $Form->{username} ) %>" />
    <% $errLabel->( 'username' ); %>
    <br />
    <input type="password" name="password" />
    <% $errLabel->( 'password' ); %>
    <br />
    <input type="submit" value="Submit" />
  </form>

The form submits to the URI C</handlers/site1.user.login> which maps to the package
C<site1::user::login>.

It is recommended that inside your C</etc> folder you have a YAML file, C</etc/properties.yaml>:

B<The YAML File>: (C</etc/properties.yaml>)

  ---
  user_login:
    username:
      is_missing: Required
      is_invalid: Invalid username
    password:
      is_missing: Required
      is_invalid: Invalid password
    general:
      success: Successfully Logged In
      fail: Invalid username and/or password.  Please try again.

B<The Handler>: (C</handlers/site1/user/login.pm>)

  package site1::user::login;
  
  use strict;
  use warnings 'all';
  use base 'Apache2::ASP::FormHandler';
  use vars __PACKAGE__->VARS;
  use Data::Properties::YAML;
  
  #============================================================================
  sub run
  {
    my ($s, $context) = @_;
    
    if( my $errors = $s->validate( $context ) )
    {
      # We found some kind of validation error:
      $Session->{__lastArgs} = $Form;
      $Session->{validation_errors} = $errors;
      return $Response->Redirect( $ENV{HTTP_REFERER} );
    }# end if()
    
    # Success! - no validation errors:
    my ($user) = find_user( ... );
    $Session->{user} = $user;
    
    # Find our success message:
    my $props = Data::Properties::YAML->new(
      properties_file => $Config->web->application_root . '/etc/properties.yaml'
    )->user_login;
    $Session->{msg} = $props->general->success;
    
    # Redirect the user to the logged-in page:
    return $Response->Redirect("/logged-in.asp");
  }# end run()
  
  #============================================================================
  sub validate
  {
    my ($s, $context) = @_;
    
    # Remove leading and trailing whitespace:
    map {
      $Form->{$_} =~ s/^\s+//;
      $Form->{$_} =~ s/\s+$//;
    } keys(%$Form);
    
    my $props = Data::Properties::YAML->new(
      properties_file => $Config->web->application_root . '/etc/properties.yaml'
    )->user_login;
    
    my $errors = { };
    
    no warnings 'uninitialized';
    
    # username:
    if( length($Form->{username}) )
    {
      # Username cannot contain whitespace:
      if( $Form->{username} =~ m/\s/ )
      {
        $errors->{username} = $props->username->is_invalid;
      }# end if()
    }
    else
    {
      $errors->{username} = $props->username->is_missing;
    }# end if()
    
    # password:
    if( length($Form->{password}) )
    {
      # Password cannot contain whitespace:
      if( $Form->{password} =~ m/\s/ )
      {
        $errors->{password} = $props->password->is_invalid;
      }# end if()
    }
    else
    {
      $errors->{password} = $props->password->is_missing;
    }# end if()
    
    # Only check to see if the user exists if we haven't encountered other errors:
    unless( keys(%$errors) )
    {
      if( ! find_user( ... ) )
      {
        $errors->{general} = $props->general->fail;
      }# end if()
    }# end unless()
    
    return unless keys(%$errors);
    return $errors;
  }# end validate()
  
  1;# return true:

=head1 UNIT TESTING

Unit testing was the number one reason behind the development of Apache2::ASP.

Apache2::ASP offers a unit testing environment that is not dependent on Apache
or any other server.

Unit tests are made possible via instances of L<Apache2::ASP::Test::Base> and 
use L<Apache2::ASP::Test::UserAgent> to make "requests" to ASP scripts and handlers
in your Apache2::ASP web application.

=head2 Example

Supposing your website is at C</var/www/www.example.com>, create a folder C</t>
at C</var/www/www.example.com/t>.

Inside C</t> create C</t/00-basic.t> which contains:

  #!/usr/bin/env perl -w
  
  use strict;
  use warnings 'all';
  use Test::More 'no_plan';
  use base 'Apache2::ASP::Test::Base';
  
  # Create our base test object:
  my $s = __PACKAGE__->SUPER::new();
  
  # Make a request:
  my $res = $s->ua->get("/index.asp");
  
  # $res is a normal HTTP::Response object:
  ok( $res->is_success => "Got /index.asp" );
  like $res->content, qr/Hello, World/, "Contents look right";
  is( $res->header('content-type') => 'text/html' );

Run your tests with:

  prove t

All of your tests will be run.

=head1 CODE COVERAGE



( run in 1.339 second using v1.01-cache-2.11-cpan-39bf76dae61 )