challenger

OAuth 2.0-based authentication service that validates user can receive messages at a certain address
Log | Files | Refs | Submodules | README | LICENSE

commit 8af7933c17dba30eb0a73166b24d7a77f6a8b8d4
parent be425bb2e36eeba2595313443ae24aaa955a10d4
Author: Christian Grothoff <christian@grothoff.org>
Date:   Mon, 17 Apr 2023 14:59:30 +0200

add challenger-admin tool

Diffstat:
MINSTALL | 6+++---
Acontrib/uncrustify.cfg | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/challenger/.gitignore | 1+
Msrc/challenger/Makefile.am | 10++++++++++
Asrc/challenger/challenger-admin.c | 177+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/challengerdb/Makefile.am | 2++
Asrc/challengerdb/pg_client_add.c | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/challengerdb/pg_client_add.h | 45+++++++++++++++++++++++++++++++++++++++++++++
Asrc/challengerdb/pg_client_delete.c | 46++++++++++++++++++++++++++++++++++++++++++++++
Asrc/challengerdb/pg_client_delete.h | 39+++++++++++++++++++++++++++++++++++++++
Asrc/challengerdb/pg_helper.h | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/challengerdb/pg_template.c | 26++++++++++++++++++++++++++
Asrc/challengerdb/pg_template.h | 29+++++++++++++++++++++++++++++
Asrc/challengerdb/pg_template.sh | 21+++++++++++++++++++++
Msrc/challengerdb/plugin_challengerdb_postgres.c | 167+++++++++++++++++++++++++------------------------------------------------------
Msrc/include/challenger_database_plugin.h | 57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/util/.gitignore | 1+
17 files changed, 764 insertions(+), 117 deletions(-)

diff --git a/INSTALL b/INSTALL @@ -1,8 +1,8 @@ Installation Instructions ************************* - Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software -Foundation, Inc. + Copyright (C) 1994-1996, 1999-2002, 2004-2017, 2020-2021 Free +Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright @@ -225,7 +225,7 @@ order to use an ANSI C compiler: and if that doesn't work, install pre-built binaries of GCC for HP-UX. - HP-UX 'make' updates targets which have the same time stamps as their + HP-UX 'make' updates targets which have the same timestamps as their prerequisites, which makes it generally unusable when shipped generated files such as 'configure' are involved. Use GNU 'make' instead. diff --git a/contrib/uncrustify.cfg b/contrib/uncrustify.cfg @@ -0,0 +1,97 @@ +input_tab_size = 2 +output_tab_size = 2 + +indent_columns = 2 +indent_with_tabs = 0 +indent_case_brace = 2 +indent_label=-16 + +code_width=80 +#cmd_width=80 + +# Leave most comments alone for now +cmt_indent_multi=false +sp_cmt_cpp_start=add + +sp_not=add + +sp_func_call_user_paren_paren=remove +sp_inside_fparen=remove +sp_after_cast=add + +ls_for_split_full=true +ls_func_split_full=true +ls_code_width=true + +# Arithmetic operations in wrapped expressions should be at the start +# of the line. +pos_arith=lead + +# Fully parenthesize boolean exprs +mod_full_paren_if_bool=true + +# Braces should be on their own line +nl_fdef_brace=add +nl_enum_brace=add +nl_struct_brace=add +nl_union_brace=add +nl_if_brace=add +nl_brace_else=add +nl_elseif_brace=add +nl_while_brace=add +nl_switch_brace=add + +# no newline between "else" and "if" +nl_else_if=remove + +nl_func_paren=remove +nl_assign_brace=remove + +# No extra newlines that cause noisy diffs +nl_start_of_file=remove +nl_before_func_body_proto = 0 +nl_before_func_body_def = 0 +nl_after_func_proto = 2 +nl_after_func_body = 3 +# If there's no new line, it's not a text file! +nl_end_of_file=add +nl_max_blank_in_func = 3 +nl_max = 3 + +sp_inside_paren = remove + +sp_arith = add +sp_arith_additive = add + +# We want spaces before and after "=" +sp_before_assign = add +sp_after_assign = add + +# we want "char *foo;" +sp_after_ptr_star = remove +sp_between_ptr_star = remove + +# we want "if (foo) { ... }" +sp_before_sparen = add + +sp_inside_fparen = remove +sp_inside_sparen = remove + +# add space before function call and decl: "foo (x)" +sp_func_call_paren = add +sp_func_proto_paren = add +sp_func_proto_paren_empty = add +sp_func_def_paren = add +sp_func_def_paren_empty = add + +# We'd want it for "if ( (foo) || (bar) )", but not for "if (m())", +# so as uncrustify doesn't give exactly what we want => ignore +sp_paren_paren = ignore +sp_inside_paren = remove +sp_bool = force + +nl_func_type_name = force +#nl_branch_else = add +nl_else_brace = add +nl_elseif_brace = add +nl_for_brace = add diff --git a/src/challenger/.gitignore b/src/challenger/.gitignore @@ -0,0 +1 @@ +challenger-admin diff --git a/src/challenger/Makefile.am b/src/challenger/Makefile.am @@ -12,8 +12,18 @@ pkgcfg_DATA = \ challenger.conf bin_PROGRAMS = \ + challenger-admin \ challenger-httpd +challenger_admin_SOURCES = \ + challenger-admin.c +challenger_admin_LDADD = \ + $(top_builddir)/src/challengerdb/libchallengerdb.la \ + $(top_builddir)/src/util/libchallengerutil.la \ + -ltalerutil \ + -lgnunetutil \ + $(XLIB) + challenger_httpd_SOURCES = \ challenger-httpd.c challenger-httpd.h \ challenger-httpd_config.c challenger-httpd_config.h \ diff --git a/src/challenger/challenger-admin.c b/src/challenger/challenger-admin.c @@ -0,0 +1,177 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger 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 + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +*/ +/** + * @file util/challenger-admin.c + * @brief Administer clients of a challenger service + * @author Christian Grothoff + */ +#include "platform.h" +#include <gnunet/gnunet_util_lib.h> +#include <gnunet/gnunet_db_lib.h> +#include "challenger_util.h" +#include "challenger_database_lib.h" + + +/** + * Return value from main(). + */ +static int global_ret; + +/** + * -a option: client secret + */ +static char *client_secret; + +/** + * -d option: delete client + */ +static int del_flag; + + +/** + * Main function that will be run. + * + * @param cls closure + * @param args remaining command-line arguments + * @param cfgfile name of the configuration file used (for saving, can be NULL!) + * @param cfg configuration + */ +static void +run (void *cls, + char *const *args, + const char *cfgfile, + const struct GNUNET_CONFIGURATION_Handle *cfg) +{ + const char *url = args[0]; + struct CHALLENGER_DatabasePlugin *plugin; + + if (NULL == url) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "challenger-admin must be invoked with the client URL as first argument\n"); + return; + } + if (NULL == + (plugin = CHALLENGER_DB_plugin_load (cfg))) + { + fprintf (stderr, + "Failed to initialize database plugin.\n"); + global_ret = EXIT_NOTINSTALLED; + return; + } + if (del_flag) + { + enum GNUNET_DB_QueryStatus qs; + + qs = plugin->client_delete (plugin->cls, + url); + switch (qs) + { + case GNUNET_DB_STATUS_SOFT_ERROR: + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + global_ret = EXIT_FAILURE; + goto cleanup; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Client with this URL is not known.\n"); + global_ret = EXIT_FAILURE; + goto cleanup; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "Client deleted\n"); + break; + } + } + if (NULL != client_secret) + { + enum GNUNET_DB_QueryStatus qs; + uint64_t row_id; + + qs = plugin->client_add (plugin->cls, + url, + client_secret, + &row_id); + switch (qs) + { + case GNUNET_DB_STATUS_SOFT_ERROR: + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + global_ret = EXIT_FAILURE; + goto cleanup; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Client with this URL already exists.\n"); + global_ret = EXIT_FAILURE; + goto cleanup; + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE, + "Client added. Client ID is: %llu\n", + (unsigned long long) row_id); + break; + } + } +cleanup: + CHALLENGER_DB_plugin_unload (plugin); +} + + +/** + * The main function of the client management tool. Used to add or + * remove clients from the Challenger' database. + * + * @param argc number of arguments from the command line + * @param argv command line arguments + * @return 0 ok, non-zero on error + */ +int +main (int argc, + char *const *argv) +{ + struct GNUNET_GETOPT_CommandLineOption options[] = { + GNUNET_GETOPT_option_string ('a', + "add", + "CLIENT_SECRET", + "add client", + &client_secret), + GNUNET_GETOPT_option_flag ('d', + "delete", + "delete client", + &del_flag), + /* TODO: add -l / --list option */ + 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 CHALLENGER defaults to be used! */ + (void) TALER_project_data_default (); + GNUNET_OS_init (CHALLENGER_project_data_default ()); + ret = GNUNET_PROGRAM_run (argc, argv, + "challenger-admin CLIENT_URL CLIENT_SECRET", + "Tool to add or remove clients from challenger", + options, + &run, NULL); + if (GNUNET_SYSERR == ret) + return EXIT_INVALIDARGUMENT; + if (GNUNET_NO == ret) + return EXIT_SUCCESS; + return global_ret; +} + + +/* end of challenger-dbinit.c */ diff --git a/src/challengerdb/Makefile.am b/src/challengerdb/Makefile.am @@ -57,6 +57,8 @@ libchallengerdb_la_LDFLAGS = \ -no-undefined libchallenger_plugin_db_postgres_la_SOURCES = \ + pg_client_add.h pg_client_add.c \ + pg_client_delete.h pg_client_delete.c \ plugin_challengerdb_postgres.c libchallenger_plugin_db_postgres_la_LIBADD = \ $(LTLIBINTL) diff --git a/src/challengerdb/pg_client_add.c b/src/challengerdb/pg_client_add.c @@ -0,0 +1,58 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger 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 + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file challengerdb/pg_client_add.c + * @brief Implementation of the client_add function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "pg_client_add.h" +#include "pg_helper.h" + +enum GNUNET_DB_QueryStatus +CH_PG_client_add (void *cls, + const char *client_url, + const char *client_secret, + uint64_t *client_id) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (client_url), + GNUNET_PQ_query_param_string (client_secret), + GNUNET_PQ_query_param_end + }; + struct GNUNET_PQ_ResultSpec rs[] = { + GNUNET_PQ_result_spec_uint64 ("client_serial_id", + client_id), + GNUNET_PQ_result_spec_end + }; + + PREPARE (pg, + "client_add", + "INSERT INTO clients" + " (url" + " ,client_secret" + ") " + "ON CONFLICT DO NOTHING" /* CONFLICT on (url) */ + "RETURNING client_serial_id"); + return GNUNET_PQ_eval_prepared_singleton_select (pg->conn, + "client_add", + params, + rs); +} diff --git a/src/challengerdb/pg_client_add.h b/src/challengerdb/pg_client_add.h @@ -0,0 +1,45 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger 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 + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file backenddb/pg_client_add.h + * @brief implementation of the client_add function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_CLIENT_ADD_H +#define PG_CLIENT_ADD_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include <challenger/challenger_database_plugin.h> + + +/** + * Add client to the list of authorized clients. + * + * @param cls + * @param client_url URL of the client + * @param client_secret authorization secret for the client + * @param[out] client_id set to the client ID on success + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +CH_PG_client_add (void *cls, + const char *client_url, + const char *client_secret, + uint64_t *client_id); + + +#endif diff --git a/src/challengerdb/pg_client_delete.c b/src/challengerdb/pg_client_delete.c @@ -0,0 +1,46 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger 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 + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file challengerdb/pg_client_delete.c + * @brief Implementation of the client_delete function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "pg_client_delete.h" +#include "pg_helper.h" + + +enum GNUNET_DB_QueryStatus +CH_PG_client_delete (void *cls, + const char *client_url) +{ + struct PostgresClosure *pg = cls; + struct GNUNET_PQ_QueryParam params[] = { + GNUNET_PQ_query_param_string (client_url), + GNUNET_PQ_query_param_end + }; + + PREPARE (pg, + "client_delete", + "DELETE FROM clients" + " WHERE url=$1;"); + return GNUNET_PQ_eval_prepared_non_select (pg->conn, + "client_delete", + params); +} diff --git a/src/challengerdb/pg_client_delete.h b/src/challengerdb/pg_client_delete.h @@ -0,0 +1,39 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger 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 + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file backenddb/pg_client_delete.h + * @brief implementation of the client_delete function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_CLIENT_DELETE_H +#define PG_CLIENT_DELETE_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include <challenger/challenger_database_plugin.h> + +/** + * Delete client from the list of authorized clients. + * + * @param cls + * @param client_url URL of the client + * @return transaction status + */ +enum GNUNET_DB_QueryStatus +CH_PG_client_delete (void *cls, + const char *client_url); + +#endif diff --git a/src/challengerdb/pg_helper.h b/src/challengerdb/pg_helper.h @@ -0,0 +1,99 @@ +/* + This file is part of Challenger + (C) 2023 Taler Systems SA + + Challenger 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. + + Challenger is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of ANASTASISABILITY 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 + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> +*/ +/** + * @file challenger/pg_helper.h + * @brief database helper definitions + * @author Christian Grothoff + */ +#ifndef PG_HELPER_H +#define PG_HELPER_H + + +/** + * Type of the "cls" argument given to each of the functions in + * our API. + */ +struct PostgresClosure +{ + + /** + * Postgres connection handle. + */ + struct GNUNET_PQ_Context *conn; + + /** + * Directory with SQL statements to run to create tables. + */ + char *sql_dir; + + /** + * Underlying configuration. + */ + const struct GNUNET_CONFIGURATION_Handle *cfg; + + /** + * Name of the currently active transaction, NULL if none is active. + */ + const char *transaction_name; + + /** + * How often did we (re)establish @a conn so far? + */ + uint64_t prep_gen; + +}; + + +/** + * Check that the database connection is still up. + * + * @param cls a `struct PostgresClosure` with connection to check + */ +void +CH_PG_check_connection (void *cls); + +/** + * Prepares SQL statement @a sql under @a name for + * connection @a pg once. + * Returns with #GNUNET_DB_STATUS_HARD_ERROR on failure. + * + * @param pg a `struct PostgresClosure` + * @param name name to prepare the statement under + * @param sql actual SQL text + */ +#define PREPARE(pg,name,sql) \ + do { \ + static unsigned long long gen; \ + \ + if (gen < pg->prep_gen) \ + { \ + struct GNUNET_PQ_PreparedStatement ps[] = { \ + GNUNET_PQ_make_prepare (name, sql), \ + GNUNET_PQ_PREPARED_STATEMENT_END \ + }; \ + \ + if (GNUNET_OK != \ + GNUNET_PQ_prepare_statements (pg->conn, \ + ps)) \ + { \ + GNUNET_break (0); \ + return GNUNET_DB_STATUS_HARD_ERROR; \ + } \ + gen = pg->prep_gen; \ + } \ + } while (0) + +#endif diff --git a/src/challengerdb/pg_template.c b/src/challengerdb/pg_template.c @@ -0,0 +1,26 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger 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 + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file challengerdb/pg_template.c + * @brief Implementation of the template function for Postgres + * @author Christian Grothoff + */ +#include "platform.h" +#include <taler/taler_error_codes.h> +#include <taler/taler_dbevents.h> +#include <taler/taler_pq_lib.h> +#include "pg_template.h" +#include "pg_helper.h" diff --git a/src/challengerdb/pg_template.h b/src/challengerdb/pg_template.h @@ -0,0 +1,29 @@ +/* + This file is part of Challenger + Copyright (C) 2023 Taler Systems SA + + Challenger is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + Challenger 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 + Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ +/** + * @file backenddb/pg_template.h + * @brief implementation of the template function for Postgres + * @author Christian Grothoff + */ +#ifndef PG_TEMPLATE_H +#define PG_TEMPLATE_H + +#include <taler/taler_util.h> +#include <taler/taler_json_lib.h> +#include <challenger/challenger_database_plugin.h> + + +#endif diff --git a/src/challengerdb/pg_template.sh b/src/challengerdb/pg_template.sh @@ -0,0 +1,21 @@ +#!/bin/sh +# This file is in the public domain. +# +# Instantiates pg_template for a particular function. + +for n in $* +do + NCAPS=`echo $n | tr a-z A-Z` + if test ! -e pg_$n.c + then + cat pg_template.c | sed -e s/template/$n/g -e s/TEMPLATE/$NCAPS/g > pg_$n.c + cat pg_template.h | sed -e s/template/$n/g -e s/TEMPLATE/$NCAPS/g > pg_$n.h + echo " plugin->$n\n = &TMH_PG_$n;" >> tmpl.c + echo "#include \"pg_$n.h\"" >> tmpl.inc + echo " pg_$n.h pg_$n.c \\" >> tmpl.am + fi +done + +echo "Add lines from tmpl.am to Makefile.am" +echo "Add lines from tmpl.inc to plugin_challengerdb_postgres.c at the beginning" +echo "Add lines from tmpl.c to plugin_challengerdb_postgres.c at the end" diff --git a/src/challengerdb/plugin_challengerdb_postgres.c b/src/challengerdb/plugin_challengerdb_postgres.c @@ -14,8 +14,8 @@ Challenger; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ /** - * @file sync/plugin_syncdb_postgres.c - * @brief database helper functions for postgres used by sync + * @file challenger/plugin_challengerdb_postgres.c + * @brief database helper functions for postgres used by challenger * @author Christian Grothoff */ #include "platform.h" @@ -25,42 +25,9 @@ #include <taler/taler_pq_lib.h> #include "challenger_database_plugin.h" #include "challenger_database_lib.h" - -/** - * Type of the "cls" argument given to each of the functions in - * our API. - */ -struct PostgresClosure -{ - - /** - * Postgres connection handle. - */ - struct GNUNET_PQ_Context *conn; - - /** - * Directory with SQL statements to run to create tables. - */ - char *sql_dir; - - /** - * Underlying configuration. - */ - const struct GNUNET_CONFIGURATION_Handle *cfg; - - /** - * Name of the currently active transaction, NULL if none is active. - */ - const char *transaction_name; - - /** - * Did we initialize the prepared statements - * for this session? - */ - bool init; - -}; - +#include "pg_helper.h" +#include "pg_client_add.h" +#include "pg_client_delete.h" /** * Drop challenger tables @@ -79,7 +46,6 @@ postgres_drop_tables (void *cls) { GNUNET_PQ_disconnect (pg->conn); pg->conn = NULL; - pg->init = false; } conn = GNUNET_PQ_connect_with_cfg (pg->cfg, "challengerdb-postgres", @@ -96,38 +62,27 @@ postgres_drop_tables (void *cls) /** - * Establish connection to the database. + * Roll back the current transaction of a database connection. * - * @param cls plugin context - * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure + * @param cls the `struct PostgresClosure` with the plugin-specific state */ -static enum GNUNET_GenericReturnValue -prepare_statements (void *cls) +static void +postgres_rollback (void *cls) { struct PostgresClosure *pg = cls; - struct GNUNET_PQ_PreparedStatement ps[] = { - GNUNET_PQ_make_prepare ("gc_accounts", - "DELETE FROM accounts " - "WHERE" - " expiration_date < $1;"), - GNUNET_PQ_make_prepare ("gc_pending_payments", - "DELETE FROM payments " - "WHERE" - " paid=FALSE" - " AND" - " timestamp < $1;"), - GNUNET_PQ_make_prepare ("do_commit", - "COMMIT"), - GNUNET_PQ_PREPARED_STATEMENT_END + struct GNUNET_PQ_ExecuteStatement es[] = { + GNUNET_PQ_make_execute ("ROLLBACK"), + GNUNET_PQ_EXECUTE_STATEMENT_END }; - enum GNUNET_GenericReturnValue ret; - ret = GNUNET_PQ_prepare_statements (pg->conn, - ps); - if (GNUNET_OK != ret) - return ret; - pg->init = true; - return GNUNET_OK; + if (GNUNET_OK != + GNUNET_PQ_exec_statements (pg->conn, + es)) + { + TALER_LOG_ERROR ("Failed to rollback transaction\n"); + GNUNET_break (0); + } + pg->transaction_name = NULL; } @@ -135,12 +90,10 @@ prepare_statements (void *cls) * Connect to the database if the connection does not exist yet. * * @param pg the plugin-specific state - * @param skip_prepare true if we should skip prepared statement setup * @return #GNUNET_OK on success */ static enum GNUNET_GenericReturnValue -internal_setup (struct PostgresClosure *pg, - bool skip_prepare) +internal_setup (struct PostgresClosure *pg) { if (NULL == pg->conn) { @@ -156,8 +109,6 @@ internal_setup (struct PostgresClosure *pg, force the default to 'serializable' if SSI is to be used. */ GNUNET_PQ_make_try_execute ( "SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;"), - GNUNET_PQ_make_try_execute ("SET enable_sort=OFF;"), - GNUNET_PQ_make_try_execute ("SET enable_seqscan=OFF;"), GNUNET_PQ_make_execute ("SET search_path TO challenger;"), GNUNET_PQ_EXECUTE_STATEMENT_END }; @@ -177,14 +128,11 @@ internal_setup (struct PostgresClosure *pg, if (NULL == db_conn) return GNUNET_SYSERR; pg->conn = db_conn; + pg->prep_gen++; } if (NULL == pg->transaction_name) GNUNET_PQ_reconnect_if_down (pg->conn); - if (pg->init) - return GNUNET_OK; - if (skip_prepare) - return GNUNET_OK; - return prepare_statements (pg); + return GNUNET_OK; } @@ -207,11 +155,10 @@ postgres_preflight (void *cls) GNUNET_PQ_EXECUTE_STATEMENT_END }; - if (! pg->init) + if (NULL == pg->conn) { if (GNUNET_OK != - internal_setup (pg, - false)) + internal_setup (pg)) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to ensure DB is initialized\n"); @@ -244,8 +191,8 @@ postgres_preflight (void *cls) * * @param cls a `struct PostgresClosure` with connection to check */ -static void -check_connection (void *cls) +void +CH_PG_check_connection (void *cls) { struct PostgresClosure *pg = cls; @@ -262,8 +209,8 @@ check_connection (void *cls) * @return #GNUNET_OK on success */ static enum GNUNET_GenericReturnValue -begin_transaction (void *cls, - const char *name) +postgres_begin_transaction (void *cls, + const char *name) { struct PostgresClosure *pg = cls; struct GNUNET_PQ_ExecuteStatement es[] = { @@ -271,7 +218,7 @@ begin_transaction (void *cls, GNUNET_PQ_EXECUTE_STATEMENT_END }; - check_connection (pg); + CH_PG_check_connection (pg); postgres_preflight (pg); pg->transaction_name = name; if (GNUNET_OK != @@ -287,38 +234,13 @@ begin_transaction (void *cls, /** - * Roll back the current transaction of a database connection. - * - * @param cls the `struct PostgresClosure` with the plugin-specific state - */ -static void -rollback (void *cls) -{ - struct PostgresClosure *pg = cls; - struct GNUNET_PQ_ExecuteStatement es[] = { - GNUNET_PQ_make_execute ("ROLLBACK"), - GNUNET_PQ_EXECUTE_STATEMENT_END - }; - - if (GNUNET_OK != - GNUNET_PQ_exec_statements (pg->conn, - es)) - { - TALER_LOG_ERROR ("Failed to rollback transaction\n"); - GNUNET_break (0); - } - pg->transaction_name = NULL; -} - - -/** * Commit the current transaction of a database connection. * * @param cls the `struct PostgresClosure` with the plugin-specific state * @return transaction status code */ static enum GNUNET_DB_QueryStatus -commit_transaction (void *cls) +postgres_commit_transaction (void *cls) { struct PostgresClosure *pg = cls; enum GNUNET_DB_QueryStatus qs; @@ -326,6 +248,9 @@ commit_transaction (void *cls) GNUNET_PQ_query_param_end }; + PREPARE (pg, + "do_commit", + "COMMIT"); qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, "do_commit", no_params); @@ -353,15 +278,23 @@ postgres_gc (void *cls, }; enum GNUNET_DB_QueryStatus qs; - check_connection (pg); + CH_PG_check_connection (pg); + PREPARE (pg, + "gc_validations", + "DELETE FROM validations" + " WHERE expiration_time < $1;"); + PREPARE (pg, + "gc_grants", + "DELETE FROM grants" + " WHERE expiration_time < $1;"); postgres_preflight (pg); qs = GNUNET_PQ_eval_prepared_non_select (pg->conn, - "gc_accounts", + "gc_validations", params); if (qs < 0) return qs; return GNUNET_PQ_eval_prepared_non_select (pg->conn, - "gc_pending_payments", + "gc_grants", params); } @@ -422,8 +355,7 @@ libchallenger_plugin_db_postgres_init (void *cls) return NULL; } if (GNUNET_OK != - internal_setup (pg, - true)) + internal_setup (pg)) { GNUNET_free (pg->sql_dir); GNUNET_free (pg); @@ -435,6 +367,13 @@ libchallenger_plugin_db_postgres_init (void *cls) plugin->drop_tables = &postgres_drop_tables; plugin->preflight = &postgres_preflight; plugin->gc = &postgres_gc; + plugin->begin_transaction = &postgres_begin_transaction; + plugin->commit_transaction = &postgres_commit_transaction; + plugin->rollback = &postgres_rollback; + plugin->client_add + = &CH_PG_client_add; + plugin->client_delete + = &CH_PG_client_delete; return plugin; } diff --git a/src/include/challenger_database_plugin.h b/src/include/challenger_database_plugin.h @@ -85,6 +85,37 @@ struct CHALLENGER_DatabasePlugin /** + * Start a transaction. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @param name unique name identifying the transaction (for debugging), + * must point to a constant + * @return #GNUNET_OK on success + */ + enum GNUNET_GenericReturnValue + (*begin_transaction)(void *cls, + const char *name); + + + /** + * Commit the current transaction of a database connection. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + * @return transaction status code + */ + enum GNUNET_DB_QueryStatus + (*commit_transaction)(void *cls); + + + /** + * Roll back the current transaction of a database connection. + * + * @param cls the `struct PostgresClosure` with the plugin-specific state + */ + void + (*rollback) (void *cls); + + /** * Function called to perform "garbage collection" on the * database, expiring records we no longer require. * @@ -97,5 +128,31 @@ struct CHALLENGER_DatabasePlugin struct GNUNET_TIME_Absolute expire); + /** + * Add client to the list of authorized clients. + * + * @param cls + * @param client_url URL of the client + * @param client_secret authorization secret for the client + * @param[out] client_id set to the client ID on success + * @return transaction status + */ + enum GNUNET_DB_QueryStatus + (*client_add)(void *cls, + const char *client_url, + const char *client_secret, + uint64_t *client_id); + + /** + * Delete client from the list of authorized clients. + * + * @param cls + * @param client_url URL of the client + * @return transaction status + */ + enum GNUNET_DB_QueryStatus + (*client_delete)(void *cls, + const char *client_url); + }; #endif diff --git a/src/util/.gitignore b/src/util/.gitignore @@ -0,0 +1 @@ +challenger-config