From eddc49fa44d9be261113860db8c203b7da8362bb Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 27 Jun 2017 11:21:01 +0530 Subject: [PATCH] API to allow authenticated users to change their password --- src/calibre/srv/handler.py | 2 +- src/calibre/srv/users.py | 2 ++ src/calibre/srv/users_api.py | 30 ++++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/calibre/srv/users_api.py diff --git a/src/calibre/srv/handler.py b/src/calibre/srv/handler.py index e29a40d60d..60ffac352c 100644 --- a/src/calibre/srv/handler.py +++ b/src/calibre/srv/handler.py @@ -152,7 +152,7 @@ class Context(object): return old[1] -SRV_MODULES = ('ajax', 'books', 'cdb', 'code', 'content', 'legacy', 'opds') +SRV_MODULES = ('ajax', 'books', 'cdb', 'code', 'content', 'legacy', 'opds', 'users_api') class Handler(object): diff --git a/src/calibre/srv/users.py b/src/calibre/srv/users.py index ff80c6fff6..bca1f60dac 100644 --- a/src/calibre/srv/users.py +++ b/src/calibre/srv/users.py @@ -54,6 +54,8 @@ def validate_username(username): def validate_password(pw): + if not pw: + return _('Empty passwords are not allowed') try: pw = pw.encode('ascii', 'strict') except ValueError: diff --git a/src/calibre/srv/users_api.py b/src/calibre/srv/users_api.py new file mode 100644 index 0000000000..be02afefd6 --- /dev/null +++ b/src/calibre/srv/users_api.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python2 +# vim:fileencoding=utf-8 +# License: GPLv3 Copyright: 2017, Kovid Goyal + +from __future__ import absolute_import, division, print_function, unicode_literals + +from calibre import as_unicode +from calibre.srv.errors import HTTPBadRequest, HTTPForbidden +from calibre.srv.routes import endpoint +from calibre.srv.users import validate_password + + +@endpoint('/users/change-pw', methods={'POST'}) +def change_pw(ctx, rd): + user = rd.username or None + if user is None: + raise HTTPForbidden('Anonymous users are not allowed to change passwords') + try: + pw = rd.request_body_file.read().decode('utf-8') + except Exception: + raise HTTPBadRequest('No decodable password found') + err = validate_password(pw) + if err: + raise HTTPBadRequest(err) + try: + ctx.user_manager.change_password(user, pw) + except Exception as err: + raise HTTPBadRequest(as_unicode(err)) + ctx.log.warn('Changed password for user', user) + return 'password for {} changed'.format(user)