[Rt-commit] rt branch, 3.9-acl_on_sql_for_queues, created. rt-3.9.7-798-g3674530
Ruslan Zakirov
ruz at bestpractical.com
Fri Dec 10 22:13:07 EST 2010
The branch, 3.9-acl_on_sql_for_queues has been created
at 367453004f46002b9f06dfe062bc7250c9472dbc (commit)
- Log -----------------------------------------------------------------
commit 4e737f72ce8deb22f33afbc877eea59075bf72b2
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date: Fri Dec 10 09:02:54 2010 +0300
JoinRoleGroups for collections method
diff --git a/lib/RT/SearchBuilder.pm b/lib/RT/SearchBuilder.pm
index cd8e3f7..3b3a821 100755
--- a/lib/RT/SearchBuilder.pm
+++ b/lib/RT/SearchBuilder.pm
@@ -298,6 +298,58 @@ sub ColumnMapClassName {
return $Class;
}
+sub JoinRoleGroups {
+ my $self = shift;
+ my %args = (
+ New => 0,
+ Left => 0,
+ Alias => 'main',
+ Field => 'id',
+ Class => undef,
+ Type => '',
+ @_
+ );
+ unless ( $args{'Class'} ) {
+ $args{'Class'} = ref $self;
+ $args{'Class'} =~ s/s$//;
+ }
+ unless ( $args{'New'} ) {
+ return $self->{'_sql_aliases'}{'role_groups'}{ join '-', @args{qw(Alias Field Class Type)} }
+ if $self->{'_sql_aliases'}{'role_groups'}{ join '-', @args{qw(Alias Field Class Type)} }
+ }
+
+ # we always have watcher groups, so we're safe to use INNER join,
+ # but we would love to see groups on demand, so make it possible
+ my $groups = $self->Join(
+ $args{'Left'}? (TYPE => 'LEFT') : (),
+ ALIAS1 => $args{'Alias'},
+ FIELD1 => $args{'Field'},
+ TABLE2 => 'Groups',
+ FIELD2 => 'Instance',
+ ENTRYAGGREGATOR => 'AND',
+ );
+ my $limit = 'Limit';
+ # special case for tickets :(
+ $limit = '_SQLLimit' if $self->isa('RT::Tickets');
+ $self->$limit(
+ LEFTJOIN => $groups,
+ ALIAS => $groups,
+ FIELD => 'Domain',
+ VALUE => $args{'Class'} .'-Role',
+ );
+ $self->$limit(
+ LEFTJOIN => $groups,
+ ALIAS => $groups,
+ FIELD => 'Type',
+ VALUE => $args{'Type'},
+ ) if $args{'Type'};
+
+ $self->{'_sql_aliases'}{'role_groups'}{ join '-', @args{qw(Alias Field Class Type)} } = $groups
+ unless $args{'New'};
+
+ return $groups;
+}
+
RT::Base->_ImportOverlays();
1;
commit 502c99cb56bcf88ce6052bc4cb90f833daeaeb4b
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date: Fri Dec 10 09:03:58 2010 +0300
_RolesWithRight and _ObjectsDirectlyHasRightOn private class methods in RT::ACL
diff --git a/lib/RT/ACL_Overlay.pm b/lib/RT/ACL_Overlay.pm
index c0b1bf4..329a4c7 100755
--- a/lib/RT/ACL_Overlay.pm
+++ b/lib/RT/ACL_Overlay.pm
@@ -310,4 +310,100 @@ sub HasEntry {
}
}
+sub _RolesWithRight {
+ my $self = shift;
+ my %args = (
+ Right => undef,
+ @_
+ );
+
+ my $right = $args{'Right'} or return ();
+
+ my $cache_key = 'RolesWithRight;:;'. $right;
+
+ if ( my $cached = $RT::Principal::_ACL_CACHE->fetch( $cache_key ) ) {
+ return %$cached;
+ }
+
+ my $ACL = RT::ACL->new( RT->SystemUser );
+ $ACL->Limit( FIELD => 'RightName', VALUE => $right );
+ $ACL->Limit( FIELD => 'PrincipalType', OPERATOR => '!=', VALUE => 'Group' );
+ my $principal_alias = $ACL->Join(
+ ALIAS1 => 'main',
+ FIELD1 => 'PrincipalId',
+ TABLE2 => 'Principals',
+ FIELD2 => 'id',
+ );
+ $ACL->Limit( ALIAS => $principal_alias, FIELD => 'Disabled', VALUE => 0 );
+
+ my $query = 'SELECT main.PrincipalType, main.ObjectType, main.ObjectId'
+ .' FROM '. $ACL->_BuildJoins .' '. $ACL->_WhereClause;
+
+ my %res = ();
+ foreach my $row ( @{ $RT::Handle->SimpleQuery($query)->fetchall_arrayref } ) {
+ my ($role, $type, $id) = @$row;
+ if ( $type eq 'RT::System' ) {
+ $res{ $role } = { 'RT::System' => 1 };
+ }
+ else {
+ next if $res{ $role }{'RT::System'};
+ push @{ $res{ $role }{ $type } ||= [] }, $id;
+ }
+ }
+ $RT::Principal::_ACL_CACHE->set( $cache_key => \%res );
+ return %res;
+}
+
+sub _ObjectsDirectlyHasRightOn {
+ my $self = shift;
+ my %args = (
+ Right => undef,
+ User => undef,
+ @_
+ );
+ my $right = $args{'Right'} or return ();
+ my $id = $args{'User'} || $self->CurrentUser->id;
+
+ my $cache_key = 'User-'. $id .';:;'. $right .';:;ObjectsDirectlyHasRightOn';
+ if ( my $cached = $RT::Principal::_ACL_CACHE->fetch( $cache_key ) ) {
+ return %$cached;
+ }
+
+ my $ACL = RT::ACL->new( RT->SystemUser );
+ $ACL->Limit( FIELD => 'RightName', VALUE => $right );
+ my $principal_alias = $ACL->Join(
+ ALIAS1 => 'main',
+ FIELD1 => 'PrincipalId',
+ TABLE2 => 'Principals',
+ FIELD2 => 'id',
+ );
+ $ACL->Limit( ALIAS => $principal_alias, FIELD => 'Disabled', VALUE => 0 );
+ my $cgm_alias = $ACL->Join(
+ ALIAS1 => 'main',
+ FIELD1 => 'PrincipalId',
+ TABLE2 => 'CachedGroupMembers',
+ FIELD2 => 'GroupId',
+ );
+ $ACL->Limit( ALIAS => $cgm_alias, FIELD => 'MemberId', VALUE => $id );
+ $ACL->Limit( ALIAS => $cgm_alias, FIELD => 'Disabled', VALUE => 0 );
+
+ my $query = 'SELECT main.ObjectType, main.ObjectId'
+ .' FROM '. $ACL->_BuildJoins .' '. $ACL->_WhereClause;
+
+ my %res = ();
+ foreach my $row ( @{ $RT::Handle->SimpleQuery($query)->fetchall_arrayref } ) {
+ my ($type, $id) = @$row;
+ if ( $type eq 'RT::System' ) {
+ # If user is direct member of a group that has the right
+ # on the system then he has this right on any object
+ %res = ('RT::System' => 1);
+ }
+ else {
+ push @{ $res{$type} ||= [] }, $id;
+ }
+ }
+ $RT::Principal::_ACL_CACHE->set( $cache_key => \%res );
+ return %res;
+}
+
1;
commit 315bad3a653bd3c206b89ef5fb18f540c5acb5e0
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date: Fri Dec 10 09:06:12 2010 +0300
make it possible to override subclause
diff --git a/lib/RT/Tickets_Overlay_SQL.pm b/lib/RT/Tickets_Overlay_SQL.pm
index 6fd2619..a61e1a2 100755
--- a/lib/RT/Tickets_Overlay_SQL.pm
+++ b/lib/RT/Tickets_Overlay_SQL.pm
@@ -86,11 +86,11 @@ sub _SQLLimit {
(!$args{'ALIAS'} || $args{'ALIAS'} eq 'main' ) ) {
$self->{'looking_at_type'} = 1;
}
+ $args{'SUBCLAUSE'} ||= 'ticketsql';
# All SQL stuff goes into one SB subclause so we can deal with all
# the aggregation
- $self->SUPER::Limit(%args,
- SUBCLAUSE => 'ticketsql');
+ $self->SUPER::Limit( %args );
}
sub _SQLJoin {
commit 7a1c051446fbf2b394c11d2b61dcdc0758c89f9c
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date: Fri Dec 10 09:08:32 2010 +0300
switch RT::Tickets over JoinRoleGroups
diff --git a/lib/RT/Tickets_Overlay.pm b/lib/RT/Tickets_Overlay.pm
index b3fc99e..c154832 100755
--- a/lib/RT/Tickets_Overlay.pm
+++ b/lib/RT/Tickets_Overlay.pm
@@ -245,7 +245,6 @@ sub CleanSlate {
_sql_cf_alias
_sql_group_members_aliases
_sql_object_cfv_alias
- _sql_role_group_aliases
_sql_trattachalias
_sql_u_watchers_alias_for_sort
_sql_u_watchers_aliases
@@ -1013,36 +1012,12 @@ sub _WatcherLimit {
sub _RoleGroupsJoin {
my $self = shift;
- my %args = (New => 0, Class => 'Ticket', Type => '', @_);
- return $self->{'_sql_role_group_aliases'}{ $args{'Class'} .'-'. $args{'Type'} }
- if $self->{'_sql_role_group_aliases'}{ $args{'Class'} .'-'. $args{'Type'} }
- && !$args{'New'};
-
- # we always have watcher groups for ticket, so we use INNER join
- my $groups = $self->Join(
- ALIAS1 => 'main',
- FIELD1 => $args{'Class'} eq 'Queue'? 'Queue': 'id',
- TABLE2 => 'Groups',
- FIELD2 => 'Instance',
- ENTRYAGGREGATOR => 'AND',
- );
- $self->SUPER::Limit(
- LEFTJOIN => $groups,
- ALIAS => $groups,
- FIELD => 'Domain',
- VALUE => 'RT::'. $args{'Class'} .'-Role',
- );
- $self->SUPER::Limit(
- LEFTJOIN => $groups,
- ALIAS => $groups,
- FIELD => 'Type',
- VALUE => $args{'Type'},
- ) if $args{'Type'};
-
- $self->{'_sql_role_group_aliases'}{ $args{'Class'} .'-'. $args{'Type'} } = $groups
- unless $args{'New'};
-
- return $groups;
+ my %args = (Class => 'RT::Ticket', @_);
+ if ( $args{'Class'} eq 'Queue' ) {
+ $args{'Class'} = 'RT::Queue';
+ $args{'Field'} = 'Queue';
+ }
+ return $self->JoinRoleGroups( %args );
}
sub _GroupMembersJoin {
commit 08fc8dc5df8bbc8ec4def3422bbaf042842374ab
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date: Fri Dec 10 09:09:54 2010 +0300
use Queue IN (1,2,3,...) instead long OR sequences
diff --git a/lib/RT/Tickets_Overlay.pm b/lib/RT/Tickets_Overlay.pm
index c154832..cd0dde6 100755
--- a/lib/RT/Tickets_Overlay.pm
+++ b/lib/RT/Tickets_Overlay.pm
@@ -3040,29 +3040,16 @@ sub CurrentUserCanSee {
my $ea = shift;
my @queues = @_;
- return unless @queues;
- if ( @queues == 1 ) {
- $self->SUPER::Limit(
- SUBCLAUSE => 'ACL',
- ALIAS => 'main',
- FIELD => 'Queue',
- VALUE => $_[0],
- ENTRYAGGREGATOR => $ea,
- );
- } else {
- $self->SUPER::_OpenParen('ACL');
- foreach my $q ( @queues ) {
- $self->SUPER::Limit(
- SUBCLAUSE => 'ACL',
- ALIAS => 'main',
- FIELD => 'Queue',
- VALUE => $q,
- ENTRYAGGREGATOR => $ea,
- );
- $ea = 'OR';
- }
- $self->SUPER::_CloseParen('ACL');
- }
+ return 0 unless @queues;
+ $self->SUPER::Limit(
+ SUBCLAUSE => 'ACL',
+ ALIAS => 'main',
+ FIELD => 'Queue',
+ OPERATOR => 'IN',
+ VALUE => '('. join(', ', @queues) .')',
+ QUOTEVALUE => 0,
+ ENTRYAGGREGATOR => $ea,
+ );
return 1;
};
commit a3bc83c5400ecff47d26dfca5e5d33b493a77cc1
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date: Fri Dec 10 09:11:04 2010 +0300
switch over generic methods we have in RT::ACL
diff --git a/lib/RT/Tickets_Overlay.pm b/lib/RT/Tickets_Overlay.pm
index cd0dde6..6c2ed86 100755
--- a/lib/RT/Tickets_Overlay.pm
+++ b/lib/RT/Tickets_Overlay.pm
@@ -2862,92 +2862,6 @@ sub _DoCount {
return $self->SUPER::_DoCount( @_ );
}
-sub _RolesCanSee {
- my $self = shift;
-
- my $cache_key = 'RolesHasRight;:;ShowTicket';
-
- if ( my $cached = $RT::Principal::_ACL_CACHE->fetch( $cache_key ) ) {
- return %$cached;
- }
-
- my $ACL = RT::ACL->new( RT->SystemUser );
- $ACL->Limit( FIELD => 'RightName', VALUE => 'ShowTicket' );
- $ACL->Limit( FIELD => 'PrincipalType', OPERATOR => '!=', VALUE => 'Group' );
- my $principal_alias = $ACL->Join(
- ALIAS1 => 'main',
- FIELD1 => 'PrincipalId',
- TABLE2 => 'Principals',
- FIELD2 => 'id',
- );
- $ACL->Limit( ALIAS => $principal_alias, FIELD => 'Disabled', VALUE => 0 );
-
- my %res = ();
- foreach my $ACE ( @{ $ACL->ItemsArrayRef } ) {
- my $role = $ACE->__Value('PrincipalType');
- my $type = $ACE->__Value('ObjectType');
- if ( $type eq 'RT::System' ) {
- $res{ $role } = 1;
- }
- elsif ( $type eq 'RT::Queue' ) {
- next if $res{ $role } && !ref $res{ $role };
- push @{ $res{ $role } ||= [] }, $ACE->__Value('ObjectId');
- }
- else {
- $RT::Logger->error('ShowTicket right is granted on unsupported object');
- }
- }
- $RT::Principal::_ACL_CACHE->set( $cache_key => \%res );
- return %res;
-}
-
-sub _DirectlyCanSeeIn {
- my $self = shift;
- my $id = $self->CurrentUser->id;
-
- my $cache_key = 'User-'. $id .';:;ShowTicket;:;DirectlyCanSeeIn';
- if ( my $cached = $RT::Principal::_ACL_CACHE->fetch( $cache_key ) ) {
- return @$cached;
- }
-
- my $ACL = RT::ACL->new( RT->SystemUser );
- $ACL->Limit( FIELD => 'RightName', VALUE => 'ShowTicket' );
- my $principal_alias = $ACL->Join(
- ALIAS1 => 'main',
- FIELD1 => 'PrincipalId',
- TABLE2 => 'Principals',
- FIELD2 => 'id',
- );
- $ACL->Limit( ALIAS => $principal_alias, FIELD => 'Disabled', VALUE => 0 );
- my $cgm_alias = $ACL->Join(
- ALIAS1 => 'main',
- FIELD1 => 'PrincipalId',
- TABLE2 => 'CachedGroupMembers',
- FIELD2 => 'GroupId',
- );
- $ACL->Limit( ALIAS => $cgm_alias, FIELD => 'MemberId', VALUE => $id );
- $ACL->Limit( ALIAS => $cgm_alias, FIELD => 'Disabled', VALUE => 0 );
-
- my @res = ();
- foreach my $ACE ( @{ $ACL->ItemsArrayRef } ) {
- my $type = $ACE->__Value('ObjectType');
- if ( $type eq 'RT::System' ) {
- # If user is direct member of a group that has the right
- # on the system then he can see any ticket
- $RT::Principal::_ACL_CACHE->set( $cache_key => [-1] );
- return (-1);
- }
- elsif ( $type eq 'RT::Queue' ) {
- push @res, $ACE->__Value('ObjectId');
- }
- else {
- $RT::Logger->error('ShowTicket right is granted on unsupported object');
- }
- }
- $RT::Principal::_ACL_CACHE->set( $cache_key => \@res );
- return @res;
-}
-
sub CurrentUserCanSee {
my $self = shift;
return if $self->{'_sql_current_user_can_see_applied'};
@@ -2960,21 +2874,30 @@ sub CurrentUserCanSee {
my $id = $self->CurrentUser->id;
# directly can see in all queues then we have nothing to do
- my @direct_queues = $self->_DirectlyCanSeeIn;
+ my %direct = RT::ACL->_ObjectsDirectlyHasRightOn(
+ User => $id,
+ Right => 'ShowTicket',
+ );
return $self->{'_sql_current_user_can_see_applied'} = 1
- if @direct_queues && $direct_queues[0] == -1;
+ if $direct{'RT::System'};
+
+ # from this point we only interested in queues
+ %direct = ('RT::Queue' => $direct{'RT::Queue'} || []);
+
+ my %roles = RT::ACL->_RolesWithRight( Right => 'ShowTicket' );
- my %roles = $self->_RolesCanSee;
{
- my %skip = map { $_ => 1 } @direct_queues;
+ my %skip = map { $_ => 1 } @{ $direct{'RT::Queue'} };
foreach my $role ( keys %roles ) {
- next unless ref $roles{ $role };
-
- my @queues = grep !$skip{$_}, @{ $roles{ $role } };
- if ( @queues ) {
- $roles{ $role } = \@queues;
+ if ( $roles{ $role }{'RT::System'} ) {
+ $roles{ $role } = 1;
} else {
- delete $roles{ $role };
+ my @queues = grep !$skip{$_}, @{ $roles{ $role }{'RT::Queue'} || [] };
+ if ( @queues ) {
+ $roles{ $role } = \@queues;
+ } else {
+ delete $roles{ $role };
+ }
}
}
}
@@ -3007,11 +2930,11 @@ sub CurrentUserCanSee {
$groups->Limit( ALIAS => $cgm_alias, FIELD => 'MemberId', VALUE => $id );
$groups->Limit( ALIAS => $cgm_alias, FIELD => 'Disabled', VALUE => 0 );
while ( my $group = $groups->Next ) {
- push @direct_queues, $group->Instance;
+ push @{ $direct{'RT::Queue'} }, $group->Instance;
}
}
- unless ( @direct_queues || keys %roles ) {
+ unless ( @{ $direct{'RT::Queue'} } || keys %roles ) {
$self->SUPER::Limit(
SUBCLAUSE => 'ACL',
ALIAS => 'main',
@@ -3055,7 +2978,7 @@ sub CurrentUserCanSee {
$self->SUPER::_OpenParen('ACL');
my $ea = 'AND';
- $ea = 'OR' if $limit_queues->( $ea, @direct_queues );
+ $ea = 'OR' if $limit_queues->( $ea, @{ $direct{'RT::Queue'} } );
while ( my ($role, $queues) = each %roles ) {
$self->SUPER::_OpenParen('ACL');
if ( $role eq 'Owner' ) {
commit f90a8d35f2b6c6d270405f1e2c7a3218f9c11879
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date: Sat Dec 11 06:03:14 2010 +0300
SUBLCAUSE doesn't work with LEFTJOIN in Limit
diff --git a/lib/RT/Tickets_Overlay_SQL.pm b/lib/RT/Tickets_Overlay_SQL.pm
index a61e1a2..3634aa4 100755
--- a/lib/RT/Tickets_Overlay_SQL.pm
+++ b/lib/RT/Tickets_Overlay_SQL.pm
@@ -86,7 +86,7 @@ sub _SQLLimit {
(!$args{'ALIAS'} || $args{'ALIAS'} eq 'main' ) ) {
$self->{'looking_at_type'} = 1;
}
- $args{'SUBCLAUSE'} ||= 'ticketsql';
+ $args{'SUBCLAUSE'} ||= 'ticketsql' unless $args{'LEFTJOIN'};
# All SQL stuff goes into one SB subclause so we can deal with all
# the aggregation
commit 8f381bf73efd0e9b9258930c9bf1046d9e936f1e
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date: Sat Dec 11 06:04:29 2010 +0300
JoinGroupMembers in RT::SearchBuilder
diff --git a/lib/RT/SearchBuilder.pm b/lib/RT/SearchBuilder.pm
index 3b3a821..7cd1789 100755
--- a/lib/RT/SearchBuilder.pm
+++ b/lib/RT/SearchBuilder.pm
@@ -350,6 +350,29 @@ sub JoinRoleGroups {
return $groups;
}
+sub JoinGroupMembers {
+ my $self = shift;
+ my %args = (New => 1, GroupsAlias => undef, Left => 1, @_);
+
+ return $self->{'_sql_aliases'}{'group_members'}{ $args{'GroupsAlias'} }
+ if $self->{'_sql_aliases'}{'group_members'}{ $args{'GroupsAlias'} }
+ && !$args{'New'};
+
+ my $alias = $self->Join(
+ $args{'Left'} ? (TYPE => 'LEFT') : (),
+ ALIAS1 => $args{'GroupsAlias'},
+ FIELD1 => 'id',
+ TABLE2 => 'CachedGroupMembers',
+ FIELD2 => 'GroupId',
+ ENTRYAGGREGATOR => 'AND',
+ );
+
+ $self->{'_sql_aliases'}{'group_members'}{ $args{'GroupsAlias'} } = $alias
+ unless $args{'New'};
+
+ return $alias;
+}
+
RT::Base->_ImportOverlays();
1;
diff --git a/lib/RT/Tickets_Overlay.pm b/lib/RT/Tickets_Overlay.pm
index 6c2ed86..08428a7 100755
--- a/lib/RT/Tickets_Overlay.pm
+++ b/lib/RT/Tickets_Overlay.pm
@@ -243,7 +243,6 @@ sub CleanSlate {
$self->SUPER::CleanSlate( @_ );
delete $self->{$_} foreach qw(
_sql_cf_alias
- _sql_group_members_aliases
_sql_object_cfv_alias
_sql_trattachalias
_sql_u_watchers_alias_for_sort
@@ -1021,26 +1020,7 @@ sub _RoleGroupsJoin {
}
sub _GroupMembersJoin {
- my $self = shift;
- my %args = (New => 1, GroupsAlias => undef, Left => 1, @_);
-
- return $self->{'_sql_group_members_aliases'}{ $args{'GroupsAlias'} }
- if $self->{'_sql_group_members_aliases'}{ $args{'GroupsAlias'} }
- && !$args{'New'};
-
- my $alias = $self->Join(
- $args{'Left'} ? (TYPE => 'LEFT') : (),
- ALIAS1 => $args{'GroupsAlias'},
- FIELD1 => 'id',
- TABLE2 => 'CachedGroupMembers',
- FIELD2 => 'GroupId',
- ENTRYAGGREGATOR => 'AND',
- );
-
- $self->{'_sql_group_members_aliases'}{ $args{'GroupsAlias'} } = $alias
- unless $args{'New'};
-
- return $alias;
+ return (shift)->JoinGroupMembers( @_ );
}
=head2 _WatcherJoin
commit 362d2769facc1db27221703c9ea41d6a17676023
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date: Sat Dec 11 06:05:10 2010 +0300
restore backwards compatibility in RT::Tickets::_RoleGroupsJoin
diff --git a/lib/RT/Tickets_Overlay.pm b/lib/RT/Tickets_Overlay.pm
index 08428a7..fdba2fa 100755
--- a/lib/RT/Tickets_Overlay.pm
+++ b/lib/RT/Tickets_Overlay.pm
@@ -1016,6 +1016,10 @@ sub _RoleGroupsJoin {
$args{'Class'} = 'RT::Queue';
$args{'Field'} = 'Queue';
}
+ elsif ( $args{'Class'} eq 'Ticket' ) {
+ $args{'Class'} = 'RT::Ticket';
+ $args{'Field'} = 'id';
+ }
return $self->JoinRoleGroups( %args );
}
commit 367453004f46002b9f06dfe062bc7250c9472dbc
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date: Sat Dec 11 06:12:24 2010 +0300
UseSQLForACLChecks for RT::Queues
diff --git a/lib/RT/Queues_Overlay.pm b/lib/RT/Queues_Overlay.pm
index 856b1b3..b39b3fa 100755
--- a/lib/RT/Queues_Overlay.pm
+++ b/lib/RT/Queues_Overlay.pm
@@ -101,11 +101,133 @@ This is used for filtering objects for both Next and ItemsArrayRef.
sub AddRecord {
my $self = shift;
my $Queue = shift;
- return unless $Queue->CurrentUserHasRight('SeeQueue');
+ return if !$self->{'_sql_current_user_can_see_applied'}
+ && !$Queue->CurrentUserHasRight('SeeQueue');
push @{$self->{'items'}}, $Queue;
$self->{'rows'}++;
}
-1;
+sub _DoSearch {
+ my $self = shift;
+ $self->CurrentUserCanSee if RT->Config->Get('UseSQLForACLChecks');
+ return $self->SUPER::_DoSearch( @_ );
+}
+
+sub _DoCount {
+ my $self = shift;
+ $self->CurrentUserCanSee if RT->Config->Get('UseSQLForACLChecks');
+ return $self->SUPER::_DoCount( @_ );
+}
+
+sub CurrentUserCanSee {
+ my $self = shift;
+ return if $self->{'_sql_current_user_can_see_applied'};
+
+ return $self->{'_sql_current_user_can_see_applied'} = 1
+ if $self->CurrentUser->UserObj->HasRight(
+ Right => 'SuperUser', Object => $RT::System
+ );
+
+ my $id = $self->CurrentUser->id;
+
+ # directly can see in all queues then we have nothing to do
+ my %direct = RT::ACL->_ObjectsDirectlyHasRightOn(
+ User => $id,
+ Right => 'SeeQueue',
+ );
+ return $self->{'_sql_current_user_can_see_applied'} = 1
+ if $direct{'RT::System'};
+
+ # from this point we only interested in queues
+ %direct = ('RT::Queue' => $direct{'RT::Queue'} || []);
+
+ my %roles = RT::ACL->_RolesWithRight( Right => 'SeeQueue' );
+ {
+ my %skip = map { $_ => 1 } @{ $direct{'RT::Queue'} };
+ foreach my $role ( keys %roles ) {
+ if ( $roles{ $role }{'RT::System'} ) {
+ $roles{ $role } = 1;
+ } else {
+ my @queues = grep !$skip{$_}, @{ $roles{ $role }{'RT::Queue'} || [] };
+ if ( @queues ) {
+ $roles{ $role } = \@queues;
+ } else {
+ delete $roles{ $role };
+ }
+ }
+ }
+ }
+
+ unless ( @{$direct{'RT::Queue'}} || keys %roles ) {
+ $self->SUPER::Limit(
+ SUBCLAUSE => 'ACL',
+ ALIAS => 'main',
+ FIELD => 'id',
+ VALUE => 0,
+ ENTRYAGGREGATOR => 'AND',
+ );
+ return $self->{'_sql_current_user_can_see_applied'} = 1;
+ }
+
+ {
+ my ($role_group_alias, $cgm_alias);
+ if ( keys %roles ) {
+ $role_group_alias = $self->JoinRoleGroups( New => 1 );
+ $cgm_alias = $self->JoinGroupMembers( GroupsAlias => $role_group_alias );
+ $self->Limit(
+ LEFTJOIN => $cgm_alias,
+ FIELD => 'MemberId',
+ OPERATOR => '=',
+ VALUE => $id,
+ );
+ }
+ my $limit_queues = sub {
+ my $ea = shift;
+ my @queues = @_;
+
+ return 0 unless @queues;
+ $self->Limit(
+ SUBCLAUSE => 'ACL',
+ ALIAS => 'main',
+ FIELD => 'id',
+ OPERATOR => 'IN',
+ VALUE => '('. join(', ', @queues) .')',
+ QUOTEVALUE => 0,
+ ENTRYAGGREGATOR => $ea,
+ );
+ return 1;
+ };
+
+ $self->SUPER::_OpenParen('ACL');
+ my $ea = 'AND';
+ $ea = 'OR' if $limit_queues->( $ea, @{ $direct{'RT::Queue'} } );
+ while ( my ($role, $queues) = each %roles ) {
+ $self->SUPER::_OpenParen('ACL');
+ $self->Limit(
+ SUBCLAUSE => 'ACL',
+ ALIAS => $cgm_alias,
+ FIELD => 'MemberId',
+ OPERATOR => 'IS NOT',
+ VALUE => 'NULL',
+ QUOTEVALUE => 0,
+ ENTRYAGGREGATOR => $ea,
+ );
+ $self->Limit(
+ SUBCLAUSE => 'ACL',
+ ALIAS => $role_group_alias,
+ FIELD => 'Type',
+ VALUE => $role,
+ ENTRYAGGREGATOR => 'AND',
+ );
+ $limit_queues->( 'AND', @$queues ) if ref $queues;
+ $ea = 'OR' if $ea eq 'AND';
+ $self->SUPER::_CloseParen('ACL');
+ }
+ $self->SUPER::_CloseParen('ACL');
+ }
+ return $self->{'_sql_current_user_can_see_applied'} = 1;
+}
+
+1;
-----------------------------------------------------------------------
More information about the Rt-commit
mailing list