set_extensions and postgres-handler implemented

This commit is contained in:
Özgür Kesim 2021-12-28 13:11:58 +01:00
parent ef4238874f
commit d0d7d78336
Signed by: oec
GPG Key ID: 3D76A56D79EDD9D7
3 changed files with 210 additions and 78 deletions

View File

@ -42,7 +42,7 @@ struct Extension
// configuration for the age restriction
struct TALER_AgeMask mask;
/* TODO oec - peer2peer config */
/* TODO oec - add peer2peer config */
};
};
@ -77,9 +77,46 @@ set_extensions (void *cls,
struct MHD_Connection *connection,
MHD_RESULT *mhd_ret)
{
// struct SetExtensionContext *sec = cls;
struct SetExtensionsContext *sec = cls;
/* save the configurations of all extensions */
for (uint32_t i = 0; i<sec->num_extensions; i++)
{
struct Extension *ext = &sec->extensions[i];
struct TALER_MasterSignatureP *sig = &sec->extensions_sigs[i];
enum GNUNET_DB_QueryStatus qs;
char *config;
config = json_dumps (ext->config_json, JSON_COMPACT | JSON_SORT_KEYS);
if (NULL == config)
{
GNUNET_break (0);
*mhd_ret = TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_GENERIC_JSON_INVALID,
"convert configuration to string");
return GNUNET_DB_STATUS_SOFT_ERROR; /* FIXME: right error? */
}
qs = TEH_plugin->set_extension_config (
TEH_plugin->cls,
TEH_extensions[ext->type].name,
config,
sig);
if (qs < 0)
{
if (GNUNET_DB_STATUS_SOFT_ERROR == qs)
return qs;
GNUNET_break (0);
*mhd_ret = TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_GENERIC_DB_STORE_FAILED,
"save extension configuration");
}
}
// TODO oec
return GNUNET_DB_STATUS_SUCCESS_ONE_RESULT; /* only 'success', so >=0, matters here */
}
@ -99,7 +136,6 @@ TEH_handler_management_post_extensions (
&extensions_sigs),
GNUNET_JSON_spec_end ()
};
bool ok;
MHD_RESULT ret;
{
@ -123,7 +159,7 @@ TEH_handler_management_post_extensions (
connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED,
"array expected for extensions and extensions_sig");
"array expected for extensions and extensions_sigs");
}
sec.num_extensions = json_array_size (extensions_sigs);
@ -135,7 +171,7 @@ TEH_handler_management_post_extensions (
connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED,
"arrays extensions and extensions_sig are not of equal size");
"arrays extensions and extensions_sigs are not of equal size");
}
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@ -145,11 +181,9 @@ TEH_handler_management_post_extensions (
struct Extension);
sec.extensions_sigs = GNUNET_new_array (sec.num_extensions,
struct TALER_MasterSignatureP);
ok = true;
for (unsigned int i = 0; i<sec.num_extensions; i++)
{
// 1. parse the extension
{
enum GNUNET_GenericReturnValue res;
@ -170,17 +204,15 @@ TEH_handler_management_post_extensions (
if (GNUNET_SYSERR == res)
{
ret = MHD_NO; /* hard failure */
ok = false;
break;
goto CLEANUP;
}
if (GNUNET_NO == res)
{
ret = MHD_YES;
ok = false;
break;
goto CLEANUP;;
}
// Make sure name refers to a supported extension
/* Make sure name refers to a supported extension */
{
bool found = false;
for (unsigned int k = 0; k < TALER_Extension_Max; k++)
@ -197,25 +229,22 @@ TEH_handler_management_post_extensions (
if (! found)
{
GNUNET_free (sec.extensions);
GNUNET_free (sec.extensions_sigs);
GNUNET_JSON_parse_free (spec);
GNUNET_JSON_parse_free (ispec);
return TALER_MHD_reply_with_error (
ret = TALER_MHD_reply_with_error (
connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED,
"invalid extension type");
goto CLEANUP;
}
}
// We have a JSON object for the extension. Increment its refcount and
// free the parser.
// TODO: is this correct?
/* We have a JSON object for the extension.
* Increment its refcount and free the parser.
* TODO: is this correct? */
json_incref (sec.extensions[i].config_json);
GNUNET_JSON_parse_free (ispec);
// Make sure the config is sound
/* Make sure the config is sound */
{
switch (sec.extensions[i].type)
{
@ -224,34 +253,33 @@ TEH_handler_management_post_extensions (
sec.extensions[i].config_json,
&sec.extensions[i].mask))
{
GNUNET_free (sec.extensions);
GNUNET_free (sec.extensions_sigs);
GNUNET_JSON_parse_free (spec);
return TALER_MHD_reply_with_error (
ret = TALER_MHD_reply_with_error (
connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED,
"invalid mask for age restriction");
goto CLEANUP;
}
break;
case TALER_Extension_Peer2Peer: /* TODO */
ok = false;
case TALER_Extension_Peer2Peer:
/* TODO */
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"peer2peer not yet supported in handler for /management/extensions\n");
ret = MHD_NO;
goto BREAK;
goto CLEANUP;
default:
/* not reachable */
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"shouldn't be reached in handler for /management/extensions\n");
ok = false;
ret = MHD_NO;
goto BREAK;
goto CLEANUP;
}
}
}
// 2. parse the signature
// 2. parse and verify the signature
{
enum GNUNET_GenericReturnValue res;
struct GNUNET_JSON_Specification ispec[] = {
@ -268,20 +296,16 @@ TEH_handler_management_post_extensions (
if (GNUNET_SYSERR == res)
{
ret = MHD_NO; /* hard failure */
ok = false;
break;
goto CLEANUP;
}
if (GNUNET_NO == res)
{
ret = MHD_YES;
ok = false;
break;
goto CLEANUP;
}
}
// 3. verify the signature
{
enum GNUNET_GenericReturnValue res;
/* verify the signature */
res = GNUNET_SYSERR;
switch (sec.extensions[i].type)
{
@ -290,53 +314,40 @@ TEH_handler_management_post_extensions (
sec.extensions[i].mask,
&TEH_master_public_key,
&sec.extensions_sigs[i]);
if (GNUNET_OK != res)
{
GNUNET_free (sec.extensions);
GNUNET_free (sec.extensions_sigs);
GNUNET_JSON_parse_free (spec);
return TALER_MHD_reply_with_error (
connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED,
"invalid signature for age mask");
}
break;
case TALER_Extension_Peer2Peer: /* TODO */
case TALER_Extension_Peer2Peer:
/* TODO */
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Peer2peer not yet supported in handler for /management/extensions\n");
ok = false;
ret = MHD_NO;
goto BREAK;
goto CLEANUP;
default:
/* not reachable */
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"shouldn't be reached in handler for /management/extensions\n");
ok = false;
ret = MHD_NO;
/* not reachable */
goto BREAK;
goto CLEANUP;
}
if (GNUNET_OK != res)
{
ret = TALER_MHD_reply_with_error (
connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED,
"invalid signature for extension");
goto CLEANUP;
}
}
}
BREAK:
if (! ok)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"Failure to handle /management/extensions\n");
GNUNET_free (sec.extensions);
GNUNET_free (sec.extensions_sigs);
GNUNET_JSON_parse_free (spec);
return ret;
}
} /* for-loop */
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Received %u extensions\n",
sec.num_extensions);
// now run the transaction to persist the configurations
{
enum GNUNET_GenericReturnValue res;
@ -347,19 +358,29 @@ BREAK:
&set_extensions,
&sec);
GNUNET_free (sec.extensions);
GNUNET_free (sec.extensions_sigs);
GNUNET_JSON_parse_free (spec);
if (GNUNET_SYSERR == res)
return ret;
goto CLEANUP;
}
return TALER_MHD_reply_static (
ret = TALER_MHD_reply_static (
connection,
MHD_HTTP_NO_CONTENT,
NULL,
NULL,
0);
CLEANUP:
for (unsigned int i = 0; i < sec.num_extensions; i++)
{
if (NULL != sec.extensions[i].config_json)
{
json_decref (sec.extensions[i].config_json);
}
}
GNUNET_free (sec.extensions);
GNUNET_free (sec.extensions_sigs);
GNUNET_JSON_parse_free (spec);
return ret;
}

View File

@ -2743,6 +2743,23 @@ prepare_statements (struct PostgresClosure *pg)
" AND start_row=$2"
" AND end_row=$3",
3),
/* Used in #postgres_set_extension_config */
GNUNET_PQ_make_prepare (
"set_extension_config",
"WITH upsert AS "
" (UPDATE extensions "
" SET config=$2 "
" config_sig=$3 "
" WHERE name=$1 RETURNING *) "
"INSERT INTO extensions (config, config_sig) VALUES ($2, $3) "
"WHERE NOT EXISTS (SELECT * FROM upsert);",
3),
/* Used in #postgres_get_extension_config */
GNUNET_PQ_make_prepare (
"get_extension_config",
"SELECT (config) FROM extensions"
" WHERE name=$1;",
1),
GNUNET_PQ_PREPARED_STATEMENT_END
};
@ -3513,7 +3530,7 @@ postgres_iterate_active_signkeys (void *cls,
void *cb_cls)
{
struct PostgresClosure *pg = cls;
struct GNUNET_TIME_Absolute now;
struct GNUNET_TIME_Absolute now = {0};
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_absolute_time (&now),
GNUNET_PQ_query_param_end
@ -4470,6 +4487,8 @@ compute_shard (const struct TALER_MerchantPublicKeyP *merchant_pub)
* Perform deposit operation, checking for sufficient balance
* of the coin and possibly persisting the deposit details.
*
* FIXME: parameters missing in description!
*
* @param cls the `struct PostgresClosure` with the plugin-specific state
* @param deposit deposit operation details
* @param known_coin_id row of the coin in the known_coins table
@ -5361,7 +5380,7 @@ postgres_get_ready_deposit (void *cls,
void *deposit_cb_cls)
{
struct PostgresClosure *pg = cls;
struct GNUNET_TIME_Absolute now;
struct GNUNET_TIME_Absolute now = {0};
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_absolute_time (&now),
GNUNET_PQ_query_param_uint64 (&start_shard_row),
@ -11394,6 +11413,67 @@ postgres_delete_shard_locks (void *cls)
}
/**
* Function called to save the configuration of an extension
* (age-restriction, peer2peer, ...)
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param extension_name the name of the extension
* @param config JSON object of the configuration as string
* @param config_sig signature of the configuration by the offline master key
* @return transaction status code
*/
enum GNUNET_DB_QueryStatus
postgres_set_extension_config (void *cls,
const char *extension_name,
const char *config,
const struct TALER_MasterSignatureP *config_sig)
{
struct PostgresClosure *pg = cls;
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_string (extension_name),
GNUNET_PQ_query_param_string (config),
GNUNET_PQ_query_param_auto_from_type (config_sig),
GNUNET_PQ_query_param_end
};
return GNUNET_PQ_eval_prepared_non_select (pg->conn,
"set_extension_config",
params);
}
/**
* Function called to get the configuration of an extension
* (age-restriction, peer2peer, ...)
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param extension_name the name of the extension
* @param[out] config JSON object of the configuration as string
* @return transaction status code
*/
enum GNUNET_DB_QueryStatus
postgres_get_extension_config (void *cls,
const char *extension_name,
char **config)
{
struct PostgresClosure *pg = cls;
struct GNUNET_PQ_QueryParam params[] = {
GNUNET_PQ_query_param_string (extension_name),
GNUNET_PQ_query_param_end
};
struct GNUNET_PQ_ResultSpec rs[] = {
GNUNET_PQ_result_spec_string ("config", config),
GNUNET_PQ_result_spec_end
};
return GNUNET_PQ_eval_prepared_singleton_select (pg->conn,
"get_extension_config",
params,
rs);
}
/**
* Initialize Postgres database subsystem.
*
@ -11628,6 +11708,10 @@ libtaler_plugin_exchangedb_postgres_init (void *cls)
= &postgres_release_revolving_shard;
plugin->delete_shard_locks
= &postgres_delete_shard_locks;
plugin->set_extension_config
= &postgres_set_extension_config;
plugin->get_extension_config
= &postgres_get_extension_config;
return plugin;
}

View File

@ -4025,8 +4025,35 @@ struct TALER_EXCHANGEDB_Plugin
(*delete_shard_locks)(void *cls);
/**
* TODO-oec: add function for adding extension config
* Function called to save the configuration of an extension
* (age-restriction, peer2peer, ...)
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param extension_name the name of the extension
* @param config JSON object of the configuration as string
* @param config_sig signature of the configuration by the offline master key
* @return transaction status code
*/
enum GNUNET_DB_QueryStatus
(*set_extension_config)(void *cls,
const char *extension_name,
const char *config,
const struct TALER_MasterSignatureP *config_sig);
/**
* Function called to retrieve the configuration of an extension
* (age-restriction, peer2peer, ...)
*
* @param cls the @e cls of this struct with the plugin-specific state
* @param extension_name the name of the extension
* @param[out] config JSON object of the configuration as string
* @param[out] config_sig signature of the configuration by the master key
* @return transaction status code
*/
enum GNUNET_DB_QueryStatus
(*get_extension_config)(void *cls,
const char *extension_name,
char **config);
};