+sub _HasGroupRightQuery {
+ my $self = shift;
+ my %args = (
+ Right => undef,
+ EquivObjects => [],
+ @_
+ );
+
+ my $query
+ = "FROM ACL, Principals, CachedGroupMembers WHERE "
+
+ # Never find disabled groups.
+ . "Principals.id = ACL.PrincipalId "
+ . "AND Principals.PrincipalType = 'Group' "
+ . "AND Principals.Disabled = 0 "
+
+# See if the principal is a member of the group recursively or _is the rightholder_
+# never find recursively disabled group members
+# also, check to see if the right is being granted _directly_ to this principal,
+# as is the case when we want to look up group rights
+ . "AND CachedGroupMembers.GroupId = ACL.PrincipalId "
+ . "AND CachedGroupMembers.GroupId = Principals.id "
+ . "AND CachedGroupMembers.MemberId = ". $self->Id . " "
+ . "AND CachedGroupMembers.Disabled = 0 ";
+
+ my @clauses;
+ foreach my $obj ( @{ $args{'EquivObjects'} } ) {
+ my $type = ref($obj) || $obj;
+ my $clause = "ACL.ObjectType = '$type'";
+
+ if ( defined eval { $obj->id } ) { # it might be 0
+ $clause .= " AND ACL.ObjectId = " . $obj->id;
+ }
+
+ push @clauses, "($clause)";
+ }
+ if (@clauses) {
+ $query .= " AND (" . join( ' OR ', @clauses ) . ")";
+ }
+ if ( my $right = $args{'Right'} ) {
+ # Only find superuser or rights with the name $right
+ $query .= " AND (ACL.RightName = 'SuperUser' "
+ . ( $right ne 'SuperUser' ? "OR ACL.RightName = '$right'" : '' )
+ . ") ";
+ }
+ return $query;
+}
+
+sub _HasRoleRight {
+ my $self = shift;
+ my %args = ( Right => undef,
+ EquivObjects => [],
+ @_
+ );
+
+ my @roles = $self->RolesWithRight(%args);
+ return 0 unless @roles;
+
+ my $query = "SELECT Groups.id "
+ . $self->_HasRoleRightQuery( %args, Roles => \@roles );
+
+ $self->_Handle->ApplyLimits( \$query, 1 );
+ my ($hit) = $self->_Handle->FetchResult($query);
+ return (1) if $hit;
+
+ return 0;
+}
+
+sub _HasRoleRightQuery {
+ my $self = shift;
+ my %args = ( Right => undef,
+ EquivObjects => [],
+ Roles => undef,
+ @_
+ );
+
+ my $query =
+ " FROM Groups, Principals, CachedGroupMembers WHERE "
+
+ # Never find disabled things
+ . "Principals.Disabled = 0 " . "AND CachedGroupMembers.Disabled = 0 "
+
+ # We always grant rights to Groups
+ . "AND Principals.id = Groups.id "
+ . "AND Principals.PrincipalType = 'Group' "
+
+# See if the principal is a member of the group recursively or _is the rightholder_
+# never find recursively disabled group members
+# also, check to see if the right is being granted _directly_ to this principal,
+# as is the case when we want to look up group rights
+ . "AND Principals.id = CachedGroupMembers.GroupId "
+ . "AND CachedGroupMembers.MemberId = " . $self->Id . " "
+ ;
+
+ if ( $args{'Roles'} ) {
+ $query .= "AND (" . join( ' OR ', map "Groups.Type = '$_'", @{ $args{'Roles'} } ) . ")";
+ }
+
+ my (@object_clauses);
+ foreach my $obj ( @{ $args{'EquivObjects'} } ) {
+ my $type = ref($obj) ? ref($obj) : $obj;
+
+ 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.
+ if ( my $id = eval { $obj->id } ) {
+ $clause .= " AND Groups.Instance = '$id'";
+ }
+ push @object_clauses, "($clause)";
+ }
+ $query .= " AND (" . join( ' OR ', @object_clauses ) . ")";
+ return $query;
+}
+
+=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 systemwide are ignored when IncludeSystemRights
+is set to a false value.