[Rt-commit] [svn] r897 - in RTx-Atom: . html/Atom/0.3 html/Atom/0.3/NoAuth lib/RT lib/RTx t

autrijus at pallas.eruditorum.org autrijus at pallas.eruditorum.org
Fri May 14 14:11:01 EDT 2004


Author: autrijus
Date: Fri May 14 14:11:01 2004
New Revision: 897

Added:
   RTx-Atom/lib/RT/
   RTx-Atom/lib/RT/Atom.pm
   RTx-Atom/lib/RT/Atom.pod
Removed:
   RTx-Atom/lib/RTx/
Modified:
   RTx-Atom/   (props changed)
   RTx-Atom/Makefile.PL
   RTx-Atom/html/Atom/0.3/NoAuth/spec.html
   RTx-Atom/html/Atom/0.3/dhandler
   RTx-Atom/t/1-basic.t
Log:
 ----------------------------------------------------------------------
 r4886 at not:  autrijus | 2004-05-14T18:10:50.992251Z
 
 * it's RT::Atom not RTx::Atom now.
 * RT auth.
 ----------------------------------------------------------------------


Modified: RTx-Atom/Makefile.PL
==============================================================================
--- RTx-Atom/Makefile.PL	(original)
+++ RTx-Atom/Makefile.PL	Fri May 14 14:11:01 2004
@@ -4,7 +4,7 @@
 
 use inc::Module::Install;
 
-RTx('Atom');
+RTx('RT-Atom');
 author('Autrijus Tang <autrijus at autrijus.org>');
 abstract('Atom API for RT');
 license('perl');

Modified: RTx-Atom/html/Atom/0.3/NoAuth/spec.html
==============================================================================
--- RTx-Atom/html/Atom/0.3/NoAuth/spec.html	(original)
+++ RTx-Atom/html/Atom/0.3/NoAuth/spec.html	Fri May 14 14:11:01 2004
@@ -2,12 +2,12 @@
 require lib;
 lib->import($m->base_comp->source_dir . '/../../../../lib');
 
-require RTx::Atom;
+require RT::Atom;
 require Pod::Html;
 require File::Temp;
 
 my ($fh, $filename) = File::Temp::tempfile();
-my $infile = $INC{'RTx/Atom.pm'};
+my $infile = $INC{'RT/Atom.pm'};
 $infile =~ s/pm$/pod/i;
 
 Pod::Html::pod2html(

Modified: RTx-Atom/html/Atom/0.3/dhandler
==============================================================================
--- RTx-Atom/html/Atom/0.3/dhandler	(original)
+++ RTx-Atom/html/Atom/0.3/dhandler	Fri May 14 14:11:01 2004
@@ -2,10 +2,10 @@
 <%INIT>
 require lib;
 lib->import($m->base_comp->source_dir . '/../../../lib');
-require RTx::Atom;
+require RT::Atom;
 
 # needs discussion on using MD5(pass) as Digest token
- at RT::AtomAuthenticationMethods = qw( WSSE Basic )
+ at RT::AtomAuthenticationMethods = qw( WSSE Basic RT )
     unless @RT::AtomAuthenticationMethods;
 
 my $realm = $RT::rtname;
@@ -165,6 +165,12 @@
     $nonce_cache->set( $auth_nonce, 1 );
 }
 
+AUTH_RT: {
+    last if $CurrentUser or !$methods{RT} or $atom_client;
+    $m->comp('/Elements/SetupSessionCookie', %ARGS);
+    $CurrentUser = delete $session{CurrentUser};
+}
+
 # Now for the dreaded "su anotheruser" feature...
 my $su = $r->header_in('X-RT-CurrentUser');
 if ($CurrentUser and $su and ($su ne $CurrentUser->Id) and ($su ne $CurrentUser->Name)) {

Added: RTx-Atom/lib/RT/Atom.pm
==============================================================================
--- (empty file)
+++ RTx-Atom/lib/RT/Atom.pm	Fri May 14 14:11:01 2004
@@ -0,0 +1,18 @@
+package RT::Atom;
+$RT::Atom::VERSION = '0.01';
+
+use strict;
+
+use XML::Simple;
+use Digest::MD5;
+use Digest::SHA1;
+use MIME::Base64;
+
+*RT::Date::W3CDTF = sub {
+    my $self = shift;
+    my $date = $self->ISO . 'Z';
+    $date =~ s/ /T/;
+    return $date;
+} unless defined &RT::Date::W3CDTF;
+
+1;

Added: RTx-Atom/lib/RT/Atom.pod
==============================================================================
--- (empty file)
+++ RTx-Atom/lib/RT/Atom.pod	Fri May 14 14:11:01 2004
@@ -0,0 +1,462 @@
+=head1 NAME
+
+RT::Atom - The RT-Atom API
+
+=head1 DESCRIPTION
+
+This RT extension implements a REST-style web service interface, based
+on the B<Atom draft specification>, version 0.3.
+
+For more information on Atom and REST, please consult the references
+in the L</SEE ALSO> section.
+
+=head2 The RT-Atom URI space
+
+Some example canonical URIs are:
+
+    /Atom/0.3                                   # FeedURI (Container)
+    /Atom/0.3/RT-Tickets                        # FeedURI (Container)
+    /Atom/0.3/RT-Tickets                        # PostURI (Container)
+    /Atom/0.3/RT-Tickets/15                     # EditURI (Object)
+    /Atom/0.3/RT-Tickets/15,16,17               # PostURI (ResultSet)
+    /Atom/0.3/RT-Tickets/15.Subject             # EditURI (Property)
+    /Atom/0.3/RT-Tickets/15/Transactions        # FeedURI (Container)
+
+Note that the C<15> above is the C<Id>; if you want element indice,
+use these URIs instead:
+
+    /Atom/0.3/RT-Users/*0                     # EditURI (Object)
+    /Atom/0.3/RT-Users/*-1                    # EditURI (Object)
+    /Atom/0.3/RT-Users.Count                  # EditURI (Property)
+
+A RT-Atom server may also supply alias URIs.  Whenever an user request such
+a URI, it is redirected to the canonical URL with a I<301 Moved Permanently>.
+
+Here are some example aliases:
+
+    /Atom                       # /Atom/0.3
+    /Atom/0.3/tickets           # /Atom/0.3/RT-Tickets
+    /Atom/0.3/Tickets           # /Atom/0.3/RT-Tickets
+    /Atom/0.3/Ticket/15         # /Atom/0.3/RT-Tickets/15
+    /Atom/0.3/Users/somename    # /Atom/0.3/Users/1234
+
+=head2 Sample exchange
+
+Create an C<autrijus> user, then add it to all groups that has C<root>
+as member.
+
+First, the B<RT::Client> code:
+
+    my $rt = RT::Client->new('http://guest:guest@localhost/');
+
+    my $user = $rt->Users->add(
+        Name => 'autrijus',
+        EmailAddress => 'autrijus at example.com',
+    );
+
+    $rt->Groups->search(Members => { Name => 'root' })->update(
+        Members => { add => $user },
+    );
+
+And now the actual requests and responses.  First, the Authentication
+part: (The C<Accept> header will be omitted for brevity from now on.)
+
+    HEAD /Atom/0.3
+    Accept: application/x.atom+xml,*/*
+
+        401 Authorization Required
+        WWW-Authenticate: WSSE realm="localhost", profile="UsernameToken"
+
+Log in and probe the C<Users> collection:
+
+    OPTIONS /Atom/0.3/Users
+    X-WSSE: UsernameToken Username="guest", ...
+
+        301 Moved Permanently
+        Location: /Atom/0.3/RT-Users
+
+Try again: (The C<X-WSSE> header is generated anew; it will be omitted
+for brevity from now on.)
+
+    OPTIONS /Atom/0.3/Users
+    X-WSSE: UsernameToken Username="guest", ...
+
+        200 OK
+        <entry>
+          <content type="text/xml" mode="xml">
+            <body Name=""
+                  EmailAddress=""
+                  ...>
+              ...
+            </body>
+          </content>
+        </entry>
+
+Now create a user.  RT-Atom supports two type of payloads for this,
+distinguished by their C<Content-Type> headers.  First is AtomEntry:
+
+    POST /Atom/0.3/Users
+    Content-Type: application/x.atom+xml
+
+    <entry>
+      <content type="text/xml" mode="xml">
+        <body Name="autrijus"
+              EmailAddress="autrijus at example.com" />
+      </content>
+    </entry>
+
+Another one is a form post:
+
+    POST /Atom/0.3/Users
+    Content-Type: application/x-www-form-urlencoded
+
+    Name=autrijus&EmailAddress=autrijus at example.com
+
+In both cases, the server will return:
+
+        303 See Other
+        Location: /Atom/0.3/RT-Users/20
+
+Now we can learn something about the freshly created user: 
+
+    GET /Atom/0.3/RT-Users/20
+
+        200 OK
+        <entry>
+          <content type="text/xml" mode="xml">
+            <body Name="autrijus"
+                  EmailAddress="autrijus at example.com"
+                  ...>
+              ...
+            </body>
+          </content>
+        </entry>
+
+Next we learn something about Groups:
+
+    OPTIONS /Atom/0.3/Groups
+
+        301 Moved Permanently
+        Location: /Atom/0.3/RT-Groups
+
+    OPTIONS /Atom/0.3/RT-Groups
+
+        200 OK
+        <entry>
+          <content type="text/xml" mode="xml">
+            <body Name="" ...>
+              <Members />
+            </body>
+          </content>
+        </entry>
+
+Now we make a query on Groups:
+
+    HEAD /Atom/0.3/RT-Groups?Members-name=root&rows=all
+
+        200 OK
+        Content-Location: /Atom/0.3/RT-Groups/1,2,3,5,8,13
+
+Before we perform an update on the result set, we again probe
+for its representation:
+
+    OPTIONS /Atom/0.3/RT-Groups/1,2,3,5,8,13
+
+        200 OK
+        <entry>
+          <content type="text/xml" mode="xml">
+            <body>
+              <Members />
+            </body>
+          </content>
+        </entry>
+
+Finally, the modification and its response:
+
+    POST /Atom/0.3/RT-Groups/1,2,3,5,8,13
+    Content-Type: application/x-www-form-urlencoded
+
+    Members-add=30
+
+The server may respond with this:
+
+        207 Multiple Status
+        <entry>
+          <content type="multipart/parallel" mode="xml">
+            <body>
+              <response status="200">Member added.</head>
+              <response status="200">Member added.</head>
+            </body>
+          </content>
+        </entry>
+
+=head2 Authentication
+
+The authentication algorithm uses the C<WWW-Authenticate>,
+C<Authorization>, and C<X-WSSE> headers as specified in the Atom
+Authentication Protocol.
+
+However, instead of using plaintext as the shared password between
+client and server, RT-Atom uses this digest function:
+
+    md5_hex(join(':', $username, $realm, md5_hex($password)));
+
+The RT server may choose to support other authentication methods, such
+as C<Basic> or C<Digest>.
+
+=head2 Identity Switching
+
+Once authenticated, the server should check for the C<X-RT-CurrentUser>
+header.  If this header is present, it takes one of the following actions:
+
+=over 4
+
+=item If the authenticated user does not have the C<SuperUser> right
+
+The server returns I<401 Authorization Required> without processing the
+request body.
+
+=item If the server cannot find the new user
+
+The server returns I<406 Forbidden> without processing the request body.
+
+=item If the user has the C<SuperUser> right, and a new user is found
+
+The client assumes the identity of the new user specified in the header.
+The request proceeds as usual.
+
+=back
+
+=head2 Content Negotiation
+
+The server understands a number of HTTP headers for content negotiation:
+
+=over 4
+
+=item Accept
+
+Specifies the content type the client is willing to process.  A RT-Atom
+client must include C<application/x.atom+xml> in its C<Accept> list.
+
+=item Accept-Charset
+
+The character encoding expected by the client.  If unspecified, defaults
+to C<UTF-8>.  If the requested encoding cannot represent certain codepoints
+in the response, the server must use XML character references (C<&#xABCD;>)
+instead.
+
+If none of the requested encodings are supported by the server, a I<406
+Not Acceptable> error is returned.
+
+=item Accept-Language
+
+The languages to use in human-readable C<CDATA> parts, notably response texts.
+
+=back
+
+=head1 RESOURCE TYPES
+
+=head2 Container
+
+...
+
+=head2 ResultSet
+
+...
+
+=head2 Object
+
+...
+
+=head2 Property
+
+...
+
+=head1 OPERATIONS
+
+Here is a list of all operations supported by this API, including their
+possible response status codes and meanings:
+
+=head2 Search - I<GET FeedURI>
+
+Search for objects within an container.
+
+Possible query parameters: I<rows> (mandatory), I<page>, I<query>,
+I<columns>.  Additional query parameters may also be available.
+
+If entries are found, the C<Content-Location> header is set to a URL
+pointing to the ResultSet.
+
+    200: Success.  Body is the result serialized as an AtomFeed.
+    400: Request failed.  Body is the error message.
+    404: There is no container matching the specified URI.
+
+=head2 Get - I<GET EditURI>
+
+Retrieve a representation of an object or property.
+
+Possible query parameters: I<expand>.
+
+    200: Success.  Body is the serialized item.
+    400: Request failed.  Body is the error message.
+    404: There is no object matching the specified URI.
+
+=head2 Set - I<PUT EditURI>
+
+Modifies an object or property with the serialization in the request body.
+
+    200: Success.  Body is the serialized item again.
+    400: Request failed.  Body is the error message.
+    404: There is no object matching the specified URI.
+
+Clients without I<PUT> support may use I<POST EditURI!PUT> instead.
+
+=head2 Remove - I<DELETE EditURI>
+
+Remove the specified object.
+
+    200: Successfully deleted.  Body is the success message.
+    400: Request failed.  Body is the error message.
+    404: There is no object matching the specified URI.
+
+Clients without I<DELETE> support may use I<POST EditURI!DELETE> instead.
+
+=head2 Describe - I<OPTIONS [ PostURI | EditURI | FeedURI ]>
+
+On a container's I<PostURI>, returns the schema of objects acceptable by this
+container.
+
+On an object's I<PostURI>, returns the schemata acceptable by it,
+differentiated with the C<type> attribute.
+
+On I<EditURI>, returns the schema of the object or the property, which is a
+I<GET> without actual contents.
+
+On I<FeedURI>, returns the schema of available query parameters and their types.
+
+    200: Success.  Body is the requested schema.
+    400: Request failed.  Body is the error message.
+    404: There is no container matching the specified URI.
+
+Clients without I<OPTIONS> support may use I<GET AnyURI!OPTIONS> instead.
+
+=head2 Add - I<POST PostURI> (Container)
+
+Create a new object from the AtomEntry in the request's body.
+
+    200: Created, but the new object has no EditURI.  Body is the
+         success message.
+    303: Created.  The 'Location' header is set to the new object's
+         EditURI (for subsequent Get/Update).  Body is the success message.
+    400: Request failed.  Body is the error message.
+    404: There is no container matching the specified URI.
+
+=head2 Update - I<POST PostURI> (Object)
+
+Updates an object.
+
+    207: Updated.  Body is the status code and messages for each update.
+    400: Request failed.  Body is the error message.
+    404: The specific object is not found, or supports no such post type.
+
+=head1 LINK DISCOVERY
+
+Methods, object membership and properties are all discovered via the
+C<link> tag inside I<AtomFeed> and I<AtomEntry> constructs.
+
+The design goal is to facilitate lazy loading - the client need not
+to follow the link to retrieve any representations immediately; it
+can wait until the first operation is performed on that object, and
+follow the link responsible for that operation.
+
+Whenever the client receives an Atom construct, it may look at each
+C<link> tag.  The C<title> attribute is the member name of the link;
+but if it begins with C<_>, then it is a backlink.
+
+The C<href> attribute is the target URI.  The C<rel> attribute determines
+the type of the link target:
+
+=over 4
+
+=item service.feed
+
+A Container.
+
+=item service.edit
+
+An Object or Property.
+
+=item service.post
+
+An operation supported by the object that shares the same C<title>.
+If no such object is found, this operation applies to the object itself.
+
+=back
+
+For example, an object's Atom representation may have the following links:
+
+    <link title="Groups"
+          rel="service.feed"
+          href="/Atom/0.3/RT-Groups" />
+    <link title="Groups"
+          rel="service.post"
+          href="/Atom/0.3/RT-Groups" />
+
+The client may then infer these relationships:
+
+=over 4
+
+=item * $obj has a member named I<Groups>.
+
+=item * $obj->Groups is a I<Container>.
+
+=item * $obj->Groups may be called to I<add> an object inside it.
+
+=item * $obj->Groups->add( key => 'value' ) should be translated to this:
+
+    POST /Atom/0.3/RT-Groups
+    Content-Type: application/x-www-form-urlencoded
+
+    key=value
+
+Or this:
+
+    POST /Atom/0.3/RT-Groups
+    Content-Type: application/x.atom+xml
+
+    <entry>
+      <content type="text/xml" mode="xml">
+        <body key="value" />
+      </content>
+    </entry>
+
+=back
+
+=head1 SEE ALSO
+
+Atom Tutorial:
+L<http://www.atomenabled.org/developers/tutorials/api-quick-guide.php>
+
+Atom API Specification (definitions of I<FeedURI>, I<EditURI> and
+I<PostURI>): L<http://www.atomenabled.org/developers/api/atom-api-spec.php>
+
+Atom Format Specification (definitions of I<AtomFeed> and I<AtomEntry>):
+L<http://www.atomenabled.org/developers/syndication/atom-format-spec.php>
+
+Atom Authentication Protocol:
+L<http://www.xml.com/pub/a/2003/12/17/dive.html>
+
+HTTP 1.1 Status codes:
+L<http://www.w3.org/Protocols/rfc2616/rfc2616.html>.
+
+Paul Prescod's REST resources: L<http://www.prescod.net/rest/>
+
+The Atom Wiki: L<http://www.intertwingly.net/wiki/pie/FrontPage>
+
+The REST Wiki: L<http://internet.conveyor.com/RESTwiki/moin.cgi/FrontPage>
+
+=head1 AUTHORS
+
+Autrijus Tang E<lt>autrijus at autrijus.orgE<gt>
+
+=cut

Modified: RTx-Atom/t/1-basic.t
==============================================================================
--- RTx-Atom/t/1-basic.t	(original)
+++ RTx-Atom/t/1-basic.t	Fri May 14 14:11:01 2004
@@ -3,7 +3,7 @@
 
 print "1..1\n";
 
-require RTx::Atom;
+require RT::Atom;
 
 print "ok 1\n";
 


More information about the Rt-commit mailing list