Bugzilla – Attachment 185537 Details for
Bug 37025
Add CLI tool to generate/delete api keys for a given patron on a Koha instance
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 37025: (follow-up) Use consistent option handling and convert to Perl
Bug-37025-follow-up-Use-consistent-option-handling.patch (text/plain), 16.54 KB, created by
Paul Derscheid
on 2025-08-19 10:39:08 UTC
(
hide
)
Description:
Bug 37025: (follow-up) Use consistent option handling and convert to Perl
Filename:
MIME Type:
Creator:
Paul Derscheid
Created:
2025-08-19 10:39:08 UTC
Size:
16.54 KB
patch
obsolete
>From 155aca1758af4824668034860b379459b6906a3e Mon Sep 17 00:00:00 2001 >From: Paul Derscheid <paul.derscheid@lmscloud.de> >Date: Tue, 19 Aug 2025 10:30:48 +0000 >Subject: [PATCH] Bug 37025: (follow-up) Use consistent option handling and > convert to Perl > >- Convert from bash to Perl for less headaches regarding quoting >- Replace positional arguments with --generate and --delete flags >- Add --description, --borrowernumber, and --client-id options >- Add POD following Koha standards >- Update DocBook XML documentation with new flag-based interface >- Add audit logging for all API key operations via C4::Log >- Document proper usage via koha-shell wrapper for administrative access > >Test plan: >NOTE: As this tool requires Koha environment access and is installed to /usr/sbin/, >it must be run via koha-shell when using sudo: >1. Test help output: > sudo koha-shell -c "koha-api-keys --help" instancename >2. Test API key generation: > sudo koha-shell -c "koha-api-keys --generate --description 'Test key' --borrowernumber 51" instancename > => Should output Client ID and Client Secret in tab-separated format >3. Test interactive deletion (use echo to provide input): > echo "CLIENT_ID_FROM_STEP_2" | sudo koha-shell -c "koha-api-keys --delete" instancename > => Should delete successfully >4. Test scripted deletion: > sudo koha-shell -c "koha-api-keys --delete --client-id CLIENT_ID_FROM_STEP_2" instancename > => Should delete without prompting >5. Test error handling: > sudo koha-shell -c "koha-api-keys --generate --description test" instancename > => Should show error about missing --borrowernumber >6. Test invalid data: > sudo koha-shell -c "koha-api-keys --generate --description test --borrowernumber 99999" instancename > => Should show error about unknown borrowernumber >7. Verify audit logging: > After steps 2 and 4, check action_logs table for APIKEY entries: > sudo koha-mysql instancename -e "SELECT timestamp, module, action, object, info FROM action_logs WHERE module='APIKEY' ORDER BY timestamp DESC LIMIT 5;" > => Should show logged generation and deletion operations >8. Verify DocBook XML validation: > prove -v xt/verify-debian-docbook.t >9. Generate and verify man page: > xsltproc /usr/share/xml/docbook/stylesheet/docbook-xsl-ns/manpages/docbook.xsl debian/docs/koha-api-keys.xml > => Should generate koha-api-keys.8 without errors >--- > debian/docs/koha-api-keys.xml | 66 +++++--- > debian/scripts/koha-api-keys | 279 +++++++++++++++++++++++++--------- > 2 files changed, 246 insertions(+), 99 deletions(-) > >diff --git a/debian/docs/koha-api-keys.xml b/debian/docs/koha-api-keys.xml >index 741dfbf8764..62bb2458f2c 100644 >--- a/debian/docs/koha-api-keys.xml >+++ b/debian/docs/koha-api-keys.xml >@@ -29,11 +29,19 @@ > > <refsynopsisdiv> > <cmdsynopsis> >- <command>koha-api-keys</command> >- <arg choice="req">generate | delete</arg> >- <arg choice="opt"><replaceable>description</replaceable></arg> >- <arg choice="opt"><replaceable>borrowernumber</replaceable></arg> >- <arg choice="opt"><replaceable>instancename</replaceable></arg> >+ <command>sudo koha-shell</command> >+ <arg choice="req"><option>-c</option> "koha-api-keys <option>--generate</option> <option>--description</option> <replaceable>description</replaceable> <option>--borrowernumber</option> <replaceable>borrowernumber</replaceable>"</arg> >+ <arg choice="req"><replaceable>instancename</replaceable></arg> >+ </cmdsynopsis> >+ <cmdsynopsis> >+ <command>sudo koha-shell</command> >+ <arg choice="req"><option>-c</option> "koha-api-keys <option>--delete</option> [<option>--client-id</option> <replaceable>client_id</replaceable>]"</arg> >+ <arg choice="req"><replaceable>instancename</replaceable></arg> >+ </cmdsynopsis> >+ <cmdsynopsis> >+ <command>sudo koha-shell</command> >+ <arg choice="req"><option>-c</option> "koha-api-keys <option>--help</option>"</arg> >+ <arg choice="req"><replaceable>instancename</replaceable></arg> > </cmdsynopsis> > </refsynopsisdiv> > >@@ -42,46 +50,48 @@ > <para> > The <command>koha-api-keys</command> script allows administrators to generate or delete API keys associated with specific Koha patrons. These API keys can be used for authorized programmatic access to the Koha system. > </para> >- </refsect1> >- >-<refsect1> >- <title>Description</title> > <para> >- The <command>koha-api-keys</command> script allows administrators to generate or delete API keys associated with specific Koha patrons. These API keys can be used for authorized programmatic access to the Koha system. >+ As this tool requires administrative privileges and access to the Koha environment, it must be run using <command>sudo</command> and the <command>koha-shell</command> wrapper as shown in the synopsis. > </para> > </refsect1> > > <refsect1> >- <title>Arguments</title> >+ <title>Options</title> > <variablelist> > <varlistentry> >- <term><replaceable>generate</replaceable></term> >+ <term><option>--generate</option></term> > <listitem> >- <para>Generates a new API key for the specified patron.</para> >+ <para>Generate a new API key for the specified patron.</para> > </listitem> > </varlistentry> > <varlistentry> >- <term><replaceable>delete</replaceable></term> >+ <term><option>--delete</option></term> > <listitem> >- <para>Deletes an existing API key based on its Client ID.</para> >+ <para>Delete an existing API key (client ID will be prompted if not provided via --client-id).</para> > </listitem> > </varlistentry> > <varlistentry> >- <term><replaceable>description</replaceable></term> >+ <term><option>--description</option></term> > <listitem> >- <para>A description for the API key.</para> >+ <para>Description for the API key (required for --generate).</para> > </listitem> > </varlistentry> > <varlistentry> >- <term><replaceable>borrowernumber</replaceable></term> >+ <term><option>--borrowernumber</option></term> > <listitem> >- <para>The borrower number of the patron to associate the API key with.</para> >+ <para>Patron's borrower number (required for --generate).</para> > </listitem> > </varlistentry> > <varlistentry> >- <term><replaceable>instancename</replaceable></term> >+ <term><option>--client-id</option></term> > <listitem> >- <para>The name of the Koha instance to operate on.</para> >+ <para>Client ID to delete (optional for --delete, will be prompted if not provided).</para> >+ </listitem> >+ </varlistentry> >+ <varlistentry> >+ <term><option>--help</option></term> >+ <listitem> >+ <para>Display help message.</para> > </listitem> > </varlistentry> > </variablelist> >@@ -89,11 +99,17 @@ > > <refsect1> > <title>Examples</title> >- <para>Generate a new API key for patron '12345' with the description 'Patron Access':</para> >- <screen>$ koha-api-keys generate 'Patron Access' 12345 kohadev</screen> >+ <para>Generate a new API key for patron '123' with the description 'Test API access':</para> >+ <screen>$ sudo koha-shell -c "koha-api-keys --generate --description 'Test API access' --borrowernumber 123" instancename</screen> >+ >+ <para>Delete an existing API key (interactive):</para> >+ <screen>$ echo "CLIENT_ID" | sudo koha-shell -c "koha-api-keys --delete" instancename</screen> >+ >+ <para>Delete an existing API key (scripted):</para> >+ <screen>$ sudo koha-shell -c "koha-api-keys --delete --client-id a1b2c3d4-e5f6-7890-abcd-ef1234567890" instancename</screen> > >- <para>Delete an existing API key with Client ID 'abc123def456':</para> >- <screen>$ koha-api-keys delete abc123def456 kohadev</screen> >+ <para>Display help information:</para> >+ <screen>$ sudo koha-shell -c "koha-api-keys --help" instancename</screen> > </refsect1> > </refentry> > </article> >diff --git a/debian/scripts/koha-api-keys b/debian/scripts/koha-api-keys >index 79878e84507..53d3234c4a0 100755 >--- a/debian/scripts/koha-api-keys >+++ b/debian/scripts/koha-api-keys >@@ -1,5 +1,5 @@ >-#!/bin/bash >-# >+#!/usr/bin/perl >+ > # koha-api-keys: generate or delete api keys for a given patron and > # koha instance. > # Copyright 2024 LMSCloud GmbH >@@ -17,81 +17,212 @@ > # You should have received a copy of the GNU General Public License > # along with this program. If not, see <http://www.gnu.org/licenses/>. > >-set -e >-umask 0077 >+use Modern::Perl; >+use Getopt::Long qw( GetOptions ); >+use Pod::Usage qw( pod2usage ); >+ >+use Koha::Script; >+use Koha::ApiKeys; >+use Koha::Patrons; >+use C4::Log qw( logaction ); >+ >+my $generate; >+my $delete; >+my $help; >+my $description; >+my $borrowernumber; >+my $client_id; >+ >+GetOptions( >+ 'generate' => \$generate, >+ 'delete' => \$delete, >+ 'help|h' => \$help, >+ 'description=s' => \$description, >+ 'borrowernumber=i' => \$borrowernumber, >+ 'client-id=s' => \$client_id, >+) or pod2usage(2); >+ >+if ($help) { >+ pod2usage(1); >+} > >-# include helper functions >-if [ -f "/usr/share/koha/bin/koha-functions.sh" ]; then >- . "/usr/share/koha/bin/koha-functions.sh" >-else >- echo "Error: /usr/share/koha/bin/koha-functions.sh not present." 1>&2 >- exit 1 >-fi >+if ( !$generate && !$delete ) { >+ pod2usage( >+ { >+ -message => "Error: No operation specified. Use --generate or --delete.", >+ -exitval => 1 >+ } >+ ); >+} > >-usage() { >- local scriptname=$0 >- cat <<EOF >-Generate, or delete api keys for specified patron. >+if ( $generate && $delete ) { >+ pod2usage( >+ { >+ -message => "Error: Cannot specify both --generate and --delete.", >+ -exitval => 1 >+ } >+ ); >+} >+ >+if ($generate) { >+ if ( !$description ) { >+ pod2usage( >+ { >+ -message => "Error: --generate requires --description.", >+ -exitval => 1 >+ } >+ ); >+ } >+ if ( !$borrowernumber ) { >+ pod2usage( >+ { >+ -message => "Error: --generate requires --borrowernumber.", >+ -exitval => 1 >+ } >+ ); >+ } >+ >+ my $patron = Koha::Patrons->find($borrowernumber); >+ if ( !$patron ) { >+ die "Error: Unknown borrowernumber: '$borrowernumber'\n"; >+ } >+ >+ my $api_key = Koha::ApiKey->new( >+ { >+ patron_id => $borrowernumber, >+ description => $description, >+ } >+ )->store; >+ >+ # Log the API key generation for audit purposes >+ logaction( >+ 'APIKEY', 'GENERATE', $borrowernumber, >+ "Generated API key for patron $borrowernumber with description '$description'" >+ ); >+ >+ printf "Client ID:\t%s\nClient Secret:\t%s\n", $api_key->client_id, $api_key->plain_text_secret; >+ exit 0; >+} > >-Usage: $scriptname generate|delete [ description ] [ borrowernumber ] [ instancename ] >+if ($delete) { >+ if ( !$client_id ) { >+ print "Client ID to delete: "; >+ $client_id = <STDIN>; >+ chomp $client_id; >+ } > >-EOF >+ if ( !$client_id ) { >+ die "Error: No client ID provided.\n"; >+ } >+ >+ my $api_key = Koha::ApiKeys->find($client_id); >+ if ( !$api_key ) { >+ die "Error: Unknown client ID: '$client_id'\n"; >+ } >+ >+ # Store patron_id for logging before deletion >+ my $patron_id = $api_key->patron_id; >+ >+ $api_key->delete; >+ >+ # Log the API key deletion for audit purposes >+ logaction( >+ 'APIKEY', 'DELETE', $patron_id, >+ "Deleted API key $client_id for patron $patron_id" >+ ); >+ >+ print "API key deleted successfully.\n"; >+ exit 0; > } > >-op="$1" >- >-[ "$#" -ge 2 ] || ( >- usage >- die 'Missing required arguments.' >-) >- >-if [ "$op" == 'generate' ]; then >- if [ "$#" -eq 3 ]; then >- description=$(openssl rand -hex 16) >- borrowernumber="$2" >- instance="$3" >- fi >- >- if [ "$#" -eq 4 ]; then >- description="$2" >- borrowernumber="$3" >- instance="$4" >- fi >- >- is_instance "$instance" || ( >- usage >- die "Unknown instance '$instance'" >- ) >- if ! koha-shell -c "perl -MKoha::Patrons -e \"Koha::Patrons->find($borrowernumber) or die;\"" "$instance" 2>/dev/null; then >- die "Unknown borrowernumber: '$borrowernumber'" >- fi >- >- { >- read -r client_id >- read -r secret >- } < <( >- koha-shell -c "perl -MKoha::ApiKeys -e \"my \\\$key = Koha::ApiKey->new( { patron_id => $borrowernumber, description => '$description' } )->store; printf \\\"%s\\n%s\\n\\\", \\\$key->client_id, \\\$key->plain_text_secret;\"" "$instance" >- ) >- >- printf "Client ID:\t%s\nClient Secret:\t%s\n" "$client_id" "$secret" >- >- exit 0 >-fi >- >-if [ "$op" == 'delete' ]; then >- instance="$2" >- is_instance "$instance" || ( >- usage >- die "Unknown instance '$instance'" >- ) >- >- read -rp "Client ID to delete: " client_id >- if ! koha-shell -c "perl -MKoha::ApiKeys -e \"Koha::ApiKeys->find(\\\"$client_id\\\")->delete or die;\"" "$instance" 2>/dev/null; then >- die "Unknown client id: '$client_id'" >- fi >- >- exit 0 >-fi >- >-usage >-die "Invalid operation: '$op'" >+__END__ >+ >+=head1 NAME >+ >+koha-api-keys - Generate or delete API keys for specified patrons >+ >+=head1 SYNOPSIS >+ >+sudo koha-shell -c "koha-api-keys --generate --description DESCRIPTION --borrowernumber BORROWERNUMBER" instancename >+ >+sudo koha-shell -c "koha-api-keys --delete [--client-id CLIENT_ID]" instancename >+ >+sudo koha-shell -c "koha-api-keys --help" instancename >+ >+=head1 OPTIONS >+ >+=over 8 >+ >+=item B<--generate> >+ >+Generate a new API key for the specified patron. >+ >+=item B<--delete> >+ >+Delete an API key (client ID will be prompted if not provided via --client-id). >+ >+=item B<--description DESCRIPTION> >+ >+Description for the API key (required for --generate). >+ >+=item B<--borrowernumber BORROWERNUMBER> >+ >+Patron's borrower number (required for --generate). >+ >+=item B<--client-id CLIENT_ID> >+ >+Client ID to delete (optional for --delete, will be prompted if not provided). >+ >+=item B<--help> >+ >+Display this help message. >+ >+=back >+ >+=head1 DESCRIPTION >+ >+This script lets you generate or delete API keys for specified patrons in Koha. >+ >+As this tool requires administrative privileges and access to the Koha environment, >+it must be run using sudo and koha-shell wrapper as shown in the synopsis. >+ >+For generating keys, you must provide both a description and a borrower number. >+For deleting keys, you can provide the client ID via --client-id or be prompted interactively. >+ >+=head1 EXAMPLES >+ >+Generate an API key: >+ sudo koha-shell -c "koha-api-keys --generate --description 'Test API access' --borrowernumber 123" instancename >+ >+Delete an API key (interactive): >+ echo "CLIENT_ID" | sudo koha-shell -c "koha-api-keys --delete" instancename >+ >+Delete an API key (scripted): >+ sudo koha-shell -c "koha-api-keys --delete --client-id a1b2c3d4-e5f6-7890-abcd-ef1234567890" instancename >+ >+=head1 AUTHOR >+ >+Koha Development Team >+ >+=head1 COPYRIGHT >+ >+Copyright LMSCloud GmbH >+ >+=head1 LICENSE >+ >+This file is part of Koha. >+ >+Koha is free software; you can redistribute it and/or modify it >+under the terms of the GNU General Public License as published by >+the Free Software Foundation; either version 3 of the License, or >+(at your option) any later version. >+ >+Koha 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 Koha; if not, see <http://www.gnu.org/licenses>. >+ >+=cut >-- >2.39.5
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 37025
:
167397
|
167524
|
171014
| 185537