[Rt-commit] [svn] r782 - in rt: . branches/rt-3.3/html/REST/2.0
branches/rt-3.3/html/REST/2.0/NoAuth
autrijus at pallas.eruditorum.org
autrijus at pallas.eruditorum.org
Sat May 1 06:35:25 EDT 2004
Author: autrijus
Date: Sat May 1 06:35:23 2004
New Revision: 782
Added:
rt/branches/rt-3.3/html/REST/2.0/NoAuth/
rt/branches/rt-3.3/html/REST/2.0/NoAuth/feed.css
Modified:
rt/ (props changed)
rt/branches/rt-3.3/html/REST/2.0/autohandler
rt/branches/rt-3.3/html/REST/2.0/dhandler
Log:
----------------------------------------------------------------------
r4317 at not: autrijus | 2004-05-01T10:35:00.584748Z
* now does Basic and Digest authentication, too.
* CSSify the example feed
----------------------------------------------------------------------
Added: rt/branches/rt-3.3/html/REST/2.0/NoAuth/feed.css
==============================================================================
--- (empty file)
+++ rt/branches/rt-3.3/html/REST/2.0/NoAuth/feed.css Sat May 1 06:35:23 2004
@@ -0,0 +1,100 @@
+feed {
+ display:block;
+ font-family:verdana, sans-serif;
+ margin:2%;
+}
+
+info {
+ margin:20px;
+ background:yellow;
+ text-align:center;
+ display:block;
+ padding:10px;
+ font-size:85%;
+}
+
+title {
+ font-size:150%;
+ color:#000000;
+ display:block;
+ font-weight:bold;
+}
+
+tagline {
+ display:block;
+ font-size:90%;
+}
+
+link {
+ font-size:90%;
+}
+
+id {
+ display:none;
+}
+
+modified {
+ display:none;
+}
+
+generator {
+ font-size:90%;
+ display:none;
+ margin:0px 0px 30px 0px;
+}
+
+entry title {
+ font-size:125%;
+ font-weight:bold;
+ color:#003366;
+ display:block;
+ padding:15px 1% 0px 3%;
+ margin:10px 0px 0px 0px;
+ border-top:solid 1px #dddddd;
+ background:#eeeeee;
+}
+
+entry modified {
+ display:inline;
+}
+
+created {
+ display:none;
+}
+
+issued {
+ display:none;
+}
+
+content {
+ background:#eeeeee;
+ display:block;
+ padding:5px 3% 10px 3%;
+ border-bottom:solid 1px #999999;
+ font-family: courier;
+ font-size: xx-small;
+}
+
+
+
+entry {
+ border-top:dotted 1px #999999;
+ margin:30px 0px 5px 0px;
+ padding:5px;
+ display:block;
+ background:#ffffff;
+ padding:5px 0px 10px 0px;
+ margin:10px 10px 35px 10px;
+
+}
+
+entry link {
+ color:#aaaaaa;
+ font-size:80%;
+}
+
+issued,modified,created,name,id {
+ color:#999999;
+ font-size:80%;
+ margin-top:25px;
+}
Modified: rt/branches/rt-3.3/html/REST/2.0/autohandler
==============================================================================
--- rt/branches/rt-3.3/html/REST/2.0/autohandler (original)
+++ rt/branches/rt-3.3/html/REST/2.0/autohandler Sat May 1 06:35:23 2004
@@ -1,4 +1,9 @@
%# Forbid direct access in this directory -- everything goes thru dhandler
+% # If it's a noauth file, don't ask for auth.
+% if ($m->base_comp->path =~ $RT::WebNoAuthRegex ) {
+% $m->call_next(%ARGS);
+% $m->abort();
+% }
% $r->content_type('text/html; charset=utf-8');
% $m->abort(403);
<%flags>
Modified: rt/branches/rt-3.3/html/REST/2.0/dhandler
==============================================================================
--- rt/branches/rt-3.3/html/REST/2.0/dhandler (original)
+++ rt/branches/rt-3.3/html/REST/2.0/dhandler Sat May 1 06:35:23 2004
@@ -1,32 +1,101 @@
%# The main dispatcher for RT/REST 2.0
<%INIT>
+require Digest::MD5;
+require MIME::Base64;
+
+# needs discussion on using MD5(pass) as Digest token
+ at RT::RESTAuthenticationMethods = qw( WSSE Basic )
+ unless @RT::RESTAuthenticationMethods;
+
my $realm = $RT::rtname;
$realm =~ s/[^\w.]//g;
+my $nonce = Digest::MD5::md5_hex($realm . rand());
+my %methods = map {($_ => 1)} @RT::RESTAuthenticationMethods;
# XXX - do Digest auth here too?
-$r->header_out(
+$r->headers_out->add(
'WWW-Authenticate' => qq(WSSE realm="$realm", profile="UsernameToken")
-);
+) if $methods{WSSE};
+$r->headers_out->add(
+ 'WWW-Authenticate' => qq(Digest realm="$realm", stale=false, nonce="", qop="auth", algorithm="MD5")
+) if $methods{Digest};
+$r->headers_out->add(
+ 'WWW-Authenticate' => qq(Basic realm="$realm")
+) if $methods{Basic};
-my $CurrentUser;
+$RT::Logger->error($r->header_in('Authorization'));
-AUTH: {
- my $auth = $r->header_in('Authorization');
- $auth =~ /^WSSE (?=.*\bprofile="UsernameToken")/ or last;
-
- my $wsse = $r->header_in('X-WSSE');
- $wsse =~ s/^(?:WSSE|UsernameToken) // or last;
-
- my %param;
- foreach my $i (split /,\s*/, $wsse) {
- my ($k, $v) = split /=/, $i, 2;
- $v =~ s/^"//; $v =~ s/"$//;
- $param{lc($k)} = $v;
+my $CurrentUser;
+my $headerParts = sub {
+ my $header = $r->header_in($_[0]);
+ $header =~ s/^(?:$_[1]) /", / or return;
+ $header =~ s/"\s*$//; # strip whitespaces after the last "
+
+ my %parts;
+ foreach my $chunk (split /,\s*/, $header) {
+ my ($k, $v) = split /=/, $chunk, 2;
+ $v =~ s/^"//;
+ $v =~ s/"$//;
+ $parts{lc($k)} = $v;
}
+ $RT::Logger->error(join(',', %parts));
+ $parts{lc($_)} = delete $parts{$_} for map "$_", keys %parts;
+ return \%parts;
+};
+
+AUTH_Basic: {
+ last if $CurrentUser or !$methods{Basic};
+
+ $r->header_in('Authorization') =~ /^Basic (.+)$/ or last;
+ my ($username, $password) = split(/:/, MIME::Base64::decode_base64($1), 2);
+
+ require RT::CurrentUser;
+ $CurrentUser = RT::CurrentUser->new;
+ $CurrentUser->Load($username) or last;
+ $CurrentUser->IsPassword($password) or undef $CurrentUser;
+}
+
+AUTH_Digest: {
+ last if $CurrentUser or !$methods{Digest};
+
+ my $parts = $headerParts->('Authorization', 'Digest') or last;
+
+ my ($username, $auth_digest, $auth_nonce,
+ $auth_nc, $auth_cnonce, $auth_qop, $auth_uri)
+ = map { defined($_) ? $_ : last AUTH_Digest }
+ @{$parts}{qw(username response nonce nc cnonce qop uri)};
+
+ # XXX validate $auth_uri
+
+ require RT::CurrentUser;
+ $CurrentUser = RT::CurrentUser->new;
+ $CurrentUser->Load($username) or last;
+
+ my $a1 = Digest::MD5::md5_hex(
+ "$username:$realm:" . $CurrentUser->UserObj->__Value('Password')
+ );
+
+ $auth_digest eq Digest::MD5::md5_hex(
+ join(
+ ":",
+ $a1, $auth_nonce,
+ $auth_nc, $auth_cnonce, $auth_qop,
+ Digest::MD5::md5_hex($r->method . ":" . $auth_uri),
+ )
+ ) or undef $CurrentUser;
+}
+
+AUTH_WSSE: {
+ last if $CurrentUser or !$methods{WSSE};
+
+ my $auth = $headerParts->('Authorization', 'WSSE') or last;
+ lc($auth->{profile}) eq 'usernametoken' or last;
+
+ my $wsse = $headerParts->('X-WSSE', qr/WSSE|UsernameToken/) or last;
my ($username, $auth_digest, $auth_nonce, $auth_created)
- = map { defined($_) ? $_ : last AUTH }
- @param{qw(username passworddigest nonce created)};
+ = map { defined($_) ? $_ : last AUTH_WSSE }
+ @{$wsse}{qw(username passworddigest nonce created)};
require RT::CurrentUser;
$CurrentUser = RT::CurrentUser->new;
@@ -64,13 +133,48 @@
}
if ($CurrentUser and $CurrentUser->Id) {
- # $m->comp( $m->dhandler_arg ); # XXX - proper delegation goes here
+ my $type = ucfirst(lc($m->dhandler_arg)); # XXX - proper delegation goes here
+ $type =~ s{/.*}{};
+ $type =~ s{s$}{};
+
+ require "RT/${type}s.pm";
+ my $collection = "RT::${type}s"->new($CurrentUser);
+ $collection->UnLimit;
+ my $count = $collection->Count;
+
+ $r->content_type('text/xml');
+ my $entries = '';
+ while (my $entry = $collection->Next) {
+ my %entry = map { $_ => eval { $entry->$_ } || '' }
+ qw(Id Name Description Content LastUpdated Created);
+ $entries .= <<".";
+ <entry>
+ <title mode="escaped">$entry{Name}</title>
+ <link rel="alternate" type="text/html" href="$RT::WebPath/$type/Display.html?id=$entry{Id}"/>
+ <modified>$entry{LastUpdated}</modified>
+ <issued>$entry{Created}</issued>
+ <created>$entry{Created}</created>
+ <id>rt-fsck.com:$RT::rtname/$entry{Id}</id>
+ <summary mode="escaped">$entry{Description}</summary>
+ <content type="text/html" mode="escaped" xml:base="http://diveintomark.org/archives/2004/04/19/feed-parser-beta-22">
+ <![CDATA[$entry{Content}]]>
+ </content>
+ </entry>
+.
+ }
print << ".";
<?xml version="1.0" encoding="utf-8"?>
+<?xml-stylesheet type="text/css" href="$RT::WebPath/REST/2.0/NoAuth/feed.css"?>
<feed version="0.3" xmlns="http://purl.org/atom/ns#">
- <title>Ticket search results</title>
- <modified>2000-01-01T01:01:01Z</modified>
- <author><name>$RT::rtname</name></author>
+ <title>\u$type search results</title>
+ <author>
+ <name>$RT::Organization</name>
+ <url>$RT::WebURL</url>
+ </author>
+ <tagline mode="escaped">$count results found.</tagline>
+ <id>$nonce</id>
+ <generator url="http://www.bestpractical.com/rt/" version="$RT::VERSION">RT</generator>
+ $entries
</feed>
.
}
More information about the Rt-commit
mailing list