[Bps-public-commit] rtx-rest branch, dev, created. 2f44aed252cf0df9450f8c5e3ce6e2235d58d229

Wallace Reis wreis at bestpractical.com
Tue Dec 16 11:12:10 EST 2014


The branch, dev has been created
        at  2f44aed252cf0df9450f8c5e3ce6e2235d58d229 (commit)

- Log -----------------------------------------------------------------
commit e5748fdc5fe8a3c841e13eb58424186f6907baef
Author: Wallace Reis <wreis at bestpractical.com>
Date:   Mon Dec 15 18:26:16 2014 -0200

    Move Log middleware to its class

diff --git a/lib/RT/Extension/REST2.pm b/lib/RT/Extension/REST2.pm
index 55b00d7..1786b66 100644
--- a/lib/RT/Extension/REST2.pm
+++ b/lib/RT/Extension/REST2.pm
@@ -182,48 +182,48 @@ sub to_psgi_app { shift->to_app(@_) }
 
 sub to_app {
     my $class = shift;
-    return sub {
-        my ($env) = @_;
-        $env->{'psgix.logger'} = sub {
-            my $what = shift;
-            RT->Logger->log(%$what);
-        };
-        # XXX TODO: logging of SQL queries in RT's framework for doing so
+
+    return builder {
+        enable '+RT::Extension::REST2::Middleware::Log';
+
         # XXX TODO: Need a dispatcher?  Or do it inside resources?  Web::Simple?
         RT::ConnectToDatabase();
-        my $dispatch = builder {
-            # XXX TODO: better auth integration
-            enable "Auth::Basic",
-                realm         => RT->Config->Get("rtname") . " API",
-                authenticator => sub {
-                    my ($user, $pass, $env) = @_;
-                    my $cu = RT::CurrentUser->new;
-                    $cu->Load($user);
-
-                    if ($cu->id and $cu->IsPassword($pass)) {
-                        $env->{"rt.current_user"} = $cu;
-                        return 1;
-                    } else {
-                        RT->Logger->error("FAILED LOGIN for $user from $env->{REMOTE_ADDR}");
-                        return 0;
-                    }
-                };
-            for ($class->resources) {
-                (my $path = lc $_) =~ s{::}{/}g;
-                mount "/$path" => resource($_);
-            }
-            mount "/"       => sub { [ 404, ['Content-type' => 'text/plain'], ['Unknown resource'] ] };
-        };
-        $dispatch->(@_);
-    }
+        sub {
+            my ($env) = @_;
+            my $dispatch = builder {
+                # XXX TODO: better auth integration
+                enable "Auth::Basic",
+                    realm         => RT->Config->Get("rtname") . " API",
+                    authenticator => sub {
+                        my ($user, $pass, $env) = @_;
+                        my $cu = RT::CurrentUser->new;
+                        $cu->Load($user);
+
+                        if ($cu->id and $cu->IsPassword($pass)) {
+                            $env->{"rt.current_user"} = $cu;
+                            return 1;
+                        } else {
+                            RT->Logger->error("FAILED LOGIN for $user from $env->{REMOTE_ADDR}");
+                            return 0;
+                        }
+                    };
+                for ($class->resources) {
+                    (my $path = lc $_) =~ s{::}{/}g;
+                    mount "/$path" => resource($_);
+                }
+                mount "/"       => sub { [ 404, ['Content-type' => 'text/plain'], ['Unknown resource'] ] };
+            };
+            $dispatch->(@_);
+        }
+    };
 }
 
 # Called by RT::Interface::Web::Handler->PSGIApp
 sub PSGIWrap {
     my ($class, $app) = @_;
-    builder {
-        mount "/REST/2.0"   => $class->to_app;
-        mount "/"           => $app;
+    return builder {
+        mount '/REST/2.0' => $class->to_app;
+        mount '/' => $app;
     };
 }
 
diff --git a/lib/RT/Extension/REST2/Middleware/Log.pm b/lib/RT/Extension/REST2/Middleware/Log.pm
new file mode 100644
index 0000000..75e95b1
--- /dev/null
+++ b/lib/RT/Extension/REST2/Middleware/Log.pm
@@ -0,0 +1,20 @@
+package RT::Extension::REST2::Middleware::Log;
+
+use strict;
+use warnings;
+
+use base 'Plack::Middleware';
+
+sub call {
+    my ( $self, $env ) = @_;
+
+    # XXX TODO: logging of SQL queries in RT's framework for doing so
+    $env->{'psgix.logger'} = sub {
+        my $what = shift;
+        RT->Logger->log(%$what);
+    };
+
+    return $self->app->($env);
+}
+
+1;

commit 38558c271fbc97c64966ff8d0c3ba770e3c1ca47
Author: Wallace Reis <wreis at bestpractical.com>
Date:   Mon Dec 15 18:35:36 2014 -0200

    Move Auth middleware to its own class

diff --git a/Makefile.PL b/Makefile.PL
index ff9b102..662a183 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -18,6 +18,7 @@ requires 'Plack::Builder';
 requires 'Scalar::Util';
 requires 'Sub::Exporter';
 requires 'Web::Machine' => '0.12';
+requires 'Class::Method::Modifiers';
 
 sign;
 WriteAll;
diff --git a/TODO b/TODO
index f783fad..5fb013e 100644
--- a/TODO
+++ b/TODO
@@ -11,7 +11,6 @@ Find TODOs in the code via `ag TODO`.
   - /scrips
   - /roles
   - /templates
-* Implement Basic HTTP authen
 * Remove any session mocking
 
 XXX TODO: Include Links in record serializations
diff --git a/lib/RT/Extension/REST2.pm b/lib/RT/Extension/REST2.pm
index 1786b66..7f6ca03 100644
--- a/lib/RT/Extension/REST2.pm
+++ b/lib/RT/Extension/REST2.pm
@@ -132,10 +132,9 @@ numbers start at 1.
 
 =head2 Authentication
 
-Currently authentication is limited to internal RT usernames and passwords,
-provided via HTTP Basic auth.  Most HTTP libraries already have a way of
-providing basic auth credentials when making requests.  Using curl, for
-example:
+Authentication is limited to internal RT usernames and passwords, provided via
+HTTP Basic auth. Most HTTP libraries already have a way of providing basic
+auth credentials when making requests.  Using curl, for example:
 
     curl -u username:password …
 
@@ -183,30 +182,15 @@ sub to_psgi_app { shift->to_app(@_) }
 sub to_app {
     my $class = shift;
 
+    RT::ConnectToDatabase();
+
     return builder {
         enable '+RT::Extension::REST2::Middleware::Log';
+        enable '+RT::Extension::REST2::Middleware::Auth';
 
-        # XXX TODO: Need a dispatcher?  Or do it inside resources?  Web::Simple?
-        RT::ConnectToDatabase();
         sub {
             my ($env) = @_;
             my $dispatch = builder {
-                # XXX TODO: better auth integration
-                enable "Auth::Basic",
-                    realm         => RT->Config->Get("rtname") . " API",
-                    authenticator => sub {
-                        my ($user, $pass, $env) = @_;
-                        my $cu = RT::CurrentUser->new;
-                        $cu->Load($user);
-
-                        if ($cu->id and $cu->IsPassword($pass)) {
-                            $env->{"rt.current_user"} = $cu;
-                            return 1;
-                        } else {
-                            RT->Logger->error("FAILED LOGIN for $user from $env->{REMOTE_ADDR}");
-                            return 0;
-                        }
-                    };
                 for ($class->resources) {
                     (my $path = lc $_) =~ s{::}{/}g;
                     mount "/$path" => resource($_);
diff --git a/lib/RT/Extension/REST2/Middleware/Auth.pm b/lib/RT/Extension/REST2/Middleware/Auth.pm
new file mode 100644
index 0000000..18587de
--- /dev/null
+++ b/lib/RT/Extension/REST2/Middleware/Auth.pm
@@ -0,0 +1,29 @@
+package RT::Extension::REST2::Middleware::Auth;
+
+use strict;
+use warnings;
+
+use base 'Plack::Middleware::Auth::Basic';
+
+use Class::Method::Modifiers;
+
+before prepare_app => sub {
+    my $self = shift;
+    $self->realm( RT->Config->Get('rtname') . ' REST API' );
+
+    $self->authenticator(sub {
+        my ($user, $pass, $env) = @_;
+        my $cu = RT::CurrentUser->new;
+        $cu->Load($user);
+        if ($cu->id and $cu->IsPassword($pass)) {
+            $env->{'rt.current_user'} = $cu;
+            return 1;
+        }
+        else {
+            RT->Logger->info("Failed login for $user");
+            return 0;
+        }
+    });
+};
+
+1;

commit d87a2e4cd07bee19ca4bc4877ce30d76b1d2235a
Author: Wallace Reis <wreis at bestpractical.com>
Date:   Mon Dec 15 19:29:25 2014 -0200

    PSGIWrap mount apps' paths
    
    When putting RT somewhere other than at the root of the server, then
    we need to have REST API respect that and serve requests on the correct
    base path. This aim to fix the wrong initial behavior of this extension
    by respecting $WebPath config option.
    
    Additionally, creates the $RESTPath config option to make the relative
    REST API path parametrizable and have a default value not spreaded as
    a magical value on the source code.

diff --git a/lib/RT/Extension/REST2.pm b/lib/RT/Extension/REST2.pm
index 7f6ca03..099734d 100644
--- a/lib/RT/Extension/REST2.pm
+++ b/lib/RT/Extension/REST2.pm
@@ -5,6 +5,7 @@ use 5.010;
 package RT::Extension::REST2;
 
 our $VERSION = '0.01';
+our $DEFAULT_REST_PATH = '/REST/2.0';
 
 use UNIVERSAL::require;
 use Plack::Builder;
@@ -20,7 +21,7 @@ RT-Extension-REST2 - Adds a modern REST API to RT under /REST/2.0/
 
 =head2 Summary
 
-Currently provided endpoints under C</REST/2.0/> are:
+Currently provided endpoints under C<$RESTPath> are:
 
     GET /ticket/:id
     PUT /ticket/:id <JSON body>
@@ -139,7 +140,7 @@ auth credentials when making requests.  Using curl, for example:
     curl -u username:password …
 
 This sort of authentication should B<always> be done over HTTPS/SSL for
-security.  You should only serve up the C</REST/2.0/> endpoint over SSL.
+security.  You should only serve up the C<$RESTPath> endpoint over SSL.
 
 =head2 Conditional requests (If-Modified-Since)
 
@@ -202,21 +203,26 @@ sub to_app {
     };
 }
 
-# Called by RT::Interface::Web::Handler->PSGIApp
-sub PSGIWrap {
-    my ($class, $app) = @_;
-    return builder {
-        mount '/REST/2.0' => $class->to_app;
-        mount '/' => $app;
-    };
-}
+sub rest_path { RT->Config->Get('RESTPath') || $DEFAULT_REST_PATH }
 
 sub base_path {
-    RT->Config->Get("WebPath") . "/REST/2.0"
+    RT->Config->Get('WebPath') . shift->rest_path
 }
 
 sub base_uri {
-    RT->Config->Get("WebBaseURL") . base_path()
+    RT->Config->Get('WebBaseURL') . shift->base_path
+}
+
+# Called by RT::Interface::Web::Handler->PSGIApp
+sub PSGIWrap {
+    my ($class, $app) = @_;
+    my $rt_path = RT->Config->Get('WebPath') || '/';
+    my $rest_path = $rt_path . $class->rest_path;
+       $rest_path =~ s{//}{/};
+    return builder {
+        mount $rt_path => $app;
+        mount $rest_path => $class->to_app;
+    };
 }
 
 =head1 INSTALLATION

commit 2f44aed252cf0df9450f8c5e3ce6e2235d58d229
Author: Wallace Reis <wreis at bestpractical.com>
Date:   Tue Dec 16 14:06:10 2014 -0200

    Documentation changes

diff --git a/lib/RT/Extension/REST2.pm b/lib/RT/Extension/REST2.pm
index 099734d..0647832 100644
--- a/lib/RT/Extension/REST2.pm
+++ b/lib/RT/Extension/REST2.pm
@@ -15,7 +15,49 @@ use Web::Machine;
 
 =head1 NAME
 
-RT-Extension-REST2 - Adds a modern REST API to RT under /REST/2.0/
+RT-Extension-REST2 - Adds a modern REST API to RT
+
+=head1 INSTALLATION
+
+=over
+
+=item C<perl Makefile.PL>
+
+=item C<make>
+
+=item C<make install>
+
+May need root permissions
+
+=item Edit your F</opt/rt4/etc/RT_SiteConfig.pm>
+
+Add this line:
+
+    Plugin('RT::Extension::REST2');
+
+=item Clear your mason cache
+
+    rm -rf /opt/rt4/var/mason_data/obj
+
+=item Restart your webserver
+
+=back
+
+=head1 CONFIGURATION
+
+=over
+
+=item C<$RESTPath>
+
+The relative path from C<$WebPath> where you want to have the REST API being
+served.
+
+C<$RESTPath> requires a leading / but no trailing /, or it can be blank.
+
+Defaults to C</REST/2.0>. Thus, if you have C<$WebPath> set to C</rt> then the
+base REST API URI will be like C<https://example.com/rt/REST/2.0>.
+
+=back
 
 =head1 USAGE
 
@@ -87,7 +129,7 @@ These resources accept a basic JSON structure as the search conditions which
 specifies one or more fields to limit on (using specified operators and
 values).  An example:
 
-    curl -si -u user:pass http://rt.example.com/REST/2.0/queues -XPOST --data-binary '
+    curl -si -u user:pass https://rt.example.com/REST/2.0/queues -XPOST --data-binary '
         [
             { "field":    "Name",
               "operator": "LIKE",
@@ -225,35 +267,9 @@ sub PSGIWrap {
     };
 }
 
-=head1 INSTALLATION
-
-=over
-
-=item C<perl Makefile.PL>
-
-=item C<make>
-
-=item C<make install>
-
-May need root permissions
-
-=item Edit your F</opt/rt4/etc/RT_SiteConfig.pm>
-
-Add this line:
-
-    Plugin('RT::Extension::REST2');
-
-=item Clear your mason cache
-
-    rm -rf /opt/rt4/var/mason_data/obj
-
-=item Restart your webserver
-
-=back
-
 =head1 AUTHOR
 
-Thomas Sibley <trs at bestpractical.com>
+Best Practical Solutions, LLC <modules at bestpractical.com>
 
 =head1 BUGS
 

-----------------------------------------------------------------------


More information about the Bps-public-commit mailing list