[Rt-commit] rt branch, 4.4/custom-roles, repushed
Shawn Moore
shawn at bestpractical.com
Tue Oct 27 21:02:47 EDT 2015
The branch 4.4/custom-roles was deleted and repushed:
was 1a8e3a17877b5bbbbf86c68cade97267b43cc0a7
now 6c22fa9242076a6863b2e15d6839c51910ede898
1: 3da168a = 1: 3da168a Tidy EmailInput and avoid including unescaped parameters
2: f4a3966 = 2: f4a3966 Placeholder and EntryHint for EmailInput
3: 5b777ea = 3: 5b777ea Support autocomplete-return for EmailInput
4: 1168416 = 4: 1168416 Support for (by default, off) autocomplete of Nobody and System
5: 87d20c2 = 5: 87d20c2 Only include one copy of "check box to delete" for queue watchers
6: 7c59fae = 6: 7c59fae Simplify IsManageableRoleGroupType
7: 78cbe3d = 7: 78cbe3d Switch several hardcoded lists to use ->Roles
8: 8b8897b = 8: 8b8897b Avoid empty results and undef warnings in bulk update
9: 89d776e = 9: 89d776e Tidy AddWatchers
10: accaf5b = 10: accaf5b Use the record we have for inspecting roles, rather than class RT::Queue
11: 3d5ba26 = 11: 3d5ba26 Add a CheckRight param to ->RoleGroup
12: f467d55 = 12: f467d55 Fix one-off "Administrative Cc" with "AdminCc"
13: 7cb01e5 = 13: 7cb01e5 Provide queue to EditBasics for new tickets (they don't have a ->QueueObj)
14: 71fc832 = 14: 71fc832 Provide defaults to EditBasics for "Add More Attach" etc
15: 4b1fd93 = 15: 4b1fd93 Factor out a CanonicalizePrincipal from AddRoleMember
16: c7759ba = 16: c7759ba Consistent error message across AddRoleMember and DeleteRoleMember
17: ff898d8 = 17: ff898d8 Factor out a _CreateRoleGroup
18: 6f0d646 = 18: 6f0d646 Lazily create ticket role groups if needed
19: b2d8700 = 19: b2d8700 Use queue to resolve roles on create since the ticket isn't created yet
20: fe79a2f = 20: fe79a2f Process watcher updates from ticket Modify
21: eccef99 ! 21: e5dda97 Improve messaging around updating queue/ticket watchers
@@ -55,12 +55,15 @@
+
+ my $original_user;
+ my $group = $self->RoleGroup( $args{Type} );
-+ if ($group->SingleMemberRoleGroup) {
++ if ($group->id && $group->SingleMemberRoleGroup) {
+ my $users = $group->UserMembersObj( Recursively => 0 );
+ $original_user = $users->First;
+ if ($original_user->PrincipalId == $principal->Id) {
+ return 1;
+ }
++ }
++ else {
++ $original_user = RT->Nobody;
+ }
+
+ ((my $ok), $msg) = $self->AddRoleMember(
22: 4a6331d = 22: 5539d9a Additional option for roles
23: f7be7cd = 23: 34bfce3 Tidy watcher searching in RT::Tickets
24: dbea774 = 24: f0acbba Improve comments around GetPrincipalsMap
25: a08feeb = 25: cdf1d2e Add Ticket->RoleAddresses($Name)
26: a6cd627 ! 26: 524f3d8 Add a Group->Label hook for when we display a group's name in the UI
@@ -53,6 +53,19 @@
];
}
}
+
+diff --git a/lib/RT/Principal.pm b/lib/RT/Principal.pm
+--- a/lib/RT/Principal.pm
++++ b/lib/RT/Principal.pm
+@@
+ return $self->Object->InstanceObj->Name if ($self->Object->Domain eq 'ACLEquivalence');
+
+ # Otherwise, show the group name
+- return $self->Object->Name;
++ return $self->Object->Label;
+ }
+
+ =head2 GrantRight { Right => RIGHTNAME, Object => undef }
diff --git a/lib/RT/Queue.pm b/lib/RT/Queue.pm
--- a/lib/RT/Queue.pm
27: 01dc0ac = 27: baa947b Switch to ->LabelForRole
28: e7b0433 ! 28: 991f84a Add custom roles for queues
@@ -1014,6 +1014,66 @@
+
+=cut
+
++sub _SetGroupsDisabledForQueue {
++ my $self = shift;
++ my $value = shift;
++ my $queue = shift;
++
++ # set disabled on the queue group
++ my $queue_group = RT::Group->new($self->CurrentUser);
++ $queue_group->LoadRoleGroup(
++ Name => $self->GroupType,
++ Object => $queue,
++ );
++
++ if (!$queue_group->Id) {
++ $RT::Handle->Rollback;
++ $RT::Logger->error("Couldn't find role group for " . $self->GroupType . " on queue " . $queue->Id);
++ return(undef);
++ }
++
++ my ($ok, $msg) = $queue_group->SetDisabled($value);
++ unless ($ok) {
++ $RT::Handle->Rollback;
++ $RT::Logger->error("Couldn't SetDisabled($value) on role group: $msg");
++ return(undef);
++ }
++
++ # disable each existant ticket group
++ my $ticket_groups = RT::Groups->new($self->CurrentUser);
++
++ if ($value) {
++ $ticket_groups->LimitToEnabled;
++ }
++ else {
++ $ticket_groups->LimitToDeleted;
++ }
++
++ $ticket_groups->Limit(FIELD => 'Domain', OPERATOR => 'LIKE', VALUE => "RT::Ticket-Role", CASESENSITIVE => 0 );
++ $ticket_groups->Limit(FIELD => 'Name', OPERATOR => '=', VALUE => $self->GroupType, CASESENSITIVE => 0);
++
++ my $tickets = $ticket_groups->Join(
++ ALIAS1 => 'main',
++ FIELD1 => 'Instance',
++ TABLE2 => 'Tickets',
++ FIELD2 => 'Id',
++ );
++ $ticket_groups->Limit(
++ ALIAS => $tickets,
++ FIELD => 'Queue',
++ VALUE => $queue->Id,
++ );
++
++ while (my $ticket_group = $ticket_groups->Next) {
++ my ($ok, $msg) = $ticket_group->SetDisabled($value);
++ unless ($ok) {
++ $RT::Handle->Rollback;
++ $RT::Logger->error("Couldn't SetDisabled($value) ticket role group: $msg");
++ return(undef);
++ }
++ }
++}
++
+sub SetDisabled {
+ my $self = shift;
+ my $value = shift;
@@ -1027,21 +1087,13 @@
+ return ($ok, $msg);
+ }
+
-+ my $groups = RT::Groups->new($self->CurrentUser);
-+ if ($value) {
-+ # if we're disabling, only need to update enabled groups
-+ $groups->LimitToEnabled;
-+ }
-+ else {
-+ $groups->LimitToDeleted;
-+ }
-+
-+ # disable all groups for this role, so they no longer grant privileges
-+ $groups->Limit(FIELD => 'Domain', OPERATOR => 'LIKE', VALUE => "%-Role", CASESENSITIVE => 0 );
-+ $groups->Limit(FIELD => 'Name', OPERATOR => '=', VALUE => $self->GroupType, CASESENSITIVE => 0);
-+
-+ while (my $group = $groups->Next) {
-+ $group->SetDisabled($value);
++ # we can't unconditionally re-enable all role groups because
++ # if you add a role to queues A and B, add users and privileges and
++ # tickets on both, remove the role from B, disable the role, then re-enable
++ # the role, we shouldn't re-enable B because it's still removed
++ my $queues = $self->AddedTo;
++ while (my $queue = $queues->Next) {
++ $self->_SetGroupsDisabledForQueue($value, $queue);
+ }
+
+ $RT::Handle->Commit();
@@ -1533,6 +1585,8 @@
+
+=head2 Add
+
++Adds the custom role to the queue and creates (or re-enables) that queue's role
++group.
+
+=cut
+
@@ -1559,7 +1613,14 @@
+ Object => $queue,
+ );
+
-+ if (!$existing->Id) {
++ if ($existing->Id) {
++ # there already was a role group for this queue, which means
++ # this was previously added, then removed, and is now being re-added,
++ # which means we have to re-enable the queue group and all the
++ # ticket groups
++ $role->_SetGroupsDisabledForQueue(0, $queue);
++ }
++ else {
+ my $group = RT::Group->new($self->CurrentUser);
+ my ($ok, $msg) = $group->CreateRoleGroup(
+ Name => $role->GroupType,
@@ -1571,6 +1632,33 @@
+ $RT::Logger->error("Couldn't create a role group: $msg");
+ return(undef);
+ }
++ }
++
++ $RT::Handle->Commit;
++
++ return ($ok, $msg);
++}
++
++
++=head2 Delete
++
++Removes the custom role from the queue and disables that queue's role group.
++
++=cut
++
++sub Delete {
++ my $self = shift;
++
++ $RT::Handle->BeginTransaction;
++
++ $self->CustomRoleObj->_SetGroupsDisabledForQueue(1, $self->QueueObj);
++
++ # remove the ObjectCustomRole record
++ my ($ok, $msg) = $self->SUPER::Delete(@_);
++ unless ($ok) {
++ $RT::Handle->Rollback;
++ $RT::Logger->error("Couldn't add ObjectCustomRole: $msg");
++ return(undef);
+ }
+
+ $RT::Handle->Commit;
@@ -3209,20 +3297,17 @@
+
+done_testing;
-diff --git a/t/customroles/tickets.t b/t/customroles/tickets.t
+diff --git a/t/customroles/existing-tickets.t b/t/customroles/existing-tickets.t
new file mode 100644
--- /dev/null
-+++ b/t/customroles/tickets.t
++++ b/t/customroles/existing-tickets.t
@@
+use strict;
+use warnings;
+
+use RT::Test tests => undef;
+
-+my $general = RT::Test->load_or_create_queue( Name => 'General' );
-+my $inbox = RT::Test->load_or_create_queue( Name => 'Inbox' );
+my $specs = RT::Test->load_or_create_queue( Name => 'Specs' );
-+my $development = RT::Test->load_or_create_queue( Name => 'Development' );
+
+my $engineer = RT::CustomRole->new(RT->SystemUser);
+my $sales = RT::CustomRole->new(RT->SystemUser);
@@ -3234,6 +3319,610 @@
+my $moss = RT::Test->load_or_create_user( EmailAddress => 'moss at example.com' );
+my $ricky = RT::Test->load_or_create_user( EmailAddress => 'ricky.roma at example.com' );
+
++ok( RT::Test->add_rights( { Principal => 'Privileged', Right => [ qw(CreateTicket ShowTicket ModifyTicket OwnTicket SeeQueue) ] } ));
++
++my $t1 = RT::Test->create_ticket(
++ Queue => $specs,
++ Subject => 'updates with a first test pass',
++);
++
++my $t2 = RT::Test->create_ticket(
++ Queue => $specs,
++ Subject => 'updates without a test pass',
++);
++
++my $sales_grouptype = 'RT::CustomRole-1';
++my $engineer_grouptype = 'RT::CustomRole-2';
++my $unapplied_grouptype = 'RT::CustomRole-3';
++
++diag 'try first pass test' if $ENV{'TEST_VERBOSE'};
++{
++ is($t1->RoleAddresses($engineer_grouptype), '', 'no engineer');
++ is($t1->RoleAddresses($sales_grouptype), '', 'no sales');
++ is($t1->RoleAddresses($unapplied_grouptype), '', 'no unapplied');
++ ok($t1->RoleGroup($engineer_grouptype), 'has a role group object');
++ ok(!$t1->RoleGroup($engineer_grouptype)->id, 'has a role group object with no id');
++
++ my ($ok, $msg) = $t1->AddWatcher(Type => $sales_grouptype, Principal => $ricky->PrincipalObj);
++ ok(!$ok, "couldn't add sales: $msg");
++ is($t1->RoleAddresses($sales_grouptype), '', 'sales still empty');
++
++ ($ok, $msg) = $t1->AddWatcher(Type => $engineer_grouptype, Principal => $linus->PrincipalObj);
++ ok(!$ok, "couldn't add engineer: $msg");
++ is($t1->RoleAddresses($engineer_grouptype), '', 'engineer still empty');
++
++ ($ok, $msg) = $t1->AddWatcher(Type => $unapplied_grouptype, Principal => $linus->PrincipalObj);
++ ok(!$ok, "couldn't add unapplied: $msg");
++ is($t1->RoleAddresses($unapplied_grouptype), '', 'no unapplied members');
++}
++
++diag 'create roles and add them to the queue' if $ENV{'TEST_VERBOSE'};
++{
++ my ($ok, $msg) = $engineer->Create(
++ Name => 'Engineer-' . $$,
++ MaxValues => 1,
++ );
++ ok($ok, "created Engineer role: $msg");
++
++ ($ok, $msg) = $sales->Create(
++ Name => 'Sales-' . $$,
++ MaxValues => 0,
++ );
++ ok($ok, "created Sales role: $msg");
++
++ ($ok, $msg) = $unapplied->Create(
++ Name => 'Unapplied-' . $$,
++ MaxValues => 0,
++ );
++ ok($ok, "created Unapplied role: $msg");
++
++ ($ok, $msg) = $sales->AddToObject($specs->id);
++ ok($ok, "added Sales to Specs: $msg");
++
++ ($ok, $msg) = $engineer->AddToObject($specs->id);
++ ok($ok, "added Engineer to Specs: $msg");
++}
++
++for my $t ($t1, $t2) {
++ diag 'test managing watchers of new roles on #' . $t->id if $ENV{'TEST_VERBOSE'};
++
++ my ($ok, $msg) = $t->AddWatcher(Type => $sales->GroupType, Principal => $ricky->PrincipalObj);
++ ok($ok, "add sales: $msg");
++ is($t->RoleAddresses($sales->GroupType), $ricky->EmailAddress, 'sales ricky');
++
++ ($ok, $msg) = $t->AddWatcher(Type => $sales->GroupType, Principal => $moss->PrincipalObj);
++ ok($ok, "add sales: $msg");
++ is($t->RoleAddresses($sales->GroupType), (join ', ', sort $ricky->EmailAddress, $moss->EmailAddress), 'sales ricky and moss');
++
++ ($ok, $msg) = $t->AddWatcher(Type => $sales->GroupType, Principal => RT->Nobody->PrincipalObj);
++ ok($ok, "add sales: $msg");
++ is($t->RoleAddresses($sales->GroupType), (join ', ', sort $ricky->EmailAddress, $moss->EmailAddress), 'sales ricky and moss');
++
++ ($ok, $msg) = $t->AddWatcher(Type => $engineer->GroupType, Principal => $linus->PrincipalObj);
++ ok($ok, "add engineer: $msg");
++ is($t->RoleAddresses($engineer->GroupType), $linus->EmailAddress, 'engineer linus');
++
++ ($ok, $msg) = $t->AddWatcher(Type => $engineer->GroupType, Principal => $blake->PrincipalObj);
++ ok($ok, "add engineer: $msg");
++ is($t->RoleAddresses($engineer->GroupType), $blake->EmailAddress, 'engineer blake (single-member role so linus gets displaced)');
++
++ ($ok, $msg) = $t->AddWatcher(Type => $engineer->GroupType, Principal => RT->Nobody->PrincipalObj);
++ ok($ok, "add engineer: $msg");
++ is($t->RoleAddresses($engineer->GroupType), '', 'engineer nobody (single-member role so blake gets displaced)');
++
++ ($ok, $msg) = $t->AddWatcher(Type => $unapplied->GroupType, Principal => $linus->PrincipalObj);
++ ok(!$ok, "did not add unapplied role member: $msg");
++ is($t->RoleAddresses($unapplied->GroupType), '', 'no unapplied members');
++
++ ok($t->RoleGroup($sales->GroupType), 'has a Sales group object');
++ ok($t->RoleGroup($sales->GroupType)->id, 'has a Sales group object with an id');
++ ok($t->RoleGroup($engineer->GroupType), 'has an Engineer group object');
++ ok($t->RoleGroup($engineer->GroupType)->id, 'has an Engineer group object with an id');
++ ok($t->RoleGroup($unapplied->GroupType), 'has an Unapplied group object');
++ ok(!$t->RoleGroup($unapplied->GroupType)->id, 'has an Unapplied group object with no id');
++}
++
++done_testing;
+
+diff --git a/t/customroles/rights.t b/t/customroles/rights.t
+new file mode 100644
+--- /dev/null
++++ b/t/customroles/rights.t
+@@
++use strict;
++use warnings;
++
++use RT::Test tests => undef;
++
++my $general = RT::Test->load_or_create_queue( Name => 'General' );
++my $inbox = RT::Test->load_or_create_queue( Name => 'Inbox' );
++my $specs = RT::Test->load_or_create_queue( Name => 'Specs' );
++my $development = RT::Test->load_or_create_queue( Name => 'Development' );
++
++my $engineer = RT::CustomRole->new(RT->SystemUser);
++my $sales = RT::CustomRole->new(RT->SystemUser);
++my $unapplied = RT::CustomRole->new(RT->SystemUser);
++
++my $linus = RT::Test->load_or_create_user( EmailAddress => 'linus at example.com' );
++my $john = RT::Test->load_or_create_user( EmailAddress => 'john at example.com' );
++
++my $blake = RT::Test->load_or_create_user( EmailAddress => 'blake at example.com' );
++my $williamson = RT::Test->load_or_create_user( EmailAddress => 'williamson at example.com' );
++my $moss = RT::Test->load_or_create_user( EmailAddress => 'moss at example.com' );
++my $ricky = RT::Test->load_or_create_user( EmailAddress => 'ricky.roma at example.com' );
++
++my $team = RT::Test->load_or_create_group(
++ 'Team',
++ Members => [$blake, $williamson, $moss, $ricky],
++);
++
++diag 'setup' if $ENV{'TEST_VERBOSE'};
++{
++ my ($ok, $msg) = $engineer->Create(
++ Name => 'Engineer-' . $$,
++ MaxValues => 1,
++ );
++ ok($ok, "created Engineer role: $msg");
++
++ ($ok, $msg) = $sales->Create(
++ Name => 'Sales-' . $$,
++ MaxValues => 0,
++ );
++ ok($ok, "created Sales role: $msg");
++
++ ($ok, $msg) = $unapplied->Create(
++ Name => 'Unapplied-' . $$,
++ MaxValues => 0,
++ );
++ ok($ok, "created Unapplied role: $msg");
++
++ ($ok, $msg) = $sales->AddToObject($inbox->id);
++ ok($ok, "added Sales to Inbox: $msg");
++
++ ($ok, $msg) = $sales->AddToObject($specs->id);
++ ok($ok, "added Sales to Specs: $msg");
++
++ ($ok, $msg) = $engineer->AddToObject($specs->id);
++ ok($ok, "added Engineer to Specs: $msg");
++
++ ($ok, $msg) = $engineer->AddToObject($development->id);
++ ok($ok, "added Engineer to Development: $msg");
++}
++
++# the rights are set up as such:
++# globally: sales can ShowTicket, engineers can ModifyTicket
++# spec queue: sales can CommentOnTicket, engineers can ReplyToTicket
++
++# blake is set up as sales person on inbox queue but not specs
++
++diag 'assign rights and queue watcher' if $ENV{'TEST_VERBOSE'};
++{
++ ok( RT::Test->add_rights( { Principal => $engineer->GroupType, Right => [ qw(ModifyTicket) ] } ));
++ ok( RT::Test->add_rights( { Principal => $sales->GroupType, Right => [ qw(ShowTicket) ] } ));
++ ok( RT::Test->add_rights( { Principal => $engineer->GroupType, Right => [ qw(ReplyToTicket) ], Object => $specs } ));
++ ok( RT::Test->add_rights( { Principal => $sales->GroupType, Right => [ qw(CommentOnTicket) ], Object => $specs } ));
++
++ ok($inbox->AddWatcher(User => $blake, Type => $sales->GroupType));
++}
++
++my ($inbox_individual, $inbox_group, $specs_individual);
++
++sub sales_has_rights_for_inbox_individual {
++ my $has_right = shift;
++ my $rationale = shift || '';
++
++ my $t = $inbox_individual;
++
++ if ($has_right) {
++ is($t->RoleAddresses($sales->GroupType), (join ', ', sort $moss->EmailAddress, $ricky->EmailAddress), 'got salespeople');
++ }
++ else {
++ is($t->RoleAddresses($sales->GroupType), '', "got no salespeople $rationale");
++ }
++
++ if ($has_right) {
++ ok($blake->HasRight(Right => 'ShowTicket', Object => $t), 'blake (queue sales) has right to see the ticket');
++ ok($moss->HasRight(Right => 'ShowTicket', Object => $t), 'moss (ticket sales) has right to see the ticket');
++ ok($ricky->HasRight(Right => 'ShowTicket', Object => $t), 'ricky (ticket sales) has right to see the ticket');
++ }
++ else {
++ ok(!$blake->HasRight(Right => 'ShowTicket', Object => $t), "blake (queue sales) has no right to see the ticket $rationale");
++ ok(!$moss->HasRight(Right => 'ShowTicket', Object => $t), "moss (ticket sales) has no right to see the ticket $rationale");
++ ok(!$ricky->HasRight(Right => 'ShowTicket', Object => $t), "ricky (ticket sales) has no right to see the ticket $rationale");
++ }
++
++ ok(!$blake->HasRight(Right => 'ModifyTicket', Object => $t), 'blake has no right to modify the ticket');
++ ok(!$blake->HasRight(Right => 'ReplyToTicket', Object => $t), 'blake has no right to reply to the ticket');
++ ok(!$blake->HasRight(Right => 'CommentOnTicket', Object => $t), 'blake has no right to comment on the ticket');
++ ok(!$moss->HasRight(Right => 'ModifyTicket', Object => $t), 'moss has no right to modify the ticket');
++ ok(!$moss->HasRight(Right => 'ReplyToTicket', Object => $t), 'moss has no right to reply to the ticket');
++ ok(!$moss->HasRight(Right => 'CommentOnTicket', Object => $t), 'moss has no right to comment on the ticket');
++ ok(!$ricky->HasRight(Right => 'ModifyTicket', Object => $t), 'ricky has no right to modify the ticket');
++ ok(!$ricky->HasRight(Right => 'ReplyToTicket', Object => $t), 'ricky has no right to reply to the ticket');
++ ok(!$ricky->HasRight(Right => 'CommentOnTicket', Object => $t), 'ricky has no right to comment on the ticket');
++ ok(!$williamson->HasRight(Right => 'ShowTicket', Object => $t), 'williamson has no right to see the ticket');
++ ok(!$williamson->HasRight(Right => 'ModifyTicket', Object => $t), 'williamson has no right to modify the ticket');
++ ok(!$williamson->HasRight(Right => 'ReplyToTicket', Object => $t), 'williamson has no right to reply to the ticket');
++ ok(!$williamson->HasRight(Right => 'CommentOnTicket', Object => $t), 'williamson has no right to comment on the ticket');
++}
++
++sub engineer_has_no_rights_for_inbox_individual {
++ my $user = shift;
++ my $t = $inbox_individual;
++
++ ok(!$user->HasRight(Right => 'ShowTicket', Object => $t), $user->EmailAddress . ' has no right to see the ticket');
++ ok(!$user->HasRight(Right => 'ModifyTicket', Object => $t), $user->EmailAddress . ' has no right to modify the ticket');
++ ok(!$user->HasRight(Right => 'ReplyToTicket', Object => $t), $user->EmailAddress . ' has no right to reply to the ticket');
++ ok(!$user->HasRight(Right => 'CommentOnTicket', Object => $t), $user->EmailAddress . ' has no right to comment on the ticket');
++}
++
++sub sales_has_rights_for_inbox_group {
++ my $has_right = shift;
++ my $rationale = shift || '';
++
++ my $t = $inbox_group;
++
++ if ($has_right) {
++ is($t->RoleAddresses($sales->GroupType), (join ', ', sort $moss->EmailAddress, $ricky->EmailAddress, $blake->EmailAddress, $williamson->EmailAddress), 'got all salespeople');
++ }
++ else {
++ is($t->RoleAddresses($sales->GroupType), '', "got no salespeople $rationale");
++ }
++
++ for my $user ($blake, $moss, $ricky, $williamson) {
++ if ($has_right) {
++ ok($user->HasRight(Right => 'ShowTicket', Object => $t), $user->Name . " (member of ticket sales group team) has right to see the ticket");
++ }
++ else {
++ ok(!$user->HasRight(Right => 'ShowTicket', Object => $t), $user->Name . " (member of ticket sales group team) has no right to see the ticket $rationale");
++ }
++
++ ok(!$user->HasRight(Right => 'ModifyTicket', Object => $t), $user->Name . " (member of ticket sales group team) has no right to modify the ticket");
++ ok(!$user->HasRight(Right => 'ReplyToTicket', Object => $t), $user->Name . " (member of ticket sales group team) has no right to reply to the ticket");
++ ok(!$user->HasRight(Right => 'CommentOnTicket', Object => $t), $user->Name . " (member of ticket sales group team) has no right to comment on the ticket");
++ }
++
++ ok(!$linus->HasRight(Right => 'ShowTicket', Object => $t), "linus has no ShowTicket on inbox");
++ ok(!$linus->HasRight(Right => 'ModifyTicket', Object => $t), "linus has no ModifyTicket on inbox");
++ ok(!$linus->HasRight(Right => 'ReplyToTicket', Object => $t), "linus has no ReplyToTicket on inbox");
++ ok(!$linus->HasRight(Right => 'CommentOnTicket', Object => $t), "linus has no CommentOnTicket on inbox");
++}
++
++sub sales_has_rights_for_specs_individual {
++ my $has_right = shift;
++ my $rationale = shift || '';
++
++ my $t = $specs_individual;
++
++ if (!$has_right || $has_right == 2) {
++ is($t->RoleAddresses($sales->GroupType), '', "got no salespeople $rationale");
++ }
++ else {
++ is($t->RoleAddresses($sales->GroupType), (join ', ', sort $moss->EmailAddress, $ricky->EmailAddress), 'got salespeople');
++ }
++
++ if (!$has_right) {
++ ok(!$moss->HasRight(Right => 'ShowTicket', Object => $t), "moss (ticket sales) has no right to see the ticket $rationale");
++ ok(!$moss->HasRight(Right => 'CommentOnTicket', Object => $t), "moss (ticket sales) has no right to comment on the ticket $rationale");
++ ok(!$ricky->HasRight(Right => 'ShowTicket', Object => $t), "ricky (ticket sales) has no right to see the ticket $rationale");
++ ok(!$ricky->HasRight(Right => 'CommentOnTicket', Object => $t), "ricky (ticket sales) has no right to comment on the ticket $rationale");
++ }
++ elsif ($has_right == 2) {
++ ok($moss->HasRight(Right => 'ShowTicket', Object => $t), 'moss (ticket sales) has right to see the ticket thru global sales right');
++ ok(!$moss->HasRight(Right => 'CommentOnTicket', Object => $t), "moss (ticket sales) has no right to comment on the ticket $rationale");
++ ok($ricky->HasRight(Right => 'ShowTicket', Object => $t), 'ricky (ticket sales) has right to see the ticket thru global sales right');
++ ok(!$ricky->HasRight(Right => 'CommentOnTicket', Object => $t), "ricky (ticket sales) has no right to comment on the ticket $rationale");
++ }
++ else {
++ ok($moss->HasRight(Right => 'ShowTicket', Object => $t), 'moss (ticket sales) has right to see the ticket');
++ ok($moss->HasRight(Right => 'CommentOnTicket', Object => $t), 'moss (ticket sales) has right to comment on the ticket');
++ ok($ricky->HasRight(Right => 'ShowTicket', Object => $t), 'ricky (ticket sales) has right to see the ticket');
++ ok($ricky->HasRight(Right => 'CommentOnTicket', Object => $t), 'ricky (ticket sales) has right to comment on the ticket');
++ }
++
++ ok(!$blake->HasRight(Right => 'ShowTicket', Object => $t), 'blake has no right to see the ticket');
++ ok(!$blake->HasRight(Right => 'ModifyTicket', Object => $t), 'blake has no right to modify the ticket');
++ ok(!$blake->HasRight(Right => 'ReplyToTicket', Object => $t), 'blake has no right to reply to the ticket');
++ ok(!$blake->HasRight(Right => 'CommentOnTicket', Object => $t), 'blake has no right to comment on the ticket');
++ ok(!$moss->HasRight(Right => 'ModifyTicket', Object => $t), 'moss has no right to modify the ticket');
++ ok(!$moss->HasRight(Right => 'ReplyToTicket', Object => $t), 'moss has no right to reply to the ticket');
++ ok(!$ricky->HasRight(Right => 'ModifyTicket', Object => $t), 'ricky has no right to modify the ticket');
++ ok(!$ricky->HasRight(Right => 'ReplyToTicket', Object => $t), 'ricky has no right to reply to the ticket');
++ ok(!$williamson->HasRight(Right => 'ShowTicket', Object => $t), 'williamson has no right to see the ticket');
++ ok(!$williamson->HasRight(Right => 'ModifyTicket', Object => $t), 'williamson has no right to modify the ticket');
++ ok(!$williamson->HasRight(Right => 'ReplyToTicket', Object => $t), 'williamson has no right to reply to the ticket');
++ ok(!$williamson->HasRight(Right => 'CommentOnTicket', Object => $t), 'williamson has no right to comment on the ticket');
++}
++
++sub engineer_has_rights_for_specs_individual {
++ my $user = shift;
++ my $has_right = shift;
++ my $t = $specs_individual;
++
++ ok(!$user->HasRight(Right => 'ShowTicket', Object => $t), $user->EmailAddress . ' has no right to see the ticket');
++ ok(!$user->HasRight(Right => 'CommentOnTicket', Object => $t), $user->EmailAddress . ' has no right to comment on the ticket');
++
++ if ($has_right) {
++ ok($user->HasRight(Right => 'ModifyTicket', Object => $t), $user->EmailAddress . ' (ticket engineer) has right to modify the ticket');
++ ok($user->HasRight(Right => 'ReplyToTicket', Object => $t), $user->EmailAddress . ' (ticket engineer) has right to reply to the ticket');
++ }
++}
++
++diag 'check individual rights on Inbox' if $ENV{'TEST_VERBOSE'};
++{
++ my $t = $inbox_individual = RT::Test->create_ticket(
++ Queue => $inbox,
++ Subject => 'wrongs',
++ $sales->GroupType => [$moss->EmailAddress, $ricky->EmailAddress],
++ );
++ ok($t->id, 'created ticket');
++
++ sales_has_rights_for_inbox_individual(1);
++ engineer_has_no_rights_for_inbox_individual($_) for $linus, $john;
++}
++
++diag 'check group rights on Inbox' if $ENV{'TEST_VERBOSE'};
++{
++ my $t = $inbox_group = RT::Test->create_ticket(
++ Queue => $inbox,
++ Subject => 'wrongs',
++ $sales->GroupType => $team->PrincipalId,
++ );
++ ok($t->id, 'created ticket');
++
++ sales_has_rights_for_inbox_group(1);
++}
++
++diag 'check individual rights on Specs' if $ENV{'TEST_VERBOSE'};
++{
++ my $t = $specs_individual = RT::Test->create_ticket(
++ Queue => $specs,
++ Subject => 'wrongs',
++ $engineer->GroupType => $linus->PrincipalId,
++ $sales->GroupType => [$moss->EmailAddress, $ricky->EmailAddress],
++ );
++ ok($t->id, 'created ticket');
++
++ sales_has_rights_for_specs_individual(1);
++ engineer_has_rights_for_specs_individual($linus => 1);
++ engineer_has_rights_for_specs_individual($john => 0);
++}
++
++diag 'disable Sales custom role to see how it shakes out permissions' if $ENV{'TEST_VERBOSE'};
++{
++ my ($ok, $msg) = $sales->SetDisabled(1);
++ ok($ok, $msg);
++
++ sales_has_rights_for_inbox_individual(0, 'because sales role is disabled');
++ sales_has_rights_for_inbox_group(0, 'because sales role is disabled');
++ sales_has_rights_for_specs_individual(0, 'because sales role is disabled');
++
++ engineer_has_no_rights_for_inbox_individual($_) for $linus, $john;
++ engineer_has_rights_for_specs_individual($linus => 1);
++ engineer_has_rights_for_specs_individual($john => 0);
++}
++
++diag 're-enable Sales custom role to make sure all old group rights and memberships come back' if $ENV{'TEST_VERBOSE'};
++{
++ my ($ok, $msg) = $sales->SetDisabled(0);
++ ok($ok, $msg);
++
++ sales_has_rights_for_inbox_individual(1);
++ sales_has_rights_for_inbox_group(1);
++ sales_has_rights_for_specs_individual(1);
++
++ engineer_has_no_rights_for_inbox_individual($_) for $linus, $john;
++ engineer_has_rights_for_specs_individual($linus => 1);
++ engineer_has_rights_for_specs_individual($john => 0);
++}
++
++diag 'remove Sales custom role from Inbox queue' if $ENV{'TEST_VERBOSE'};
++{
++ my ($ok, $msg) = $sales->RemoveFromObject($inbox->id);
++ ok($ok, "removed Sales from Inbox: $msg");
++
++ sales_has_rights_for_inbox_individual(0, 'because sales role was removed from Inbox');
++ sales_has_rights_for_inbox_group(0, 'because sales role was removed from Inbox');
++ sales_has_rights_for_specs_individual(1);
++
++ engineer_has_no_rights_for_inbox_individual($_) for $linus, $john;
++ engineer_has_rights_for_specs_individual($linus => 1);
++ engineer_has_rights_for_specs_individual($john => 0);
++}
++
++diag 're-add Sales custom role to Inbox queue' if $ENV{'TEST_VERBOSE'};
++{
++ my ($ok, $msg) = $sales->AddToObject($inbox->id);
++ ok($ok, "re-added Sales to Specs: $msg");
++
++ sales_has_rights_for_inbox_individual(1);
++ sales_has_rights_for_inbox_group(1);
++ sales_has_rights_for_specs_individual(1);
++
++ engineer_has_no_rights_for_inbox_individual($_) for $linus, $john;
++ engineer_has_rights_for_specs_individual($linus => 1);
++ engineer_has_rights_for_specs_individual($john => 0);
++}
++
++diag 'remove Sales custom role from Inbox queue...' if $ENV{'TEST_VERBOSE'};
++{
++ my ($ok, $msg) = $sales->RemoveFromObject($inbox->id);
++ ok($ok, "removed Sales from Inbox: $msg");
++
++ sales_has_rights_for_inbox_individual(0, 'because sales role was removed from Inbox');
++ sales_has_rights_for_inbox_group(0, 'because sales role was removed from Inbox');
++ sales_has_rights_for_specs_individual(1);
++
++ engineer_has_no_rights_for_inbox_individual($_) for $linus, $john;
++ engineer_has_rights_for_specs_individual($linus => 1);
++ engineer_has_rights_for_specs_individual($john => 0);
++}
++
++diag 'disable Sales custom role to see how it shakes out permissions' if $ENV{'TEST_VERBOSE'};
++{
++ my ($ok, $msg) = $sales->SetDisabled(1);
++ ok($ok, $msg);
++
++ sales_has_rights_for_inbox_individual(0, 'because sales role is disabled and was removed from Inbox');
++ sales_has_rights_for_inbox_group(0, 'because sales role is disabled and was removed from Inbox');
++ sales_has_rights_for_specs_individual(0, 'because sales role is disabled');
++
++ engineer_has_no_rights_for_inbox_individual($_) for $linus, $john;
++ engineer_has_rights_for_specs_individual($linus => 1);
++ engineer_has_rights_for_specs_individual($john => 0);
++}
++
++diag 're-enable Sales custom role to make sure specs regains rights and members but inbox does not because it was removed' if $ENV{'TEST_VERBOSE'};
++{
++ my ($ok, $msg) = $sales->SetDisabled(0);
++ ok($ok, $msg);
++
++ sales_has_rights_for_inbox_individual(0, 'because sales role is still removed from Inbox');
++ sales_has_rights_for_inbox_group(0, 'because sales role is still removed from Inbox');
++ sales_has_rights_for_specs_individual(1);
++
++ engineer_has_no_rights_for_inbox_individual($_) for $linus, $john;
++ engineer_has_rights_for_specs_individual($linus => 1);
++ engineer_has_rights_for_specs_individual($john => 0);
++}
++
++diag 're-add Sales custom role to Inbox queue' if $ENV{'TEST_VERBOSE'};
++{
++ my ($ok, $msg) = $sales->AddToObject($inbox->id);
++ ok($ok, "re-added Sales to Specs: $msg");
++
++ sales_has_rights_for_inbox_individual(1);
++ sales_has_rights_for_inbox_group(1);
++ sales_has_rights_for_specs_individual(1);
++
++ engineer_has_no_rights_for_inbox_individual($_) for $linus, $john;
++ engineer_has_rights_for_specs_individual($linus => 1);
++ engineer_has_rights_for_specs_individual($john => 0);
++}
++
++diag 'change engineer from linus to john' if $ENV{'TEST_VERBOSE'};
++{
++ my ($ok, $msg) = $specs_individual->AddWatcher(Type => $engineer->GroupType, Principal => $john->PrincipalObj);
++ ok($ok, "set John as engineer: $msg");
++ is($specs_individual->RoleAddresses($engineer->GroupType), $john->EmailAddress, 'engineer set to John');
++
++ sales_has_rights_for_inbox_individual(1);
++ sales_has_rights_for_inbox_group(1);
++ sales_has_rights_for_specs_individual(1);
++
++ engineer_has_no_rights_for_inbox_individual($_) for $linus, $john;
++ engineer_has_rights_for_specs_individual($linus => 0);
++ engineer_has_rights_for_specs_individual($john => 1);
++}
++
++diag 'change engineer from john to nobody' if $ENV{'TEST_VERBOSE'};
++{
++ my ($ok, $msg) = $specs_individual->AddWatcher(Type => $engineer->GroupType, Principal => RT->Nobody->PrincipalObj);
++ ok($ok, "set Nobody as engineer: $msg");
++ is($specs_individual->RoleAddresses($engineer->GroupType), '', 'engineer set to Nobody');
++
++ sales_has_rights_for_inbox_individual(1);
++ sales_has_rights_for_inbox_group(1);
++ sales_has_rights_for_specs_individual(1);
++
++ engineer_has_no_rights_for_inbox_individual($_) for $linus, $john;
++ engineer_has_rights_for_specs_individual($linus => 0);
++ engineer_has_rights_for_specs_individual($john => 0);
++}
++
++diag 'change engineer from nobody to linus' if $ENV{'TEST_VERBOSE'};
++{
++ my ($ok, $msg) = $specs_individual->AddWatcher(Type => $engineer->GroupType, Principal => $linus->PrincipalObj);
++ ok($ok, "set Linus as engineer: $msg");
++ is($specs_individual->RoleAddresses($engineer->GroupType), $linus->EmailAddress, 'engineer set to Linus');
++
++ sales_has_rights_for_inbox_individual(1);
++ sales_has_rights_for_inbox_group(1);
++ sales_has_rights_for_specs_individual(1);
++
++ engineer_has_no_rights_for_inbox_individual($_) for $linus, $john;
++ engineer_has_rights_for_specs_individual($linus => 1);
++ engineer_has_rights_for_specs_individual($john => 0);
++}
++
++diag 'change queue from Specs to General' if $ENV{'TEST_VERBOSE'};
++{
++ my ($ok, $msg) = $specs_individual->SetQueue($general->Id);
++ ok($ok, "set queue to General: $msg");
++
++ sales_has_rights_for_inbox_individual(1);
++ sales_has_rights_for_inbox_group(1);
++ sales_has_rights_for_specs_individual(2, 'queue changed to General');
++
++ engineer_has_no_rights_for_inbox_individual($_) for $linus, $john;
++ engineer_has_rights_for_specs_individual($linus => 0);
++ engineer_has_rights_for_specs_individual($john => 0);
++}
++
++diag 'change queue from General to Specs' if $ENV{'TEST_VERBOSE'};
++{
++ my ($ok, $msg) = $specs_individual->SetQueue($specs->Id);
++ ok($ok, "set queue to Specs: $msg");
++
++ sales_has_rights_for_inbox_individual(1);
++ sales_has_rights_for_inbox_group(1);
++ sales_has_rights_for_specs_individual(1);
++
++ engineer_has_no_rights_for_inbox_individual($_) for $linus, $john;
++ engineer_has_rights_for_specs_individual($linus => 1);
++ engineer_has_rights_for_specs_individual($john => 0);
++}
++
++done_testing;
++
+
+diff --git a/t/customroles/tickets.t b/t/customroles/tickets.t
+new file mode 100644
+--- /dev/null
++++ b/t/customroles/tickets.t
+@@
++use strict;
++use warnings;
++
++use RT::Test tests => undef;
++
++my $general = RT::Test->load_or_create_queue( Name => 'General' );
++my $inbox = RT::Test->load_or_create_queue( Name => 'Inbox' );
++my $specs = RT::Test->load_or_create_queue( Name => 'Specs' );
++my $development = RT::Test->load_or_create_queue( Name => 'Development' );
++
++my $engineer = RT::CustomRole->new(RT->SystemUser);
++my $sales = RT::CustomRole->new(RT->SystemUser);
++my $unapplied = RT::CustomRole->new(RT->SystemUser);
++
++my $linus = RT::Test->load_or_create_user( EmailAddress => 'linus at example.com' );
++my $blake = RT::Test->load_or_create_user( EmailAddress => 'blake at example.com' );
++my $williamson = RT::Test->load_or_create_user( EmailAddress => 'williamson at example.com' );
++my $moss = RT::Test->load_or_create_user( EmailAddress => 'moss at example.com' );
++my $ricky = RT::Test->load_or_create_user( EmailAddress => 'ricky.roma at example.com' );
++
++my $team = RT::Test->load_or_create_group(
++ 'Team',
++ Members => [$blake, $williamson, $moss, $ricky],
++);
++
++sub txn_messages_like {
++ local $Test::Builder::Level = $Test::Builder::Level + 1;
++
++ my $t = shift;
++ my $re = shift;
++
++ my $txns = $t->Transactions;
++ $txns->Limit(FIELD => 'Type', VALUE => 'SetWatcher');
++ $txns->Limit(FIELD => 'Type', VALUE => 'AddWatcher');
++ $txns->Limit(FIELD => 'Type', VALUE => 'DelWatcher');
++
++ is($txns->Count, scalar(@$re), 'expected number of transactions');
++
++ while (my $txn = $txns->Next) {
++ like($txn->BriefDescription, (shift(@$re) || qr/(?!)/));
++ }
++}
+
+diag 'setup' if $ENV{'TEST_VERBOSE'};
+{
@@ -3294,7 +3983,7 @@
+ AdminCc => [$blake->EmailAddress],
+ );
+ is($general2->OwnerObj->id, $linus->id, 'owner is correct');
-+ is($general2->RequestorAddresses, (join ', ', $moss->EmailAddress, $williamson->EmailAddress), 'requestors correct');
++ is($general2->RequestorAddresses, (join ', ', sort $moss->EmailAddress, $williamson->EmailAddress), 'requestors correct');
+ is($general2->CcAddresses, $ricky->EmailAddress, 'cc correct');
+ is($general2->AdminCcAddresses, $blake->EmailAddress, 'admincc correct');
+ is($general2->RoleAddresses($engineer->GroupType), '', 'no engineer (role not applied to queue)');
@@ -3339,7 +4028,7 @@
+ AdminCc => [$blake->EmailAddress],
+ );
+ is($inbox2->OwnerObj->id, $linus->id, 'owner is correct');
-+ is($inbox2->RequestorAddresses, (join ', ', $moss->EmailAddress, $williamson->EmailAddress), 'requestors correct');
++ is($inbox2->RequestorAddresses, (join ', ', sort $moss->EmailAddress, $williamson->EmailAddress), 'requestors correct');
+ is($inbox2->CcAddresses, $ricky->EmailAddress, 'cc correct');
+ is($inbox2->AdminCcAddresses, $blake->EmailAddress, 'admincc correct');
+ is($inbox2->RoleAddresses($engineer->GroupType), '', 'no engineer (role not applied to queue)');
@@ -3358,8 +4047,185 @@
+ is($inbox3->AdminCcAddresses, '', 'no admincc');
+ is($inbox3->RoleAddresses($engineer->GroupType), '', 'no engineer (role not applied to queue)');
+ is($inbox3->RoleAddresses($sales->GroupType), $blake->EmailAddress, 'got sales');
++
++ my $inbox4 = RT::Test->create_ticket(
++ Queue => $inbox,
++ Subject => 'more',
++ Owner => $ricky,
++ $engineer->GroupType => $linus,
++ $sales->GroupType => [$blake->EmailAddress, $williamson->EmailAddress],
++ );
++ is($inbox4->OwnerObj->id, $ricky->id, 'owner is correct');
++ is($inbox4->RequestorAddresses, '', 'no requestors');
++ is($inbox4->CcAddresses, '', 'no cc');
++ is($inbox4->AdminCcAddresses, '', 'no admincc');
++ is($inbox4->RoleAddresses($engineer->GroupType), '', 'no engineer (role not applied to queue)');
++ is($inbox4->RoleAddresses($sales->GroupType), (join ', ', sort $blake->EmailAddress, $williamson->EmailAddress), 'got sales');
++}
++
++diag 'create tickets in Specs (both roles)' if $ENV{'TEST_VERBOSE'};
++{
++ my $specs1 = RT::Test->create_ticket(
++ Queue => $specs,
++ Subject => 'a ticket',
++ Owner => $williamson,
++ Requestor => [$blake->EmailAddress],
++ );
++ is($specs1->OwnerObj->id, $williamson->id, 'owner is correct');
++ is($specs1->RequestorAddresses, $blake->EmailAddress, 'requestors correct');
++ is($specs1->CcAddresses, '', 'no ccs');
++ is($specs1->AdminCcAddresses, '', 'no adminccs');
++ is($specs1->RoleAddresses($engineer->GroupType), '', 'no engineer (role not applied to queue)');
++ is($specs1->RoleAddresses($sales->GroupType), '', 'no sales (role not applied to queue)');
++
++ my $specs2 = RT::Test->create_ticket(
++ Queue => $specs,
++ Subject => 'another ticket',
++ Owner => $linus,
++ Requestor => [$moss->EmailAddress, $williamson->EmailAddress],
++ Cc => [$ricky->EmailAddress],
++ AdminCc => [$blake->EmailAddress],
++ );
++ is($specs2->OwnerObj->id, $linus->id, 'owner is correct');
++ is($specs2->RequestorAddresses, (join ', ', sort $moss->EmailAddress, $williamson->EmailAddress), 'requestors correct');
++ is($specs2->CcAddresses, $ricky->EmailAddress, 'cc correct');
++ is($specs2->AdminCcAddresses, $blake->EmailAddress, 'admincc correct');
++ is($specs2->RoleAddresses($engineer->GroupType), '', 'no engineer (role not applied to queue)');
++ is($specs2->RoleAddresses($sales->GroupType), '', 'no sales (role not applied to queue)');
++
++ my $specs3 = RT::Test->create_ticket(
++ Queue => $specs,
++ Subject => 'oops',
++ Owner => $ricky,
++ $engineer->GroupType => $linus,
++ $sales->GroupType => [$blake->EmailAddress],
++ );
++ is($specs3->OwnerObj->id, $ricky->id, 'owner is correct');
++ is($specs3->RequestorAddresses, '', 'no requestors');
++ is($specs3->CcAddresses, '', 'no cc');
++ is($specs3->AdminCcAddresses, '', 'no admincc');
++ is($specs3->RoleAddresses($engineer->GroupType), $linus->EmailAddress, 'got engineer');
++ is($specs3->RoleAddresses($sales->GroupType), $blake->EmailAddress, 'got sales');
++
++ my $specs4 = RT::Test->create_ticket(
++ Queue => $specs,
++ Subject => 'more',
++ Owner => $ricky,
++ $engineer->GroupType => $linus,
++ $sales->GroupType => [$blake->EmailAddress, $williamson->EmailAddress],
++ );
++ is($specs4->OwnerObj->id, $ricky->id, 'owner is correct');
++ is($specs4->RequestorAddresses, '', 'no requestors');
++ is($specs4->CcAddresses, '', 'no cc');
++ is($specs4->AdminCcAddresses, '', 'no admincc');
++ is($specs4->RoleAddresses($engineer->GroupType), $linus->EmailAddress, 'got engineer');
++ is($specs4->RoleAddresses($sales->GroupType), (join ', ', sort $blake->EmailAddress, $williamson->EmailAddress), 'got sales');
++}
++
++diag 'update ticket in Specs' if $ENV{'TEST_VERBOSE'};
++{
++ my $t = RT::Test->create_ticket(
++ Queue => $specs,
++ Subject => 'updates',
++ );
++
++ is($t->OwnerObj->id, RT->Nobody->id, 'owner nobody');
++ is($t->RequestorAddresses, '', 'no requestors');
++ is($t->CcAddresses, '', 'no cc');
++ is($t->AdminCcAddresses, '', 'no admincc');
++ is($t->RoleAddresses($engineer->GroupType), '', 'no engineer');
++ is($t->RoleAddresses($sales->GroupType), '', 'no sales');
++ is($t->RoleAddresses($unapplied->GroupType), '', 'no unapplied');
++
++ my ($ok, $msg) = $t->SetOwner($linus);
++ ok($ok, "set owner: $msg");
++ is($t->OwnerObj->id, $linus->id, 'owner linus');
++
++ ($ok, $msg) = $t->AddWatcher(Type => 'Requestor', Principal => $ricky->PrincipalObj);
++ ok($ok, "add requestor: $msg");
++ is($t->RequestorAddresses, $ricky->EmailAddress, 'requestor ricky');
++
++ ($ok, $msg) = $t->AddWatcher(Type => 'AdminCc', Principal => $blake->PrincipalObj);
++ ok($ok, "add admincc: $msg");
++ is($t->AdminCcAddresses, $blake->EmailAddress, 'admincc blake');
++
++ ($ok, $msg) = $t->AddWatcher(Type => 'Cc', Principal => $moss->PrincipalObj);
++ ok($ok, "add cc: $msg");
++ is($t->CcAddresses, $moss->EmailAddress, 'cc moss');
++
++ ($ok, $msg) = $t->AddWatcher(Type => $sales->GroupType, Principal => $ricky->PrincipalObj);
++ ok($ok, "add sales: $msg");
++ is($t->RoleAddresses($sales->GroupType), $ricky->EmailAddress, 'sales ricky');
++
++ ($ok, $msg) = $t->AddWatcher(Type => $sales->GroupType, Principal => $moss->PrincipalObj);
++ ok($ok, "add sales: $msg");
++ is($t->RoleAddresses($sales->GroupType), (join ', ', sort $ricky->EmailAddress, $moss->EmailAddress), 'sales ricky and moss');
++
++ ($ok, $msg) = $t->AddWatcher(Type => $sales->GroupType, Principal => RT->Nobody->PrincipalObj);
++ ok($ok, "add sales: $msg");
++ is($t->RoleAddresses($sales->GroupType), (join ', ', sort $ricky->EmailAddress, $moss->EmailAddress), 'sales ricky and moss');
++
++ ($ok, $msg) = $t->DeleteWatcher(Type => $sales->GroupType, PrincipalId => $moss->PrincipalId);
++ ok($ok, "remove sales: $msg");
++ is($t->RoleAddresses($sales->GroupType), $ricky->EmailAddress, 'sales ricky');
++
++ ($ok, $msg) = $t->DeleteWatcher(Type => $sales->GroupType, PrincipalId => $ricky->PrincipalId);
++ ok($ok, "remove sales: $msg");
++ is($t->RoleAddresses($sales->GroupType), '', 'sales empty');
++
++ ($ok, $msg) = $t->AddWatcher(Type => $engineer->GroupType, Principal => $linus->PrincipalObj);
++ ok($ok, "add engineer: $msg");
++ is($t->RoleAddresses($engineer->GroupType), $linus->EmailAddress, 'engineer linus');
++
++ ($ok, $msg) = $t->AddWatcher(Type => $engineer->GroupType, Principal => $blake->PrincipalObj);
++ ok($ok, "add engineer: $msg");
++ is($t->RoleAddresses($engineer->GroupType), $blake->EmailAddress, 'engineer blake (single-member role so linus gets displaced)');
++
++ ($ok, $msg) = $t->AddWatcher(Type => $engineer->GroupType, Principal => RT->Nobody->PrincipalObj);
++ ok($ok, "add engineer: $msg");
++ is($t->RoleAddresses($engineer->GroupType), '', 'engineer nobody (single-member role so blake gets displaced)');
++
++ ($ok, $msg) = $t->AddWatcher(Type => $unapplied->GroupType, Principal => $linus->PrincipalObj);
++ ok(!$ok, "did not add unapplied role member: $msg");
++ like($msg, qr/That role is invalid for this object/);
++ is($t->RoleAddresses($unapplied->GroupType), '', 'no unapplied members');
++
++ txn_messages_like($t, [
++ qr/Owner set to linus\@example\.com/,
++ qr/Requestor ricky\.roma\@example\.com added/,
++ qr/AdminCc blake\@example\.com added/,
++ qr/Cc moss\@example\.com added/,
++ qr/Sales-$$ ricky\.roma\@example\.com added/,
++ qr/Sales-$$ moss\@example\.com added/,
++ qr/Sales-$$ Nobody in particular added/,
++ qr/Sales-$$ moss\@example\.com deleted/,
++ qr/Sales-$$ ricky\.roma\@example\.com deleted/,
++ qr/Engineer-$$ set to linus\@example\.com/,
++ qr/Engineer-$$ set to blake\@example\.com/,
++ qr/Engineer-$$ set to Nobody in particular/,
++ ]);
++}
++
++diag 'groups can be role members' if $ENV{'TEST_VERBOSE'};
++{
++ my $t = RT::Test->create_ticket(
++ Queue => $specs,
++ Subject => 'groups',
++ );
++
++ my ($ok, $msg) = $t->AddWatcher(Type => $sales->GroupType, Principal => $team->PrincipalObj);
++ ok($ok, "add team: $msg");
++ is($t->RoleAddresses($sales->GroupType), (join ', ', sort $blake->EmailAddress, $ricky->EmailAddress, $moss->EmailAddress, $williamson->EmailAddress), 'sales is all the team members');
++
++ ($ok, $msg) = $t->AddWatcher(Type => $engineer->GroupType, Principal => $team->PrincipalObj);
++ ok(!$ok, "could not add team: $msg");
++ like($msg, qr/cannot be a group/);
++ is($t->RoleAddresses($engineer->GroupType), '', 'engineer is still nobody');
++
++ txn_messages_like($t, [
++ qr/Sales-$$ group Team added/,
++ ]);
+}
+
+done_testing;
-+
29: 5a924ad = 29: b35a81d @CustomRoles in initialdata, support CustomRole in @ACL
30: 8be477a = 30: bb1cc0d Add custom roles to search builder
31: 1a8e3a1 = 31: 6c22fa9 Ensure custom role name uniqueness in rt-validator
More information about the rt-commit
mailing list