[Rt-commit] r18349 - in rt/3.8/branches/html-css-cleanup: . etc lib/RT lib/RT/Interface sbin share/html/Elements/RT__Ticket share/html/NoAuth/css/web2 share/html/Search share/html/Ticket share/html/Widgets

falcone at bestpractical.com falcone at bestpractical.com
Thu Feb 12 15:38:13 EST 2009


Author: falcone
Date: Thu Feb 12 15:38:12 2009
New Revision: 18349

Added:
   rt/3.8/branches/html-css-cleanup/etc/schema.mysql-4.0   (props changed)
      - copied unchanged from r17726, /rt/3.8/branches/html-css-cleanup/etc/schema.mysql
   rt/3.8/branches/html-css-cleanup/t/validator/
   rt/3.8/branches/html-css-cleanup/t/validator/group_members.t
Removed:
   rt/3.8/branches/html-css-cleanup/etc/schema.mysql
Modified:
   rt/3.8/branches/html-css-cleanup/   (props changed)
   rt/3.8/branches/html-css-cleanup/Makefile.in
   rt/3.8/branches/html-css-cleanup/etc/RT_Config.pm.in
   rt/3.8/branches/html-css-cleanup/lib/RT/Interface/Email.pm
   rt/3.8/branches/html-css-cleanup/lib/RT/Principal_Overlay.pm
   rt/3.8/branches/html-css-cleanup/lib/RT/Record.pm
   rt/3.8/branches/html-css-cleanup/sbin/rt-validator.in
   rt/3.8/branches/html-css-cleanup/share/html/Elements/RT__Ticket/ColumnMap
   rt/3.8/branches/html-css-cleanup/share/html/NoAuth/css/web2/msie.css
   rt/3.8/branches/html-css-cleanup/share/html/Search/Chart.html
   rt/3.8/branches/html-css-cleanup/share/html/Ticket/Update.html
   rt/3.8/branches/html-css-cleanup/share/html/Widgets/ComboBox

Log:
- Merge //mirror/bps-public/rt/3.8/trunk to //mirror/bps-public/rt/3.8/branches/html-css-cleanup

Modified: rt/3.8/branches/html-css-cleanup/Makefile.in
==============================================================================
--- rt/3.8/branches/html-css-cleanup/Makefile.in	(original)
+++ rt/3.8/branches/html-css-cleanup/Makefile.in	Thu Feb 12 15:38:12 2009
@@ -167,7 +167,8 @@
 				rt-server \
 				rt-test-dependencies \
 				rt-clean-sessions \
-				rt-shredder
+				rt-shredder \
+				rt-validator
 
 
 ETC_FILES		=	acl.Informix \
@@ -178,7 +179,7 @@
 			schema.Informix \
 			schema.Pg \
 			schema.Oracle \
-			schema.mysql \
+			schema.mysql-4.0 \
 			schema.mysql-4.1 \
 			schema.Sybase \
 			schema.SQLite \

Modified: rt/3.8/branches/html-css-cleanup/etc/RT_Config.pm.in
==============================================================================
--- rt/3.8/branches/html-css-cleanup/etc/RT_Config.pm.in	(original)
+++ rt/3.8/branches/html-css-cleanup/etc/RT_Config.pm.in	Thu Feb 12 15:38:12 2009
@@ -259,7 +259,10 @@
 =item C<$RTAddressRegexp> 
 
 C<$RTAddressRegexp> is used to make sure RT doesn't add itself as a ticket CC if
-the setting above is enabled.
+the setting above is enabled.  It is important that you set this to a 
+regular expression that matches all addresses used by your RT.  This lets RT
+avoid sending mail to itself.  It will also hide RT addresses from the list of 
+"One-time Cc" and Bcc lists on ticket reply.
 
 =cut
 
@@ -688,14 +691,12 @@
 
 =item C<$LogStackTraces>
 
-If set to a log level then logging will include stack
-traces for messages with level equal to or greater than
-specified.
-
-NOTICE: Stack traces include parameters that functions or methods
-were called wiht. It is possible for stack trace logging to reveal
-sensitive information such as passwords or ticket content in your
-logs.
+If set to a log level then logging will include stack traces for
+messages with level equal to or greater than specified.
+
+NOTICE: Stack traces include parameters supplied to functions or
+methods. It is possible for stack trace logging to reveal sensitive
+information such as passwords or ticket content in your logs.
 
 =cut
 

Modified: rt/3.8/branches/html-css-cleanup/lib/RT/Interface/Email.pm
==============================================================================
--- rt/3.8/branches/html-css-cleanup/lib/RT/Interface/Email.pm	(original)
+++ rt/3.8/branches/html-css-cleanup/lib/RT/Interface/Email.pm	Thu Feb 12 15:38:12 2009
@@ -435,9 +435,8 @@
 
         # duplicate head as we want drop Bcc field
         my $head = $args{'Entity'}->head->dup;
-        my @recipients = map $_->address, Email::Address->parse(
-            map $head->get($_), qw(To Cc Bcc)
-        );
+        my @recipients = map $_->address, map 
+            Email::Address->parse($head->get($_)), qw(To Cc Bcc);                       
         $head->delete('Bcc');
 
         my $sender = RT->Config->Get('SMTPFrom')

Modified: rt/3.8/branches/html-css-cleanup/lib/RT/Principal_Overlay.pm
==============================================================================
--- rt/3.8/branches/html-css-cleanup/lib/RT/Principal_Overlay.pm	(original)
+++ rt/3.8/branches/html-css-cleanup/lib/RT/Principal_Overlay.pm	Thu Feb 12 15:38:12 2009
@@ -323,23 +323,13 @@
         return (undef);
     }
 
-    # If this object is a ticket, we care about ticket roles and queue roles
-    if ( UNIVERSAL::isa( $args{'Object'} => 'RT::Ticket' ) ) {
-         
 
-
-        # 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.
-        unshift @{ $args{'EquivObjects'} }, $args{'Object'}->ACLEquivalenceObjects;
-
-    }
+    unshift @{ $args{'EquivObjects'} }, $args{'Object'}->ACLEquivalenceObjects;
 
     unshift @{ $args{'EquivObjects'} }, $RT::System
         unless $self->can('_IsOverrideGlobalACL')
                && $self->_IsOverrideGlobalACL( $args{'Object'} );
 
-
     # {{{ If we've cached a win or loss for this lookup say so
 
     # Construct a hashkeys to cache decisions:

Modified: rt/3.8/branches/html-css-cleanup/lib/RT/Record.pm
==============================================================================
--- rt/3.8/branches/html-css-cleanup/lib/RT/Record.pm	(original)
+++ rt/3.8/branches/html-css-cleanup/lib/RT/Record.pm	Thu Feb 12 15:38:12 2009
@@ -1889,15 +1889,9 @@
     return $cf;
 }
 
+sub ACLEquivalenceObjects { } 
 
-# }}}
-
-# }}}
-
-# }}}
-
-sub BasicColumns {
-}
+sub BasicColumns { }
 
 sub WikiBase {
     return RT->Config->Get('WebPath'). "/index.html?q=";

Modified: rt/3.8/branches/html-css-cleanup/sbin/rt-validator.in
==============================================================================
--- rt/3.8/branches/html-css-cleanup/sbin/rt-validator.in	(original)
+++ rt/3.8/branches/html-css-cleanup/sbin/rt-validator.in	Thu Feb 12 15:38:12 2009
@@ -130,7 +130,7 @@
 RT::Init();
 
 my $dbh = $RT::Handle->dbh;
-my $db_type = $RT::DatabaseType;
+my $db_type = RT->Config->Get('DatabaseType');
 
 my %TYPE = (
     'Transactions.Field'    => 'text',
@@ -497,10 +497,11 @@
     );
 
     # for every CGM where ImmediateParentId != GroupId there should be
-    # matching parent record 
+    # matching parent record (first level) 
     check_integrity(
-        CachedGroupMembers => ['ImmediateParentId', 'MemberId', 'Via'],
-        CachedGroupMembers => ['GroupId', 'MemberId', 'id'],
+        CachedGroupMembers => ['ImmediateParentId', 'MemberId'],
+        CachedGroupMembers => ['GroupId', 'MemberId'],
+        join_condition => 't.Via = t.id',
         condition => 's.ImmediateParentId != s.GroupId',
         action => sub {
             my $id = shift;
@@ -516,8 +517,8 @@
     # for every CGM where ImmediateParentId != GroupId there should be
     # matching "grand" parent record
     check_integrity(
-        CachedGroupMembers => ['GroupId', 'ImmediateParentId'],
-        CachedGroupMembers => ['GroupId', 'MemberId'],
+        CachedGroupMembers => ['GroupId', 'ImmediateParentId', 'Via'],
+        CachedGroupMembers => ['GroupId', 'MemberId', 'id'],
         condition => 's.ImmediateParentId != s.GroupId',
         action => sub {
             my $id = shift;
@@ -531,25 +532,23 @@
     );
 
     # CHECK recursive records:
-    # if we have G1 - (M1 == G2) - M2 then we should have G1 - M2 record with
-    # Via = CGM2.id and IP = CGM2.G
-    # Disabled field should be fixed separatedly
+    # if we have CGM1 (G1,M1,V1,IP1) then for every GM2(G2, M2), where G2 == M1,
+    # we should have CGM3 where G3 = G1, M3 = M2, V3 = ID1, IP3 = M1
     {
         my $query = <<END;
-SELECT grand.GroupId, parent.MemberId, parent.id AS Via,
-    parent.GroupId AS ImmediateParentId, grand.Disabled, parent.Disabled
+SELECT cgm1.GroupId, gm2.MemberId, cgm1.id AS Via,
+    cgm1.MemberId AS ImmediateParentId, cgm1.Disabled
 FROM
-    CachedGroupMembers grand
-    CROSS JOIN CachedGroupMembers parent
-    LEFT JOIN CachedGroupMembers grand_child ON (
-        grand_child.GroupId = grand.GroupId
-        AND grand_child.MemberId = parent.MemberId
-        AND grand_child.Via = parent.id
-        AND grand_child.ImmediateParentId = parent.GroupId )
-WHERE grand.GroupId != grand.MemberId
-AND parent.GroupId != parent.MemberId
-AND parent.GroupId = grand.MemberId
-AND grand_child.id IS NULL
+    CachedGroupMembers cgm1
+    CROSS JOIN GroupMembers gm2
+    LEFT JOIN CachedGroupMembers cgm3 ON (
+            cgm3.GroupId           = cgm1.GroupId
+        AND cgm3.MemberId          = gm2.MemberId
+        AND cgm3.Via               = cgm1.id
+        AND cgm3.ImmediateParentId = cgm1.MemberId )
+WHERE cgm1.GroupId != cgm1.MemberId
+AND gm2.GroupId = cgm1.MemberId
+AND cgm3.id IS NULL
 END
 
         my $action = sub {
@@ -562,12 +561,12 @@
         };
 
         my $sth = execute_query( $query );
-        while ( my ($g, $m, $via, $ip, $gdis, $pdis) = $sth->fetchrow_array ) {
-            print STDERR "Principal #$m is member of #$ip when #$ip is member of #$g,\n";
-            print STDERR "but there is no cached GM record that $m is member of #$g.\n";
+        while ( my ($g, $m, $via, $ip, $dis) = $sth->fetchrow_array ) {
+            print STDERR "Principal #$m is member of #$ip when #$ip is member of #$g,";
+            print STDERR " but there is no cached GM record that $m is member of #$g.\n";
             $action->(
                 GroupId => $g, MemberId => $m, Via => $via,
-                ImmediateParentId => $ip, Disabled => $gdis || $pdis,
+                ImmediateParentId => $ip, Disabled => $dis,
             );
         }
     }
@@ -650,7 +649,7 @@
     );
     # type = DelWatcher
     check_integrity(
-        'Transactions', 'OldValue' => 'Users', 'id',
+        'Transactions', 'OldValue' => 'Principals', 'id',
         condition   => 's.Type = ?',
         bind_values => [ 'DelWatcher' ],
         action => sub {
@@ -665,7 +664,7 @@
     );
     # type = AddWatcher
     check_integrity(
-        'Transactions', 'NewValue' => 'Users', 'id',
+        'Transactions', 'NewValue' => 'Principals', 'id',
         condition   => 's.Type = ?',
         bind_values => [ 'AddWatcher' ],
         action => sub {
@@ -822,11 +821,10 @@
             my $query = <<END;
 SELECT m.id, g.id, g.Instance
 FROM
-    Groups g JOIN $table m
+    Groups g JOIN $table m ON g.id = m.$column
 WHERE
     g.Domain = ?
     AND g.Type = ?
-    AND g.id = m.$column
 END
             my $action = sub {
                 my ($gid, $uid) = @_;

Modified: rt/3.8/branches/html-css-cleanup/share/html/Elements/RT__Ticket/ColumnMap
==============================================================================
--- rt/3.8/branches/html-css-cleanup/share/html/Elements/RT__Ticket/ColumnMap	(original)
+++ rt/3.8/branches/html-css-cleanup/share/html/Elements/RT__Ticket/ColumnMap	Thu Feb 12 15:38:12 2009
@@ -113,7 +113,12 @@
                     return \'<em>', loc('(pending approval)'), \'</em>';
                 }
                 else {
-                    return \'<em>', loc('(pending [quant,_1,other ticket])',$count), \'</em>';
+                    my $Query = "DependedOnBy = " . $Ticket->id;
+                    $Query .= " AND (" . join(" OR ", map { "Status = '$_'" } RT::Queue->ActiveStatusArray) . ")";
+
+                    my $SearchURL = RT->Config->Get('WebPath') . '/Search/Results.html?' . $m->comp('/Elements/QueryString', Query => $Query);
+
+                    return \'<a href="',$SearchURL,\'">', loc('(pending [quant,_1,other ticket])',$count), \'</a>';
                 }
             }
             else {

Modified: rt/3.8/branches/html-css-cleanup/share/html/NoAuth/css/web2/msie.css
==============================================================================
--- rt/3.8/branches/html-css-cleanup/share/html/NoAuth/css/web2/msie.css	(original)
+++ rt/3.8/branches/html-css-cleanup/share/html/NoAuth/css/web2/msie.css	Thu Feb 12 15:38:12 2009
@@ -129,6 +129,11 @@
 .titlebox .titlebox .titlebox-title .right{
     top: 0.25em;
 }
+
+.combobox {
+    float: left;
+}
+
 .combobox .combo-button {
     color: ButtonText;
     padding: 0;

Modified: rt/3.8/branches/html-css-cleanup/share/html/Search/Chart.html
==============================================================================
--- rt/3.8/branches/html-css-cleanup/share/html/Search/Chart.html	(original)
+++ rt/3.8/branches/html-css-cleanup/share/html/Search/Chart.html	Thu Feb 12 15:38:12 2009
@@ -55,7 +55,22 @@
 <%init>
 $ARGS{SecondaryGroupBy} ||= '';
 
-my $title = loc( "Search results grouped by [_1]", loc($PrimaryGroupBy) );
+# FIXME: should be factored with RT::Report::Tickets::Label :(
+my $PrimaryGroupByLabel;
+if ( $PrimaryGroupBy =~ /^(?:CF|CustomField)\.{(.*)}$/ ) {
+    my $cf = $1;
+    if ( $cf =~ /\D/ ) {
+        $PrimaryGroupByLabel = loc( "custom field '[_1]'", $cf );
+    } else {
+        my $obj = RT::CustomField->new( $session{'CurrentUser'} );
+        $obj->Load( $cf );
+        $PrimaryGroupByLabel = loc( "custom field '[_1]'", $obj->Name );
+    }
+} else {
+    $PrimaryGroupByLabel = loc( $PrimaryGroupBy );
+}
+
+my $title = loc( "Search results grouped by [_1]", $PrimaryGroupByLabel );
 
 my $saved_search = $m->comp( '/Widgets/SavedSearch:new',
     SearchType   => 'Chart',

Modified: rt/3.8/branches/html-css-cleanup/share/html/Ticket/Update.html
==============================================================================
--- rt/3.8/branches/html-css-cleanup/share/html/Ticket/Update.html	(original)
+++ rt/3.8/branches/html-css-cleanup/share/html/Ticket/Update.html	Thu Feb 12 15:38:12 2009
@@ -100,6 +100,7 @@
 
 % if (my $TxnCFs = $TicketObj->TransactionCustomFields) {
 %    while (my $CF = $TxnCFs->Next()) {
+%        next unless $CF->CurrentUserHasRight('ModifyCustomField');
 <tr>
 <td class="label"><% $CF->Name %>:</td>
 <td><& /Elements/EditCustomField, CustomField => $CF, NamePrefix =>

Modified: rt/3.8/branches/html-css-cleanup/share/html/Widgets/ComboBox
==============================================================================
--- rt/3.8/branches/html-css-cleanup/share/html/Widgets/ComboBox	(original)
+++ rt/3.8/branches/html-css-cleanup/share/html/Widgets/ComboBox	Thu Feb 12 15:38:12 2009
@@ -56,7 +56,7 @@
         <option value="<%$value%>"><% $value%></option>
 % }
 </select>
-</span>
+</div>
 <script language="javascript"><!--
 ComboBox_InitWith('<% $Name %>');
 //--></script>

Added: rt/3.8/branches/html-css-cleanup/t/validator/group_members.t
==============================================================================
--- (empty file)
+++ rt/3.8/branches/html-css-cleanup/t/validator/group_members.t	Thu Feb 12 15:38:12 2009
@@ -0,0 +1,179 @@
+#!/usr/bin/perl -w
+
+use strict;
+use warnings;
+
+use Test::More tests => 60;
+use RT::Test;
+
+sub load_or_create_group {
+    my $name = shift;
+    my %args = (@_);
+
+    my $group = RT::Group->new( $RT::SystemUser );
+    $group->LoadUserDefinedGroup( $name );
+    unless ( $group->id ) {
+        my ($id, $msg) = $group->CreateUserDefinedGroup(
+            Name => $name,
+        );
+        die "$msg" unless $id;
+    }
+
+    if ( $args{Members} ) {
+        my $cur = $group->MembersObj;
+        while ( my $entry = $cur->Next ) {
+            my ($status, $msg) = $entry->Delete;
+            die "$msg" unless $status;
+        }
+
+        foreach my $new ( @{ $args{Members} } ) {
+            my ($status, $msg) = $group->AddMember(
+                ref($new)? $new->id : $new,
+            );
+            die "$msg" unless $status;
+        }
+    }
+    
+    return $group;
+}
+
+my $validator_path = "$RT::SbinPath/rt-validator";
+sub run_validator {
+    my %args = (check => 1, resolve => 0, force => 1, @_ );
+
+    my $cmd = $validator_path;
+    die "Couldn't find $cmd command" unless -f $cmd;
+
+    while( my ($k,$v) = each %args ) {
+        next unless $v;
+        $cmd .= " --$k '$v'";
+    }
+    $cmd .= ' 2>&1';
+
+    require IPC::Open2;
+    my ($child_out, $child_in);
+    my $pid = IPC::Open2::open2($child_out, $child_in, $cmd);
+    close $child_in;
+
+    my $result = do { local $/; <$child_out> };
+    close $child_out;
+    waitpid $pid, 0;
+
+    DBIx::SearchBuilder::Record::Cachable->FlushCache
+        if $args{'resolve'};
+
+    return ($?, $result);
+}
+
+{
+    my ($ecode, $res) = run_validator();
+    is $res, '', 'empty result';
+}
+
+{
+    my $group = load_or_create_group('test', Members => [] );
+    ok $group, "loaded or created a group";
+
+    my ($ecode, $res) = run_validator();
+    is $res, '', 'empty result';
+}
+
+# G1 -> G2
+{
+    my $group1 = load_or_create_group( 'test1', Members => [] );
+    ok $group1, "loaded or created a group";
+
+    my $group2 = load_or_create_group( 'test2', Members => [ $group1 ]);
+    ok $group2, "loaded or created a group";
+
+    ok $group2->HasMember( $group1->id ), "has member";
+    ok $group2->HasMemberRecursively( $group1->id ), "has member";
+
+    my ($ecode, $res) = run_validator();
+    is $res, '', 'empty result';
+
+    $RT::Handle->dbh->do("DELETE FROM CachedGroupMembers");
+    DBIx::SearchBuilder::Record::Cachable->FlushCache;
+    ok !$group2->HasMemberRecursively( $group1->id ), "has no member, broken DB";
+
+    ($ecode, $res) = run_validator(resolve => 1);
+
+    ok $group2->HasMember( $group1->id ), "has member";
+    ok $group2->HasMemberRecursively( $group1->id ), "has member";
+
+    ($ecode, $res) = run_validator();
+    is $res, '', 'empty result';
+}
+
+# G1 <- G2 <- G3 <- G4 <- G5
+{
+    my @groups;
+    for (1..5) {
+        my $child = @groups? $groups[-1]: undef;
+
+        my $group = load_or_create_group( 'test'. $_, Members => [ $child? ($child): () ] );
+        ok $group, "loaded or created a group";
+
+        ok $group->HasMember( $child->id ), "has member"
+            if $child;
+        ok $group->HasMemberRecursively( $_->id ), "has member"
+            foreach @groups;
+
+        push @groups, $group;
+    }
+
+    my ($ecode, $res) = run_validator();
+    is $res, '', 'empty result';
+
+    $RT::Handle->dbh->do("DELETE FROM CachedGroupMembers");
+    DBIx::SearchBuilder::Record::Cachable->FlushCache;
+
+    ok !$groups[1]->HasMemberRecursively( $groups[0]->id ), "has no member, broken DB";
+
+    ($ecode, $res) = run_validator(resolve => 1);
+
+    for ( my $i = 1; $i < @groups; $i++ ) {
+        ok $groups[$i]->HasMember( $groups[$i-1]->id ), "has member";
+        ok $groups[$i]->HasMemberRecursively( $groups[$_]->id ), "has member"
+            foreach 0..$i-1;
+    }
+
+    ($ecode, $res) = run_validator();
+    is $res, '', 'empty result';
+}
+
+# G1 <- (G2, G3, G4, G5)
+{
+    my @groups;
+    for (2..5) {
+        my $group = load_or_create_group( 'test'. $_, Members => [] );
+        ok $group, "loaded or created a group";
+        push @groups, $group;
+    }
+
+    my $parent = load_or_create_group( 'test1', Members => \@groups );
+    ok $parent, "loaded or created a group";
+
+    my ($ecode, $res) = run_validator();
+    is $res, '', 'empty result';
+}
+
+# G1 <- (G2, G3, G4) <- G5
+{
+    my $gchild = load_or_create_group( 'test5', Members => [] );
+    ok $gchild, "loaded or created a group";
+    
+    my @groups;
+    for (2..4) {
+        my $group = load_or_create_group( 'test'. $_, Members => [ $gchild ] );
+        ok $group, "loaded or created a group";
+        push @groups, $group;
+    }
+
+    my $parent = load_or_create_group( 'test1', Members => \@groups );
+    ok $parent, "loaded or created a group";
+
+    my ($ecode, $res) = run_validator();
+    is $res, '', 'empty result';
+}
+


More information about the Rt-commit mailing list