Line data Source code
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 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_patch-private-units-UNIT.c
18 : * @brief implement PATCH /private/units/$UNIT
19 : * @author Bohdan Potuzhnyi
20 : */
21 : #include "platform.h"
22 : #include "taler-merchant-httpd_patch-private-units-UNIT.h"
23 : #include "taler-merchant-httpd_helper.h"
24 : #include <taler/taler_json_lib.h>
25 : #include "merchant-database/update_unit.h"
26 :
27 : #define TMH_MAX_UNIT_PRECISION_LEVEL 6
28 :
29 :
30 : enum MHD_Result
31 10 : TMH_private_patch_units_ID (const struct TMH_RequestHandler *rh,
32 : struct MHD_Connection *connection,
33 : struct TMH_HandlerContext *hc)
34 : {
35 10 : struct TMH_MerchantInstance *mi = hc->instance;
36 10 : const char *unit_id = hc->infix;
37 10 : struct TALER_MERCHANTDB_UnitDetails nud = { 0 };
38 10 : bool unit_allow_fraction_missing = true;
39 10 : bool unit_precision_missing = true;
40 10 : bool unit_active_missing = true;
41 : struct GNUNET_JSON_Specification spec[] = {
42 10 : GNUNET_JSON_spec_mark_optional (
43 : GNUNET_JSON_spec_string ("unit_name_long",
44 : (const char **) &nud.unit_name_long),
45 : NULL),
46 10 : GNUNET_JSON_spec_mark_optional (
47 : GNUNET_JSON_spec_json ("unit_name_long_i18n",
48 : &nud.unit_name_long_i18n),
49 : NULL),
50 10 : GNUNET_JSON_spec_mark_optional (
51 : GNUNET_JSON_spec_string ("unit_name_short",
52 : (const char **) &nud.unit_name_short),
53 : NULL),
54 10 : GNUNET_JSON_spec_mark_optional (
55 : GNUNET_JSON_spec_json ("unit_name_short_i18n",
56 : &nud.unit_name_short_i18n),
57 : NULL),
58 10 : GNUNET_JSON_spec_mark_optional (
59 : GNUNET_JSON_spec_bool ("unit_allow_fraction",
60 : &nud.unit_allow_fraction),
61 : &unit_allow_fraction_missing),
62 10 : GNUNET_JSON_spec_mark_optional (
63 : GNUNET_JSON_spec_uint32 ("unit_precision_level",
64 : &nud.unit_precision_level),
65 : &unit_precision_missing),
66 10 : GNUNET_JSON_spec_mark_optional (
67 : GNUNET_JSON_spec_bool ("unit_active",
68 : &nud.unit_active),
69 : &unit_active_missing),
70 10 : GNUNET_JSON_spec_end ()
71 : };
72 : enum GNUNET_GenericReturnValue res;
73 10 : const bool *unit_allow_fraction_ptr = NULL;
74 10 : const uint32_t *unit_precision_ptr = NULL;
75 10 : const bool *unit_active_ptr = NULL;
76 : enum GNUNET_DB_QueryStatus qs;
77 10 : bool no_unit = false;
78 10 : bool builtin_conflict = false;
79 10 : enum MHD_Result ret = MHD_YES;
80 :
81 : (void) rh;
82 10 : GNUNET_assert (NULL != mi);
83 10 : GNUNET_assert (NULL != unit_id);
84 :
85 10 : res = TALER_MHD_parse_json_data (connection,
86 10 : hc->request_body,
87 : spec);
88 10 : if (GNUNET_OK != res)
89 0 : return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
90 :
91 10 : if (NULL == nud.unit_name_long &&
92 6 : NULL == nud.unit_name_long_i18n &&
93 6 : NULL == nud.unit_name_short &&
94 6 : NULL == nud.unit_name_short_i18n &&
95 0 : unit_allow_fraction_missing &&
96 0 : unit_precision_missing &&
97 : unit_active_missing)
98 : {
99 0 : ret = TALER_MHD_reply_static (connection,
100 : MHD_HTTP_NO_CONTENT,
101 : NULL,
102 : NULL,
103 : 0);
104 0 : goto cleanup;
105 : }
106 :
107 10 : if (! unit_precision_missing)
108 : {
109 10 : if (nud.unit_precision_level > TMH_MAX_UNIT_PRECISION_LEVEL)
110 : {
111 0 : GNUNET_break_op (0);
112 0 : ret = TALER_MHD_reply_with_error (connection,
113 : MHD_HTTP_BAD_REQUEST,
114 : TALER_EC_GENERIC_PARAMETER_MALFORMED,
115 : "unit_precision_level");
116 0 : goto cleanup;
117 : }
118 10 : unit_precision_ptr = &nud.unit_precision_level;
119 : }
120 :
121 10 : if (! unit_allow_fraction_missing)
122 : {
123 10 : unit_allow_fraction_ptr = &nud.unit_allow_fraction;
124 10 : if (! nud.unit_allow_fraction)
125 : {
126 4 : nud.unit_precision_level = 0;
127 4 : unit_precision_missing = false;
128 4 : unit_precision_ptr = &nud.unit_precision_level;
129 : }
130 : }
131 :
132 10 : if (! unit_active_missing)
133 10 : unit_active_ptr = &nud.unit_active;
134 :
135 10 : if (NULL != nud.unit_name_long_i18n)
136 : {
137 2 : if (! TALER_JSON_check_i18n (nud.unit_name_long_i18n))
138 : {
139 0 : GNUNET_break_op (0);
140 0 : ret = TALER_MHD_reply_with_error (connection,
141 : MHD_HTTP_BAD_REQUEST,
142 : TALER_EC_GENERIC_PARAMETER_MALFORMED,
143 : "unit_name_long_i18n");
144 0 : goto cleanup;
145 : }
146 : }
147 :
148 10 : if (NULL != nud.unit_name_short_i18n)
149 : {
150 2 : if (! TALER_JSON_check_i18n (nud.unit_name_short_i18n))
151 : {
152 0 : GNUNET_break_op (0);
153 0 : ret = TALER_MHD_reply_with_error (connection,
154 : MHD_HTTP_BAD_REQUEST,
155 : TALER_EC_GENERIC_PARAMETER_MALFORMED,
156 : "unit_name_short_i18n");
157 0 : goto cleanup;
158 : }
159 : }
160 :
161 10 : qs = TALER_MERCHANTDB_update_unit (TMH_db,
162 10 : mi->settings.id,
163 : unit_id,
164 10 : nud.unit_name_long,
165 10 : nud.unit_name_long_i18n,
166 10 : nud.unit_name_short,
167 10 : nud.unit_name_short_i18n,
168 : unit_allow_fraction_ptr,
169 : unit_precision_ptr,
170 : unit_active_ptr,
171 : &no_unit,
172 : &builtin_conflict);
173 10 : switch (qs)
174 : {
175 10 : case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
176 10 : break;
177 0 : case GNUNET_DB_STATUS_SOFT_ERROR:
178 0 : GNUNET_break (0);
179 0 : ret = TALER_MHD_reply_with_error (connection,
180 : MHD_HTTP_INTERNAL_SERVER_ERROR,
181 : TALER_EC_GENERIC_DB_SOFT_FAILURE,
182 : "update_unit");
183 0 : goto cleanup;
184 0 : case GNUNET_DB_STATUS_HARD_ERROR:
185 : default:
186 0 : GNUNET_break (0);
187 0 : ret = TALER_MHD_reply_with_error (connection,
188 : MHD_HTTP_INTERNAL_SERVER_ERROR,
189 : TALER_EC_GENERIC_DB_STORE_FAILED,
190 : "update_unit");
191 0 : goto cleanup;
192 : }
193 :
194 10 : if (no_unit)
195 : {
196 0 : ret = TALER_MHD_reply_with_error (connection,
197 : MHD_HTTP_NOT_FOUND,
198 : TALER_EC_MERCHANT_GENERIC_UNIT_UNKNOWN,
199 : unit_id);
200 0 : goto cleanup;
201 : }
202 10 : if (builtin_conflict)
203 : {
204 2 : ret = TALER_MHD_reply_with_error (connection,
205 : MHD_HTTP_CONFLICT,
206 : TALER_EC_MERCHANT_GENERIC_UNIT_BUILTIN,
207 : unit_id);
208 2 : goto cleanup;
209 : }
210 :
211 8 : ret = TALER_MHD_reply_static (connection,
212 : MHD_HTTP_NO_CONTENT,
213 : NULL,
214 : NULL,
215 : 0);
216 :
217 10 : cleanup:
218 10 : if (NULL != nud.unit_name_long_i18n)
219 : {
220 2 : json_decref (nud.unit_name_long_i18n);
221 2 : nud.unit_name_long_i18n = NULL;
222 : }
223 10 : if (NULL != nud.unit_name_short_i18n)
224 : {
225 2 : json_decref (nud.unit_name_short_i18n);
226 2 : nud.unit_name_short_i18n = NULL;
227 : }
228 10 : GNUNET_JSON_parse_free (spec);
229 10 : return ret;
230 : }
231 :
232 :
233 : /* end of taler-merchant-httpd_patch-private-units-UNIT.c */
|