taler-merchant-httpd_patch-private-reports-REPORT_ID.c (6413B)
1 /* 2 This file is part of TALER 3 (C) 2025 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 Affero General Public License for more 12 details. 13 14 You should have received a copy of the GNU Affero General Public License 15 along with TALER; see the file COPYING. If not, see 16 <http://www.gnu.org/licenses/> 17 */ 18 /** 19 * @file src/backend/taler-merchant-httpd_patch-private-reports-REPORT_ID.c 20 * @brief implementation of PATCH /private/reports/$REPORT_ID 21 * @author Christian Grothoff 22 */ 23 #include "platform.h" 24 #include "taler-merchant-httpd_patch-private-reports-REPORT_ID.h" 25 #include <taler/taler_json_lib.h> 26 #include <taler/taler_dbevents.h> 27 #include "taler/taler_merchant_util.h" 28 #include "merchant-database/update_report.h" 29 #include "merchant-database/event_notify.h" 30 31 32 enum MHD_Result 33 TMH_private_patch_report (const struct TMH_RequestHandler *rh, 34 struct MHD_Connection *connection, 35 struct TMH_HandlerContext *hc) 36 { 37 const char *report_id_str = hc->infix; 38 unsigned long long report_id; 39 const char *description; 40 const char *program_section; 41 const char *mime_type; 42 const char *data_source; 43 const char *target_address; 44 struct GNUNET_TIME_Relative frequency; 45 struct GNUNET_TIME_Relative frequency_shift 46 = GNUNET_TIME_UNIT_ZERO; 47 enum GNUNET_DB_QueryStatus qs; 48 struct GNUNET_JSON_Specification spec[] = { 49 GNUNET_JSON_spec_string ("description", 50 &description), 51 GNUNET_JSON_spec_string ("program_section", 52 &program_section), 53 GNUNET_JSON_spec_string ("mime_type", 54 &mime_type), 55 GNUNET_JSON_spec_string ("data_source", 56 &data_source), 57 GNUNET_JSON_spec_string ("target_address", 58 &target_address), 59 GNUNET_JSON_spec_relative_time ("report_frequency", 60 &frequency), 61 GNUNET_JSON_spec_mark_optional ( 62 GNUNET_JSON_spec_relative_time ("report_frequency_shift", 63 &frequency_shift), 64 NULL), 65 GNUNET_JSON_spec_end () 66 }; 67 68 (void) rh; 69 { 70 char dummy; 71 72 if (1 != sscanf (report_id_str, 73 "%llu%c", 74 &report_id, 75 &dummy)) 76 { 77 GNUNET_break_op (0); 78 return TALER_MHD_reply_with_error (connection, 79 MHD_HTTP_BAD_REQUEST, 80 TALER_EC_GENERIC_PARAMETER_MALFORMED, 81 "report_id"); 82 } 83 } 84 85 { 86 enum GNUNET_GenericReturnValue res; 87 88 res = TALER_MHD_parse_json_data (connection, 89 hc->request_body, 90 spec); 91 if (GNUNET_OK != res) 92 { 93 GNUNET_break_op (0); 94 return (GNUNET_NO == res) 95 ? MHD_YES 96 : MHD_NO; 97 } 98 } 99 if ('/' != data_source[0]) 100 { 101 GNUNET_break_op (0); 102 return TALER_MHD_reply_with_error (connection, 103 MHD_HTTP_BAD_REQUEST, 104 TALER_EC_GENERIC_PARAMETER_MALFORMED, 105 "data_source"); 106 107 } 108 109 /* The report generator passes both values to the generator binary on 110 the command line, and the mime type into an "Accept:" header of its 111 own request. A target address that begins with '-' is taken for an 112 option by the delivery tools behind the generator, and a control 113 character in either value would distort the header. */ 114 if (! TALER_MERCHANT_report_target_valid (target_address)) 115 { 116 GNUNET_break_op (0); 117 return TALER_MHD_reply_with_error (connection, 118 MHD_HTTP_BAD_REQUEST, 119 TALER_EC_GENERIC_PARAMETER_MALFORMED, 120 "target_address"); 121 } 122 if (! TALER_MERCHANT_mime_type_valid (mime_type)) 123 { 124 GNUNET_break_op (0); 125 return TALER_MHD_reply_with_error (connection, 126 MHD_HTTP_BAD_REQUEST, 127 TALER_EC_GENERIC_PARAMETER_MALFORMED, 128 "mime_type"); 129 } 130 qs = TALER_MERCHANTDB_update_report (TMH_db, 131 hc->instance->settings.id, 132 report_id, 133 program_section, 134 description, 135 mime_type, 136 data_source, 137 target_address, 138 frequency, 139 frequency_shift); 140 if (qs < 0) 141 { 142 GNUNET_break (0); 143 return TALER_MHD_reply_with_error (connection, 144 MHD_HTTP_INTERNAL_SERVER_ERROR, 145 TALER_EC_GENERIC_DB_STORE_FAILED, 146 "update_report"); 147 } 148 if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == qs) 149 { 150 return TALER_MHD_reply_with_error (connection, 151 MHD_HTTP_NOT_FOUND, 152 TALER_EC_MERCHANT_GENERIC_REPORT_UNKNOWN, 153 report_id_str); 154 } 155 156 /* FIXME-Optimization: Trigger MERCHANT_REPORT_UPDATE event inside of UPDATE transaction */ 157 { 158 struct GNUNET_DB_EventHeaderP ev = { 159 .size = htons (sizeof (ev)), 160 .type = htons (TALER_DBEVENT_MERCHANT_REPORT_UPDATE) 161 }; 162 163 TALER_MERCHANTDB_event_notify (TMH_db, 164 &ev, 165 NULL, 166 0); 167 } 168 169 return TALER_MHD_reply_static (connection, 170 MHD_HTTP_NO_CONTENT, 171 NULL, 172 NULL, 173 0); 174 }