Line data Source code
1 : /*
2 : This file is part of TALER
3 : (C) 2020 Taler Systems SA
4 :
5 : TALER is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU Affero General Public License as published by the Free Software
7 : Foundation; either version 3, or (at your option) any later version.
8 :
9 : TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 : WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 : A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 :
13 : You should have received a copy of the GNU General Public License along with
14 : TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
15 : */
16 : /**
17 : * @file src/backend/taler-merchant-httpd_delete-private-orders-ORDER_ID.c
18 : * @brief implement DELETE /orders/$ID
19 : * @author Christian Grothoff
20 : */
21 : #include "platform.h"
22 : #include "taler-merchant-httpd_delete-private-orders-ORDER_ID.h"
23 : #include <stdint.h>
24 : #include <taler/taler_json_lib.h>
25 : #include "merchant-database/delete_contract_terms.h"
26 : #include "merchant-database/delete_order.h"
27 : #include "merchant-database/get_contract_terms.h"
28 : #include "merchant-database/get_contract_terms_status.h"
29 : #include "merchant-database/get_order.h"
30 :
31 :
32 : /**
33 : * Check if the given @a contract_terms contain external payment
34 : * entries ("amount_external"). Such orders may have been settled
35 : * outside of Taler and must not be deleted without force.
36 : *
37 : * @param contract_terms contract terms to check
38 : * @return true if external payment entries are present
39 : */
40 : static bool
41 8 : has_external_payments (const json_t *contract_terms)
42 : {
43 8 : return 0 != json_array_size (json_object_get (contract_terms,
44 : "amount_external"));
45 : }
46 :
47 :
48 : /**
49 : * Handle a DELETE "/orders/$ID" request.
50 : *
51 : * @param rh context of the handler
52 : * @param connection the MHD connection to handle
53 : * @param[in,out] hc context with further information about the request
54 : * @return MHD result code
55 : */
56 : enum MHD_Result
57 14 : TMH_private_delete_orders_ID (const struct TMH_RequestHandler *rh,
58 : struct MHD_Connection *connection,
59 : struct TMH_HandlerContext *hc)
60 : {
61 14 : struct TMH_MerchantInstance *mi = hc->instance;
62 : enum GNUNET_DB_QueryStatus qs;
63 : bool force;
64 :
65 : (void) rh;
66 14 : GNUNET_assert (NULL != mi);
67 14 : TALER_MHD_parse_request_bool (connection,
68 : "force",
69 : false,
70 : &force);
71 14 : if (! force)
72 : {
73 : /* Orders with externally settled payments require an explicit
74 : force operation to be removed. */
75 10 : json_t *contract_terms = NULL;
76 : uint64_t order_serial;
77 :
78 10 : qs = TALER_MERCHANTDB_get_contract_terms (TMH_db,
79 10 : mi->settings.id,
80 10 : hc->infix,
81 : &contract_terms,
82 : &order_serial,
83 : NULL);
84 10 : if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
85 : {
86 : struct TALER_MerchantPostDataHashP unused;
87 :
88 6 : qs = TALER_MERCHANTDB_get_order (TMH_db,
89 6 : mi->settings.id,
90 6 : hc->infix,
91 : NULL,
92 : &unused,
93 : &contract_terms);
94 : }
95 10 : if (0 > qs)
96 2 : return TALER_MHD_reply_with_error (connection,
97 : MHD_HTTP_INTERNAL_SERVER_ERROR,
98 : TALER_EC_GENERIC_DB_FETCH_FAILED,
99 : "lookup order for deletion");
100 10 : if (NULL != contract_terms)
101 : {
102 8 : bool blocked = has_external_payments (contract_terms);
103 :
104 8 : json_decref (contract_terms);
105 8 : if (blocked)
106 2 : return TALER_MHD_reply_with_error (
107 : connection,
108 : MHD_HTTP_CONFLICT,
109 : TALER_EC_MERCHANT_PRIVATE_DELETE_ORDERS_EXTERNALLY_PAID,
110 2 : hc->infix);
111 : }
112 : }
113 12 : qs = TALER_MERCHANTDB_delete_order (TMH_db,
114 12 : mi->settings.id,
115 12 : hc->infix,
116 : force);
117 12 : if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
118 6 : qs = TALER_MERCHANTDB_delete_contract_terms (TMH_db,
119 6 : mi->settings.id,
120 6 : hc->infix,
121 : TMH_legal_expiration);
122 12 : switch (qs)
123 : {
124 0 : case GNUNET_DB_STATUS_HARD_ERROR:
125 0 : return TALER_MHD_reply_with_error (connection,
126 : MHD_HTTP_INTERNAL_SERVER_ERROR,
127 : TALER_EC_GENERIC_DB_COMMIT_FAILED,
128 : NULL);
129 0 : case GNUNET_DB_STATUS_SOFT_ERROR:
130 0 : GNUNET_break (0);
131 0 : return TALER_MHD_reply_with_error (connection,
132 : MHD_HTTP_INTERNAL_SERVER_ERROR,
133 : TALER_EC_GENERIC_INTERNAL_INVARIANT_FAILURE,
134 : NULL);
135 6 : case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
136 : {
137 : struct TALER_MerchantPostDataHashP unused;
138 : uint64_t order_serial;
139 6 : bool paid = false;
140 6 : bool wired = false;
141 6 : bool matches = false;
142 : int16_t choice_index;
143 :
144 6 : qs = TALER_MERCHANTDB_get_order (TMH_db,
145 6 : mi->settings.id,
146 6 : hc->infix,
147 : NULL,
148 : &unused,
149 : NULL);
150 6 : if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
151 : {
152 4 : qs = TALER_MERCHANTDB_get_contract_terms_status (TMH_db,
153 4 : mi->settings.id,
154 4 : hc->infix,
155 : NULL,
156 : NULL,
157 : &order_serial,
158 : &paid,
159 : &wired,
160 : &matches,
161 : NULL,
162 : &choice_index);
163 : }
164 6 : if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs)
165 2 : return TALER_MHD_reply_with_error (connection,
166 : MHD_HTTP_NOT_FOUND,
167 : TALER_EC_MERCHANT_GENERIC_ORDER_UNKNOWN,
168 2 : hc->infix);
169 4 : if (paid)
170 2 : return TALER_MHD_reply_with_error (connection,
171 : MHD_HTTP_CONFLICT,
172 : TALER_EC_MERCHANT_PRIVATE_DELETE_ORDERS_ALREADY_PAID,
173 2 : hc->infix);
174 2 : return TALER_MHD_reply_with_error (connection,
175 : MHD_HTTP_CONFLICT,
176 : TALER_EC_MERCHANT_PRIVATE_DELETE_ORDERS_AWAITING_PAYMENT,
177 2 : hc->infix);
178 : }
179 6 : case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
180 6 : return TALER_MHD_reply_static (connection,
181 : MHD_HTTP_NO_CONTENT,
182 : NULL,
183 : NULL,
184 : 0);
185 : }
186 0 : GNUNET_assert (0);
187 : return MHD_NO;
188 : }
189 :
190 :
191 : /* end of taler-merchant-httpd_delete-private-orders-ORDER_ID.c */
|