+#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(@_));
+
+}
+
+
+
+=head2 NewItem
+
+Returns an empty new RT::Group item
+
+=cut
+
+sub NewItem {
+ my $self = shift;
+ return(RT::Group->new($self->CurrentUser));
+}
+RT::Base->_ImportOverlays();