[Rt-commit] rt branch, 5.0/core-rt-authentoken, repushed

Craig Kaiser craig at bestpractical.com
Thu May 7 18:02:07 EDT 2020


The branch 5.0/core-rt-authentoken was deleted and repushed:
       was 0f005b83ff49104b8de55503ba8061e5f39765e8
       now c41a3f2a7129e7e3eb2754587432bd27eb2f5cd3

1: 549b57065e ! 1: 85aad74ba5 Core RT::Authen::Token
    @@ -9,8 +9,8 @@
              ObjectCustomRoles
              configurations_id_seq
              Configurations
    -+        rtxauthtokens_id_seq
    -+        RTxAuthTokens
    ++        authtokens_id_seq
    ++        AuthTokens
          );
      
          my $db_user = RT->Config->Get('DatabaseUser');
    @@ -23,9 +23,9 @@
      CREATE INDEX Configurations1 ON Configurations (LOWER(Name), Disabled);
      CREATE INDEX Configurations2 ON Configurations (Disabled);
     +
    -+CREATE SEQUENCE RTxAuthTokens_seq;
    -+CREATE TABLE RTxAuthTokens (
    -+    id              NUMBER(11,0)    CONSTRAINT RTxAuthTokens_key PRIMARY KEY,
    ++CREATE SEQUENCE AuthTokens_seq;
    ++CREATE TABLE AuthTokens (
    ++    id              NUMBER(11,0)    CONSTRAINT AuthTokens_key PRIMARY KEY,
     +    Owner           NUMBER(11,0)    DEFAULT 0 NOT NULL,
     +    Token           VARCHAR2(256),
     +    Description     varchar2(255)   DEFAULT '',
    @@ -36,7 +36,7 @@
     +    LastUpdated     DATE
     +);
     +
    -+CREATE INDEX RTxAuthTokensOwner ON RTxAuthTokens (Owner);
    ++CREATE INDEX AuthTokensOwner ON AuthTokens (Owner);
     
     diff --git a/etc/schema.Pg b/etc/schema.Pg
     --- a/etc/schema.Pg
    @@ -45,9 +45,9 @@
      CREATE INDEX Configurations1 ON Configurations (LOWER(Name), Disabled);
      CREATE INDEX Configurations2 ON Configurations (Disabled);
      
    -+CREATE SEQUENCE rtxauthtokens_id_seq;
    -+CREATE TABLE RTxAuthTokens (
    -+    id                integer                  DEFAULT nextval('rtxauthtokens_id_seq'),
    ++CREATE SEQUENCE authtokens_id_seq;
    ++CREATE TABLE AuthTokens (
    ++    id                integer                  DEFAULT nextval('authtokens_id_seq'),
     +    Owner             integer         NOT NULL DEFAULT 0,
     +    Token             varchar(256)    NULL,
     +    Description       varchar(255)    NOT NULL DEFAULT '',
    @@ -59,7 +59,7 @@
     +    PRIMARY KEY (id)
     +);
     +
    -+CREATE INDEX RTxAuthTokensOwner ON RTxAuthTokens (Owner);
    ++CREATE INDEX AuthTokensOwner ON AuthTokens (Owner);
     
     diff --git a/etc/schema.SQLite b/etc/schema.SQLite
     --- a/etc/schema.SQLite
    @@ -68,7 +68,7 @@
      CREATE INDEX Configurations1 ON Configurations (Name, Disabled);
      CREATE INDEX Configurations2 ON Configurations (Disabled);
      
    -+CREATE TABLE RTxAuthTokens (
    ++CREATE TABLE AuthTokens (
     +    id                INTEGER PRIMARY KEY,
     +    Owner             int(11)         NOT NULL DEFAULT 0,
     +    Token             varchar(256)    collate NOCASE NULL  ,
    @@ -80,7 +80,7 @@
     +    LastUpdated       timestamp                DEFAULT NULL
     +);
     +
    -+CREATE INDEX RTxAuthTokensOwner on RTxAuthTokens (Owner);
    ++CREATE INDEX AuthTokensOwner on AuthTokens (Owner);
     
     diff --git a/etc/schema.mysql b/etc/schema.mysql
     --- a/etc/schema.mysql
    @@ -89,7 +89,7 @@
      CREATE INDEX Configurations1 ON Configurations (Name, Disabled);
      CREATE INDEX Configurations2 ON Configurations (Disabled);
      
    -+CREATE TABLE RTxAuthTokens (
    ++CREATE TABLE AuthTokens (
     +    id                int(11)         NOT NULL AUTO_INCREMENT,
     +    Owner             int(11)         NOT NULL DEFAULT 0,
     +    Token             varchar(256)    NULL,
    @@ -102,28 +102,28 @@
     +    PRIMARY KEY (id)
     +) ENGINE=InnoDB DEFAULT CHARSET=utf8;
     +
    -+CREATE INDEX RTxAuthTokensOwner ON RTxAuthTokens (Owner);
    -
    -diff --git a/etc/upgrade/4.5.5/acl.Oracle b/etc/upgrade/4.5.5/acl.Oracle
    -new file mode 100644
    ---- /dev/null
    -+++ b/etc/upgrade/4.5.5/acl.Oracle
    ++CREATE INDEX AuthTokensOwner ON AuthTokens (Owner);
    +
    +diff --git a/etc/upgrade/4.5.7/acl.Oracle b/etc/upgrade/4.5.7/acl.Oracle
    +new file mode 100644
    +--- /dev/null
    ++++ b/etc/upgrade/4.5.7/acl.Oracle
     @@
     +sub acl { return () }
     +1;
     
    -diff --git a/etc/upgrade/4.5.5/acl.Pg b/etc/upgrade/4.5.5/acl.Pg
    -new file mode 100644
    ---- /dev/null
    -+++ b/etc/upgrade/4.5.5/acl.Pg
    +diff --git a/etc/upgrade/4.5.7/acl.Pg b/etc/upgrade/4.5.7/acl.Pg
    +new file mode 100644
    +--- /dev/null
    ++++ b/etc/upgrade/4.5.7/acl.Pg
     @@
     +sub acl {
     +    my $dbh = shift;
     +
     +    my @acls;
     +    my @tables = qw (
    -+        rtxauthtokens_id_seq
    -+        RTxAuthTokens
    ++        authtokens_id_seq
    ++        AuthTokens
     +    );
     +
     +    my $db_user = RT->Config->Get('DatabaseUser');
    @@ -148,22 +148,27 @@
     +1;
     +
     
    -diff --git a/etc/upgrade/4.5.5/acl.mysql b/etc/upgrade/4.5.5/acl.mysql
    -new file mode 100644
    ---- /dev/null
    -+++ b/etc/upgrade/4.5.5/acl.mysql
    +diff --git a/etc/upgrade/4.5.7/acl.mysql b/etc/upgrade/4.5.7/acl.mysql
    +new file mode 100644
    +--- /dev/null
    ++++ b/etc/upgrade/4.5.7/acl.mysql
     @@
     +sub acl { return () }
     +1;
     
    -diff --git a/etc/upgrade/4.5.5/schema.Oracle b/etc/upgrade/4.5.5/schema.Oracle
    -new file mode 100644
    ---- /dev/null
    -+++ b/etc/upgrade/4.5.5/schema.Oracle
    -@@
    -+CREATE SEQUENCE RTxAuthTokens_seq;
    -+CREATE TABLE RTxAuthTokens (
    -+    id              NUMBER(11,0)    CONSTRAINT RTxAuthTokens_key PRIMARY KEY,
    +diff --git a/etc/upgrade/4.5.5/content b/etc/upgrade/4.5.7/content
    +similarity index 100%
    +rename from etc/upgrade/4.5.5/content
    +rename to etc/upgrade/4.5.7/content
    +
    +diff --git a/etc/upgrade/4.5.7/schema.Oracle b/etc/upgrade/4.5.7/schema.Oracle
    +new file mode 100644
    +--- /dev/null
    ++++ b/etc/upgrade/4.5.7/schema.Oracle
    +@@
    ++CREATE SEQUENCE AuthTokens_seq;
    ++CREATE TABLE AuthTokens (
    ++    id              NUMBER(11,0)    CONSTRAINT AuthTokens_key PRIMARY KEY,
     +    Owner           NUMBER(11,0)    DEFAULT 0 NOT NULL,
     +    Token           VARCHAR2(256),
     +    Description     varchar2(255)   DEFAULT '',
    @@ -174,17 +179,17 @@
     +    LastUpdated     DATE
     +);
     +
    -+CREATE INDEX RTxAuthTokensOwner ON RTxAuthTokens (Owner);
    -+
    -
    -diff --git a/etc/upgrade/4.5.5/schema.Pg b/etc/upgrade/4.5.5/schema.Pg
    -new file mode 100644
    ---- /dev/null
    -+++ b/etc/upgrade/4.5.5/schema.Pg
    -@@
    -+CREATE SEQUENCE rtxauthtokens_id_seq;
    -+CREATE TABLE RTxAuthTokens (
    -+    id                integer                  DEFAULT nextval('rtxauthtokens_id_seq'),
    ++CREATE INDEX AuthTokensOwner ON AuthTokens (Owner);
    ++
    +
    +diff --git a/etc/upgrade/4.5.7/schema.Pg b/etc/upgrade/4.5.7/schema.Pg
    +new file mode 100644
    +--- /dev/null
    ++++ b/etc/upgrade/4.5.7/schema.Pg
    +@@
    ++CREATE SEQUENCE authtokens_id_seq;
    ++CREATE TABLE AuthTokens (
    ++    id                integer                  DEFAULT nextval('authtokens_id_seq'),
     +    Owner             integer         NOT NULL DEFAULT 0,
     +    Token             varchar(256)    NULL,
     +    Description       varchar(255)    NOT NULL DEFAULT '',
    @@ -196,14 +201,14 @@
     +    PRIMARY KEY (id)
     +);
     +
    -+CREATE INDEX RTxAuthTokensOwner ON RTxAuthTokens (Owner);
    -
    -diff --git a/etc/upgrade/4.5.5/schema.SQLite b/etc/upgrade/4.5.5/schema.SQLite
    -new file mode 100644
    ---- /dev/null
    -+++ b/etc/upgrade/4.5.5/schema.SQLite
    -@@
    -+CREATE TABLE RTxAuthTokens (
    ++CREATE INDEX AuthTokensOwner ON AuthTokens (Owner);
    +
    +diff --git a/etc/upgrade/4.5.7/schema.SQLite b/etc/upgrade/4.5.7/schema.SQLite
    +new file mode 100644
    +--- /dev/null
    ++++ b/etc/upgrade/4.5.7/schema.SQLite
    +@@
    ++CREATE TABLE AuthTokens (
     +    id                INTEGER PRIMARY KEY,
     +    Owner             int(11)         NOT NULL DEFAULT 0,
     +    Token             varchar(256)    collate NOCASE NULL  ,
    @@ -215,15 +220,15 @@
     +    LastUpdated       timestamp                DEFAULT NULL
     +);
     +
    -+CREATE INDEX RTxAuthTokensOwner on RTxAuthTokens (Owner);
    -+
    -
    -diff --git a/etc/upgrade/4.5.5/schema.mysql b/etc/upgrade/4.5.5/schema.mysql
    -new file mode 100644
    ---- /dev/null
    -+++ b/etc/upgrade/4.5.5/schema.mysql
    -@@
    -+CREATE TABLE RTxAuthTokens (
    ++CREATE INDEX AuthTokensOwner on AuthTokens (Owner);
    ++
    +
    +diff --git a/etc/upgrade/4.5.7/schema.mysql b/etc/upgrade/4.5.7/schema.mysql
    +new file mode 100644
    +--- /dev/null
    ++++ b/etc/upgrade/4.5.7/schema.mysql
    +@@
    ++CREATE TABLE AuthTokens (
     +    id                int(11)         NOT NULL AUTO_INCREMENT,
     +    Owner             int(11)         NOT NULL DEFAULT 0,
     +    Token             varchar(256)    NULL,
    @@ -236,7 +241,7 @@
     +    PRIMARY KEY (id)
     +) ENGINE=InnoDB DEFAULT CHARSET=utf8;
     +
    -+CREATE INDEX RTxAuthTokensOwner ON RTxAuthTokens (Owner);
    ++CREATE INDEX AuthTokensOwner ON AuthTokens (Owner);
     +
     
     diff --git a/lib/RT.pm b/lib/RT.pm
    @@ -352,14 +357,13 @@
     +
     +=head1 DESCRIPTION
     +
    -+This module adds the ability for users to generate and login with
    -+authentication tokens. Users with the C<ManageAuthTokens> permission
    -+will see a new "Auth Tokens" menu item under "Logged in as ____" ->
    -+Settings. On that page they will be able to generate new tokens and
    -+modify or revoke existing tokens.
    ++Allow for users to generate and login with authentication tokens. Users
    ++with the C<ManageAuthTokens> permission will see a new "Auth Tokens" menu
    ++item under "Logged in as ____" -> Settings. On that page they will be able
    ++to generate new tokens and modify or revoke existing tokens.
     +
     +Once you have an authentication token, you may use it in place of a
    -+password to log into RT. (Additionally, L<RT::Extension::REST2> allows
    ++password to log into RT. (Additionally, L<REST2> allows
     +for using auth tokens with the C<Authorization: token> HTTP header.) One
     +common use case is to use an authentication token as an
     +application-specific password, so that you may revoke that application's
    @@ -381,6 +385,7 @@
     +Apache configuration to allow RT to access the Authorization header.
     +
     +    SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1
    ++
     +=cut
     +
     +1;
    @@ -390,11 +395,59 @@
     --- /dev/null
     +++ b/lib/RT/Authen/Token/AuthToken.pm
     @@
    ++# BEGIN BPS TAGGED BLOCK {{{
    ++#
    ++# COPYRIGHT:
    ++#
    ++# This software is Copyright (c) 1996-2019 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 strict;
     +use warnings;
     +use 5.10.1;
     +
    -+package RT::AuthToken;
    ++package RT::Authen::Token::AuthToken;
     +use base 'RT::Record';
     +
     +require RT::User;
    @@ -403,7 +456,7 @@
     +
     +=head1 NAME
     +
    -+RT::AuthToken - Represents an authentication token for a user
    ++RT::Authen::Token::AuthToken - Represents an authentication token for a user
     +
     +=cut
     +
    @@ -616,7 +669,7 @@
     +=head1 PRIVATE METHODS
     +
     +Documented for internal use only, do not call these from outside
    -+RT::AuthToken itself.
    ++RT::Authen::Token::AuthToken itself.
     +
     +=head2 _Set
     +
    @@ -697,7 +750,7 @@
     +    return $self->_CryptToken_bcrypt(@_);
     +}
     +
    -+sub Table { "RTxAuthTokens" }
    ++sub Table { "AuthTokens" }
     +
     +sub _CoreAccessible {
     +    {
    @@ -720,15 +773,63 @@
     --- /dev/null
     +++ b/lib/RT/Authen/Token/AuthTokens.pm
     @@
    ++# BEGIN BPS TAGGED BLOCK {{{
    ++#
    ++# COPYRIGHT:
    ++#
    ++# This software is Copyright (c) 1996-2019 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 strict;
     +use warnings;
     +
    -+package RT::AuthTokens;
    ++package RT::Authen::Token::AuthTokens;
     +use base 'RT::SearchBuilder';
     +
     +=head1 NAME
     +
    -+RT::AuthTokens - a collection of L<RT::AuthToken> objects
    ++RT::Authen::Token::AuthTokens - a collection of L<RT::Authen::Token::AuthToken> objects
     +
     +=cut
     +
    @@ -751,7 +852,7 @@
     +
     +sub NewItem {
     +    my $self = shift;
    -+    return RT::AuthToken->new( $self->CurrentUser );
    ++    return RT::Authen::Token::AuthToken->new( $self->CurrentUser );
     +}
     +
     +=head2 _Init
    @@ -767,7 +868,7 @@
     +    return $self->SUPER::_Init( @_ );
     +}
     +
    -+sub Table { "RTxAuthTokens" }
    ++sub Table { "AuthTokens" }
     +
     +1;
     +
    @@ -787,50 +888,63 @@
              # Authenticate if the user is trying to login via user/pass query args
              my ($authed, $msg) = AttemptPasswordAuthentication($ARGS);
      
    -+        unless ($authed) {
    -+            my $get_env = sub {
    -+                my $key = shift;
    -+                if (RT::Interface::Web->can('RequestENV')) {
    -+                    return RT::Interface::Web::RequestENV($key)
    -+                }
    -+                return $ENV{$key};
    -+            };
    -+
    -+            my ($pass, $user) = ('', '');
    -+            if (($get_env->('HTTP_AUTHORIZATION')||'') =~ /^token (.*)$/i) {
    -+                $pass ||= $1;
    -+            }
    -+            unless ( defined $pass ) {
    -+                my ($user_obj, $token) = RT::Authen::Token->UserForAuthString($pass, $user);
    -+                if ( $user_obj ) {
    -+                    # log in
    -+                    my $remote_addr = $get_env->('REMOTE_ADDR');
    -+                    $RT::Logger->info("Successful login for @{[$user_obj->Name]} from $remote_addr using authentication token #@{[$token->Id]} (\"@{[$token->Description]}\")");
    -+
    -+                    # It's important to nab the next page from the session before we blow
    -+                    # the session away
    -+                    my $next = RT::Interface::Web::RemoveNextPage($ARGS->{'next'});
    -+                    $next = $next->{'url'} if ref $next;
    -+
    -+                    RT::Interface::Web::InstantiateNewSession();
    -+                    $HTML::Mason::Commands::session{'CurrentUser'} = $user_obj;
    -+
    -+                    # Really the only time we don't want to redirect here is if we were
    -+                    # passed user and pass as query params in the URL.
    -+                    if ($next) {
    -+                        RT::Interface::Web::Redirect($next);
    -+                    }
    -+                    elsif ($ARGS->{'next'}) {
    -+                        # Invalid hash, but still wants to go somewhere, take them to /
    -+                        RT::Interface::Web::Redirect(RT->Config->Get('WebURL'));
    -+                    }
    -+                }
    -+            }
    -+        }
    ++        AttemptTokenAuthentication($ARGS) unless $authed;
     +
              unless ($authed) {
                  my $m = $HTML::Mason::Commands::m;
      
    +@@
    +     }
    + }
    + 
    ++sub AttemptTokenAuthentication {
    ++    my $ARGS = shift;
    ++    return if _UserLoggedIn();
    ++
    ++    my $get_env = sub {
    ++        my $key = shift;
    ++        if (RT::Interface::Web->can('RequestENV')) {
    ++            return RT::Interface::Web::RequestENV($key)
    ++        }
    ++        return $ENV{$key};
    ++    };
    ++
    ++    my ($pass, $user) = ('', '');
    ++    if (($get_env->('HTTP_AUTHORIZATION')||'') =~ /^token (.*)$/i) {
    ++        $pass ||= $1;
    ++    }
    ++    unless ( defined $pass ) {
    ++        my ($user_obj, $token) = RT::Authen::Token->UserForAuthString($pass, $user);
    ++        if ( $user_obj ) {
    ++            # log in
    ++            my $remote_addr = $get_env->('REMOTE_ADDR');
    ++            $RT::Logger->info("Successful login for @{[$user_obj->Name]} from $remote_addr using authentication token #@{[$token->Id]} (\"@{[$token->Description]}\")");
    ++
    ++            # It's important to nab the next page from the session before we blow
    ++            # the session away
    ++            my $next = RT::Interface::Web::RemoveNextPage($ARGS->{'next'});
    ++            $next = $next->{'url'} if ref $next;
    ++
    ++            RT::Interface::Web::InstantiateNewSession();
    ++            $HTML::Mason::Commands::session{'CurrentUser'} = $user_obj;
    ++
    ++            # Really the only time we don't want to redirect here is if we were
    ++            # passed user and pass as query params in the URL.
    ++            if ($next) {
    ++                RT::Interface::Web::Redirect($next);
    ++            }
    ++            elsif ($ARGS->{'next'}) {
    ++                # Invalid hash, but still wants to go somewhere, take them to /
    ++                RT::Interface::Web::Redirect(RT->Config->Get('WebURL'));
    ++            }
    ++        }
    ++    }
    ++}
    ++
    ++
    + =head2 LoadSessionFromCookie
    + 
    + Load or setup a session cookie for the current user.
     
     diff --git a/lib/RT/Interface/Web/MenuBuilder.pm b/lib/RT/Interface/Web/MenuBuilder.pm
     --- a/lib/RT/Interface/Web/MenuBuilder.pm
    @@ -873,6 +987,54 @@
     --- /dev/null
     +++ b/share/html/Admin/Users/AuthTokens.html
     @@
    ++%# BEGIN BPS TAGGED BLOCK {{{
    ++%#
    ++%# COPYRIGHT:
    ++%#
    ++%# This software is Copyright (c) 1996-2019 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 }}}
    ++
     +<& /Admin/Elements/Header, Title => loc("[_1]'s authentication tokens",$UserObj->Name)  &>
     +<& /Elements/Tabs &>
     +<& /Elements/ListActions, actions => \@results &>
    @@ -910,6 +1072,53 @@
     --- /dev/null
     +++ b/share/html/Elements/AuthToken/CreateButton
     @@
    ++%# BEGIN BPS TAGGED BLOCK {{{
    ++%#
    ++%# COPYRIGHT:
    ++%#
    ++%# This software is Copyright (c) 1996-2019 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 }}}
     +<%ARGS>
     +$Owner
     +$ShowCreateForm => 0
    @@ -941,6 +1150,53 @@
     --- /dev/null
     +++ b/share/html/Elements/AuthToken/CreateForm
     @@
    ++%# BEGIN BPS TAGGED BLOCK {{{
    ++%#
    ++%# COPYRIGHT:
    ++%#
    ++%# This software is Copyright (c) 1996-2019 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 }}}
     +<%ARGS>
     +$Owner
     +$Error => ''
    @@ -988,13 +1244,60 @@
     --- /dev/null
     +++ b/share/html/Elements/AuthToken/CreateResults
     @@
    ++%# BEGIN BPS TAGGED BLOCK {{{
    ++%#
    ++%# COPYRIGHT:
    ++%#
    ++%# This software is Copyright (c) 1996-2019 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 }}}
     +<%ARGS>
     +$Owner => undef
     +$Password => ''
     +$Description => ''
     +</%ARGS>
     +<%INIT>
    -+my $token = RT::AuthToken->new($session{CurrentUser});
    ++my $token = RT::Authen::Token::AuthToken->new($session{CurrentUser});
     +# Don't require password for systems with some form of federated auth
     +my %res = $session{'CurrentUser'}->CurrentUserRequireToSetPassword();
     +my ($error, $authstring);
    @@ -1036,11 +1339,58 @@
     --- /dev/null
     +++ b/share/html/Elements/AuthToken/List
     @@
    ++%# BEGIN BPS TAGGED BLOCK {{{
    ++%#
    ++%# COPYRIGHT:
    ++%#
    ++%# This software is Copyright (c) 1996-2019 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 }}}
     +<%ARGS>
     +$Owner
     +</%ARGS>
     +<%INIT>
    -+my $tokens = RT::AuthTokens->new($session{CurrentUser});
    ++my $tokens = RT::Authen::Token::AuthTokens->new($session{CurrentUser});
     +$tokens->LimitOwner(VALUE => $Owner);
     +</%INIT>
     +<div class="form-row authtoken-list" data-owner="<% $Owner %>">
    @@ -1100,6 +1450,53 @@
     --- /dev/null
     +++ b/share/html/Elements/AuthToken/ModifyForm
     @@
    ++%# BEGIN BPS TAGGED BLOCK {{{
    ++%#
    ++%# COPYRIGHT:
    ++%#
    ++%# This software is Copyright (c) 1996-2019 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 }}}
     +<%ARGS>
     +$Token => undef
     +$TokenObj => undef
    @@ -1107,7 +1504,7 @@
     +</%ARGS>
     +<%INIT>
     +if (!$TokenObj) {
    -+    $TokenObj = RT::AuthToken->new($session{CurrentUser});
    ++    $TokenObj = RT::Authen::Token::AuthToken->new($session{CurrentUser});
     +    $TokenObj->Load($Token);
     +}
     +
    @@ -1166,6 +1563,53 @@
     --- /dev/null
     +++ b/share/html/Elements/AuthToken/ModifyResults
     @@
    ++%# BEGIN BPS TAGGED BLOCK {{{
    ++%#
    ++%# COPYRIGHT:
    ++%#
    ++%# This software is Copyright (c) 1996-2019 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 }}}
     +<%ARGS>
     +$Token
     +$Description => ''
    @@ -1173,7 +1617,7 @@
     +$Revoke => 0
     +</%ARGS>
     +<%INIT>
    -+my $TokenObj = RT::AuthToken->new($session{CurrentUser});
    ++my $TokenObj = RT::Authen::Token::AuthToken->new($session{CurrentUser});
     +$TokenObj->Load($Token);
     +my ($error, $ok, $msg);
     +
    @@ -1202,6 +1646,53 @@
     --- /dev/null
     +++ b/share/html/Helpers/AuthToken/Create
     @@
    ++%# BEGIN BPS TAGGED BLOCK {{{
    ++%#
    ++%# COPYRIGHT:
    ++%#
    ++%# This software is Copyright (c) 1996-2019 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 }}}
     +<& /Elements/AuthToken/CreateResults, %ARGS &>
     +% $m->abort;
     
    @@ -1210,6 +1701,53 @@
     --- /dev/null
     +++ b/share/html/Helpers/AuthToken/List
     @@
    ++%# BEGIN BPS TAGGED BLOCK {{{
    ++%#
    ++%# COPYRIGHT:
    ++%#
    ++%# This software is Copyright (c) 1996-2019 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 }}}
     +<& /Elements/AuthToken/List, Owner => $ARGS{owner} &>
     +% $m->abort;
     
    @@ -1218,6 +1756,53 @@
     --- /dev/null
     +++ b/share/html/Helpers/AuthToken/Modify
     @@
    ++%# BEGIN BPS TAGGED BLOCK {{{
    ++%#
    ++%# COPYRIGHT:
    ++%#
    ++%# This software is Copyright (c) 1996-2019 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 }}}
     +<& /Elements/AuthToken/ModifyResults, %ARGS &>
     +% $m->abort;
     
    @@ -1226,6 +1811,54 @@
     --- /dev/null
     +++ b/share/html/Prefs/AuthTokens.html
     @@
    ++%# BEGIN BPS TAGGED BLOCK {{{
    ++%#
    ++%# COPYRIGHT:
    ++%#
    ++%# This software is Copyright (c) 1996-2019 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 }}}
    ++
     +<& /Elements/Header, Title => loc('My authentication tokens') &>
     +<& /Elements/Tabs &>
     +<& /Elements/ListActions, actions => \@results &>
2: e3979eb579 ! 2: a4767ecdf9 Make RT::Authen::Token behave like other parts of RT
    @@ -1,18 +1,101 @@
     Author: Craig <craig at bestpractical.com>
     
    -    Migrate to elevator theme
    -
    -diff --git a/share/html/Elements/AuthToken/CreateButton b/share/html/Elements/AuthToken/CreateButton
    +    Make RT::Authen::Token behave like other parts of RT
    +
    +diff --git a/lib/RT/Authen/Token/AuthTokens.pm b/lib/RT/Authen/Token/AuthTokens.pm
    +--- a/lib/RT/Authen/Token/AuthTokens.pm
    ++++ b/lib/RT/Authen/Token/AuthTokens.pm
    +@@
    + 
    + RT::Authen::Token::AuthTokens - a collection of L<RT::Authen::Token::AuthToken> objects
    + 
    +-=cut
    +-
    + =head2 LimitOwner
    + 
    + Limit Owner
    +
    +diff --git a/lib/RT/Interface/Web/MenuBuilder.pm b/lib/RT/Interface/Web/MenuBuilder.pm
    +--- a/lib/RT/Interface/Web/MenuBuilder.pm
    ++++ b/lib/RT/Interface/Web/MenuBuilder.pm
    +@@
    +         $page->child( history => title => loc('History'), path => "/Admin/Tools/ConfigHistory.html" );
    +     }
    + 
    ++    if ( $request_path =~ m{^/Prefs/AuthTokens} ) {
    ++        $page->child( select_auth_token => title => loc('Select'), path => '/Prefs/AuthTokens.html');
    ++        $page->child( create_auth_token => title => loc('Create'),
    ++            raw_html => q[<a class="btn menu-item" href="#create-auth-token" data-toggle="modal" rel="modal:open">].loc("Create")."</a>"
    ++        );
    ++    }
    ++
    +     # due to historical reasons of always having been in /Elements/Tabs
    +     $HTML::Mason::Commands::m->callback( CallbackName => 'Privileged', Path => $request_path, Search_Args => $args, Has_Query => $has_query, ARGSRef => \%args, CallbackPage => '/Elements/Tabs' );
    + }
    +@@
    +                     $page->child( keys    => title => loc('Private keys'),   path => "/Admin/Users/Keys.html?id=" . $id );
    +                 }
    +                 $page->child( 'summary'   => title => loc('User Summary'),   path => "/User/Summary.html?id=" . $id );
    ++
    ++                my $auth_tokens = $page->child(auth_tokens => title => loc('Auth Tokens'), path => '/Admin/Users/AuthTokens.html?id=' . $id);
    ++                $auth_tokens->child( select_auth_token => title => loc('Select'), path => '/Admin/Users/AuthTokens.html');
    ++                $auth_tokens->child( create_auth_token => title => loc('Create'),
    ++                    raw_html => q[<a class="btn menu-item" href="#create-auth-token" data-toggle="modal" rel="modal:open">].loc("Create")."</a>"
    ++                );
    +             }
    +         }
    + 
    +@@
    +             $page->child( create => title => loc('Create'), path => "/Admin/Articles/Classes/Modify.html?Create=1" );
    +         }
    +     }
    +-
    +-    my $request_path_token = $request_path =~ s!/{2,}!/!g;
    +-    if ( $request_path_token =~ m{^(/Admin/Users|/User/(Summary|History)\.html)} and $admin->child("users") ) {
    +-        if ( $HTML::Mason::Commands::DECODED_ARGS->{'id'} && $HTML::Mason::Commands::DECODED_ARGS->{'id'} =~ /^\d+$/ ) {
    +-            my $id = $HTML::Mason::Commands::DECODED_ARGS->{'id'};
    +-            my $obj = RT::User->new( $HTML::Mason::Commands::session{'CurrentUser'} );
    +-            $obj->Load($id);
    +-
    +-            if ( $obj and $obj->id ) {
    +-                my $tabs = PageMenu();
    +-                $tabs->child(auth_tokens => title => loc('Auth Tokens'), path => '/Admin/Users/AuthTokens.html?id=' . $id);
    +-            }
    +-        }
    +-    }
    + }
    + 
    + sub BuildSelfServiceNav {
    +
    +diff --git a/share/html/Elements/AuthToken/CreateButton b/share/html/Admin/Users/AuthToken/Create.html
    +similarity index 75%
    +rename from share/html/Elements/AuthToken/CreateButton
    +rename to share/html/Admin/Users/AuthToken/Create.html
     --- a/share/html/Elements/AuthToken/CreateButton
    -+++ b/share/html/Elements/AuthToken/CreateButton
    -@@
    --<%ARGS>
    ++++ b/share/html/Admin/Users/AuthToken/Create.html
    +@@
    + %# those contributions and any derivatives thereof.
    + %#
    + %# END BPS TAGGED BLOCK }}}
    ++
    ++<& /Elements/AuthToken/Create, Owner => $UserObj->Id, %ARGS &>
    ++
    + <%ARGS>
     -$Owner
     -$ShowCreateForm => 0
     -$CreateToken => 0
    --</%ARGS>
    --<%INIT>
    --</%INIT>
    ++$id => undef
    + </%ARGS>
    + <%INIT>
    ++my @results;
    ++
    ++my $UserObj = RT::User->new( $session{'CurrentUser'} );
    ++$UserObj->Load( $id );
    ++unless ( $UserObj->id ) {
    ++    Abort( loc("Couldn't load user #[_1]", $id) );
    ++}
    ++$id = $ARGS{'id'} = $UserObj->id;
    + </%INIT>
     -% if ($CreateToken) {
     -  <&| /Widgets/TitleBox, title => loc("Create Auth Token") &>
     -    <& /Elements/AuthToken/CreateResults, %ARGS &>
    @@ -32,10 +115,306 @@
     -</form>
     -% }
     
    +diff --git a/share/html/Admin/Users/AuthTokens.html b/share/html/Admin/Users/AuthTokens.html
    +--- a/share/html/Admin/Users/AuthTokens.html
    ++++ b/share/html/Admin/Users/AuthTokens.html
    +@@
    + <& /Elements/Tabs &>
    + <& /Elements/ListActions, actions => \@results &>
    + 
    +-<div class="form-row">
    +-  <div class="auth-tokens col-12">
    +-    <p><&|/l&>Authentication tokens allow other applications to use your user
    +-        account without having to share your password, while allowing you to
    +-       revoke access on an application-specific basis. Changing your password
    +-        <em>does not</em> invalidate your auth tokens; you must revoke them here.</&>
    +-    </p>
    +-  </div>
    +-</div>
    ++<& /Elements/AuthToken/AuthTokens, Owner => $id, Path => '/Prefs/AuthTokens.html', %ARGS &>
    + 
    +-<& /Elements/AuthToken/CreateButton, %ARGS, Owner => $UserObj->Id &>
    +-<& /Elements/AuthToken/List, %ARGS, Owner => $UserObj->Id &>
    +-</div>
    +-
    +-<%ARGS>
    +-$id => undef
    +-</%ARGS>
    + <%INIT>
    +-my @results;
    +-
    + my $UserObj = RT::User->new( $session{'CurrentUser'} );
    + $UserObj->Load( $id );
    + unless ( $UserObj->id ) {
    +@@
    + }
    + $id = $ARGS{'id'} = $UserObj->id;
    + </%INIT>
    ++
    ++<%ARGS>
    ++$id => undef
    ++</%ARGS>
    +
    +diff --git a/share/html/Elements/AuthToken/AuthTokens b/share/html/Elements/AuthToken/AuthTokens
    +new file mode 100644
    +--- /dev/null
    ++++ b/share/html/Elements/AuthToken/AuthTokens
    +@@
    ++%# BEGIN BPS TAGGED BLOCK {{{
    ++%#
    ++%# COPYRIGHT:
    ++%#
    ++%# This software is Copyright (c) 1996-2019 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 }}}
    ++<& /Elements/ListActions, actions => \@results &>
    ++
    ++<div class="form-row">
    ++    <div class="col-12">
    ++    <p><&|/l&>Authentication tokens allow other applications to use your user account without having to share your password, while allowing you to revoke access on an application-specific basis. Changing your password <em>does not</em> invalidate your auth tokens; you must revoke them here.</&></p>
    ++    </div>
    ++
    ++% if ( $Authstring ) {
    ++    <div class="modal authtoken-success" id="auth-token-auth-string">
    ++    <div class="modal-dialog modal-dialog-centered" role="document">
    ++        <div class="modal-content">
    ++        <div class="modal-header">
    ++            <&|/l,$Description &>This is your new authentication token. Treat it carefully like a password. Please save it now because you cannot access it again.</&>
    ++            <a id="auth-token-close-modal" href="javascript:void(0)" class="close" data-dismiss="modal" aria-label="Close">
    ++            <span aria-hidden="true">×</span>
    ++            </a>
    ++        </div>
    ++        <div class="col-12 authstring text-center">
    ++            <span><% $Authstring %></span>
    ++        </div>
    ++        </div>
    ++    </div>
    ++    </div>
    ++% }
    ++
    ++    <div class="col-12">
    ++    <& /Elements/AuthToken/Create, Path => $Path, Owner => $Owner &>
    ++    </div>
    ++
    ++    <div class="col-12">
    ++    <& /Elements/AuthToken/List, Path => $Path, Owner => $Owner &>
    ++    </div>
    ++</div>
    ++
    ++<%INIT>
    ++my @results;
    ++
    ++if ( $Update || $Revoke ) {
    ++    my $error = '';
    ++
    ++    my $token = RT::Authen::Token::AuthToken->new( $session{CurrentUser} );
    ++    $token->Load( $ARGS{'Token'} );
    ++    my ($ok, $msg);
    ++    if ( $Update ) {
    ++        if ( !length( $Description ) ) {
    ++            push @results, loc( "Description cannot be blank." );
    ++        }
    ++
    ++        if ( $Description ne $token->Description ) {
    ++            ($ok, $msg) = $token->SetDescription( $Description );
    ++            push @results, $msg;
    ++        }
    ++    }
    ++    elsif ($Revoke) {
    ++        ($ok, $msg) = $token->Delete;
    ++        push @results, $msg;
    ++    }
    ++}
    ++
    ++my ($authstring);
    ++if ( $CreateToken ) {
    ++    my $token = RT::Authen::Token::AuthToken->new( $session{CurrentUser} );
    ++
    ++    # Don't require password for systems with some form of federated auth
    ++    my %res = $session{'CurrentUser'}->CurrentUserRequireToSetPassword();
    ++
    ++    if ( !length( $Description ) ) {
    ++        push @results, loc("Description cannot be blank.");
    ++    }
    ++    elsif ( $res{'CanSet'} && !length( $ARGS{'Password'} ) ) {
    ++        push @results, loc("Please enter your current password.");
    ++    }
    ++    elsif ( $res{'CanSet'} && !$session{CurrentUser}->IsPassword($ARGS{'Password'} ) ) {
    ++        push @results, loc("Please enter your current password correctly.");
    ++    }
    ++    else {
    ++        ((my $ok), (my $msg), $Authstring) = $token->Create(
    ++            Owner       => $Owner,
    ++            Description => $Description,
    ++        );
    ++        if ( $ok ) {
    ++            push @results, loc( "New token successfully created" );
    ++        }
    ++        else {
    ++            push @results, loc( "Something went wrong" );
    ++        }
    ++    }
    ++}
    ++</%INIT>
    ++
    ++<%ARGS>
    ++$Path
    ++$Owner
    ++$Update      => 0
    ++$Revoke      => 0
    ++$CreateToken => 0
    ++$Authstring  => ''
    ++$Description => ''
    ++</%ARGS>
    +
    +diff --git a/share/html/Elements/AuthToken/Create b/share/html/Elements/AuthToken/Create
    +new file mode 100644
    +--- /dev/null
    ++++ b/share/html/Elements/AuthToken/Create
    +@@
    ++%# BEGIN BPS TAGGED BLOCK {{{
    ++%#
    ++%# COPYRIGHT:
    ++%#
    ++%# This software is Copyright (c) 1996-2019 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 class="modal" id="create-auth-token">
    ++  <div class="modal-dialog modal-dialog-centered" role="document">
    ++    <div class="modal-content">
    ++        <div class="modal-header">
    ++        <h5 class="modal-title"><&|/l&>Create auth token</&></h5>
    ++        <a id="auth-token-close-modal" href="javascript:void(0)" class="close" data-dismiss="modal" aria-label="Close">
    ++          <span aria-hidden="true">×</span>
    ++        </a>
    ++        </div>
    ++        <div class="modal-body">
    ++          <form class="authtoken-form" method="POST" action="<% RT->Config->Get('WebPath') . $Path %>">
    ++            <div class="form-row">
    ++              <input type="hidden" name="Owner" value="<% $Owner %>">
    ++% if ( $res{'CanSet'} ){
    ++              <div class="label col-3">
    ++                <&|/l, $session{'CurrentUser'}->Name()&>[_1]'s current password</&>:
    ++              </div>
    ++              <div class="value col-9">
    ++                <input class="form-control" type="password" name="Password" size="16" autocomplete="off" /></td>
    ++              </div>
    ++% }
    ++              <div class="col-3 label">
    ++                <&|/l&>Description</&>:<br><em><&|/l&>What's this token for?</&></em>
    ++              </div>
    ++              <div class="value col-9">
    ++                <input class="form-control" type="text" name="Description" value="<% $Description %>" size="16" />
    ++              </div>
    ++            </div>
    ++
    ++            <div class="form-row">
    ++              <div class="col-12">
    ++                <& /Elements/Submit, Label => loc("Create"), Name => 'CreateToken' &>
    ++              </div>
    ++            </div>
    ++          </form>
    ++        </div>
    ++    </div>
    ++  </div>
    ++</div>
    ++
    ++<%INIT>
    ++# Don't require password for systems with some form of federated auth
    ++my %res = $session{'CurrentUser'}->CurrentUserRequireToSetPassword();
    ++</%INIT>
    ++
    ++<%ARGS>
    ++$Path
    ++$Owner
    ++$Description => ''
    ++</%ARGS>
    +
     diff --git a/share/html/Elements/AuthToken/CreateForm b/share/html/Elements/AuthToken/CreateForm
     --- a/share/html/Elements/AuthToken/CreateForm
     +++ b/share/html/Elements/AuthToken/CreateForm
     @@
    + %# END BPS TAGGED BLOCK }}}
      <%ARGS>
      $Owner
     -$Error => ''
    @@ -150,9 +529,16 @@
     --- a/share/html/Elements/AuthToken/List
     +++ b/share/html/Elements/AuthToken/List
     @@
    - my $tokens = RT::AuthTokens->new($session{CurrentUser});
    - $tokens->LimitOwner(VALUE => $Owner);
    - </%INIT>
    + %# those contributions and any derivatives thereof.
    + %#
    + %# END BPS TAGGED BLOCK }}}
    +-<%ARGS>
    +-$Owner
    +-</%ARGS>
    +-<%INIT>
    +-my $tokens = RT::Authen::Token::AuthTokens->new($session{CurrentUser});
    +-$tokens->LimitOwner(VALUE => $Owner);
    +-</%INIT>
     -<div class="form-row authtoken-list" data-owner="<% $Owner %>">
     -  <div class="col-6">
     -    <span class="loading"><img src="<%RT->Config->Get('WebPath')%>/static/images/loading.gif" alt="<%loc('Loading')%>" title="<%loc('Loading')%>" /></span>
    @@ -198,7 +584,7 @@
     +            <& /Elements/AuthToken/ModifyResults, %ARGS, Token => $token->Id, Owner => $Owner &>
     +% }
     +% }
    -+            <form class="authtoken-form" method="post" data-ajax-url="<% RT->Config->Get('WebPath') %>/Helpers/AuthToken/Modify" action="<% RT->Config->Get('WebPath') %><% $r->uri %>">
    ++            <form class="authtoken-form" method="post" action="<% RT->Config->Get('WebPath') . $Path %>">
     +              <div class="form-row">
     +% if ($ARGS{id}) {
     +                <input type="hidden" name="id" value="<% $ARGS{id} %>">
    @@ -272,12 +658,23 @@
      % }
        </ul>
      % }
    + </div>
    ++
    ++<%INIT>
    ++my $tokens = RT::Authen::Token::AuthTokens->new($session{CurrentUser});
    ++$tokens->LimitOwner(VALUE => $Owner);
    ++</%INIT>
    ++
    ++<%ARGS>
    ++$Owner
    ++$Path
    ++</%ARGS>
     
     diff --git a/share/html/Elements/AuthToken/ModifyForm b/share/html/Elements/AuthToken/ModifyForm
     --- a/share/html/Elements/AuthToken/ModifyForm
     +++ b/share/html/Elements/AuthToken/ModifyForm
     @@
    -     $TokenObj = RT::AuthToken->new($session{CurrentUser});
    +     $TokenObj = RT::Authen::Token::AuthToken->new($session{CurrentUser});
          $TokenObj->Load($Token);
      }
     -
    @@ -408,45 +805,35 @@
     --- a/share/html/Prefs/AuthTokens.html
     +++ b/share/html/Prefs/AuthTokens.html
     @@
    - <& /Elements/ListActions, actions => \@results &>
    - 
    - <div class="form-row">
    + 
    + <& /Elements/Header, Title => loc('My authentication tokens') &>
    + <& /Elements/Tabs &>
    +-<& /Elements/ListActions, actions => \@results &>
    + 
    +-<div class="form-row">
     -  <div class="auth-tokens col-12">
    -+  <div class="col-12">
    -     <p><&|/l&>Authentication tokens allow other applications to use your user
    -         account without having to share your password, while allowing you to
    -        revoke access on an application-specific basis. Changing your password
    -         <em>does not</em> invalidate your auth tokens; you must revoke them here.
    -     </&></p>
    -   </div>
    +-    <p><&|/l&>Authentication tokens allow other applications to use your user
    +-        account without having to share your password, while allowing you to
    +-       revoke access on an application-specific basis. Changing your password
    +-        <em>does not</em> invalidate your auth tokens; you must revoke them here.
    +-    </&></p>
    +-  </div>
     -</div>
    - 
    +-
     -<& /Elements/AuthToken/CreateButton, %ARGS, Owner => $UserObj->Id &>
     -<& /Elements/AuthToken/List, %ARGS, Owner => $UserObj->Id &>
    -+  <div class="col-12">
    -+    <& /Elements/AuthToken/CreateForm, %ARGS, Owner => $UserObj->Id &>
    -+  </div>
    -+
    -+  <div id="auth-token-messages" class="auth-token-messages col-12">
    -+  </div>
    -+
    -+  <div class="col-12">
    -+    <& /Elements/AuthToken/List, %ARGS, Owner => $UserObj->Id &>
    -+  </div>
    - </div>
    +-</div>
    ++<& /Elements/AuthToken/AuthTokens, Owner => $owner, Path => '/Prefs/AuthTokens.html', %ARGS &>
      
      <%INIT>
    -
    -diff --git a/share/static/css/elevator-light/rt-authen-token.css b/share/static/css/elevator-light/rt-authen-token.css
    ---- a/share/static/css/elevator-light/rt-authen-token.css
    -+++ b/share/static/css/elevator-light/rt-authen-token.css
    -@@
    -     float: left;
    - }
    - 
    -+.auth-token-messages {
    -+    margin: 1rem 0rem 0rem 0px;
    -+}
    +-my @results;
    +-my $UserObj = $session{'CurrentUser'}->UserObj;
    ++my $owner = $session{'CurrentUser'}->UserObj->Id;
    + </%INIT>
    +
    +diff --git a/share/static/images/loading.gif b/share/static/images/loading.gif
    +deleted file mode 100644
    +Binary files a/share/static/images/loading.gif and /dev/null differ
     
     diff --git a/share/static/js/rt-authen-token.js b/share/static/js/rt-authen-token.js
     --- a/share/static/js/rt-authen-token.js
    @@ -471,49 +858,64 @@
     -        showModal(container.find('.authtoken-form-container').html());
     -    });
     -
    -     var refreshTokenList = function () {
    -         var list = jQuery('.authtoken-list');
    -         jQuery.post(
    -@@
    - 
    -     var submitForm = function (form, extraParams) {
    -         var payload = form.serializeArray();
    -+        var name = extraParams[0].name;
    -+
    -         if (extraParams) {
    -             Array.prototype.push.apply(payload, extraParams);
    -         }
    -@@
    -         form.addClass('submitting');
    -         form.find('input').attr('disabled', true);
    - 
    +-    var refreshTokenList = function () {
    +-        var list = jQuery('.authtoken-list');
    +-        jQuery.post(
    +-            RT.Config.WebHomePath + "/Helpers/AuthToken/List",
    +-            list.data(),
    +-            function (data) {
    +-                list.replaceWith(data);
    +-            }
    +-        );
    +-    };
    +-
    +-    var submitForm = function (form, extraParams) {
    +-        var payload = form.serializeArray();
    +-        if (extraParams) {
    +-            Array.prototype.push.apply(payload, extraParams);
    +-        }
    +-
    +-        form.addClass('submitting');
    +-        form.find('input').attr('disabled', true);
    +-
     -        var renderResult = function(html) {
     -            var form = jQuery('.modal .authtoken-form');
     -            if (form.length) {
     -                form.replaceWith(html);
    -+        var renderResult = function(name, html) {
    -+            if ( name === 'CreateToken' ) {
    -+                var form = jQuery('.modal .authtoken-form');
    -+                if (form.length) {
    -+                    form.replaceWith(html);
    -+                }
    -+                else {
    -+                    jQuery('#body').append(html);
    -+                }
    -             }
    -             else {
    +-            }
    +-            else {
     -                jQuery('#body').append(html);
    -+                jQuery('#auth-token-messages').replaceWith(html);
    -             }
    -             refreshTokenList();
    -         };
    -@@
    -             data: payload,
    -             timeout: 30000, /* 30 seconds */
    -             success: function (data, status) {
    +-            }
    +-            refreshTokenList();
    +-        };
    +-
    +-        jQuery.ajax({
    +-            method: 'POST',
    +-            url: form.data('ajax-url'),
    +-            data: payload,
    +-            timeout: 30000, /* 30 seconds */
    +-            success: function (data, status) {
     -                renderResult(data);
    -+                renderResult(name, data);
    -             },
    -             error: function (xhr, status, error) {
    -                 renderResult("<p>An error has occurred. Please refresh the page and try again.<p>");
    -
    +-            },
    +-            error: function (xhr, status, error) {
    +-                renderResult("<p>An error has occurred. Please refresh the page and try again.<p>");
    +-            }
    +-        });
    +-    };
    +-
    +-    jQuery('body').on('click', '.authtoken-form button, .authtoken-form input[type=submit]', function (e) {
    +-        e.preventDefault();
    +-        var button = jQuery(this);
    +-
    +-        var params = [{ name: button.attr('name'), value: button.attr('value') }];
    +-        submitForm(button.closest('form'), params);
    +-    });
    +-
    +-    jQuery('body').on('submit', '.authtoken-form', function (e) {
    +-        e.preventDefault();
    +-        submitForm(jQuery(this));
    +-    });
    ++    jQuery('#auth-token-auth-string').modal('show');
    + });
    +-
    +
3: e7043c1549 < -:  ------- Migrate Authen-Token code to work like other RT pages
4: 0f005b83ff ! 3: c41a3f2a71 Add documentation for using token auth
    @@ -5,6 +5,16 @@
     diff --git a/docs/authentication.pod b/docs/authentication.pod
     --- a/docs/authentication.pod
     +++ b/docs/authentication.pod
    +@@
    + provide new user creation as well as password setting and control of RT's
    + privileged flag for existing users.
    + 
    ++There is also built in token generation for users to authentificate with a
    ++token, for more information on this see L<RT::Authen::Token>.
    ++
    + =head1 External Authentication
    + 
    + There are two primary types of external authentication: in one you type your
     @@
          </Location>
      
    @@ -45,7 +55,7 @@
     +
      =head1 DESCRIPTION
      
    - This module adds the ability for users to generate and login with
    + Allow for users to generate and login with authentication tokens. Users
     @@
      database just like passwords, and so cannot be recovered after they are
      generated.
    @@ -55,3 +65,16 @@
      
      If you are running RT under Apache, add the following directive to your RT
      Apache configuration to allow RT to access the Authorization header.
    +
    +diff --git a/lib/RT/Authen/Token/AuthTokens.pm b/lib/RT/Authen/Token/AuthTokens.pm
    +--- a/lib/RT/Authen/Token/AuthTokens.pm
    ++++ b/lib/RT/Authen/Token/AuthTokens.pm
    +@@
    + 
    + RT::Authen::Token::AuthTokens - a collection of L<RT::Authen::Token::AuthToken> objects
    + 
    ++=cut
    ++
    + =head2 LimitOwner
    + 
    + Limit Owner



More information about the rt-commit mailing list