[Bps-public-commit] RT-Extension-NHD branch, master, updated. d4f65312f9d832c22f49f3a778713b7c13e13273
Ruslan Zakirov
ruz at bestpractical.com
Mon Oct 3 05:52:24 EDT 2011
The branch, master has been updated
via d4f65312f9d832c22f49f3a778713b7c13e13273 (commit)
via cd636df1781eeef832247329fa362fc003b6c35a (commit)
from 40d221b84e230db3c6a558a9d6c8dae1f0c2d570 (commit)
Summary of changes:
TODO | 8 +++
lib/RT/Extension/NHD.pm | 29 ++++++++++-
lib/RT/Extension/NHD/Test/Web.pm | 11 +----
lib/RT/NHD/Agreement.pm | 74 +++++++++++++++++++--------
t/api/agreement.t | 106 ++++++++++++++++++++++++++++++++++++++
t/rest/agreement.t | 6 +-
6 files changed, 199 insertions(+), 35 deletions(-)
create mode 100644 TODO
- Log -----------------------------------------------------------------
commit cd636df1781eeef832247329fa362fc003b6c35a
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date: Mon Oct 3 11:49:59 2011 +0200
sync creates and updates with remote site
diff --git a/lib/RT/Extension/NHD.pm b/lib/RT/Extension/NHD.pm
index 3e8e06e..b80e06e 100644
--- a/lib/RT/Extension/NHD.pm
+++ b/lib/RT/Extension/NHD.pm
@@ -15,6 +15,8 @@ RT::Extension::NHD - Networked Help Desk protocol for Request Tracker
use RT::NHD::Agreement;
use JSON::Any;
+use LWP::UserAgent;
+use HTTP::Request;
sub FromJSON {
return JSON::Any->new->from_json( $_[1] );
@@ -32,7 +34,29 @@ sub CheckUUID {
return 1;
}
-my %HTTP_CODE = (
+sub JSONRequest {
+ my $self = shift;
+ my ($method, $uri, %args) = @_;
+
+ my $data;
+ $data = RT::Extension::NHD->ToJSON( delete $args{'Data'} )
+ unless uc($method) eq 'GET';
+ my %headers = %{ delete $args{'Headers'} || {} };
+ %headers = (
+ 'X-Ticket-Sharing-Version' => '1',
+ 'Content-Type' => 'text/x-json; charset="UTF-8"',
+ %headers,
+ );
+ my $request = HTTP::Request->new( $method, $uri, [%headers], $data );
+ return $self->SendRequest( $request );
+}
+
+sub SendRequest {
+ my $self = shift;
+ return LWP::UserAgent->new->request( shift );
+}
+
+our %HTTP_CODE = (
'OK' => 200,
'Created' => 201,
@@ -44,6 +68,7 @@ my %HTTP_CODE = (
'Precondition Failed' => 412,
'Unprocessable Entity' => 422,
);
+our %HTTP_MESSAGE = reverse %HTTP_CODE;
sub BadWebRequest {
my $self = shift;
@@ -77,6 +102,8 @@ sub StopWebRequest {
}
my %METHOD_TO_ACTION = ( GET => 'show', POST => 'create', PUT => 'update' );
+my %ACTION_TO_METHOD = reverse %METHOD_TO_ACTION;
+sub ActionToWebMethod { return $ACTION_TO_METHOD{ lc $_[1] } };
sub WebRequestAction {
return $METHOD_TO_ACTION{ uc $HTML::Mason::Commands::r->method };
}
diff --git a/lib/RT/Extension/NHD/Test/Web.pm b/lib/RT/Extension/NHD/Test/Web.pm
index 292ff46..280890f 100644
--- a/lib/RT/Extension/NHD/Test/Web.pm
+++ b/lib/RT/Extension/NHD/Test/Web.pm
@@ -20,16 +20,7 @@ sub json_request {
my $self = shift;
my ($method, $uri, %args) = @_;
$uri = $self->rt_base_url .'NoAuth/NHD/1.0'. $uri;
- my $data;
- $data = RT::Extension::NHD->ToJSON( delete $args{'data'} )
- unless $method eq 'GET';
- my %headers = %{ $args{'headers'}||{}};
- %headers = (
- %headers,
- 'X-Ticket-Sharing-Version' => '1',
- );
- my $request = HTTP::Request->new( $method, $uri, [%headers], $data );
- return $self->request( $request );
+ RT::Extension::NHD->JSONRequest( $method, $uri, %args );
}
1;
\ No newline at end of file
diff --git a/lib/RT/NHD/Agreement.pm b/lib/RT/NHD/Agreement.pm
index 60c2603..33e5954 100644
--- a/lib/RT/NHD/Agreement.pm
+++ b/lib/RT/NHD/Agreement.pm
@@ -40,7 +40,7 @@ sub Create {
my @rv = $self->SUPER::Create( %args );
if ( $we_are eq $by ) {
- my ($status, $msg) = $self->SendUpdate;
+ my ($status, $msg) = $self->Send( 'create' );
return $self->RollbackTransaction( "Couldn't send update to remote host: $msg" )
unless $status;
}
@@ -120,7 +120,7 @@ sub Update {
unless $status;
}
if ( $by eq $we_are ) {
- my ($status, $msg) = $self->SendUpdate( Fields => [keys %args] );
+ my ($status, $msg) = $self->Send( update => Fields => [keys %args] );
return $self->RollbackTransaction( "Couldn't send update to remote host: $msg" )
unless $status;
}
@@ -129,9 +129,35 @@ sub Update {
return (1, 'Updated');
}
-sub SendUpdate {
+my %INVERT_ROLE = ( Receiver => 'Sender', Sender => 'Receiver' );
+
+sub Send {
my $self = shift;
- return (1, 'Updated remote host');
+ my $action = shift;
+ my %args = @_;
+
+ my $recipient = $INVERT_ROLE{ $self->WhoWeAre };
+ return (0, 'We are neither sender nor receiver')
+ unless $recipient;
+
+ my $method = RT::Extension::NHD->ActionToWebMethod( $action );
+ return (0, "Unknown action '$action'")
+ unless $method;
+
+ my $response = RT::Extension::NHD->JSONRequest(
+ $method => $self->$recipient() .'/agreements/'. $self->UUID,
+ Headers => {
+ 'X-Ticket-Sharing-Token' => $self->UUID .':'. $self->AccessKey,
+ },
+ Data => $self->ForJSON( %args ),
+ );
+
+ unless ( $response && $response->is_success ) {
+ return (0, 'No response', $response) unless $response;
+ return (0, 'Request was not successful', $response);
+ }
+
+ return (1, 'Updated remote host', $response);
}
sub WhoWeAre {
@@ -231,32 +257,38 @@ sub _ValidateURI {
return 1;
}
+our %FIELDS_MAP = (
+ UUID => 'uuid',
+ Name => 'name',
+ Status => 'status',
+ Sender => 'sender_url',
+ Receiver => 'receiver_url',
+ AccessKey => 'access_key',
+ DeactivatedBy => 'deactivated_by',
+);
+
sub FromJSON {
my $self = shift;
my ($args) = @_;
- return {
- UUID => $args->{'uuid'},
- Name => $args->{'name'},
- Status => $args->{'status'},
- Sender => $args->{'sender_url'},
- Receiver => $args->{'receiver_url'},
- AccessKey => $args->{'access_key'},
- DeactivatedBy => $args->{'deactivated_by'},
+ my %res;
+ while ( my ($k, $v) = each %FIELDS_MAP ) {
+ next unless exists $args->{$v};
+ $res{ $k } = $args->{$v};
};
+
+ return \%res;
}
sub ForJSON {
my $self = shift;
- return {
- uuid => $self->UUID,
- name => $self->Name,
- status => $self->Status,
- sender_url => $self->Sender,
- receiver_url => $self->Receiver,
- access_key => $self->AccessKey,
- deactivated_by => $self->DeactivatedBy,
- };
+ my %args = @_;
+
+ my @fields = $args{'Fields'} ? @{$args{'Fields'}} : keys %FIELDS_MAP;
+
+ my %res;
+ $res{ $FIELDS_MAP{$_} } = $self->$_() foreach @fields;
+ return \%res;
}
sub TableAttributes {
diff --git a/t/api/agreement.t b/t/api/agreement.t
index 5cdbd08..fc58c79 100644
--- a/t/api/agreement.t
+++ b/t/api/agreement.t
@@ -6,6 +6,41 @@ use warnings;
use RT::Extension::NHD::Test tests => 24;
use Digest::SHA1 qw(sha1_hex);
+use_ok 'RT::Extension::NHD';
+
+{
+ my (@requests, @responses);
+
+ sub remote_requests { return splice @requests }
+
+ sub set_next_remote_response {
+ my $code = shift;
+ my %args = @_;
+
+ my $msg = $args{'Message'} || $RT::Extension::NHD::HTTP_MESSAGE{ $code }
+ || die "no message for code $code";
+
+ my %headers = %{ $args{'Headers'} || {} };
+ %headers = (
+ %headers,
+ 'X-Ticket-Sharing-Version' => '1',
+ );
+ my $content = $args{'Data'};
+ $content = RT::Extension::NHD->ToJSON( $content )
+ if ref $content;
+ push @responses, HTTP::Response->new(
+ $code, $msg, [%headers], $content,
+ );
+ }
+
+ no strict 'subs';
+ *RT::Extension::NHD::SendRequest = sub {
+ my $self = shift;
+ push @requests, shift;
+ return shift @responses;
+ };
+}
+
{
my $agreement = RT::NHD::Agreement->new( RT->SystemUser );
isa_ok($agreement, 'RT::NHD::Agreement');
@@ -50,6 +85,8 @@ my $i = 0;
is( $agreement->Sender, $remote_url, 'correct value' );
is( $agreement->Receiver, RT->Config->Get('NHD_WebURL'), 'correct value' );
like( $agreement->AccessKey, qr{^[0-9a-f]{40}$}i, 'correct value' );
+
+ is scalar remote_requests(), 0, 'no outgoing requests';
}
# bad status
@@ -65,6 +102,7 @@ my $i = 0;
AccessKey => sha1_hex( ''. ++$i ),
);
ok(!$id, "Couldn't create an agreement $uuid: $msg");
+ is scalar remote_requests(), 0, 'no outgoing requests';
}
# can only be created with pending status
@@ -80,6 +118,7 @@ my $i = 0;
AccessKey => sha1_hex( ''. ++$i ),
);
ok(!$id, "Couldn't create an agreement $uuid: $msg");
+ is scalar remote_requests(), 0, 'no outgoing requests';
}
# simple update by sender we are receiver
@@ -103,6 +142,7 @@ my $i = 0;
ok $status, 'updated URL of the sender by sender';
is( $agreement->Name, 'Correct Test Company', 'correct value' );
is( $agreement->AccessKey, sha1_hex( ''. $i ), 'correct value' );
+ is scalar remote_requests(), 0, 'no outgoing requests';
}
# update with error
@@ -127,5 +167,71 @@ my $i = 0;
# make sure we're transactional
is( $agreement->Name, 'Test Company', 'correct value' );
is( $agreement->AccessKey, sha1_hex( ''. $i ), 'correct value' );
+ is scalar remote_requests(), 0, 'no outgoing requests';
+}
+
+# we are sending
+{
+ set_next_remote_response(201);
+
+ my $uuid = sha1_hex( ''. ++$i );
+
+ my $agreement = RT::NHD::Agreement->new( RT->SystemUser );
+ my ($id, $msg) = $agreement->Create(
+ UUID => $uuid,
+ Name => 'Test Company',
+ Status => 'pending',
+ Sender => RT->Config->Get('NHD_WebURL'),
+ Receiver => $remote_url,
+ AccessKey => sha1_hex( ''. ++$i ),
+ );
+ ok($id, "Created an agreement $uuid");
+
+ $agreement = RT::NHD::Agreement->new( RT->SystemUser );
+ $agreement->Load( $uuid );
+ ok( $agreement->id, 'loaded agreement' );
+
+ is( $agreement->UUID, $uuid, 'correct value' );
+ is( $agreement->Name, 'Test Company', 'correct value' );
+ is( $agreement->Status, 'pending', 'correct value' );
+ is( $agreement->Receiver, $remote_url, 'correct value' );
+ is( $agreement->Sender, RT->Config->Get('NHD_WebURL'), 'correct value' );
+ like( $agreement->AccessKey, qr{^[0-9a-f]{40}$}i, 'correct value' );
+
+ my @requests = remote_requests();
+ is scalar @requests, 1, 'one outgoing request';
+ is $requests[0]->uri, "$remote_url/agreements/$uuid";
+ is $requests[0]->method, "POST";
+ is $requests[0]->header('X-Ticket-Sharing-Version'), 1;
+ is $requests[0]->header('X-Ticket-Sharing-Token'),
+ $agreement->UUID .':'. $agreement->AccessKey;
+ is lc $requests[0]->header('Content-Type'), 'text/x-json; charset="utf-8"';
+ is_deeply(
+ RT::Extension::NHD->FromJSON( $requests[0]->content ),
+ $agreement->ForJSON,
+ );
+
+ set_next_remote_response(200);
+
+ (my $status, $msg) = $agreement->Update(
+ Name => 'Correct Test Company',
+ AccessKey => sha1_hex( ''. ++$i ),
+ );
+ ok $status, 'updated URL of the sender by sender' or "error: $msg";
+ is( $agreement->Name, 'Correct Test Company', 'correct value' );
+ is( $agreement->AccessKey, sha1_hex( ''. $i ), 'correct value' );
+
+ @requests = remote_requests();
+ is scalar @requests, 1, 'one outgoing request';
+ is $requests[0]->uri, "$remote_url/agreements/$uuid";
+ is $requests[0]->method, "PUT";
+ is $requests[0]->header('X-Ticket-Sharing-Version'), 1;
+ is $requests[0]->header('X-Ticket-Sharing-Token'),
+ $agreement->UUID .':'. sha1_hex( ''. ($i - 1) );
+ is lc $requests[0]->header('Content-Type'), 'text/x-json; charset="utf-8"';
+ is_deeply(
+ RT::Extension::NHD->FromJSON( $requests[0]->content ),
+ $agreement->ForJSON( Fields => ['Name', 'AccessKey'] ),
+ );
}
diff --git a/t/rest/agreement.t b/t/rest/agreement.t
index 9f0bb43..7308bf5 100644
--- a/t/rest/agreement.t
+++ b/t/rest/agreement.t
@@ -17,10 +17,10 @@ my $i = 0;
my $response = $m->json_request(
POST => '/agreements/'. $uuid,
- headers => {
+ Headers => {
'X-Ticket-Sharing-Token' => "$uuid:$access_key",
},
- data => {
+ Data => {
uuid => $uuid,
name => 'Test Company',
status => 'pending',
@@ -53,7 +53,7 @@ my $i = 0;
$response = $m->json_request(
GET => '/agreements/'. $uuid,
- headers => {
+ Headers => {
'X-Ticket-Sharing-Token' => "$uuid:$access_key",
},
);
commit d4f65312f9d832c22f49f3a778713b7c13e13273
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date: Mon Oct 3 11:52:15 2011 +0200
add TODO message
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..1d3f253
--- /dev/null
+++ b/TODO
@@ -0,0 +1,8 @@
+* in Agreement::Create make sure that the following situation
+ is denined: WhoWeAre == Sender and CurrentUserIs Receiver
+
+* Transactional Create
+
+* When AccessKey changes locally we send wrong auth token
+ to the other side
+
-----------------------------------------------------------------------
More information about the Bps-public-commit
mailing list