%# BEGIN BPS TAGGED BLOCK {{{
%#
%# COPYRIGHT:
%#
%# This software is Copyright (c) 1996-2025 Best Practical Solutions, LLC
%#                                          <sales@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 => $title &>
<& /Elements/Tabs &>

<& /Elements/ListActions &>


<form action="<% RT->Config->Get('WebPath')%>/Admin/Tools/GnuPG.html" name="ImportKeys" method="POST" enctype="multipart/form-data" class="mx-auto max-width-lg">
<&|/Widgets/TitleBox, title => loc('Import Keys'), content_class => 'mx-auto width-md' &>
% my %options = RT->Config->Get('GnuPGOptions');
% if ( $options{'keyserver'} ) {
  <&| /Elements/LabeledValue, Label => '' &>
    <div class="input-group">
      <input name="Query" class="form-control" value="<% $ARGS{Query} // '' %>" size="40" />
      <input name="Search" type="submit" class="button btn btn-primary" value="<&|/l&>Search</&>" />
    </div>
  </&>
% if ( @search_results ) {
  <&| /Elements/LabeledValue, Label => '' &>
      <div class="custom-control custom-checkbox">
        <input type="checkbox" class="custom-control-input checkbox" id="KeyAll" name="KeyAll" value="1" onclick="setCheckbox(this, 'Key')" />
        <label class="custom-control-label" for="KeyAll"><&|/l&>Check All</&></label>
      </div>
  </&>
% for my $item ( @search_results ) {
  <&| /Elements/LabeledValue, Label => loc("Key") &>
      <div class="custom-control custom-checkbox">
        <input type="checkbox" class="custom-control-input checkbox" id="Key-<% $item->{Key} %>" name="Key" value="<% $item->{Key} %>" />
        <label class="custom-control-label" for="Key-<% $item->{Key} %>"><% $item->{Summary} %></label>
      </div>
  </&>
% }
% }

% }

  <&| /Elements/LabeledValue, Label => loc("Content") &>
      <textarea class="form-control" name="Content" rows="8"><% $ARGS{Content} // '' %></textarea>
  </&>
  <div class="form-row">
    <div class="col-12">
      <& /Elements/Submit, Name => 'Import', Label => loc('Import') &>
    </div>
  </div>
</&>
</form>

<&|/Widgets/TitleBox, title => loc('GnuPG Public Keys') &>

% if ( $public{info} && @{$public{info}} ) {
<form action="<% RT->Config->Get('WebPath')%>/Admin/Tools/GnuPG.html" name="PublicKeys" method="POST" enctype="multipart/form-data">
    <table class="table collection-as-table">
        <tr>
            <th>
              <div class="custom-control custom-checkbox">
                <input type="checkbox" name="PublicKeyAll" value="1" id="PublicKeyAll" class="checkbox custom-control-input" onclick="setCheckbox(this, 'PublicKey')" />
                <label class="custom-control-label" for="PublicKeyAll"></label>
              </div>
            </th>
            <th><% loc('Summary') %></th>
            <th><% loc('Trust Level') %></th>
        </tr>
% for my $item ( @{$public{info}} ) {
        <tr>
            <td>
              <div class="custom-control custom-checkbox">
                <input type="checkbox" name="PublicKey" id="PublicKey-<% $item->{Fingerprint} %>" value="<% $item->{Fingerprint} %>" class="checkbox custom-control-input" <% $delete{$item->{Fingerprint}} ? 'checked="checked"' : '' |n %> />
                <label class="custom-control-label" for="PublicKey-<% $item->{Fingerprint} %>"></label>
              </div>
            </td>
            <td><% $item->{Formatted} %></td>
            <td><% $owner_trust_level{$item->{OwnerTrustChar}} || loc('Not set') %></td>
        </tr>
% }
    </table>
    <hr />

    <div class="form-row">
      <div class="label col-3">
        <% loc('Trust Level' ) %>:
      </div>
      <div class="input-group col-6">
        <select name="OwnerTrustLevel" class="form-control selectpicker">
            <option value=""  <% $OwnerTrustLevel eq '' ? 'selected="selected"' : '' |n %> >-</option>
            <option value="1" <% $OwnerTrustLevel eq 1 ? 'selected="selected"' : '' |n %> ><% $owner_trust_level{1} %></option>
            <option value="2" <% $OwnerTrustLevel eq 2 ? 'selected="selected"' : '' |n %> ><% $owner_trust_level{2} %></option>
            <option value="3" <% $OwnerTrustLevel eq 3 ? 'selected="selected"' : '' |n %> ><% $owner_trust_level{3} %></option>
            <option value="4" <% $OwnerTrustLevel eq 4 ? 'selected="selected"' : '' |n %> ><% $owner_trust_level{4} %></option>
            <option value="5" <% $OwnerTrustLevel eq 5 ? 'selected="selected"' : '' |n %> ><% $owner_trust_level{5} %></option>
        </select>
      </div>
    </div>

    <div class="form-row">
      <div class="col-12">
        <& /Elements/Submit, Label => loc('Delete'), Name => 'DeletePublic', CheckboxNameRegex => '/^PublicKey(All)?$/', CheckAll => 1, ClearAll => 1 &>
        <& /Elements/Submit, Label => loc('Save Changes'), Name => 'TrustPublic' &>
      </div>
    </div>
</form>
% } else {
<p class="mt-3 mb-1 ml-3"><&|/l&>No public keys found.</&></p>
% }

</&>

<&|/Widgets/TitleBox, title => loc('GnuPG Private Keys') &>

% if ( $private{info} && @{$private{info}} ) {
<form action="<% RT->Config->Get('WebPath')%>/Admin/Tools/GnuPG.html" name="PrivateKeys" method="POST" enctype="multipart/form-data">
    <table class="table collection-as-table">
        <tr>
            <th>
              <div class="custom-control custom-checkbox">
                <input type="checkbox" name="PrivateKeyAll" value="1" id="PrivateKeyAll" class="checkbox custom-control-input" onclick="setCheckbox(this, 'PrivateKey')" />
                <label class="custom-control-label" for="PrivateKeyAll"></label>
              </div>
            <th><% loc('Summary') %></th>
        </tr>
% for my $item ( @{$private{info}} ) {
        <tr>
            <td>
              <div class="custom-control custom-checkbox">
                <input type="checkbox" name="PrivateKey" id="PrivateKey-<% $item->{Fingerprint} %>" value="<% $item->{Fingerprint} %>" class="checkbox custom-control-input" <% $delete{$item->{Fingerprint}} ? 'checked="checked"' : '' |n %> />
                <label class="custom-control-label" for="PrivateKey-<% $item->{Fingerprint} %>"></label>
              </div>
            </td>
            <td><% $item->{Formatted} %></td>
        </tr>
% }
    </table>
    <hr />
    <div class="form-row">
      <div class="col-12">
        <& /Elements/Submit, Label => loc('Delete'), Name => 'DeletePrivate', CheckboxNameRegex => '/^PrivateKey(All)?$/', CheckAll => 1, ClearAll => 1 &>
      </div>
    </div>
</form>
% } else {
<p class="mt-3 mb-1 ml-3"><&|/l&>No private keys found.</&></p>
% }

</&>
<%INIT>

my $title = loc('Manage GnuPG Keys');
unless ( $session{'CurrentUser'}->HasRight( Object => $RT::System, Right => 'SuperUser' ) ) {
    Abort( loc('This feature is only available to system administrators.') );
}

my @results;
my %delete;

my %owner_trust_level = (
    1 => loc("I don't know or won't say"),
    2 => loc("I do NOT trust"),
    3 => loc("I trust marginally"),
    4 => loc("I trust fully"),
    5 => loc("I trust ultimately"),

    q => loc("I don't know or won't say"),
    n => loc("I do NOT trust"),
    m => loc("I trust marginally"),
    f => loc("I trust fully"),
    u => loc("I trust ultimately"),
);

require RT::Crypt::GnuPG;

my @search_results;
if ( $ARGS{Search} ) {
    if ( $ARGS{Query} ) {
        my %ret = RT::Crypt::GnuPG->SearchKey( $ARGS{Query} );
        @search_results = @{$ret{results}};
        push @results, split /\n+/, $ret{logger} unless @search_results;
    }
}
elsif ( $ARGS{Import} ) {

    # show admin detailed imported messages
    if ( $ARGS{Key} ) {
        for my $key ( ref $ARGS{Key} ? @{ $ARGS{Key} } : $ARGS{Key} ) {
            my %ret = RT::Crypt::GnuPG->ReceiveKey( $key );
            push @results, split /\n+/, $ret{logger};
        }
    }

    if ( $ARGS{Content} ) {
        my %ret = RT::Crypt::GnuPG->ImportKey( $ARGS{Content} );
        push @results, split /\n+/, $ret{logger};
    }
}
elsif ( $ARGS{TrustPublic} ) {
    if ( length $ARGS{OwnerTrustLevel} && $ARGS{PublicKey} ) {
        for my $key ( ref $ARGS{PublicKey} ? @{ $ARGS{PublicKey} } : $ARGS{PublicKey} ) {
            my %ret = RT::Crypt::GnuPG->TrustKey( $key, $ARGS{OwnerTrustLevel} );
            if ( $ret{exit_code} == 0 ) {
                if ( $ret{logger} ) {

                    # success messages are like "changing ownertrust
                    # from 6 to 4", which is useless and misleading to
                    # end users, so we hide them here.

                    RT->Logger->debug( $ret{logger} );
                    push @results, loc( "Key [_1] trust level is updated", substr( $key, -8 ) );
                }
            }
            elsif ( $ret{logger} ) {
                push @results, split /\n+/, $ret{logger};
            }
        }
    }
}
else {
    for my $type (qw/Public Private/) {
        next unless $ARGS{"Delete$type"};
        my $value = $ARGS{"${type}Key"};
        for my $key ( ref $value ? @$value : $value ) {
            $delete{$key} ||= 1;
            my %ret = RT::Crypt::GnuPG->DeleteKey($key);

            if ( $ret{exit_code} == 0 ) {
                # delete is silent, no extra debug messages
                push @results, loc( "Key [_1] is deleted", substr( $key, -8 ) );
            }
            elsif ( $ret{logger} ) {
                push @results, split /\n+/, $ret{logger};
            }
        }
    }
}

MaybeRedirectForResults(
    Actions => \@results,
    Path    => '/Admin/Tools/GnuPG.html',
);

my %public = RT::Crypt::GnuPG->GetKeysInfo( Force => 1 );
my %private = RT::Crypt::GnuPG->GetKeysInfo( Force => 1, Type => 'private' );

</%INIT>

<%ARGS>
$OwnerTrustLevel => ''
</%ARGS>
