From 7e669bcf6b6336ec429da949bcb4aa456971dba2 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 30 Jul 2021 10:38:27 +0200 Subject: folding history in preparation of GNU Anastasis v0.0.0 release --- src/cli/.gitignore | 6 + src/cli/Makefile.am | 56 +++ src/cli/anastasis-cli-redux.c | 366 +++++++++++++++ src/cli/resources/00-backup.json | 8 + src/cli/resources/00-recovery.json | 8 + src/cli/resources/01-backup.json | 41 ++ src/cli/resources/01-recovery.json | 41 ++ src/cli/resources/02-backup.json | 83 ++++ src/cli/resources/02-recovery.json | 83 ++++ src/cli/resources/03-backup.json | 155 +++++++ src/cli/resources/04-backup.json | 172 +++++++ src/cli/resources/05-backup.json | 213 +++++++++ src/cli/resources/06-backup.json | 223 +++++++++ src/cli/test_anastasis_reducer_1.conf | 9 + src/cli/test_anastasis_reducer_2.conf | 9 + src/cli/test_anastasis_reducer_3.conf | 9 + src/cli/test_anastasis_reducer_4.conf | 9 + .../test_anastasis_reducer_add_authentication.sh | 134 ++++++ ...astasis_reducer_backup_enter_user_attributes.sh | 140 ++++++ .../test_anastasis_reducer_done_authentication.sh | 65 +++ .../test_anastasis_reducer_done_policy_review.sh | 105 +++++ src/cli/test_anastasis_reducer_enter_secret.sh | 417 +++++++++++++++++ src/cli/test_anastasis_reducer_initialize_state.sh | 64 +++ ...tasis_reducer_recovery_enter_user_attributes.sh | 516 +++++++++++++++++++++ src/cli/test_anastasis_reducer_select_continent.sh | 116 +++++ src/cli/test_anastasis_reducer_select_country.sh | 144 ++++++ src/cli/test_reducer.conf | 197 ++++++++ src/cli/user-details-example.json | 6 + 28 files changed, 3395 insertions(+) create mode 100644 src/cli/.gitignore create mode 100644 src/cli/Makefile.am create mode 100644 src/cli/anastasis-cli-redux.c create mode 100644 src/cli/resources/00-backup.json create mode 100644 src/cli/resources/00-recovery.json create mode 100644 src/cli/resources/01-backup.json create mode 100644 src/cli/resources/01-recovery.json create mode 100644 src/cli/resources/02-backup.json create mode 100644 src/cli/resources/02-recovery.json create mode 100644 src/cli/resources/03-backup.json create mode 100644 src/cli/resources/04-backup.json create mode 100644 src/cli/resources/05-backup.json create mode 100644 src/cli/resources/06-backup.json create mode 100644 src/cli/test_anastasis_reducer_1.conf create mode 100644 src/cli/test_anastasis_reducer_2.conf create mode 100644 src/cli/test_anastasis_reducer_3.conf create mode 100644 src/cli/test_anastasis_reducer_4.conf create mode 100755 src/cli/test_anastasis_reducer_add_authentication.sh create mode 100755 src/cli/test_anastasis_reducer_backup_enter_user_attributes.sh create mode 100755 src/cli/test_anastasis_reducer_done_authentication.sh create mode 100755 src/cli/test_anastasis_reducer_done_policy_review.sh create mode 100755 src/cli/test_anastasis_reducer_enter_secret.sh create mode 100755 src/cli/test_anastasis_reducer_initialize_state.sh create mode 100755 src/cli/test_anastasis_reducer_recovery_enter_user_attributes.sh create mode 100755 src/cli/test_anastasis_reducer_select_continent.sh create mode 100755 src/cli/test_anastasis_reducer_select_country.sh create mode 100644 src/cli/test_reducer.conf create mode 100644 src/cli/user-details-example.json (limited to 'src/cli') diff --git a/src/cli/.gitignore b/src/cli/.gitignore new file mode 100644 index 0000000..dbf01fa --- /dev/null +++ b/src/cli/.gitignore @@ -0,0 +1,6 @@ +*.log +anastasis-reducer +test_reducer_home +*.trs +taler-bank.err +wallet.err diff --git a/src/cli/Makefile.am b/src/cli/Makefile.am new file mode 100644 index 0000000..6b8bf23 --- /dev/null +++ b/src/cli/Makefile.am @@ -0,0 +1,56 @@ +# This Makefile.am is in the public domain +AM_CPPFLAGS = -I$(top_srcdir)/src/include + +bin_PROGRAMS = \ + anastasis-reducer + +if USE_COVERAGE + AM_CFLAGS = --coverage -O0 + XLIB = -lgcov +endif + +check_SCRIPTS = \ + test_anastasis_reducer_initialize_state.sh \ + test_anastasis_reducer_select_continent.sh \ + test_anastasis_reducer_select_country.sh \ + test_anastasis_reducer_backup_enter_user_attributes.sh \ + test_anastasis_reducer_add_authentication.sh \ + test_anastasis_reducer_done_authentication.sh \ + test_anastasis_reducer_done_policy_review.sh \ + test_anastasis_reducer_enter_secret.sh \ + test_anastasis_reducer_recovery_enter_user_attributes.sh + + +AM_TESTS_ENVIRONMENT=export ANASTASIS_PREFIX=$${ANASTASIS_PREFIX:-@libdir@};export PATH=$${ANASTASIS_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME; + +TESTS = \ + $(check_SCRIPTS) + +EXTRA_DIST = \ + $(check_SCRIPTS) \ + test_reducer.conf \ + test_anastasis_reducer_1.conf \ + test_anastasis_reducer_2.conf \ + test_anastasis_reducer_3.conf \ + test_anastasis_reducer_4.conf \ + resources/00-backup.json \ + resources/01-backup.json \ + resources/02-backup.json \ + resources/03-backup.json \ + resources/04-backup.json \ + resources/00-recovery.json \ + resources/01-recovery.json \ + resources/02-recovery.json + +anastasis_reducer_SOURCES = \ + anastasis-cli-redux.c +anastasis_reducer_LDADD = \ + $(top_builddir)/src/util/libanastasisutil.la \ + $(top_builddir)/src/reducer/libanastasisredux.la \ + -ltalerjson \ + -ltalerutil \ + -lgnunetjson \ + -lgnunetcurl \ + -lgnunetutil \ + -ljansson \ + $(XLIB) diff --git a/src/cli/anastasis-cli-redux.c b/src/cli/anastasis-cli-redux.c new file mode 100644 index 0000000..7b533c2 --- /dev/null +++ b/src/cli/anastasis-cli-redux.c @@ -0,0 +1,366 @@ +/* + This file is part of Anastasis + Copyright (C) 2020,2021 Taler Systems SA + + Anastasis is free software; you can redistribute it and/or modify it under the + terms of the GNU Lesser General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Anastasis 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 + Anastasis; see the file COPYING.GPL. If not, see +*/ +/** + * @file cli/anastasis-cli-redux.c + * @brief command line tool for our reducer + * @author Christian Grothoff + * @author Dennis Neufeld + * @author Dominik Meister + */ + +#include "platform.h" +#include +#include +#include "anastasis_redux.h" +#include +#include +#include +#include "anastasis_util_lib.h" + +/** + * Closure for #GNUNET_CURL_gnunet_scheduler_reschedule(). + */ +static struct GNUNET_CURL_RescheduleContext *rc; + +/** + * Curl context for communication with anastasis backend + */ +static struct GNUNET_CURL_Context *ctx; + +/** + * -b option given. + */ +static int b_flag; + +/** + * -r option given. + */ +static int r_flag; + +/** + * Input to -a option given. + */ +static char *input; + +/** + * Output filename, if given. + */ +static char *output_filename; + +/** + * JSON containing previous state + */ +static json_t *prev_state; + +/** + * JSON containing arguments for action + */ +static json_t *arguments; + +/** + * Handle to an ongoing action. + */ +static struct ANASTASIS_ReduxAction *ra; + +/** + * Return value from main. + */ +static int global_ret; + + +/** + * Persist a json state, report errors. + * + * @param state to persist + * @param filename where to write the state to, NULL for stdout + */ +static void +persist_new_state (json_t *state, + const char *filename) +{ + if (NULL != filename) + { + if (0 != + json_dump_file (state, + filename, + JSON_COMPACT)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Could not dump state to `%s'\n", + filename); + return; + } + return; + } + { + char *state_str = json_dumps (state, + JSON_COMPACT); + if (-1 >= + fprintf (stdout, + "%s", + state_str)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Could not dump state to stdout\n"); + GNUNET_free (state_str); + return; + } + GNUNET_free (state_str); + } +} + + +/** + * Function called with the results of #ANASTASIS_backup_action + * or #ANASTASIS_recovery_action. + * + * @param cls closure + * @param error_code Error code + * @param new_state new state as result + */ +static void +action_cb (void *cls, + enum TALER_ErrorCode error_code, + json_t *result_state) +{ + (void) cls; + ra = NULL; + if (NULL != result_state) + persist_new_state (result_state, + output_filename); + if (TALER_EC_NONE != error_code) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Redux failed with error %d: %s\n", + error_code, + TALER_ErrorCode_get_hint (error_code)); + } + GNUNET_SCHEDULER_shutdown (); + global_ret = (TALER_EC_NONE != error_code) ? 1 : 0; +} + + +/** + * @brief Shutdown the application. + * + * @param cls closure + */ +static void +shutdown_task (void *cls) +{ + (void) cls; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Shutdown initiated\n"); + if (NULL != ra) + { + ANASTASIS_redux_action_cancel (ra); + ra = NULL; + } + ANASTASIS_redux_done (); + if (NULL != ctx) + { + GNUNET_CURL_fini (ctx); + ctx = NULL; + } + if (NULL != rc) + { + GNUNET_CURL_gnunet_rc_destroy (rc); + rc = NULL; + } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Shutdown complete\n"); +} + + +/** + * @brief Start the application + * + * @param cls closure + * @param args arguments left + * @param cfgfile config file name + * @param cfg handle for the configuration file + */ +static void +run (void *cls, + char *const *args, + const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + (void) cls; + json_error_t error; + + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Starting anastasis-reducer\n"); + GNUNET_SCHEDULER_add_shutdown (&shutdown_task, + NULL); + if (b_flag && r_flag) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "We cannot start backup and recovery at the same time!\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + if (r_flag) + { + json_t *init_state; + + init_state = ANASTASIS_recovery_start (cfg); + if (NULL == init_state) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "Failed to create an initial recovery state!\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + persist_new_state (init_state, + args[0]); + json_decref (init_state); + GNUNET_SCHEDULER_shutdown (); + return; + } + if (b_flag) + { + json_t *init_state; + + init_state = ANASTASIS_backup_start (cfg); + if (NULL == init_state) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "Failed to create an initial backup state!\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + persist_new_state (init_state, + args[0]); + json_decref (init_state); + GNUNET_SCHEDULER_shutdown (); + return; + } + + /* action processing */ + { + const char *action = args[0]; + + if (NULL == action) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "You must specify an action as the first argument (or `-b' or `-r')\n"); + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "Example: anastasis-reducer back\n"); + GNUNET_SCHEDULER_shutdown (); + return; + } + args++; + if (NULL != input) + { + arguments = json_loads (input, + JSON_DECODE_ANY, + &error); + if (NULL == arguments) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "Failed to parse arguments on line %u:%u: %s!\n", + error.line, + error.column, + error.text); + GNUNET_SCHEDULER_shutdown (); + return; + } + } + if (NULL != args[0]) + { + prev_state = json_load_file (args[0], + JSON_DECODE_ANY, + &error); + args++; + } + else + { + prev_state = json_loadf (stdin, + JSON_DECODE_ANY, + &error); + } + if (NULL == prev_state) + { + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "Failed to parse initial state on line %u:%u: %s!\n", + error.line, + error.column, + error.text); + GNUNET_SCHEDULER_shutdown (); + return; + } + output_filename = args[0]; + /* initialize HTTP client event loop */ + ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule, + &rc); + rc = GNUNET_CURL_gnunet_rc_create (ctx); + ANASTASIS_redux_init (ctx); + ra = ANASTASIS_redux_action (prev_state, + action, + arguments, + &action_cb, + cls); + } +} + + +int +main (int argc, + char *const *argv) +{ + /* the available command line options */ + struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_option_flag ('b', + "backup", + "use reducer to handle states for backup process", + &b_flag), + GNUNET_GETOPT_option_flag ('r', + "restore", + "use reducer to handle states for restore process", + &r_flag), + GNUNET_GETOPT_option_string ('a', + "arguments", + "JSON", + "pass a JSON string containing arguments to reducer", + &input), + + GNUNET_GETOPT_OPTION_END + }; + enum GNUNET_GenericReturnValue ret; + + /* FIRST get the libtalerutil initialization out + of the way. Then throw that one away, and force + the SYNC defaults to be used! */ + (void) TALER_project_data_default (); + GNUNET_OS_init (ANASTASIS_project_data_default ()); + ret = GNUNET_PROGRAM_run (argc, + argv, + "anastasis-reducer", + "This is an application for using Anastasis to handle the states.\n", + options, + &run, + NULL); + if (GNUNET_SYSERR == ret) + return 3; + if (GNUNET_NO == ret) + return 0; + return global_ret; +} + + +/* end of anastasis-cli-redux.c */ diff --git a/src/cli/resources/00-backup.json b/src/cli/resources/00-backup.json new file mode 100644 index 0000000..6e6c320 --- /dev/null +++ b/src/cli/resources/00-backup.json @@ -0,0 +1,8 @@ +{ + "continents": [ + "Europe", + "North America", + "Testcontinent" + ], + "backup_state": "CONTINENT_SELECTING" +} \ No newline at end of file diff --git a/src/cli/resources/00-recovery.json b/src/cli/resources/00-recovery.json new file mode 100644 index 0000000..acff19a --- /dev/null +++ b/src/cli/resources/00-recovery.json @@ -0,0 +1,8 @@ +{ + "continents": [ + "Europe", + "North America", + "Testcontinent" + ], + "recovery_state": "CONTINENT_SELECTING" +} \ No newline at end of file diff --git a/src/cli/resources/01-backup.json b/src/cli/resources/01-backup.json new file mode 100644 index 0000000..842d3af --- /dev/null +++ b/src/cli/resources/01-backup.json @@ -0,0 +1,41 @@ +{ + "continents": [ + "Europe", + "North America", + "Testcontinent" + ], + "backup_state": "COUNTRY_SELECTING", + "selected_continent": "Testcontinent", + "countries": [ + { + "code": "xx", + "name": "Testland", + "continent": "Testcontinent", + "continent_i18n": { + "xx": "Testkontinent" + }, + "name_i18n": { + "de_DE": "Testlandt", + "de_CH": "Testlandi", + "fr": "Testpais", + "en": "Testland" + }, + "currency": "TESTKUDOS" + }, + { + "code": "xy", + "name": "Demoland", + "continent": "Testcontinent", + "continent_i18n": { + "xx": "Testkontinent" + }, + "name_i18n": { + "de_DE": "Demolandt", + "de_CH": "Demolandi", + "fr": "Demopais", + "en": "Demoland" + }, + "currency": "KUDOS" + } + ] +} \ No newline at end of file diff --git a/src/cli/resources/01-recovery.json b/src/cli/resources/01-recovery.json new file mode 100644 index 0000000..11aafd3 --- /dev/null +++ b/src/cli/resources/01-recovery.json @@ -0,0 +1,41 @@ +{ + "continents": [ + "Europe", + "North America", + "Testcontinent" + ], + "recovery_state": "COUNTRY_SELECTING", + "selected_continent": "Testcontinent", + "countries": [ + { + "code": "xx", + "name": "Testland", + "continent": "Testcontinent", + "continent_i18n": { + "xx": "Testkontinent" + }, + "name_i18n": { + "de_DE": "Testlandt", + "de_CH": "Testlandi", + "fr": "Testpais", + "en": "Testland" + }, + "currency": "TESTKUDOS" + }, + { + "code": "xy", + "name": "Demoland", + "continent": "Testcontinent", + "continent_i18n": { + "xx": "Testkontinent" + }, + "name_i18n": { + "de_DE": "Demolandt", + "de_CH": "Demolandi", + "fr": "Demopais", + "en": "Demoland" + }, + "currency": "KUDOS" + } + ] +} \ No newline at end of file diff --git a/src/cli/resources/02-backup.json b/src/cli/resources/02-backup.json new file mode 100644 index 0000000..c9bba16 --- /dev/null +++ b/src/cli/resources/02-backup.json @@ -0,0 +1,83 @@ +{ + "continents": [ + "Europe", + "North America", + "Testcontinent" + ], + "backup_state": "USER_ATTRIBUTES_COLLECTING", + "selected_continent": "Testcontinent", + "countries": [ + { + "code": "xx", + "name": "Testland", + "continent": "Testcontinent", + "continent_i18n": { + "xx": "Testkontinent" + }, + "name_i18n": { + "de_DE": "Testlandt", + "de_CH": "Testlandi", + "fr": "Testpais", + "en": "Testland" + }, + "currency": "TESTKUDOS" + }, + { + "code": "xy", + "name": "Demoland", + "continent": "Testcontinent", + "continent_i18n": { + "xx": "Testkontinent" + }, + "name_i18n": { + "de_DE": "Demolandt", + "de_CH": "Demolandi", + "fr": "Demopais", + "en": "Demoland" + }, + "currency": "KUDOS" + } + ], + "authentication_providers": { + "http://localhost:8086/": {}, + "http://localhost:8087/": {}, + "http://localhost:8088/": {}, + "http://localhost:8089/": {} + }, + "selected_country": "xx", + "currencies": [ "TESTKUDOS" ], + "required_attributes": [ + { + "type": "string", + "name": "full_name", + "label": "Full name", + "label_i18n": { + "de_DE": "Vollstaendiger Name", + "de_CH": "Vollstaendiger Name" + }, + "widget": "anastasis_gtk_ia_full_name" + }, + { + "type": "date", + "name": "birthdate", + "label": "Birthdate", + "label_i18n": { + "de_CH": "Geburtsdatum" + }, + "widget": "anastasis_gtk_ia_birthdate" + }, + { + "type": "string", + "name": "sq_number", + "label": "Square number", + "label_i18n":{ + "de_DE":"Quadratzahl", + "de_CH":"Quadratzahl" + }, + "widget": "anastasis_gtk_xx_square", + "uuid" : "ed790bca-89bf-11eb-96f2-233996cf644e", + "validation-regex": "^[0-9]+$", + "validation-logic": "XX_SQUARE_check" + } + ] +} diff --git a/src/cli/resources/02-recovery.json b/src/cli/resources/02-recovery.json new file mode 100644 index 0000000..79cfd6d --- /dev/null +++ b/src/cli/resources/02-recovery.json @@ -0,0 +1,83 @@ +{ + "continents": [ + "Europe", + "North America", + "Testcontinent" + ], + "recovery_state": "USER_ATTRIBUTES_COLLECTING", + "selected_continent": "Testcontinent", + "countries": [ + { + "code": "xx", + "name": "Testland", + "continent": "Testcontinent", + "continent_i18n": { + "xx": "Testkontinent" + }, + "name_i18n": { + "de_DE": "Testlandt", + "de_CH": "Testlandi", + "fr": "Testpais", + "en": "Testland" + }, + "currency": "TESTKUDOS" + }, + { + "code": "xy", + "name": "Demoland", + "continent": "Testcontinent", + "continent_i18n": { + "xx": "Testkontinent" + }, + "name_i18n": { + "de_DE": "Demolandt", + "de_CH": "Demolandi", + "fr": "Demopais", + "en": "Demoland" + }, + "currency": "KUDOS" + } + ], + "authentication_providers": { + "http://localhost:8086/": {}, + "http://localhost:8087/": {}, + "http://localhost:8088/": {}, + "http://localhost:8089/": {} + }, + "selected_country": "xx", + "currencies": [ "TESTKUDOS" ], + "required_attributes": [ + { + "type": "string", + "name": "full_name", + "label": "Full name", + "label_i18n": { + "de_DE": "Vollstaendiger Name", + "de_CH": "Vollstaendiger Name" + }, + "widget": "anastasis_gtk_ia_full_name" + }, + { + "type": "date", + "name": "birthdate", + "label": "Birthdate", + "label_i18n": { + "de_CH": "Geburtsdatum" + }, + "widget": "anastasis_gtk_ia_birthdate" + }, + { + "type": "string", + "name": "sq_number", + "label": "Square number", + "label_i18n":{ + "de_DE":"Quadratzahl", + "de_CH":"Quadratzahl" + }, + "widget": "anastasis_gtk_xx_square", + "uuid" : "ed790bca-89bf-11eb-96f2-233996cf644e", + "validation-regex": "^[0-9]+$", + "validation-logic": "XX_SQUARE_check" + } + ] +} diff --git a/src/cli/resources/03-backup.json b/src/cli/resources/03-backup.json new file mode 100644 index 0000000..9d599d7 --- /dev/null +++ b/src/cli/resources/03-backup.json @@ -0,0 +1,155 @@ +{ + "continents": [ + "Europe", + "North America", + "Testcontinent" + ], + "backup_state": "AUTHENTICATIONS_EDITING", + "selected_continent": "Testcontinent", + "countries": [ + { + "code": "xx", + "name": "Testland", + "continent": "Testcontinent", + "continent_i18n": { + "xx": "Testkontinent" + }, + "name_i18n": { + "de_DE": "Testlandt", + "de_CH": "Testlandi", + "fr": "Testpais", + "en": "Testland" + }, + "currency": "TESTKUDOS" + }, + { + "code": "xy", + "name": "Demoland", + "continent": "Testcontinent", + "continent_i18n": { + "xx": "Testkontinent" + }, + "name_i18n": { + "de_DE": "Demolandt", + "de_CH": "Demolandi", + "fr": "Demopais", + "en": "Demoland" + }, + "currency": "KUDOS" + } + ], + "authentication_providers": { + "http://localhost:8086/": { + "methods": [ + { + "type": "question", + "usage_fee": "TESTKUDOS:0" + } + ], + "annual_fee": "TESTKUDOS:4.99", + "truth_upload_fee": "TESTKUDOS:0.01", + "liability_limit": "TESTKUDOS:1", + "truth_lifetime": { + "d_ms": 63115200000 + }, + "currency": "TESTKUDOS", + "business_name": "Data loss #1 Inc.", + "storage_limit_in_megabytes": 1, + "salt": "F0HEYJQW81ZAZ3VYMZHFG8T1Z0" + }, + "http://localhost:8087/": { + "methods": [ + { + "type": "question", + "usage_fee": "TESTKUDOS:0" + } + ], + "annual_fee": "TESTKUDOS:4.99", + "truth_upload_fee": "TESTKUDOS:0.01", + "liability_limit": "TESTKUDOS:1", + "truth_lifetime": { + "d_ms": 63115200000 + }, + "currency": "TESTKUDOS", + "business_name": "Data loss #2 Inc.", + "storage_limit_in_megabytes": 1, + "salt": "D378FWXHJB8JHPQFQRZGGV9PWG" + }, + "http://localhost:8088/": { + "methods": [ + { + "type": "question", + "usage_fee": "TESTKUDOS:0" + } + ], + "annual_fee": "TESTKUDOS:4.99", + "truth_upload_fee": "TESTKUDOS:0.01", + "liability_limit": "TESTKUDOS:1", + "truth_lifetime": { + "d_ms": 63115200000 + }, + "currency": "TESTKUDOS", + "business_name": "Data loss #3 Inc.", + "storage_limit_in_megabytes": 1, + "salt": "7W9W4A4TTWSWRPJ76RNDPJHSPR" + }, + "http://localhost:8089/": { + "methods": [ + { + "type": "question", + "usage_fee": "TESTKUDOS:0" + } + ], + "annual_fee": "TESTKUDOS:4.99", + "truth_upload_fee": "TESTKUDOS:0.01", + "liability_limit": "TESTKUDOS:1", + "truth_lifetime": { + "d_ms": 63115200000 + }, + "currency": "TESTKUDOS", + "business_name": "Data loss #4 Inc.", + "storage_limit_in_megabytes": 1, + "salt": "PN0VJF6KDSBYN40SGRCEXPB07M" + } + }, + "selected_country": "xx", + "currencies": ["TESTKUDOS"], + "required_attributes": [ + { + "type": "string", + "name": "full_name", + "label": "Full name", + "label_i18n": { + "de_DE": "Vollstaendiger Name", + "de_CH": "Vollstaendiger Name" + }, + "widget": "anastasis_gtk_ia_full_name" + }, + { + "type": "date", + "name": "birthdate", + "label": "Birthdate", + "label_i18n": { + "de_CH": "Geburtsdatum" + }, + "widget": "anastasis_gtk_ia_birthdate" + }, + { + "type": "string", + "name": "ahv_number", + "label": "AHV number", + "label_i18n": { + "de_DE": "AHV-Nummer", + "de_CH": "AHV-Nummer" + }, + "widget": "anastasis_gtk_ia_ahv", + "validation-regex": "^(756).[0-9]{4}.[0-9]{4}.[0-9]{2}|(756)[0-9]{10}$", + "validation-logic": "CH_AVH_check" + } + ], + "identity_attributes": { + "full_name": "Max Musterman", + "sq_number": 4, + "birthdate": "2000-01-01" + } +} diff --git a/src/cli/resources/04-backup.json b/src/cli/resources/04-backup.json new file mode 100644 index 0000000..15c329a --- /dev/null +++ b/src/cli/resources/04-backup.json @@ -0,0 +1,172 @@ +{ + "continents": [ + "Europe", + "North America", + "Testcontinent" + ], + "backup_state": "AUTHENTICATIONS_EDITING", + "selected_continent": "Testcontinent", + "countries": [ + { + "code": "xx", + "name": "Testland", + "continent": "Testcontinent", + "continent_i18n": { + "xx": "Testkontinent" + }, + "name_i18n": { + "de_DE": "Testlandt", + "de_CH": "Testlandi", + "fr": "Testpais", + "en": "Testland" + }, + "currency": "TESTKUDOS" + }, + { + "code": "xy", + "name": "Demoland", + "continent": "Testcontinent", + "continent_i18n": { + "xx": "Testkontinent" + }, + "name_i18n": { + "de_DE": "Demolandt", + "de_CH": "Demolandi", + "fr": "Demopais", + "en": "Demoland" + }, + "currency": "KUDOS" + } + ], + "authentication_providers": { + "http://localhost:8086/": { + "methods": [ + { + "type": "question", + "usage_fee": "TESTKUDOS:0" + } + ], + "annual_fee": "TESTKUDOS:4.99", + "truth_upload_fee": "TESTKUDOS:0.01", + "liability_limit": "TESTKUDOS:1", + "truth_lifetime": { + "d_ms": 63115200000 + }, + "currency": "TESTKUDOS", + "business_name": "Data loss #1 Inc.", + "storage_limit_in_megabytes": 1, + "salt": "F0HEYJQW81ZAZ3VYMZHFG8T1Z0" + }, + "http://localhost:8087/": { + "methods": [ + { + "type": "question", + "usage_fee": "TESTKUDOS:0" + } + ], + "annual_fee": "TESTKUDOS:4.99", + "truth_upload_fee": "TESTKUDOS:0.01", + "liability_limit": "TESTKUDOS:1", + "truth_lifetime": { + "d_ms": 63115200000 + }, + "currency": "TESTKUDOS", + "business_name": "Data loss #2 Inc.", + "storage_limit_in_megabytes": 1, + "salt": "D378FWXHJB8JHPQFQRZGGV9PWG" + }, + "http://localhost:8088/": { + "methods": [ + { + "type": "question", + "usage_fee": "TESTKUDOS:0" + } + ], + "annual_fee": "TESTKUDOS:4.99", + "truth_upload_fee": "TESTKUDOS:0.01", + "liability_limit": "TESTKUDOS:1", + "truth_lifetime": { + "d_ms": 63115200000 + }, + "currency": "TESTKUDOS", + "business_name": "Data loss #3 Inc.", + "storage_limit_in_megabytes": 1, + "salt": "7W9W4A4TTWSWRPJ76RNDPJHSPR" + }, + "http://localhost:8089/": { + "methods": [ + { + "type": "question", + "usage_fee": "TESTKUDOS:0" + } + ], + "annual_fee": "TESTKUDOS:4.99", + "truth_upload_fee": "TESTKUDOS:0.01", + "liability_limit": "TESTKUDOS:1", + "truth_lifetime": { + "d_ms": 63115200000 + }, + "currency": "TESTKUDOS", + "business_name": "Data loss #4 Inc.", + "storage_limit_in_megabytes": 1, + "salt": "PN0VJF6KDSBYN40SGRCEXPB07M" + } + }, + "selected_country": "xx", + "currencies": [ "TESTKUDOS" ], + "required_attributes": [ + { + "type": "string", + "name": "full_name", + "label": "Full name", + "label_i18n": { + "de_DE": "Vollstaendiger Name", + "de_CH": "Vollstaendiger Name" + }, + "widget": "anastasis_gtk_ia_full_name" + }, + { + "type": "date", + "name": "birthdate", + "label": "Birthdate", + "label_i18n": { + "de_CH": "Geburtsdatum" + }, + "widget": "anastasis_gtk_ia_birthdate" + }, + { + "type": "string", + "name": "ahv_number", + "label": "AHV number", + "label_i18n": { + "de_DE": "AHV-Nummer", + "de_CH": "AHV-Nummer" + }, + "widget": "anastasis_gtk_ia_ahv", + "validation-regex": "^(756).[0-9]{4}.[0-9]{4}.[0-9]{2}|(756)[0-9]{10}$", + "validation-logic": "CH_AVH_check" + } + ], + "identity_attributes": { + "full_name": "Max Musterman", + "sq_number": 4, + "birthdate": "2000-01-01" + }, + "authentication_methods": [ + { + "type": "question", + "instructions": "What's your name?", + "challenge": "Hans" + }, + { + "type": "question", + "instructions": "What's your X name?", + "challenge": "Hansx" + }, + { + "type": "question", + "instructions": "Where do you live?", + "challenge": "Mars" + } + ] +} diff --git a/src/cli/resources/05-backup.json b/src/cli/resources/05-backup.json new file mode 100644 index 0000000..c0ce8ae --- /dev/null +++ b/src/cli/resources/05-backup.json @@ -0,0 +1,213 @@ +{ + "continents": [ + "Europe", + "North America", + "Testcontinent" + ], + "backup_state": "POLICIES_REVIEWING", + "selected_continent": "Testcontinent", + "countries": [ + { + "code": "xx", + "name": "Testland", + "continent": "Testcontinent", + "continent_i18n": { + "xx": "Testkontinent" + }, + "name_i18n": { + "de_DE": "Testlandt", + "de_CH": "Testlandi", + "fr": "Testpais", + "en": "Testland" + }, + "currency": "TESTKUDOS" + }, + { + "code": "xy", + "name": "Demoland", + "continent": "Testcontinent", + "continent_i18n": { + "xx": "Testkontinent" + }, + "name_i18n": { + "de_DE": "Demolandt", + "de_CH": "Demolandi", + "fr": "Demopais", + "en": "Demoland" + }, + "currency": "KUDOS" + } + ], + "authentication_providers": { + "http://localhost:8086/": { + "methods": [ + { + "type": "question", + "usage_fee": "TESTKUDOS:0" + } + ], + "annual_fee": "TESTKUDOS:4.99", + "truth_upload_fee": "TESTKUDOS:0.01", + "liability_limit": "TESTKUDOS:1", + "truth_lifetime": { + "d_ms": 63115200000 + }, + "currency": "TESTKUDOS", + "business_name": "Data loss #1 Inc.", + "storage_limit_in_megabytes": 1, + "salt": "F0HEYJQW81ZAZ3VYMZHFG8T1Z0" + }, + "http://localhost:8087/": { + "methods": [ + { + "type": "question", + "usage_fee": "TESTKUDOS:0" + } + ], + "annual_fee": "TESTKUDOS:4.99", + "truth_upload_fee": "TESTKUDOS:0.01", + "liability_limit": "TESTKUDOS:1", + "truth_lifetime": { + "d_ms": 63115200000 + }, + "currency": "TESTKUDOS", + "business_name": "Data loss #2 Inc.", + "storage_limit_in_megabytes": 1, + "salt": "D378FWXHJB8JHPQFQRZGGV9PWG" + }, + "http://localhost:8088/": { + "methods": [ + { + "type": "question", + "usage_fee": "TESTKUDOS:0" + } + ], + "annual_fee": "TESTKUDOS:4.99", + "truth_upload_fee": "TESTKUDOS:0.01", + "liability_limit": "TESTKUDOS:1", + "truth_lifetime": { + "d_ms": 63115200000 + }, + "currency": "TESTKUDOS", + "business_name": "Data loss #3 Inc.", + "storage_limit_in_megabytes": 1, + "salt": "7W9W4A4TTWSWRPJ76RNDPJHSPR" + }, + "http://localhost:8089/": { + "methods": [ + { + "type": "question", + "usage_fee": "TESTKUDOS:0" + } + ], + "annual_fee": "TESTKUDOS:4.99", + "truth_upload_fee": "TESTKUDOS:0.01", + "liability_limit": "TESTKUDOS:1", + "truth_lifetime": { + "d_ms": 63115200000 + }, + "currency": "TESTKUDOS", + "business_name": "Data loss #4 Inc.", + "storage_limit_in_megabytes": 1, + "salt": "PN0VJF6KDSBYN40SGRCEXPB07M" + } + }, + "selected_country": "xx", + "currencies": [ "TESTKUDOS" ], + "required_attributes": [ + { + "type": "string", + "name": "full_name", + "label": "Full name", + "label_i18n": { + "de_DE": "Vollstaendiger Name", + "de_CH": "Vollstaendiger Name" + }, + "widget": "anastasis_gtk_ia_full_name" + }, + { + "type": "date", + "name": "birthdate", + "label": "Birthdate", + "label_i18n": { + "de_CH": "Geburtsdatum" + }, + "widget": "anastasis_gtk_ia_birthdate" + }, + { + "type": "string", + "name": "ahv_number", + "label": "AHV number", + "label_i18n": { + "de_DE": "AHV-Nummer", + "de_CH": "AHV-Nummer" + }, + "widget": "anastasis_gtk_ia_ahv", + "validation-regex": "^(756).[0-9]{4}.[0-9]{4}.[0-9]{2}|(756)[0-9]{10}$", + "validation-logic": "CH_AVH_check" + } + ], + "identity_attributes": { + "full_name": "Max Musterman", + "sq_number": 4, + "birthdate": "2000-01-01" + }, + "authentication_methods": [ + { + "type": "question", + "instructions": "What's your name?", + "challenge": "Hans" + }, + { + "type": "question", + "instructions": "What's your X name?", + "challenge": "Hansx" + }, + { + "type": "question", + "instructions": "Where do you live?", + "challenge": "Mars" + } + ], + "policies": [ + { + "recovery_cost": "TESTKUDOS:0", + "methods": [ + { + "authentication_method": 0, + "provider": "http://localhost:8089/" + }, + { + "authentication_method": 1, + "provider": "http://localhost:8088/" + } + ] + }, + { + "recovery_cost": "TESTKUDOS:0", + "methods": [ + { + "authentication_method": 0, + "provider": "http://localhost:8089/" + }, + { + "authentication_method": 2, + "provider": "http://localhost:8088/" + } + ] + }, + { + "recovery_cost": "TESTKUDOS:0", + "methods": [ + { + "authentication_method": 1, + "provider": "http://localhost:8089/" + }, + { + "authentication_method": 2, + "provider": "http://localhost:8088/" + } + ] + } + ] +} diff --git a/src/cli/resources/06-backup.json b/src/cli/resources/06-backup.json new file mode 100644 index 0000000..d1f0b9e --- /dev/null +++ b/src/cli/resources/06-backup.json @@ -0,0 +1,223 @@ +{ + "continents": [ + "Europe", + "North America", + "Testcontinent" + ], + "backup_state": "SECRET_EDITING", + "selected_continent": "Testcontinent", + "countries": [ + { + "code": "xx", + "name": "Testland", + "continent": "Testcontinent", + "continent_i18n": { + "xx": "Testkontinent" + }, + "name_i18n": { + "de_DE": "Testlandt", + "de_CH": "Testlandi", + "fr": "Testpais", + "en": "Testland" + }, + "currency": "TESTKUDOS" + }, + { + "code": "xy", + "name": "Demoland", + "continent": "Testcontinent", + "continent_i18n": { + "xx": "Testkontinent" + }, + "name_i18n": { + "de_DE": "Demolandt", + "de_CH": "Demolandi", + "fr": "Demopais", + "en": "Demoland" + }, + "currency": "KUDOS" + } + ], + "authentication_providers": { + "http://localhost:8086/": { + "methods": [ + { + "type": "question", + "usage_fee": "TESTKUDOS:0" + } + ], + "annual_fee": "TESTKUDOS:4.99", + "truth_upload_fee": "TESTKUDOS:0.01", + "liability_limit": "TESTKUDOS:1", + "truth_lifetime": { + "d_ms": 63115200000 + }, + "currency": "TESTKUDOS", + "business_name": "Data loss #1 Inc.", + "storage_limit_in_megabytes": 1, + "salt": "F0HEYJQW81ZAZ3VYMZHFG8T1Z0" + }, + "http://localhost:8087/": { + "methods": [ + { + "type": "question", + "usage_fee": "TESTKUDOS:0" + } + ], + "annual_fee": "TESTKUDOS:4.99", + "truth_upload_fee": "TESTKUDOS:0.01", + "liability_limit": "TESTKUDOS:1", + "truth_lifetime": { + "d_ms": 63115200000 + }, + "currency": "TESTKUDOS", + "business_name": "Data loss #2 Inc.", + "storage_limit_in_megabytes": 1, + "salt": "D378FWXHJB8JHPQFQRZGGV9PWG" + }, + "http://localhost:8088/": { + "methods": [ + { + "type": "question", + "usage_fee": "TESTKUDOS:0" + } + ], + "annual_fee": "TESTKUDOS:4.99", + "truth_upload_fee": "TESTKUDOS:0.01", + "liability_limit": "TESTKUDOS:1", + "truth_lifetime": { + "d_ms": 63115200000 + }, + "currency": "TESTKUDOS", + "business_name": "Data loss #3 Inc.", + "storage_limit_in_megabytes": 1, + "salt": "7W9W4A4TTWSWRPJ76RNDPJHSPR" + }, + "http://localhost:8089/": { + "methods": [ + { + "type": "question", + "usage_fee": "TESTKUDOS:0" + } + ], + "annual_fee": "TESTKUDOS:4.99", + "truth_upload_fee": "TESTKUDOS:0.01", + "liability_limit": "TESTKUDOS:1", + "truth_lifetime": { + "d_ms": 63115200000 + }, + "currency": "TESTKUDOS", + "business_name": "Data loss #4 Inc.", + "storage_limit_in_megabytes": 1, + "salt": "PN0VJF6KDSBYN40SGRCEXPB07M" + } + }, + "selected_country": "xx", + "currencies": ["TESTKUDOS"], + "required_attributes": [ + { + "type": "string", + "name": "full_name", + "label": "Full name", + "label_i18n": { + "de_DE": "Vollstaendiger Name", + "de_CH": "Vollstaendiger Name" + }, + "widget": "anastasis_gtk_ia_full_name" + }, + { + "type": "date", + "name": "birthdate", + "label": "Birthdate", + "label_i18n": { + "de_CH": "Geburtsdatum" + }, + "widget": "anastasis_gtk_ia_birthdate" + }, + { + "type": "string", + "name": "ahv_number", + "label": "AHV number", + "label_i18n": { + "de_DE": "AHV-Nummer", + "de_CH": "AHV-Nummer" + }, + "widget": "anastasis_gtk_ia_ahv", + "validation-regex": "^(756).[0-9]{4}.[0-9]{4}.[0-9]{2}|(756)[0-9]{10}$", + "validation-logic": "CH_AVH_check" + } + ], + "identity_attributes": { + "full_name": "Max Musterman", + "ahv_number": "756.9217.0769.85", + "birth_year": 2000, + "birth_month": 1, + "birth_day": 1 + }, + "authentication_methods": [ + { + "type": "question", + "instructions": "What's your name?", + "challenge": "Hans" + }, + { + "type": "question", + "instructions": "What's your X name?", + "challenge": "Hansx" + }, + { + "type": "question", + "instructions": "Where do you live?", + "challenge": "Mars" + } + ], + "policy_providers" : [ + { + "provider_url": "http://localhost:8089/" + }, + { + "provider_url": "http://localhost:8089/" + } + ], + "policies": [ + { + "recovery_cost": "TESTKUDOS:0", + "methods": [ + { + "authentication_method": 0, + "provider": "http://localhost:8089/" + }, + { + "authentication_method": 1, + "provider": "http://localhost:8088/" + } + ] + }, + { + "recovery_cost": "TESTKUDOS:0", + "methods": [ + { + "authentication_method": 0, + "provider": "http://localhost:8089/" + }, + { + "authentication_method": 2, + "provider": "http://localhost:8088/" + } + ] + }, + { + "recovery_cost": "TESTKUDOS:0", + "methods": [ + { + "authentication_method": 1, + "provider": "http://localhost:8089/" + }, + { + "authentication_method": 2, + "provider": "http://localhost:8088/" + } + ] + } + ] +} diff --git a/src/cli/test_anastasis_reducer_1.conf b/src/cli/test_anastasis_reducer_1.conf new file mode 100644 index 0000000..6a9704d --- /dev/null +++ b/src/cli/test_anastasis_reducer_1.conf @@ -0,0 +1,9 @@ +@INLINE@ test_reducer.conf + +[anastasis] +PORT = 8086 +SERVER_SALT = AUfO1KGOKYIFlFQg +BUSINESS_NAME = "Data loss #1 Inc." + +[stasis-postgres] +CONFIG = postgres:///anastasischeck1 diff --git a/src/cli/test_anastasis_reducer_2.conf b/src/cli/test_anastasis_reducer_2.conf new file mode 100644 index 0000000..f909ade --- /dev/null +++ b/src/cli/test_anastasis_reducer_2.conf @@ -0,0 +1,9 @@ +@INLINE@ test_reducer.conf + +[anastasis] +PORT = 8087 +SERVER_SALT = BUfO1KGOKYIFlFQg +BUSINESS_NAME = "Data loss #2 Inc." + +[stasis-postgres] +CONFIG = postgres:///anastasischeck2 diff --git a/src/cli/test_anastasis_reducer_3.conf b/src/cli/test_anastasis_reducer_3.conf new file mode 100644 index 0000000..63c38ff --- /dev/null +++ b/src/cli/test_anastasis_reducer_3.conf @@ -0,0 +1,9 @@ +@INLINE@ test_reducer.conf + +[anastasis] +PORT = 8088 +SERVER_SALT = CUfO1KGOKYIFlFQg +BUSINESS_NAME = "Data loss #3 Inc." + +[stasis-postgres] +CONFIG = postgres:///anastasischeck3 diff --git a/src/cli/test_anastasis_reducer_4.conf b/src/cli/test_anastasis_reducer_4.conf new file mode 100644 index 0000000..a6d590e --- /dev/null +++ b/src/cli/test_anastasis_reducer_4.conf @@ -0,0 +1,9 @@ +@INLINE@ test_reducer.conf + +[anastasis] +PORT = 8089 +SERVER_SALT = DUfO1KGOKYIFlFQg +BUSINESS_NAME = "Data loss #4 Inc." + +[stasis-postgres] +CONFIG = postgres:///anastasischeck4 diff --git a/src/cli/test_anastasis_reducer_add_authentication.sh b/src/cli/test_anastasis_reducer_add_authentication.sh new file mode 100755 index 0000000..7d69076 --- /dev/null +++ b/src/cli/test_anastasis_reducer_add_authentication.sh @@ -0,0 +1,134 @@ +#!/bin/bash + +set -eu + +# Exit, with status code "skip" (no 'real' failure) +function exit_skip() { + echo " SKIP: $1" + exit 77 +} + +# Exit, with error message (hard failure) +function exit_fail() { + echo " ERROR: $1" + exit 1 +} + +# Cleanup to run whenever we exit +function cleanup() +{ + for n in `jobs -p` + do + kill $n 2> /dev/null || true + done + rm -f $TFILE $SFILE + wait +} + +SFILE=`mktemp test_reducer_stateXXXXXX` +TFILE=`mktemp test_reducer_stateXXXXXX` + +# Install cleanup handler (except for kill -9) +trap cleanup EXIT + +# Check we can actually run +echo -n "Testing for jq" +jq -h > /dev/null || exit_skip "jq required" +echo " FOUND" + +echo -n "Testing for anastasis-reducer ..." +anastasis-reducer -h > /dev/null || exit_skip "anastasis-reducer required" +echo " FOUND" + +echo -n "Test add authentication ..." + +# First method +anastasis-reducer -a \ + '{"authentication_method": { + "type": "question", + "instructions": "What is your name?", + "challenge": "91GPWWR" + } }' \ + add_authentication resources/03-backup.json $TFILE + +STATE=`jq -r -e .backup_state < $TFILE` +if test "$STATE" != "AUTHENTICATIONS_EDITING" +then + exit_fail "Expected new state to be 'AUTHENTICATIONS_EDITING', got '$STATE'" +fi + +ARRAY_LENGTH=`jq -r -e '.authentication_methods | length' < $TFILE` +if test $ARRAY_LENGTH != 1 +then + exit_fail "Expected array length to be 1, got '$ARRAY_LENGTH'" +fi + +echo -n "." +# Second method +anastasis-reducer -a \ + '{"authentication_method": { + "type": "question", + "instructions": "How old are you?", + "challenge": "64S36" + }}' \ + add_authentication $TFILE $SFILE + +STATE=`jq -r -e .backup_state < $SFILE` +if test "$STATE" != "AUTHENTICATIONS_EDITING" +then + exit_fail "Expected new state to be 'AUTHENTICATIONS_EDITING', got '$STATE'" +fi + +ARRAY_LENGTH=`jq -r -e '.authentication_methods | length' < $SFILE` +if test $ARRAY_LENGTH != 2 +then + exit_fail "Expected array length to be 2, got '$ARRAY_LENGTH'" +fi + +echo -n "." + +# Third method +anastasis-reducer -a \ + '{"authentication_method": { + "type": "question", + "instructions": "Where do you live?", + "challenge": "9NGQ4WR" + }}' \ + add_authentication $SFILE $TFILE + +STATE=`jq -r -e .backup_state < $TFILE` +if test "$STATE" != "AUTHENTICATIONS_EDITING" +then + exit_fail "Expected new state to be 'AUTHENTICATIONS_EDITING', got '$STATE'" +fi + +ARRAY_LENGTH=`jq -r -e '.authentication_methods | length' < $TFILE` +if test $ARRAY_LENGTH != 3 +then + exit_fail "Expected array length to be 3, got '$ARRAY_LENGTH'" +fi + +echo " OK" + + +echo -n "Test delete authentication ..." + +anastasis-reducer -a \ + '{"authentication_method": 2 }' \ + delete_authentication $TFILE $SFILE + +STATE=`jq -r -e .backup_state < $SFILE` +if test "$STATE" != "AUTHENTICATIONS_EDITING" +then + exit_fail "Expected new state to be 'AUTHENTICATIONS_EDITING', got '$STATE'" +fi + +ARRAY_LENGTH=`jq -r -e '.authentication_methods | length' < $SFILE` +if test $ARRAY_LENGTH != 2 +then + exit_fail "Expected array length to be 2, got '$ARRAY_LENGTH'" +fi + +echo " OK" + +exit 0 diff --git a/src/cli/test_anastasis_reducer_backup_enter_user_attributes.sh b/src/cli/test_anastasis_reducer_backup_enter_user_attributes.sh new file mode 100755 index 0000000..433438e --- /dev/null +++ b/src/cli/test_anastasis_reducer_backup_enter_user_attributes.sh @@ -0,0 +1,140 @@ +#!/bin/bash + +set -eu + +# Exit, with status code "skip" (no 'real' failure) +function exit_skip() { + echo " SKIP: $1" + exit 77 +} + +# Exit, with error message (hard failure) +function exit_fail() { + echo " ERROR: $1" + exit 1 +} + +# Cleanup to run whenever we exit +function cleanup() +{ + for n in `jobs -p` + do + kill $n 2> /dev/null || true + done + wait +} + +CONF_1="test_anastasis_reducer_1.conf" +CONF_2="test_anastasis_reducer_2.conf" +CONF_3="test_anastasis_reducer_3.conf" +CONF_4="test_anastasis_reducer_4.conf" +TFILE=`mktemp test_reducer_stateXXXXXX` + +# Install cleanup handler (except for kill -9) +trap cleanup EXIT + +# Check we can actually run +echo -n "Testing for jq" +jq -h > /dev/null || exit_skip "jq required" +echo " FOUND" + +echo -n "Testing for anastasis-reducer ..." +anastasis-reducer -h > /dev/null || exit_skip "anastasis-reducer required" +echo " FOUND" + +echo -n "Testing for anastasis-httpd" +anastasis-httpd -h >/dev/null /dev/null 2>/dev/null || true +createdb $TARGET_DB_1 || exit_skip "Could not create database $TARGET_DB_1" +anastasis-dbinit -c $CONF_1 2> anastasis-dbinit_1.log +dropdb $TARGET_DB_2 >/dev/null 2>/dev/null || true +createdb $TARGET_DB_2 || exit_skip "Could not create database $TARGET_DB_2" +anastasis-dbinit -c $CONF_2 2> anastasis-dbinit_2.log +dropdb $TARGET_DB_3 >/dev/null 2>/dev/null || true +createdb $TARGET_DB_3 || exit_skip "Could not create database $TARGET_DB_3" +anastasis-dbinit -c $CONF_3 2> anastasis-dbinit_3.log +dropdb $TARGET_DB_4 >/dev/null 2>/dev/null || true +createdb $TARGET_DB_4 || exit_skip "Could not create database $TARGET_DB_4" +anastasis-dbinit -c $CONF_4 2> anastasis-dbinit_4.log + +echo " OK" + +echo -n "Launching anastasis service ..." +anastasis-httpd -c $CONF_1 2> anastasis-httpd_1.log & +anastasis-httpd -c $CONF_2 2> anastasis-httpd_2.log & +anastasis-httpd -c $CONF_3 2> anastasis-httpd_3.log & +anastasis-httpd -c $CONF_4 2> anastasis-httpd_4.log & + +# Wait for anastasis service to be available +for n in `seq 1 50` +do + echo -n "." + sleep 0.1 + OK=0 + # anastasis_01 + wget http://localhost:8086/ -o /dev/null -O /dev/null >/dev/null || continue + # anastasis_02 + wget http://localhost:8087/ -o /dev/null -O /dev/null >/dev/null || continue + # anastasis_03 + wget http://localhost:8088/ -o /dev/null -O /dev/null >/dev/null || continue + # anastasis_04 + wget http://localhost:8089/ -o /dev/null -O /dev/null >/dev/null || continue + OK=1 + break +done + +if [ 1 != $OK ] +then + exit_skip "Failed to launch anastasis services" +fi +echo " OK" + +# Test user attributes collection in a backup state +echo -n "Test user attributes collection in a backup state ..." + +anastasis-reducer -L WARNING -a \ + '{"identity_attributes": { + "full_name": "Max Musterman", + "sq_number": "4", + "birthdate": "2000-01-01"}}' \ + enter_user_attributes resources/02-backup.json $TFILE + +STATE=`jq -r -e .backup_state < $TFILE` +if test "$STATE" != "AUTHENTICATIONS_EDITING" +then + exit_fail "Expected new state to be 'AUTHENTICATIONS_EDITING', got '$STATE'" +fi + +SELECTED_COUNTRY=`jq -r -e .selected_country < $TFILE` +if test "$SELECTED_COUNTRY" != "xx" +then + exit_fail "Expected selected country to be 'xx', got '$SELECTED_COUNTRY'" +fi + +echo "OK" + +echo -n "Test user attributes collection in a recovery state ..." +anastasis-reducer -a \ + '{"identity_attributes": { + "full_name": "Max Musterman", + "sq_number": "4", + "birthdate": "2000-01-01"}}' \ + enter_user_attributes resources/02-recovery.json $TFILE 2> /dev/null && exit_fail "Expected recovery to fail due to lacking policy data" + +echo "OK" + +rm -f $TFILE + +exit 0 diff --git a/src/cli/test_anastasis_reducer_done_authentication.sh b/src/cli/test_anastasis_reducer_done_authentication.sh new file mode 100755 index 0000000..87c738c --- /dev/null +++ b/src/cli/test_anastasis_reducer_done_authentication.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +set -eu + +# Exit, with status code "skip" (no 'real' failure) +function exit_skip() { + echo " SKIP: $1" + exit 77 +} + +# Exit, with error message (hard failure) +function exit_fail() { + echo " ERROR: $1" + exit 1 +} + +# Cleanup to run whenever we exit +function cleanup() +{ + for n in `jobs -p` + do + kill $n 2> /dev/null || true + done + rm -f $TFILE + wait +} + +# Install cleanup handler (except for kill -9) +TFILE=`mktemp test_reducer_stateXXXXXX` +trap cleanup EXIT + +# Check we can actually run +echo -n "Testing for jq ..." +jq -h > /dev/null || exit_skip "jq required" +echo " FOUND" + +echo -n "Testing for anastasis-reducer ..." +anastasis-reducer -h > /dev/null || exit_skip "anastasis-reducer required" +echo " FOUND" + + +echo -n "Test failing done authentication (next) ..." +anastasis-reducer next resources/03-backup.json $TFILE 2> /dev/null && exit_fail "Should have failed without challenges" + +echo " OK" + + +echo -n "Test done authentication (next) ..." +anastasis-reducer next resources/04-backup.json $TFILE + +STATE=`jq -r -e .backup_state < $TFILE` +if test "$STATE" != "POLICIES_REVIEWING" +then + exit_fail "Expected new state to be AUTHENTICATIONS_EDITING, got $STATE" +fi + +ARRAY_LENGTH=`jq -r -e '.policies | length' < $TFILE` +if test $ARRAY_LENGTH -lt 3 +then + exit_fail "Expected policy array length to be >= 3, got $ARRAY_LENGTH" +fi + +echo " OK" + +exit 0 diff --git a/src/cli/test_anastasis_reducer_done_policy_review.sh b/src/cli/test_anastasis_reducer_done_policy_review.sh new file mode 100755 index 0000000..7052067 --- /dev/null +++ b/src/cli/test_anastasis_reducer_done_policy_review.sh @@ -0,0 +1,105 @@ +#!/bin/bash + +set -eu + +# Exit, with status code "skip" (no 'real' failure) +function exit_skip() { + echo " SKIP: $1" + exit 77 +} + +# Exit, with error message (hard failure) +function exit_fail() { + echo " ERROR: $1" + exit 1 +} + +# Cleanup to run whenever we exit +function cleanup() +{ + for n in `jobs -p` + do + kill $n 2> /dev/null || true + done + rm -f $TFILE + wait +} + +# Install cleanup handler (except for kill -9) +TFILE=`mktemp test_reducer_stateXXXXXX` +trap cleanup EXIT + + +# Check we can actually run +echo -n "Testing for jq ..." +jq -h > /dev/null || exit_skip "jq required" +echo " FOUND" + +echo -n "Testing for anastasis-reducer ..." +anastasis-reducer -h > /dev/null || exit_skip "anastasis-reducer required" +echo " FOUND" + +echo -n "Test done policy review (next) in a backup state ..." +anastasis-reducer next resources/05-backup.json $TFILE + +STATE=`jq -r -e .backup_state < $TFILE` +if test "$STATE" != "SECRET_EDITING" +then + exit_fail "Expected new state to be 'SECRET_EDITING', got '$STATE'" +fi + +ARRAY_LENGTH=`jq -r -e '.authentication_methods | length' < $TFILE` +if test $ARRAY_LENGTH -lt 3 +then + exit_fail "Expected auth methods array length to be >= 3, got $ARRAY_LENGTH" +fi + +ARRAY_LENGTH=`jq -r -e '.policies | length' < $TFILE` +if test $ARRAY_LENGTH -lt 3 +then + exit_fail "Expected policies array length to be >= 3, got $ARRAY_LENGTH" +fi + +echo " OK" + + + +echo -n "Test adding policy ..." +anastasis-reducer -a \ + '{ "policy" : [ + { "authentication_method" : 1, + "provider" : "http://localhost:8088/" }, + { "authentication_method" : 1, + "provider" : "http://localhost:8089/" } + ] }' \ + add_policy \ + resources/05-backup.json \ + $TFILE 2> /dev/null + +ARRAY_LENGTH=`jq -r -e '.policies | length' < $TFILE` +if test $ARRAY_LENGTH -lt 4 +then + exit_fail "Expected policy array length to be >= 4, got $ARRAY_LENGTH" +fi + +echo " OK" + + +echo -n "Test deleting policy ..." +anastasis-reducer -a \ + '{ "policy_index" : 2 }' \ + delete_policy \ + resources/05-backup.json \ + $TFILE 2> /dev/null + +ARRAY_LENGTH=`jq -r -e '.policies | length' < $TFILE` +if test $ARRAY_LENGTH -ge 3 +then + exit_fail "Expected policy array length to be < 3, got $ARRAY_LENGTH" +fi + +echo " OK" + + + +exit 0 diff --git a/src/cli/test_anastasis_reducer_enter_secret.sh b/src/cli/test_anastasis_reducer_enter_secret.sh new file mode 100755 index 0000000..dadd8d0 --- /dev/null +++ b/src/cli/test_anastasis_reducer_enter_secret.sh @@ -0,0 +1,417 @@ +#!/bin/bash +## Coloring style Text shell script +COLOR='\033[0;35m' +NOCOLOR='\033[0m' +BOLD="$(tput bold)" +NORM="$(tput sgr0)" + +set -eu + +# Exit, with status code "skip" (no 'real' failure) +function exit_skip() { + echo " SKIP: $1" + exit 77 +} + +# Exit, with error message (hard failure) +function exit_fail() { + echo " FAIL: $1" + exit 1 +} + +# Cleanup to run whenever we exit +function cleanup() +{ + for n in `jobs -p` + do + kill $n 2> /dev/null || true + done + rm -rf $CONF $WALLET_DB $TFILE $UFILE $TMP_DIR + wait +} + +CONF_1="test_anastasis_reducer_1.conf" +CONF_2="test_anastasis_reducer_2.conf" +CONF_3="test_anastasis_reducer_3.conf" +CONF_4="test_anastasis_reducer_4.conf" + +# Exchange configuration file will be edited, so we create one +# from the template. +CONF=`mktemp test_reducerXXXXXX.conf` +cp test_reducer.conf $CONF + +TMP_DIR=`mktemp -d keys-tmp-XXXXXX` +WALLET_DB=`mktemp test_reducer_walletXXXXXX.json` +TFILE=`mktemp test_reducer_statePPXXXXXX` +UFILE=`mktemp test_reducer_stateBFXXXXXX` + +# Install cleanup handler (except for kill -9) +trap cleanup EXIT + +# Check we can actually run +echo -n "Testing for jq" +jq -h > /dev/null || exit_skip "jq required" +echo " FOUND" +echo -n "Testing for anastasis-reducer ..." +anastasis-reducer -h > /dev/null || exit_skip "anastasis-reducer required" +echo " FOUND" + +echo -n "Testing for taler" +taler-exchange-httpd -h > /dev/null || exit_skip " taler-exchange required" +taler-merchant-httpd -h > /dev/null || exit_skip " taler-merchant required" +echo " FOUND" + +echo -n "Testing for taler-bank-manage" +taler-bank-manage --help >/dev/null /dev/null /dev/null /dev/null 2>/dev/null || true +createdb $TARGET_DB_1 || exit_skip "Could not create database $TARGET_DB_1" +anastasis-dbinit -c $CONF_1 2> anastasis-dbinit_1.log +dropdb $TARGET_DB_2 >/dev/null 2>/dev/null || true +createdb $TARGET_DB_2 || exit_skip "Could not create database $TARGET_DB_2" +anastasis-dbinit -c $CONF_2 2> anastasis-dbinit_2.log +dropdb $TARGET_DB_3 >/dev/null 2>/dev/null || true +createdb $TARGET_DB_3 || exit_skip "Could not create database $TARGET_DB_3" +anastasis-dbinit -c $CONF_3 2> anastasis-dbinit_3.log +dropdb $TARGET_DB_4 >/dev/null 2>/dev/null || true +createdb $TARGET_DB_4 || exit_skip "Could not create database $TARGET_DB_4" +anastasis-dbinit -c $CONF_4 2> anastasis-dbinit_4.log + +echo " OK" + +echo -n "Generating Taler auditor, exchange and merchant configurations ..." + +DATA_DIR=`taler-config -f -c $CONF -s PATHS -o TALER_HOME` +rm -rf $DATA_DIR + +# obtain key configuration data +MASTER_PRIV_FILE=`taler-config -f -c $CONF -s EXCHANGE -o MASTER_PRIV_FILE` +MASTER_PRIV_DIR=`dirname $MASTER_PRIV_FILE` +mkdir -p $MASTER_PRIV_DIR +gnunet-ecc -g1 $MASTER_PRIV_FILE > /dev/null 2> /dev/null +MASTER_PUB=`gnunet-ecc -p $MASTER_PRIV_FILE` +EXCHANGE_URL=`taler-config -c $CONF -s EXCHANGE -o BASE_URL` +MERCHANT_PORT=`taler-config -c $CONF -s MERCHANT -o PORT` +MERCHANT_URL=http://localhost:${MERCHANT_PORT}/ +BANK_PORT=`taler-config -c $CONF -s BANK -o HTTP_PORT` +BANK_URL=http://localhost:${BANK_PORT}/ +AUDITOR_URL=http://localhost:8083/ +AUDITOR_PRIV_FILE=`taler-config -f -c $CONF -s AUDITOR -o AUDITOR_PRIV_FILE` +AUDITOR_PRIV_DIR=`dirname $AUDITOR_PRIV_FILE` +mkdir -p $AUDITOR_PRIV_DIR +gnunet-ecc -g1 $AUDITOR_PRIV_FILE > /dev/null 2> /dev/null +AUDITOR_PUB=`gnunet-ecc -p $AUDITOR_PRIV_FILE` + +# patch configuration +TALER_DB=talercheck +taler-config -c $CONF -s exchange -o MASTER_PUBLIC_KEY -V $MASTER_PUB +taler-config -c $CONF -s merchant-exchange-default -o MASTER_KEY -V $MASTER_PUB +taler-config -c $CONF -s exchangedb-postgres -o CONFIG -V postgres:///$TALER_DB +taler-config -c $CONF -s auditordb-postgres -o CONFIG -V postgres:///$TALER_DB +taler-config -c $CONF -s merchantdb-postgres -o CONFIG -V postgres:///$TALER_DB +taler-config -c $CONF -s bank -o database -V postgres:///$TALER_DB +taler-config -c $CONF -s exchange -o KEYDIR -V "${TMP_DIR}/keydir/" +taler-config -c $CONF -s exchange -o REVOCATION_DIR -V "${TMP_DIR}/revdir/" + +echo " OK" + +echo -n "Setting up exchange ..." + +# reset database +dropdb $TALER_DB >/dev/null 2>/dev/null || true +createdb $TALER_DB || exit_skip "Could not create database $TALER_DB" +taler-exchange-dbinit -c $CONF +taler-merchant-dbinit -c $CONF +taler-auditor-dbinit -c $CONF +taler-auditor-exchange -c $CONF -m $MASTER_PUB -u $EXCHANGE_URL + +echo " OK" + +# Launch services +echo -n "Launching taler services ..." +taler-bank-manage-testing $CONF postgres:///$TALER_DB serve > taler-bank.log 2> taler-bank.err & +taler-exchange-secmod-eddsa -c $CONF 2> taler-exchange-secmod-eddsa.log & +taler-exchange-secmod-rsa -c $CONF 2> taler-exchange-secmod-rsa.log & +taler-exchange-httpd -c $CONF 2> taler-exchange-httpd.log & +taler-merchant-httpd -c $CONF -L INFO 2> taler-merchant-httpd.log & +taler-exchange-wirewatch -c $CONF 2> taler-exchange-wirewatch.log & +taler-auditor-httpd -L INFO -c $CONF 2> taler-auditor-httpd.log & + +echo " OK" + +echo -n "Launching anastasis services ..." +PREFIX="" #valgrind +$PREFIX anastasis-httpd -c $CONF_1 2> anastasis-httpd_1.log & +$PREFIX anastasis-httpd -c $CONF_2 2> anastasis-httpd_2.log & +$PREFIX anastasis-httpd -c $CONF_3 2> anastasis-httpd_3.log & +$PREFIX anastasis-httpd -c $CONF_4 2> anastasis-httpd_4.log & + +# Wait for bank to be available (usually the slowest) +for n in `seq 1 50` +do + echo -n "." + sleep 0.2 + OK=0 + # bank + wget --tries=1 --timeout=1 http://localhost:8082/ -o /dev/null -O /dev/null >/dev/null || continue + OK=1 + break +done + +if [ 1 != $OK ] +then + exit_skip "Failed to launch services (bank)" +fi + +# Wait for all other taler services to be available +for n in `seq 1 50` +do + echo -n "." + sleep 0.1 + OK=0 + # exchange + wget --tries=1 --timeout=1 http://localhost:8081/seed -o /dev/null -O /dev/null >/dev/null || continue + # merchant + wget --tries=1 --timeout=1 http://localhost:9966/ -o /dev/null -O /dev/null >/dev/null || continue + # auditor + wget --tries=1 --timeout=1 http://localhost:8083/ -o /dev/null -O /dev/null >/dev/null || continue + OK=1 + break +done + +if [ 1 != $OK ] +then + exit_skip "Failed to launch taler services" +fi + +echo "OK" + +echo -n "Setting up keys ..." +taler-exchange-offline -c $CONF \ + download \ + sign \ + enable-account payto://x-taler-bank/localhost/Exchange \ + enable-auditor $AUDITOR_PUB $AUDITOR_URL "TESTKUDOS Auditor" \ + wire-fee now x-taler-bank TESTKUDOS:0.01 TESTKUDOS:0.01 \ + upload &> taler-exchange-offline.log + +echo -n "." + +for n in `seq 1 3` +do + echo -n "." + OK=0 + wget --tries=1 --timeout=1 http://localhost:8081/keys -o /dev/null -O /dev/null >/dev/null || continue + OK=1 + break +done + +if [ 1 != $OK ] +then + exit_skip "Failed to setup keys" +fi + +echo " OK" + +echo -n "Setting up auditor signatures ..." +taler-auditor-offline -c $CONF \ + download sign upload &> taler-auditor-offline.log +echo " OK" + +echo -n "Waiting for anastasis services ..." + +# Wait for anastasis services to be available +for n in `seq 1 50` +do + echo -n "." + sleep 0.1 + OK=0 + # anastasis_01 + wget --tries=1 --timeout=1 http://localhost:8086/ -o /dev/null -O /dev/null >/dev/null || continue + # anastasis_02 + wget --tries=1 --timeout=1 http://localhost:8087/ -o /dev/null -O /dev/null >/dev/null || continue + # anastasis_03 + wget --tries=1 --timeout=1 http://localhost:8088/ -o /dev/null -O /dev/null >/dev/null || continue + # anastasis_04 + wget --tries=1 --timeout=1 http://localhost:8089/ -o /dev/null -O /dev/null >/dev/null || continue + OK=1 + break +done + +if [ 1 != $OK ] +then + exit_skip "Failed to launch anastasis services" +fi +echo "OK" + +echo -n "Configuring merchant instance ..." +# Setup merchant + +curl -H "Content-Type: application/json" -X POST -d '{"auth":{"method":"external"},"payto_uris":["payto://x-taler-bank/localhost/43"],"id":"default","name":"default","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_ms" : 3600000},"default_pay_delay":{"d_ms": 3600000}}' http://localhost:9966/private/instances + + +echo " DONE" + +echo -en $COLOR$BOLD"Test enter secret in a backup state ..."$NORM$NOCOLOR + +$PREFIX anastasis-reducer -a \ + '{"secret": { "value" : "veryhardtoguesssecret", "mime" : "text/plain" } }' \ + enter_secret resources/06-backup.json $TFILE + +STATE=`jq -r -e .backup_state < $TFILE` +if test "$STATE" != "SECRET_EDITING" +then + jq -e . $TFILE + exit_fail "Expected new state to be 'SECRET_EDITING', got '$STATE'" +fi + +echo " DONE" +echo -en $COLOR$BOLD"Test expiration change ..."$NORM$NOCOLOR + +MILLIS=`date '+%s'`000 +# Use 156 days into the future to get 1 year +MILLIS=`expr $MILLIS + 13478400000` + +$PREFIX anastasis-reducer -a \ + "$(jq -n ' + {"expiration": { "t_ms" : $MSEC } }' \ + --argjson MSEC $MILLIS + )" \ + update_expiration $TFILE $UFILE + +STATE=`jq -r -e .backup_state < $UFILE` +if test "$STATE" != "SECRET_EDITING" +then + jq -e . $UFILE + exit_fail "Expected new state to be 'SECRET_EDITING', got '$STATE'" +fi + +FEES=`jq -r -e '.upload_fees[0].fee' < $UFILE` +# 4x 4.99 for annual fees, plus 4x0.01 for truth uploads +if test "$FEES" != "TESTKUDOS:20" +then + jq -e . $TFILE + exit_fail "Expected upload fees to be 'TESTKUDOS:20', got '$FEES'" +fi + + +echo " DONE" +echo -en $COLOR$BOLD"Test advance to payment ..."$NORM$NOCOLOR + +$PREFIX anastasis-reducer next $UFILE $TFILE + +STATE=`jq -r -e .backup_state < $TFILE` +if test "$STATE" != "TRUTHS_PAYING" +then + jq -e . $TFILE + exit_fail "Expected new state to be 'TRUTHS_PAYING', got '$STATE'" +fi + +TMETHOD=`jq -r -e '.policies[0].methods[0].truth.type' < $TFILE` +if test $TMETHOD != "question" +then + exit_fail "Expected method to be >='question', got $TMETHOD" +fi + +echo " OK" +#Pay + +echo -en $COLOR$BOLD"Withdrawing amount to wallet ..."$NORM$NOCOLOR + +rm $WALLET_DB +taler-wallet-cli --no-throttle --wallet-db=$WALLET_DB api 'withdrawTestBalance' \ + "$(jq -n ' + { + amount: "TESTKUDOS:40", + bankBaseUrl: $BANK_URL, + exchangeBaseUrl: $EXCHANGE_URL + }' \ + --arg BANK_URL "$BANK_URL" \ + --arg EXCHANGE_URL "$EXCHANGE_URL" + )" 2>wallet.err >wallet.log +taler-wallet-cli --wallet-db=$WALLET_DB run-until-done 2>wallet.err >wallet.log + +echo " OK" + +echo -en $COLOR$BOLD"Making payments for truth uploads ... "$NORM$NOCOLOR +OBJECT_SIZE=`jq -r -e '.payments | length' < $TFILE` +for ((INDEX=0; INDEX < $OBJECT_SIZE; INDEX++)) +do + PAY_URI=`jq --argjson INDEX $INDEX -r -e '.payments[$INDEX]' < $TFILE` + # run wallet CLI + echo -n "$INDEX" + taler-wallet-cli --wallet-db=$WALLET_DB handle-uri $PAY_URI -y 2>wallet.err >wallet.log + echo -n "," +done +echo " OK" +echo -e $COLOR$BOLD"Running wallet run-pending..."$NORM$NOCOLOR +taler-wallet-cli --wallet-db=$WALLET_DB run-pending 2>wallet.err >wallet.log +echo -e $COLOR$BOLD"Payments done"$NORM$NOCOLOR + + +echo -en $COLOR$BOLD"Try to upload again ..."$NORM$NOCOLOR +$PREFIX anastasis-reducer pay $TFILE $UFILE +mv $UFILE $TFILE +echo " OK" + + +STATE=`jq -r -e .backup_state < $TFILE` +if test "$STATE" != "POLICIES_PAYING" +then + exit_fail "Expected new state to be 'POLICIES_PAYING', got '$STATE'" +fi + +export TFILE +export UFILE + +echo -en $COLOR$BOLD"Making payments for policy uploads ... "$NORM$NOCOLOR +OBJECT_SIZE=`jq -r -e '.policy_payment_requests | length' < $TFILE` +for ((INDEX=0; INDEX < $OBJECT_SIZE; INDEX++)) +do + PAY_URI=`jq --argjson INDEX $INDEX -r -e '.policy_payment_requests[$INDEX].payto' < $TFILE` + # run wallet CLI + export PAY_URI + echo -n "$INDEX" + taler-wallet-cli --wallet-db=$WALLET_DB handle-uri $PAY_URI -y 2>wallet.err >wallet.log + echo -n "," +done +echo " OK" +echo -e $COLOR$BOLD"Running wallet run-pending..."$NORM$NOCOLOR +taler-wallet-cli --wallet-db=$WALLET_DB run-pending 2>wallet.err >wallet.log +echo -e $COLOR$BOLD"Payments done"$NORM$NOCOLOR + +echo -en $COLOR$BOLD"Try to upload again ..."$NORM$NOCOLOR +$PREFIX anastasis-reducer pay $TFILE $UFILE + +echo " OK" + +echo -n "Final checks ..." + +STATE=`jq -r -e .backup_state < $UFILE` +if test "$STATE" != "BACKUP_FINISHED" +then + exit_fail "Expected new state to be BACKUP_FINISHED, got $STATE" +fi + +jq -r -e .core_secret < $UFILE > /dev/null && exit_fail "'core_secret' was not cleared upon success" + +echo " OK" + +exit 0 diff --git a/src/cli/test_anastasis_reducer_initialize_state.sh b/src/cli/test_anastasis_reducer_initialize_state.sh new file mode 100755 index 0000000..9dc0c59 --- /dev/null +++ b/src/cli/test_anastasis_reducer_initialize_state.sh @@ -0,0 +1,64 @@ +#!/bin/bash + +set -eu + +# Exit, with status code "skip" (no 'real' failure) +function exit_skip() { + echo " SKIP: $1" + exit 77 +} + +# Exit, with error message (hard failure) +function exit_fail() { + echo " FAIL: $1" + exit 1 +} + +# Cleanup to run whenever we exit +function cleanup() +{ + for n in `jobs -p` + do + kill $n 2> /dev/null || true + done + rm -f $SFILE $TFILE + wait +} + +# Install cleanup handler (except for kill -9) +SFILE=`mktemp test_reducer_stateXXXXXX` +TFILE=`mktemp test_reducer_stateXXXXXX` + +trap cleanup EXIT + +# Check we can actually run +echo -n "Testing for jq ..." +jq -h > /dev/null || exit_skip "jq required" +echo " FOUND" +echo -n "Testing for anastasis-reducer ..." +anastasis-reducer -h > /dev/null || exit_skip "anastasis-reducer required" +echo " FOUND" +echo -n "Test initialization of a backup state ..." +anastasis-reducer -b $SFILE + +STATE=`jq -r -e .backup_state < $SFILE` +if test "$STATE" != "CONTINENT_SELECTING" +then + exit_fail "Expected initial state to be CONTINENT_SELECTING, got $STATE" +fi +jq -e .continents[0] < $SFILE > /dev/null || exit_fail "Expected initial state to include continents" + +echo " OK" + +echo -n "Test initialization of a recovery state ..." +anastasis-reducer -r $TFILE + +STATE=`jq -r -e .recovery_state < $TFILE` +if test "$STATE" != "CONTINENT_SELECTING" +then + exit_fail "Expected initial state to be CONTINENT_SELECTING, got $STATE" +fi +jq -e .continents[0] < $TFILE > /dev/null || exit_fail "Expected initial state to include continents" +echo " OK" + +exit 0 diff --git a/src/cli/test_anastasis_reducer_recovery_enter_user_attributes.sh b/src/cli/test_anastasis_reducer_recovery_enter_user_attributes.sh new file mode 100755 index 0000000..d0562e2 --- /dev/null +++ b/src/cli/test_anastasis_reducer_recovery_enter_user_attributes.sh @@ -0,0 +1,516 @@ +#!/bin/bash + +set -eu + +# Exit, with status code "skip" (no 'real' failure) +function exit_skip() { + echo " SKIP: $1" + exit 77 +} + +# Exit, with error message (hard failure) +function exit_fail() { + echo " FAIL: $1" + exit 1 +} + +# Cleanup to run whenever we exit +function cleanup() +{ + for n in `jobs -p` + do + kill $n 2> /dev/null || true + done + rm -rf $CONF $WALLET_DB $R1FILE $R2FILE $B1FILE $B2FILE $TMP_DIR + wait +} + + +CONF_1="test_anastasis_reducer_1.conf" +CONF_2="test_anastasis_reducer_2.conf" +CONF_3="test_anastasis_reducer_3.conf" +CONF_4="test_anastasis_reducer_4.conf" + + +# Exchange configuration file will be edited, so we create one +# from the template. +CONF=`mktemp test_reducerXXXXXX.conf` +cp test_reducer.conf $CONF + +TMP_DIR=`mktemp -d keys-tmp-XXXXXX` +WALLET_DB=`mktemp test_reducer_walletXXXXXX.json` +B1FILE=`mktemp test_reducer_stateB1XXXXXX` +B2FILE=`mktemp test_reducer_stateB2XXXXXX` +R1FILE=`mktemp test_reducer_stateR1XXXXXX` +R2FILE=`mktemp test_reducer_stateR2XXXXXX` + +# Install cleanup handler (except for kill -9) +trap cleanup EXIT + +# Check we can actually run +echo -n "Testing for jq" +jq -h > /dev/null || exit_skip "jq required" +echo " FOUND" +echo -n "Testing for anastasis-reducer ..." +anastasis-reducer -h > /dev/null || exit_skip "anastasis-reducer required" +echo " FOUND" + +echo -n "Testing for taler" +taler-exchange-httpd -h > /dev/null || exit_skip " taler-exchange required" +taler-merchant-httpd -h > /dev/null || exit_skip " taler-merchant required" +echo " FOUND" + +echo -n "Testing for taler-bank-manage" +taler-bank-manage --help >/dev/null /dev/null /dev/null /dev/null 2>/dev/null || true +createdb $TARGET_DB_1 || exit_skip "Could not create database $TARGET_DB_1" +anastasis-dbinit -c $CONF_1 2> anastasis-dbinit_1.log +dropdb $TARGET_DB_2 >/dev/null 2>/dev/null || true +createdb $TARGET_DB_2 || exit_skip "Could not create database $TARGET_DB_2" +anastasis-dbinit -c $CONF_2 2> anastasis-dbinit_2.log +dropdb $TARGET_DB_3 >/dev/null 2>/dev/null || true +createdb $TARGET_DB_3 || exit_skip "Could not create database $TARGET_DB_3" +anastasis-dbinit -c $CONF_3 2> anastasis-dbinit_3.log +dropdb $TARGET_DB_4 >/dev/null 2>/dev/null || true +createdb $TARGET_DB_4 || exit_skip "Could not create database $TARGET_DB_4" +anastasis-dbinit -c $CONF_4 2> anastasis-dbinit_4.log + +echo " OK" + +echo -n "Generating Taler auditor, exchange and merchant configurations ..." + +DATA_DIR=`taler-config -f -c $CONF -s PATHS -o TALER_HOME` +rm -rf $DATA_DIR + +# obtain key configuration data +MASTER_PRIV_FILE=`taler-config -f -c $CONF -s EXCHANGE -o MASTER_PRIV_FILE` +MASTER_PRIV_DIR=`dirname $MASTER_PRIV_FILE` +mkdir -p $MASTER_PRIV_DIR +gnunet-ecc -g1 $MASTER_PRIV_FILE > /dev/null 2> /dev/null +MASTER_PUB=`gnunet-ecc -p $MASTER_PRIV_FILE` +EXCHANGE_URL=`taler-config -c $CONF -s EXCHANGE -o BASE_URL` +MERCHANT_PORT=`taler-config -c $CONF -s MERCHANT -o PORT` +MERCHANT_URL=http://localhost:${MERCHANT_PORT}/ +BANK_PORT=`taler-config -c $CONF -s BANK -o HTTP_PORT` +BANK_URL=http://localhost:${BANK_PORT}/ +AUDITOR_URL=http://localhost:8083/ +AUDITOR_PRIV_FILE=`taler-config -f -c $CONF -s AUDITOR -o AUDITOR_PRIV_FILE` +AUDITOR_PRIV_DIR=`dirname $AUDITOR_PRIV_FILE` +mkdir -p $AUDITOR_PRIV_DIR +gnunet-ecc -g1 $AUDITOR_PRIV_FILE > /dev/null 2> /dev/null +AUDITOR_PUB=`gnunet-ecc -p $AUDITOR_PRIV_FILE` + +# patch configuration +TALER_DB=talercheck +taler-config -c $CONF -s exchange -o MASTER_PUBLIC_KEY -V $MASTER_PUB +taler-config -c $CONF -s merchant-exchange-default -o MASTER_KEY -V $MASTER_PUB +taler-config -c $CONF -s exchangedb-postgres -o CONFIG -V postgres:///$TALER_DB +taler-config -c $CONF -s auditordb-postgres -o CONFIG -V postgres:///$TALER_DB +taler-config -c $CONF -s merchantdb-postgres -o CONFIG -V postgres:///$TALER_DB +taler-config -c $CONF -s bank -o database -V postgres:///$TALER_DB +taler-config -c $CONF -s exchange -o KEYDIR -V "${TMP_DIR}/keydir/" +taler-config -c $CONF -s exchange -o REVOCATION_DIR -V "${TMP_DIR}/revdir/" + +echo " OK" + +echo -n "Setting up exchange ..." + +# reset database +dropdb $TALER_DB >/dev/null 2>/dev/null || true +createdb $TALER_DB || exit_skip "Could not create database $TALER_DB" +taler-exchange-dbinit -c $CONF +taler-merchant-dbinit -c $CONF +taler-auditor-dbinit -c $CONF +taler-auditor-exchange -c $CONF -m $MASTER_PUB -u $EXCHANGE_URL + +echo " OK" + +# Launch services +echo -n "Launching taler services ..." +taler-bank-manage-testing $CONF postgres:///$TALER_DB serve > taler-bank.log 2> taler-bank.err & +taler-exchange-secmod-eddsa -c $CONF 2> taler-exchange-secmod-eddsa.log & +taler-exchange-secmod-rsa -c $CONF 2> taler-exchange-secmod-rsa.log & +taler-exchange-httpd -c $CONF 2> taler-exchange-httpd.log & +taler-merchant-httpd -c $CONF -L INFO 2> taler-merchant-httpd.log & +taler-exchange-wirewatch -c $CONF 2> taler-exchange-wirewatch.log & +taler-auditor-httpd -L INFO -c $CONF 2> taler-auditor-httpd.log & + +echo " OK" + +echo -n "Launching anastasis services ..." +PREFIX="" #valgrind +$PREFIX anastasis-httpd -c $CONF_1 2> anastasis-httpd_1.log & +$PREFIX anastasis-httpd -c $CONF_2 2> anastasis-httpd_2.log & +$PREFIX anastasis-httpd -c $CONF_3 2> anastasis-httpd_3.log & +$PREFIX anastasis-httpd -c $CONF_4 2> anastasis-httpd_4.log & + +# Wait for bank to be available (usually the slowest) +for n in `seq 1 50` +do + echo -n "." + sleep 0.2 + OK=0 + # bank + wget --tries=1 --timeout=1 http://localhost:8082/ -o /dev/null -O /dev/null >/dev/null || continue + OK=1 + break +done + +if [ 1 != $OK ] +then + exit_skip "Failed to launch services (bank)" +fi + +# Wait for all other taler services to be available +for n in `seq 1 50` +do + echo -n "." + sleep 0.1 + OK=0 + # exchange + wget --tries=1 --timeout=1 http://localhost:8081/seed -o /dev/null -O /dev/null >/dev/null || continue + # merchant + wget --tries=1 --timeout=1 http://localhost:9966/ -o /dev/null -O /dev/null >/dev/null || continue + # auditor + wget --tries=1 --timeout=1 http://localhost:8083/ -o /dev/null -O /dev/null >/dev/null || continue + OK=1 + break +done + +if [ 1 != $OK ] +then + exit_skip "Failed to launch taler services" +fi + +echo "OK" + +echo -n "Setting up keys ..." +taler-exchange-offline -c $CONF \ + download \ + sign \ + enable-account payto://x-taler-bank/localhost/Exchange \ + enable-auditor $AUDITOR_PUB $AUDITOR_URL "TESTKUDOS Auditor" \ + wire-fee now x-taler-bank TESTKUDOS:0.01 TESTKUDOS:0.01 \ + upload &> taler-exchange-offline.log + +echo -n "." + +for n in `seq 1 3` +do + echo -n "." + OK=0 + wget --tries=1 --timeout=1 http://localhost:8081/keys -o /dev/null -O /dev/null >/dev/null || continue + OK=1 + break +done + +if [ 1 != $OK ] +then + exit_skip "Failed to setup keys" +fi + +echo " OK" + +echo -n "Setting up auditor signatures ..." +taler-auditor-offline -c $CONF \ + download sign upload &> taler-auditor-offline.log +echo " OK" + +echo -n "Waiting for anastasis services ..." + +# Wait for anastasis services to be available +for n in `seq 1 50` +do + echo -n "." + sleep 0.1 + OK=0 + # anastasis_01 + wget --tries=1 --timeout=1 http://localhost:8086/ -o /dev/null -O /dev/null >/dev/null || continue + # anastasis_02 + wget --tries=1 --timeout=1 http://localhost:8087/ -o /dev/null -O /dev/null >/dev/null || continue + # anastasis_03 + wget --tries=1 --timeout=1 http://localhost:8088/ -o /dev/null -O /dev/null >/dev/null || continue + # anastasis_04 + wget --tries=1 --timeout=1 http://localhost:8089/ -o /dev/null -O /dev/null >/dev/null || continue + OK=1 + break +done + +if [ 1 != $OK ] +then + exit_skip "Failed to launch anastasis services" +fi +echo "OK" + +echo -n "Configuring merchant instance ..." +# Setup merchant + +curl -H "Content-Type: application/json" -X POST -d '{"auth":{"method":"external"},"payto_uris":["payto://x-taler-bank/localhost/43"],"id":"default","name":"default","address":{},"jurisdiction":{},"default_max_wire_fee":"TESTKUDOS:1", "default_max_deposit_fee":"TESTKUDOS:1","default_wire_fee_amortization":1,"default_wire_transfer_delay":{"d_ms" : 3600000},"default_pay_delay":{"d_ms": 3600000}}' http://localhost:9966/private/instances + + +echo " DONE" + +echo -n "Running backup logic ...," +anastasis-reducer -b > $B1FILE +echo -n "." +anastasis-reducer -a \ + '{"continent": "Testcontinent"}' \ + select_continent < $B1FILE > $B2FILE +echo -n "." +anastasis-reducer -a \ + '{"country_code": "xx", + "currencies":["TESTKUDOS"]}' \ + select_country < $B2FILE > $B1FILE +echo -n "." +anastasis-reducer -a \ + '{"identity_attributes": { + "full_name": "Max Musterman", + "sq_number": "4", + "birthdate": "2000-01-01"}}' \ + enter_user_attributes < $B1FILE > $B2FILE +echo -n "," +# "91GPWWR" encodes "Hans" +anastasis-reducer -a \ + '{"authentication_method": { + "type": "question", + "instructions": "What is your name?", + "challenge": "91GPWWR" + } }' \ + add_authentication < $B2FILE > $B1FILE +echo -n "." +# "64S36" encodes "123" +anastasis-reducer -a \ + '{"authentication_method": { + "type": "question", + "instructions": "How old are you?", + "challenge": "64S36" + } }' \ + add_authentication < $B1FILE > $B2FILE +echo -n "." +# "9NGQ4WR" encodes "Mars" +anastasis-reducer -a \ + '{"authentication_method": { + "type": "question", + "instructions": "Where do you live?", + "challenge": "9NGQ4WR" + } }' \ + add_authentication < $B2FILE > $B1FILE +echo -n "." +# Finished adding authentication methods +anastasis-reducer \ + next < $B1FILE > $B2FILE + + +echo -n "," +# Finished policy review +anastasis-reducer \ + next < $B2FILE > $B1FILE +echo -n "." + +# Note: 'secret' must here be a Crockford base32-encoded value +anastasis-reducer -a \ + '{"secret": { "value" : "VERYHARDT0GVESSSECRET", "mime" : "text/plain" }}' \ + enter_secret < $B1FILE > $B2FILE +mv $B2FILE $B1FILE +anastasis-reducer next $B1FILE $B2FILE +echo " OK" + + +echo -n "Preparing wallet" +rm $WALLET_DB +taler-wallet-cli --no-throttle --wallet-db=$WALLET_DB api 'withdrawTestBalance' \ + "$(jq -n ' + { + amount: "TESTKUDOS:100", + bankBaseUrl: $BANK_URL, + exchangeBaseUrl: $EXCHANGE_URL + }' \ + --arg BANK_URL "$BANK_URL" \ + --arg EXCHANGE_URL "$EXCHANGE_URL" + )" 2> /dev/null >/dev/null +taler-wallet-cli --wallet-db=$WALLET_DB run-until-done 2>/dev/null >/dev/null +echo " OK" + +echo -en "Making payments for truth uploads ... " +OBJECT_SIZE=`jq -r -e '.payments | length' < $B2FILE` +for ((INDEX=0; INDEX < $OBJECT_SIZE; INDEX++)) +do + PAY_URI=`jq --argjson INDEX $INDEX -r -e '.payments[$INDEX]' < $B2FILE` + # run wallet CLI + echo -n "$INDEX" + taler-wallet-cli --wallet-db=$WALLET_DB handle-uri $PAY_URI -y 2>/dev/null >/dev/null + echo -n ", " +done +echo "OK" +echo -e "Running wallet run-pending..." +taler-wallet-cli --wallet-db=$WALLET_DB run-pending 2>/dev/null >/dev/null +echo -e "Payments done" + +export B2FILE +export B1FILE + +echo -en "Try to upload again ..." +$PREFIX anastasis-reducer pay $B2FILE $B1FILE +mv $B1FILE $B2FILE +echo " OK" + +echo -en "Making payments for policy uploads ... " +OBJECT_SIZE=`jq -r -e '.policy_payment_requests | length' < $B2FILE` +for ((INDEX=0; INDEX < $OBJECT_SIZE; INDEX++)) +do + PAY_URI=`jq --argjson INDEX $INDEX -r -e '.policy_payment_requests[$INDEX].payto' < $B2FILE` + # run wallet CLI + echo -n "$INDEX" + taler-wallet-cli --wallet-db=$WALLET_DB handle-uri $PAY_URI -y 2>/dev/null >/dev/null + echo -n ", " +done +echo " OK" +echo -en "Running wallet run-pending..." +taler-wallet-cli --wallet-db=$WALLET_DB run-pending 2>/dev/null >/dev/null +echo -e " payments DONE" + +echo -en "Try to upload again ..." +anastasis-reducer \ + pay < $B2FILE > $B1FILE +echo " OK: Backup finished" +echo -n "Final backup checks ..." +STATE=`jq -r -e .backup_state < $B1FILE` +if test "$STATE" != "BACKUP_FINISHED" +then + exit_fail "Expected new state to be 'BACKUP_FINISHED', got '$STATE'" +fi + +jq -r -e .core_secret < $B1FILE > /dev/null && exit_fail "'core_secret' was not cleared upon success" + +echo " OK" + +echo -n "Running recovery basic logic ..." +anastasis-reducer -r > $R1FILE +anastasis-reducer -a \ + '{"continent": "Testcontinent"}' \ + select_continent < $R1FILE > $R2FILE +anastasis-reducer -a \ + '{"country_code": "xx", + "currencies":["TESTKUDOS"]}' \ + select_country < $R2FILE > $R1FILE +anastasis-reducer -a '{"identity_attributes": { "full_name": "Max Musterman", "sq_number": "4", "birthdate": "2000-01-01" }}' enter_user_attributes < $R1FILE > $R2FILE + + +STATE=`jq -r -e .recovery_state < $R2FILE` +if test "$STATE" != "SECRET_SELECTING" +then + exit_fail "Expected new state to be 'SECRET_SELECTING', got '$STATE'" +fi +echo " OK" + +echo -n "Selecting default secret" +mv $R2FILE $R1FILE +anastasis-reducer next < $R1FILE > $R2FILE + +STATE=`jq -r -e .recovery_state < $R2FILE` +if test "$STATE" != "CHALLENGE_SELECTING" +then + exit_fail "Expected new state to be 'CHALLENGE_SELECTING', got '$STATE'" +fi +echo " OK" + +echo -n "Running challenge logic ..." + +UUID0=`jq -r -e .recovery_information.challenges[0].uuid < $R2FILE` +UUID1=`jq -r -e .recovery_information.challenges[1].uuid < $R2FILE` +UUID2=`jq -r -e .recovery_information.challenges[2].uuid < $R2FILE` +UUID0Q=`jq -r -e .recovery_information.challenges[0].instructions < $R2FILE` +UUID1Q=`jq -r -e .recovery_information.challenges[1].instructions < $R2FILE` +UUID2Q=`jq -r -e .recovery_information.challenges[2].instructions < $R2FILE` + +if test "$UUID2Q" = 'How old are you?' +then + AGE_UUID=$UUID2 +elif test "$UUID1Q" = 'How old are you?' +then + AGE_UUID=$UUID1 +else + AGE_UUID=$UUID0 +fi + +if test "$UUID2Q" = 'What is your name?' +then + NAME_UUID=$UUID2 +elif test "$UUID1Q" = 'What is your name?' +then + NAME_UUID=$UUID1 +else + NAME_UUID=$UUID0 +fi + +anastasis-reducer -a \ + "$(jq -n ' + { + uuid: $UUID + }' \ + --arg UUID "$NAME_UUID" + )" \ + select_challenge < $R2FILE > $R1FILE + +anastasis-reducer -a '{"answer": "Hans"}' \ + solve_challenge < $R1FILE > $R2FILE + +anastasis-reducer -a \ + "$(jq -n ' + { + uuid: $UUID + }' \ + --arg UUID "$AGE_UUID" + )" \ + select_challenge < $R2FILE > $R1FILE + +anastasis-reducer -a '{"answer": "123"}' \ + solve_challenge < $R1FILE > $R2FILE + +echo " OK" + +echo -n "Checking recovered secret ..." +# finally: check here that we recovered the secret... + +STATE=`jq -r -e .recovery_state < $R2FILE` +if test "$STATE" != "RECOVERY_FINISHED" +then + jq -e . $R2FILE + exit_fail "Expected new state to be 'RECOVERY_FINISHED', got '$STATE'" +fi + +SECRET=`jq -r -e .core_secret.value < $R2FILE` +if test "$SECRET" != "VERYHARDT0GVESSSECRET" +then + jq -e . $R2FILE + exit_fail "Expected recovered secret to be 'VERYHARDT0GVESSSECRET', got '$SECRET'" +fi + +MIME=`jq -r -e .core_secret.mime < $R2FILE` +if test "$MIME" != "text/plain" +then + jq -e . $R2FILE + exit_fail "Expected recovered mime to be 'text/plain', got '$MIME'" +fi + +echo " OK" + +exit 0 diff --git a/src/cli/test_anastasis_reducer_select_continent.sh b/src/cli/test_anastasis_reducer_select_continent.sh new file mode 100755 index 0000000..4cd8a84 --- /dev/null +++ b/src/cli/test_anastasis_reducer_select_continent.sh @@ -0,0 +1,116 @@ +#!/bin/bash + +set -eu + +# Exit, with status code "skip" (no 'real' failure) +function exit_skip() { + echo " SKIP: $1" + exit 77 +} + +# Exit, with error message (hard failure) +function exit_fail() { + echo " FAIL: $1" + exit 1 +} + +# Cleanup to run whenever we exit +function cleanup() +{ + for n in `jobs -p` + do + kill $n 2> /dev/null || true + done + rm -f $SFILE $TFILE + wait +} + +# Install cleanup handler (except for kill -9) +SFILE=`mktemp test_reducer_stateXXXXXX` +TFILE=`mktemp test_reducer_stateXXXXXX` + +trap cleanup EXIT + +# Check we can actually run +echo -n "Testing for jq ..." +jq -h > /dev/null || exit_skip "jq required" +echo " FOUND" +echo -n "Testing for anastasis-reducer ..." +anastasis-reducer -h > /dev/null || exit_skip "anastasis-reducer required" +echo " FOUND" + +# Test continent selection in a backup state +echo -n "Test continent selection in a backup state ..." +anastasis-reducer -a '{"continent": "Testcontinent"}' select_continent resources/00-backup.json $TFILE + +STATE=`jq -r -e .backup_state < $TFILE` +if test "$STATE" != "COUNTRY_SELECTING" +then + exit_fail "Expected new state to be COUNTRY_SELECTING, got $STATE" +fi +SELECTED_CONTINENT=`jq -r -e .selected_continent < $TFILE` +if test "$SELECTED_CONTINENT" != "Testcontinent" +then + exit_fail "Expected selected continent to be Testcontinent, got $SELECTED_CONTINENT" +fi +COUNTRIES=`jq -r -e .countries < $TFILE` +if test "$COUNTRIES" == NULL +then + exit_fail "Expected country array (countries) not to be NULL" +fi +echo " OK" + + +echo -n "Test invalid continent selection ..." +anastasis-reducer -a '{"continent": "Pangaia"}' select_continent resources/00-recovery.json $TFILE 2> /dev/null \ + && exit_fail "Expected selection to fail. Check '$TFILE'" + +echo " OK" + +echo -n "Test continent selection in a recovery state ..." +anastasis-reducer -a '{"continent": "Testcontinent"}' select_continent resources/00-recovery.json $TFILE + +STATE=`jq -r -e .recovery_state < $TFILE` +if test "$STATE" != "COUNTRY_SELECTING" +then + exit_fail "Expected new state to be COUNTRY_SELECTING, got $STATE" +fi +jq -e .countries[0] < $TFILE > /dev/null || exit_fail "Expected new state to include countries" +jq -e .countries[0].code < $TFILE > /dev/null || exit_fail "Expected new state to include countries with code" +jq -e .countries[0].continent < $TFILE > /dev/null || exit_fail "Expected new state to include countries with continent" +jq -e .countries[0].name < $TFILE > /dev/null || exit_fail "Expected new state to include countries with name" +jq -e .countries[0].currency < $TFILE > /dev/null || exit_fail "Expected new state to include countries with currency" + +SELECTED_CONTINENT=`jq -r -e .selected_continent < $TFILE` +if test "$SELECTED_CONTINENT" != "Testcontinent" +then + exit_fail "Expected selected continent to be 'Testcontinent', got $SELECTED_CONTINENT" +fi + +COUNTRIES=`jq -r -e .countries < $TFILE` +if test "$COUNTRIES" == NULL +then + exit_fail "Expected country array (countries) not to be NULL" +fi +jq -e .countries[0] < $TFILE > /dev/null || exit_fail "Expected new state to include countries" +jq -e .countries[0].code < $TFILE > /dev/null || exit_fail "Expected new state to include countries with code" +jq -e .countries[0].continent < $TFILE > /dev/null || exit_fail "Expected new state to include countries with continent" +jq -e .countries[0].name < $TFILE > /dev/null || exit_fail "Expected new state to include countries with name" +jq -e .countries[0].currency < $TFILE > /dev/null || exit_fail "Expected new state to include countries with currency" + +echo " OK" + + +# Test missing arguments in a recovery state +echo -n "Test bogus country selection in a recovery state ..." +anastasis-reducer -a '{"country": "Germany"}' select_continent resources/00-recovery.json $TFILE 2> /dev/null && exit_fail "Expected state transition to fail, but it worked, check $TFILE" + +echo " OK" + +# Test continent selection in a recovery state +echo -n "Test bogus continent selection in a recovery state ..." +anastasis-reducer -a '{"continent": "Germany"}' select_continent resources/00-recovery.json $TFILE 2> /dev/null && exit_fail "Expected state transition to fail, but it worked, check $TFILE" + +echo " OK" + +exit 0 diff --git a/src/cli/test_anastasis_reducer_select_country.sh b/src/cli/test_anastasis_reducer_select_country.sh new file mode 100755 index 0000000..db17052 --- /dev/null +++ b/src/cli/test_anastasis_reducer_select_country.sh @@ -0,0 +1,144 @@ +#!/bin/bash + +set -eu + +# Exit, with status code "skip" (no 'real' failure) +function exit_skip() { + echo " SKIP: $1" + exit 77 +} + +# Exit, with error message (hard failure) +function exit_fail() { + echo " FAIL: $1" + exit 1 +} + +# Cleanup to run whenever we exit +function cleanup() +{ + for n in `jobs -p` + do + kill $n 2> /dev/null || true + done + rm -f $TFILE + wait +} + + + +TFILE=`mktemp test_reducer_stateXXXXXX` + +# Install cleanup handler (except for kill -9) +trap cleanup EXIT + +# Check we can actually run +echo -n "Testing for jq" +jq -h > /dev/null || exit_skip "jq required" +echo " FOUND" + +echo -n "Testing for anastasis-reducer ..." +anastasis-reducer -h > /dev/null || exit_skip "anastasis-reducer required" +echo " FOUND" + + + +# Test continent re-selection +echo -n "Test continent re-selection ..." +anastasis-reducer -a '{"continent": "Europe"}' select_continent resources/01-recovery.json $TFILE + +echo -n "." + + +STATE=`jq -r -e .recovery_state < $TFILE` +if test "$STATE" != "COUNTRY_SELECTING" +then + exit_fail "Expected new state to be COUNTRY_SELECTING, got $STATE" +fi + +echo -n "." + +jq -e .countries[0] < $TFILE > /dev/null || exit_fail "Expected new state to include countries" +jq -e .countries[0].code < $TFILE > /dev/null || exit_fail "Expected new state to include countries with code" +jq -e .countries[0].continent < $TFILE > /dev/null || exit_fail "Expected new state to include countries with continent" +jq -e .countries[0].name < $TFILE > /dev/null || exit_fail "Expected new state to include countries with name" +jq -e .countries[0].currency < $TFILE > /dev/null || exit_fail "Expected new state to include countries with currency" + +SELECTED_CONTINENT=`jq -r -e .selected_continent < $TFILE` +if test "$SELECTED_CONTINENT" != "Europe" +then + exit_fail "Expected selected continent to be 'Testcontinent', got $SELECTED_CONTINENT" +fi + +echo " OK" + + +echo -n "Test invalid continent re-selection ..." +anastasis-reducer -a '{"continent": "Pangaia"}' select_continent resources/00-recovery.json $TFILE 2> /dev/null \ + && exit_fail "Expected selection to fail. Check '$TFILE'" + +echo " OK" + + +echo -n "Test NX country selection ..." + +anastasis-reducer -a \ + '{"country_code": "zz", + "currencies": ["EUR" ]}' \ + select_country \ + resources/01-backup.json $TFILE 2> /dev/null \ + && exit_fail "Expected selection to fail. Check '$TFILE'" + +echo " OK" + +echo -n "Test invalid country selection for continent ..." + +anastasis-reducer -a \ + '{"country_code": "de", + "currencies":["EUR"]}' \ + select_country \ + resources/01-backup.json $TFILE 2> /dev/null \ + && exit_fail "Expected selection to fail. Check '$TFILE'" + +echo " OK" + +echo -n "Test country selection ..." + +anastasis-reducer -a \ + '{"country_code": "xx", + "currencies":["TESTKUDOS"]}' \ + select_country resources/01-backup.json $TFILE + +STATE=`jq -r -e .backup_state < $TFILE` +if test "$STATE" != "USER_ATTRIBUTES_COLLECTING" +then + exit_fail "Expected new state to be 'USER_ATTRIBUTES_COLLECTING', got '$STATE'" +fi +echo -n "." +SELECTED_COUNTRY=`jq -r -e .selected_country < $TFILE` +if test "$SELECTED_COUNTRY" != "xx" +then + exit_fail "Expected selected country to be 'xx', got '$SELECTED_COUNTRY'" +fi +echo -n "." +SELECTED_CURRENCY=`jq -r -e .currencies[0] < $TFILE` +if test "$SELECTED_CURRENCY" != "TESTKUDOS" +then + exit_fail "Expected selected currency to be 'TESTKUDOS', got '$SELECTED_CURRENCY'" +fi +echo -n "." +REQ_ATTRIBUTES=`jq -r -e .required_attributes < $TFILE` +if test "$REQ_ATTRIBUTES" == NULL +then + exit_fail "Expected required attributes array not to be NULL" +fi +echo -n "." +AUTH_PROVIDERS=`jq -r -e .authentication_providers < $TFILE` +if test "$AUTH_PROVIDERS" == NULL +then + exit_fail "Expected authentication_providers array not to be NULL" +fi + +echo " OK" + +exit 0 diff --git a/src/cli/test_reducer.conf b/src/cli/test_reducer.conf new file mode 100644 index 0000000..a4baaed --- /dev/null +++ b/src/cli/test_reducer.conf @@ -0,0 +1,197 @@ +[PATHS] +TALER_HOME = ${PWD}/test_reducer_home/ +TALER_DATA_HOME = $TALER_HOME/.local/share/taler/ +TALER_CONFIG_HOME = $TALER_HOME/.config/taler/ +TALER_CACHE_HOME = $TALER_HOME/.cache/taler/ +TALER_RUNTIME_DIR = ${TMPDIR:-${TMP:-/tmp}}/${USER:-}/taler-system-runtime/ + +[taler] +CURRENCY = TESTKUDOS +CURRENCY_ROUND_UNIT = TESTKUDOS:0.01 + +[anastasis] +DB = postgres +PAYMENT_BACKEND_URL = http://localhost:9966/ +ANNUAL_FEE = TESTKUDOS:4.99 +TRUTH_UPLOAD_FEE = TESTKUDOS:0.01 +UPLOAD_LIMIT_MB = 1 +ANNUAL_POLICY_UPLOAD_LIMIT = 128 +INSURANCE = TESTKUDOS:1.0 + +[authorization-question] +COST = TESTKUDOS:0.0 + + +[exchange] +MAX_KEYS_CACHING = forever +DB = postgres +MASTER_PRIV_FILE = ${TALER_DATA_HOME}/exchange/offline-keys/master.priv +SERVE = tcp +UNIXPATH = ${TALER_RUNTIME_DIR}/exchange.http +UNIXPATH_MODE = 660 +PORT = 8081 +BASE_URL = http://localhost:8081/ +SIGNKEY_DURATION = 2 weeks +SIGNKEY_LEGAL_DURATION = 2 years +LEGAL_DURATION = 2 years +LOOKAHEAD_SIGN = 3 weeks 1 day +LOOKAHEAD_PROVIDE = 2 weeks 1 day +KEYDIR = ${TALER_DATA_HOME}/exchange/live-keys/ +REVOCATION_DIR = ${TALER_DATA_HOME}/exchange/revocations/ +TERMS_ETAG = 0 +PRIVACY_ETAG = 0 + +[merchant] +SERVE = tcp +PORT = 9966 +UNIXPATH = ${TALER_RUNTIME_DIR}/merchant.http +UNIXPATH_MODE = 660 +DEFAULT_WIRE_FEE_AMORTIZATION = 1 +DB = postgres +WIREFORMAT = default +# Set very low, so we can be sure that the database generated +# will contain wire transfers "ready" for the aggregator. +WIRE_TRANSFER_DELAY = 1 minute +DEFAULT_PAY_DEADLINE = 1 day +DEFAULT_MAX_DEPOSIT_FEE = TESTKUDOS:0.1 +KEYFILE = ${TALER_DATA_HOME}/merchant/merchant.priv +DEFAULT_MAX_WIRE_FEE = TESTKUDOS:0.10 + +# Ensure that merchant reports EVERY deposit confirmation to auditor +FORCE_AUDIT = YES + +[auditor] +DB = postgres +AUDITOR_PRIV_FILE = ${TALER_DATA_HOME}/auditor/offline-keys/auditor.priv +SERVE = tcp +UNIXPATH = ${TALER_RUNTIME_DIR}/exchange.http +UNIXPATH_MODE = 660 +PORT = 8083 +AUDITOR_URL = http://localhost:8083/ +TINY_AMOUNT = TESTKUDOS:0.01 +AUDITOR_PRIV_FILE = ${TALER_DATA_HOME}/auditor/offline-keys/auditor.priv +BASE_URL = "http://localhost:8083/" + +[bank] +DATABASE = postgres:///taler-auditor-basedb +MAX_DEBT = TESTKUDOS:50.0 +MAX_DEBT_BANK = TESTKUDOS:100000.0 +HTTP_PORT = 8082 +SUGGESTED_EXCHANGE = http://localhost:8081/ +SUGGESTED_EXCHANGE_PAYTO = payto://x-taler-bank/localhost/2 +ALLOW_REGISTRATIONS = YES +SERVE = http + +[exchangedb] +IDLE_RESERVE_EXPIRATION_TIME = 4 weeks +LEGAL_RESERVE_EXPIRATION_TIME = 7 years + +[exchange-account-1] +PAYTO_URI = payto://x-taler-bank/localhost/Exchange +enable_debit = yes +enable_credit = yes +WIRE_GATEWAY_URL = "http://localhost:8082/taler-wire-gateway/Exchange/" +WIRE_GATEWAY_AUTH_METHOD = basic +USERNAME = Exchange +PASSWORD = x + +[merchant-exchange-default] +EXCHANGE_BASE_URL = http://localhost:8081/ +CURRENCY = TESTKUDOS + +[payments-generator] +currency = TESTKUDOS +instance = default +bank = http://localhost:8082/ +merchant = http://localhost:9966/ +exchange_admin = http://localhost:18080/ +exchange-admin = http://localhost:18080/ +exchange = http://localhost:8081/ + +[coin_kudos_ct_1] +value = TESTKUDOS:0.01 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = TESTKUDOS:0.01 +fee_deposit = TESTKUDOS:0.01 +fee_refresh = TESTKUDOS:0.01 +fee_refund = TESTKUDOS:0.01 +rsa_keysize = 1024 + +[coin_kudos_ct_10] +value = TESTKUDOS:0.10 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = TESTKUDOS:0.01 +fee_deposit = TESTKUDOS:0.01 +fee_refresh = TESTKUDOS:0.03 +fee_refund = TESTKUDOS:0.01 +rsa_keysize = 1024 + +[coin_kudos_1] +value = TESTKUDOS:1 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = TESTKUDOS:0.02 +fee_deposit = TESTKUDOS:0.02 +fee_refresh = TESTKUDOS:0.03 +fee_refund = TESTKUDOS:0.01 +rsa_keysize = 1024 + +[coin_kudos_2] +value = TESTKUDOS:2 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = TESTKUDOS:0.03 +fee_deposit = TESTKUDOS:0.03 +fee_refresh = TESTKUDOS:0.04 +fee_refund = TESTKUDOS:0.02 +rsa_keysize = 1024 + +[coin_kudos_4] +value = TESTKUDOS:4 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = TESTKUDOS:0.03 +fee_deposit = TESTKUDOS:0.03 +fee_refresh = TESTKUDOS:0.04 +fee_refund = TESTKUDOS:0.02 +rsa_keysize = 1024 + +[coin_kudos_5] +value = TESTKUDOS:5 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = TESTKUDOS:0.01 +fee_deposit = TESTKUDOS:0.01 +fee_refresh = TESTKUDOS:0.03 +fee_refund = TESTKUDOS:0.01 +rsa_keysize = 1024 + +[coin_kudos_8] +value = TESTKUDOS:8 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = TESTKUDOS:0.05 +fee_deposit = TESTKUDOS:0.02 +fee_refresh = TESTKUDOS:0.03 +fee_refund = TESTKUDOS:0.04 +rsa_keysize = 1024 + +[coin_kudos_10] +value = TESTKUDOS:10 +duration_withdraw = 7 days +duration_spend = 2 years +duration_legal = 3 years +fee_withdraw = TESTKUDOS:0.01 +fee_deposit = TESTKUDOS:0.01 +fee_refresh = TESTKUDOS:0.03 +fee_refund = TESTKUDOS:0.01 +rsa_keysize = 1024 diff --git a/src/cli/user-details-example.json b/src/cli/user-details-example.json new file mode 100644 index 0000000..3eb1f7a --- /dev/null +++ b/src/cli/user-details-example.json @@ -0,0 +1,6 @@ +{ + "first-name":"John", + "last-name":"Wayne", + "birthdate":"01-01-1901", + "social-security-number":"123456789" +} \ No newline at end of file -- cgit v1.2.3