1 # BEGIN BPS TAGGED BLOCK {{{
5 # This software is Copyright (c) 1996-2011 Best Practical Solutions, LLC
6 # <sales@bestpractical.com>
8 # (Except where explicitly superseded by other copyright notices)
13 # This work is made available to you under the terms of Version 2 of
14 # the GNU General Public License. A copy of that license should have
15 # been provided with this software, but in any event can be snarfed
18 # This work is distributed in the hope that it will be useful, but
19 # WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 # General Public License for more details.
23 # You should have received a copy of the GNU General Public License
24 # along with this program; if not, write to the Free Software
25 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 # 02110-1301 or visit their web page on the internet at
27 # http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
30 # CONTRIBUTION SUBMISSION POLICY:
32 # (The following paragraph is not intended to limit the rights granted
33 # to you to modify and distribute this software under the terms of
34 # the GNU General Public License and is only of importance to you if
35 # you choose to contribute your changes and enhancements to the
36 # community by submitting them to Best Practical Solutions, LLC.)
38 # By intentionally submitting any modifications, corrections or
39 # derivatives to this work, or any other work intended for use with
40 # Request Tracker, to Best Practical Solutions, LLC, you confirm that
41 # you are the copyright holder for those contributions and you grant
42 # Best Practical Solutions, LLC a nonexclusive, worldwide, irrevocable,
43 # royalty-free, perpetual, license to use, copy, create derivative
44 # works based on those contributions, and sublicense and distribute
45 # those contributions and any derivatives thereof.
47 # END BPS TAGGED BLOCK }}}
51 RT::Queue - an RT Queue object
69 no warnings qw(redefine);
73 use RT::Interface::Email;
75 our @DEFAULT_ACTIVE_STATUS = qw(new open stalled);
76 our @DEFAULT_INACTIVE_STATUS = qw(resolved rejected deleted);
78 # $self->loc('new'); # For the string extractor to get a string to localize
79 # $self->loc('open'); # For the string extractor to get a string to localize
80 # $self->loc('stalled'); # For the string extractor to get a string to localize
81 # $self->loc('resolved'); # For the string extractor to get a string to localize
82 # $self->loc('rejected'); # For the string extractor to get a string to localize
83 # $self->loc('deleted'); # For the string extractor to get a string to localize
87 SeeQueue => 'Can this principal see this queue', # loc_pair
88 AdminQueue => 'Create, delete and modify queues', # loc_pair
89 ShowACL => 'Display Access Control List', # loc_pair
90 ModifyACL => 'Modify Access Control List', # loc_pair
91 ModifyQueueWatchers => 'Modify the queue watchers', # loc_pair
92 SeeCustomField => 'See custom field values', # loc_pair
93 ModifyCustomField => 'Modify custom field values', # loc_pair
94 AssignCustomFields => 'Assign and remove custom fields', # loc_pair
95 ModifyTemplate => 'Modify Scrip templates for this queue', # loc_pair
96 ShowTemplate => 'Display Scrip templates for this queue', # loc_pair
98 ModifyScrips => 'Modify Scrips for this queue', # loc_pair
99 ShowScrips => 'Display Scrips for this queue', # loc_pair
101 ShowTicket => 'See ticket summaries', # loc_pair
102 ShowTicketComments => 'See ticket private commentary', # loc_pair
103 ShowOutgoingEmail => 'See exact outgoing email messages and their recipeients', # loc_pair
105 Watch => 'Sign up as a ticket Requestor or ticket or queue Cc', # loc_pair
106 WatchAsAdminCc => 'Sign up as a ticket or queue AdminCc', # loc_pair
107 CreateTicket => 'Create tickets in this queue', # loc_pair
108 ReplyToTicket => 'Reply to tickets', # loc_pair
109 CommentOnTicket => 'Comment on tickets', # loc_pair
110 OwnTicket => 'Own tickets', # loc_pair
111 ModifyTicket => 'Modify tickets', # loc_pair
112 DeleteTicket => 'Delete tickets', # loc_pair
113 TakeTicket => 'Take tickets', # loc_pair
114 StealTicket => 'Steal tickets', # loc_pair
116 ForwardMessage => 'Forward messages to third person(s)', # loc_pair
120 # Tell RT::ACE that this sort of object can get acls granted
121 $RT::ACE::OBJECT_TYPES{'RT::Queue'} = 1;
123 # TODO: This should be refactored out into an RT::ACLedObject or something
124 # stuff the rights into a hash of rights that can exist.
126 foreach my $right ( keys %{$RIGHTS} ) {
127 $RT::ACE::LOWERCASERIGHTNAMES{ lc $right } = $right;
130 =head2 AddRights C<RIGHT>, C<DESCRIPTION> [, ...]
132 Adds the given rights to the list of possible rights. This method
133 should be called during server startup, not at runtime.
140 $RIGHTS = { %$RIGHTS, %new };
141 %RT::ACE::LOWERCASERIGHTNAMES = ( %RT::ACE::LOWERCASERIGHTNAMES,
142 map { lc($_) => $_ } keys %new);
147 my %args = ( Target => '',
153 unless ( $self->CurrentUserHasRight('ModifyQueue') ) {
154 return ( 0, $self->loc("Permission Denied") );
157 return $self->SUPER::_AddLink(%args);
170 unless ( $self->CurrentUserHasRight('ModifyQueue') ) {
171 $RT::Logger->debug("No permission to delete links");
172 return ( 0, $self->loc('Permission Denied'))
175 return $self->SUPER::_DeleteLink(%args);
178 =head2 AvailableRights
180 Returns a hash of available rights for this object. The keys are the right names and the values are a description of what the rights do
184 sub AvailableRights {
189 # {{{ ActiveStatusArray
191 =head2 ActiveStatusArray
193 Returns an array of all ActiveStatuses for this queue
197 sub ActiveStatusArray {
199 if (RT->Config->Get('ActiveStatus')) {
200 return (RT->Config->Get('ActiveStatus'))
202 $RT::Logger->warning("RT::ActiveStatus undefined, falling back to deprecated defaults");
203 return (@DEFAULT_ACTIVE_STATUS);
209 # {{{ InactiveStatusArray
211 =head2 InactiveStatusArray
213 Returns an array of all InactiveStatuses for this queue
217 sub InactiveStatusArray {
219 if (RT->Config->Get('InactiveStatus')) {
220 return (RT->Config->Get('InactiveStatus'))
222 $RT::Logger->warning("RT::InactiveStatus undefined, falling back to deprecated defaults");
223 return (@DEFAULT_INACTIVE_STATUS);
233 Returns an array of all statuses for this queue
239 return ($self->ActiveStatusArray(), $self->InactiveStatusArray());
246 =head2 IsValidStatus VALUE
248 Returns true if VALUE is a valid status. Otherwise, returns 0.
257 my $retval = grep ( $_ eq $value, $self->StatusArray );
266 =head2 IsActiveStatus VALUE
268 Returns true if VALUE is a Active status. Otherwise, returns 0
277 my $retval = grep ( $_ eq $value, $self->ActiveStatusArray );
284 # {{{ IsInactiveStatus
286 =head2 IsInactiveStatus VALUE
288 Returns true if VALUE is a Inactive status. Otherwise, returns 0
293 sub IsInactiveStatus {
297 my $retval = grep ( $_ eq $value, $self->InactiveStatusArray );
312 Arguments: ARGS is a hash of named parameters. Valid parameters are:
322 If you pass the ACL check, it creates the queue and returns its queue id.
331 CorrespondAddress => '',
333 CommentAddress => '',
335 InitialPriority => 0,
341 _RecordTransaction => 1,
345 unless ( $self->CurrentUser->HasRight(Right => 'AdminQueue', Object => $RT::System) )
347 return ( 0, $self->loc("No permission to create queues") );
350 unless ( $self->ValidateName( $args{'Name'} ) ) {
351 return ( 0, $self->loc('Queue already exists') );
354 my %attrs = map {$_ => 1} $self->ReadableAttributes;
356 #TODO better input validation
357 $RT::Handle->BeginTransaction();
358 my $id = $self->SUPER::Create( map { $_ => $args{$_} } grep exists $args{$_}, keys %attrs );
360 $RT::Handle->Rollback();
361 return ( 0, $self->loc('Queue could not be created') );
364 my $create_ret = $self->_CreateQueueGroups();
365 unless ($create_ret) {
366 $RT::Handle->Rollback();
367 return ( 0, $self->loc('Queue could not be created') );
369 if ( $args{'_RecordTransaction'} ) {
370 $self->_NewTransaction( Type => "Create" );
374 for my $attr (qw/Sign SignAuto Encrypt/) {
375 next unless defined $args{$attr};
376 my $set = "Set" . $attr;
377 my ($status, $msg) = $self->$set( $args{$attr} );
378 $RT::Logger->error("Couldn't set attribute '$attr': $msg")
382 RT->System->QueueCacheNeedsUpdate(1);
384 return ( $id, $self->loc("Queue created") );
394 $self->loc('Deleting this object would break referential integrity') );
399 # {{{ sub SetDisabled
404 1 will cause this queue to no longer be available for tickets.
405 0 will re-enable this queue.
413 $RT::Handle->BeginTransaction();
414 my $set_err = $self->SUPER::SetDisabled($val);
416 $RT::Handle->Rollback();
417 $RT::Logger->warning("Couldn't ".($val == 1) ? "disable" : "enable"." queue ".$self->PrincipalObj->Id);
420 $self->_NewTransaction( Type => ($val == 1) ? "Disabled" : "Enabled" );
422 $RT::Handle->Commit();
424 RT->System->QueueCacheNeedsUpdate(1);
427 return (1, $self->loc("Queue disabled"));
429 return (1, $self->loc("Queue enabled"));
440 Takes either a numerical id or a textual Name and loads the specified queue.
447 my $identifier = shift;
448 if ( !$identifier ) {
452 if ( $identifier =~ /^(\d+)$/ ) {
453 $self->SUPER::LoadById($identifier);
456 $self->LoadByCols( Name => $identifier );
459 return ( $self->Id );
465 # {{{ sub ValidateName
467 =head2 ValidateName NAME
469 Takes a queue name. Returns true if it's an ok name for
470 a new queue. Returns undef if there's already a queue by that name.
478 my $tempqueue = new RT::Queue($RT::SystemUser);
479 $tempqueue->Load($name);
481 #If this queue exists, return undef
482 if ( $tempqueue->Name() && $tempqueue->id != $self->id) {
486 #If the queue doesn't exist, return 1
488 return ($self->SUPER::ValidateName($name));
503 return undef unless $self->CurrentUserHasRight('SeeQueue');
504 my $attr = $self->FirstAttribute('Sign') or return 0;
505 return $attr->Content;
512 return ( 0, $self->loc('Permission Denied') )
513 unless $self->CurrentUserHasRight('AdminQueue');
515 my ($status, $msg) = $self->SetAttribute(
517 Description => 'Sign outgoing messages by default',
520 return ($status, $msg) unless $status;
521 return ($status, $self->loc('Signing enabled')) if $value;
522 return ($status, $self->loc('Signing disabled'));
529 return undef unless $self->CurrentUserHasRight('SeeQueue');
530 my $attr = $self->FirstAttribute('SignAuto') or return 0;
531 return $attr->Content;
538 return ( 0, $self->loc('Permission Denied') )
539 unless $self->CurrentUserHasRight('AdminQueue');
541 my ($status, $msg) = $self->SetAttribute(
543 Description => 'Sign auto-generated outgoing messages',
546 return ($status, $msg) unless $status;
547 return ($status, $self->loc('Signing enabled')) if $value;
548 return ($status, $self->loc('Signing disabled'));
555 return undef unless $self->CurrentUserHasRight('SeeQueue');
556 my $attr = $self->FirstAttribute('Encrypt') or return 0;
557 return $attr->Content;
564 return ( 0, $self->loc('Permission Denied') )
565 unless $self->CurrentUserHasRight('AdminQueue');
567 my ($status, $msg) = $self->SetAttribute(
569 Description => 'Encrypt outgoing messages by default',
572 return ($status, $msg) unless $status;
573 return ($status, $self->loc('Encrypting enabled')) if $value;
574 return ($status, $self->loc('Encrypting disabled'));
579 return RT->System->SubjectTag( $self );
586 return ( 0, $self->loc('Permission Denied') )
587 unless $self->CurrentUserHasRight('AdminQueue');
589 my $attr = RT->System->FirstAttribute('BrandedSubjectTag');
590 my $map = $attr ? $attr->Content : {};
591 if ( defined $value && length $value ) {
592 $map->{ $self->id } = $value;
594 delete $map->{ $self->id };
597 my ($status, $msg) = RT->System->SetAttribute(
598 Name => 'BrandedSubjectTag',
599 Description => 'Queue id => subject tag map',
602 return ($status, $msg) unless $status;
603 return ($status, $self->loc(
604 "SubjectTag changed to [_1]",
605 (defined $value && length $value)? $value : $self->loc("(no value)")
613 Returns an RT::Templates object of all of this queue's templates.
620 my $templates = RT::Templates->new( $self->CurrentUser );
622 if ( $self->CurrentUserHasRight('ShowTemplate') ) {
623 $templates->LimitToQueue( $self->id );
631 # {{{ Dealing with custom fields
635 =head2 CustomField NAME
637 Load the queue-specific custom field named NAME
644 my $cf = RT::CustomField->new($self->CurrentUser);
645 $cf->LoadByNameAndQueue(Name => $name, Queue => $self->Id);
650 # {{{ TicketCustomFields
652 =head2 TicketCustomFields
654 Returns an L<RT::CustomFields> object containing all global and
655 queue-specific B<ticket> custom fields.
659 sub TicketCustomFields {
662 my $cfs = RT::CustomFields->new( $self->CurrentUser );
663 if ( $self->CurrentUserHasRight('SeeQueue') ) {
664 $cfs->SetContextObject( $self );
665 $cfs->LimitToGlobalOrObjectId( $self->Id );
666 $cfs->LimitToLookupType( 'RT::Queue-RT::Ticket' );
667 $cfs->ApplySortOrder;
674 # {{{ TicketTransactionCustomFields
676 =head2 TicketTransactionCustomFields
678 Returns an L<RT::CustomFields> object containing all global and
679 queue-specific B<transaction> custom fields.
683 sub TicketTransactionCustomFields {
686 my $cfs = RT::CustomFields->new( $self->CurrentUser );
687 if ( $self->CurrentUserHasRight('SeeQueue') ) {
688 $cfs->SetContextObject( $self );
689 $cfs->LimitToGlobalOrObjectId( $self->Id );
690 $cfs->LimitToLookupType( 'RT::Queue-RT::Ticket-RT::Transaction' );
691 $cfs->ApplySortOrder;
701 # {{{ Routines dealing with watchers.
703 # {{{ _CreateQueueGroups
705 =head2 _CreateQueueGroups
707 Create the ticket groups and links for this ticket.
708 This routine expects to be called from Ticket->Create _inside of a transaction_
710 It will create four groups for this ticket: Requestor, Cc, AdminCc and Owner.
712 It will return true on success and undef on failure.
718 sub _CreateQueueGroups {
721 my @types = qw(Cc AdminCc Requestor Owner);
723 foreach my $type (@types) {
724 my $type_obj = RT::Group->new($self->CurrentUser);
725 my ($id, $msg) = $type_obj->CreateRoleGroup(Instance => $self->Id,
727 Domain => 'RT::Queue-Role');
729 $RT::Logger->error("Couldn't create a Queue group of type '$type' for ticket ".
730 $self->Id.": ".$msg);
745 AddWatcher takes a parameter hash. The keys are as follows:
747 Type One of Requestor, Cc, AdminCc
749 PrinicpalId The RT::Principal id of the user or group that's being added as a watcher
750 Email The email address of the new watcher. If a user with this
751 email address can't be found, a new nonprivileged user will be created.
753 If the watcher you\'re trying to set has an RT account, set the Owner parameter to their User Id. Otherwise, set the Email parameter to their Email address.
755 Returns a tuple of (status/id, message).
763 PrincipalId => undef,
768 return ( 0, "No principal specified" )
769 unless $args{'Email'} or $args{'PrincipalId'};
771 if ( !$args{'PrincipalId'} && $args{'Email'} ) {
772 my $user = RT::User->new( $self->CurrentUser );
773 $user->LoadByEmail( $args{'Email'} );
774 $args{'PrincipalId'} = $user->PrincipalId if $user->id;
778 return ( $self->_AddWatcher(%args) )
779 if $self->CurrentUserHasRight('ModifyQueueWatchers');
781 #If the watcher we're trying to add is for the current user
782 if ( defined $args{'PrincipalId'} && $self->CurrentUser->PrincipalId eq $args{'PrincipalId'}) {
783 # If it's an AdminCc and they don't have
784 # 'WatchAsAdminCc' or 'ModifyTicket', bail
785 if ( defined $args{'Type'} && ($args{'Type'} eq 'AdminCc') ) {
786 return ( $self->_AddWatcher(%args) )
787 if $self->CurrentUserHasRight('WatchAsAdminCc');
790 # If it's a Requestor or Cc and they don't have
791 # 'Watch' or 'ModifyTicket', bail
792 elsif ( $args{'Type'} eq 'Cc' or $args{'Type'} eq 'Requestor' ) {
793 return ( $self->_AddWatcher(%args) )
794 if $self->CurrentUserHasRight('Watch');
797 $RT::Logger->warning( "$self -> AddWatcher got passed a bogus type");
798 return ( 0, $self->loc('Error in parameters to Queue->AddWatcher') );
802 return ( 0, $self->loc("Permission Denied") );
805 #This contains the meat of AddWatcher. but can be called from a routine like
806 # Create, which doesn't need the additional acl check
812 PrincipalId => undef,
818 my $principal = RT::Principal->new( $self->CurrentUser );
819 if ( $args{'PrincipalId'} ) {
820 $principal->Load( $args{'PrincipalId'} );
821 if ( $principal->id and $principal->IsUser and my $email = $principal->Object->EmailAddress ) {
822 return (0, $self->loc("[_1] is an address RT receives mail at. Adding it as a '[_2]' would create a mail loop", $email, $self->loc($args{'Type'})))
823 if RT::EmailParser->IsRTAddress( $email );
826 elsif ( $args{'Email'} ) {
827 if ( RT::EmailParser->IsRTAddress( $args{'Email'} ) ) {
828 return (0, $self->loc("[_1] is an address RT receives mail at. Adding it as a '[_2]' would create a mail loop", $args{'Email'}, $self->loc($args{'Type'})));
830 my $user = RT::User->new($self->CurrentUser);
831 $user->LoadByEmail( $args{'Email'} );
832 $user->Load( $args{'Email'} )
835 if ( $user->Id ) { # If the user exists
836 $principal->Load( $user->PrincipalId );
838 # if the user doesn't exist, we need to create a new user
839 my $new_user = RT::User->new($RT::SystemUser);
841 my ( $Address, $Name ) =
842 RT::Interface::Email::ParseAddressFromHeader($args{'Email'});
844 my ( $Val, $Message ) = $new_user->Create(
846 EmailAddress => $Address,
849 Comments => 'Autocreated when added as a watcher'
852 $RT::Logger->error("Failed to create user ".$args{'Email'} .": " .$Message);
853 # Deal with the race condition of two account creations at once
854 $new_user->LoadByEmail( $args{'Email'} );
856 $principal->Load( $new_user->PrincipalId );
859 # If we can't find this watcher, we need to bail.
860 unless ( $principal->Id ) {
861 return(0, $self->loc("Could not find or create that user"));
864 my $group = RT::Group->new($self->CurrentUser);
865 $group->LoadQueueRoleGroup(Type => $args{'Type'}, Queue => $self->Id);
866 unless ($group->id) {
867 return(0,$self->loc("Group not found"));
870 if ( $group->HasMember( $principal)) {
872 return ( 0, $self->loc('That principal is already a [_1] for this queue', $args{'Type'}) );
876 my ($m_id, $m_msg) = $group->_AddMember(PrincipalId => $principal->Id);
878 $RT::Logger->error("Failed to add ".$principal->Id." as a member of group ".$group->Id.": ".$m_msg);
880 return ( 0, $self->loc('Could not make that principal a [_1] for this queue', $args{'Type'}) );
882 return ( 1, $self->loc('Added principal as a [_1] for this queue', $args{'Type'}) );
887 # {{{ sub DeleteWatcher
889 =head2 DeleteWatcher { Type => TYPE, PrincipalId => PRINCIPAL_ID, Email => EMAIL_ADDRESS }
892 Deletes a queue watcher. Takes two arguments:
894 Type (one of Requestor,Cc,AdminCc)
898 PrincipalId (an RT::Principal Id of the watcher you want to remove)
900 Email (the email address of an existing wathcer)
909 my %args = ( Type => undef,
910 PrincipalId => undef,
914 unless ( $args{'PrincipalId'} || $args{'Email'} ) {
915 return ( 0, $self->loc("No principal specified") );
918 if ( !$args{PrincipalId} and $args{Email} ) {
919 my $user = RT::User->new( $self->CurrentUser );
920 my ($rv, $msg) = $user->LoadByEmail( $args{Email} );
921 $args{PrincipalId} = $user->PrincipalId if $rv;
924 my $principal = RT::Principal->new( $self->CurrentUser );
925 if ( $args{'PrincipalId'} ) {
926 $principal->Load( $args{'PrincipalId'} );
929 my $user = RT::User->new( $self->CurrentUser );
930 $user->LoadByEmail( $args{'Email'} );
931 $principal->Load( $user->Id );
934 # If we can't find this watcher, we need to bail.
935 unless ( $principal->Id ) {
936 return ( 0, $self->loc("Could not find that principal") );
939 my $group = RT::Group->new($self->CurrentUser);
940 $group->LoadQueueRoleGroup(Type => $args{'Type'}, Queue => $self->Id);
941 unless ($group->id) {
942 return(0,$self->loc("Group not found"));
945 my $can_modify_queue = $self->CurrentUserHasRight('ModifyQueueWatchers');
948 #If the watcher we're trying to add is for the current user
949 if ( defined $args{'PrincipalId'} and $self->CurrentUser->PrincipalId eq $args{'PrincipalId'}) {
950 # If it's an AdminCc and they don't have
951 # 'WatchAsAdminCc' or 'ModifyQueue', bail
952 if ( $args{'Type'} eq 'AdminCc' ) {
953 unless ( $can_modify_queue
954 or $self->CurrentUserHasRight('WatchAsAdminCc') ) {
955 return ( 0, $self->loc('Permission Denied'))
959 # If it's a Requestor or Cc and they don't have
960 # 'Watch' or 'ModifyQueue', bail
961 elsif ( ( $args{'Type'} eq 'Cc' ) or ( $args{'Type'} eq 'Requestor' ) ) {
962 unless ( $can_modify_queue
963 or $self->CurrentUserHasRight('Watch') ) {
964 return ( 0, $self->loc('Permission Denied'))
968 $RT::Logger->warning( "$self -> DeleteWatcher got passed a bogus type");
969 return ( 0, $self->loc('Error in parameters to Queue->DeleteWatcher') );
973 # If the watcher isn't the current user
974 # and the current user doesn't have 'ModifyQueueWathcers' bail
976 unless ( $can_modify_queue ) {
977 return ( 0, $self->loc("Permission Denied") );
984 # see if this user is already a watcher.
986 unless ( $group->HasMember($principal)) {
988 $self->loc('That principal is not a [_1] for this queue', $args{'Type'}) );
991 my ($m_id, $m_msg) = $group->_DeleteMember($principal->Id);
993 $RT::Logger->error("Failed to delete ".$principal->Id.
994 " as a member of group ".$group->Id.": ".$m_msg);
996 return ( 0, $self->loc('Could not remove that principal as a [_1] for this queue', $args{'Type'}) );
999 return ( 1, $self->loc("[_1] is no longer a [_2] for this queue.", $principal->Object->Name, $args{'Type'} ));
1004 # {{{ AdminCcAddresses
1006 =head2 AdminCcAddresses
1008 returns String: All queue AdminCc email addresses as a string
1012 sub AdminCcAddresses {
1015 unless ( $self->CurrentUserHasRight('SeeQueue') ) {
1019 return ( $self->AdminCc->MemberEmailAddressesAsString )
1029 returns String: All queue Ccs as a string of email addresses
1036 unless ( $self->CurrentUserHasRight('SeeQueue') ) {
1040 return ( $self->Cc->MemberEmailAddressesAsString);
1051 Returns an RT::Group object which contains this Queue's Ccs.
1052 If the user doesn't have "ShowQueue" permission, returns an empty group
1059 my $group = RT::Group->new($self->CurrentUser);
1060 if ( $self->CurrentUserHasRight('SeeQueue') ) {
1061 $group->LoadQueueRoleGroup(Type => 'Cc', Queue => $self->Id);
1074 Returns an RT::Group object which contains this Queue's AdminCcs.
1075 If the user doesn't have "ShowQueue" permission, returns an empty group
1082 my $group = RT::Group->new($self->CurrentUser);
1083 if ( $self->CurrentUserHasRight('SeeQueue') ) {
1084 $group->LoadQueueRoleGroup(Type => 'AdminCc', Queue => $self->Id);
1092 # {{{ IsWatcher, IsCc, IsAdminCc
1095 # a generic routine to be called by IsRequestor, IsCc and IsAdminCc
1097 =head2 IsWatcher { Type => TYPE, PrincipalId => PRINCIPAL_ID }
1099 Takes a param hash with the attributes Type and PrincipalId
1101 Type is one of Requestor, Cc, AdminCc and Owner
1103 PrincipalId is an RT::Principal id
1105 Returns true if that principal is a member of the group Type for this queue
1113 my %args = ( Type => 'Cc',
1114 PrincipalId => undef,
1118 # Load the relevant group.
1119 my $group = RT::Group->new($self->CurrentUser);
1120 $group->LoadQueueRoleGroup(Type => $args{'Type'}, Queue => $self->id);
1121 # Ask if it has the member in question
1123 my $principal = RT::Principal->new($self->CurrentUser);
1124 $principal->Load($args{'PrincipalId'});
1125 unless ($principal->Id) {
1129 return ($group->HasMemberRecursively($principal));
1137 =head2 IsCc PRINCIPAL_ID
1139 Takes an RT::Principal id.
1140 Returns true if the principal is a requestor of the current queue.
1149 return ( $self->IsWatcher( Type => 'Cc', PrincipalId => $cc ) );
1157 =head2 IsAdminCc PRINCIPAL_ID
1159 Takes an RT::Principal id.
1160 Returns true if the principal is a requestor of the current queue.
1168 return ( $self->IsWatcher( Type => 'AdminCc', PrincipalId => $person ) );
1183 # {{{ ACCESS CONTROL
1189 unless ( $self->CurrentUserHasRight('AdminQueue') ) {
1190 return ( 0, $self->loc('Permission Denied') );
1192 return ( $self->SUPER::_Set(@_) );
1202 unless ( $self->CurrentUserHasRight('SeeQueue') ) {
1206 return ( $self->__Value(@_) );
1211 # {{{ sub CurrentUserHasRight
1213 =head2 CurrentUserHasRight
1215 Takes one argument. A textual string with the name of the right we want to check.
1216 Returns true if the current user has that right for this queue.
1217 Returns undef otherwise.
1221 sub CurrentUserHasRight {
1227 Principal => $self->CurrentUser,
1236 =head2 CurrentUserCanSee
1238 Returns true if the current user can see the queue, using SeeQueue
1242 sub CurrentUserCanSee {
1245 return $self->CurrentUserHasRight('SeeQueue');
1252 Takes a param hash with the fields 'Right' and 'Principal'.
1253 Principal defaults to the current user.
1254 Returns true if the principal has that right for this queue.
1255 Returns undef otherwise.
1259 # TAKES: Right and optional "Principal" which defaults to the current user
1264 Principal => $self->CurrentUser,
1267 my $principal = delete $args{'Principal'};
1268 unless ( $principal ) {
1269 $RT::Logger->error("Principal undefined in Queue::HasRight");
1273 return $principal->HasRight(
1275 Object => ($self->Id ? $self : $RT::System),