/* This file is part of TALER (C) 2020 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 */ /** * @file backend/taler-merchant-httpd_private-patch-orders-ID-forget.c * @brief implementing PATCH /orders/$ORDER_ID/forget request handling * @author Jonathan Buchanan */ #include "platform.h" #include "taler-merchant-httpd_private-patch-instances-ID.h" #include /** * Forget part of the contract terms. * * @param cls pointer to the result of the forget operation. * @param object_id name of the object to forget. * @param parent parent of the object at @e object_id. */ static void forget (void *cls, const char *object_id, json_t *parent) { int *res = cls; if (GNUNET_OK != TALER_JSON_contract_part_forget (parent, object_id)) *res = GNUNET_SYSERR; } /** * Forget fields of an order's contract terms. * * @param rh context of the handler * @param connection the MHD connection to handle * @param[in,out] hc context with further information about the request * @return MHD result code */ MHD_RESULT TMH_private_patch_orders_ID_forget (const struct TMH_RequestHandler *rh, struct MHD_Connection *connection, struct TMH_HandlerContext *hc) { const char *order_id = hc->infix; enum GNUNET_DB_QueryStatus qs; json_t *fields; json_t *contract_terms; uint64_t order_serial; qs = TMH_db->lookup_contract_terms (TMH_db->cls, hc->instance->settings.id, order_id, &contract_terms, &order_serial); switch (qs) { case GNUNET_DB_STATUS_HARD_ERROR: return TALER_MHD_reply_with_error (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_ORDERS_CLAIM_HARD_DB_ERROR, "Failed to run DB transaction to lookup order"); case GNUNET_DB_STATUS_SOFT_ERROR: return TALER_MHD_reply_with_error (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_ORDERS_CLAIM_SOFT_DB_ERROR, "Failed to serialize DB transaction to lookup order"); case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: return TALER_MHD_reply_with_error (connection, MHD_HTTP_NOT_FOUND, TALER_EC_FORGET_ORDER_NOT_FOUND, "unknown order id"); case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: GNUNET_assert (NULL != contract_terms); break; } { struct GNUNET_JSON_Specification spec[] = { GNUNET_JSON_spec_json ("fields", &fields), GNUNET_JSON_spec_end () }; enum GNUNET_GenericReturnValue res; res = TALER_MHD_parse_json_data (connection, hc->request_body, spec); if (GNUNET_OK != res) return (GNUNET_NO == res) ? MHD_YES : MHD_NO; } if (! (json_is_array (fields))) { json_decref (contract_terms); json_decref (fields); return TALER_MHD_reply_with_error (connection, MHD_HTTP_BAD_REQUEST, TALER_EC_PARAMETER_MALFORMED, "paths"); } { size_t index; json_t *value; json_array_foreach (fields, index, value) { int forget_status = GNUNET_OK; int expand_status; if (! (json_is_string (value))) { json_decref (contract_terms); json_decref (fields); return TALER_MHD_reply_with_error (connection, MHD_HTTP_BAD_REQUEST, TALER_EC_FORGET_PATH_SYNTAX_INCORRECT, "field isn't a string"); } expand_status = TALER_JSON_expand_path (contract_terms, json_string_value (value), &forget, &forget_status); if (GNUNET_SYSERR == forget_status) { /* We tried to forget a field that isn't forgettable */ json_decref (contract_terms); json_decref (fields); return TALER_MHD_reply_with_error (connection, MHD_HTTP_CONFLICT, TALER_EC_FORGET_PATH_NOT_FORGETTABLE, "field isn't forgettable"); } if (GNUNET_SYSERR == expand_status) { /* One of the paths was malformed and couldn't be expanded */ json_decref (contract_terms); json_decref (fields); return TALER_MHD_reply_with_error (connection, MHD_HTTP_BAD_REQUEST, TALER_EC_FORGET_PATH_SYNTAX_INCORRECT, "malformed path"); } } } qs = TMH_db->update_contract_terms (TMH_db->cls, hc->instance->settings.id, order_id, contract_terms); switch (qs) { case GNUNET_DB_STATUS_HARD_ERROR: return TALER_MHD_reply_with_error (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_ORDERS_CLAIM_HARD_DB_ERROR, "Failed to run DB transaction to update contract terms"); case GNUNET_DB_STATUS_SOFT_ERROR: return TALER_MHD_reply_with_error (connection, MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_ORDERS_CLAIM_SOFT_DB_ERROR, "Failed to serialize DB transaction to update contract terms"); case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS: return TALER_MHD_reply_with_error (connection, MHD_HTTP_NOT_FOUND, TALER_EC_FORGET_ORDER_NOT_FOUND, "unknown order id"); case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT: break; } json_decref (contract_terms); json_decref (fields); return TALER_MHD_reply_static (connection, MHD_HTTP_OK, NULL, NULL, 0); }