+sub LimitToRolesForSystem {
+ my $self = shift;
+ RT->Deprecated(
+ Instead => "LimitToRolesForObject",
+ Remove => "4.4",
+ );
+ $self->Limit(FIELD => 'Domain', OPERATOR => '=', VALUE => 'RT::System-Role', CASESENSITIVE => 0 );
+ $self->Limit(FIELD => 'Instance', OPERATOR => '=', VALUE => RT::System->Id );
+}
+
+
+=head2 WithMember {PrincipalId => PRINCIPAL_ID, Recursively => undef}
+
+Limits the set of groups returned to groups which have
+Principal PRINCIPAL_ID as a member. Returns the alias used for the join.
+
+=cut
+
+sub WithMember {
+ my $self = shift;
+ my %args = ( PrincipalId => undef,
+ Recursively => undef,
+ @_);
+ my $members = $self->Join(
+ ALIAS1 => 'main', FIELD1 => 'id',
+ $args{'Recursively'}
+ ? (TABLE2 => 'CachedGroupMembers')
+ # (GroupId, MemberId) is unique in GM table
+ : (TABLE2 => 'GroupMembers', DISTINCT => 1)
+ ,
+ FIELD2 => 'GroupId',
+ );
+
+ $self->Limit(ALIAS => $members, FIELD => 'MemberId', OPERATOR => '=', VALUE => $args{'PrincipalId'});
+ $self->Limit(ALIAS => $members, FIELD => 'Disabled', VALUE => 0)
+ if $args{'Recursively'};
+
+ return $members;
+}
+
+sub WithCurrentUser {
+ my $self = shift;
+ $self->{with_current_user} = 1;
+ return $self->WithMember(
+ PrincipalId => $self->CurrentUser->PrincipalId,
+ Recursively => 1,
+ );
+}
+
+sub WithoutMember {
+ my $self = shift;
+ my %args = (
+ PrincipalId => undef,
+ Recursively => undef,
+ @_
+ );
+
+ my $members = $args{'Recursively'} ? 'CachedGroupMembers' : 'GroupMembers';
+ my $members_alias = $self->Join(
+ TYPE => 'LEFT',
+ FIELD1 => 'id',
+ TABLE2 => $members,
+ FIELD2 => 'GroupId',
+ DISTINCT => $members eq 'GroupMembers',
+ );
+ $self->Limit(
+ LEFTJOIN => $members_alias,
+ ALIAS => $members_alias,
+ FIELD => 'MemberId',
+ OPERATOR => '=',
+ VALUE => $args{'PrincipalId'},
+ );
+ $self->Limit(
+ LEFTJOIN => $members_alias,
+ ALIAS => $members_alias,
+ FIELD => 'Disabled',
+ VALUE => 0
+ ) if $args{'Recursively'};
+ $self->Limit(
+ ALIAS => $members_alias,
+ FIELD => 'MemberId',
+ OPERATOR => 'IS',
+ VALUE => 'NULL',
+ QUOTEVALUE => 0,
+ );
+}
+
+=head2 WithRight { Right => RIGHTNAME, Object => RT::Record, IncludeSystemRights => 1, IncludeSuperusers => 0, EquivObjects => [ ] }
+
+
+Find all groups which have RIGHTNAME for RT::Record. Optionally include global rights and superusers. By default, include the global rights, but not the superusers.
+
+
+
+=cut
+
+#XXX: should be generilized
+sub WithRight {
+ my $self = shift;
+ my %args = ( Right => undef,
+ Object => => undef,
+ IncludeSystemRights => 1,
+ IncludeSuperusers => undef,
+ IncludeSubgroupMembers => 0,
+ EquivObjects => [ ],
+ @_ );
+
+ my $from_role = $self->Clone;
+ $from_role->WithRoleRight( %args );
+
+ my $from_group = $self->Clone;
+ $from_group->WithGroupRight( %args );
+
+ #XXX: DIRTY HACK
+ use DBIx::SearchBuilder 1.50; #no version on ::Union :(
+ use DBIx::SearchBuilder::Union;
+ my $union = DBIx::SearchBuilder::Union->new();
+ $union->add($from_role);
+ $union->add($from_group);
+ %$self = %$union;
+ bless $self, ref($union);
+
+ return;
+}
+
+#XXX: methods are active aliases to Users class to prevent code duplication
+# should be generalized
+sub _JoinGroups {
+ my $self = shift;
+ my %args = (@_);
+ return 'main' unless $args{'IncludeSubgroupMembers'};
+ return $self->RT::Users::_JoinGroups( %args );
+}
+sub _JoinGroupMembers {
+ my $self = shift;
+ my %args = (@_);
+ return 'main' unless $args{'IncludeSubgroupMembers'};
+ return $self->RT::Users::_JoinGroupMembers( %args );
+}
+sub _JoinGroupMembersForGroupRights {
+ my $self = shift;
+ my %args = (@_);
+ my $group_members = $self->_JoinGroupMembers( %args );
+ unless( $group_members eq 'main' ) {
+ return $self->RT::Users::_JoinGroupMembersForGroupRights( %args );
+ }
+ $self->Limit( ALIAS => $args{'ACLAlias'},
+ FIELD => 'PrincipalId',
+ VALUE => "main.id",
+ QUOTEVALUE => 0,
+ );
+}
+sub _JoinACL { return (shift)->RT::Users::_JoinACL( @_ ) }
+sub _RoleClauses { return (shift)->RT::Users::_RoleClauses( @_ ) }
+sub _WhoHaveRoleRightSplitted { return (shift)->RT::Users::_WhoHaveRoleRightSplitted( @_ ) }
+sub _GetEquivObjects { return (shift)->RT::Users::_GetEquivObjects( @_ ) }
+sub WithGroupRight { return (shift)->RT::Users::WhoHaveGroupRight( @_ ) }
+sub WithRoleRight { return (shift)->RT::Users::WhoHaveRoleRight( @_ ) }
+
+sub ForWhichCurrentUserHasRight {
+ my $self = shift;
+ my %args = (
+ Right => undef,
+ IncludeSuperusers => undef,
+ @_,
+ );
+
+ # Non-disabled groups...
+ $self->LimitToEnabled;
+
+ # ...which are the target object of an ACL with that right, or
+ # where the target is the system object (a global right)
+ my $acl = $self->_JoinACL( %args );
+ $self->_AddSubClause(
+ ACLObjects => "( (main.id = $acl.ObjectId AND $acl.ObjectType = 'RT::Group')"
+ . " OR $acl.ObjectType = 'RT::System')");
+
+ # ...and where that right is granted to any group..
+ my $member = $self->Join(
+ ALIAS1 => $acl,
+ FIELD1 => 'PrincipalId',
+ TABLE2 => 'CachedGroupMembers',
+ FIELD2 => 'GroupId',
+ );
+ $self->Limit(
+ ALIAS => $member,
+ FIELD => 'Disabled',
+ VALUE => '0',
+ );
+
+ # ...with the current user in it
+ $self->Limit(
+ ALIAS => $member,
+ FIELD => 'MemberId',
+ VALUE => $self->CurrentUser->Id,
+ );
+
+ return;
+}
+
+=head2 LimitToEnabled
+
+Only find items that haven't been disabled
+
+=cut
+
+sub LimitToEnabled {
+ my $self = shift;
+
+ $self->{'handled_disabled_column'} = 1;
+ $self->Limit(
+ ALIAS => $self->PrincipalsAlias,
+ FIELD => 'Disabled',
+ VALUE => '0',
+ );
+}
+
+
+=head2 LimitToDeleted
+
+Only find items that have been deleted.
+
+=cut
+
+sub LimitToDeleted {
+ my $self = shift;
+
+ $self->{'handled_disabled_column'} = $self->{'find_disabled_rows'} = 1;
+ $self->Limit(
+ ALIAS => $self->PrincipalsAlias,
+ FIELD => 'Disabled',
+ VALUE => 1,
+ );
+}
+
+
+
+sub AddRecord {
+ my $self = shift;
+ my ($record) = @_;
+
+ # If we've explicitly limited to groups the user is a member of (for
+ # dashboard or savedsearch privacy objects), skip the ACL.
+ return unless $self->{with_current_user}
+ or $record->CurrentUserHasRight('SeeGroup');
+
+ return $self->SUPER::AddRecord( $record );
+}
+
+
+
+sub _DoSearch {
+ my $self = shift;
+
+ #unless we really want to find disabled rows, make sure we're only finding enabled ones.
+ unless($self->{'find_disabled_rows'}) {
+ $self->LimitToEnabled();
+ }
+
+ return($self->SUPER::_DoSearch(@_));
+
+}
+
+RT::Base->_ImportOverlays();