X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?p=catagits%2FCatalyst-Manual.git;a=blobdiff_plain;f=lib%2FCatalyst%2FManual%2FTutorial%2FAuthorization.pod;fp=lib%2FCatalyst%2FManual%2FTutorial%2FAuthorization.pod;h=0000000000000000000000000000000000000000;hp=fce6161619b09cb046ac8b392d37005ac6184207;hb=3ab6187c1a123983b6ae29e57f543328ce15755c;hpb=418ded01713d313bdc03308ced5b0cc408682e24 diff --git a/lib/Catalyst/Manual/Tutorial/Authorization.pod b/lib/Catalyst/Manual/Tutorial/Authorization.pod deleted file mode 100644 index fce6161..0000000 --- a/lib/Catalyst/Manual/Tutorial/Authorization.pod +++ /dev/null @@ -1,362 +0,0 @@ -=head1 NAME - -Catalyst::Manual::Tutorial::Authorization - Catalyst Tutorial - Chapter 6: Authorization - - -=head1 OVERVIEW - -This is B for the Catalyst tutorial. - -L - -=over 4 - -=item 1 - -L - -=item 2 - -L - -=item 3 - -L - -=item 4 - -L - -=item 5 - -L - -=item 6 - -B - -=item 7 - -L - -=item 8 - -L - -=item 9 - -L - -=item 10 - -L - -=back - - -=head1 DESCRIPTION - -This chapter of the tutorial adds role-based authorization to the -existing authentication implemented in Chapter 5. It provides simple -examples of how to use roles in both TT templates and controller -actions. The first half looks at basic authorization concepts. The -second half looks at how moving your authorization code to your model -can simplify your code and make things easier to maintain. - -You can checkout the source code for this example from the catalyst -subversion repository as per the instructions in -L. - - -=head1 BASIC AUTHORIZATION - -In this section you learn the basics of how authorization works under -Catalyst. - - -=head2 Update Plugins to Include Support for Authorization - -Edit C and add C to the list: - - # Load plugins - use Catalyst qw/-Debug - ConfigLoader - Static::Simple - - StackTrace - - Authentication - Authorization::Roles - - Session - Session::Store::FastMmap - Session::State::Cookie - /; - -B As discussed in MoreCatalystBasics, different versions of -C have used a variety of methods to load the plugins. -You can put the plugins in the C statement if you -prefer. - -Once again (remain sharp, by now you should be getting the hang of things) -include this additional plugin as a new dependency in the Makefile.PL file -like this: - - requires ( - ... - 'Catalyst::Plugin::Authorization::Roles' => '0', - ); - -=head2 Add Role-Specific Logic to the "Book List" Template - -Open C in your editor and add the following -lines to the bottom of the file: - - ... -

Hello [% c.user.username %], you have the following roles:

- -
    - [% # Dump list of roles -%] - [% FOR role = c.user.role %]
  • [% role %]
  • [% END %] -
- -

- [% # Add some simple role-specific logic to template %] - [% # Use $c->check_user_roles() to check authz -%] - [% IF c.check_user_roles('user') %] - [% # Give normal users a link for 'logout' %] - User Logout - [% END %] - - [% # Can also use $c->user->check_roles() to check authz -%] - [% IF c.check_user_roles('admin') %] - [% # Give admin users a link for 'create' %] - Admin Create - [% END %] -

- -This code displays a different combination of links depending on the -roles assigned to the user. - - -=head2 Limit Books::add to 'admin' Users - -C statements in TT templates simply control the output that is sent -to the user's browser; it provides no real enforcement (if users know or -guess the appropriate URLs, they are still perfectly free to hit any -action within your application). We need to enhance the controller -logic to wrap restricted actions with role-validation logic. - -For example, we might want to restrict the "formless create" action to -admin-level users by editing C and -updating C to match the following code: - - =head2 url_create - - Create a book with the supplied title and rating, - with manual authorization - - =cut - - sub url_create :Chained('base') :PathPart('url_create') :Args(3) { - # In addition to self & context, get the title, rating & author_id args - # from the URL. Note that Catalyst automatically puts extra information - # after the "//check_user_roles('admin')) { - # Call create() on the book model object. Pass the table - # columns/field values we want to set as hash values - my $book = $c->model('DB::Book')->create({ - title => $title, - rating => $rating - }); - - # Add a record to the join table for this book, mapping to - # appropriate author - $book->add_to_book_author({author_id => $author_id}); - # Note: Above is a shortcut for this: - # $book->create_related('book_author', {author_id => $author_id}); - - # Assign the Book object to the stash for display in the view - $c->stash->{book} = $book; - - # Set the TT template to use - $c->stash->{template} = 'books/create_done.tt2'; - } else { - # Provide very simple feedback to the user. - $c->response->body('Unauthorized!'); - } - } - - -To add authorization, we simply wrap the main code of this method in an -C statement that calls C. If the user does not -have the appropriate permissions, they receive an "Unauthorized!" -message. Note that we intentionally chose to display the message this -way to demonstrate that TT templates will not be used if the response -body has already been set. In reality you would probably want to use a -technique that maintains the visual continuity of your template layout -(for example, using the "status" or "error" message feature added in -Chapter 3 or C to an action that shows an "unauthorized" page). - -B: If you want to keep your existing C method, you can -create a new copy and comment out the original by making it look like a -Pod comment. For example, put something like C<=begin> before -C and C<=end> after the closing C<}>. - - -=head2 Try Out Authentication And Authorization - -Press C to kill the previous server instance (if it's still -running) and restart it: - - $ script/myapp_server.pl - -Now trying going to L and you should -be taken to the login page (you might have to C or -C your browser and/or click the "User Logout" link on the book -list page). Try logging in with both C and C (both -use a password of C) and notice how the roles information -updates at the bottom of the "Book List" page. Also try the "User Logout" -link on the book list page. - -Now the "url_create" URL will work if you are already logged in as user -C, but receive an authorization failure if you are logged in as -C. Try: - - http://localhost:3000/books/url_create/test/1/6 - -while logged in as each user. Use one of the "logout" links (or go to -L in your browser directly) when you are -done. - - -=head1 ENABLE MODEL-BASED AUTHORIZATION - -Hopefully it's fairly obvious that adding detailed permission checking -logic to our controllers and view templates isn't a very clean or -scalable way to build role-based permissions into out application. As -with many other aspects of MVC web development, the goal is to have -your controllers and views be an "thin" as possible, with all of the -"fancy business logic" built into your model. - -For example, let's add a method to our C Result Class to -check if a user is allowed to delete a book. Open -C and add the following method -(be sure to add it below the "C" line): - - =head2 delete_allowed_by - - Can the specified user delete the current book? - - =cut - - sub delete_allowed_by { - my ($self, $user) = @_; - - # Only allow delete if user has 'admin' role - return $user->has_role('admin'); - } - -Here we call a C method on our user object, so we should add -this method to our Result Class. Open -C and add the following method below -the "C" line: - - =head 2 has_role - - Check if a user has the specified role - - =cut - - use Perl6::Junction qw/any/; - sub has_role { - my ($self, $role) = @_; - - # Does this user posses the required role? - return any(map { $_->role } $self->roles) eq $role; - } - -Now we need to add some enforcement inside our controller. Open -C and update the C method to -match the following code: - - =head2 delete - - Delete a book - - =cut - - sub delete :Chained('object') :PathPart('delete') :Args(0) { - my ($self, $c) = @_; - - # Check permissions - $c->detach('/error_noperms') - unless $c->stash->{object}->delete_allowed_by($c->user->get_object); - - # Use the book object saved by 'object' and delete it along - # with related 'book_authors' entries - $c->stash->{object}->delete; - - # Use 'flash' to save information across requests until it's read - $c->flash->{status_msg} = "Book deleted"; - - # Redirect the user back to the list page - $c->response->redirect($c->uri_for($self->action_for('list'))); - } - -Here, we C to an error page if the user is lacking the -appropriate permissions. For this to work, we need to make -arrangements for the '/error_noperms' action to work. Open -C and add this method: - - =head2 error_noperms - - Permissions error screen - - =cut - - sub error_noperms :Chained('/') :PathPath('error_noperms') :Args(0) { - my ($self, $c) = @_; - - $c->stash->{template} = 'error_noperms.tt2'; - } - -And also add the template file by putting the following text into -C: - - Permission Denied - -Then run the Catalyst development server script: - - $ script/myapp_server.pl - -Log in as C and create several new books using the C -feature: - - http://localhost:3000/books/url_create/Test/1/4 - -Then, while still logged in as C, click the "Delete" link next -to one of these books. The book should be removed and you should see -the usual green "Book deleted" message. Next, click the "User Logout" -link and log back in as C. Now try deleting one of the books. -You should be taken to the red "Permission Denied" message on our -error page. - -Use one of the 'Logout' links (or go to the -L URL directly) when you are done. - - -=head1 AUTHOR - -Kennedy Clark, C - -Please report any errors, issues or suggestions to the author. The -most recent version of the Catalyst Tutorial can be found at -L. - -Copyright 2006-2008, Kennedy Clark, under Creative Commons License -(L). -