Line data Source code
1 : /**
2 : * Copyright Soramitsu Co., Ltd. All Rights Reserved.
3 : * SPDX-License-Identifier: Apache-2.0
4 : */
5 :
6 : #include <boost/algorithm/string.hpp>
7 : #include <fstream>
8 :
9 : #include "backend/protobuf/queries/proto_query.hpp"
10 :
11 : #include "client.hpp"
12 : #include "common/byteutils.hpp"
13 : #include "crypto/keys_manager_impl.hpp"
14 : #include "cryptography/ed25519_sha3_impl/internal/ed25519_impl.hpp"
15 : #include "datetime/time.hpp"
16 : #include "grpc_response_handler.hpp"
17 : #include "interactive/interactive_query_cli.hpp"
18 : #include "logger/logger.hpp"
19 : #include "model/converters/json_query_factory.hpp"
20 : #include "model/converters/pb_query_factory.hpp"
21 : #include "model/model_crypto_provider.hpp" // for ModelCryptoProvider
22 : #include "model/queries/get_asset_info.hpp"
23 : #include "model/queries/get_roles.hpp"
24 : #include "model/sha3_hash.hpp"
25 :
26 : using namespace iroha::model;
27 :
28 : namespace iroha_cli {
29 : namespace interactive {
30 :
31 : void InteractiveQueryCli::create_queries_menu() {
32 0 : description_map_ = {
33 0 : {GET_ACC, "Get Account Information"},
34 0 : {GET_ACC_AST, "Get Account's Assets"},
35 0 : {GET_ACC_AST_TX, "Get Account's Asset Transactions"},
36 0 : {GET_ACC_TX, "Get Account's Transactions"},
37 0 : {GET_TX, "Get Transactions by transactions' hashes"},
38 0 : {GET_ACC_SIGN, "Get Account's Signatories"},
39 0 : {GET_ROLES, "Get all current roles in the system"},
40 0 : {GET_AST_INFO, "Get information about asset"},
41 0 : {GET_ROLE_PERM, "Get all permissions related to role"}
42 : // description_map_
43 : };
44 :
45 0 : const auto acc_id = "Requested account Id";
46 0 : const auto ast_id = "Requested asset Id";
47 0 : const auto role_id = "Requested role name";
48 0 : const auto tx_hashes = "Requested tx hashes";
49 :
50 0 : query_params_map_ = {
51 0 : {GET_ACC, makeParamsDescription({acc_id})},
52 0 : {GET_ACC_AST, makeParamsDescription({acc_id, ast_id})},
53 0 : {GET_ACC_AST_TX, makeParamsDescription({acc_id, ast_id})},
54 0 : {GET_ACC_TX, makeParamsDescription({acc_id})},
55 0 : {GET_TX, makeParamsDescription({tx_hashes})},
56 0 : {GET_ACC_SIGN, makeParamsDescription({acc_id})},
57 0 : {GET_ROLES, makeParamsDescription({})},
58 0 : {GET_AST_INFO, makeParamsDescription({ast_id})},
59 0 : {GET_ROLE_PERM, makeParamsDescription({role_id})}
60 : // query_params_map_
61 : };
62 :
63 0 : query_handlers_ = {
64 0 : {GET_ACC, &InteractiveQueryCli::parseGetAccount},
65 0 : {GET_ACC_AST, &InteractiveQueryCli::parseGetAccountAssets},
66 0 : {GET_ACC_AST_TX,
67 0 : &InteractiveQueryCli::parseGetAccountAssetTransactions},
68 0 : {GET_ACC_TX, &InteractiveQueryCli::parseGetAccountTransactions},
69 0 : {GET_TX, &InteractiveQueryCli::parseGetTransactions},
70 0 : {GET_ACC_SIGN, &InteractiveQueryCli::parseGetSignatories},
71 0 : {GET_ROLE_PERM, &InteractiveQueryCli::parseGetRolePermissions},
72 0 : {GET_ROLES, &InteractiveQueryCli::parseGetRoles},
73 0 : {GET_AST_INFO, &InteractiveQueryCli::parseGetAssetInfo}
74 : // query_handlers_
75 : };
76 0 :
77 0 : menu_points_ =
78 0 : formMenu(query_handlers_, query_params_map_, description_map_);
79 0 : // Add "go back" option
80 0 : addBackOption(menu_points_);
81 0 : }
82 0 :
83 : void InteractiveQueryCli::create_result_menu() {
84 0 : result_handlers_ = {{SAVE_CODE, &InteractiveQueryCli::parseSaveFile},
85 0 : {SEND_CODE, &InteractiveQueryCli::parseSendToIroha}};
86 0 : result_params_map_ = getCommonParamsMap(default_peer_ip_, default_port_);
87 :
88 0 : result_points_ = formMenu(
89 0 : result_handlers_, result_params_map_, getCommonDescriptionMap());
90 0 : addBackOption(result_points_);
91 0 : }
92 :
93 : InteractiveQueryCli::InteractiveQueryCli(
94 : const std::string &account_name,
95 : const std::string &default_peer_ip,
96 : int default_port,
97 : uint64_t query_counter,
98 : const std::shared_ptr<iroha::model::ModelCryptoProvider> &provider,
99 : logger::LoggerManagerTreePtr response_handler_log_manager,
100 : logger::LoggerPtr pb_qry_factory_log,
101 : logger::LoggerPtr json_qry_factory_log,
102 : logger::LoggerPtr log)
103 0 : : current_context_(MAIN),
104 0 : creator_(account_name),
105 0 : default_peer_ip_(default_peer_ip),
106 0 : default_port_(default_port),
107 0 : counter_(query_counter),
108 0 : provider_(provider),
109 0 : response_handler_log_manager_(
110 0 : std::move(response_handler_log_manager)),
111 0 : pb_qry_factory_log_(std::move(pb_qry_factory_log)),
112 0 : json_qry_factory_log_(std::move(json_qry_factory_log)),
113 0 : log_(std::move(log)) {
114 0 : create_queries_menu();
115 0 : create_result_menu();
116 0 : }
117 :
118 : static void printMenu(const MenuPoints &menu) {
119 0 : printMenu("Choose query: ", menu);
120 0 : }
121 :
122 : void InteractiveQueryCli::run() {
123 0 : bool is_parsing = true;
124 0 : current_context_ = MAIN;
125 0 : printMenu(menu_points_);
126 : // Creating a new query, increment local counter
127 0 : ++counter_;
128 : // Init timestamp for a new query
129 0 : local_time_ = iroha::time::now();
130 :
131 0 : while (is_parsing) {
132 0 : auto line = promptString("> ");
133 0 : if (not line) {
134 : // The promtSting returns error, terminating symbol
135 0 : is_parsing = false;
136 0 : break;
137 : }
138 0 : switch (current_context_) {
139 : case MAIN:
140 0 : is_parsing = parseQuery(line.value());
141 0 : break;
142 : case RESULT:
143 0 : is_parsing = parseResult(line.value());
144 0 : break;
145 : default:
146 0 : BOOST_ASSERT_MSG(false, "not implemented");
147 : }
148 0 : }
149 0 : }
150 :
151 : bool InteractiveQueryCli::parseQuery(std::string line) {
152 0 : if (isBackOption(line)) {
153 : // Stop parsing
154 0 : return false;
155 : }
156 :
157 0 : auto res = handleParse<std::shared_ptr<iroha::model::Query>>(
158 0 : this, line, query_handlers_, query_params_map_);
159 0 : if (not res) {
160 : // Continue parsing
161 0 : return true;
162 : }
163 :
164 0 : query_ = res.value();
165 0 : current_context_ = RESULT;
166 0 : printMenu("Query is formed. Choose what to do:", result_points_);
167 : // Continue parsing
168 0 : return true;
169 0 : }
170 :
171 : std::shared_ptr<iroha::model::Query> InteractiveQueryCli::parseGetAccount(
172 : QueryParams params) {
173 0 : auto account_id = params[0];
174 0 : return generator_.generateGetAccount(
175 0 : local_time_, creator_, counter_, account_id);
176 0 : }
177 :
178 : std::shared_ptr<iroha::model::Query>
179 : InteractiveQueryCli::parseGetAccountAssets(QueryParams params) {
180 0 : auto account_id = params[0];
181 0 : auto asset_id = params[1];
182 0 : return generator_.generateGetAccountAssets(
183 0 : local_time_, creator_, counter_, account_id, asset_id);
184 0 : }
185 :
186 : std::shared_ptr<iroha::model::Query>
187 : InteractiveQueryCli::parseGetAccountAssetTransactions(QueryParams params) {
188 0 : auto account_id = params[0];
189 0 : auto asset_id = params[1];
190 0 : return generator_.generateGetAccountAssetTransactions(
191 0 : local_time_, creator_, counter_, account_id, asset_id);
192 0 : }
193 :
194 : std::shared_ptr<iroha::model::Query>
195 : InteractiveQueryCli::parseGetAccountTransactions(QueryParams params) {
196 0 : auto account_id = params[0];
197 0 : return generator_.generateGetAccountTransactions(
198 0 : local_time_, creator_, counter_, account_id);
199 0 : }
200 :
201 : std::shared_ptr<iroha::model::Query>
202 : InteractiveQueryCli::parseGetTransactions(QueryParams params) {
203 : // Parser definition: hash1 hash2 ...
204 0 : GetTransactions::TxHashCollectionType tx_hashes;
205 0 : std::for_each(
206 : params.begin(), params.end(), [&tx_hashes](auto const &hex_hash) {
207 0 : if (auto opt = iroha::hexstringToArray<
208 0 : GetTransactions::TxHashType::size()>(hex_hash)) {
209 0 : tx_hashes.push_back(*opt);
210 0 : }
211 0 : });
212 0 : return generator_.generateGetTransactions(
213 0 : local_time_, creator_, counter_, tx_hashes);
214 0 : }
215 :
216 : std::shared_ptr<iroha::model::Query>
217 : InteractiveQueryCli::parseGetSignatories(QueryParams params) {
218 0 : auto account_id = params[0];
219 0 : return generator_.generateGetSignatories(
220 0 : local_time_, creator_, counter_, account_id);
221 0 : }
222 :
223 : std::shared_ptr<iroha::model::Query> InteractiveQueryCli::parseGetAssetInfo(
224 : QueryParams params) {
225 0 : auto asset_id = params[0];
226 0 : auto query = std::make_shared<GetAssetInfo>(asset_id);
227 : // TODO 26/09/17 grimadas: remove duplicated code and move
228 : // setQueryMetaData calls to private method IR-508 #goodfirstissue
229 0 : generator_.setQueryMetaData(query, local_time_, creator_, counter_);
230 0 : return query;
231 0 : }
232 :
233 : std::shared_ptr<iroha::model::Query> InteractiveQueryCli::parseGetRoles(
234 : QueryParams params) {
235 0 : auto query = std::make_shared<GetRoles>();
236 0 : generator_.setQueryMetaData(query, local_time_, creator_, counter_);
237 0 : return query;
238 0 : }
239 :
240 : std::shared_ptr<iroha::model::Query>
241 : InteractiveQueryCli::parseGetRolePermissions(QueryParams params) {
242 0 : auto role_name = params[0];
243 0 : auto query = std::make_shared<GetRolePermissions>(role_name);
244 0 : generator_.setQueryMetaData(query, local_time_, creator_, counter_);
245 0 : return query;
246 0 : }
247 :
248 : bool InteractiveQueryCli::parseResult(std::string line) {
249 0 : if (isBackOption(line)) {
250 : // Give up the last query and start a new one
251 0 : current_context_ = MAIN;
252 0 : printEnd();
253 0 : printMenu(menu_points_);
254 : // Continue parsing
255 0 : return true;
256 : }
257 :
258 : auto res =
259 0 : handleParse<bool>(this, line, result_handlers_, result_params_map_);
260 :
261 0 : return res.get_value_or(true);
262 0 : }
263 :
264 : bool InteractiveQueryCli::parseSendToIroha(QueryParams params) {
265 : auto address =
266 0 : parseIrohaPeerParams(params, default_peer_ip_, default_port_);
267 0 : if (not address) {
268 0 : return true;
269 : }
270 :
271 0 : provider_->sign(*query_);
272 :
273 0 : CliClient client(
274 0 : address.value().first, address.value().second, pb_qry_factory_log_);
275 0 : auto query = shared_model::proto::Query(
276 0 : *iroha::model::converters::PbQueryFactory(pb_qry_factory_log_)
277 0 : .serialize(query_));
278 0 : GrpcResponseHandler{response_handler_log_manager_}.handle(
279 0 : client.sendQuery(query));
280 0 : printEnd();
281 : // Stop parsing
282 0 : return false;
283 0 : }
284 :
285 : bool InteractiveQueryCli::parseSaveFile(QueryParams params) {
286 0 : provider_->sign(*query_);
287 :
288 0 : auto path = params[0];
289 0 : iroha::model::converters::JsonQueryFactory json_factory(
290 0 : json_qry_factory_log_);
291 0 : auto json_string = json_factory.serialize(query_);
292 0 : std::ofstream output_file(path);
293 0 : if (not output_file) {
294 0 : std::cout << "Cannot create file" << std::endl;
295 : // Continue parsing
296 0 : return true;
297 : }
298 0 : output_file << json_string;
299 0 : std::cout << "Successfully saved!" << std::endl;
300 0 : printEnd();
301 : // Stop parsing
302 0 : return false;
303 0 : }
304 :
305 : } // namespace interactive
306 : } // namespace iroha_cli
|