[Rt-commit] rt branch 5.0/add-auth-token-expires-field created. rt-5.0.3-523-gca1cf14cf9

BPS Git Server git at git.bestpractical.com
Fri Jun 16 15:59:42 UTC 2023


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "rt".

The branch, 5.0/add-auth-token-expires-field has been created
        at  ca1cf14cf94253d19c1848f99e899cbe655d0a3e (commit)

- Log -----------------------------------------------------------------
commit ca1cf14cf94253d19c1848f99e899cbe655d0a3e
Author: Brad Embree <brad at bestpractical.com>
Date:   Fri Jun 16 08:58:33 2023 -0700

    Fix incorrect Limit calls on Pg
    
    The Limit calls were tested on MySQL which is more forgiving than Pg.
    Had to fix the Limit call for the NOT NULL check and remove the Limit
    call that checked for an empty string for it to work on Pg.

diff --git a/sbin/rt-email-expiring-auth-tokens.in b/sbin/rt-email-expiring-auth-tokens.in
index 326eefedc1..0d042b85e1 100644
--- a/sbin/rt-email-expiring-auth-tokens.in
+++ b/sbin/rt-email-expiring-auth-tokens.in
@@ -123,13 +123,7 @@ $authTokens->Limit(
 $authTokens->Limit(
     FIELD           => 'Expires',
     VALUE           => 'NULL',
-    OPERATOR        => '!=',
-    ENTRYAGGREGATOR => 'AND',
-);
-$authTokens->Limit(
-    FIELD           => 'Expires',
-    VALUE           => '',
-    OPERATOR        => '!=',
+    OPERATOR        => 'IS NOT',
     ENTRYAGGREGATOR => 'AND',
 );
 

commit 6456bbdcd0d6a6a7abc9b1912c76db503b349284
Author: Brad Embree <brad at bestpractical.com>
Date:   Tue May 2 07:54:34 2023 -0700

    Add new script to gitignore

diff --git a/.gitignore b/.gitignore
index 5ad579ba53..e8dd1da8e3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,6 +33,7 @@
 /sbin/rt-dump-metadata
 /sbin/rt-email-dashboards
 /sbin/rt-email-digest
+/sbin/rt-email-expiring-auth-tokens
 /sbin/rt-email-group-admin
 /sbin/rt-externalize-attachments
 /sbin/rt-fulltext-indexer

commit 4e2c33c5023645cf8e783141e0e4ae8c9772d6f5
Author: Brad Embree <brad at bestpractical.com>
Date:   Tue May 2 07:49:17 2023 -0700

    Add new script to build files

diff --git a/Makefile.in b/Makefile.in
index e15981eba1..4b0d464186 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -146,6 +146,7 @@ SYSTEM_BINARIES		=	rt-attributes-viewer \
 				rt-dump-metadata \
 				rt-email-dashboards \
 				rt-email-digest \
+                rt-email-expiring-auth-tokens \
 				rt-email-group-admin \
 				rt-externalize-attachments \
 				rt-fulltext-indexer \
diff --git a/configure.ac b/configure.ac
index acae97c8b1..bcc11a8b6b 100755
--- a/configure.ac
+++ b/configure.ac
@@ -473,6 +473,7 @@ AC_CONFIG_FILES([
                  sbin/rt-test-dependencies
                  sbin/rt-email-digest
                  sbin/rt-email-dashboards
+                 sbin/rt-email-expiring-auth-tokens
                  sbin/rt-externalize-attachments
                  sbin/rt-clean-attributes
                  sbin/rt-clean-sessions

commit 1c77fed997601c31a6f6acc941ea42dcd8d1ae67
Author: Brad Embree <brad at bestpractical.com>
Date:   Mon May 1 20:03:40 2023 -0700

    Add script to email users expiring auth tokens

diff --git a/sbin/rt-email-expiring-auth-tokens.in b/sbin/rt-email-expiring-auth-tokens.in
new file mode 100644
index 0000000000..326eefedc1
--- /dev/null
+++ b/sbin/rt-email-expiring-auth-tokens.in
@@ -0,0 +1,238 @@
+#!@PERL@
+# BEGIN BPS TAGGED BLOCK {{{
+#
+# COPYRIGHT:
+#
+# This software is Copyright (c) 1996-2023 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 }}}
+use warnings;
+use strict;
+
+BEGIN { # BEGIN RT CMD BOILERPLATE
+    require File::Spec;
+    require Cwd;
+    my @libs = ("@RT_LIB_PATH@", "@LOCAL_LIB_PATH@");
+    my $bin_path;
+
+    for my $lib (@libs) {
+        unless ( File::Spec->file_name_is_absolute($lib) ) {
+            $bin_path ||= ( File::Spec->splitpath(Cwd::abs_path(__FILE__)) )[1];
+            $lib = File::Spec->catfile( $bin_path, File::Spec->updir, $lib );
+        }
+        unshift @INC, $lib;
+    }
+
+}
+
+use Getopt::Long;
+use RT;
+use RT::Interface::CLI qw( loc );
+use RT::Interface::Email;
+
+RT::LoadConfig();
+RT::Init();
+
+sub usage {
+    my ($error) = @_;
+    print loc("Usage:") . " $0 --expired-by date [--print] [--help]\n";
+    print "\n" . loc(
+        "[_1] is a utility, meant to be run from cron, that emails all users with a list of their auth tokens that will expire by the expired-by date.",
+        $0
+    ) . "\n";
+    print "\t--expired-by date\t"
+        . loc("Include all auth tokens that will expire by date.")
+        . "\n"
+        . "\t                 \t"
+        . loc("Date can be in any format understood by Time::ParseDate.")
+        . "\n";
+    print "\t-p, --print      \t"
+        . loc("Print the expiring auth tokens to STDOUT; don't email them.");
+    print "\t-h, --help       \t" . loc("Print this message") . "\n";
+
+    if ( $error eq 'help' ) {
+        exit 0;
+    } else {
+        print loc("Error") . ": " . loc($error) . "\n";
+        exit 1;
+    }
+}
+
+my ( $expiredBy, $print, $help ) = ( '', '', '' );
+GetOptions(
+    'expired-by=s' => \$expiredBy,
+    'print'        => \$print,
+    'help'         => \$help,
+);
+
+usage('help') if $help;
+usage("expired-by parameter is required")
+    unless $expiredBy;
+
+my $expiredByDateObj = RT::Date->new( RT->SystemUser );
+usage("Invalid date parameter '$expiredBy'")
+    unless $expiredByDateObj->Set( Format => 'unknown', Value => $expiredBy ) > 0;
+
+my $authTokens = RT::AuthTokens->new( RT->SystemUser );
+$authTokens->Limit(
+    FIELD           => 'Expires',
+    VALUE           => $expiredByDateObj->ISO(),
+    OPERATOR        => '<=',
+    ENTRYAGGREGATOR => 'AND',
+);
+$authTokens->Limit(
+    FIELD           => 'Expires',
+    VALUE           => 'NULL',
+    OPERATOR        => '!=',
+    ENTRYAGGREGATOR => 'AND',
+);
+$authTokens->Limit(
+    FIELD           => 'Expires',
+    VALUE           => '',
+    OPERATOR        => '!=',
+    ENTRYAGGREGATOR => 'AND',
+);
+
+my %expiredTokensByUser = ();
+while ( my $row = $authTokens->Next ) {
+    $expiredTokensByUser{ $row->Owner } = [
+        @{ $expiredTokensByUser{ $row->Owner } || [] },
+        {
+            desc    => $row->Description,
+            expires => $row->Expires
+        }
+    ];
+}
+
+# Load our template.  If we cannot load the template, abort
+# immediately rather than failing through many loops.
+my $token_template = RT::Template->new( RT->SystemUser );
+my ( $ret, $msg ) = $token_template->Load('Email Auth Token Expiry');
+unless ($ret) {
+    print loc("Failed to load template")
+        . " 'Email Auth Token Expiry': "
+        . $msg
+        . ".  Cannot continue.\n";
+    exit 1;
+}
+
+foreach my $userId ( keys %expiredTokensByUser ) {
+    my $userObj = RT::User->new( RT->SystemUser );
+    my ( $ret, $msg ) = $userObj->Load($userId);
+    if ( $ret ) {
+        my $userName     = $userObj->RealName || $userObj->Name;
+        my $userEmail    = $userObj->EmailAddress;
+        my $emailContent = $print ? "Expiring Auth Tokens for '$userName':\n"
+                                  : "Hello, $userName.\n\nThe following auth tokens will expire by " . $expiredByDateObj->Date . ":\n\n";
+        foreach my $authToken ( @{ $expiredTokensByUser{$userId} } ) {
+            $emailContent .= $print ? "\t" : "";
+            $emailContent .= $authToken->{desc} . ' expires on ' . $authToken->{expires} . "\n";
+        }
+
+        if ( $print ) {
+            print "$emailContent\n";
+        } else {
+            unless ( $userEmail ) {
+                RT->Logger->warning( loc("No email for User") . ": $userName" );
+                next;
+            }
+            ( $ret, $msg ) = $token_template->Parse( Argument => $emailContent );
+            unless ($ret) {
+                print loc("Failed to parse template")
+                    . " 'Email Auth Token Expiry'.  Cannot continue.\n";
+                exit 1;
+            }
+
+            # Set our sender and recipient.
+            $token_template->MIMEObj->head->replace(
+                'From', Encode::encode( "UTF-8", RT::Config->Get('CorrespondAddress') ) );
+            $token_template->MIMEObj->head->replace(
+                'To',   Encode::encode( "UTF-8", $userEmail ) );
+
+            my $ok = RT::Interface::Email::SendEmail(
+                Entity => $token_template->MIMEObj );
+
+            if ( ! $ok ) {
+                RT->Logger->error("Failed to send expiring auth tokens email to $userEmail");
+            }
+        }
+
+    } else {
+        RT->Logger->error("Could not load User with id $userId: $msg");
+    }
+}
+
+
+__END__
+
+=head1 NAME
+
+rt-email-expiring-auth-tokens - email users about expiring auth tokens
+
+=head1 SYNOPSIS
+
+    rt-email-expiring-auth-tokens --expired-by Expire-By-Date [--print] [--help]
+
+=head1 DESCRIPTION
+
+This script is a tool to email users about their expiring auth tokens.
+
+=head1 OPTIONS
+
+=over
+
+=item expired-by
+
+Any auth tokens that expire by this date will be included in the email.
+
+Format is YYYY-MM-DD.
+
+=item print
+
+Print the expiring auth tokens to STDOUT; don't email them.
+
+=item help
+
+Print this message
+
+=back

commit bb0653c12bab6c58743296293acef4fb18591649
Author: Brad Embree <brad at bestpractical.com>
Date:   Mon May 1 19:57:01 2023 -0700

    Add database schema change

diff --git a/etc/schema.Oracle b/etc/schema.Oracle
index f0f783f80d..c456422d8a 100644
--- a/etc/schema.Oracle
+++ b/etc/schema.Oracle
@@ -569,7 +569,8 @@ CREATE TABLE AuthTokens (
     Creator         NUMBER(11,0)    DEFAULT 0 NOT NULL,
     Created         DATE,
     LastUpdatedBy   NUMBER(11,0)    DEFAULT 0 NOT NULL,
-    LastUpdated     DATE
+    LastUpdated     DATE,
+    Expires         DATE
 );
 
 CREATE INDEX AuthTokensOwner ON AuthTokens (Owner);
diff --git a/etc/schema.Pg b/etc/schema.Pg
index 9ab84bba1c..ca27dbb9e3 100644
--- a/etc/schema.Pg
+++ b/etc/schema.Pg
@@ -811,6 +811,7 @@ CREATE TABLE AuthTokens (
     Created           timestamp                DEFAULT NULL,
     LastUpdatedBy     integer         NOT NULL DEFAULT 0,
     LastUpdated       timestamp                DEFAULT NULL,
+    Expires           timestamp                DEFAULT NULL,
     PRIMARY KEY (id)
 );
 
diff --git a/etc/schema.SQLite b/etc/schema.SQLite
index cdafced4f8..e9c107c652 100644
--- a/etc/schema.SQLite
+++ b/etc/schema.SQLite
@@ -598,7 +598,8 @@ CREATE TABLE AuthTokens (
     Creator           int(11)         NOT NULL DEFAULT 0,
     Created           timestamp                DEFAULT NULL,
     LastUpdatedBy     int(11)         NOT NULL DEFAULT 0,
-    LastUpdated       timestamp                DEFAULT NULL
+    LastUpdated       timestamp                DEFAULT NULL,
+    Expires           timestamp                DEFAULT NULL
 );
 
 CREATE INDEX AuthTokensOwner on AuthTokens (Owner);
diff --git a/etc/schema.mysql b/etc/schema.mysql
index 5a359e5e9d..049d74538f 100644
--- a/etc/schema.mysql
+++ b/etc/schema.mysql
@@ -590,6 +590,7 @@ CREATE TABLE AuthTokens (
     Created           datetime                 DEFAULT NULL,
     LastUpdatedBy     int(11)         NOT NULL DEFAULT 0,
     LastUpdated       datetime                 DEFAULT NULL,
+    Expires           datetime                 DEFAULT NULL,
     PRIMARY KEY (id)
 ) ENGINE=InnoDB CHARACTER SET utf8mb4;
 
diff --git a/etc/upgrade/5.0.5/schema.Oracle b/etc/upgrade/5.0.5/schema.Oracle
new file mode 100644
index 0000000000..c86d412ff2
--- /dev/null
+++ b/etc/upgrade/5.0.5/schema.Oracle
@@ -0,0 +1 @@
+ALTER TABLE AuthTokens ADD Expires DATE;
diff --git a/etc/upgrade/5.0.5/schema.Pg b/etc/upgrade/5.0.5/schema.Pg
new file mode 100644
index 0000000000..a750698056
--- /dev/null
+++ b/etc/upgrade/5.0.5/schema.Pg
@@ -0,0 +1 @@
+ALTER TABLE AuthTokens ADD COLUMN Expires timestamp DEFAULT NULL;
diff --git a/etc/upgrade/5.0.5/schema.SQLite b/etc/upgrade/5.0.5/schema.SQLite
new file mode 100644
index 0000000000..a750698056
--- /dev/null
+++ b/etc/upgrade/5.0.5/schema.SQLite
@@ -0,0 +1 @@
+ALTER TABLE AuthTokens ADD COLUMN Expires timestamp DEFAULT NULL;
diff --git a/etc/upgrade/5.0.5/schema.mysql b/etc/upgrade/5.0.5/schema.mysql
new file mode 100644
index 0000000000..93887a48b7
--- /dev/null
+++ b/etc/upgrade/5.0.5/schema.mysql
@@ -0,0 +1 @@
+ALTER TABLE AuthTokens ADD COLUMN Expires datetime DEFAULT NULL;

commit 8e9b2b2b707a52fd9d8c23edc1c043c240408d11
Author: Brad Embree <brad at bestpractical.com>
Date:   Mon May 1 19:56:08 2023 -0700

    Add template for auth token expiry email

diff --git a/etc/initialdata b/etc/initialdata
index 32da7e63e7..4f79505616 100644
--- a/etc/initialdata
+++ b/etc/initialdata
@@ -778,6 +778,14 @@ Hour:         { $SubscriptionObj->SubValue('Hour') }
 }
 }
 },
+               {   Queue       => '0',
+                   Name        => 'Email Auth Token Expiry', # loc
+                   Description => 'Email template for emailing users about expiring auth tokens', # loc
+                   Content => q[Subject: Expiring Auth Token Notification
+
+{ $Argument }
+],
+               },
 );
 
 @Scrips = (
diff --git a/etc/upgrade/5.0.5/content b/etc/upgrade/5.0.5/content
new file mode 100644
index 0000000000..0ce329a09a
--- /dev/null
+++ b/etc/upgrade/5.0.5/content
@@ -0,0 +1,14 @@
+use strict;
+use warnings;
+
+our @Templates = (
+
+               {   Queue       => '0',
+                   Name        => 'Email Auth Token Expiry',    # loc
+                   Description => 'Email template for emailing users about expiring auth tokens',  # loc
+                   Content => q[Subject: Expiring Auth Token Notification
+
+{ $Argument }
+],
+               },
+);

commit fa612f7dabde3913d0ad708daa4ceb6f86d53738
Author: Brad Embree <brad at bestpractical.com>
Date:   Sun Apr 30 17:10:51 2023 -0700

    Check for Expires when validating AuthToken

diff --git a/lib/RT/AuthToken.pm b/lib/RT/AuthToken.pm
index f75e5671d2..59593a011d 100644
--- a/lib/RT/AuthToken.pm
+++ b/lib/RT/AuthToken.pm
@@ -237,6 +237,20 @@ sub IsToken {
     my $self = shift;
     my $value = shift;
 
+    # check if token has expired
+    if ( my $expires = $self->__Value('Expires') ) {
+        my $expiresObj = RT::Date->new( $self->CurrentUser );
+        my $nowObj     = RT::Date->new( $self->CurrentUser );
+
+        $expiresObj->Set( Format => 'ISO', Value => $expires );
+        $nowObj->SetToNow();
+
+        if ( $expiresObj->Unix < $nowObj->Unix ) {
+            $RT::Logger->debug("Auth Token has expired.");
+            return 0;
+        }
+    }
+
     my $stored = $self->__Value('Token');
 
     # If it's a new-style (>= RT 4.0) password, it starts with a '!'

commit de25f29e9ce908ac080f1090176a2edd933e3fed
Author: Brad Embree <brad at bestpractical.com>
Date:   Sun Apr 30 17:10:20 2023 -0700

    Display Expires details

diff --git a/share/html/Elements/AuthToken/List b/share/html/Elements/AuthToken/List
index b341a59c6c..a9ae035556 100644
--- a/share/html/Elements/AuthToken/List
+++ b/share/html/Elements/AuthToken/List
@@ -67,6 +67,16 @@
           <&|/l&>never used</&>
 %       }
         </span>
+%       if ( $token->Expires ) {
+%           if ( $token->ExpiresObj->Unix < $now->Unix ) {
+        <span class="last-used font-italic ml-2" style="color:red">
+          <% loc("Expired") %>
+%           } else {
+        <span class="last-used font-italic ml-2">
+          <% '(' . loc("expires on") . ' ' . $token->ExpiresObj->Date . ' at ' . $token->ExpiresObj->Time . ')' %>
+%           }
+        </span>
+%       }
       </div>
       <a class="button btn btn-sm btn-primary float-right" href="#edit-auth-token-<% $token->id %>" data-toggle="modal" rel="modal:open"><% loc('Edit') %></a>
     </li>
@@ -78,6 +88,9 @@
 <%INIT>
 my $tokens = RT::AuthTokens->new($session{CurrentUser});
 $tokens->LimitOwner(VALUE => $Owner);
+
+my $now = RT::Date->new($session{CurrentUser});
+$now->SetToNow;
 </%INIT>
 
 <%ARGS>

commit e3c9675a57eda3f7625f9caaa01c5a209e1817a1
Author: Brad Embree <brad at bestpractical.com>
Date:   Sun Apr 30 17:09:52 2023 -0700

    Add ExpiresObj method

diff --git a/lib/RT/AuthToken.pm b/lib/RT/AuthToken.pm
index 205d4cf13f..f75e5671d2 100644
--- a/lib/RT/AuthToken.pm
+++ b/lib/RT/AuthToken.pm
@@ -277,6 +277,19 @@ sub LastUsedObj {
     return $date;
 }
 
+=head2 ExpiresObj
+
+L</Expires> as an L<RT::Date> object.
+
+=cut
+
+sub ExpiresObj {
+    my $self = shift;
+    my $date = RT::Date->new($self->CurrentUser);
+    $date->Set(Format => 'sql', Value => $self->Expires);
+    return $date;
+}
+
 =head1 PRIVATE METHODS
 
 Documented for internal use only, do not call these from outside

commit 9ad2157c91a62d2f3f4890f3db0a8b5eca971198
Author: Brad Embree <brad at bestpractical.com>
Date:   Sun Apr 30 17:08:45 2023 -0700

    Add Expires input controls

diff --git a/share/html/Elements/AuthToken/Create b/share/html/Elements/AuthToken/Create
index cfe8350598..e34f2fa261 100644
--- a/share/html/Elements/AuthToken/Create
+++ b/share/html/Elements/AuthToken/Create
@@ -55,7 +55,7 @@
         </a>
       </div>
       <div class="modal-body">
-        <form method="POST">
+        <form method="POST" id="createAuthToken">
           <input type="hidden" name="Owner" value="<% $Owner %>">
 %         if ( $require_password ){
           <div class="form-row">
@@ -76,6 +76,32 @@
               <input class="form-control" type="text" name="Description" value="<% $Description %>" size="16" />
             </div>
           </div>
+          <div class="form-row">
+            <div class="label col-4">
+              <span class="prev-icon-helper"><&|/l&>Expires</&>:</span>\
+<span class="far fa-question-circle icon-helper" data-toggle="tooltip" data-placement="top" data-original-title="<% loc("Set an optional Expires date?") %>"></span>
+            </div>
+            <div class="col-8">
+              <div class="form-row">
+              <div class="custom-control custom-checkbox">
+                <input type="checkbox" id="ExpiresCheckbox" name="ExpiresCheckbox" class="custom-control-input" value="0" />
+                <label class="custom-control-label" for="ExpiresCheckbox">Set Expires Date</label>
+              </div>
+              </div>
+              <div class="form-row">
+              <select name="ExpiresSelect" id="ExpiresSelect" class="form-control selectpicker">
+                <option value="1M" ><&|/l&>1 Month</&></option>
+                <option value="3M"><&|/l&>3 Months</&></option>
+                <option value="6M"><&|/l&>6 Months</&></option>
+                <option value="1Y"><&|/l&>1 Year</&></option>
+                <option value="Custom"><&|/l&>Custom Date</&></option>
+              </select>
+              </div>
+              <div class="form-row">
+              <& /Elements/SelectDate, Name=>"Expires", id=>"Expires", Default => $Expires, ShowTime => 1 &>
+              </div>
+            </div>
+          </div>
 
           <div class="form-row">
             <div class="col-12">
@@ -88,6 +114,81 @@
   </div>
 </div>
 
+<script>
+  jQuery("#ExpiresSelect").prop( "disabled", true );
+  jQuery("#Expires").prop( "disabled", true );
+
+  // Expires input needs to be enabled when the form is submitted to read its value
+  jQuery("#createAuthToken").submit(
+    function(e){
+      jQuery("#Expires").prop( "disabled", false );
+      return true;
+    }
+  );
+
+  var onExpiresSelectChange = function() {
+    var expiresSelectVal = jQuery("#ExpiresSelect option:selected").val();
+    var expires          = jQuery("#Expires");
+
+    // make sure expires is enabled so we can change value
+    expires.prop( "disabled", false );
+    if ( jQuery("#ExpiresSelect").prop("disabled") ) {
+      // Expires date options are disabled so Expires should be blank
+      expires.val("");
+    } else {
+      // Expires date options are enabled so determine what we should set
+      // Expires value to based on selected Expires option
+      if ( expiresSelectVal != 'Custom' ) {
+        var date   = new Date();
+        var regexp = /(\d)(\w)/;
+        var match  = expiresSelectVal.match(regexp);
+
+        if ( match != null ) {
+          if ( match[2] == "M" ) {
+            date.setMonth( date.getMonth() + parseInt( match[1] ) );
+          } else {
+            date.setFullYear( date.getFullYear() + parseInt( match[1] ) );
+          }
+          expires.val( date.toISOString().substr(0, 10) + ' 00:00:00' );
+        }
+      }
+    }
+
+    // now enable/disable expires
+    expires.prop( "disabled", expiresSelectVal != "Custom" );
+  };
+
+  jQuery("#ExpiresCheckbox").click(
+    function(){
+      var expiresSelect = jQuery("#ExpiresSelect");
+
+      var disable = true;
+      if ( expiresSelect.prop("disabled") ) {
+        // user is enabling the Expires date options
+        disable = false;
+      } else {
+        // user is disabling the Expires date options
+        disable = true;
+
+        // set back to default value
+        expiresSelect.val("1M");
+
+        jQuery(".selectpicker").selectpicker("refresh");
+      }
+
+      expiresSelect.prop( "disabled", disable );
+
+      jQuery(".selectpicker").selectpicker("refresh");
+      onExpiresSelectChange();
+    }
+  );
+  jQuery("#ExpiresSelect").change(
+    function(){
+      onExpiresSelectChange();
+    }
+  );
+</script>
+
 <%INIT>
 # Don't require password for systems with some form of federated auth,
 # or if configured to not require a password
@@ -101,4 +202,5 @@ if ( RT->Config->Get('DisablePasswordForAuthToken') or not $res{'CanSet'}) {
 <%ARGS>
 $Owner
 $Description => ''
+$Expires => ''
 </%ARGS>

commit 2e9a28b3bf5332117aac4383a3952a6652343f32
Author: Brad Embree <brad at bestpractical.com>
Date:   Sun Apr 30 17:06:56 2023 -0700

    Allow optional Expires param for new AuthToken

diff --git a/lib/RT/AuthToken.pm b/lib/RT/AuthToken.pm
index 729391caef..205d4cf13f 100644
--- a/lib/RT/AuthToken.pm
+++ b/lib/RT/AuthToken.pm
@@ -81,6 +81,10 @@ object's CurrentUser, then the AdminUsers permission is required.
 
 A human-readable description of what this token will be used for.
 
+=item Expires
+
+An optional date for when this token should expire.
+
 =back
 
 Returns a tuple of (status, msg) on failure and (id, msg, authstring) on
@@ -110,10 +114,14 @@ sub Create {
 
     my $token = $self->_GenerateToken;
 
+    # delete Expires arg if it is empty
+    delete $args{Expires}
+        unless $args{Expires};
+
     my ( $id, $msg ) = $self->SUPER::Create(
         Token => $self->_CryptToken($token),
         map { $_ => $args{$_} } grep {exists $args{$_}}
-            qw(Owner Description),
+            qw(Owner Description Expires),
     );
     unless ($id) {
         return (0, $self->loc("Authentication token create failed: [_1]", $msg));
@@ -366,6 +374,7 @@ sub _CoreAccessible {
         Created       => { read => 1, type => 'datetime',       default => '',  auto => 1 },
         LastUpdatedBy => { read => 1, type => 'int(11)',        default => '0', auto => 1 },
         LastUpdated   => { read => 1, type => 'datetime',       default => '',  auto => 1 },
+        Expires       => { read => 1, type => 'datetime',       default => '',  auto => 1 },
     }
 }
 
diff --git a/lib/RT/Interface/Web.pm b/lib/RT/Interface/Web.pm
index 444eb1c24e..909a1d7f89 100644
--- a/lib/RT/Interface/Web.pm
+++ b/lib/RT/Interface/Web.pm
@@ -5270,6 +5270,7 @@ sub ProcessAuthToken {
             my ( $ok, $msg, $auth_string ) = $token->Create(
                 Owner       => $args_ref->{Owner},
                 Description => $args_ref->{Description},
+                Expires     => $args_ref->{Expires},
             );
             if ($ok) {
                 push @results, $msg;

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


hooks/post-receive
-- 
rt


More information about the rt-commit mailing list