[Rt-commit] rt branch, roles_that_has_right, updated. rt-3.8.7-180-gf1fb1d5

Ruslan Zakirov ruz at bestpractical.com
Fri Mar 5 06:30:43 EST 2010


The branch, roles_that_has_right has been updated
       via  f1fb1d5a287e03006fe8b2c81c11097c4c71e2a3 (commit)
       via  932a5a25a3520f42471e82df5688cf18b26700c4 (commit)
       via  0eccfde1a83d9b11eb2d86eeb0db910ab1a05e8e (commit)
       via  109dc24bb87cf986afba8ea25b6f5aa3ded6b525 (commit)
      from  64764a9aec4d3db397566f2ae91f7babe8c22054 (commit)

Summary of changes:
 lib/RT/Principal_Overlay.pm |  105 ++++++++++++++++++++++++++++++++----------
 lib/RT/Users_Overlay.pm     |   84 +++++-----------------------------
 2 files changed, 92 insertions(+), 97 deletions(-)

- Log -----------------------------------------------------------------
commit 109dc24bb87cf986afba8ea25b6f5aa3ded6b525
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Thu Mar 4 20:56:29 2010 +0300

    RolesWithRight method

diff --git a/lib/RT/Principal_Overlay.pm b/lib/RT/Principal_Overlay.pm
index e0646a7..7ad2bb1 100755
--- a/lib/RT/Principal_Overlay.pm
+++ b/lib/RT/Principal_Overlay.pm
@@ -448,17 +448,18 @@ sub _HasRoleRight
         EquivObjects => [],
         @_
     );
+
+    my @roles = $self->RolesWithRight( %args );
+    return 0 unless @roles;
+
     my $right = $args{'Right'};
 
     my $query =
-      "SELECT ACL.id " .
-      "FROM ACL, Groups, Principals, CachedGroupMembers WHERE " .
-
-      # Only find superuser or rights with the name $right
-      "(ACL.RightName = 'SuperUser' OR ACL.RightName = '$right') "
+      "SELECT Groups.id "
+      . "FROM Groups, Principals, CachedGroupMembers WHERE "
 
       # Never find disabled things
-      . "AND Principals.Disabled = 0 "
+      . "Principals.Disabled = 0 "
       . "AND CachedGroupMembers.Disabled = 0 "
 
       # We always grant rights to Groups
@@ -471,7 +472,9 @@ sub _HasRoleRight
       #  as is the case when we want to look up group rights
       . "AND Principals.id = CachedGroupMembers.GroupId "
       . "AND CachedGroupMembers.MemberId = ". $self->Id ." "
-      . "AND ACL.PrincipalType = Groups.Type ";
+
+      . "AND (". join(' OR ', map "Groups.Type = '$_'", @roles ) .")"
+    ;
 
     my (@object_clauses);
     foreach my $obj ( @{ $args{'EquivObjects'} } ) {
@@ -479,33 +482,59 @@ sub _HasRoleRight
         my $id;
         $id = $obj->id if ref($obj) && UNIVERSAL::can($obj, 'id') && $obj->id;
 
-        my $object_clause = "ACL.ObjectType = '$type'";
-        $object_clause   .= " AND ACL.ObjectId = $id" if $id;
-        push @object_clauses, "($object_clause)";
+        my $clause = "Groups.Domain = '$type-Role'";
+        # XXX: Groups.Instance is VARCHAR in DB, we should quote value
+        # if we want mysql 4.0 use indexes here. we MUST convert that
+        # field to integer and drop this quotes.
+        $clause .= " AND Groups.Instance = '$id'" if $id;
+        push @object_clauses, "($clause)";
     }
-    # find ACLs that are related to our objects only
     $query .= " AND (". join( ' OR ', @object_clauses ) .")";
 
-    # because of mysql bug in versions up to 5.0.45 we do one query per object
-    # each query should be faster on any DB as it uses indexes more effective
+    $self->_Handle->ApplyLimits( \$query, 1 );
+    my ($hit) = $self->_Handle->FetchResult( $query );
+    return (1) if $hit;
+
+    return 0;
+}
+
+sub RolesWithRight {
+    my $self = shift;
+    my %args = (
+        Right        => undef,
+        EquivObjects => [],
+        @_
+    );
+    my $right = $args{'Right'};
+
+    my $query =
+        "SELECT DISTINCT PrincipalType FROM ACL"
+        # Only find superuser or rights with the name $right
+        ." WHERE (RightName = 'SuperUser' OR RightName = '$right')"
+        # we need only roles
+        ." AND PrincipalType != 'Group'"
+    ;
+
+    my (@object_clauses);
     foreach my $obj ( @{ $args{'EquivObjects'} } ) {
         my $type = ref($obj)? ref($obj): $obj;
         my $id;
         $id = $obj->id if ref($obj) && UNIVERSAL::can($obj, 'id') && $obj->id;
 
-        my $tmp = $query;
-        $tmp .= " AND Groups.Domain = '$type-Role'";
-        # XXX: Groups.Instance is VARCHAR in DB, we should quote value
-        # if we want mysql 4.0 use indexes here. we MUST convert that
-        # field to integer and drop this quotes.
-        $tmp .= " AND Groups.Instance = '$id'" if $id;
-
-        $self->_Handle->ApplyLimits( \$tmp, 1 );
-        my ($hit) = $self->_Handle->FetchResult( $tmp );
-        return (1) if $hit;
+        my $object_clause = "ObjectType = '$type'";
+        $object_clause   .= " AND ObjectId = $id" if $id;
+        push @object_clauses, "($object_clause)";
     }
+    # find ACLs that are related to our objects only
+    $query .= " AND (". join( ' OR ', @object_clauses ) .")";
 
-    return 0;
+    my $dbh = $self->_Handle->dbh;
+    my $roles = $dbh->selectcol_arrayref($query);
+    unless ( $roles ) {
+        $RT::Logger->warning( $dbh->errstr );
+        return ();
+    }
+    return @$roles;
 }
 
 # }}}

commit 0eccfde1a83d9b11eb2d86eeb0db910ab1a05e8e
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Fri Mar 5 08:27:50 2010 +0300

    improve RolesWithRights
    
    * IncludeSystemRights and IncludeSuperusers arguments
    * handle case when list of objects is empty

diff --git a/lib/RT/Principal_Overlay.pm b/lib/RT/Principal_Overlay.pm
index 7ad2bb1..f2279e1 100755
--- a/lib/RT/Principal_Overlay.pm
+++ b/lib/RT/Principal_Overlay.pm
@@ -501,8 +501,10 @@ sub _HasRoleRight
 sub RolesWithRight {
     my $self = shift;
     my %args = (
-        Right        => undef,
-        EquivObjects => [],
+        Right               => undef,
+        IncludeSystemRights => 1,
+        IncludeSuperusers   => 1,
+        EquivObjects        => [],
         @_
     );
     my $right = $args{'Right'};
@@ -510,11 +512,19 @@ sub RolesWithRight {
     my $query =
         "SELECT DISTINCT PrincipalType FROM ACL"
         # Only find superuser or rights with the name $right
-        ." WHERE (RightName = 'SuperUser' OR RightName = '$right')"
+        ." WHERE ( RightName = '$right' "
+        # Check SuperUser if we were asked to
+        . ($args{'IncludeSuperusers'}? "OR RightName = 'SuperUser' " : '' )
+        .")"
         # we need only roles
         ." AND PrincipalType != 'Group'"
     ;
 
+    # skip rights granted on system level if we were asked to
+    unless ( $args{'IncludeSystemRights'} ) {
+        $query .= " AND ObjectType != 'RT::System'";
+    }
+
     my (@object_clauses);
     foreach my $obj ( @{ $args{'EquivObjects'} } ) {
         my $type = ref($obj)? ref($obj): $obj;
@@ -526,9 +536,10 @@ sub RolesWithRight {
         push @object_clauses, "($object_clause)";
     }
     # find ACLs that are related to our objects only
-    $query .= " AND (". join( ' OR ', @object_clauses ) .")";
+    $query .= " AND (". join( ' OR ', @object_clauses ) .")"
+        if @object_clauses;
 
-    my $dbh = $self->_Handle->dbh;
+    my $dbh = $RT::Handle->dbh;
     my $roles = $dbh->selectcol_arrayref($query);
     unless ( $roles ) {
         $RT::Logger->warning( $dbh->errstr );

commit 932a5a25a3520f42471e82df5688cf18b26700c4
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Fri Mar 5 14:21:10 2010 +0300

    get rid of _WhoHaveRoleRightSplitted and use RolesWithRights

diff --git a/lib/RT/Users_Overlay.pm b/lib/RT/Users_Overlay.pm
index a2d235c..6d3da78 100755
--- a/lib/RT/Users_Overlay.pm
+++ b/lib/RT/Users_Overlay.pm
@@ -378,7 +378,8 @@ sub WhoHaveRight {
         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 );
@@ -386,8 +387,8 @@ sub WhoHaveRight {
     #XXX: DIRTY HACK
     use DBIx::SearchBuilder::Union;
     my $union = new DBIx::SearchBuilder::Union;
-    $union->add( $_ ) foreach @from_role;
     $union->add( $from_group );
+    $union->add( $from_role );
     %$self = %$union;
     bless $self, ref($union);
 
@@ -409,57 +410,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 );
-    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;
     }
 
-    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 $acl = $self->_JoinACL( %args );
-
-    $self->Limit( ALIAS => $acl,
-                  FIELD => 'PrincipalType',
-                  VALUE => "$groups.Type",
-                  QUOTEVALUE => 0,
-                );
 
     # no system user
     $self->Limit( ALIAS => $self->PrincipalsAlias,
@@ -468,35 +426,21 @@ sub _WhoHaveRoleRightSplitted {
                   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;
-    my $acl = shift;
     my @objects = @_;
 
     my @groups_clauses;
-    my @acl_clauses;
     foreach my $obj ( @objects ) {
         my $type = ref($obj)? ref($obj): $obj;
         my $id;
@@ -508,12 +452,8 @@ sub _RoleClauses {
         # 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

commit f1fb1d5a287e03006fe8b2c81c11097c4c71e2a3
Author: Ruslan Zakirov <ruz at bestpractical.com>
Date:   Fri Mar 5 14:28:42 2010 +0300

    documentation for RolesWithRight method

diff --git a/lib/RT/Principal_Overlay.pm b/lib/RT/Principal_Overlay.pm
index f2279e1..75f89ca 100755
--- a/lib/RT/Principal_Overlay.pm
+++ b/lib/RT/Principal_Overlay.pm
@@ -498,6 +498,21 @@ sub _HasRoleRight
     return 0;
 }
 
+=head2 RolesWithRight
+
+Returns list with names of roles that have right on
+set of objects. Takes Right, EquiveObjects,
+IncludeSystemRights and IncludeSuperusers arguments.
+
+IncludeSystemRights is true by default, rights
+granted on system level are not accouned when option
+is set to false value.
+
+IncludeSuperusers is true by default, SuperUser right
+is not checked if it's set to false value.
+
+=cut
+
 sub RolesWithRight {
     my $self = shift;
     my %args = (

-----------------------------------------------------------------------


More information about the Rt-commit mailing list