[Catalyst-commits] r14366 - CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD

karpet at dev.catalyst.perl.org karpet at dev.catalyst.perl.org
Wed Oct 31 18:11:13 GMT 2012


Author: karpet
Date: 2012-10-31 18:11:13 +0000 (Wed, 31 Oct 2012)
New Revision: 14366

Modified:
   CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD/Controller.pm
   CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD/REST.pm
Log:
fix rest compat for list_related and view_related

Modified: CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD/Controller.pm
===================================================================
--- CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD/Controller.pm	2012-10-31 06:13:55 UTC (rev 14365)
+++ CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD/Controller.pm	2012-10-31 18:11:13 UTC (rev 14366)
@@ -581,14 +581,6 @@
         $self->throw_error('Permission denied');
         return;
     }
-    if ( !$self->allow_GET_writes ) {
-        if ( uc( $c->req->method ) ne 'POST' ) {
-            $c->res->status(400);
-            $c->res->body('GET request not allowed');
-            $c->stash->{error} = 1;    # so has_errors() will return true
-            return;
-        }
-    }
     $c->stash( rel_name         => $rel );
     $c->stash( foreign_pk_value => $fpk_value );
 }
@@ -611,8 +603,24 @@
 
 =cut
 
+sub _check_idempotent {
+    my ( $self, $c ) = @_;
+    if ( !$self->allow_GET_writes ) {
+        if ( uc( $c->req->method ) ne 'POST' ) {
+            $c->log->warn( "allow_GET_writes!=true, related method="
+                    . uc( $c->req->method ) );
+            $c->res->status(405);
+            $c->res->header( 'Allow' => 'POST' );
+            $c->res->body('GET request not allowed');
+            $c->stash->{error} = 1;    # so has_errors() will return true
+            return;
+        }
+    }
+}
+
 sub remove : PathPart Chained('related') Args(0) {
     my ( $self, $c ) = @_;
+    $self->_check_idempotent($c);
     return if $self->has_errors($c);
     $self->do_model(
         $c, 'rm_related', $c->stash->{object},
@@ -643,6 +651,7 @@
 
 sub add : PathPart Chained('related') Args(0) {
     my ( $self, $c ) = @_;
+    $self->_check_idempotent($c);
     return if $self->has_errors($c);
     $self->do_model(
         $c, 'add_related', $c->stash->{object},
@@ -680,13 +689,17 @@
 
 sub list_related : PathPart('list') Chained('fetch_related') Args(0) {
     my ( $self, $c, $rel ) = @_;
+    unless ( $self->can_read($c) ) {
+        $self->throw_error('Permission denied');
+        return;
+    }
     return if $self->has_errors($c);
-    $c->stash(
-        results => scalar $self->do_model(
-            $c,                  'iterator_related',
-            $c->stash->{object}, $c->stash->{rel_name},
-        )
-    );
+    $self->view($c);    # set form
+    my $results
+        = $self->do_model( $c, 'iterator_related', $c->stash->{object},
+        $c->stash->{rel_name},
+        );
+    $c->stash( results => $results );
 }
 
 =head2 view_related
@@ -705,12 +718,18 @@
 
 sub view_related : PathPart('view') Chained('related') Args(0) {
     my ( $self, $c ) = @_;
+    unless ( $self->can_read($c) ) {
+        $self->throw_error('Permission denied');
+        return;
+    }
     return if $self->has_errors($c);
-    $self->do_model(
+    $self->view($c);    # set form
+    my $result = $self->do_model(
         $c, 'find_related', $c->stash->{object},
         $c->stash->{rel_name},
         $c->stash->{foreign_pk_value}
     );
+    $c->stash( results => $result );
 }
 
 =head1 INTERNAL METHODS

Modified: CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD/REST.pm
===================================================================
--- CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD/REST.pm	2012-10-31 06:13:55 UTC (rev 14365)
+++ CatalystX-CRUD/CatalystX-CRUD/trunk/lib/CatalystX/CRUD/REST.pm	2012-10-31 18:11:13 UTC (rev 14366)
@@ -155,6 +155,7 @@
     $c->log->debug( "rpc compat mode = " . $self->enable_rpc_compat )
         if $c->debug;
     $c->log->debug( "rest args : " . dump \@arg ) if $c->debug;
+    $c->log->debug( "rest action->name=" . $c->action->name ) if $c->debug;
 
     my $n = scalar @arg;
     if ( $n <= 2 ) {
@@ -223,6 +224,9 @@
             $rpc_method      = 'list_related';
             $dispatch_method = 'fetch_related';
         }
+        elsif ($fval) {
+            $rpc_method = 'view_related';
+        }
         else {
             $c->res->status(400);
             $c->res->body("Bad HTTP request for method $http_method");
@@ -237,6 +241,8 @@
         $c->res->body("Bad HTTP request for method $http_method");
         return;
     }
+    $c->log->debug("rest dispatch: $dispatch_method( $rel_name, $fval )")
+        if $c->debug;
     $self->$dispatch_method( $c, $rel_name, $fval );
     $self->_call_rpc_method_as_action( $c, $rpc_method, $oid );
 }
@@ -250,18 +256,33 @@
     my $oid = shift @arg || '';
     my $rpc = shift @arg;
 
-    $c->log->debug("rest OID: $oid") if $c->debug;
+    my $http_method = $self->req_method($c);
+    $c->log->debug("rest OID:$oid  rpc:$rpc  http:$http_method")
+        if $c->debug;
 
-    if ($rpc) {
-        if ( !$self->enable_rpc_compat or !exists $rpc_methods{$rpc} ) {
+    if ( length $oid and $rpc ) {
+        if ( exists $rpc_methods{$rpc} ) {
+
+            # do nothing - logic below
+        }
+        elsif ( $http_method eq 'GET' ) {
+
+            # same logic as !length $oid below:
+            # assume that $rpc is a relationship name
+            # and a 'list' is being requested
+            $c->log->debug(
+                "GET request with OID and unknown rpc; assuming 'list_related'"
+            ) if $c->debug;
+            $self->fetch_related( $c, $rpc );
+            $rpc = 'list_related';
+        }
+        elsif ( !$self->enable_rpc_compat or !exists $rpc_methods{$rpc} ) {
             $self->_set_status_404($c);
             return;
         }
     }
 
-    my $method = $self->req_method($c);
-
-    if ( !length $oid && $method eq 'GET' ) {
+    if ( !length $oid and $http_method eq 'GET' ) {
         $c->log->debug("GET request with no OID") if $c->debug;
         $c->action->name('list');
         $c->action->reverse( join( '/', $c->action->namespace, 'list' ) );
@@ -269,13 +290,17 @@
     }
 
     # what RPC-style method to call
-    my $rpc_method = defined($rpc) ? $rpc : $http_method_map{$method};
+    my $rpc_method = defined($rpc) ? $rpc : $http_method_map{$http_method};
 
     # backwards compat naming for RPC style
     if ( $rpc_method =~ m/^(create|edit)$/ ) {
         $rpc_method .= '_form';
     }
 
+    if ( !$self->can($rpc_method) ) {
+        $c->log->warn("no such rpc method in class: $rpc_method");
+    }
+
     $self->_call_rpc_method_as_action( $c, $rpc_method, $oid );
 }
 
@@ -286,7 +311,7 @@
 
     my $http_method = $self->req_method($c);
 
-    $c->log->debug("$http_method -> $rpc_method") if $c->debug;
+    $c->log->debug("rpc: $http_method -> $rpc_method") if $c->debug;
 
     # so View::TT (others?) auto-template-deduction works just like RPC style
     $c->action->name($rpc_method);




More information about the Catalyst-commits mailing list