CleanCode Perl Libraries
Multi-Lingual Library Maintainability
available: Perl not available: Java not available: JavaScript not available: Certified
Class
not available: Testable
Class
not available: Standalone
Mode
available: Diagnostic
Enabled

NAME

cgiAppBase - Provides CGI::Application base implementation.

SYNOPSIS

        CgiAppBase->new->run();

REQUIRES

CGI, CGI::Application, CGI::Session, CGI::Session::Auth::DBI, CGI::Carp, Log::Log4perl, DBI::Helper, CGI::Application::Helper, Data::Diagnostic, Data::InputOptions, Data::Handy, Time::SimpleFormat

DESCRIPTION

The CGI::Application package provides an excellent framework for creating a dynamic web site. But it is still a long way from there to a working site. This package bridges a large portion of that gap, providing a functional web site with: account creation (by user), account deletion (by admin), admin vs. non-admin privileges, admin override (su username), state retention, authentication, site flow engine, template-driven pages, logging, and on-demand diagnostics delivered to browser.

You will still need to set up a few things: notably, a configuration file and a database (MySQL is assumed). But you have all of the infrastructure code provided; you need only add code/templates for your application functionality.

Each page on your site will be accessed via a URL of the form

        http://xxx/cgi-bin/cgiAppBase.pl/page

where page is also the base name of the template for the page. That is, for each of these pages, there is a template file page.thtml used to generate each page dynamically. Within each such template page are placeholders for variables, conditionals, and looping constructs, which specify what data to place on the page.

cgiAppBase includes a pre-defined, standard set of web pages, described below. The set of pre-defined, standard variables (accessible from any template) is in the section after that.

Getting Started

In order to run this base application framework as-is you will need to setup a few files, directories, and databases, as described below. Once you have the basic system running, can login as an admin user with administrative privileges, can add and delete accounts, then you can move to on customizing the framework, as described in subsequent sections.

Main configuration file

cgiAppBase comes with a default main configuration file (see DIAG_CONF). Edit this file to customize it to your needs. Note that there are several parameters you must define for the system to work; others may use their default values (as noted in the file).

Log4perl configuration file

cgiAppBase comes with a default Log4perl configuration file (see LOG_CONF). Edit this file to customize it to your needs. The logging of Log4perl is one form of logging available to you for debugging/tracing. Within the Log4perl configuration file, you should specify a filename for logging. The CleanCode Data::Diagnostic facility is also available; settings are in the main configuration file, including the log directory and file names (the LOG_DIR, LOG_DIAG_NAME, and LOG_ERR_NAME parameters).

Session directory

Sessions are managed via CGI::Session, which allows storing sessions as database entries or as regular files; cgiAppBase uses the latter. The session directory must be specified in the configuration file, in the SESSION_DIR parameter.

Cleaning session files

Old sessions tend to accumulate, so you'll need a cron entry to remove expired session files, such as this (replace xxx with your actual path):

        0 6 * * * find xxx/sessions -type f -mtime +2 2>/dev/null | xargs rm -f

which tells the system to remove any session files older than two days. Since sessions expire typically in less than an hour, this should not affect any active sessions.

Log directory

Logs are managed via Log::Log4perl and/or CleanCode's own Data::Diagnostic modules. Log files for both may be stored in the same or different directories, as you choose.

Web support files

Images, CSS files, and JavaScript files provided with the installation need to be installed in the appropriate locations. Images are located via the IMAGE_DIR parameter in the configuration file. CSS and JavaScript files use the HTDOCS parameter in the configuration file, as well as path-relative components in the template files.

Templates

cgiAppBase includes a baseline set of 9 templates (see "Standard Web Page Templates"). You will need to add templates for your custom pages to this set, all in the same directory. This directory must then be defined in the configuration file in the TEMPLATE_DIR parameter.

Authorization database

Sessions are authorized via CGI::Session::Auth, providing login/logout capability to provide security to your application. CGI::Session::Auth provides for a choice of backends; cgiAppBase uses a database repository. As such, you need to define the auth_user table (as specified in CGI::Session::Auth::DBI) with at least these columns:

  CREATE TABLE auth_user (
    userid char(32) NOT NULL PRIMARY KEY,
    username varchar(30) NOT NULL,
    passwd varchar(30) NOT NULL default '',
    UNIQUE username (username)
  );

The CGI::Session::Auth::DBI also shows how to add an entry for an admin user and a guest user. You should at least add the admin user, so you can have an administrative login. Also, you'll need to tell the system the user name for your admin user (typically "admin") via the ADMIN_USER parameter in the main configuration file.

User database

User accounts require only basic information, as shown in the SQL for the user_data table below.

  CREATE TABLE user_data (
    username varchar(30) NOT NULL PRIMARY KEY,
    first_name varchar(30) NOT NULL,
    last_name varchar(30) NOT NULL,
    email varchar(50) NOT NULL,
    FOREIGN KEY(username) REFERENCES auth_user(username)
  );

You may add fields as well as supporting code and template structure as needed.

Database connectivity

In the configuration file above, you must specify the host, database, username, and password to access the database used by the system.

Code libraries

Finally, in case it is not obvious, you will also need to install all the Perl libraries listed above (see "REQUIRES").

Customizing the Framework

In the last section, you learned how to get the generic cgiAppBase running. But the point of this framework is to customize it to your own needs. Here's how.

Step 1: Create a web page template

A web page template is an ordinary HTML or XHTML file with the addition of template variables. And, due to the presence of the template variables, the file extension should be .thtml rather than .html. You'll need to review the documentation for the excellent HTML::Template module for details, or you could examine the template files included with cgiAppBase for examples. Look for <TMPL_IF ...>, <TMPL_VAR ...>, and <TMPL_UNLESS ...> constructs.

Let's say you create a picture.html template file; on this web page, you intend to display a user's personal image catalog. The URL for this page, as mentioned earlier will be

        http://xxx/cgi-bin/cgiAppBase.pl/picture

where the picture suffix specifies the run mode to CGI::Application.

If your page is a dynamic page (needing data to be filled in), go on to Step 2; otherwise, you're finished.

Step 2: Populate your template

In step 1, you defined the run mode implicitly by creating a correspondingly named template. Each run mode xxx requires a corresponding method showXxx to produce a dynamic page; this method may be omitted if the page is static. So, if picture.thtml includes some template variables, create a showPicture method in this (cgiAppBase.pl) file. You'll see examples of showXxx methods below. The name of the method is important: it must have the show prefix, concatenated to the run mode, with the first letter in uppercase. In this method, you call methods to fill out the template. Again, see examples here and/or the HTML::Template documentation.

If you encounter errors or warnings that you wish to communicate to the user inside your showXxx method, use setUserMsg to display a message as given, or use setSimpleMsg to display a user-qualified message. A user-qualified message will display as given if the user is the administrator, but a generic problem message will be displayed to any other user.

If your page, once displayed, then sends back data from the user, go on to Step 3; if it does not ask the user for any input, you're finished.

Step 3: Process your input

Just as the page needed a showXXX method to display data, it needs a submit button (named submitXxx), and a processXxx method to process data returned from the user. Your web page might require multiple action buttons. Each of them should have the same name (submitXxx) but different values. The skeleton method below shows how to handle an update action and a done action. No parameters are passed to the processXxx method; all needed data must be accessible from the object itself.

  sub processXxx {
    my $self = shift;
    my $action = $self->query->param("submitXxx");
    if ($action =~ /done/i) {
      return "main";
    }
    elsif ($action =~ /update/i) {
      my $success = . . .
      . . .
      return $success? 1 : 0;
    }
  }
   

The return value of this method is critical.

You may choose to return a basic true (1) or false (0), indicating success or failure of the method. If there is a failure--such as the user left a required field blank--then you want to redisplay the page, prompting the user for the missing information. Using a false return value causes the page to be redisplayed automatically. You must manually supply a string for the user prompt, via the setRevertReason method. A true return value (1), on the other hand, allows "normal" site sequencing to occur, i.e. to proceed to the run mode specified in the action attribute of the HTML form element.

Using the above paradigm, you obviously are limited to two branches, two destinations that your user may traverse to from your page. If you need more than two, then you use a slightly different mechanism. If instead of 1 or 0, you return the name of a run mode, that run mode will be the destination. You can see this in the skeleton above where the run mode main is returned.

Step 4: Support multiple web sites

You'll observe that for the Authorization database and User database described above the table names are hard-coded as auth_user and user_data, respectively. But what if you want to create a login gateway for more than one site on your server? This is simple to do. Take a look in the sample configuration file for the TABLE_PREFIX parameter. If that parameter is defined as, for example, xyz, then the table names will need to be created with the names xyz_auth_user and xyz_user_data, that is, the TABLE_PREFIX parameter, an underscore, and the standard name. If the TABLE_PREFIX parameter is undefined, then you use just the standard names. This let's you create multiple login gateways by having multiple configuration files.

Standard Web Page Templates

The framework includes these pre-defined pages:

welcome

A general starting point--a gateway page--with a link to login.

login

A specific login form (though you could include the same functionality on the welcome page).

forgotPwd

A form for the user to request a password reminder.

newAcct

A form for the user to register for a new account.

main

The entry point once a user is authenticated.

logout

Once logged out, the user gets to this general exit page.

editProfile

A form for the user to change the details they entered on the newAcct page.

user

A page accessible only to the admin user, this lists each user, along with when each account was created, its last login, and whether it is currently logged in.

error

A general error page for major errors. "Normal" errors are presented inline at the top of any page as they occur.

Standard Template Variables

The framework includes these pre-defined template variables:

dbError

Major error message(s) passed to the CGI::Application::error() method.

script

The name of this script, suitable for use as a link or form target.

generator

The name and version of this program suitable for assignment in a meta tag.

image_root

The root directory for images on your web server.

htdocs

The root directory for files on your web server (for this application).

username

The name of the current logged-in user, if any.

admin

The user name of the administrative user.

override

The user name of the assumed user ID when the admin has overridden, if any.

Examples of how to use these variables can be found in several of the template files or in the API for the templates, HTML::Template|HTML::Template. One is also free to use one's own variables in the templates, adding corresponding code in this file to manage them.

Standard Configuration Parameters

The framework includes a variety of configurable parameters; please see the sample configuration file for the list of these with explanation of their use.

Diagnostics

This framework uses the CleanCode Data::Diagnostic module for displaying diagnostic information for debugging. The details of using the module are covered in its documentation; in a nutshell, use diagA->print(string) to generate a message. In the main configuration file you specify which diagnostic messages are displayed, via DIAG_LEVEL parameter, and which channel they are displayed on (log file, web page, etc.), via OUTPUT_DIAG and/or OUTPUT_ERR parameters.

Note that you may override configuration settings in your browser. Instead of, for example:

        http://xxx/cgi-bin/cgiAppBase.pl/picture

use

        http://xxx/cgi-bin/cgiAppBase.pl/picture?DIAG_LEVEL=0x4000000A

to set a value for the DIAG_LEVEL parameter. Note, however, that if DIAG_LEVEL is defined in the configuration file, then browser overrides will only affect the single web page requested. If it is not defined in the configuration file, then browser overrides will be persistent. Also, a browser override affects only the browser that sets the value; all other users will use the configuration file value.

The display of diagnostics is richer when displayed on the actual web page, since it can make use of HTML formatting and style sheets (CSS) to present the data, compared to plain text when outputting to a log file. Note that each possible diagnostic level (32 total) has its own style available; see the sample style sheet included with this application.

There is a variety of diagnostic information pre-formatted and available at the proverbial flick of a switch (i.e. setting a bit in DIAG_LEVEL), including CGI environment, cookies, HTTP transaction information, module versions, run mode/template chart, and others. See the main configuration file for the settings.

CLASS VARIABLES

VERSION

Current version of this class.

LOG_CONF

Configuration file for Log4perl ("conf/cgi-log.conf").

DIAG_CONF

Configuration file for general configuration and for diagnostics ("conf/cgi-diag.conf").

TO BE DONE

N/A

BUGS

None

AUTHOR

Michael Sorens

VERSION

$Revision: 1178 $ $Date: 2011-10-31 14:26:51 -0700 (Mon, 31 Oct 2011) $

SINCE

CleanCode 0.9.05

POD ERRORS

Hey! The above document had some coding errors, which are explained below:

Around line 532:

=back doesn't take any parameters, but you said =back -- end of CLASS VARIABLES section


CleanCode Perl Libraries Copyright © 2001-2013 Michael Sorens - Revised 2013.06.30 Get CleanCode at SourceForge.net. Fast, secure and Free Open Source software downloads