[Rt-commit] rt branch, master, updated. rt-4.0.1-393-g8ee5c55

Alex Vandiver alexmv at bestpractical.com
Thu Aug 4 21:21:29 EDT 2011


The branch, master has been updated
       via  8ee5c5576b948e95e32eedbe82b4461fec52d67e (commit)
       via  88fe4cda74fef7a79333ec0f843d9e781fe7bac4 (commit)
       via  1fa76238bf522984d0d8afad3b13b44492961d79 (commit)
       via  dbb313915c65f1d24e36f4defa02311e30da7a10 (commit)
       via  f75bbeab6f3ab55e544edc5abda078d421b58fc0 (commit)
       via  aa660dbe7e5e8e55451544350b0b44583156c3d7 (commit)
       via  f2d6499d76e7e102e312506920325ccf1c0d75f0 (commit)
       via  89332a9567d2bd07882df55cc7d77956cfc57143 (commit)
       via  96434ce0de13a7a6d2858b2696d6b8bc6bacf4a8 (commit)
       via  edd07b4279610bd45becc761581edfb39f0c4a05 (commit)
       via  c0a2d2afbdbed6d823e626bb21abf1f30b70ab4b (commit)
       via  5f813981918c083d2d72932da2db45ec0dc48c52 (commit)
       via  bf3c6abcffe575b73994d2ead4b37c7d0e819282 (commit)
       via  09bdfde0614e6cb57ee61086f9cbc705898c9e4e (commit)
       via  541e71b72ee56ba67e613df1a92694a0a5345641 (commit)
       via  ab504002e8692c9ab9fe2504af27467a9d260cb4 (commit)
       via  c907226c4c3929a4bb29cfb9fa8050b732042b31 (commit)
       via  350317d60b6e086a80ba2a44220abade3db32897 (commit)
       via  a905eb46c3a4d74e42a412df587fea0413dc025f (commit)
       via  86857277fe240a4701f305b0fb831dca255a95b5 (commit)
       via  8962dc6d9d14e05ee97e90667fbf584f08ff71de (commit)
       via  66f3299ee7c1853b219c4e07b734a4f0519f6b18 (commit)
       via  6a036f543b81f20aad26afe768d27268f6b58de9 (commit)
       via  c2ca8f1a6a6335af2fd03e08f2238e4bbb29ff3f (commit)
       via  622b9ca98e5afd491a0a48a59e2d28dfd1797375 (commit)
       via  c51828dddca5e340ca266df835d1e7ea51708dfb (commit)
       via  4e728fe880723297fe6a9800a0bc418e853ed46b (commit)
       via  eef259a21f0a1867fd54d32f4ba3736751b97dee (commit)
       via  e3fb175021fcaac0447bf7d74c57baa5bf3e60af (commit)
       via  ed3fb32bf2c0168e37b968baf9d31c68c11595d4 (commit)
       via  e712769e74a02ff9baff5ce86e1be0b4dddca549 (commit)
       via  662bde0eb24e97780f691e99f80902eeb9ab6ca1 (commit)
       via  da9976a87d50a4326ea1743e4e0ff1c3af0463f7 (commit)
       via  f3fc75933b49195cf1d03f912642c6dbc4dfe5ae (commit)
       via  c4dc4014e82fccc914282ab46014397103f94871 (commit)
       via  39e08fefe21c63ef1a719a7c726159ec9b6b29df (commit)
       via  839fdd8356ea9374955fb3ac8badb210bd8c34f1 (commit)
       via  5cf4e7ca7369d126ba9488b2f14fb4cc971e793f (commit)
       via  e061bdb04edc5b52c3671a37128c469107e1b409 (commit)
       via  dad4ed46cd388980ca5950a326b27d525ec2c896 (commit)
       via  54b3703417b35a63f03e00f28b91cf062e289516 (commit)
       via  f86db6038bbf37da71f2dcb33bd33744be1449ce (commit)
       via  7389a12ef85f15c74d681435670a812d78348fd7 (commit)
       via  ca31aacb4ff243c2a58bd0168beb7b6c04db9411 (commit)
       via  7101be5e6b2f16c1ecd0cdee593f0237434f7721 (commit)
       via  a77f514fa386a83480a413c1c842d1549185e94c (commit)
       via  431652203ec8ed71b10164dec7e80aeb75130021 (commit)
       via  6f4825424763a07e3a3f01517b90adfdfca1dcef (commit)
       via  0e987c99d177bd91a88393c267b3c1ddbccef4ae (commit)
       via  9173f453901cc079b90bc9796a1ef0b69363ff84 (commit)
       via  6e9d8af5ff21681adbc80cb32d333139f3650dfa (commit)
       via  abb70d9f01f121a00c0aecdf662c3d70e765ba71 (commit)
       via  a23c4ed7b610f9d6da85bf7267dae800e2c5b675 (commit)
       via  a352dcd02801695192a80b5b24ba0fa7b0953503 (commit)
       via  727a221a6594c51e8eda9c09a3625aed4b4af11e (commit)
       via  9d37787909d935d0fcd1f4d8f97705436f9dad27 (commit)
       via  3550d52c5e98956e0b7b6500cad75361671aa279 (commit)
       via  e02445cabb4d93e9518f070d3cb06eaf3b039206 (commit)
       via  c265cda315bd395d6d015cb3298d8aaabe124027 (commit)
       via  3da1ac60eb4dbfeec1c403eac0f48e6f0a6996c5 (commit)
       via  0bffa2a69e697a24817e79cce64021041538ab66 (commit)
       via  ab6203b1cda0e32e02d318dc9e083536a6f38eab (commit)
       via  d258f535e789a62590858640df387af331da54bd (commit)
       via  c5a3dd2406ae4cab3e300dd4af2ee104a176662d (commit)
       via  469aff87d02d1fa6115c55cf93f5350274e3be96 (commit)
       via  d13be25f579c898303e5e027498bce07597ce79d (commit)
       via  415d6c197467f1e21d81bea2f2486b00b356d17c (commit)
       via  5339220b76531c88dfa2a3d13b6dc4cbbffa2f03 (commit)
       via  6e18d872b061e1f07c9f00875ab5ad78a71448c6 (commit)
       via  50b71988c792997a74994936c078f96c15ecb80f (commit)
       via  e1675b1031c2d3e9d2bba444547929134c8e10ab (commit)
       via  cd653d8cd9b28b4fec9d58d2b42dd752def8a964 (commit)
       via  da488bb4e161632c3e6d750dbf9c2465b367c255 (commit)
       via  2e85388e291dffa14b9817d0bb1305d1b4be5b0f (commit)
       via  f6cb772b25445c69f3024ede7a020d3657134d1d (commit)
       via  9cdbe85361145fe3b058157862ad30f1e5966876 (commit)
       via  66262242cc17df86f6e5ab69b9518de564fac96e (commit)
       via  db7b47776c8e8747bd8869af24ba21fa0581784a (commit)
       via  0707c1866ed8b1556ab29a5abd9b2668302d0788 (commit)
       via  9b4f9541312680e57355060e56198f7db16fd27d (commit)
       via  86a78900a79961dc4bc0e67a30f70e2016356599 (commit)
       via  a3438d7e00940b0e05839b8e5ec8e74a5e994b2a (commit)
       via  00746c072bfdd4615593fcd1867085ffea741f1a (commit)
       via  4f94d8c95604a2c5d612f3ee147f492b9d15bd94 (commit)
       via  47b1c48129a77fe9ef6e6ad69e7860ea27a3e200 (commit)
       via  7c85c01001ba272fb8dc7cbe7a8f971b412dafbe (commit)
       via  7441da04c0e1066e47d10165d52b01e394eab2d4 (commit)
       via  54c53a739e63a45a37f721a100ff506c38694b32 (commit)
       via  c246bb9118560d16f735f3d9586efddd35ea68da (commit)
       via  e5b1ebaae29cb810cefc1a14fc30511eacc0a072 (commit)
       via  308acad81619e80a9ee54da9db7030c0e78af231 (commit)
       via  f9a7aadd15f4d534e2ffb22bfaafa4ddd6ac04f7 (commit)
       via  4b264c9a632ec3a9916e51afabe0472ecde9a888 (commit)
       via  5f6509da75d9845536b9faafe1adbbfaec236fbe (commit)
       via  9506dccc4700024b3ab86741e7100d27eb13b7d6 (commit)
       via  dc57120b621efa4e3f99a0319944f99885d9d85a (commit)
       via  4f9162d82ad9b66d9f31a6e61f52f31def89beb3 (commit)
       via  6242ba95572bc860e734e478a0b6cbcfd9a3983b (commit)
       via  6fd2cb6c9d25fb4e761b439065837b23c7d1f5a9 (commit)
       via  8268325664c28bcc1fd4dc5bb5b45b95f376ee7a (commit)
       via  e212b4ac8a7d901bb5baccfb2d7750e303f176ea (commit)
       via  24e10893b834a15675a63757219ad03a3a51eb15 (commit)
       via  ccafbd233e4f50bd8ef1889949e91dc6190f495b (commit)
       via  1a12831804477b5cdbf91bcbf7169cd7e31ada52 (commit)
       via  8087bb0aece69c0c7e358b5ffcc3ab4b5cf769ec (commit)
       via  61db454cc0084b69339c32d1ccfd7f1daff16914 (commit)
       via  54f7ca556f6590bf96771bbd02ec10d8588e49e4 (commit)
       via  84f1cecaae95468d83d8fa2d8e3c6d3714357060 (commit)
       via  a324304cd60e1b04c474fe532bae9701e015552f (commit)
       via  ff09564fc054be472cfb900bb0d0d52b65fb7eeb (commit)
       via  8071fe96d041120157c2093f4a66d5bd5b275e22 (commit)
       via  d3341b787e3a734c441596b84ce621339f327851 (commit)
       via  bba3baa07423b65ee04ba5d12a65d5cb795e6dbf (commit)
       via  5e026242a46c4e085e0516e8f2eb6b3a5fd18ce5 (commit)
       via  3e3a65f30827fb606615ff045f984cb136f3a8c9 (commit)
       via  ad27e2af46acbd0fd4b1b124783047016c4421ee (commit)
       via  d54b01b60699113c26ee8f587af98459a4814f74 (commit)
       via  80c1de6fe05a74b026a6943d3789e14b954d1411 (commit)
       via  38962236130108bd333aa6ff782c714fffec496e (commit)
       via  a920952a6873c34f77c94170b409d2bb117e2169 (commit)
       via  9b345a44a60607247d0197be9ef9e71ce66c1a8f (commit)
       via  a7a3df54f0c2a83e61098f69434ed75d17ddddae (commit)
       via  7037e2e46d23dd3dd9c10abaf74fe77261131c53 (commit)
       via  17988e6b5c626f2d530826974d5d9af840f8cae8 (commit)
       via  4c1ff6fd63416cec3853d2e82d6f105afe803b9b (commit)
       via  6425485ab7e11a782a3671f43350dfdfbae6a3bb (commit)
       via  ec6c47884edb24b9a0e26f0368cf34bc47cd1dc8 (commit)
       via  afa767d6d4673f14c35c7c4b1d7ab73353e525e9 (commit)
       via  e352eb978850609274f22d35508a733f3bd54519 (commit)
       via  6415231f10fb8672da23a1eda97eef403723c5e8 (commit)
       via  ebe34f8cfd694a4655b012a86f2ac44bd2a2698e (commit)
       via  8f40138bd4528e39179ab2357d47465812b54b2e (commit)
       via  e9438ff93e30c444f4690d76508585f3128f6aaa (commit)
       via  3642a925478113aab0da7c56b885ca0a39f91aa7 (commit)
       via  38ab255dec8fec923e031d6473d2f436d7aa03b6 (commit)
       via  f889cbb350deda1e20af8be720cc5ebe5a60bfbc (commit)
       via  0f916e34bbede7dcddd5e2b3e341a99faac65bf4 (commit)
       via  6a65e7e6a04dcc0f635be9ad8d060a20a764d536 (commit)
       via  d34fd4b7a7183e48eb61f142480348d4162f5b72 (commit)
       via  ce28b2a95e18362d27c1a1f0336b2fc9c1e0d970 (commit)
       via  11c0d5d840e331e9fb1d3dd48c3d535a83e7666e (commit)
       via  6742ab2bb746ef812f354a9a1eabc0e94861f8f5 (commit)
       via  04adfe638624163a23a8a4df4ef0ee549e87e097 (commit)
       via  cfd2128fd386398119f29b524cf3662835410806 (commit)
       via  8364064ffc7f942add6f4c886e87acadf14f5c32 (commit)
       via  486379c6c24c31e381b62c36ecd141861a748a42 (commit)
       via  9a57f9584dab85bedd440c980c5128cdcb989503 (commit)
       via  7854511b23e35d28d118a59b7c3d8985a76cd607 (commit)
      from  d9cfcad78b5c563d72ba92e5d6746d22d4c5274b (commit)

Summary of changes:
 .gitignore                                         |    1 +
 Makefile.in                                        |    7 +
 README                                             |    6 +-
 configure.ac                                       |    3 +-
 devel/tools/apache.conf                            |  173 ++++++++++++++++++++
 etc/RT_Config.pm.in                                |    2 +-
 lib/RT/Action/CreateTickets.pm                     |    7 +-
 lib/RT/Action/SendEmail.pm                         |    6 +-
 lib/RT/Approval/Rule/Created.pm                    |    2 +
 lib/RT/Approval/Rule/NewPending.pm                 |    2 +
 lib/RT/Approval/Rule/Passed.pm                     |   23 ++-
 lib/RT/Approval/Rule/Rejected.pm                   |   25 ++-
 lib/RT/Attachment.pm                               |   47 +++++-
 lib/RT/Config.pm                                   |   10 +
 lib/RT/Dashboard.pm                                |   22 ++-
 lib/RT/Dashboard/Mailer.pm                         |    4 +-
 lib/RT/Groups.pm                                   |   34 +++-
 lib/RT/I18N.pm                                     |   90 +---------
 lib/RT/Interface/Email.pm                          |   51 ++++--
 lib/RT/Interface/Email/Auth/GnuPG.pm               |    8 +-
 lib/RT/Interface/Web.pm                            |    9 +-
 lib/RT/Interface/Web/Session.pm                    |    2 +-
 lib/RT/Queue.pm                                    |    2 +-
 lib/RT/Search/Googleish.pm                         |    2 +-
 lib/RT/Templates.pm                                |    1 -
 lib/RT/Test.pm                                     |   18 ++-
 lib/RT/Test/GnuPG.pm                               |    2 +-
 lib/RT/Ticket.pm                                   |    6 +-
 lib/RT/Transaction.pm                              |   51 ++----
 ...tributes-viewer.in => rt-preferences-viewer.in} |   84 +++++++---
 sbin/rt-setup-database.in                          |    3 +-
 sbin/rt-test-dependencies.in                       |    3 +-
 share/html/Admin/CustomFields/Modify.html          |    5 +-
 share/html/Admin/Elements/ListGlobalScrips         |    5 +-
 share/html/Admin/Elements/SelectTemplate           |    3 +-
 share/html/Admin/Groups/Modify.html                |   21 ++-
 share/html/Admin/Groups/index.html                 |    4 +-
 share/html/Admin/Users/DashboardsInMenu.html       |    2 +-
 share/html/Admin/Users/Modify.html                 |   44 +++---
 share/html/Admin/Users/index.html                  |    4 +-
 share/html/Articles/Article/Delete.html            |    8 +-
 share/html/Articles/Article/Search.html            |    4 +-
 share/html/Dashboards/Elements/ListOfDashboards    |    6 +-
 share/html/Dashboards/Elements/ShowDashboards      |    5 +-
 share/html/Elements/Dashboards                     |    2 +-
 share/html/Elements/EditTimeValue                  |    4 +-
 share/html/Elements/SelectTimeUnits                |    2 +-
 share/html/Prefs/DashboardsInMenu.html             |    2 +-
 share/html/REST/1.0/Forms/ticket/default           |   17 ++-
 share/html/REST/1.0/search/ticket                  |   31 ++--
 share/html/Ticket/Elements/ShowAttachments         |    2 +-
 share/html/Ticket/Elements/ShowTransaction         |   54 +++++--
 share/html/Ticket/Forward.html                     |   11 +-
 share/html/User/Prefs.html                         |   85 +++++-----
 share/html/index.html                              |    4 +
 share/html/m/_elements/ticket_list                 |    7 +-
 t/api/action-createtickets.t                       |   31 ++++-
 t/api/group-rights.t                               |  137 ++++++++++++++++
 t/api/groups.t                                     |  141 ++++-------------
 {share/html/NoAuth/images => t/data}/bpslogo.png   |  Bin 3929 -> 3929 bytes
 t/mail/rfc822-attachment.t                         |  139 ++++++++++++++++
 t/mail/sendmail.t                                  |   34 +++-
 t/mail/wrong_mime_charset.t                        |   17 +-
 t/ticket/{quicksearch.t => googleish_search.t}     |    0
 t/web/admin_groups.t                               |    4 +-
 t/web/charting.t                                   |   11 +-
 t/web/command_line.t                               |    1 +
 t/web/command_line_with_unknown_field.t            |    1 +
 t/web/dashboards-groups.t                          |  108 ++++++++++++-
 t/web/gnupg-headers.t                              |   53 ++++++
 t/web/googleish_search.t                           |   30 ++++-
 t/web/quickcreate.t                                |    5 +-
 t/web/rest-sort.t                                  |   46 +++++
 t/web/ticket_forward.t                             |  143 ++++++++++++++++-
 74 files changed, 1433 insertions(+), 506 deletions(-)
 create mode 100644 devel/tools/apache.conf
 copy sbin/{rt-attributes-viewer.in => rt-preferences-viewer.in} (56%)
 create mode 100644 t/api/group-rights.t
 copy {share/html/NoAuth/images => t/data}/bpslogo.png (100%)
 create mode 100644 t/mail/rfc822-attachment.t
 rename t/ticket/{quicksearch.t => googleish_search.t} (100%)
 create mode 100644 t/web/gnupg-headers.t
 create mode 100644 t/web/rest-sort.t

- Log -----------------------------------------------------------------
commit 8ee5c5576b948e95e32eedbe82b4461fec52d67e
Merge: d9cfcad 88fe4cd
Author: Alex Vandiver <alexmv at bestpractical.com>
Date:   Thu Aug 4 21:02:36 2011 -0400

    Merge branch '4.0-trunk'
    
    Conflicts:
    	share/html/Dashboards/Elements/ListOfDashboards
    	share/html/Elements/Tabs
    	share/html/User/Prefs.html
    	t/web/dashboards-groups.t
    	t/web/ticket_forward.t

diff --cc share/html/Admin/Users/DashboardsInMenu.html
index 6bcb721,1dab1eb..4959626
--- a/share/html/Admin/Users/DashboardsInMenu.html
+++ b/share/html/Admin/Users/DashboardsInMenu.html
@@@ -77,36 -77,45 +77,36 @@@ if ($ARGS{Reset}) 
      push @actions, $ok ? loc('Preferences saved for user [_1].', $UserObj->Name) : $msg;
  }
  
 -my ($default_portlets) = RT::System->new($session{'CurrentUser'})->Attributes->Named('HomepageSettings');
 -my $portlets  = $UserObj->Preferences('HomepageSettings', $default_portlets ? $default_portlets->Content  : {});
 +my ($default_dashboards) =
 +RT::System->new($session{'CurrentUser'})->Attributes->Named('DashboardsInMenu');
  
 -my %allowed_components = map {$_ => 1} @{ RT->Config->Get('HomepageComponents') };
 +my $user = RT::CurrentUser->new( $session{CurrentUser} );
 +$user->Load( $UserObj->id );
 +my @dashboards =
 +  map { [ $_->id, $_->Name ] }
-   $m->comp( "/Dashboards/Elements/ListOfDashboards", User => $user );
++  $m->comp( "/Dashboards/Elements/ListOfDashboards", User => $user, IncludeSuperuserGroups => 0 );
  
 -my @items;
 -push @items, map {["component-$_", $_]} sort keys %allowed_components;
  
 -my $sys = RT::System->new( RT::CurrentUser->new($UserObj) );
 -my @objs = ($sys);
 -
 -push @objs, RT::SavedSearch->new( RT::CurrentUser->new( $UserObj ) )->ObjectsForLoading;
 -
 -for my $object (@objs) {
 -    for ($m->comp("/Search/Elements/SearchesForObject", Object => $object)) {
 -        my ($desc, $search) = @$_;
 -        my $SearchType = $search->Content->{'SearchType'} || 'Ticket';
 -        if ($object eq $sys && $SearchType eq 'Ticket') {
 -            push @items, ["system-$desc", $desc];
 -        }
 -        else {
 -            my $oid = ref($object).'-'.$object->Id.'-SavedSearch-'.$search->Id;
 -            my $type = ($SearchType eq 'Ticket')
 -                ? 'Saved Search' : $SearchType; # loc
 -            push @items, ["saved-$oid", loc($type).": $desc"];
 -        }
 -    }
 -}
 +my $current_pref =
 +  $UserObj->Preferences( 'DashboardsInMenu',
 +    $default_dashboards ? $default_dashboards->Content : () );
 +my $current_portlets =
 +    $current_pref && $current_pref->{dashboards}
 +  ? $current_pref->{dashboards}
 +  : [];
  
  my @panes = $m->comp(
 -    '/Admin/Elements/ConfigureMyRT',
 -    panes  => ['body', 'summary'],
 -    Action => "MyRT.html?id=$id",
 -    items => \@items,
 -    current_portlets => $portlets,
 +    '/Admin/Elements/ConfigureDashboardsInMenu',
 +    Action           => "DashboardsInMenu.html?id=$id",
 +    panes            => ['dashboards_in_menu'],
 +    items            => \@dashboards,
 +    current_portlets => $current_portlets,
      OnSave => sub {
 -        my ( $conf, $pane ) = @_;
 -        my ($ok, $msg) = $UserObj->SetPreferences( 'HomepageSettings', $conf );
 -        push @actions, $ok ? loc('Preferences [_1] for user [_2].', $pane, $UserObj->Name) : $msg;
 +        my ($conf) = @_;
 +        my ( $ok, $msg ) =
 +          $UserObj->SetPreferences( 'DashboardsInMenu', $conf );
 +        push @actions,
 +          $ok ? loc('Preferences saved for dashboards in menu.') : $msg;
      }
  );
  
diff --cc share/html/Dashboards/Elements/ListOfDashboards
index 0e48eef,49a48ad..c0eab8d
--- a/share/html/Dashboards/Elements/ListOfDashboards
+++ b/share/html/Dashboards/Elements/ListOfDashboards
@@@ -48,7 -48,10 +48,9 @@@
  <%init>
  # put the list of dashboards into the navigation
  use RT::Dashboard;
- my @objs = RT::Dashboard->new($User)->ObjectsForLoading;
 -
 -my @objs = RT::Dashboard->new($session{CurrentUser})->ObjectsForLoading(
++my @objs = RT::Dashboard->new($User)->ObjectsForLoading(
+                IncludeSuperuserGroups => $IncludeSuperuserGroups
+            );
  
  my %dashboard_map;
  
@@@ -75,7 -77,6 +77,7 @@@ $m->callback(%ARGS, dashboards => \@das
  
  return @dashboards;
  </%init>
- 
  <%args>
 +$User => $session{CurrentUser}
+ $IncludeSuperuserGroups => 1
  </%args>
diff --cc share/html/Prefs/DashboardsInMenu.html
index 0038010,cba4265..66dbc99
--- a/share/html/Prefs/DashboardsInMenu.html
+++ b/share/html/Prefs/DashboardsInMenu.html
@@@ -52,60 -50,57 +52,60 @@@
  
  <& /Widgets/SelectionBox:header, nojs => 1 &>
  
 -<& /Elements/ListActions, actions => \@actions &>
 -<br />
 -% for my $pane (@panes) {
 -<&|/Widgets/TitleBox, title => loc('RT at a glance').': '.loc($pane->{Name}), bodyclass => "" &>
 -<& /Widgets/SelectionBox:show, self => $pane, nojs => 1 &></&>
 +
  <br />
 +
 +% for my $pane ( @panes ) {
 +<&|/Widgets/TitleBox,
 +    title => loc('Dashboards in menu'),
 +    bodyclass => ""
 +&>
 +<& /Widgets/SelectionBox:show, self => $pane, nojs => 1 &>
 +</&>
  % }
 -<%init>
 -my @actions;
 -
 -my @items = map { [ "component-$_", $_ ] } sort @{ RT->Config->Get('HomepageComponents') };
 -my $sys = RT::System->new( $session{'CurrentUser'} );
 -# XXX: put this in savedsearches_to_portlet_items
 -for ( $m->comp( "/Search/Elements/SearchesForObject",
 -                Object => $sys )) {
 -    my ( $desc, $search ) = @$_;
 -    my $SearchType = $search->Content->{'SearchType'} || 'Ticket';
 -    if ( $SearchType eq 'Ticket' ) {
 -        push @items, [ "system-$desc", $desc ];
 -    } else {
 -        my $oid = ref($sys) . '-' . $sys->Id . '-SavedSearch-' . $search->Id;
 -        my $type =
 -            ( $SearchType eq 'Ticket' )
 -            ? 'Saved Search' : $SearchType;    # loc
 -        push @items, [ "saved-$oid", loc($type) . ": $desc" ];
 -    }
 +
 +<&|/Widgets/TitleBox, title => loc("Reset dashboards in menu") &>
 +<form method="post" action="DashboardsInMenu.html">
 +<input type="hidden" name="Reset" value="1" />
 +<input type="submit" class="button" value="<% loc('Reset to default') %>">
 +</form>
 +</&>
 +
 +
 +<%INIT>
 +my @results;
 +my $title = loc("Customize").' '.loc("dashboards in menu");
 +my $user = $session{'CurrentUser'}->UserObj;
 +
 +if ($ARGS{Reset}) {
 +    my ($ok, $msg) = $user->SetPreferences('DashboardsInMenu', {});
 +    push @results, $ok ? loc('Preferences saved.') : $msg;
 +    delete $session{'dashboards_in_menu'};
  }
  
 -my ($default_portlets) = $sys->Attributes->Named('HomepageSettings');
 +my ($default_dashboards) =
 +RT::System->new($session{'CurrentUser'})->Attributes->Named('DashboardsInMenu');
 +
 +my $dashboard_pref =
 +  $session{CurrentUser}->UserObj->Preferences( 'DashboardsInMenu',
 +    $default_dashboards ? $default_dashboards->Content : () );
  
 -my $has_right = $session{'CurrentUser'}->HasRight( Object=> $RT::System, Right => 'SuperUser');
 +my $current_dashboards = $dashboard_pref->{dashboards} || [];
 +
- my @dashboards = map { [$_->id, $_->Name] } $m->comp("/Dashboards/Elements/ListOfDashboards");
++my @dashboards = map { [$_->id, $_->Name] } $m->comp("/Dashboards/Elements/ListOfDashboards", IncludeSuperuserGroups => 0 );
  
  my @panes = $m->comp(
 -    '/Admin/Elements/ConfigureMyRT',
 -    panes  => [
 -        'body', #loc
 -        'summary', #loc
 -    ],
 -    Action => 'MyRT.html',
 -    items => \@items,
 -    ReadOnly => !$has_right,
 -    current_portlets => $default_portlets->Content,
 +    '/Admin/Elements/ConfigureDashboardsInMenu',
 +    Action => 'DashboardsInMenu.html',
 +    panes => ['dashboards_in_menu'],
 +    items => \@dashboards,
 +    current_portlets => $current_dashboards,
      OnSave => sub {
 -        my ( $conf, $pane ) = @_;
 -        if (!$has_right) {
 -            push @actions, loc( 'Permission denied' );
 -        }
 -        else {
 -            $default_portlets->SetContent( $conf );
 -            push @actions, loc( 'Global portlet [_1] saved.', $pane );
 -        }
 +        my ( $conf ) = @_;
 +        my ( $ok, $msg ) =
 +          $user->SetPreferences( 'DashboardsInMenu', $conf );
 +        push @results, $ok ? loc('Preferences saved for dashboards in menu.') : $msg;
 +        delete $session{'dashboards_in_menu'};
      }
  );
  
diff --cc share/html/User/Prefs.html
index 2b4dadd,ecca2ba..34de4ea
--- a/share/html/User/Prefs.html
+++ b/share/html/User/Prefs.html
@@@ -209,54 -209,55 +209,55 @@@ $id = $UserObj->id
  
  my @results;
  
- my @fields = qw(
-     Name Comments Signature EmailAddress FreeformContactInfo 
-     Organization RealName NickName Lang EmailEncoding WebEncoding 
-     ExternalContactInfoId ContactInfoSystem Gecos ExternalAuthId 
-     AuthSystem HomePhone WorkPhone MobilePhone PagerPhone Address1
-     Address2 City State Zip Country Timezone
- );
- 
- $m->callback(
-     CallbackName => 'UpdateLogic',
-     fields       => \@fields,
-     results      => \@results,
-     UserObj      => $UserObj,
-     ARGSRef      => \%ARGS,
- );
- 
- if ( $Lang ) {
-     $session{'CurrentUser'}->LanguageHandle($Lang);
-     $session{'CurrentUser'} = $session{'CurrentUser'}; # force writeback
+ if ( $ARGS{'ResetAuthToken'} ) {
+     my ($status, $msg) = $UserObj->GenerateAuthToken;
+     push @results, $msg;
  }
+ else {
+     my @fields = qw(
+         Name Comments Signature EmailAddress FreeformContactInfo 
+         Organization RealName NickName Lang EmailEncoding WebEncoding 
+         ExternalContactInfoId ContactInfoSystem Gecos ExternalAuthId 
+         AuthSystem HomePhone WorkPhone MobilePhone PagerPhone Address1
+         Address2 City State Zip Country Timezone
+     );
  
- push @results, UpdateRecordObject (
-     AttributesRef => \@fields,
-     Object => $UserObj,
-     ARGSRef => \%ARGS,
- );
- 
- push @results, ProcessObjectCustomFieldUpdates( ARGSRef => \%ARGS, Object => $UserObj );
+     $m->callback(
+         CallbackName => 'UpdateLogic',
+         fields       => \@fields,
+         results      => \@results,
+         UserObj      => $UserObj,
+         ARGSRef      => \%ARGS,
+     );
  
- # Deal with special fields: Privileged, Enabled, and Password
- if  ( $SetPrivileged and $Privileged != $UserObj->Privileged ) {
-     my ($code, $msg) = $UserObj->SetPrivileged( $Privileged );
-     push @results, loc('Privileged status: [_1]', loc_fuzzy($msg));
- }
++    if ( $Lang ) {
++        $session{'CurrentUser'}->LanguageHandle($Lang);
++        $session{'CurrentUser'} = $session{'CurrentUser'}; # force writeback
++    }
 +
- my %password_cond = $UserObj->CurrentUserRequireToSetPassword;
- if (defined $Pass1 && length $Pass1 ) {
-     my ($status, $msg) = $UserObj->SafeSetPassword(
-         Current      => $CurrentPass,
-         New          => $Pass1,
-         Confirmation => $Pass2,
+     push @results, UpdateRecordObject (
+         AttributesRef => \@fields,
+         Object => $UserObj,
+         ARGSRef => \%ARGS,
      );
-     push @results, loc("Password: [_1]", $msg);
- }
  
- if ( $ARGS{'ResetAuthToken'} ) {
-     my ($status, $msg) = $UserObj->GenerateAuthToken;
-     push @results, $msg;
+     push @results, ProcessObjectCustomFieldUpdates( ARGSRef => \%ARGS, Object => $UserObj );
+ 
 -    if ( $Lang ) {
 -        $session{'CurrentUser'}->LanguageHandle($Lang);
 -        $session{'CurrentUser'} = $session{'CurrentUser'}; # force writeback
 -    }
 -
+     # Deal with special fields: Privileged, Enabled, and Password
+     if  ( $SetPrivileged and $Privileged != $UserObj->Privileged ) {
+         my ($code, $msg) = $UserObj->SetPrivileged( $Privileged );
+         push @results, loc('Privileged status: [_1]', loc_fuzzy($msg));
+     }
+ 
+     my %password_cond = $UserObj->CurrentUserRequireToSetPassword;
+     if (defined $Pass1 && length $Pass1 ) {
+         my ($status, $msg) = $UserObj->SafeSetPassword(
+             Current      => $CurrentPass,
+             New          => $Pass1,
+             Confirmation => $Pass2,
+         );
+         push @results, loc("Password: [_1]", $msg);
+     }
  }
  
  </%INIT>
diff --cc t/web/dashboards-groups.t
index a5b697b,ac2a5ac..c43ac78
--- a/t/web/dashboards-groups.t
+++ b/t/web/dashboards-groups.t
@@@ -1,6 -1,7 +1,6 @@@
 -#!/usr/bin/perl -w
  use strict;
  
- use RT::Test nodata => 1, tests => 35;
+ use RT::Test nodata => 1, tests => 64;
  my ($baseurl, $m) = RT::Test->started_ok;
  
  my $url = $m->rt_base_url;
@@@ -74,8 -74,12 +73,12 @@@ $user_obj->PrincipalObj->GrantRight
      Right  => 'SeeGroupDashboard',
      Object => $inner_group,
  );
- $m->reload;
+ $m->follow_link_ok({ id => 'home-dashboard_create'});
+ $m->form_name('ModifyDashboard');
+ $m->field("Name" => 'inner dashboard');
+ $m->field("Privacy" => "RT::Group-" . $inner_group->Id);
+ $m->click_button(value => 'Create');
 -$m->content_lacks("Permission denied", "we now have SeeGroupDashboard");
 +$m->content_lacks("Permission Denied", "we now have SeeGroupDashboard");
  $m->content_contains("Saved dashboard inner dashboard");
  $m->content_lacks('Delete', "Delete button hidden because we lack DeleteDashboard");
  
@@@ -91,6 -95,101 +94,101 @@@ is($dashboard->PossibleHiddenSearches, 
  
  $m->get_ok("/Dashboards/Modify.html?id=$id");
  $m->content_contains("inner dashboard", "we now have SeeGroupDashboard right");
 -$m->content_lacks("Permission denied");
 +$m->content_lacks("Permission Denied");
  $m->content_contains('Subscription', "Subscription link not hidden because we have SubscribeDashboard");
  
+ 
+ $m->get_ok("/Dashboards/index.html");
+ $m->content_contains("inner dashboard", "We can see the inner dashboard from the UI");
+ 
 -$m->get_ok("/index.html");
 -$m->content_contains("inner dashboard", "We can see the inner dashboard from the menu drop-down");
++$m->get_ok("/Prefs/DashboardsInMenu.html");
++$m->content_contains("inner dashboard", "Can also see it in the menu options");
+ 
+ my ($group) = grep {$_->isa("RT::Group") and $_->Id == $inner_group->Id}
+     RT::Dashboard->new($currentuser)->_PrivacyObjects;
+ ok($group, "Found the group in  the privacy objects list");
+ 
+ my @loading = map {ref($_)."-".$_->Id} RT::Dashboard->new($currentuser)->ObjectsForLoading;
+ is_deeply(
+     \@loading,
+     ["RT::User-".$user_obj->Id, "RT::Group-".$inner_group->Id],
+     "We can load from ourselves (SeeOwnDashboard) and a group we are with SeeGroupDashboard"
+ );
+ 
+ # If you are granted SeeGroupDashboard globally, you can only see
+ # dashboards in groups you are in.
+ $user_obj->PrincipalObj->RevokeRight(
+     Right  => 'SeeGroupDashboard',
+     Object => $inner_group,
+ );
+ $user_obj->PrincipalObj->GrantRight(
+     Right  => 'SeeGroupDashboard',
+     Object => RT->System,
+ );
+ $m->get_ok("/Dashboards/index.html");
+ $m->content_contains("inner dashboard", "Having SeeGroupDashboard gobally is fine for groups you are in");
+ @loading = map {ref($_)."-".$_->Id} RT::Dashboard->new($currentuser)->ObjectsForLoading;
+ is_deeply(
+     \@loading,
+     ["RT::User-".$user_obj->Id, "RT::Group-".$inner_group->Id],
+     "SeeGroupDashboard globally still works for groups you are in"
+ );
+ 
+ $inner_group->DeleteMember($user_obj->PrincipalObj->Id);
+ ok(!$outer_group->HasMemberRecursively($user_obj->PrincipalId), "outer no longer has user recursively");
+ ok(!$inner_group->HasMemberRecursively($user_obj->PrincipalId), "inner no longer has user recursively");
+ $m->get_ok("/Dashboards/index.html");
+ $m->content_lacks("inner dashboard", "But global SeeGroupDashboard isn't enough for other groups");
+ $m->no_warnings_ok;
+ @loading = map {ref($_)."-".$_->Id} RT::Dashboard->new($currentuser)->ObjectsForLoading;
+ is_deeply(
+     \@loading,
+     ["RT::User-".$user_obj->Id],
+     "We only have our SeeOwnDashboard right, as we are no longer in inner"
+ );
+ 
+ # Similarly, if you're a SuperUser, you still only see dashboards for
+ # groups you belong to
+ $user_obj->PrincipalObj->RevokeRight(
+     Right  => 'SeeGroupDashboard',
+     Object => RT->System,
+ );
+ $user_obj->PrincipalObj->GrantRight(
+     Right  => 'SuperUser',
+     Object => RT->System,
+ );
+ $m->get_ok("/Dashboards/index.html");
+ $m->content_lacks("inner dashboard", "Superuser can't see dashboards in groups they're not in");
+ @loading = map {ref($_)."-".$_->Id} RT::Dashboard->new($currentuser)->ObjectsForLoading;
+ is_deeply(
+     \@loading,
+     ["RT::User-".$user_obj->Id, "RT::System-1"],
+     "We pick up the system-level SeeDashboard right from superuser"
+ );
+ @loading = map {ref($_)."-".$_->Id} RT::Dashboard->new($currentuser)->ObjectsForLoading(IncludeSuperuserGroups => 0);
+ is_deeply(
+     \@loading,
+     ["RT::User-".$user_obj->Id, "RT::System-1"],
+     "IncludeSuperusers only cuts out _group_ dashboard objects for loading, not user and system ones"
+ );
+ 
+ $inner_group->AddMember($user_obj->PrincipalId);
+ $m->get_ok("/Dashboards/index.html");
+ $m->content_contains("inner dashboard", "Superuser can see dashboards in groups they are in");
+ @loading = map {ref($_)."-".$_->Id} RT::Dashboard->new($currentuser)->ObjectsForLoading;
+ is_deeply(
+     \@loading,
+     ["RT::User-".$user_obj->Id, "RT::Group-".$inner_group->Id, "RT::System-1"],
+     "Becoming a member of the group makes it a possibility"
+ );
+ @loading = map {ref($_)."-".$_->Id} RT::Dashboard->new($currentuser)->ObjectsForLoading(IncludeSuperuserGroups => 0);
+ is_deeply(
+     \@loading,
+     ["RT::User-".$user_obj->Id, "RT::System-1"],
+     "But only via superuser"
+ );
+ 
+ $m->get_ok("/Dashboards/index.html");
+ $m->content_contains("inner dashboard", "The dashboards list includes superuser rights");
 -$m->get_ok("/index.html");
++$m->get_ok("/Prefs/DashboardsInMenu.html");
+ $m->content_lacks("inner dashboard", "But the menu skips them");
diff --cc t/web/ticket_forward.t
index cf66494,c8205be..90bd3b5
--- a/t/web/ticket_forward.t
+++ b/t/web/ticket_forward.t
@@@ -1,4 -1,4 +1,3 @@@
- 
 -#!/usr/bin/perl
  use strict;
  use warnings;
  

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


More information about the Rt-commit mailing list