-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathControllerInputValidator.hpp
188 lines (160 loc) · 5.47 KB
/
ControllerInputValidator.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
/**
*@file ControllerInputValidator.hpp
* @author Fabio Rossini Sluzala ()
* @brief Implementação de templates para rodar a validação de campos de json
* @version 0.1
* @date 2021-08-04
*
* @copyright Copyright (c) 2021
*
*/
#pragma once
#ifndef CONTROLLERINPUTVALIDATOR_HPP
#define CONTROLLERINPUTVALIDATOR_HPP
#include "InputValidators.hpp"
class ControllerInputValidator {
const Poco::JSON::Object::Ptr parameters;
Poco::JSON::Object::Ptr resultadofinal;
Poco::JSON::Object::Ptr resobj;
bool validation_failed{};
public:
std::string RESULT{"resultado"};
std::string SUCCESS{"sucesso"};
std::string MESSAGE{"mensagem"};
std::string DEFAULT_MESSAGE{"Falha na validação de um ou mais campos"};
std::string UNKNOWN_FIELD{"Não é um parâmetro reconhecido"};
/**
*@brief pequeno helper que recebe um pair e guarda o first como
*std::string_view, criado para ser usado em conjunto com
*find_values_not_in_list para testar se um campo json está fora da lista de
*validação
*
*/
struct pair_first {
std::string_view str;
auto operator==(const std::string &strtocmp) const -> bool {
return strtocmp == str;
}
// NOLINTNEXTLINE(hicpp-explicit-conversions)
template <class P> pair_first(const P &pair) : str(pair.first) {}
};
static void push_validation_msg(const Poco::Dynamic::Var &var,
Poco::JSON::Array &data) {
if (var.isEmpty()) {
return;
}
data.add(var);
}
/**
*@brief Registra mensagens de erro de validação
*
* @param fieldname nome do campo
* @param arr lista de mensagens de erro
*/
void push_val_list(std::string_view fieldname,
const Poco::JSON::Array &arr) {
if (arr.size() == 0) {
return;
}
/**
*@brief "Lazy pointer", alocando apenas se houver necessidade
*
*/
if (resultadofinal.isNull()) {
resultadofinal = new Poco::JSON::Object;
resultadofinal->set(SUCCESS, false);
resultadofinal->set(MESSAGE, DEFAULT_MESSAGE);
}
if (resobj.isNull()) {
resobj = new Poco::JSON::Object;
}
validation_failed = true;
resobj->set(fieldname.data(), arr);
}
/**
*@brief Efetua validação de um campo específico do json e grava os erros de
*validação
*
* @tparam Types InputValidator
* @param fieldname nome do campo
* @param args sequencia de objetos de validadores para serem testados com
*os dados do campo
* @return true um ou mais validadores falharam
* @return false não houveram falhas
*/
template <class... Types>
auto validate_input(std::string_view fieldname, Types... args) -> bool {
const Poco::Dynamic::Var data = parameters->get(fieldname.data());
Poco::JSON::Array result;
((push_validation_msg(args.validate(fieldname, data), result)), ...);
bool failed = result.size() > 0;
push_val_list(fieldname, result);
return failed;
}
template <class N, class T>
auto validate_input_custom(N name, T data) -> bool {
return std::apply(
[&](auto &&...validation_list) {
return validate_input(name, validation_list...);
},
data);
}
/**
*@brief Valida se o json possui campos que não estão na lista de validação
*
* @tparam Types std::pair(std::string_view, {...})...
* @param args std::pair(nome_campo, std::tuple{ validadores })...
* @return auto .
*/
template <class... Types> auto find_values_not_in_list(Types... args) {
const std::array<pair_first,
std::tuple_size<std::tuple<Types...>>::value>
valid = {std::forward<Types>(args)...};
for (const auto &item : *parameters) {
auto itval = std::find(valid.begin(), valid.end(), item.first);
if (itval == valid.end()) {
Poco::JSON::Array resultmsg;
resultmsg.add(UNKNOWN_FIELD);
push_val_list(item.first, resultmsg);
}
}
}
/**
*@brief Valida os tipos dos parâmetros do json e valida se há parâmetros
*desconhecidos
*
* @tparam Types std::pair(std::string_view, {...})...
* @param args std::pair(nome_campo, std::tuple{ validadores })...
* @return true ocorreu um erro
* @return false não foi encontrado problema
*/
template <class... Types> auto full_validation(Types... args) -> bool {
bool result = false;
((result |= validate_input_custom(args.first, args.second)), ...);
find_values_not_in_list(std::forward<Types>(args)...);
return result;
}
/**
*@brief Recebe um json de resposta ao usuário
*
* @return auto Poco::JSON::Object::Ptr
*/
auto get_response() {
if (!resultadofinal.isNull()) {
resultadofinal->set(RESULT, resobj);
}
return resultadofinal;
}
auto get_only_messages() { return resobj; }
/**
*@brief Construct a new Controller Input Validator object
*
* @param inputvalues json com os dados para serem validados
*/
explicit ControllerInputValidator(
const Poco::JSON::Object::Ptr &inputvalues)
: parameters(inputvalues) {
validation_failed = false;
}
};
#endif