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