/*
This file is part of TALER
(C) 2016-2023 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 Foundation; either version 3,
or (at your option) any later version.
TALER 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 TALER; see the file COPYING. If not,
see
*/
/**
* @file bank-lib/fakebank_tbi_post_withdrawal_operation.c
* @brief library that fakes being a Taler bank for testcases
* @author Christian Grothoff
*/
#include "platform.h"
#include
#include "taler_fakebank_lib.h"
#include "taler_bank_service.h"
#include "taler_mhd_lib.h"
#include
#include "fakebank.h"
#include "fakebank_common_lookup.h"
#include "fakebank_tbi_post_withdrawal_operation.h"
/**
* Execute POST /withdrawal-operation/ request.
*
* @param h our handle
* @param connection the connection
* @param wopid the withdrawal operation identifier
* @param reserve_pub public key of the reserve
* @param exchange_payto_uri payto://-URI of the exchange
* @return MHD result code
*/
static MHD_RESULT
do_post_withdrawal (
struct TALER_FAKEBANK_Handle *h,
struct MHD_Connection *connection,
const char *wopid,
const struct TALER_ReservePublicKeyP *reserve_pub,
const char *exchange_payto_uri)
{
struct WithdrawalOperation *wo;
char *credit_name;
struct Account *credit_account;
const char *status_string;
GNUNET_assert (0 ==
pthread_mutex_lock (&h->big_lock));
wo = TALER_FAKEBANK_lookup_withdrawal_operation_ (h,
wopid);
if (NULL == wo)
{
GNUNET_assert (0 ==
pthread_mutex_unlock (&h->big_lock));
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_NOT_FOUND,
TALER_EC_BANK_TRANSACTION_NOT_FOUND,
wopid);
}
if ( (wo->selection_done) &&
(0 != GNUNET_memcmp (&wo->reserve_pub,
reserve_pub)) )
{
GNUNET_assert (0 ==
pthread_mutex_unlock (&h->big_lock));
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_CONFLICT,
TALER_EC_BANK_WITHDRAWAL_OPERATION_RESERVE_SELECTION_CONFLICT,
"reserve public key changed");
}
{
/* check if reserve_pub is already in use */
const struct GNUNET_PeerIdentity *pid;
pid = (const struct GNUNET_PeerIdentity *) &wo->reserve_pub;
if (GNUNET_CONTAINER_multipeermap_contains (h->rpubs,
pid))
{
GNUNET_assert (0 ==
pthread_mutex_unlock (&h->big_lock));
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_CONFLICT,
TALER_EC_BANK_DUPLICATE_RESERVE_PUB_SUBJECT,
NULL);
}
}
credit_name = TALER_xtalerbank_account_from_payto (exchange_payto_uri);
if (NULL == credit_name)
{
GNUNET_break_op (0);
GNUNET_assert (0 ==
pthread_mutex_unlock (&h->big_lock));
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PAYTO_URI_MALFORMED,
NULL);
}
credit_account = TALER_FAKEBANK_lookup_account_ (h,
credit_name,
NULL);
if (NULL == credit_account)
{
MHD_RESULT res;
GNUNET_break_op (0);
GNUNET_assert (0 ==
pthread_mutex_unlock (&h->big_lock));
res = TALER_MHD_reply_with_error (connection,
MHD_HTTP_NOT_FOUND,
TALER_EC_BANK_UNKNOWN_ACCOUNT,
credit_name);
GNUNET_free (credit_name);
return res;
}
GNUNET_free (credit_name);
if ( (NULL != wo->exchange_account) &&
(credit_account != wo->exchange_account) )
{
GNUNET_assert (0 ==
pthread_mutex_unlock (&h->big_lock));
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_CONFLICT,
TALER_EC_BANK_WITHDRAWAL_OPERATION_RESERVE_SELECTION_CONFLICT,
"exchange account changed");
}
wo->exchange_account = credit_account;
wo->reserve_pub = *reserve_pub;
wo->selection_done = true;
GNUNET_assert (0 ==
pthread_mutex_unlock (&h->big_lock));
if (wo->aborted)
status_string = "aborted";
else if (wo->confirmation_done)
status_string = "confirmed";
else
status_string = "selected";
return TALER_MHD_REPLY_JSON_PACK (
connection,
MHD_HTTP_OK,
// FIXME: Deprecated field, should be deleted in the future.
GNUNET_JSON_pack_bool ("transfer_done",
wo->confirmation_done),
GNUNET_JSON_pack_string ("status",
status_string));
}
MHD_RESULT
TALER_FAKEBANK_tbi_post_withdrawal (
struct TALER_FAKEBANK_Handle *h,
struct MHD_Connection *connection,
const char *wopid,
const void *upload_data,
size_t *upload_data_size,
void **con_cls)
{
struct ConnectionContext *cc = *con_cls;
enum GNUNET_JSON_PostResult pr;
json_t *json;
MHD_RESULT res;
if (NULL == cc)
{
cc = GNUNET_new (struct ConnectionContext);
cc->ctx_cleaner = &GNUNET_JSON_post_parser_cleanup;
*con_cls = cc;
}
pr = GNUNET_JSON_post_parser (REQUEST_BUFFER_MAX,
connection,
&cc->ctx,
upload_data,
upload_data_size,
&json);
switch (pr)
{
case GNUNET_JSON_PR_OUT_OF_MEMORY:
GNUNET_break (0);
return MHD_NO;
case GNUNET_JSON_PR_CONTINUE:
return MHD_YES;
case GNUNET_JSON_PR_REQUEST_TOO_LARGE:
GNUNET_break (0);
return MHD_NO;
case GNUNET_JSON_PR_JSON_INVALID:
GNUNET_break (0);
return MHD_NO;
case GNUNET_JSON_PR_SUCCESS:
break;
}
{
struct TALER_ReservePublicKeyP reserve_pub;
const char *exchange_payto_url;
enum GNUNET_GenericReturnValue ret;
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("reserve_pub",
&reserve_pub),
GNUNET_JSON_spec_string ("selected_exchange",
&exchange_payto_url),
GNUNET_JSON_spec_end ()
};
if (GNUNET_OK !=
(ret = TALER_MHD_parse_json_data (connection,
json,
spec)))
{
GNUNET_break_op (0);
json_decref (json);
return (GNUNET_NO == ret) ? MHD_YES : MHD_NO;
}
res = do_post_withdrawal (h,
connection,
wopid,
&reserve_pub,
exchange_payto_url);
}
json_decref (json);
return res;
}