refinements of policy extension APIs
This commit is contained in:
parent
086c4a243f
commit
b447506342
@ -114,6 +114,11 @@ struct DepositContext
|
||||
*/
|
||||
const struct TALER_EXCHANGEDB_Deposit *deposit;
|
||||
|
||||
/**
|
||||
* Extension handler for policy, maybe NULL.
|
||||
*/
|
||||
const struct TALER_Extension *policy_extension;
|
||||
|
||||
/**
|
||||
* Our timestamp (when we received the request).
|
||||
* Possibly updated by the transaction if the
|
||||
@ -156,6 +161,7 @@ deposit_transaction (void *cls,
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
bool balance_ok;
|
||||
bool in_conflict;
|
||||
bool blocked_by_policy = false;
|
||||
|
||||
qs = TEH_make_coin_known (&dc->deposit->coin,
|
||||
connection,
|
||||
@ -163,11 +169,30 @@ deposit_transaction (void *cls,
|
||||
mhd_ret);
|
||||
if (qs < 0)
|
||||
return qs;
|
||||
|
||||
/* Check and apply policies, if applicable */
|
||||
if (NULL != dc->policy_extension)
|
||||
{
|
||||
const struct TALER_Extension *ext = dc->policy_extension;
|
||||
struct TALER_ExtensionsPolicySerialID serialID;
|
||||
struct GNUNET_TIME_Timestamp deadline;
|
||||
GNUNET_assert (ext->parse_policy_details);
|
||||
|
||||
qs = ext->parse_policy_details (dc->deposit->policy_details,
|
||||
&serialID,
|
||||
&deadline);
|
||||
|
||||
if (qs < 0)
|
||||
return qs;
|
||||
|
||||
blocked_by_policy = true;
|
||||
}
|
||||
|
||||
qs = TEH_plugin->do_deposit (TEH_plugin->cls,
|
||||
dc->deposit,
|
||||
dc->known_coin_id,
|
||||
&dc->h_payto,
|
||||
false, /* FIXME-OEC: extension blocked #7270 */
|
||||
blocked_by_policy,
|
||||
&dc->exchange_timestamp,
|
||||
&balance_ok,
|
||||
&in_conflict);
|
||||
@ -208,86 +233,6 @@ deposit_transaction (void *cls,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief check the provided policy
|
||||
*
|
||||
* @param[in] policy_details JSON object provided by the client with prolicy
|
||||
* @param[out] hc On success, will contain the hash of the normalized policy_details object
|
||||
* @param[out] handler_out On success, the handler might provide an output
|
||||
* @param[out] error_hint On failure, might contain a hint of the error from the extension
|
||||
* @return GNUNET_OK on success.
|
||||
*/
|
||||
enum GNUNET_GenericReturnValue
|
||||
check_policy_details (
|
||||
json_t *policy_details,
|
||||
struct TALER_ExtensionPolicyHashP *hc,
|
||||
json_t **handler_out,
|
||||
char **error_hint)
|
||||
{
|
||||
const char *type = NULL;
|
||||
const struct TALER_Extension *extension;
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
|
||||
*error_hint = NULL;
|
||||
|
||||
if ((NULL == policy_details) ||
|
||||
(! json_is_object (policy_details)))
|
||||
{
|
||||
*error_hint = "invalid policy object";
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
// parse and evaluate the object
|
||||
{
|
||||
json_t *jtype = json_object_get (
|
||||
policy_details,
|
||||
"type");
|
||||
if (NULL == jtype)
|
||||
{
|
||||
*error_hint = "no type in policy object";
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
type = json_string_value (jtype);
|
||||
if (NULL == type)
|
||||
{
|
||||
*error_hint = "invalid type in policy object";
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
extension = TALER_extensions_get_by_name (type);
|
||||
if ((NULL == extension) ||
|
||||
(NULL == extension->deposit_handler))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
*error_hint = "no such policy";
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
ret = extension->deposit_handler (policy_details,
|
||||
handler_out);
|
||||
if (GNUNET_OK != ret)
|
||||
{
|
||||
GNUNET_break (0);
|
||||
if (NULL != *handler_out)
|
||||
{
|
||||
*error_hint = json_dumps (*handler_out, JSON_INDENT (2));
|
||||
}
|
||||
else
|
||||
{
|
||||
GNUNET_break (1);
|
||||
*error_hint = "unknown error with the policy";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
TALER_deposit_policy_hash (policy_details,
|
||||
hc);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
MHD_RESULT
|
||||
TEH_handler_deposit (struct MHD_Connection *connection,
|
||||
const struct TALER_CoinSpendPublicKeyP *coin_pub,
|
||||
@ -296,9 +241,7 @@ TEH_handler_deposit (struct MHD_Connection *connection,
|
||||
struct DepositContext dc;
|
||||
struct TALER_EXCHANGEDB_Deposit deposit;
|
||||
const char *payto_uri;
|
||||
struct TALER_ExtensionPolicyHashP h_policy;
|
||||
struct TALER_ExtensionPolicyHashP *ph_policy = NULL;
|
||||
bool no_policy;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
GNUNET_JSON_spec_string ("merchant_payto_uri",
|
||||
&payto_uri),
|
||||
@ -311,8 +254,6 @@ TEH_handler_deposit (struct MHD_Connection *connection,
|
||||
&deposit.coin.denom_pub_hash),
|
||||
TALER_JSON_spec_denom_sig ("ub_sig",
|
||||
&deposit.coin.denom_sig),
|
||||
GNUNET_JSON_spec_fixed_auto ("merchant_pub",
|
||||
&deposit.merchant_pub),
|
||||
GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
|
||||
&deposit.h_contract_terms),
|
||||
GNUNET_JSON_spec_mark_optional (
|
||||
@ -324,17 +265,20 @@ TEH_handler_deposit (struct MHD_Connection *connection,
|
||||
GNUNET_JSON_spec_timestamp ("timestamp",
|
||||
&deposit.timestamp),
|
||||
|
||||
/* TODO: this will move to an extension for refunds */
|
||||
/* TODO: refund_deadline and merchant_pub will move into the
|
||||
* extension policy_merchant_refunds */
|
||||
GNUNET_JSON_spec_mark_optional (
|
||||
GNUNET_JSON_spec_timestamp ("refund_deadline",
|
||||
&deposit.refund_deadline),
|
||||
NULL),
|
||||
GNUNET_JSON_spec_fixed_auto ("merchant_pub",
|
||||
&deposit.merchant_pub),
|
||||
GNUNET_JSON_spec_timestamp ("wire_transfer_deadline",
|
||||
&deposit.wire_deadline),
|
||||
GNUNET_JSON_spec_mark_optional (
|
||||
GNUNET_JSON_spec_json ("policy",
|
||||
&deposit.policy_details),
|
||||
&no_policy),
|
||||
GNUNET_JSON_spec_timestamp ("wire_transfer_deadline",
|
||||
&deposit.wire_deadline),
|
||||
&deposit.no_policy_details),
|
||||
GNUNET_JSON_spec_end ()
|
||||
};
|
||||
struct TALER_MerchantWireHashP h_wire;
|
||||
@ -472,29 +416,11 @@ TEH_handler_deposit (struct MHD_Connection *connection,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/* TODO: check policy_details */
|
||||
if (! no_policy)
|
||||
if (! deposit.no_policy_details)
|
||||
{
|
||||
char *hint;
|
||||
json_t *out;
|
||||
MHD_RESULT res;
|
||||
|
||||
if (GNUNET_OK !=
|
||||
check_policy_details (dc.deposit->policy_details,
|
||||
&h_policy,
|
||||
&out,
|
||||
&hint))
|
||||
{
|
||||
res = TALER_MHD_reply_with_error (connection,
|
||||
MHD_HTTP_BAD_REQUEST,
|
||||
/* TODO: new error type needed */
|
||||
TALER_EC_EXCHANGE_GENERIC_OPERATION_UNKNOWN,
|
||||
hint);
|
||||
GNUNET_free (hint);
|
||||
return res;
|
||||
}
|
||||
|
||||
ph_policy = &h_policy;
|
||||
TALER_deposit_policy_hash (deposit.policy_details,
|
||||
&deposit.h_policy);
|
||||
ph_policy = &deposit.h_policy;
|
||||
}
|
||||
|
||||
deposit.deposit_fee = dk->meta.fees.deposit;
|
||||
|
@ -151,7 +151,9 @@ struct TALER_Extension TE_age_restriction = {
|
||||
.disable = &age_restriction_disable,
|
||||
.load_config = &age_restriction_load_config,
|
||||
.manifest = &age_restriction_manifest,
|
||||
.deposit_handler = NULL,
|
||||
|
||||
/* This extension is not a policy extension */
|
||||
.parse_policy_details = NULL,
|
||||
.http_get_handler = NULL,
|
||||
.http_post_handler = NULL,
|
||||
};
|
||||
|
@ -353,4 +353,53 @@ TALER_extensions_load_manifests (
|
||||
}
|
||||
|
||||
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_extensions_from_policy_details (
|
||||
const json_t *policy_details,
|
||||
const struct TALER_Extension **extension,
|
||||
char **error_hint)
|
||||
{
|
||||
const json_t *jtype;
|
||||
const char *type;
|
||||
|
||||
*extension = NULL;
|
||||
*error_hint = NULL;
|
||||
|
||||
if ((NULL == policy_details) ||
|
||||
(! json_is_object (policy_details)))
|
||||
{
|
||||
*error_hint = "invalid policy object";
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
jtype = json_object_get (policy_details, "type");
|
||||
if (NULL == jtype)
|
||||
{
|
||||
*error_hint = "no type in policy object";
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
type = json_string_value (jtype);
|
||||
if (NULL == type)
|
||||
{
|
||||
*error_hint = "invalid type in policy object";
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
|
||||
*extension = TALER_extensions_get_by_name (type);
|
||||
if ((NULL == *extension) ||
|
||||
(NULL == (*extension)->parse_policy_details))
|
||||
{
|
||||
GNUNET_break (0);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
"Unsupported extension policy '%s' requested\n",
|
||||
type);
|
||||
*extension = NULL;
|
||||
return GNUNET_NO;
|
||||
}
|
||||
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/* end of extensions.c */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
This file is part of TALER
|
||||
Copyright (C) 2021-2022 Taler Systems SA
|
||||
Copyright (C) 2022 Taler Systems SA
|
||||
|
||||
TALER 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
|
||||
@ -32,7 +32,7 @@
|
||||
|
||||
/* (public) configuration of this extension */
|
||||
/* TODO: these fields need to be set in the init handler */
|
||||
static struct TALER_BrandtVickreyAuction BV_config = {
|
||||
static struct TALER_ExtensionPolicyBrandtVickreyAuctionConfig BV_config = {
|
||||
.max_bidders = 10,
|
||||
.max_prices = 10,
|
||||
.auction_fee = {
|
||||
@ -497,7 +497,7 @@ static json_t *
|
||||
auction_manifest (
|
||||
const struct TALER_Extension *ext)
|
||||
{
|
||||
struct TALER_BrandtVickreyAuction *conf = ext->config;
|
||||
struct TALER_ExtensionPolicyBrandtVickreyAuctionConfig *conf = ext->config;
|
||||
GNUNET_assert (conf);
|
||||
|
||||
json_t *config = GNUNET_JSON_PACK (
|
||||
@ -589,20 +589,66 @@ auction_http_post_handler (
|
||||
|
||||
|
||||
/**
|
||||
* @brief implements the TALER_Extensions.deposit_handler interface.
|
||||
* @brief implements the TALER_Extensions.parse_policy_details interface.
|
||||
*
|
||||
* @param[in] input JSON input from the client during a deposit request
|
||||
* @param[out] output by this extension
|
||||
* @param[in] input The policy_details for this handler during deposit
|
||||
* @param[out] serial On success will contain the serial-ID under which the
|
||||
* @param[out] deadline On success will contain a deadline, might be "forever"
|
||||
* exchange should store the policy_details in the policy_details table.
|
||||
* @return GNUNET_OK if the request was OK
|
||||
*/
|
||||
enum GNUNET_GenericReturnValue
|
||||
auction_deposit_handler (
|
||||
json_t *input,
|
||||
json_t **output)
|
||||
auction_parse_policy_details (
|
||||
const json_t *input,
|
||||
struct TALER_ExtensionsPolicySerialID *serial,
|
||||
struct GNUNET_TIME_Timestamp *deadline)
|
||||
{
|
||||
/* TODO */
|
||||
*output = NULL;
|
||||
return GNUNET_OK;
|
||||
enum GNUNET_GenericReturnValue ret = GNUNET_NO;
|
||||
struct GNUNET_CRYPTO_EddsaPublicKey pub;
|
||||
struct GNUNET_HashCode hc;
|
||||
struct GNUNET_JSON_Specification spec[] = {
|
||||
/* We ignore the "type" field as it must have been parsed already upstream
|
||||
* - or this handler wouldn't have been called in first place. */
|
||||
GNUNET_JSON_spec_fixed_auto ("bidder_pub", &pub),
|
||||
GNUNET_JSON_spec_fixed_auto ("h_auction", &hc),
|
||||
GNUNET_JSON_spec_timestamp ("deadline", deadline),
|
||||
GNUNET_JSON_spec_end (),
|
||||
};
|
||||
|
||||
GNUNET_assert (serial);
|
||||
GNUNET_assert (deadline);
|
||||
|
||||
do {
|
||||
ret = GNUNET_JSON_parse (input,
|
||||
spec,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (GNUNET_OK != ret)
|
||||
break;
|
||||
|
||||
/* FIXME: check the deadline */
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
|
||||
LOG_PREFIX "check of deadline %ld not implemented!\n",
|
||||
deadline->abs_time.abs_value_us);
|
||||
|
||||
/* Create serial as H(bidder_pub, h_auction) */
|
||||
{
|
||||
struct GNUNET_HashContext *hc = GNUNET_CRYPTO_hash_context_start ();
|
||||
GNUNET_CRYPTO_hash_context_read (hc,
|
||||
&pub,
|
||||
sizeof(pub));
|
||||
GNUNET_CRYPTO_hash_context_read (hc,
|
||||
&hc,
|
||||
sizeof(hc));
|
||||
GNUNET_CRYPTO_hash_context_finish (hc,
|
||||
&serial->hash);
|
||||
}
|
||||
|
||||
ret = GNUNET_OK;
|
||||
} while(0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -617,7 +663,7 @@ struct TALER_Extension TE_auction_brandt = {
|
||||
.disable = &auction_disable,
|
||||
.load_config = &auction_load_config,
|
||||
.manifest = &auction_manifest,
|
||||
.deposit_handler = &auction_deposit_handler,
|
||||
.parse_policy_details = &auction_parse_policy_details,
|
||||
.http_get_handler = &auction_http_get_handler,
|
||||
.http_post_handler = &auction_http_post_handler,
|
||||
};
|
||||
|
@ -25,17 +25,21 @@
|
||||
#include "taler_crypto_lib.h"
|
||||
#include "taler_json_lib.h"
|
||||
#include "taler_mhd_lib.h"
|
||||
#include "taler_exchangedb_plugin.h"
|
||||
|
||||
|
||||
#define TALER_EXTENSION_SECTION_PREFIX "exchange-extension-"
|
||||
|
||||
enum TALER_Extension_Type
|
||||
{
|
||||
TALER_Extension_AgeRestriction = 0,
|
||||
TALER_Extension_PolicyMerchantRefund = 1,
|
||||
TALER_Extension_PolicyBrandtVickeryAuction = 2,
|
||||
TALER_Extension_PolicyEscrowedPayment = 3,
|
||||
TALER_Extension_MaxPredefined = 4 // Must be last of the predefined
|
||||
TALER_Extension_PolicyNull = 0,
|
||||
|
||||
TALER_Extension_AgeRestriction = 1,
|
||||
TALER_Extension_PolicyMerchantRefund = 2,
|
||||
TALER_Extension_PolicyBrandtVickeryAuction = 3,
|
||||
TALER_Extension_PolicyEscrowedPayment = 4,
|
||||
|
||||
TALER_Extension_MaxPredefined = 5 // Must be last of the predefined
|
||||
};
|
||||
|
||||
|
||||
@ -49,6 +53,15 @@ struct TALER_Extensions
|
||||
const struct TALER_Extension *extension;
|
||||
};
|
||||
|
||||
/*
|
||||
* @brief Serial ID under which the policy details to an deposit are stored in
|
||||
* the policy_details table.
|
||||
*/
|
||||
struct TALER_ExtensionsPolicySerialID
|
||||
{
|
||||
struct GNUNET_HashCode hash;
|
||||
};
|
||||
|
||||
/*
|
||||
* @brief Represents the implementation of an extension.
|
||||
*
|
||||
@ -151,22 +164,30 @@ struct TALER_Extension
|
||||
json_t *(*manifest)(
|
||||
const struct TALER_Extension *ext);
|
||||
|
||||
/* =========================
|
||||
* Policy related handlers
|
||||
* =========================
|
||||
*/
|
||||
/**
|
||||
* @brief Handler for /{batch}-deposit requests. Can be NULL.
|
||||
* @brief Handler to check a policy. Can be NULL;
|
||||
*
|
||||
* When a deposit request refers to this extension in its policy
|
||||
* (see https://docs.taler.net/core/api-exchange.html#deposit), this handler
|
||||
* will be called during the deposit operation.
|
||||
* will be called before the deposit transaction.
|
||||
*
|
||||
* @param[in] input The policy/extension specific data, provided by the client in
|
||||
* the policy-field of the deposit request.
|
||||
* @param[out] output Potential output by the extension to be provided to the
|
||||
* client as part of the response to the deposit request. Can be NULL.
|
||||
* @param[in] policy_details Details about the policy, provided by the client
|
||||
* during a deposit request.
|
||||
* @param[out] serial On success, will contain the serial-ID under which the
|
||||
* exchange should save the policy_details in the deposit table.
|
||||
* @param[out] deadline On sucess, set to the deadline until the policy must
|
||||
* be fulfilled. Might be "forever". This value is used by an external
|
||||
* mechanism to detect timeouts.
|
||||
* @return GNUNET_OK if the data was accepted by the extension.
|
||||
*/
|
||||
enum GNUNET_GenericReturnValue (*deposit_handler)(
|
||||
json_t *input,
|
||||
json_t **output);
|
||||
enum GNUNET_GenericReturnValue (*parse_policy_details)(
|
||||
const json_t *policy_details,
|
||||
struct TALER_ExtensionsPolicySerialID *serial,
|
||||
struct GNUNET_TIME_Timestamp *deadline);
|
||||
|
||||
/**
|
||||
* @brief Handler for POST-requests to the /policy/$name endpoint. Can be NULL.
|
||||
@ -366,19 +387,65 @@ struct TALER_AgeMask
|
||||
TALER_extensions_get_age_restriction_mask ();
|
||||
|
||||
|
||||
/*
|
||||
* ===================================
|
||||
* Policy extensions related functions
|
||||
* ===================================
|
||||
*/
|
||||
|
||||
/*
|
||||
* @brief Finds the extension for a given policy
|
||||
*
|
||||
* @param[in] policy_details JSON of the policy detail from a deposit request
|
||||
* @param[out] extension On GNUNET_OK, the exentions handling the given policy
|
||||
* @param[out] error_hint On GNUNET_SYSERR, will contain a hint for the reason why it failed
|
||||
* @return GNUNET_OK on success, with *extension set to the correct extension.
|
||||
* GNUNET_NO, when no extension was found. GNUNET_SYSERR when the JSON was
|
||||
* invalid, with *error_hint maybe non-NULL.
|
||||
*/
|
||||
enum GNUNET_GenericReturnValue
|
||||
TALER_extensions_from_policy_details (
|
||||
const json_t *policy_details,
|
||||
const struct TALER_Extension **extension,
|
||||
char **error_hint);
|
||||
|
||||
/*
|
||||
* ================================
|
||||
* Brandt-Vickrey Auctions
|
||||
* Merchant refund policy
|
||||
* ================================
|
||||
*/
|
||||
struct TALER_ExtensionPolicyMerchantRefundPolicyConfig
|
||||
{
|
||||
struct GNUNET_TIME_Relative max_timeout;
|
||||
};
|
||||
|
||||
/*
|
||||
* ================================
|
||||
* Brandt-Vickrey Auctions policy
|
||||
* ================================
|
||||
*/
|
||||
/*
|
||||
* @brief Configuration for Brandt-Vickrey auctions
|
||||
* @brief Configuration for Brandt-Vickrey auctions policy
|
||||
*/
|
||||
struct TALER_BrandtVickreyAuction
|
||||
struct TALER_ExtensionPolicyBrandtVickreyAuctionConfig
|
||||
{
|
||||
uint16_t max_bidders;
|
||||
uint16_t max_prices;
|
||||
struct TALER_Amount auction_fee;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* ================================
|
||||
* Escrowed Payments policy
|
||||
* ================================
|
||||
*/
|
||||
/*
|
||||
* @brief Configuration for escrowed payments policy
|
||||
*/
|
||||
struct TALER_ExtensionPolicyEscrowedPaymentsConfig
|
||||
{
|
||||
struct GNUNET_TIME_Relative max_timeout;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user