X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fp5-CGI-Ex;a=blobdiff_plain;f=lib%2FCGI%2FEx%2FApp.pod;fp=lib%2FCGI%2FEx%2FApp.pod;h=6fe97464e0e828e7d241fff509c46dcfe814ffd8;hp=0188cdc40e6c0d38d508384a491d956f05fd4094;hb=419d9570723c210429e2be23875160f57dd36156;hpb=aa030874456c91d688e6c9b25e82d2bf9575ea6f diff --git a/lib/CGI/Ex/App.pod b/lib/CGI/Ex/App.pod index 0188cdc..6fe9746 100644 --- a/lib/CGI/Ex/App.pod +++ b/lib/CGI/Ex/App.pod @@ -202,6 +202,9 @@ The nav_loop method will run as follows: foreach step of path { + ->require_auth (hook) + # exits nav_loop if true + ->morph # check ->allow_morph # check ->allow_nested_morph @@ -314,31 +317,31 @@ The default out of the box configuration will map URIs to steps as follows: # Assuming /cgi-bin/my_app is the program being run - URI: /cgi-bin/my_app + URI: /cgi-bin/my_app STEP: main FORM: {} WHY: No other information is passed. The path method is called which eventually calls ->default_step which defaults to "main" - URI: /cgi-bin/my_app?foo=bar + URI: /cgi-bin/my_app?foo=bar STEP: main FORM: {foo => "bar"} WHY: Same as previous example except that QUERY_STRING information was passed and placed in form. - URI: /cgi-bin/my_app?step=my_step + URI: /cgi-bin/my_app?step=my_step STEP: my_step FORM: {step => "my_step"} WHY: The path method is called which looks in $self->form for the key ->step_key (which defaults to "step"). - URI: /cgi-bin/my_app?step=my_step&foo=bar + URI: /cgi-bin/my_app?step=my_step&foo=bar STEP: my_step FORM: {foo => "bar", step => "my_step"} - WHY: Same as before but has other parameters were passed. + WHY: Same as before but another parameter was passed. - URI: /cgi-bin/my_app/my_step + URI: /cgi-bin/my_app/my_step STEP: my_step FORM: {step => "my_step"} WHY: The path method is called which called path_info_map_base @@ -348,12 +351,12 @@ The default out of the box configuration will map URIs to steps as follows: $self->form->{$self->step_key} for the initial step. See the path_info_map_base method for more information. - URI: /cgi-bin/my_app/my_step?foo=bar + URI: /cgi-bin/my_app/my_step?foo=bar STEP: my_step FORM: {foo => "bar", step => "my_step"} WHY: Same as before but other parameters were passed. - URI: /cgi-bin/my_app/my_step?step=other_step + URI: /cgi-bin/my_app/my_step?step=other_step STEP: other_step FORM: {step => "other_step"} WHY: The same procedure took place, but when the PATH_INFO @@ -371,7 +374,7 @@ that the following method is installed in your script. ]; } - URI: /cgi-bin/my_app/my_step/bar + URI: /cgi-bin/my_app/my_step/bar STEP: my_step FORM: {foo => "bar"} WHY: The step was matched as in previous examples using @@ -381,7 +384,7 @@ that the following method is installed in your script. and the corresponding matched value was placed into the form using the keys specified following the regex. - URI: /cgi-bin/my_app/my_step/bar/1234 + URI: /cgi-bin/my_app/my_step/bar/1234 STEP: my_step FORM: {foo => "bar", id => "1234"} WHY: Same as the previous example, except that the first @@ -391,19 +394,19 @@ that the following method is installed in your script. order that will match the most data. The third regex would also match this PATH_INFO. - URI: /cgi-bin/my_app/my_step/some/other/type/of/data + URI: /cgi-bin/my_app/my_step/some/other/type/of/data STEP: my_step FORM: {anything_else => 'some/other/type/of/data'} WHY: Same as the previous example, except that the third regex matched. - URI: /cgi-bin/my_app/my_step/bar?bling=blang + URI: /cgi-bin/my_app/my_step/bar?bling=blang STEP: my_step FORM: {foo => "bar", bling => "blang"} - WHY: Same as the first step, but additional QUERY_STRING + WHY: Same as the first sample, but additional QUERY_STRING information was passed. - URI: /cgi-bin/my_app/my_step/one%20two?bar=three%20four + URI: /cgi-bin/my_app/my_step/one%20two?bar=three%20four STEP: my_step FORM: {anything_else => "one two", bar => "three four"} WHY: The third path_info_map regex matched. Note that the @@ -440,7 +443,7 @@ for more information about the many ways you can validate your data. The default hash_validation hook returns an empty hashref. This means that passed in data is all valid and the script will automatically call the step's finalize method. -The following shows how to some contrived validation to a step called "my_step". +The following shows how to add some contrived validation to a step called "my_step". sub my_step_hash_validation { return { @@ -564,7 +567,9 @@ validation files). The default file_print hook will look for content on your file system, but it can also be completely overridden to return a reference to a -scalar containing the contents of your file. Actually it can return +scalar containing the contents of your file (beginning with version 2.14 +string references can be cached which makes templates passed this way +"first class" citizens). Actually it can return anything that Template::Alloy (Template::Toolkit compatible) will treat as input. This templated html is displayed to the user during any step that enters the "print" phase. @@ -1171,6 +1176,7 @@ called is "view". debug: admin/Recipe.pm line 14 shift->dump_history = [ "Elapsed: 0.00562", + "view - require_auth - require_auth - 0.00001 - 0", "view - run_step - run_step - 0.00488 - 1", " view - pre_step - pre_step - 0.00003 - 0", " view - skip - view_skip - 0.00004 - 0", @@ -1382,8 +1388,7 @@ to the authentication object during the get_valid_auth method. =item get_valid_auth (method) -If require_auth is true at either the application level or at the -step level, get_valid_auth will be called. +If require_auth hook returns true on any given step then get_valid_auth will be called. It will call auth_args to get some default args to pass to CGI::Ex::Auth->new. It augments the args with sensible defaults that @@ -1772,8 +1777,9 @@ This starts the process flow for the path and its steps. =item navigate_authenticated (method) -Same as the method navigate but sets require_auth(1) before -running. See the require_auth method. +Same as the method navigate but calls ->require_auth(1) before +running. It will only work if the navigate_authenticated method +has not been overwritten. See the require_auth method. =item new (class method) @@ -2022,45 +2028,104 @@ had been successfully validated and acted upon. Arguments are the steps used to replace. Can be called any time. Replaces the remaining steps (if any) of the current path. -=item require_auth (method) +=item require_auth (hook) -Default undef. Can return either a true value or a hashref of step names. +Defaults to self->{require_auth} which defaults to undef. +If called as a method and passed a single value of 1, 0, or undef it will +set the value of $self->{require_auth} to that value. If set to a true +value then any subsequent step will require authentication (unless its +hook has been overwritten). -If a hashref of stepnames is returned, authentication will be turned on -at the step level. In this mode if any step is accessed, the get_valid_auth -method will be called. If it fails, then the nav_loop will be stopped -(the post_navigate method will be called - use the is_authed method to perform -different functions). Any step of the path not in the hash will not require -authentication. For example, to add authentication to add authentication -to the add, edit and delete steps you could do: +Any of the following ways can be used to require authentication on +every step. - sub require_auth { {add => 1, edit => 1, delete => 1} } +=over 4 -If a non-hash true value is returned from the require_auth method then -authentication will take place before the pre_navigation or the nav_loop methods. -If authentication fails the navigation process is exited (the post_navigate -method will not be called). +=item sub require_auth { 1 } -Alternatively you can also could do either of the following: +=item __PACKAGE__->navigate_authenticated; # instead of __PACKAGE__->navigate; - # OR +=item + + __PACKAGE__->new({require_auth => 1}->navigate; + +=item sub init { shift->require_auth(1) } - # OR +=back - __PACKAGE__->new({require_auth => 1}->navigate; +Because it is called as a hook, the current step is passed as the +first argument. If the hook returns false, no authentication will be +required on this step. If the hook returns a true, non-hashref value, +authentication will be required via the get_valid_auth method. If the +method returns a hashref of stepnames to require authentication on, +the step will require authentication via the get_valid_auth method if +the current step is in the hashref. If authentication is required and +succeeds, the step will proceed. If authentication is required and +fails at the step level the current step will be aborted, +authentication will be asked for (the post_navigate method will still +be called). + +For example you could add authentication to the add, edit, and delete +steps in any of the following ways: -If get_valid_auth returns true, in either case, the is_authed method will -return true and the auth_data will contain the authenticated user's data. -If it returns false, auth_data may possibly contain a defined but false -data object with details as to why authentication failed. +=over 4 -See the get_valid_auth method. +=item + + sub require_auth { {add => 1, edit => 1, delete => 1} } + +=item + + sub add_require_auth { 1 } + sub edit_require_auth { 1 } + sub delete_require_auth { 1 } + +=item + + sub require_auth { + my ($self, $step) = @_; + return 1 if $step && $step =~ /^(add|edit|delete)$/; + return 0; + } + +=back + +If however you wanted to require authentication on all but one or two methods +(such as requiring authentication on all but a forgot_password step) you could do +either of the following: + +=over 4 + +=item + + sub require_auth { + my ($self, $step) = @_; + return 0 if $step && $step eq 'forgot_password'; + return 1; # require auth on all other steps + } + +=item + + sub require_auth { 1 } # turn it on for all steps + + sub forgot_password_require_auth { 0 } # turn it off + +=back + +See the get_valid_auth method for what occurs should authentication be required. + +There is one key difference from the 2.14 version of App. In 2.14 and +previous versions, the pre_navigate and post_navigate methods would +not be called if require_auth returned a true non-hashref value. In +version 2.15 and later, the 2.15 pre_navigate and post_navigate +methods are always called - even if authentication fails. Also in 2.15 +and later, the method is called as a hook meaning the step is passed in. =item run_hook (method) @@ -2601,7 +2666,7 @@ the core logic of the application. return 0; } - my $s = "UPDATE recipe SET title = ?, ingredients = ?, directions = ? WHERE id = ?"; + $s = "UPDATE recipe SET title = ?, ingredients = ?, directions = ? WHERE id = ?"; $self->dbh->do($s, {}, $form->{'title'}, $form->{'ingredients'}, $form->{'directions'}, @@ -2983,6 +3048,18 @@ will cause all steps to require validation): sub require_auth { {add => 1, edit => 1, delete => 1} } +We could also enable authentication by using individual hooks as in: + + sub add_require_auth { 1 } + sub edit_require_auth { 1 } + sub delete_require_auth { 1 } + +Or we could require authentication on everything - but let a few steps in: + + sub require_auth { 1 } # turn authentication on for all + sub main_require_auth { 0 } # turn it off for main and view + sub view_require_auth { 0 } + That's it. The add, edit, and delete steps will now require authentication. See the require_auth, get_valid_auth, and auth_args methods for more information. Also see the L perldoc. @@ -2992,13 +3069,15 @@ Also see the L perldoc. The following corporation and individuals contributed in some part to the original versions. - Bizhosting.com - giving a problem that fit basic design patterns. + Bizhosting.com - giving a problem that fit basic design patterns. + + Earl Cahill - pushing the idea of more generic frameworks. - Earl Cahill - pushing the idea of more generic frameworks. + Adam Erickson - design feedback, bugfixing, feature suggestions. - Adam Erickson - design feedback, bugfixing, feature suggestions. + James Lance - design feedback, bugfixing, feature suggestions. - James Lance - design feedback, bugfixing, feature suggestions. + Krassimir Berov - feedback and some warnings issues with POD examples. =head1 AUTHOR