[Rt-commit] r2113 - in rt/branches/3.4-RELEASE: . html/Elements
lib/RT
jesse at bestpractical.com
jesse at bestpractical.com
Tue Jan 18 10:46:49 EST 2005
Author: jesse
Date: Tue Jan 18 10:46:48 2005
New Revision: 2113
Modified:
rt/branches/3.4-RELEASE/ (props changed)
rt/branches/3.4-RELEASE/html/Elements/SelectOwner
rt/branches/3.4-RELEASE/lib/RT/Users_Overlay.pm
Log:
r3885 at hualien: jesse | 2005-01-18T15:02:02.574134Z
Reimplemented RT::Users->WhoHaveRights to remove O(n^2) SQL calls. (That means it's faster now)
Reimplemented SelectOwner widget to take advantage of the new WhoHaveRights
Modified: rt/branches/3.4-RELEASE/html/Elements/SelectOwner
==============================================================================
--- rt/branches/3.4-RELEASE/html/Elements/SelectOwner (original)
+++ rt/branches/3.4-RELEASE/html/Elements/SelectOwner Tue Jan 18 10:46:48 2005
@@ -67,25 +67,20 @@
@objects = keys %{$cfqueues};
}
else {
- my $Queues = RT::Queues->new($session{CurrentUser});
- $Queues->UnLimit();
- while (my $Queue = $Queues->Next()) {
- push( @objects, $Queue );
- }
+ # Let's check rights on an empty queue object. that will do a search for any queue.
+ my $queue = RT::Queue->new($session{'CurrentUser'});
+ push( @objects, $queue );
}
my %user_uniq_hash;
foreach my $object (@objects) {
my $Users = RT::Users->new($session{CurrentUser});
- $Users->WhoHaveRight(Right => 'OwnTicket',
- Object => $object,
- IncludeSystemRights => 1,
- IncludeSuperusers => 0);
+ $Users->WhoHaveRight(Right => 'OwnTicket', Object => $object, IncludeSystemRights => 1, IncludeSuperusers => 0);
while (my $User = $Users->Next()) {
$user_uniq_hash{$User->Id()} = $User;
}
}
- at users = sort { uc($a->Name) cmp uc($b->Name) } values %user_uniq_hash;
+ at users = sort { uc($a->Name) cmp uc($b->Name) } values %user_uniq_hash;
</%INIT>
<%ARGS>
Modified: rt/branches/3.4-RELEASE/lib/RT/Users_Overlay.pm
==============================================================================
--- rt/branches/3.4-RELEASE/lib/RT/Users_Overlay.pm (original)
+++ rt/branches/3.4-RELEASE/lib/RT/Users_Overlay.pm Tue Jan 18 10:46:48 2005
@@ -239,6 +239,7 @@
or as members of groups
+If passed a queue object, with no id, it will find users who have that right for _any_ queue
@@ -246,38 +247,121 @@
sub WhoHaveRight {
my $self = shift;
- my %args = ( Right => undef,
- Object => undef,
- IncludeSystemRights => undef,
- IncludeSuperusers => undef,
- IncludeSubgroupMembers => 1,
- @_ );
+ my %args = (
+ Right => undef,
+ Object => undef,
+ IncludeSystemRights => undef,
+ IncludeSuperusers => undef,
+ IncludeSubgroupMembers => 1,
+ @_
+ );
+
+ if ( defined $args{'ObjectType'} || defined $args{'ObjectId'} ) {
+ $RT::Logger->crit( "$self WhoHaveRight called with the Obsolete ObjectId/ObjectType API");
+ return (undef);
+ }
+
+
+ # Find only members of groups that have the right.
+
+ my $acl = $self->NewAlias('ACL');
+ my $groups = $self->NewAlias('Groups');
+ my $userprinc = $self->{'princalias'};
+
+# The cachedgroupmembers table is used for unrolling group memberships to allow fast lookups
+# if we bind to CachedGroupMembers, we'll find all members of groups recursively.
+# if we don't we'll find only 'direct' members of the group in question
+ my $cgm;
+
+ if ( $args{'IncludeSubgroupMembers'} ) {
+ $cgm = $self->NewAlias('CachedGroupMembers');
+ }
+ else {
+ $cgm = $self->NewAlias('GroupMembers');
+ }
- if (defined $args{'ObjectType'} || defined $args{'ObjectId'}) {
- $RT::Logger->crit("$self WhoHaveRight called with the Obsolete ObjectId/ObjectType API");
- return(undef);
- }
- my @privgroups;
- my $Groups = RT::Groups->new($RT::SystemUser);
- $Groups->WithRight(Right=> $args{'Right'},
- Object => $args{'Object'},
- IncludeSystemRights => $args{'IncludeSystemRights'},
- IncludeSuperusers => $args{'IncludeSuperusers'});
- while (my $Group = $Groups->Next()) {
- push @privgroups, $Group->Id();
+#Tie the users we're returning ($userprinc) to the groups that have rights granted to them ($groupprinc)
+ $self->Join(
+ ALIAS1 => $cgm,
+ FIELD1 => 'MemberId',
+ ALIAS2 => $userprinc,
+ FIELD2 => 'id'
+ );
+
+ $self->Join(
+ ALIAS1 => $groups,
+ FIELD1 => 'id',
+ ALIAS2 => $cgm,
+ FIELD2 => 'GroupId'
+ );
+
+# {{{ Find only rows where the right granted is the one we're looking up or _possibly_ superuser
+ $self->Limit(
+ ALIAS => $acl,
+ FIELD => 'RightName',
+ OPERATOR => ( $args{Right} ? '=' : 'IS NOT' ),
+ VALUE => $args{Right} || 'NULL',
+ ENTRYAGGREGATOR => 'OR'
+ );
+
+ if ( $args{'IncludeSuperusers'} and $args{'Right'} ) {
+ $self->Limit(
+ ALIAS => $acl,
+ FIELD => 'RightName',
+ OPERATOR => '=',
+ VALUE => 'SuperUser',
+ ENTRYAGGREGATOR => 'OR'
+ );
+ }
+
+ # }}}
+
+ my ( $or_check_ticket_roles, $or_check_roles );
+ my $which_object = "$acl.ObjectType = 'RT::System'";
+
+ if ( defined $args{'Object'} ) {
+ if ( ref( $args{'Object'} ) eq 'RT::Ticket' ) {
+ $or_check_ticket_roles = " OR ( $groups.Domain = 'RT::Ticket-Role' AND $groups.Instance = " . $args{'Object'}->Id . ") ";
+
+# If we're looking at ticket rights, we also want to look at the associated queue rights.
+# this is a little bit hacky, but basically, now that we've done the ticket roles magic,
+# we load the queue object and ask all the rest of our questions about the queue.
+ $args{'Object'} = $args{'Object'}->QueueObj;
}
+ # TODO XXX This really wants some refactoring
+ if ( ref( $args{'Object'} ) eq 'RT::Queue' ) {
+ $or_check_roles = " OR ( ( ($groups.Domain = 'RT::Queue-Role' ";
+ $or_check_roles .= "AND $groups.Instance = " . $args{'Object'}->id if ( $args{'Object'}->id );
+ $or_check_roles .= ") $or_check_ticket_roles ) " . " AND $groups.Type = $acl.PrincipalType) ";
+ }
+ if ( $args{'IncludeSystemRights'} ) {
+ $which_object .= ' OR ';
+ }
+ else {
+ $which_object = '';
+ }
+ $which_object .= " ($acl.ObjectType = '" . ref( $args{'Object'} ) . "'";
+ if ( $args{'Object'}->id ) {
+ $which_object .= " AND $acl.ObjectId = " . $args{'Object'}->id;
+ }
- if (@privgroups) {
- $self->WhoBelongToGroups(Groups => \@privgroups,
- IncludeSubgroupMembers => $args{'IncludeSubgroupMembers'});
- }
- else {
- # We don't have any group that matches -- make it impossible.
- $self->Limit( FIELD => 'Id', VALUE => 'IS', OPERATOR => 'NULL' );
+ $which_object .= ") ";
}
-}
+ $self->_AddSubClause( "WhichObject", "($which_object)" );
+ $self->_AddSubClause(
+ "WhichGroup",
+ qq{ ( ( $acl.PrincipalId = $groups.id AND $acl.PrincipalType = 'Group'
+ AND ( $groups.Domain = 'SystemInternal' OR $groups.Domain = 'UserDefined' OR $groups.Domain = 'ACLEquivalence'))
+ $or_check_roles) }
+ );
+ # only include regular RT users
+ $self->LimitToEnabled;
+
+ # no system user
+ $self->Limit( ALIAS => $userprinc, FIELD => 'id', OPERATOR => '!=', VALUE => $RT::SystemUser->id);
+}
# }}}
# {{{ WhoBelongToGroups
@@ -310,20 +394,14 @@
$cgm = $self->NewAlias('GroupMembers');
}
- # {{{ Tie the users we're returning ($userprinc) to the groups that have rights granted to them ($groupprinc)
+ #Tie the users we're returning ($userprinc) to the groups that have rights granted to them ($groupprinc)
$self->Join( ALIAS1 => $cgm, FIELD1 => 'MemberId',
ALIAS2 => $userprinc, FIELD2 => 'id' );
- # }}}
- # my $and_check_groups = "($cgm.GroupId = NULL";
foreach my $groupid (@{$args{'Groups'}}) {
$self->Limit(ALIAS => $cgm, FIELD => 'GroupId', VALUE => $groupid, QUOTEVALUE => 0, ENTRYAGGREGATOR=> 'OR')
- #$and_check_groups .= " OR $cgm.GroupId = $groupid";
}
- #$and_check_groups .= ")";
-
- #$self->_AddSubClause("WhichGroup", $and_check_groups);
}
# }}}
More information about the Rt-commit
mailing list