[Rt-commit] rt branch, 4.4/remove-user-info, created. rt-4.4.2-244-gb90d7c4fc

Craig Kaiser craig at bestpractical.com
Thu Sep 13 12:06:43 EDT 2018


The branch, 4.4/remove-user-info has been created
        at  b90d7c4fce68928fa131b1f97d9e84bd7d0e5c74 (commit)

- Log -----------------------------------------------------------------
commit 846aad4443f2a16682795001c7731aa1af3f7203
Author: Maureen E. Mirville <maureen at bestpractical.com>
Date:   Mon Apr 9 16:15:29 2018 -0400

    Allow rt-setup-fulltext-index to prompt for dba password

diff --git a/sbin/rt-setup-fulltext-index.in b/sbin/rt-setup-fulltext-index.in
index 5cab8f632..76da05dcd 100644
--- a/sbin/rt-setup-fulltext-index.in
+++ b/sbin/rt-setup-fulltext-index.in
@@ -49,6 +49,7 @@
 use strict;
 use warnings;
 no warnings 'once';
+use Term::ReadKey;
 
 # fix lib paths, some may be relative
 BEGIN { # BEGIN RT CMD BOILERPLATE
@@ -650,6 +651,17 @@ sub dba_handle {
         $ENV{'NLS_NCHAR'} = "AL32UTF8";
     }
     my $dsn = do { my $h = new RT::Handle; $h->BuildDSN; $h->DSN };
+    my $password;
+    if ( defined $DB{'admin_password'} || defined $ENV{'RT_DBA_PASSWORD'} ) {
+        $password = $DB{'admin_password'} // $ENV{'RT_DBA_PASSWORD'};
+    } else {
+        print "Please enter $DB{'type'} admin password: ";
+        ReadMode('noecho');
+        chomp($password = ReadLine(0));
+        ReadMode('normal');
+        print "\n";
+    }
+    $DB{'admin_password'} = $password;
     my $dbh = DBI->connect(
         $dsn, $DB{admin}, $DB{admin_password},
         { RaiseError => 1, PrintError => 1 },

commit 2626be861ea8440215cce7ed94a09b685ac58018
Author: Craig Kaiser <craig at bestpractical.com>
Date:   Mon May 21 11:01:48 2018 -0400

    Fix typo in POD

diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm
index a38b14718..e8a4545de 100644
--- a/lib/RT/Interface/Web.pm
+++ b/lib/RT/Interface/Web.pm
@@ -928,7 +928,7 @@ sub GetWebURLFromRequest {
 
 =head2 Redirect URL
 
-This routine ells the current user's browser to redirect to URL.  
+This routine tells the current user's browser to redirect to URL.  
 Additionally, it unties the user's currently active session, helping to avoid 
 A bug in Apache::Session 1.81 and earlier which clobbers sessions if we try to use 
 a cached DBI statement handle twice at the same time.

commit 03a365485abf1cff8c9c497518ef43193d027576
Author: Maureen E. Mirville <maureen at bestpractical.com>
Date:   Wed Aug 30 10:46:17 2017 -0400

    Improve message when applying/removing custom roles from queues
    
    When a user is applying or removing a custom role from a queue, the
    previous message after making a change, "Object created" or "Object
    deleted" was unclear. Message updated to make it clear user applied
    a role or removed a role from a queue.
    
    Fixes: I#32695

diff --git a/lib/RT/CustomRole.pm b/lib/RT/CustomRole.pm
index 4b6c07292..8c9b08451 100644
--- a/lib/RT/CustomRole.pm
+++ b/lib/RT/CustomRole.pm
@@ -409,9 +409,11 @@ sub AddToObject {
 
     return ( 0, $self->loc('Permission Denied') )
         unless $queue->CurrentUserHasRight('AdminCustomRoles');
-
     my $rec = RT::ObjectCustomRole->new( $self->CurrentUser );
-    return $rec->Add( %args, CustomRole => $self );
+    my ( $status, $add ) = $rec->Add( %args, CustomRole => $self );
+    my $msg = $self->loc("[_1] added to queue [_2]", $self->Name, $queue->Name) if $status;
+
+    return ( $add, $msg );
 }
 
 =head2 RemoveFromObject
@@ -444,11 +446,13 @@ sub RemoveFromObject {
 
     return ( 0, $self->loc('Permission Denied') )
         unless $queue->CurrentUserHasRight('AdminCustomRoles');
-
     my $rec = RT::ObjectCustomRole->new( $self->CurrentUser );
     $rec->LoadByCols( CustomRole => $self->id, ObjectId => $args{'ObjectId'} );
     return (0, $self->loc('Custom role is not added') ) unless $rec->id;
-    return $rec->Delete;
+    my ( $status, $delete ) = $rec->Delete;
+    my $msg = $self->loc("[_1] removed from queue [_2]", $self->Name, $queue->Name) if $status;
+
+    return ( $delete, $msg );
 }
 
 =head2 SingleValue

commit 1e38d70cbb785c14443d5168170955f164906068
Author: Craig Kaiser <craig at bestpractical.com>
Date:   Fri Jun 15 08:54:46 2018 -0400

    Add GenerateAnonymousName function for RT::User
    
    The GenerateAnonymousName function will return a random valid (unique)
    username with the format 'anon_1234abcd' where after 'anon_' is a random
    string. Specify length of the random string by providing int value to
    function.

diff --git a/lib/RT/User.pm b/lib/RT/User.pm
index ca47377cf..6ade28f6a 100644
--- a/lib/RT/User.pm
+++ b/lib/RT/User.pm
@@ -281,6 +281,31 @@ sub ValidateName {
     }
 }
 
+=head2 GenerateAnonymousName INT
+
+Generate a random username proceeded by 'anon_' and then a
+random string, Returns the AnonymousName string. The length of the
+random string can be set by providing an integer for character length.
+
+=cut
+
+sub GenerateAnonymousName {
+    my $self = shift;
+    my $length = shift;
+
+    my $invalid = 1;
+    my $name = '';
+
+    while ( $invalid ) {
+        my @Chars = ('a'..'z', 'A'..'Z', '0'..'9');
+        for (1..$length || 9) {
+            $name .= $Chars[int rand @Chars];
+        }
+        $invalid = !$self->ValidateName('anon_' . $name);
+    }
+    return 'anon_' . $name;
+}
+
 =head2 ValidatePassword STRING
 
 Returns either (0, "failure reason") or 1 depending on whether the given

commit 814480b46fa8921ec4d0e6f84e629c8559924e16
Author: Craig Kaiser <craig at bestpractical.com>
Date:   Fri Jun 15 08:56:22 2018 -0400

    Create method AnonymizeUser in User.pm
    
    Create method 'AnonymizeUser' that will remove the personal
    identifying information from a user record, but keep the record alive.

diff --git a/lib/RT/User.pm b/lib/RT/User.pm
index 6ade28f6a..2ef511907 100644
--- a/lib/RT/User.pm
+++ b/lib/RT/User.pm
@@ -306,6 +306,68 @@ sub GenerateAnonymousName {
     return 'anon_' . $name;
 }
 
+=head2 AnonymizeUser { clear_customfields }
+
+Remove all personal identifying information on the user record, but keep
+the user record alive. Additionally replace the username with an anonymous name.
+Submit clear_customfields in a paramhash, if true all customfield values
+applied to the user record will be cleared.
+
+=cut
+
+sub AnonymizeUser {
+    my $self = shift;
+    my %args = (
+        ClearCustomFields  => undef,
+        @_,
+    );
+
+    my @user_idenifying_info = qw (
+        Address1 Address2 City Comments Country EmailAddress
+        FreeformContactInfo Gecos HomePhone MobilePhone NickName Organization
+        PagerPhone RealName Signature SMIMECertificate State Timezone WorkPhone Zip
+    );
+
+    $RT::Handle->BeginTransaction();
+    # Remove identifying user information from record
+    foreach my $attr (@user_idenifying_info) {
+        if ( defined $self->$attr && length $self->$attr) {
+                my $method = 'Set' . $attr;
+                my ($ret, $msg) = $self->$method('');
+                RT::Logger->error($msg) unless $ret;
+                return ($ret, $msg) unless $ret;
+        }
+    }
+
+    # Do not do anything if password is already unset
+    if ( $self->HasPassword ) {
+        my ($ret, $msg) = $self->_Set(Field => 'Password', Value => '*NO-PASSWORD*' );
+        RT::Logger->error($msg) unless $ret;
+    }
+
+    # Generate the random anon username
+    my ($ret, $msg) = $self->SetName($self->GenerateAnonymousName);
+    RT::Logger->error($msg) unless $ret;
+
+    # Remove user customfield values
+    if ( $args{'ClearCustomFields'} ) {
+        my $customfields = RT::CustomFields->new(RT->SystemUser);
+        ($ret, $msg) = $customfields->LimitToLookupType('RT::User');
+        RT::Logger->error($msg) unless $ret;
+
+        while (my $customfield = $customfields->Next) {
+            if ( $self->FirstCustomFieldValue( $customfield->Name ) ) {
+                ($ret, $msg) = $self->DeleteCustomFieldValue( Field => $customfield->Id, Value =>  $self->FirstCustomFieldValue( $customfield->Name ) );
+                RT::Logger->error($msg) unless $ret;
+                $RT::Handle->Rollback() unless $ret;
+            }
+        }
+    }
+    $RT::Handle->Commit();
+
+    return(1, 'User successfully anonymized');
+}
+
 =head2 ValidatePassword STRING
 
 Returns either (0, "failure reason") or 1 depending on whether the given

commit 61a2dbd9efa8b90e101ec9ce94d32f0c661cf553
Author: Craig Kaiser <craig at bestpractical.com>
Date:   Tue Sep 4 15:25:33 2018 -0400

    Create modal mason component

diff --git a/share/html/Elements/Modal b/share/html/Elements/Modal
new file mode 100644
index 000000000..c998db378
--- /dev/null
+++ b/share/html/Elements/Modal
@@ -0,0 +1,71 @@
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
+%# COPYRIGHT:
+%#
+%# This software is Copyright (c) 1996-2018 Best Practical Solutions, LLC
+%#                                          <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
+%#
+%#
+%# LICENSE:
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+%# General Public License for more details.
+%#
+%# You should have received a copy of the GNU General Public License
+%# along with this program; if not, write to the Free Software
+%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+%# 02110-1301 or visit their web page on the internet at
+%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
+%#
+%#
+%# CONTRIBUTION SUBMISSION POLICY:
+%#
+%# (The following paragraph is not intended to limit the rights granted
+%# to you to modify and distribute this software under the terms of
+%# the GNU General Public License and is only of importance to you if
+%# you choose to contribute your changes and enhancements to the
+%# community by submitting them to Best Practical Solutions, LLC.)
+%#
+%# By intentionally submitting any modifications, corrections or
+%# derivatives to this work, or any other work intended for use with
+%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+%# you are the copyright holder for those contributions and you grant
+%# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
+%# royalty-free, perpetual, license to use, copy, create derivative
+%# works based on those contributions, and sublicense and distribute
+%# those contributions and any derivatives thereof.
+%#
+%# END BPS TAGGED BLOCK }}}
+<div id="<% $ModalId %>" class="<% $Class %>" align="center">
+    <form action="<% $Action %>" method="<% $Method %>" id="<% $ModalId %>" name="<% $Name %>" >
+% foreach my $field (@{$Fields}) {
+        <p><% $field->{'Label'} %>
+%   if ( $field->{'Input'} ) {
+        <input type="<% $field->{'Input'} %>" class="<% $field->{'Class'} %>" name="<% $field->{'Name'} %>" value="<% $field->{'Value'} %>">
+%   }
+        </p>
+% }
+        <a href="#" rel="modal:close" class="button"><&|/l&><%$Cancel%></&></a>
+        <button type="Submit" class="button"><&|/l&><%$Accept%></&></button>
+    </form>
+</div>
+
+<%ARGS>
+$Fields   => undef
+$Name     => undef
+$ModalId  => undef
+$Class    => 'modal'
+$Action   => undef
+$Method   => 'GET'
+$Accept   => 'Ok'
+$Cancel   => 'Cancel'
+</%ARGS>

commit a35c9b42314628966251b5785e9c726892568611
Author: Craig Kaiser <craig at bestpractical.com>
Date:   Fri Jun 15 08:57:47 2018 -0400

    Create portlet for removing user information
    
    Mason template that has three buttons for removing user information. The
    buttons are 'Anonymize user', 'Replace User' and 'Remove User'.
    Anonymize user will call the 'AnonymizeUser' method to clear identifying
    information from the user record. 'Replace User' and 'Remove User' will
    link to the shredder page with a pre formatted search.

diff --git a/share/html/Elements/UserRelatedInfo b/share/html/Elements/UserRelatedInfo
new file mode 100644
index 000000000..c14663f85
--- /dev/null
+++ b/share/html/Elements/UserRelatedInfo
@@ -0,0 +1,71 @@
+%# BEGIN BPS TAGGED BLOCK {{{
+%#
+%# COPYRIGHT:
+%#
+%# This software is Copyright (c) 1996-2018 Best Practical Solutions, LLC
+%#                                          <sales at bestpractical.com>
+%#
+%# (Except where explicitly superseded by other copyright notices)
+%#
+%#
+%# LICENSE:
+%#
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%#
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+%# General Public License for more details.
+%#
+%# You should have received a copy of the GNU General Public License
+%# along with this program; if not, write to the Free Software
+%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+%# 02110-1301 or visit their web page on the internet at
+%# http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
+%#
+%#
+%# CONTRIBUTION SUBMISSION POLICY:
+%#
+%# (The following paragraph is not intended to limit the rights granted
+%# to you to modify and distribute this software under the terms of
+%# the GNU General Public License and is only of importance to you if
+%# you choose to contribute your changes and enhancements to the
+%# community by submitting them to Best Practical Solutions, LLC.)
+%#
+%# By intentionally submitting any modifications, corrections or
+%# derivatives to this work, or any other work intended for use with
+%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+%# you are the copyright holder for those contributions and you grant
+%# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
+%# royalty-free, perpetual, license to use, copy, create derivative
+%# works based on those contributions, and sublicense and distribute
+%# those contributions and any derivatives thereof.
+%#
+%# END BPS TAGGED BLOCK }}}
+% if ( $UserObj && $UserObj->Id ) {
+<&|/Widgets/TitleBox,
+    class => 'user-related-info',
+    title => loc("User related info"),
+&>
+
+<table>
+    <tr>
+        <td class="label"><&|/l&>Remove user information and add anonymous username</&>:</td>
+        <td class="value"><a href="#user-info-modal" rel="modal:open" class="button value" name="anonymize_user"><&|/l&>Anonymize</&></a></td>
+    </tr><tr>
+        <td class="label"><&|/l&>Replace user links in DB with "Nobody" user</&>:</td>
+        <td class="value"><a href="<%RT->Config->Get('WebPath')%>/Admin/Tools/Shredder/index.html?Plugin=Users&Users%3Astatus=enabled&Users%3Aname=<% $UserObj->Name %>&Users%3Areplace_relations=Nobody&Search=Search" name="replace-user" class="button value"><&|/l&>Replace</&></a></td>
+    </tr><tr>
+        <td class="label"><&|/l&>Remove all references to user and links to user</&>:</td>
+        <td class="value"><a href="<%RT->Config->Get('WebPath')%>/Admin/Tools/Shredder/index.html?Plugin=Users&Users%3Astatus=enabled&Users%3Aname=<% $UserObj->Name %>&Search=Search&remove_user" class="button value" name="remove-user"><&|/l&>Remove</&></a></td>
+    </tr>
+</table>
+
+</&>
+% }
+<%ARGS>
+$UserObj
+</%ARGS>

commit e4e88fe8fabe42bd74c8f448e7d0af6a3e4fdad3
Author: Craig Kaiser <craig at bestpractical.com>
Date:   Fri Jun 15 09:00:42 2018 -0400

    Add remove user info portlet to user modify page

diff --git a/share/html/Admin/Users/Modify.html b/share/html/Admin/Users/Modify.html
index 3b8bc42fc..1d892acf1 100644
--- a/share/html/Admin/Users/Modify.html
+++ b/share/html/Admin/Users/Modify.html
@@ -206,14 +206,19 @@
 <br />
 
 <& /Elements/EditCustomFieldCustomGroupings, Object => $UserObj &>
+<& /Elements/UserRelatedInfo, UserObj => $UserObj &>
 
 % $m->callback( %ARGS, CallbackName => 'RightColumnBottom', UserObj => $UserObj );
 </td></tr>
 <tr>
-<td colspan="2">
+<td>
 <&| /Widgets/TitleBox, title => loc('Comments about this user'), class => 'user-info-comments' &>
 <textarea class="comments" name="Comments" cols="80" rows="5" wrap="virtual"><%$UserObj->Comments//$ARGS{Comments}//''%></textarea>
 </&>
+</td>
+</tr>
+
+<tr><td>
 %if (!$Create && $UserObj->Privileged) {
 <br />
 <&| /Widgets/TitleBox, title => loc('Signature'), class => 'user-info-signature' &>
@@ -232,6 +237,21 @@
 % }
 </form>
 
+% if ( $UserObj->Id ) {
+    <& /Elements/Modal, ModalId => "user-info-modal", Method => 'POST', Action => RT->Config->Get('WebPath') . '/Admin/Users/Modify.html', Fields => [
+    { Label   => "Are you sure you want to anonymize user: ". $UserObj->Name . "?" },
+    { Input => 'Hidden', Value => $UserObj->Id, Name => 'id' },
+    { Input => 'Hidden', Value => 1, Name => 'Anonymize' },
+    {
+        Label    => "Check to clear user customfields:",
+        Input    => 'checkbox',
+        Class    => 'checkbox',
+        Name     => 'clear_customfields',
+        Value    => 'On',
+    },
+]
+&>
+% }
 <%INIT>
 
 my $UserObj = RT::User->new($session{'CurrentUser'});
@@ -294,6 +314,11 @@ if ($Create) {
     }
 }
 
+if ( $ARGS{'Anonymize'} and $UserObj->Id ) {
+    my ($ret, $msg) = $UserObj->AnonymizeUser(ClearCustomFields => $ARGS{'clear_customfields'});
+    push @results, $msg;
+}
+
 if ( $UserObj->Id ) {
     # Deal with Password field
     my ($status, $msg) = $UserObj->SafeSetPassword(

commit b90d7c4fce68928fa131b1f97d9e84bd7d0e5c74
Author: Craig Kaiser <craig at bestpractical.com>
Date:   Fri Jun 15 09:01:37 2018 -0400

    Create test for remove user information

diff --git a/t/web/remove_user_info.t b/t/web/remove_user_info.t
new file mode 100644
index 000000000..bc166241a
--- /dev/null
+++ b/t/web/remove_user_info.t
@@ -0,0 +1,156 @@
+use strict;
+use warnings;
+
+use RT::Test tests => undef;
+
+RT::Config->Set( 'ShredderStoragePath', RT::Test->temp_directory . '' );
+
+my ( $baseurl, $agent ) = RT::Test->started_ok;
+
+diag("Test server running at $baseurl");
+my $url = $agent->rt_base_url;
+
+# Login
+$agent->login( 'root' => 'password' );
+
+# Anonymize User
+{
+    my $user = RT::Test->load_or_create_user( Name => 'Test User' );
+    ok $user && $user->id;
+
+    my $user_id = $user->id;
+
+    $agent->get_ok( $url . "Admin/Users/Modify.html?id=" . $user_id );
+    $agent->follow_link_ok( { text => 'Anonymize' } );
+
+    $agent->submit_form_ok( { form_id => 'user-info-modal', },
+        "Anonymize user" );
+
+    $user->Load($user_id);
+    is $user->EmailAddress, '', 'User Email removed';
+
+# UserId is still the same, but all other records should be anonimyzed for TestUser
+    my ( $ret, $msg ) = $user->Load($user_id);
+    ok $ret;
+
+    is $user->Name =~ /anon_/, 1, 'Username replaced with anon name';
+
+    my @user_idenifying_info = qw (
+        Address1 Address2 City Comments Country EmailAddress
+        FreeformContactInfo Gecos HomePhone MobilePhone NickName Organization
+        PagerPhone RealName Signature SMIMECertificate State Timezone WorkPhone Zip
+        );
+    $user->Load($user_id);
+
+    # Ensure that all other user fields are blank
+    foreach my $attr (@user_idenifying_info) {
+        my $check = grep { not defined $_ or $_ eq '' or $_ eq 0 } $user->$attr;
+        is $check, 1, 'Attribute ' . $attr . ' is blank';
+    }
+
+    # Test that customfield values are removed with anonymize user action
+    my $customfield = RT::CustomField->new( RT->SystemUser );
+    ( $ret, $msg ) = $customfield->Create(
+        Name       => 'TestCustomfield',
+        LookupType => 'RT::User',
+        Type       => 'FreeformSingle',
+    );
+    ok $ret, $msg;
+
+    ( $ret, $msg ) = $customfield->AddToObject($user);
+    ok( $ret, "Added CF to user object - " . $msg );
+
+    ( $ret, $msg ) = $user->AddCustomFieldValue(
+        Field => 'TestCustomfield',
+        Value => 'Testing'
+    );
+    ok $ret, $msg;
+
+    is $user->FirstCustomFieldValue('TestCustomfield'), 'Testing',
+        'Customfield exists and has value for user.';
+
+    $agent->get_ok( $url . "Admin/Users/Modify.html?id=" . $user->id );
+    $agent->follow_link_ok( { text => 'Anonymize' } );
+
+    $agent->submit_form_ok(
+        {   form_id => 'user-info-modal',
+            fields  => { clear_customfields => 'On' },
+        },
+        "Anonymize user and customfields"
+    );
+
+    is $user->FirstCustomFieldValue('TestCustomfield'), undef,
+        'Customfield value cleared';
+}
+
+# Test replace user
+{
+    my $user = RT::Test->load_or_create_user(
+        Name       => 'user',
+        Password   => 'password',
+        Privileged => 1
+    );
+    ok $user && $user->id;
+
+    ok( RT::Test->set_rights(
+            { Principal => $user, Right => [qw(SuperUser)] },
+        ),
+        'set rights'
+      );
+
+    ok $agent->logout;
+    ok $agent->login( 'root' => 'password' );
+
+    $agent->get_ok( $url . "Admin/Users/Modify.html?id=" . $user->id );
+    $agent->follow_link_ok( { text => 'Replace' } );
+
+    $agent->submit_form_ok(
+        {   form_id => 'shredder-search-form',
+            fields  => { WipeoutObject => 'RT::User-' . $user->Name, },
+            button  => 'Wipeout'
+        },
+        "Replace user"
+    );
+
+    my ($ret, $msg) = $user->Load($user->Id);
+
+    is $ret, 0,
+        'User successfully deleted with replace';
+}
+
+# Test Remove user
+{
+    my $user = RT::Test->load_or_create_user(
+        Name       => 'user',
+        Password   => 'password',
+        Privileged => 1
+    );
+    ok $user && $user->id;
+
+    ok( RT::Test->set_rights(
+            { Principal => $user, Right => [qw(SuperUser)] },
+        ),
+        'set rights'
+      );
+
+    $agent->logout;
+    $agent->login( 'root' => 'password' );
+
+    $agent->get_ok( $url . "Admin/Users/Modify.html?id=" . $user->id );
+    $agent->follow_link_ok( { text => 'Remove' } );
+
+    $agent->submit_form_ok(
+        {   form_id => 'shredder-search-form',
+            fields  => { WipeoutObject => 'RT::User-' . $user->Name, },
+            button  => 'Wipeout'
+        },
+        "Remove user"
+    );
+
+    my ($ret, $msg) = $user->Load($user->Id);
+
+    is $ret, 0,
+        'User successfully deleted with remove';
+}
+
+done_testing();

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


More information about the rt-commit mailing list