summaryrefslogtreecommitdiff
path: root/src/backend/taler-merchant-httpd_private-post-account.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/taler-merchant-httpd_private-post-account.c')
-rw-r--r--src/backend/taler-merchant-httpd_private-post-account.c238
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 */