[Rt-commit] rt branch, 4.4/sql-acl-for-queues, created. rt-4.0.8-575-g352f8a6
Alex Vandiver
alexmv at bestpractical.com
Fri Oct 11 18:41:41 EDT 2013
The branch, 4.4/sql-acl-for-queues has been created
at 352f8a62d447e12de10fb0b29363b7f5c6b3457c (commit)
- Log -----------------------------------------------------------------
commit b1a2c16a0df985244a5fe9cbb387e6a0d3c3ca29
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 47c09a6..7e6f00c 100644
--- a/lib/RT/SearchBuilder.pm
+++ b/lib/RT/SearchBuilder.pm
@@ -370,6 +370,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 6c536420be8fe4d80807f766ff052f9c3230b57c
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.pm b/lib/RT/ACL.pm
index 49a7f1d..9f24b5c 100644
--- a/lib/RT/ACL.pm
+++ b/lib/RT/ACL.pm
@@ -334,4 +334,100 @@ sub NewItem {
}
RT::Base->_ImportOverlays();
+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 17bf42854cfeed0ca3025e070ae92cc88ce7ce57
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date: Fri Dec 10 09:06:12 2010 +0300
make it possible to override subclause
RT::Tickets has so bad overrides for Limit that
we have to use _SQLLimit, but it hardcodes
subclause.
Let's default subclause and respect provided.
SUBLCAUSE doesn't work together with LEFTJOIN
argument.
diff --git a/lib/RT/Tickets_SQL.pm b/lib/RT/Tickets_SQL.pm
index ec1bb49..e5f3aef 100644
--- a/lib/RT/Tickets_SQL.pm
+++ b/lib/RT/Tickets_SQL.pm
@@ -87,11 +87,11 @@ sub _SQLLimit {
(!$args{'ALIAS'} || $args{'ALIAS'} eq 'main' ) ) {
$self->{'looking_at_type'} = 1;
}
+ $args{'SUBCLAUSE'} = 'ticketsql' if !defined $args{'SUBCLAUSE'} && !$args{'LEFTJOIN'};
# 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 {
@@ -148,7 +148,6 @@ sub _close_bundle {
$bundle[0]->{'key'},
$bundle[0]->{'op'},
$bundle[0]->{'val'},
- SUBCLAUSE => '',
ENTRYAGGREGATOR => $bundle[0]->{ea},
SUBKEY => $bundle[0]->{subkey},
);
@@ -160,7 +159,6 @@ sub _close_bundle {
$chunk->{key},
$chunk->{op},
$chunk->{val},
- SUBCLAUSE => '',
ENTRYAGGREGATOR => $chunk->{ea},
SUBKEY => $chunk->{subkey},
];
@@ -229,7 +227,6 @@ sub _parser {
else {
$self->_close_bundle(@bundle); @bundle = ();
$sub->( $self, $key, $op, $value,
- SUBCLAUSE => '', # don't need anymore
ENTRYAGGREGATOR => $ea,
SUBKEY => $subkey,
);
commit fa8f2c4677b1bf06613623fa7d9eaf90faea2c23
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.pm b/lib/RT/Tickets.pm
index 580a66f..820b28a 100644
--- a/lib/RT/Tickets.pm
+++ b/lib/RT/Tickets.pm
@@ -259,7 +259,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
@@ -1049,36 +1048,16 @@ 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';
+ }
+ elsif ( $args{'Class'} eq 'Ticket' ) {
+ $args{'Class'} = 'RT::Ticket';
+ $args{'Field'} = 'id';
+ }
+ return $self->JoinRoleGroups( %args );
}
sub _GroupMembersJoin {
commit f4b24a044be6ab013a4186bb6d657755efc807d3
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.pm b/lib/RT/Tickets.pm
index 820b28a..12564ff 100644
--- a/lib/RT/Tickets.pm
+++ b/lib/RT/Tickets.pm
@@ -3176,29 +3176,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 657974c254ef387477e3a9092aea8c6e2fe8fd71
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.pm b/lib/RT/Tickets.pm
index 12564ff..1575f9d 100644
--- a/lib/RT/Tickets.pm
+++ b/lib/RT/Tickets.pm
@@ -2998,92 +2998,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'};
@@ -3096,21 +3010,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 };
+ }
}
}
}
@@ -3143,11 +3066,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',
@@ -3191,7 +3114,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 c23913083248e7bf92f652855426aa9072d037c5
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 7e6f00c..2e19e51 100644
--- a/lib/RT/SearchBuilder.pm
+++ b/lib/RT/SearchBuilder.pm
@@ -422,6 +422,42 @@ sub JoinRoleGroups {
return $groups;
}
+sub JoinGroupMembers {
+ my $self = shift;
+ my %args = (New => 1, GroupsAlias => undef, ActiveOnly => 1, Left => 1, @_);
+
+ my $key = join '_', $args{'ActiveOnly'}? ('active'): (),
+ 'group_members', $args{'GroupsAlias'};
+
+ return $self->{'_sql_aliases'}{ $key }
+ if $self->{'_sql_aliases'}{ $key } && !$args{'New'};
+
+ my $alias = $self->Join(
+ $args{'Left'} ? (TYPE => 'LEFT') : (),
+ ALIAS1 => $args{'GroupsAlias'},
+ FIELD1 => 'id',
+ TABLE2 => 'CachedGroupMembers',
+ FIELD2 => 'GroupId',
+ ENTRYAGGREGATOR => 'AND',
+ );
+ if ( $args{'ActiveOnly'} ) {
+ my $limit = 'Limit';
+ # special case for tickets :(
+ $limit = '_SQLLimit' if $self->isa('RT::Tickets');
+ $self->$limit(
+ $args{'Left'} ? (LEFTJOIN => $alias) : (),
+ SUBCLAUSE => '',
+ ALIAS => $alias,
+ FIELD => 'Disabled',
+ VALUE => 0,
+ );
+ }
+
+ $self->{'_sql_aliases'}{ $key } = $alias unless $args{'New'};
+
+ return $alias;
+}
+
RT::Base->_ImportOverlays();
1;
diff --git a/lib/RT/Tickets.pm b/lib/RT/Tickets.pm
index 1575f9d..d3f41c5 100644
--- a/lib/RT/Tickets.pm
+++ b/lib/RT/Tickets.pm
@@ -257,7 +257,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
@@ -1061,32 +1060,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->SUPER::Limit(
- $args{'Left'} ? (LEFTJOIN => $alias) : (),
- ALIAS => $alias,
- FIELD => 'Disabled',
- VALUE => 0,
- );
-
- $self->{'_sql_group_members_aliases'}{ $args{'GroupsAlias'} } = $alias
- unless $args{'New'};
-
- return $alias;
+ return (shift)->JoinGroupMembers( @_ );
}
=head2 _WatcherJoin
commit 352f8a62d447e12de10fb0b29363b7f5c6b3457c
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.pm b/lib/RT/Queues.pm
index feb3491..24ec586 100644
--- a/lib/RT/Queues.pm
+++ b/lib/RT/Queues.pm
@@ -107,12 +107,135 @@ 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'}++;
}
+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;
+}
+
-----------------------------------------------------------------------
More information about the Rt-commit
mailing list