diff options
Diffstat (limited to 'src/backend/taler-merchant-httpd_private-post-account.c')
-rw-r--r-- | src/backend/taler-merchant-httpd_private-post-account.c | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/src/backend/taler-merchant-httpd_private-post-account.c b/src/backend/taler-merchant-httpd_private-post-account.c new file mode 100644 index 00000000..dbaac7ba --- /dev/null +++ b/src/backend/taler-merchant-httpd_private-post-account.c @@ -0,0 +1,238 @@ +/* + This file is part of TALER + (C) 2020-2023 Taler Systems SA + + TALER is free software; you can redistribute it and/or modify + it under the terms of the GNU Affero 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 <http://www.gnu.org/licenses/> +*/ + +/** + * @file taler-merchant-httpd_private-post-account.c + * @brief implementing POST /private/accounts request handling + * @author Christian Grothoff + */ +#include "platform.h" +#include "taler-merchant-httpd_private-post-account.h" +#include "taler-merchant-httpd_helper.h" +#include "taler_merchant_bank_lib.h" +#include <taler/taler_dbevents.h> +#include <taler/taler_json_lib.h> + + +MHD_RESULT +TMH_private_post_account (const struct TMH_RequestHandler *rh, + struct MHD_Connection *connection, + struct TMH_HandlerContext *hc) +{ + struct TMH_MerchantInstance *mi = hc->instance; + const char *credit_facade_url = NULL; + const json_t *credit_facade_credentials = NULL; + const char *uri; + struct GNUNET_JSON_Specification ispec[] = { + TALER_JSON_spec_payto_uri ("payto_uri", + &uri), + GNUNET_JSON_spec_mark_optional ( + TALER_JSON_spec_web_url ("credit_facade_url", + &credit_facade_url), + NULL), + GNUNET_JSON_spec_mark_optional ( + GNUNET_JSON_spec_object_const ("credit_facade_credentials", + &credit_facade_credentials), + NULL), + GNUNET_JSON_spec_end () + }; + struct TMH_WireMethod *wm; + + { + enum GNUNET_GenericReturnValue res; + + res = TALER_MHD_parse_json_data (connection, + hc->request_body, + ispec); + if (GNUNET_OK != res) + return (GNUNET_NO == res) + ? MHD_YES + : MHD_NO; + } + + { + char *err; + + if (NULL != + (err = TALER_payto_validate (uri))) + { + MHD_RESULT mret; + + GNUNET_break_op (0); + mret = TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PAYTO_URI_MALFORMED, + err); + GNUNET_free (err); + return mret; + } + } + + if ( (NULL == credit_facade_url) != + (NULL == credit_facade_credentials) ) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MISSING, + (NULL == credit_facade_url) + ? "credit_facade_url" + : "credit_facade_credentials"); + } + if ( (NULL != credit_facade_url) || + (NULL != credit_facade_credentials) ) + { + struct TALER_MERCHANT_BANK_AuthenticationData auth; + + if (GNUNET_OK != + TALER_MERCHANT_BANK_auth_parse_json (credit_facade_credentials, + credit_facade_url, + &auth)) + { + GNUNET_break_op (0); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_BAD_REQUEST, + TALER_EC_GENERIC_PARAMETER_MALFORMED, + "credit_facade_url or credit_facade_credentials"); + } + TALER_MERCHANT_BANK_auth_free (&auth); + } + + /* convert provided payto URI into internal data structure with salts */ + wm = TMH_setup_wire_account (uri, + credit_facade_url, + credit_facade_credentials); + GNUNET_assert (NULL != wm); + { + struct TALER_MERCHANTDB_AccountDetails ad = { + .payto_uri = wm->payto_uri, + .salt = wm->wire_salt, + .h_wire = wm->h_wire, + .credit_facade_url = wm->credit_facade_url, + .credit_facade_credentials = wm->credit_facade_credentials, + .active = wm->active + }; + enum GNUNET_DB_QueryStatus qs; + + qs = TMH_db->insert_account (TMH_db->cls, + mi->settings.id, + &ad); + switch (qs) + { + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + break; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + /* conflict: account exists */ + { + struct TALER_MERCHANTDB_AccountDetails adx; + + qs = TMH_db->select_account_by_uri (TMH_db->cls, + mi->settings.id, + ad.payto_uri, + &adx); + switch (qs) + { + case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: + if ( (0 == strcmp (adx.payto_uri, + ad.payto_uri) ) && + ( (adx.credit_facade_credentials == + ad.credit_facade_credentials) || + ( (NULL != adx.credit_facade_credentials) && + (NULL != ad.credit_facade_credentials) && + (1 == json_equal (adx.credit_facade_credentials, + ad.credit_facade_credentials)) ) ) && + ( (adx.credit_facade_url == ad.credit_facade_url) || + ( (NULL != adx.credit_facade_url) && + (NULL != ad.credit_facade_url) && + (0 == strcmp (adx.credit_facade_url, + ad.credit_facade_url)) ) ) ) + { + TMH_wire_method_free (wm); + GNUNET_free (adx.payto_uri); + GNUNET_free (adx.credit_facade_url); + json_decref (adx.credit_facade_credentials); + return TALER_MHD_REPLY_JSON_PACK ( + connection, + MHD_HTTP_OK, + GNUNET_JSON_pack_data_auto ( + "salt", + &adx.salt), + GNUNET_JSON_pack_data_auto ( + "h_wire", + &adx.h_wire)); + } + GNUNET_free (adx.payto_uri); + GNUNET_free (adx.credit_facade_url); + json_decref (adx.credit_facade_credentials); + break; + case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: + case GNUNET_DB_STATUS_SOFT_ERROR: + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + TMH_wire_method_free (wm); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_FETCH_FAILED, + "select_account"); + } + } + TMH_wire_method_free (wm); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_CONFLICT, + TALER_EC_MERCHANT_PRIVATE_ACCOUNT_EXISTS, + uri); + case GNUNET_DB_STATUS_SOFT_ERROR: + case GNUNET_DB_STATUS_HARD_ERROR: + GNUNET_break (0); + TMH_wire_method_free (wm); + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GENERIC_DB_STORE_FAILED, + "insert_account"); + } + } + + { + struct GNUNET_DB_EventHeaderP es = { + .size = htons (sizeof (es)), + .type = htons (TALER_DBEVENT_MERCHANT_ACCOUNTS_CHANGED) + }; + + TMH_db->event_notify (TMH_db->cls, + &es, + NULL, + 0); + } + /* Finally, also update our running process */ + GNUNET_CONTAINER_DLL_insert (mi->wm_head, + mi->wm_tail, + wm); + /* Note: we may not need to do this, as we notified + about the account change above. But also hardly hurts. */ + TMH_reload_instances (mi->settings.id); + return TALER_MHD_REPLY_JSON_PACK (connection, + MHD_HTTP_OK, + GNUNET_JSON_pack_data_auto ("salt", + &wm->wire_salt), + GNUNET_JSON_pack_data_auto ("h_wire", + &wm->h_wire)); +} + + +/* end of taler-merchant-httpd_private-post-account.c */ |