Use trunk.
[manu/RT-Extension-ToggleSuperUser.git] / lib / RT / Principal_Vendor.pm
1 no warnings qw(redefine);
2
3 sub _HasGroupRight
4 {
5     my $self = shift;
6     my %args = (
7         Right        => undef,
8         EquivObjects => [],
9         @_
10     );
11     my $right = $args{'Right'};
12
13     my $query =
14       "SELECT ACL.id, ACL.ObjectType, ACL.ObjectId " .
15       "FROM ACL, Principals, CachedGroupMembers WHERE ";
16
17       if ( $self->CurrentUser->UserObj->FirstAttribute('DisableSuperUser') && $self->CurrentUser->UserObj->FirstAttribute('DisableSuperUser')->Content ) {
18           # Only find rights with the name $right
19           $query .= " (ACL.RightName = '$right') ";
20       } else {
21           # Only find superuser or rights with the name $right
22           $query .= " (ACL.RightName = 'SuperUser' OR ACL.RightName = '$right') ";
23       }
24
25       # Never find disabled groups.
26       $query .= "AND Principals.id = ACL.PrincipalId "
27       . "AND Principals.PrincipalType = 'Group' "
28       . "AND Principals.Disabled = 0 "
29
30       # See if the principal is a member of the group recursively or _is the rightholder_
31       # never find recursively disabled group members
32       # also, check to see if the right is being granted _directly_ to this principal,
33       #  as is the case when we want to look up group rights
34       . "AND CachedGroupMembers.GroupId  = ACL.PrincipalId "
35       . "AND CachedGroupMembers.GroupId  = Principals.id "
36       . "AND CachedGroupMembers.MemberId = ". $self->Id ." "
37       . "AND CachedGroupMembers.Disabled = 0 ";
38
39     my @clauses;
40     foreach my $obj ( @{ $args{'EquivObjects'} } ) {
41         my $type = ref( $obj ) || $obj;
42         my $clause = "ACL.ObjectType = '$type'";
43
44         if ( ref($obj) && UNIVERSAL::can($obj, 'id') && $obj->id ) {
45             $clause .= " AND ACL.ObjectId = ". $obj->id;
46         }
47
48         push @clauses, "($clause)";
49     }
50     if ( @clauses ) {
51         $query .= " AND (". join( ' OR ', @clauses ) .")";
52     }
53
54     $self->_Handle->ApplyLimits( \$query, 1 );
55     my ($hit, $obj, $id) = $self->_Handle->FetchResult( $query );
56     return (0) unless $hit;
57
58     $obj .= "-$id" if $id;
59     return (1, $obj);
60 }
61
62 sub _HasRoleRight
63 {
64     my $self = shift;
65     my %args = (
66         Right        => undef,
67         EquivObjects => [],
68         @_
69     );
70     my $right = $args{'Right'};
71
72     my $query =
73       "SELECT ACL.id " .
74       "FROM ACL, Groups, Principals, CachedGroupMembers WHERE "; 
75
76       if ( $self->CurrentUser->UserObj->FirstAttribute('DisableSuperUser') && $self->CurrentUser->UserObj->FirstAttribute('DisableSuperUser')->Content ) {
77           # Only find rights with the name $right
78           $query .= " (ACL.RightName = '$right') ";
79       } else {
80           # Only find superuser or rights with the name $right
81           $query .= " (ACL.RightName = 'SuperUser' OR ACL.RightName = '$right') ";
82       }
83
84       # Never find disabled things
85       $query .= "AND Principals.Disabled = 0 "
86       . "AND CachedGroupMembers.Disabled = 0 "
87
88       # We always grant rights to Groups
89       . "AND Principals.id = Groups.id "
90       . "AND Principals.PrincipalType = 'Group' "
91
92       # See if the principal is a member of the group recursively or _is the rightholder_
93       # never find recursively disabled group members
94       # also, check to see if the right is being granted _directly_ to this principal,
95       #  as is the case when we want to look up group rights
96       . "AND Principals.id = CachedGroupMembers.GroupId "
97       . "AND CachedGroupMembers.MemberId = ". $self->Id ." "
98       . "AND ACL.PrincipalType = Groups.Type ";
99
100     my (@object_clauses);
101     foreach my $obj ( @{ $args{'EquivObjects'} } ) {
102         my $type = ref($obj)? ref($obj): $obj;
103         my $id;
104         $id = $obj->id if ref($obj) && UNIVERSAL::can($obj, 'id') && $obj->id;
105
106         my $object_clause = "ACL.ObjectType = '$type'";
107         $object_clause   .= " AND ACL.ObjectId = $id" if $id;
108         push @object_clauses, "($object_clause)";
109     }
110     # find ACLs that are related to our objects only
111     $query .= " AND (". join( ' OR ', @object_clauses ) .")";
112
113     # because of mysql bug in versions up to 5.0.45 we do one query per object
114     # each query should be faster on any DB as it uses indexes more effective
115     foreach my $obj ( @{ $args{'EquivObjects'} } ) {
116         my $type = ref($obj)? ref($obj): $obj;
117         my $id;
118         $id = $obj->id if ref($obj) && UNIVERSAL::can($obj, 'id') && $obj->id;
119
120         my $tmp = $query;
121         $tmp .= " AND Groups.Domain = '$type-Role'";
122         # XXX: Groups.Instance is VARCHAR in DB, we should quote value
123         # if we want mysql 4.0 use indexes here. we MUST convert that
124         # field to integer and drop this quotes.
125         $tmp .= " AND Groups.Instance = '$id'" if $id;
126
127         $self->_Handle->ApplyLimits( \$tmp, 1 );
128         my ($hit) = $self->_Handle->FetchResult( $tmp );
129         return (1) if $hit;
130     }
131
132     return 0;
133 }
134
135
136 1;