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 taler-merchant-httpd_private-patch-units-ID.c
18 : * @brief implement PATCH /private/units/$UNIT
19 : * @author Bohdan Potuzhnyi
20 : */
21 : #include "platform.h"
22 : #include "taler-merchant-httpd_private-patch-units-ID.h"
23 : #include "taler-merchant-httpd_helper.h"
24 : #include <taler/taler_json_lib.h>
25 :
26 : #define TMH_MAX_UNIT_PRECISION_LEVEL 6
27 :
28 :
29 : MHD_RESULT
30 4 : TMH_private_patch_units_ID (const struct TMH_RequestHandler *rh,
31 : struct MHD_Connection *connection,
32 : struct TMH_HandlerContext *hc)
33 : {
34 4 : struct TMH_MerchantInstance *mi = hc->instance;
35 4 : const char *unit_id = hc->infix;
36 4 : struct TALER_MERCHANTDB_UnitDetails nud = { 0 };
37 4 : bool unit_allow_fraction_missing = true;
38 4 : bool unit_precision_missing = true;
39 4 : bool unit_active_missing = true;
40 : struct GNUNET_JSON_Specification spec[] = {
41 4 : GNUNET_JSON_spec_mark_optional (
42 : GNUNET_JSON_spec_string ("unit_name_long",
43 : (const char **) &nud.unit_name_long),
44 : NULL),
45 4 : GNUNET_JSON_spec_mark_optional (
46 : GNUNET_JSON_spec_json ("unit_name_long_i18n",
47 : &nud.unit_name_long_i18n),
48 : NULL),
49 4 : GNUNET_JSON_spec_mark_optional (
50 : GNUNET_JSON_spec_string ("unit_name_short",
51 : (const char **) &nud.unit_name_short),
52 : NULL),
53 4 : GNUNET_JSON_spec_mark_optional (
54 : GNUNET_JSON_spec_json ("unit_name_short_i18n",
55 : &nud.unit_name_short_i18n),
56 : NULL),
57 4 : GNUNET_JSON_spec_mark_optional (
58 : GNUNET_JSON_spec_bool ("unit_allow_fraction",
59 : &nud.unit_allow_fraction),
60 : &unit_allow_fraction_missing),
61 4 : GNUNET_JSON_spec_mark_optional (
62 : GNUNET_JSON_spec_uint32 ("unit_precision_level",
63 : &nud.unit_precision_level),
64 : &unit_precision_missing),
65 4 : GNUNET_JSON_spec_mark_optional (
66 : GNUNET_JSON_spec_bool ("unit_active",
67 : &nud.unit_active),
68 : &unit_active_missing),
69 4 : GNUNET_JSON_spec_end ()
70 : };
71 : enum GNUNET_GenericReturnValue res;
72 4 : const bool *unit_allow_fraction_ptr = NULL;
73 4 : const uint32_t *unit_precision_ptr = NULL;
74 4 : const bool *unit_active_ptr = NULL;
75 : enum GNUNET_DB_QueryStatus qs;
76 4 : bool no_instance = false;
77 4 : bool no_unit = false;
78 4 : bool builtin_conflict = false;
79 4 : MHD_RESULT ret = MHD_YES;
80 :
81 : (void) rh;
82 4 : GNUNET_assert (NULL != mi);
83 4 : GNUNET_assert (NULL != unit_id);
84 :
85 4 : res = TALER_MHD_parse_json_data (connection,
86 4 : hc->request_body,
87 : spec);
88 4 : if (GNUNET_OK != res)
89 0 : return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
90 :
91 4 : if (NULL == nud.unit_name_long &&
92 2 : NULL == nud.unit_name_long_i18n &&
93 2 : NULL == nud.unit_name_short &&
94 2 : 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 4 : if (! unit_precision_missing)
108 : {
109 4 : 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 4 : unit_precision_ptr = &nud.unit_precision_level;
119 : }
120 :
121 4 : if (! unit_allow_fraction_missing)
122 : {
123 4 : unit_allow_fraction_ptr = &nud.unit_allow_fraction;
124 4 : if (! nud.unit_allow_fraction)
125 : {
126 2 : nud.unit_precision_level = 0;
127 2 : unit_precision_missing = false;
128 2 : unit_precision_ptr = &nud.unit_precision_level;
129 : }
130 : }
131 :
132 4 : if (! unit_active_missing)
133 4 : unit_active_ptr = &nud.unit_active;
134 :
135 4 : 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 4 : 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 4 : qs = TMH_db->update_unit (TMH_db->cls,
162 4 : mi->settings.id,
163 : unit_id,
164 4 : nud.unit_name_long,
165 4 : nud.unit_name_long_i18n,
166 4 : nud.unit_name_short,
167 4 : nud.unit_name_short_i18n,
168 : unit_allow_fraction_ptr,
169 : unit_precision_ptr,
170 : unit_active_ptr,
171 : &no_instance,
172 : &no_unit,
173 : &builtin_conflict);
174 4 : switch (qs)
175 : {
176 4 : case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
177 4 : break;
178 0 : case GNUNET_DB_STATUS_SOFT_ERROR:
179 0 : GNUNET_break (0);
180 0 : ret = TALER_MHD_reply_with_error (connection,
181 : MHD_HTTP_INTERNAL_SERVER_ERROR,
182 : TALER_EC_GENERIC_DB_SOFT_FAILURE,
183 : "update_unit");
184 0 : goto cleanup;
185 0 : case GNUNET_DB_STATUS_HARD_ERROR:
186 : default:
187 0 : GNUNET_break (0);
188 0 : ret = TALER_MHD_reply_with_error (connection,
189 : MHD_HTTP_INTERNAL_SERVER_ERROR,
190 : TALER_EC_GENERIC_DB_STORE_FAILED,
191 : "update_unit");
192 0 : goto cleanup;
193 : }
194 :
195 4 : if (no_instance)
196 : {
197 0 : ret = TALER_MHD_reply_with_error (connection,
198 : MHD_HTTP_NOT_FOUND,
199 : TALER_EC_MERCHANT_GENERIC_INSTANCE_UNKNOWN,
200 0 : mi->settings.id);
201 0 : goto cleanup;
202 : }
203 4 : if (no_unit)
204 : {
205 0 : ret = TALER_MHD_reply_with_error (connection,
206 : MHD_HTTP_NOT_FOUND,
207 : TALER_EC_MERCHANT_GENERIC_UNIT_UNKNOWN,
208 : unit_id);
209 0 : goto cleanup;
210 : }
211 4 : if (builtin_conflict)
212 : {
213 0 : ret = TALER_MHD_reply_with_error (connection,
214 : MHD_HTTP_CONFLICT,
215 : TALER_EC_MERCHANT_GENERIC_UNIT_BUILTIN,
216 : unit_id);
217 0 : goto cleanup;
218 : }
219 :
220 4 : ret = TALER_MHD_reply_static (connection,
221 : MHD_HTTP_NO_CONTENT,
222 : NULL,
223 : NULL,
224 : 0);
225 :
226 4 : cleanup:
227 4 : if (NULL != nud.unit_name_long_i18n)
228 : {
229 2 : json_decref (nud.unit_name_long_i18n);
230 2 : nud.unit_name_long_i18n = NULL;
231 : }
232 4 : if (NULL != nud.unit_name_short_i18n)
233 : {
234 2 : json_decref (nud.unit_name_short_i18n);
235 2 : nud.unit_name_short_i18n = NULL;
236 : }
237 4 : GNUNET_JSON_parse_free (spec);
238 4 : return ret;
239 : }
240 :
241 :
242 : /* end of taler-merchant-httpd_private-patch-units-ID.c */
|