calibre-server --manage-users: Add a scriptable interface calibre-server --manage-users -- help. Fixes #1912337 [[Enhancement] Add parameters for executing actions programatically from calibre-server --manage-users](https://bugs.launchpad.net/calibre/+bug/1912337)

This commit is contained in:
Kovid Goyal 2021-01-19 20:39:53 +05:30
parent 991e61af32
commit 0727fb7793
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 88 additions and 7 deletions

View File

@ -7,14 +7,97 @@ from functools import partial
from calibre import prints
from calibre.constants import preferred_encoding, iswindows
from calibre.utils.config import OptionParser
from polyglot.builtins import iteritems, raw_input, filter, unicode_type
# Manage users CLI {{{
def create_subcommand_parser(name, usage):
usage = f'%prog --manage-users -- {name} ' + usage
parser = OptionParser(usage)
return parser
def manage_users_cli(path=None):
def add(user_manager, args):
p = create_subcommand_parser('add', _('username [password]') + '\n\n' + '''\
Create a new user account with the specified name and password. If the password
is not specified on the command line, it will be read from STDIN.
''')
p.add_option('--readonly', action='store_true', default=False, help=_('Give this user only read access'))
opts, args = p.parse_args(['calibre-server'] + list(args))
if len(args) < 2:
p.print_help()
raise SystemExit(_('username is required'))
username = args[1]
if len(args) > 2:
pw = args[2]
else:
pw = sys.stdin.read()
user_manager.add_user(username, pw, readonly=opts.readonly)
def remove(user_manager, args):
p = create_subcommand_parser('remove', _('username') + '\n\n' + '''\
Remove the user account with the specified username.
''')
opts, args = p.parse_args(['calibre-server'] + list(args))
if len(args) < 2:
p.print_help()
raise SystemExit(_('username is required'))
username = args[1]
user_manager.remove_user(username)
def list_users(user_manager, args):
p = create_subcommand_parser('list', '\n\n' + '''\
List all usernames.
''')
opts, args = p.parse_args(['calibre-server'] + list(args))
for name in user_manager.all_user_names:
print(name)
def chpass(user_manager, args):
p = create_subcommand_parser('chpass', _('username [password]') + '\n\n' + '''\
Change the password of the new user account with the specified username. If the password
is not specified on the command line, it will be read from STDIN.
''')
opts, args = p.parse_args(['calibre-server'] + list(args))
if len(args) < 2:
p.print_help()
raise SystemExit(_('username is required'))
username = args[1]
if len(args) > 2:
pw = args[2]
else:
pw = sys.stdin.read()
user_manager.change_password(username, pw)
def main(user_manager, args):
q, rest = args[0], args[1:]
if q == 'add':
return add(user_manager, rest)
if q == 'remove':
return remove(user_manager, rest)
if q == 'chpass':
return chpass(user_manager, rest)
if q == 'list':
return list_users(user_manager, rest)
if q != 'help':
print(_('Unknown command: {}').format(q), file=sys.stderr)
print()
print(_('Manage the user accounts for calibre-server. Available commands are:'))
print('add, remove, chpass, list')
print(_('Use {} for help on individual commands').format('calibre-server --manage-users -- command -h'))
raise SystemExit(1)
def manage_users_cli(path=None, args=()):
from calibre.srv.users import UserManager
m = UserManager(path)
if args:
main(m, args)
return
enc = getattr(sys.stdin, 'encoding', preferred_encoding) or preferred_encoding
def get_input(prompt):
@ -228,6 +311,3 @@ def manage_users_cli(path=None):
while actions:
actions[0]()
del actions[0]
# }}}

View File

@ -155,7 +155,8 @@ libraries that the main calibre program knows about will be used.
action='store_true',
help=_(
'Manage the database of users allowed to connect to this server.'
' See also the %s option.') % '--userdb')
' You can use it in automated mode by adding a --. See {0}'
' for details. See also the {1} option.').format('calibre-server --manage-users -- help', '--userdb'))
parser.get_option('--userdb').help = _(
'Path to the user database to use for authentication. The database'
' is a SQLite file. To create it use {0}. You can read more'
@ -202,7 +203,7 @@ def main(args=sys.argv):
connect(opts.userdb, exc_class=SystemExit).close()
if opts.manage_users:
try:
manage_users_cli(opts.userdb)
manage_users_cli(opts.userdb, args[1:])
except (KeyboardInterrupt, EOFError):
raise SystemExit(_('Interrupted by user'))
raise SystemExit(0)