From 28380cdf36b6d519eb7e9049f263470f1ed5d86f Mon Sep 17 00:00:00 2001 From: Armin Grodon Date: Wed, 8 Mar 2017 14:59:14 +0100 Subject: [PATCH] Change password input flow for external APIs Program flow is more straight forward and intuitive. Program flow is documented in separate chapter. --- doc/chapter-password.txt | 31 +++++++++++++++++++++++++++++++ doc/newsbeuter.txt | 15 +++++++++++++++ src/remote_api.cpp | 22 +++++++++++----------- 3 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 doc/chapter-password.txt diff --git a/doc/chapter-password.txt b/doc/chapter-password.txt new file mode 100644 index 00000000..e5faf353 --- /dev/null +++ b/doc/chapter-password.txt @@ -0,0 +1,31 @@ +When using external APIs for newsfeeds, the user has different options for how +to provide the password to authenticate against the API. +Instead of directly writing the password into the configuration file, +the user can choose to provide a file containing the password or an external +command that evaluates to the user's password. +This is useful if the user wants to share the configuration file online or +store the password in a password manager or the systems keyring. + +For example when using the API for "The Old Reader", +Newsbeuter will first check the `oldreader-password` configuration variable, +if this variable is set (meaning it's present and not empty), +then its value will be used for authentication. +If `oldreader-password` is not set (meaning it's not present or it's empty) +but the `oldreader-passwordfile` configuration variable is set, +then the first line of this file will be used as the password. +This is, unless the file doesn't exist, is unreadable or its first line is empty, +in those cases Newsbeuter will exit with an error. +If `oldreader-passwordfile` is not set but `oldreader-passwordeval` is set, +then the command will be evaluated and the first line of the result will be +used as the password. +This is, unless the first line of the result's string is empty, +in those cases Newsbeuter will exit with an error. +Newsbeuter will ignore the exit status of the command, +however it will wait for the command to exit. +The command's output to stderr will be ignored by Newsbeuter and forwarded to +the user, the output to stdout on the other hand will never be printed. +If neither `oldreader-password`, `oldreader-passwordfile` nor +`oldreader-passwordeval` are set, then Newsbeuter will ask for the user's +password with an interactive prompt. +The entered password will be used unless it is empty, +in which case Newsbeuter will exit with an error. diff --git a/doc/newsbeuter.txt b/doc/newsbeuter.txt index f5fea567..71ccefa7 100644 --- a/doc/newsbeuter.txt +++ b/doc/newsbeuter.txt @@ -528,6 +528,8 @@ so that it can authenticate with The Old Reader: (Note that double quotes should be escaped, i.e. you should write +{backslash}"+ instead of +"+.) +See also <<_passwords_for_external_apis,oldreader-passwordfile and oldreader-passwordeval>>. + After setting these configuration values, you can start newsbeuter, it will authenticate with The Old Reader and download your subscription list. If you use "folders" in The Old Reader to organize your feeds, newsbeuter will regard them @@ -584,6 +586,8 @@ Then, configure your NewsBlur credentials: (Note that double quotes should be escaped, i.e. you should write +{backslash}"+ instead of +"+.) +See also <<_passwords_for_external_apis,newsblur-passwordfile and newsblur-passwordeval>>. + When you start newsbeuter, it will download the feeds that you configured in NewsBlur. Please take a closer look at the configuration commands for what you can configure in newsbeuter regarding NewsBlur. @@ -609,6 +613,8 @@ Then, configure your FeedHQ credentials: (Note that double quotes should be escaped, i.e. you should write +{backslash}"+ instead of +"+.) +See also <<_passwords_for_external_apis,feedhq-passwordfile and feedhq-passwordeval>>. + When you start newsbeuter, it will download the feeds that you configured in FeedHQ. Please take a closer look at the configuration commands for what you can configure in newsbeuter regarding FeedHQ. @@ -650,6 +656,8 @@ In addition, it requires username and password for authentication: (Note that double quotes should be escaped, i.e. you should write +{backslash}"+ instead of +"+.) +See also <<_passwords_for_external_apis,ttrss-passwordfile and ttrss-passwordeval>>. + Tiny Tiny RSS provides two modes of usage, single-user mode and multi-user mode. newsbeuter needs to know about this, too: In single-user mode, authentication is done via Basic HTTP authentication, while in multi-user mode, @@ -693,6 +701,8 @@ Username and password are required: ocnews-login "user" ocnews-password "password" +See also <<_passwords_for_external_apis,ocnews-passwordfile and ocnews-passwordeval>>. + ownCloud News API uses HTTP basic auth, therefore running ownCloud with SSL is highly recommended. @@ -1165,6 +1175,11 @@ title changes. And nicely enough this works all inside newsbeuter, no need to restart it so that it rereads the cache, that magically modifies itself. It just works. +Passwords for external APIs +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +include::chapter-password.txt[] + Feedback -------- diff --git a/src/remote_api.cpp b/src/remote_api.cpp index 74a450c0..234e08c1 100644 --- a/src/remote_api.cpp +++ b/src/remote_api.cpp @@ -58,21 +58,21 @@ credentials remote_api::get_credentials(const std::string& scope, const std::str if (pass.empty()) { if (!pass_file.empty()) { pass = read_password(pass_file); - if (pass.empty()) return { "", "" }; } else if (!pass_eval.empty()) { pass = eval_password(pass_eval); - if (pass.empty()) return { "", "" }; + } else { + if (!flushed) { + std::cout << std::endl; + std::cout.flush(); + } + // Find a way to do this in C++ by removing cin echoing. + std::string pass_prompt = "Password for "+name+": "; + pass = std::string(getpass(pass_prompt.c_str())); } - } - if (pass.empty()) { - if (!flushed) { - std::cout << std::endl; - std::cout.flush(); - } - // Find a way to do this in C++ by removing cin echoing. - std::string pass_prompt = "Password for "+name+": "; - pass = std::string(getpass(pass_prompt.c_str())); + if (pass.empty()) { + return { "", "" }; + } } return { user, pass };