summaryrefslogtreecommitdiff
path: root/rt/t/ticket/linking.t
diff options
context:
space:
mode:
Diffstat (limited to 'rt/t/ticket/linking.t')
-rw-r--r--rt/t/ticket/linking.t385
1 files changed, 385 insertions, 0 deletions
diff --git a/rt/t/ticket/linking.t b/rt/t/ticket/linking.t
new file mode 100644
index 000000000..2ea3d58da
--- /dev/null
+++ b/rt/t/ticket/linking.t
@@ -0,0 +1,385 @@
+
+use strict;
+use warnings;
+
+use RT::Test tests => '101';
+use_ok('RT');
+use_ok('RT::Ticket');
+use_ok('RT::ScripConditions');
+use_ok('RT::ScripActions');
+use_ok('RT::Template');
+use_ok('RT::Scrips');
+use_ok('RT::Scrip');
+
+
+use File::Temp qw/tempfile/;
+my ($fh, $filename) = tempfile( UNLINK => 1, SUFFIX => '.rt');
+my $link_scrips_orig = RT->Config->Get( 'LinkTransactionsRun1Scrip' );
+RT->Config->Set( 'LinkTransactionsRun1Scrip', 1 );
+
+my $link_acl_checks_orig = RT->Config->Get( 'StrictLinkACL' );
+RT->Config->Set( 'StrictLinkACL', 1);
+
+my $condition = RT::ScripCondition->new( $RT::SystemUser );
+$condition->Load('User Defined');
+ok($condition->id);
+my $action = RT::ScripAction->new( $RT::SystemUser );
+$action->Load('User Defined');
+ok($action->id);
+my $template = RT::Template->new( $RT::SystemUser );
+$template->Load('Blank');
+ok($template->id);
+
+my $q1 = RT::Queue->new($RT::SystemUser);
+my ($id,$msg) = $q1->Create(Name => "LinkTest1.$$");
+ok ($id,$msg);
+my $q2 = RT::Queue->new($RT::SystemUser);
+($id,$msg) = $q2->Create(Name => "LinkTest2.$$");
+ok ($id,$msg);
+
+my $commit_code = <<END;
+open my \$file, "<$filename" or die "couldn't open $filename";
+my \$data = <\$file>;
+chomp \$data;
+\$data += 0;
+close \$file;
+\$RT::Logger->debug("Data is \$data");
+
+open \$file, ">$filename" or die "couldn't open $filename";
+if (\$self->TransactionObj->Type eq 'AddLink') {
+ \$RT::Logger->debug("AddLink");
+ print \$file \$data+1, "\n";
+}
+elsif (\$self->TransactionObj->Type eq 'DeleteLink') {
+ \$RT::Logger->debug("DeleteLink");
+ print \$file \$data-1, "\n";
+}
+else {
+ \$RT::Logger->error("THIS SHOULDN'T HAPPEN");
+ print \$file "666\n";
+}
+close \$file;
+1;
+END
+
+my $Scrips = RT::Scrips->new( $RT::SystemUser );
+$Scrips->UnLimit;
+while ( my $Scrip = $Scrips->Next ) {
+ $Scrip->Delete if $Scrip->Description and $Scrip->Description =~ /Add or Delete Link \d+/;
+}
+
+
+my $scrip = RT::Scrip->new($RT::SystemUser);
+($id,$msg) = $scrip->Create( Description => "Add or Delete Link $$",
+ ScripCondition => $condition->id,
+ ScripAction => $action->id,
+ Template => $template->id,
+ Stage => 'TransactionCreate',
+ Queue => 0,
+ CustomIsApplicableCode => '$self->TransactionObj->Type =~ /(Add|Delete)Link/;',
+ CustomPrepareCode => '1;',
+ CustomCommitCode => $commit_code,
+ );
+ok($id, "Scrip created");
+
+my $u1 = RT::User->new($RT::SystemUser);
+($id,$msg) = $u1->Create(Name => "LinkTestUser.$$");
+ok ($id,$msg);
+
+# grant ShowTicket right to allow count transactions
+($id,$msg) = $u1->PrincipalObj->GrantRight ( Object => $q1, Right => 'ShowTicket');
+ok ($id,$msg);
+($id,$msg) = $u1->PrincipalObj->GrantRight ( Object => $q2, Right => 'ShowTicket');
+ok ($id,$msg);
+($id,$msg) = $u1->PrincipalObj->GrantRight ( Object => $q1, Right => 'CreateTicket');
+ok ($id,$msg);
+
+my $creator = RT::CurrentUser->new($u1->id);
+
+diag('Create tickets without rights to link') if $ENV{'TEST_VERBOSE'};
+{
+ # on q2 we have no rights, yet
+ my $parent = RT::Ticket->new( $RT::SystemUser );
+ my ($id,$tid,$msg) = $parent->Create( Subject => 'Link test 1', Queue => $q2->id );
+ ok($id,$msg);
+ my $child = RT::Ticket->new( $creator );
+ ($id,$tid,$msg) = $child->Create( Subject => 'Link test 1', Queue => $q1->id, MemberOf => $parent->id );
+ ok($id,$msg);
+ $child->CurrentUser( $RT::SystemUser );
+ is($child->_Links('Base')->Count, 0, 'link was not created, no permissions');
+ is($child->_Links('Target')->Count, 0, 'link was not create, no permissions');
+}
+
+diag('Create tickets with rights checks on one end of a link') if $ENV{'TEST_VERBOSE'};
+{
+ # on q2 we have no rights, but use checking one only on thing
+ RT->Config->Set( StrictLinkACL => 0 );
+ my $parent = RT::Ticket->new( $RT::SystemUser );
+ my ($id,$tid,$msg) = $parent->Create( Subject => 'Link test 1', Queue => $q2->id );
+ ok($id,$msg);
+ my $child = RT::Ticket->new( $creator );
+ ($id,$tid,$msg) = $child->Create( Subject => 'Link test 1', Queue => $q1->id, MemberOf => $parent->id );
+ ok($id,$msg);
+ $child->CurrentUser( $RT::SystemUser );
+ is($child->_Links('Base')->Count, 1, 'link was created');
+ is($child->_Links('Target')->Count, 0, 'link was created only one');
+ # no scrip run on second ticket accroding to config option
+ is(link_count($filename), undef, "scrips ok");
+ RT->Config->Set( StrictLinkACL => 1 );
+}
+
+($id,$msg) = $u1->PrincipalObj->GrantRight ( Object => $q1, Right => 'ModifyTicket');
+ok ($id,$msg);
+
+diag('try to add link without rights') if $ENV{'TEST_VERBOSE'};
+{
+ # on q2 we have no rights, yet
+ my $parent = RT::Ticket->new( $RT::SystemUser );
+ my ($id,$tid,$msg) = $parent->Create( Subject => 'Link test 1', Queue => $q2->id );
+ ok($id,$msg);
+ my $child = RT::Ticket->new( $creator );
+ ($id,$tid,$msg) = $child->Create( Subject => 'Link test 1', Queue => $q1->id );
+ ok($id,$msg);
+ ($id, $msg) = $child->AddLink(Type => 'MemberOf', Target => $parent->id);
+ ok(!$id, $msg);
+ is(link_count($filename), undef, "scrips ok");
+ $child->CurrentUser( $RT::SystemUser );
+ is($child->_Links('Base')->Count, 0, 'link was not created, no permissions');
+ is($child->_Links('Target')->Count, 0, 'link was not create, no permissions');
+}
+
+diag('add link with rights only on base') if $ENV{'TEST_VERBOSE'};
+{
+ # on q2 we have no rights, but use checking one only on thing
+ RT->Config->Set( StrictLinkACL => 0 );
+ my $parent = RT::Ticket->new( $RT::SystemUser );
+ my ($id,$tid,$msg) = $parent->Create( Subject => 'Link test 1', Queue => $q2->id );
+ ok($id,$msg);
+ my $child = RT::Ticket->new( $creator );
+ ($id,$tid,$msg) = $child->Create( Subject => 'Link test 1', Queue => $q1->id );
+ ok($id,$msg);
+ ($id, $msg) = $child->AddLink(Type => 'MemberOf', Target => $parent->id);
+ ok($id, $msg);
+ is(link_count($filename), 1, "scrips ok");
+ $child->CurrentUser( $RT::SystemUser );
+ is($child->_Links('Base')->Count, 1, 'link was created');
+ is($child->_Links('Target')->Count, 0, 'link was created only one');
+ $child->CurrentUser( $creator );
+
+ # turn off feature and try to delete link, we should fail
+ RT->Config->Set( StrictLinkACL => 1 );
+ ($id, $msg) = $child->AddLink(Type => 'MemberOf', Target => $parent->id);
+ ok(!$id, $msg);
+ is(link_count($filename), 1, "scrips ok");
+ $child->CurrentUser( $RT::SystemUser );
+ $child->_Links('Base')->_DoCount;
+ is($child->_Links('Base')->Count, 1, 'link was not deleted');
+ $child->CurrentUser( $creator );
+
+ # try to delete link, we should success as feature is active
+ RT->Config->Set( StrictLinkACL => 0 );
+ ($id, $msg) = $child->DeleteLink(Type => 'MemberOf', Target => $parent->id);
+ ok($id, $msg);
+ is(link_count($filename), 0, "scrips ok");
+ $child->CurrentUser( $RT::SystemUser );
+ $child->_Links('Base')->_DoCount;
+ is($child->_Links('Base')->Count, 0, 'link was deleted');
+ RT->Config->Set( StrictLinkACL => 1 );
+}
+
+my $tid;
+my $ticket = RT::Ticket->new( $creator);
+ok($ticket->isa('RT::Ticket'));
+($id,$tid, $msg) = $ticket->Create(Subject => 'Link test 1', Queue => $q1->id);
+ok ($id,$msg);
+
+diag('try link to itself') if $ENV{'TEST_VERBOSE'};
+{
+ my ($id, $msg) = $ticket->AddLink(Type => 'RefersTo', Target => $ticket->id);
+ ok(!$id, $msg);
+ is(link_count($filename), 0, "scrips ok");
+}
+
+my $ticket2 = RT::Ticket->new($RT::SystemUser);
+($id, $tid, $msg) = $ticket2->Create(Subject => 'Link test 2', Queue => $q2->id);
+ok ($id, $msg);
+($id,$msg) =$ticket->AddLink(Type => 'RefersTo', Target => $ticket2->id);
+ok(!$id,$msg);
+is(link_count($filename), 0, "scrips ok");
+
+($id,$msg) = $u1->PrincipalObj->GrantRight ( Object => $q2, Right => 'CreateTicket');
+ok ($id,$msg);
+($id,$msg) = $u1->PrincipalObj->GrantRight ( Object => $q2, Right => 'ModifyTicket');
+ok ($id,$msg);
+($id,$msg) = $ticket->AddLink(Type => 'RefersTo', Target => $ticket2->id);
+ok($id,$msg);
+is(link_count($filename), 1, "scrips ok");
+($id,$msg) = $ticket->AddLink(Type => 'RefersTo', Target => -1);
+ok(!$id,$msg);
+($id,$msg) = $ticket->AddLink(Type => 'RefersTo', Target => $ticket2->id);
+ok($id,$msg);
+is(link_count($filename), 1, "scrips ok");
+
+my $transactions = $ticket2->Transactions;
+$transactions->Limit( FIELD => 'Type', VALUE => 'AddLink' );
+is( $transactions->Count, 1, "Transaction found in other ticket" );
+is( $transactions->First->Field , 'ReferredToBy');
+is( $transactions->First->NewValue , $ticket->URI );
+
+($id,$msg) = $ticket->DeleteLink(Type => 'RefersTo', Target => $ticket2->id);
+ok($id,$msg);
+is(link_count($filename), 0, "scrips ok");
+$transactions = $ticket2->Transactions;
+$transactions->Limit( FIELD => 'Type', VALUE => 'DeleteLink' );
+is( $transactions->Count, 1, "Transaction found in other ticket" );
+is( $transactions->First->Field , 'ReferredToBy');
+is( $transactions->First->OldValue , $ticket->URI );
+
+RT->Config->Set( LinkTransactionsRun1Scrip => 0 );
+
+($id,$msg) =$ticket->AddLink(Type => 'RefersTo', Target => $ticket2->id);
+ok($id,$msg);
+is(link_count($filename), 2, "scrips ok");
+($id,$msg) =$ticket->DeleteLink(Type => 'RefersTo', Target => $ticket2->id);
+ok($id,$msg);
+is(link_count($filename), 0, "scrips ok");
+
+# tests for silent behaviour
+($id,$msg) = $ticket->AddLink(Type => 'RefersTo', Target => $ticket2->id, Silent => 1);
+ok($id,$msg);
+is(link_count($filename), 0, "scrips ok");
+{
+ my $transactions = $ticket->Transactions;
+ $transactions->Limit( FIELD => 'Type', VALUE => 'AddLink' );
+ is( $transactions->Count, 2, "Still two txns on the base" );
+
+ $transactions = $ticket2->Transactions;
+ $transactions->Limit( FIELD => 'Type', VALUE => 'AddLink' );
+ is( $transactions->Count, 2, "Still two txns on the target" );
+
+}
+($id,$msg) =$ticket->DeleteLink(Type => 'RefersTo', Target => $ticket2->id, Silent => 1);
+ok($id,$msg);
+is(link_count($filename), 0, "scrips ok");
+
+($id,$msg) = $ticket->AddLink(Type => 'RefersTo', Target => $ticket2->id, SilentBase => 1);
+ok($id,$msg);
+is(link_count($filename), 1, "scrips ok");
+{
+ my $transactions = $ticket->Transactions;
+ $transactions->Limit( FIELD => 'Type', VALUE => 'AddLink' );
+ is( $transactions->Count, 2, "still five txn on the base" );
+
+ $transactions = $ticket2->Transactions;
+ $transactions->Limit( FIELD => 'Type', VALUE => 'AddLink' );
+ is( $transactions->Count, 3, "+1 txn on the target" );
+
+}
+($id,$msg) =$ticket->DeleteLink(Type => 'RefersTo', Target => $ticket2->id, SilentBase => 1);
+ok($id,$msg);
+is(link_count($filename), 0, "scrips ok");
+
+($id,$msg) = $ticket->AddLink(Type => 'RefersTo', Target => $ticket2->id, SilentTarget => 1);
+ok($id,$msg);
+is(link_count($filename), 1, "scrips ok");
+{
+ my $transactions = $ticket->Transactions;
+ $transactions->Limit( FIELD => 'Type', VALUE => 'AddLink' );
+ is( $transactions->Count, 3, "+1 txn on the base" );
+
+ $transactions = $ticket2->Transactions;
+ $transactions->Limit( FIELD => 'Type', VALUE => 'AddLink' );
+ is( $transactions->Count, 3, "three txns on the target" );
+}
+($id,$msg) =$ticket->DeleteLink(Type => 'RefersTo', Target => $ticket2->id, SilentTarget => 1);
+ok($id,$msg);
+is(link_count($filename), 0, "scrips ok");
+
+
+# restore
+RT->Config->Set( LinkTransactionsRun1Scrip => $link_scrips_orig );
+RT->Config->Set( StrictLinkACL => $link_acl_checks_orig );
+
+{
+ my $Scrips = RT::Scrips->new( $RT::SystemUser );
+ $Scrips->Limit( FIELD => 'Description', OPERATOR => 'STARTSWITH', VALUE => 'Add or Delete Link ');
+ while ( my $s = $Scrips->Next ) { $s->Delete };
+}
+
+
+my $link = RT::Link->new( $RT::SystemUser );
+($id,$msg) = $link->Create( Base => $ticket->URI, Target => $ticket2->URI, Type => 'MyLinkType' );
+ok($id, $msg);
+ok($link->LocalBase == $ticket->id, "LocalBase set correctly");
+ok($link->LocalTarget == $ticket2->id, "LocalTarget set correctly");
+
+{
+ no warnings 'once';
+ *RT::NotTicket::Id = sub { return $$ };
+ *RT::NotTicket::id = \&RT::NotTicket::Id;
+}
+
+{
+ package RT::URI::not_ticket;
+ use RT::URI::base;
+ use vars qw(@ISA);
+ @ISA = qw/RT::URI::base/;
+ sub IsLocal { 1; }
+ sub Object { return bless {}, 'RT::NotTicket'; }
+}
+
+my $orig_getresolver = \&RT::URI::_GetResolver;
+{
+ no warnings 'redefine';
+ *RT::URI::_GetResolver = sub {
+ my $self = shift;
+ my $scheme = shift;
+
+ $scheme =~ s/(\.|-)/_/g;
+ my $resolver;
+ my $module = "RT::URI::$scheme";
+ $resolver = $module->new($self->CurrentUser);
+
+ if ($resolver) {
+ $self->{'resolver'} = $resolver;
+ } else {
+ $self->{'resolver'} = RT::URI::base->new($self->CurrentUser);
+ }
+ };
+}
+
+($id,$msg) = $link->Create( Base => "not_ticket::$RT::Organization/notticket/$$", Target => $ticket2->URI, Type => 'MyLinkType' );
+ok($id, $msg);
+ok($link->LocalBase == 0, "LocalBase set correctly");
+ok($link->LocalTarget == $ticket2->id, "LocalTarget set correctly");
+
+($id,$msg) = $link->Create( Target => "not_ticket::$RT::Organization/notticket/$$", Base => $ticket->URI, Type => 'MyLinkType' );
+ok($id, $msg);
+ok($link->LocalTarget == 0, "LocalTarget set correctly");
+ok($link->LocalBase == $ticket->id, "LocalBase set correctly");
+
+($id,$msg) = $link->Create(
+ Target => "not_ticket::$RT::Organization/notticket/1$$",
+ Base => "not_ticket::$RT::Organization/notticket/$$",
+ Type => 'MyLinkType' );
+
+ok($id, $msg);
+ok($link->LocalTarget == 0, "LocalTarget set correctly");
+ok($link->LocalBase == 0, "LocalBase set correctly");
+
+# restore _GetResolver
+{
+ no warnings 'redefine';
+ *RT::URI::_GetResolver = $orig_getresolver;
+}
+
+sub link_count {
+ my $file = shift;
+ open my $fh, "<$file" or die "couldn't open $file";
+ my $data = <$fh>;
+ close $fh;
+
+ return undef unless $data;
+ chomp $data;
+ return $data + 0;
+}