summaryrefslogtreecommitdiff
path: root/rt/lib/RT/Users_Overlay.pm
diff options
context:
space:
mode:
Diffstat (limited to 'rt/lib/RT/Users_Overlay.pm')
-rw-r--r--rt/lib/RT/Users_Overlay.pm211
1 files changed, 175 insertions, 36 deletions
diff --git a/rt/lib/RT/Users_Overlay.pm b/rt/lib/RT/Users_Overlay.pm
index 49e4a99a6..4bb9f8f91 100644
--- a/rt/lib/RT/Users_Overlay.pm
+++ b/rt/lib/RT/Users_Overlay.pm
@@ -1,8 +1,8 @@
-# {{{ BEGIN BPS TAGGED BLOCK
+# BEGIN BPS TAGGED BLOCK {{{
#
# COPYRIGHT:
#
-# This software is Copyright (c) 1996-2004 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2005 Best Practical Solutions, LLC
# <jesse@bestpractical.com>
#
# (Except where explicitly superseded by other copyright notices)
@@ -42,7 +42,8 @@
# works based on those contributions, and sublicense and distribute
# those contributions and any derivatives thereof.
#
-# }}} END BPS TAGGED BLOCK
+# END BPS TAGGED BLOCK }}}
+
=head1 NAME
RT::Users - Collection of RT::User objects
@@ -65,6 +66,9 @@ ok(require RT::Users);
=cut
+
+package RT::Users;
+
use strict;
no warnings qw(redefine);
@@ -219,7 +223,7 @@ sub LimitToPrivileged {
# {{{ WhoHaveRight
-=head2 WhoHaveRight { Right => 'name', Object => $rt_object , IncludeSuperusers => undef, IncludeSubgroupMembers => undef, IncludeSystemRights => undef }
+=head2 WhoHaveRight { Right => 'name', Object => $rt_object , IncludeSuperusers => undef, IncludeSubgroupMembers => undef, IncludeSystemRights => undef, EquivObjects => [ ] }
=begin testing
@@ -228,6 +232,59 @@ $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
@@ -236,6 +293,7 @@ find all users who the right Right for this group, either individually
or as members of groups
+If passed a queue object, with no id, it will find users who have that right for _any_ queue
@@ -243,38 +301,125 @@ or as members of groups
sub WhoHaveRight {
my $self = shift;
- 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);
+ my %args = (
+ Right => undef,
+ Object => undef,
+ IncludeSystemRights => undef,
+ IncludeSuperusers => undef,
+ IncludeSubgroupMembers => 1,
+ EquivObjects => [ ],
+ @_
+ );
+
+ 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();
- }
+
+
+ # 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 (@privgroups) {
- $self->WhoBelongToGroups(Groups => \@privgroups,
- IncludeSubgroupMembers => $args{'IncludeSubgroupMembers'});
+ if ( $args{'IncludeSubgroupMembers'} ) {
+ $cgm = $self->NewAlias('CachedGroupMembers');
}
else {
- # We don't have any group that matches -- make it impossible.
- $self->Limit( FIELD => 'Id', VALUE => 'IS', OPERATOR => 'NULL' );
+ $cgm = $self->NewAlias('GroupMembers');
}
-}
+#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 = '';
+ }
+ foreach my $obj ( @{ $args{'EquivObjects'} } ) {
+ $which_object .= "($acl.ObjectType = '" . ref( $obj ) . "' AND $acl.ObjectId = " . $obj->id . ") OR ";
+ }
+ $which_object .= " ($acl.ObjectType = '" . ref( $args{'Object'} ) . "'";
+ if ( $args{'Object'}->id ) {
+ $which_object .= " AND $acl.ObjectId = " . $args{'Object'}->id;
+ }
+
+ $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
@@ -307,20 +452,14 @@ sub WhoBelongToGroups {
$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);
}
# }}}