1 /*
2 // Copyright (c) 2018 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16 #include "utils/json_utils.hpp"
17 
18 #include <error_messages.hpp>
19 
20 namespace redfish
21 {
22 
23 namespace json_util
24 {
25 
26 Result getString(const char* fieldName, const nlohmann::json& json,
27                  const std::string*& output)
28 {
29     // Find field
30     auto fieldIt = json.find(fieldName);
31 
32     // Verify existence
33     if (fieldIt == json.end())
34     {
35         return Result::NOT_EXIST;
36     }
37 
38     output = fieldIt->get_ptr<const std::string*>();
39 
40     // Verify type - we know that it exists, so nullptr means wrong type
41     if (output == nullptr)
42     {
43         return Result::WRONG_TYPE;
44     }
45 
46     return Result::SUCCESS;
47 }
48 
49 Result getObject(const char* fieldName, const nlohmann::json& json,
50                  nlohmann::json* output)
51 {
52     // Verify input pointer
53     if (output == nullptr)
54     {
55         return Result::NULL_POINTER;
56     }
57 
58     // Find field
59     auto fieldIt = json.find(fieldName);
60 
61     // Verify existence
62     if (fieldIt == json.end())
63     {
64         return Result::NOT_EXIST;
65     }
66 
67     // Verify type
68     if (!fieldIt->is_object())
69     {
70         return Result::WRONG_TYPE;
71     }
72 
73     // Extract value
74     *output = *fieldIt;
75 
76     return Result::SUCCESS;
77 }
78 
79 Result getArray(const char* fieldName, const nlohmann::json& json,
80                 nlohmann::json* output)
81 {
82     // Verify input pointer
83     if (output == nullptr)
84     {
85         return Result::NULL_POINTER;
86     }
87 
88     // Find field
89     auto fieldIt = json.find(fieldName);
90 
91     // Verify existence
92     if (fieldIt == json.end())
93     {
94         return Result::NOT_EXIST;
95     }
96 
97     // Verify type
98     if (!fieldIt->is_array())
99     {
100         return Result::WRONG_TYPE;
101     }
102 
103     // Extract value
104     *output = *fieldIt;
105 
106     return Result::SUCCESS;
107 }
108 
109 Result getInt(const char* fieldName, const nlohmann::json& json,
110               int64_t& output)
111 {
112     // Find field
113     auto fieldIt = json.find(fieldName);
114 
115     // Verify existence
116     if (fieldIt == json.end())
117     {
118         return Result::NOT_EXIST;
119     }
120 
121     const int64_t* retVal = fieldIt->get_ptr<const int64_t*>();
122 
123     // Verify type - we know that it exists, so nullptr means wrong type
124     if (retVal == nullptr)
125     {
126         return Result::WRONG_TYPE;
127     }
128 
129     // Extract value
130     output = *retVal;
131 
132     return Result::SUCCESS;
133 }
134 
135 Result getUnsigned(const char* fieldName, const nlohmann::json& json,
136                    uint64_t& output)
137 {
138     // Find field
139     auto fieldIt = json.find(fieldName);
140 
141     // Verify existence
142     if (fieldIt == json.end())
143     {
144         return Result::NOT_EXIST;
145     }
146 
147     const uint64_t* retVal = fieldIt->get_ptr<const uint64_t*>();
148 
149     // Verify type - we know that it exists, so nullptr means wrong type
150     if (retVal == nullptr)
151     {
152         return Result::WRONG_TYPE;
153     }
154 
155     // Extract value
156     output = *retVal;
157 
158     return Result::SUCCESS;
159 }
160 
161 Result getBool(const char* fieldName, const nlohmann::json& json, bool& output)
162 {
163     // Find field
164     auto fieldIt = json.find(fieldName);
165 
166     // Verify existence
167     if (fieldIt == json.end())
168     {
169         return Result::NOT_EXIST;
170     }
171 
172     const bool* retVal = fieldIt->get_ptr<const bool*>();
173 
174     // Verify type - we know that it exists, so nullptr means wrong type
175     if (retVal == nullptr)
176     {
177         return Result::WRONG_TYPE;
178     }
179 
180     // Extract value
181     output = *retVal;
182 
183     return Result::SUCCESS;
184 }
185 
186 Result getDouble(const char* fieldName, const nlohmann::json& json,
187                  double& output)
188 {
189     // Find field
190     auto fieldIt = json.find(fieldName);
191 
192     // Verify existence
193     if (fieldIt == json.end())
194     {
195         return Result::NOT_EXIST;
196     }
197 
198     const double* retVal = fieldIt->get_ptr<const double*>();
199 
200     // Verify type - we know that it exists, so nullptr means wrong type
201     if (retVal == nullptr)
202     {
203         return Result::WRONG_TYPE;
204     }
205 
206     // Extract value
207     output = *retVal;
208 
209     return Result::SUCCESS;
210 }
211 
212 Result getString(const char* fieldName, const nlohmann::json& json,
213                  const std::string*& output, uint8_t msgCfgMap,
214                  nlohmann::json& msgJson, const std::string&& fieldPath)
215 {
216     // Find field
217     auto fieldIt = json.find(fieldName);
218 
219     // Verify existence
220     if (fieldIt == json.end())
221     {
222         if (msgCfgMap & static_cast<int>(MessageSetting::MISSING))
223         {
224             messages::addMessageToJson(
225                 msgJson, messages::propertyMissing(fieldName), fieldPath);
226         }
227 
228         return Result::NOT_EXIST;
229     }
230 
231     output = fieldIt->get_ptr<const std::string*>();
232 
233     // Verify type - we know that it exists, so nullptr means wrong type
234     if (output == nullptr)
235     {
236         if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR))
237         {
238             messages::addMessageToJson(
239                 msgJson,
240                 messages::propertyValueTypeError(fieldIt->dump(), fieldName),
241                 fieldPath);
242         }
243 
244         return Result::WRONG_TYPE;
245     }
246 
247     return Result::SUCCESS;
248 }
249 
250 Result getObject(const char* fieldName, const nlohmann::json& json,
251                  nlohmann::json* output, uint8_t msgCfgMap,
252                  nlohmann::json& msgJson, const std::string&& fieldPath)
253 {
254     // Verify input pointer
255     if (output == nullptr)
256     {
257         return Result::NULL_POINTER;
258     }
259 
260     // Find field
261     auto fieldIt = json.find(fieldName);
262 
263     // Verify existence
264     if (fieldIt == json.end())
265     {
266         if (msgCfgMap & static_cast<int>(MessageSetting::MISSING))
267         {
268             messages::addMessageToJson(
269                 msgJson, messages::propertyMissing(fieldName), fieldPath);
270         }
271 
272         return Result::NOT_EXIST;
273     }
274 
275     // Verify type
276     if (!fieldIt->is_object())
277     {
278         if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR))
279         {
280             messages::addMessageToJson(
281                 msgJson,
282                 messages::propertyValueTypeError(fieldIt->dump(), fieldName),
283                 fieldPath);
284         }
285 
286         return Result::WRONG_TYPE;
287     }
288 
289     // Extract value
290     *output = *fieldIt;
291 
292     return Result::SUCCESS;
293 }
294 
295 Result getArray(const char* fieldName, const nlohmann::json& json,
296                 nlohmann::json* output, uint8_t msgCfgMap,
297                 nlohmann::json& msgJson, const std::string&& fieldPath)
298 {
299     // Verify input pointer
300     if (output == nullptr)
301     {
302         return Result::NULL_POINTER;
303     }
304 
305     // Find field
306     auto fieldIt = json.find(fieldName);
307 
308     // Verify existence
309     if (fieldIt == json.end())
310     {
311         if (msgCfgMap & static_cast<int>(MessageSetting::MISSING))
312         {
313             messages::addMessageToJson(
314                 msgJson, messages::propertyMissing(fieldName), fieldPath);
315         }
316 
317         return Result::NOT_EXIST;
318     }
319 
320     // Verify type
321     if (!fieldIt->is_array())
322     {
323         if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR))
324         {
325             messages::addMessageToJson(
326                 msgJson,
327                 messages::propertyValueTypeError(fieldIt->dump(), fieldName),
328                 fieldPath);
329         }
330 
331         return Result::WRONG_TYPE;
332     }
333 
334     // Extract value
335     *output = *fieldIt;
336 
337     return Result::SUCCESS;
338 }
339 
340 Result getInt(const char* fieldName, const nlohmann::json& json,
341               int64_t& output, uint8_t msgCfgMap, nlohmann::json& msgJson,
342               const std::string&& fieldPath)
343 {
344     // Find field
345     auto fieldIt = json.find(fieldName);
346 
347     // Verify existence
348     if (fieldIt == json.end())
349     {
350         if (msgCfgMap & static_cast<int>(MessageSetting::MISSING))
351         {
352             messages::addMessageToJson(
353                 msgJson, messages::propertyMissing(fieldName), fieldPath);
354         }
355 
356         return Result::NOT_EXIST;
357     }
358 
359     const int64_t* retVal = fieldIt->get_ptr<const int64_t*>();
360 
361     // Verify type - we know that it exists, so nullptr means wrong type
362     if (retVal == nullptr)
363     {
364         if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR))
365         {
366             messages::addMessageToJson(
367                 msgJson,
368                 messages::propertyValueTypeError(fieldIt->dump(), fieldName),
369                 fieldPath);
370         }
371 
372         return Result::WRONG_TYPE;
373     }
374 
375     // Extract value
376     output = *retVal;
377 
378     return Result::SUCCESS;
379 }
380 
381 Result getUnsigned(const char* fieldName, const nlohmann::json& json,
382                    uint64_t& output, uint8_t msgCfgMap, nlohmann::json& msgJson,
383                    const std::string&& fieldPath)
384 {
385     // Find field
386     auto fieldIt = json.find(fieldName);
387 
388     // Verify existence
389     if (fieldIt == json.end())
390     {
391         if (msgCfgMap & static_cast<int>(MessageSetting::MISSING))
392         {
393             messages::addMessageToJson(
394                 msgJson, messages::propertyMissing(fieldName), fieldPath);
395         }
396 
397         return Result::NOT_EXIST;
398     }
399 
400     const uint64_t* retVal = fieldIt->get_ptr<const uint64_t*>();
401 
402     // Verify type - we know that it exists, so nullptr means wrong type
403     if (retVal == nullptr)
404     {
405         if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR))
406         {
407             messages::addMessageToJson(
408                 msgJson,
409                 messages::propertyValueTypeError(fieldIt->dump(), fieldName),
410                 fieldPath);
411         }
412 
413         return Result::WRONG_TYPE;
414     }
415 
416     // Extract value
417     output = *retVal;
418 
419     return Result::SUCCESS;
420 }
421 
422 Result getBool(const char* fieldName, const nlohmann::json& json, bool& output,
423                uint8_t msgCfgMap, nlohmann::json& msgJson,
424                const std::string&& fieldPath)
425 {
426     // Find field
427     auto fieldIt = json.find(fieldName);
428 
429     // Verify existence
430     if (fieldIt == json.end())
431     {
432         if (msgCfgMap & static_cast<int>(MessageSetting::MISSING))
433         {
434             messages::addMessageToJson(
435                 msgJson, messages::propertyMissing(fieldName), fieldPath);
436         }
437 
438         return Result::NOT_EXIST;
439     }
440 
441     const bool* retVal = fieldIt->get_ptr<const bool*>();
442 
443     // Verify type - we know that it exists, so nullptr means wrong type
444     if (retVal == nullptr)
445     {
446         if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR))
447         {
448             messages::addMessageToJson(
449                 msgJson,
450                 messages::propertyValueTypeError(fieldIt->dump(), fieldName),
451                 fieldPath);
452         }
453 
454         return Result::WRONG_TYPE;
455     }
456 
457     // Extract value
458     output = *retVal;
459 
460     return Result::SUCCESS;
461 }
462 
463 Result getDouble(const char* fieldName, const nlohmann::json& json,
464                  double& output, uint8_t msgCfgMap, nlohmann::json& msgJson,
465                  const std::string&& fieldPath)
466 {
467     // Find field
468     auto fieldIt = json.find(fieldName);
469 
470     // Verify existence
471     if (fieldIt == json.end())
472     {
473         if (msgCfgMap & static_cast<int>(MessageSetting::MISSING))
474         {
475             messages::addMessageToJson(
476                 msgJson, messages::propertyMissing(fieldName), fieldPath);
477         }
478 
479         return Result::NOT_EXIST;
480     }
481 
482     const double* retVal = fieldIt->get_ptr<const double*>();
483 
484     // Verify type - we know that it exists, so nullptr means wrong type
485     if (retVal == nullptr)
486     {
487         if (msgCfgMap & static_cast<int>(MessageSetting::TYPE_ERROR))
488         {
489             messages::addMessageToJson(
490                 msgJson,
491                 messages::propertyValueTypeError(fieldIt->dump(), fieldName),
492                 fieldPath);
493         }
494 
495         return Result::WRONG_TYPE;
496     }
497 
498     // Extract value
499     output = *retVal;
500 
501     return Result::SUCCESS;
502 }
503 
504 bool processJsonFromRequest(crow::Response& res, const crow::Request& req,
505                             nlohmann::json& reqJson)
506 {
507     reqJson = nlohmann::json::parse(req.body, nullptr, false);
508 
509     if (reqJson.is_discarded())
510     {
511         messages::addMessageToErrorJson(res.jsonValue,
512                                         messages::malformedJSON());
513 
514         res.result(boost::beast::http::status::bad_request);
515         res.end();
516 
517         return false;
518     }
519 
520     return true;
521 }
522 
523 } // namespace json_util
524 
525 } // namespace redfish
526