Re: CGI::Application design strategy
by Ctrl-z (Friar) on Mar 02, 2004 at 10:39 UTC
|
Run_modes are like the public interface to your App - they dont need
to account for everything your app does. Id be more likely to have just
1 runmode - login - that calls private methods depending on whether the
appropriate username/password combo was coming in on the CGI params.
sub login
{
my $self = shift;
my $q = $self->query(); # ?
if($q->param("username") && $q->param("password"))
{
$self->_verify_login() ;
}
else
{
$self->_generate_form();
}
# ... do template stuff here
}
For login_retry - id probably just put a <TMPL_IF> in my original form template,
and reuse it for the retry.
<tmpl_if name="BAD_LOGIN">
Sorry please try again...
</tmpl_if>
<form>...</form>
Hope that helps
time was, I could move my arms like a bird and...
| [reply] |
Re: CGI::Application design strategy
by dragonchild (Archbishop) on Mar 02, 2004 at 12:44 UTC
|
I use three runmodes for this purpose.
- login() presents the login form. It also optionally accepts an error message which it passes off to HTML::Template.
- validate() is the runmode executed by the login form. If the login is unsuccessful, it returns a call to login() with the appropriate error message. If it is successful, it calls home(). validate() doesn't display anything of its own.
- home() displays the home page. It's a passthru to HTML::Template, with the appropriate values for the specific user set. (It doesn't do any processing of its own - all the user processing is done in a base class.)
I hope that helps.
------
We are the carpenters and bricklayers of the Information Age.
Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.
| [reply] |
Re: CGI::Application design strategy
by Corion (Patriarch) on Mar 02, 2004 at 09:38 UTC
|
I didn't find anything wrong with the run mode switching in CGI::Application, but I didn't do authentication through it.
You say in your intro, that you have two run modes, "login" and "login_submit", but later on, you mention a third run mode, which I would calll "login_retry". I would redirect the user from a failed login to the login_retry run mode, either internally (by changing the used template) or externally, by sending the correct location: redirect.
| [reply] |
Re: CGI::Application design strategy
by larsen (Parson) on Mar 02, 2004 at 15:29 UTC
|
I'm used to write two runmodes for every panel in my application. In your case, they would be login and login_update. Given a method redirect to set the appropriate headers, the code could be the following (not-so-pseudo-code):
# Does nothing except printing the form.
# Using sessions you can pass to it an error_message,
# for example.
#
sub login
+
{
my $self = shift;
+
my $tmpl = $self->load_tmpl( 'login' );
+
return $tmpl->output();
+
}
sub login_update
+
{
my $self = shift;
+
my $q = $self->query;
# Fetch username and password from the form
#
if ( PASSWORD CORRECT ) {
$self->redirect( { rm => 'first_panel' } );
}
else {
# It could store some useful info in a session,
# for example the error message.
#
$self->redirect( { rm => 'login' } );
}
return;
}
I use this technique a lot, and it has proven its flexibility and
efficiency. | [reply] [d/l] [select] |
|
I realise you say the above is psuedo code but I have to ask. How do you normally represent:
$self->redirect( { rm => 'first_panel' } );
In your normal applications? Do you have a template method like the following (this is naturally untested):
sub redirect {
my $self = shift;
my $mode = shift;
my $new_url = $self->param('app_url') . $mode->{'rm'};
$self->header_type('redirect');
$self->header_props(-url=>$new_url);
return "Redirecting to $new_url";
}
I ask as I have wanted to switch between run modes based on data and have had to stick with these kind of methods. Either that or I call the runmode method directly.
Just a quick question - I'm sure the answer is yes but I thought I would ask anyhoo. | [reply] [d/l] [select] |
|
The answer is yes. My actual code is pretty similar to yours.
sub build_redirect
{
my ($self, $form, $script) = @_;
$form ||= {};
+
my $q = $self->query;
my $uri = URI->new( $script || $q->script_name );
+
$uri->query_form(%$form);
+
return $uri->as_string;
}
sub redirect
{
my $self = shift;
+
$self->header_add( -uri => $self->build_redirect( @_ ) );
+
$self->header_type('redirect');
+
}
| [reply] [d/l] |
|
If you want to switch run modes in mid-stream your current run mode just has to call the runmode that you want.
There is never any need for a normal CGI::Application based app to use redirect headers to access
another runmode unless the resource has actually moved (e.g. has a new URL)
Here is larsen's example modified updated to remove the
redirect.
# Does nothing except printing the form.
# Using sessions you can pass to it an error_message,
# for example.
#
sub login
+
{
my $self = shift;
+
my $tmpl = $self->load_tmpl( 'login' );
+
return $tmpl->output();
+
}
sub login_update
+
{
my $self = shift;
+
my $q = $self->query;
# Fetch username and password from the form
#
if ( PASSWORD CORRECT ) {
return $self->first_panel;
}
else {
# It could store some useful info in a session,
# for example the error message.
#
return $self->login;
}
# You have a problem if this return ever actually executed
#return;
}
--
Clayton
| [reply] [d/l] |
|
|
Re: CGI::Application design strategy
by zby (Vicar) on Mar 02, 2004 at 12:21 UTC
|
In my app I just call the other mode from inside of my analog of login_submit:
sub login_submit{
my $self = shift;
.
.
.
if(badlogin()){
return $self->login();
}
}
Update: Added 'return' (following rchiav). | [reply] [d/l] |
|
Since your login_submit sub has to return what's to be displayed to the browser, don't you have to do
if(badlogin()){
return $self->login();
}
?
| [reply] [d/l] |
|
| [reply] |
|
Yeah - you are right. That's how I did that. I can't comment on what jdtoronto wrote.
| [reply] |
Re: CGI::Application design strategy
by esskar (Deacon) on Mar 02, 2004 at 10:30 UTC
|
i would definitly go with location-redirect using the "Status: 302 Moved" and the "Location" header-field. There is nothing wrong with that and inefficienty can not be your reason of not doing it! | [reply] |