limit ticket creation queue dropdowns based on ACL, RT#7778
[freeside.git] / rt / lib / RT / Users_Overlay.pm
index 7b14229..ea12dbe 100644 (file)
@@ -1,8 +1,8 @@
 # BEGIN BPS TAGGED BLOCK {{{
 # 
 # COPYRIGHT:
 # BEGIN BPS TAGGED BLOCK {{{
 # 
 # COPYRIGHT:
-#  
-# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC 
+# 
+# This software is Copyright (c) 1996-2009 Best Practical Solutions, LLC
 #                                          <jesse@bestpractical.com>
 # 
 # (Except where explicitly superseded by other copyright notices)
 #                                          <jesse@bestpractical.com>
 # 
 # (Except where explicitly superseded by other copyright notices)
@@ -24,7 +24,7 @@
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 # 02110-1301 or visit their web page on the internet at
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 # 02110-1301 or visit their web page on the internet at
-# http://www.gnu.org/copyleft/gpl.html.
+# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
 # 
 # 
 # CONTRIBUTION SUBMISSION POLICY:
 # 
 # 
 # CONTRIBUTION SUBMISSION POLICY:
@@ -45,6 +45,7 @@
 # those contributions and any derivatives thereof.
 # 
 # END BPS TAGGED BLOCK }}}
 # those contributions and any derivatives thereof.
 # 
 # END BPS TAGGED BLOCK }}}
+
 =head1 NAME
 
   RT::Users - Collection of RT::User objects
 =head1 NAME
 
   RT::Users - Collection of RT::User objects
 
 =head1 METHODS
 
 
 =head1 METHODS
 
-=begin testing
-
-ok(require RT::Users);
-
-=end testing
 
 =cut
 
 
 =cut
 
@@ -77,11 +73,10 @@ no warnings qw(redefine);
 sub _Init {
     my $self = shift;
     $self->{'table'} = 'Users';
 sub _Init {
     my $self = shift;
     $self->{'table'} = 'Users';
-        $self->{'primary_key'} = 'id';
-
-
+    $self->{'primary_key'} = 'id';
+    $self->{'with_disabled_column'} = 1;
 
 
-    my @result =          $self->SUPER::_Init(@_);
+    my @result = $self->SUPER::_Init(@_);
     # By default, order by name
     $self->OrderBy( ALIAS => 'main',
                     FIELD => 'Name',
     # By default, order by name
     $self->OrderBy( ALIAS => 'main',
                     FIELD => 'Name',
@@ -118,46 +113,41 @@ sub PrincipalsAlias {
 }
 
 
 }
 
 
-# {{{ sub _DoSearch 
-
-=head2 _DoSearch
+=head2 LimitToEnabled
 
 
-  A subclass of DBIx::SearchBuilder::_DoSearch that makes sure that _Disabled rows never get seen unless
-we're explicitly trying to see them.
+Only find items that haven\'t been disabled
 
 =cut
 
 
 =cut
 
-sub _DoSearch {
+# XXX: should be generalized
+sub LimitToEnabled {
     my $self = shift;
 
     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(@_) );
-
+    $self->{'handled_disabled_column'} = 1;
+    $self->Limit(
+        ALIAS    => $self->PrincipalsAlias,
+        FIELD    => 'Disabled',
+        VALUE    => '0',
+    );
 }
 
 }
 
-# }}}
-# {{{ sub LimitToEnabled
+=head2 LimitToDeleted
 
 
-=head2 LimitToEnabled
-
-Only find items that haven\'t been disabled
+Only find items that have been deleted.
 
 =cut
 
 
 =cut
 
-# XXX: should be generalized
-sub LimitToEnabled {
+sub LimitToDeleted {
     my $self = shift;
     my $self = shift;
-
-    $self->Limit( ALIAS    => $self->PrincipalsAlias,
-                  FIELD    => 'Disabled',
-                  VALUE    => '0',
-                  OPERATOR => '=' );
+    
+    $self->{'handled_disabled_column'} = $self->{'find_disabled_rows'} = 1;
+    $self->Limit(
+        ALIAS => $self->PrincipalsAlias,
+        FIELD => 'Disabled',
+        VALUE => 1,
+    );
 }
 
 }
 
-# }}}
 
 # {{{ LimitToEmail
 
 
 # {{{ LimitToEmail
 
@@ -232,68 +222,6 @@ sub LimitToPrivileged {
 
 =head2 WhoHaveRight { Right => 'name', Object => $rt_object , IncludeSuperusers => undef, IncludeSubgroupMembers => undef, IncludeSystemRights => undef, EquivObjects => [ ] }
 
 
 =head2 WhoHaveRight { Right => 'name', Object => $rt_object , IncludeSuperusers => undef, IncludeSubgroupMembers => undef, IncludeSystemRights => undef, EquivObjects => [ ] }
 
-=begin testing
-
-ok(my $users = RT::Users->new($RT::SystemUser));
-$users->WhoHaveRight(Object =>$RT::System, Right =>'SuperUser');
-ok($users->Count == 1, "There is one privileged superuser - Found ". $users->Count );
-# TODO: this wants more testing
-
-my $RTxUser = RT::User->new($RT::SystemUser);
-($id, $msg) = $RTxUser->Create( Name => 'RTxUser', Comments => "RTx extension user", Privileged => 1);
-ok ($id,$msg);
-
-my $group = RT::Group->new($RT::SystemUser);
-$group->LoadACLEquivalenceGroup($RTxUser->PrincipalObj);
-
-my $RTxSysObj = {};
-bless $RTxSysObj, 'RTx::System';
-*RTx::System::Id = sub { 1; };
-*RTx::System::id = *RTx::System::Id;
-my $ace = RT::Record->new($RT::SystemUser);
-$ace->Table('ACL');
-$ace->_BuildTableAttributes unless ($_TABLE_ATTR->{ref($self)});
-($id, $msg) = $ace->Create( PrincipalId => $group->id, PrincipalType => 'Group', RightName => 'RTxUserRight', ObjectType => 'RTx::System', ObjectId  => 1 );
-ok ($id, "ACL for RTxSysObj created");
-
-my $RTxObj = {};
-bless $RTxObj, 'RTx::System::Record';
-*RTx::System::Record::Id = sub { 4; };
-*RTx::System::Record::id = *RTx::System::Record::Id;
-
-$users = RT::Users->new($RT::SystemUser);
-$users->WhoHaveRight(Right => 'RTxUserRight', Object => $RTxSysObj);
-is($users->Count, 1, "RTxUserRight found for RTxSysObj");
-
-$users = RT::Users->new($RT::SystemUser);
-$users->WhoHaveRight(Right => 'RTxUserRight', Object => $RTxObj);
-is($users->Count, 0, "RTxUserRight not found for RTxObj");
-
-$users = RT::Users->new($RT::SystemUser);
-$users->WhoHaveRight(Right => 'RTxUserRight', Object => $RTxObj, EquivObjects => [ $RTxSysObj ]);
-is($users->Count, 1, "RTxUserRight found for RTxObj using EquivObjects");
-
-$ace = RT::Record->new($RT::SystemUser);
-$ace->Table('ACL');
-$ace->_BuildTableAttributes unless ($_TABLE_ATTR->{ref($self)});
-($id, $msg) = $ace->Create( PrincipalId => $group->id, PrincipalType => 'Group', RightName => 'RTxUserRight', ObjectType => 'RTx::System::Record', ObjectId => 5 );
-ok ($id, "ACL for RTxObj created");
-
-my $RTxObj2 = {};
-bless $RTxObj2, 'RTx::System::Record';
-*RTx::System::Record::Id = sub { 5; };
-*RTx::System::Record::id = sub { 5; };
-
-$users = RT::Users->new($RT::SystemUser);
-$users->WhoHaveRight(Right => 'RTxUserRight', Object => $RTxObj2);
-is($users->Count, 1, "RTxUserRight found for RTxObj2");
-
-$users = RT::Users->new($RT::SystemUser);
-$users->WhoHaveRight(Right => 'RTxUserRight', Object => $RTxObj2, EquivObjects => [ $RTxSysObj ]);
-is($users->Count, 1, "RTxUserRight found for RTxObj2");
-
-
-=end testing
 
 find all users who the right Right for this group, either individually
 or as members of groups
 
 find all users who the right Right for this group, either individually
 or as members of groups
@@ -363,6 +291,16 @@ sub _JoinACL
         @_,
     );
 
         @_,
     );
 
+    if ( $args{'Right'} ) {
+        my $canonic = RT::ACE->CanonicalizeRightName( $args{'Right'} );
+        unless ( $canonic ) {
+            $RT::Logger->error("Invalid right. Couldn't canonicalize right '$args{'Right'}'");
+        }
+        else {
+            $args{'Right'} = $canonic;
+        }
+    }
+
     my $acl = $self->NewAlias('ACL');
     $self->Limit(
         ALIAS    => $acl,
     my $acl = $self->NewAlias('ACL');
     $self->Limit(
         ALIAS    => $acl,
@@ -403,7 +341,7 @@ sub _GetEquivObjects
 
         # XXX: This should be abstracted into object itself
         if( $args{'Object'}->id ) {
 
         # XXX: This should be abstracted into object itself
         if( $args{'Object'}->id ) {
-            push @objects, $args{'Object'}->QueueObj;
+            push @objects, $args{'Object'}->ACLEquivalenceObjects;
         } else {
             push @objects, 'RT::Queue';
         }
         } else {
             push @objects, 'RT::Queue';
         }
@@ -434,16 +372,18 @@ sub WhoHaveRight {
         return (undef);
     }
 
         return (undef);
     }
 
-    my @from_role = $self->Clone->_WhoHaveRoleRightSplitted( %args );
+    my $from_role = $self->Clone;
+    $from_role->WhoHaveRoleRight( %args );
 
     my $from_group = $self->Clone;
     $from_group->WhoHaveGroupRight( %args );
 
     #XXX: DIRTY HACK
 
     my $from_group = $self->Clone;
     $from_group->WhoHaveGroupRight( %args );
 
     #XXX: DIRTY HACK
+    use DBIx::SearchBuilder 1.50; #no version on ::Union :(
     use DBIx::SearchBuilder::Union;
     my $union = new DBIx::SearchBuilder::Union;
     use DBIx::SearchBuilder::Union;
     my $union = new DBIx::SearchBuilder::Union;
-    $union->add( $_ ) foreach @from_role;
     $union->add( $from_group );
     $union->add( $from_group );
+    $union->add( $from_role );
     %$self = %$union;
     bless $self, ref($union);
 
     %$self = %$union;
     bless $self, ref($union);
 
@@ -465,57 +405,14 @@ sub WhoHaveRoleRight
         @_
     );
 
         @_
     );
 
-    my $groups = $self->_JoinGroups( %args );
-    my $acl = $self->_JoinACL( %args );
-
-    $self->Limit( ALIAS => $acl,
-                  FIELD => 'PrincipalType',
-                  VALUE => "$groups.Type",
-                  QUOTEVALUE => 0,
-                );
-
-    # no system user
-    $self->Limit( ALIAS => $self->PrincipalsAlias,
-                  FIELD => 'id',
-                  OPERATOR => '!=',
-                  VALUE => $RT::SystemUser->id
-                );
-
     my @objects = $self->_GetEquivObjects( %args );
     my @objects = $self->_GetEquivObjects( %args );
-    unless ( @objects ) {
-        unless ( $args{'IncludeSystemRights'} ) {
-            $self->_AddSubClause( WhichObjects => "($acl.ObjectType != 'RT::System')" );
-        }
+    my @roles = RT::Principal->RolesWithRight( %args );
+    unless ( @roles ) {
+        $self->_AddSubClause( "WhichRole", "(main.id = 0)" );
         return;
     }
 
         return;
     }
 
-    my ($groups_clauses, $acl_clauses) = $self->_RoleClauses( $groups, $acl, @objects );
-    $self->_AddSubClause( "WhichObject", "(". join( ' OR ', @$groups_clauses ) .")" );
-    $self->_AddSubClause( "WhichRole", "(". join( ' OR ', @$acl_clauses ) .")" );
-
-    return;
-}
-
-sub _WhoHaveRoleRightSplitted {
-    my $self = shift;
-    my %args = (
-        Right                  => undef,
-        Object                 => undef,
-        IncludeSystemRights    => undef,
-        IncludeSuperusers      => undef,
-        IncludeSubgroupMembers => 1,
-        EquivObjects           => [ ],
-        @_
-    );
-
     my $groups = $self->_JoinGroups( %args );
     my $groups = $self->_JoinGroups( %args );
-    my $acl = $self->_JoinACL( %args );
-
-    $self->Limit( ALIAS => $acl,
-                  FIELD => 'PrincipalType',
-                  VALUE => "$groups.Type",
-                  QUOTEVALUE => 0,
-                );
 
     # no system user
     $self->Limit( ALIAS => $self->PrincipalsAlias,
 
     # no system user
     $self->Limit( ALIAS => $self->PrincipalsAlias,
@@ -524,35 +421,21 @@ sub _WhoHaveRoleRightSplitted {
                   VALUE => $RT::SystemUser->id
                 );
 
                   VALUE => $RT::SystemUser->id
                 );
 
-    my @objects = $self->_GetEquivObjects( %args );
-    unless ( @objects ) {
-        unless ( $args{'IncludeSystemRights'} ) {
-            $self->_AddSubClause( WhichObjects => "($acl.ObjectType != 'RT::System')" );
-        }
-        return $self;
-    }
+    $self->_AddSubClause( "WhichRole", "(". join( ' OR ', map "$groups.Type = '$_'", @roles ) .")" );
 
 
-    my ($groups_clauses, $acl_clauses) = $self->_RoleClauses( $groups, $acl, @objects );
-    $self->_AddSubClause( "WhichRole", "(". join( ' OR ', @$acl_clauses ) .")" );
-    
-    my @res;
-    foreach ( @$groups_clauses ) {
-        my $tmp = $self->Clone;
-        $tmp->_AddSubClause( WhichObject => $_ );
-        push @res, $tmp;
-    }
+    my @groups_clauses = $self->_RoleClauses( $groups, @objects );
+    $self->_AddSubClause( "WhichObject", "(". join( ' OR ', @groups_clauses ) .")" )
+        if @groups_clauses;
 
 
-    return @res;
+    return;
 }
 
 sub _RoleClauses {
     my $self = shift;
     my $groups = shift;
 }
 
 sub _RoleClauses {
     my $self = shift;
     my $groups = shift;
-    my $acl = shift;
     my @objects = @_;
 
     my @groups_clauses;
     my @objects = @_;
 
     my @groups_clauses;
-    my @acl_clauses;
     foreach my $obj ( @objects ) {
         my $type = ref($obj)? ref($obj): $obj;
         my $id;
     foreach my $obj ( @objects ) {
         my $type = ref($obj)? ref($obj): $obj;
         my $id;
@@ -564,12 +447,8 @@ sub _RoleClauses {
         # field to integer and drop this quotes.
         $role_clause   .= " AND $groups.Instance = '$id'" if $id;
         push @groups_clauses, "($role_clause)";
         # field to integer and drop this quotes.
         $role_clause   .= " AND $groups.Instance = '$id'" if $id;
         push @groups_clauses, "($role_clause)";
-
-        my $object_clause = "$acl.ObjectType = '$type'";
-        $object_clause   .= " AND $acl.ObjectId = $id" if $id;
-        push @acl_clauses, "($object_clause)";
     }
     }
-    return (\@groups_clauses, \@acl_clauses);
+    return @groups_clauses;
 }
 
 # XXX: should be generalized
 }
 
 # XXX: should be generalized