identt
ParamLookupService.hpp
Go to the documentation of this file.
1 
33 #ifndef _IDENTT_QUERY_PARAM_LOOKUP_SERVICE_HPP_
34 #define _IDENTT_QUERY_PARAM_LOOKUP_SERVICE_HPP_
35 
36 #include <query/QueryBase.hpp>
38 #include <store/LookupService.hpp>
39 
40 // #include <rapidjson/rapidjson.h>
41 #include <rapidjson/writer.h>
42 #include <rapidjson/stringbuffer.h>
43 #include <rapidjson/pointer.h>
44 
45 namespace identt {
46 namespace query {
47 
48 template <class HttpServerT>
50  public identt::query::ServiceBase<HttpServerT> {
51 public:
52 
73  identt::utils::SharedTable::pointer stptr,
74  typename std::shared_ptr<HttpServerT> server,
75  ::identt::query::HelpQuery::pointer helpquery,
76  unsigned int scope)
77  : identt::query::ServiceBase<HttpServerT>(IDENTT_SERVICE_SCOPE_HTTP | IDENTT_SERVICE_SCOPE_HTTPS)
78  {
79  if (!(this->myscope & scope)) return; // scope mismatch
80 
81  // Endpoint : POST _matrix/identity/api/v1/lookup_params
82  helpquery->add({scope,"POST _matrix/identity/api/v1/lookup_params", {
83  "Look up the Matrix user ID for a 3pid.",
84  "query parameters: medium, address",
85  "medium Required. The literal string email.",
86  "address Required. The email address being looked up.",
87  "accesskey Required if lookup_requires_accesskey is set.",
88  "This variant sends back additional parameters from Params"
89  }
90  });
91 
92  server->resource["/_matrix/identity/api/v1/lookup_params$"]["POST"]
93  =[this,stptr](typename HttpServerT::RespPtr response, typename HttpServerT::ReqPtr request) {
94  IDENTT_PARALLEL_ONE([this,stptr,response,request] {
95  try {
96  LOG(INFO) << request->path;
97  std::string err;
98  bool use_json = this->JsonRequest(request);
99 
100  identt::query::LookupDataT lact;
101  if (use_json)
102  {
103  int stat = json2pb( request->content.string() , lact.mutable_query() , err);
104  if (stat<0) throw SydentException("Bad Json Format",M_BAD_JSON);
105  } else {
106  form2pb( request->content.string() , lact.mutable_query() ); // throws on error
107  }
108  if (!stptr->is_ready.Get()) throw identt::BadDataException("System Not Ready");
109 
110  // action
111 
112  // if accesskey is shared_secret it is server request, else check
113  if (stptr->lookup_requires_key.Get()) {
114  bool is_server_query = false;
115  auto it=request->header.find("Shared-Secret");
116  if (it!=request->header.end()) {
117  is_server_query = (it->second == stptr->shared_secret.Get());
118  }
119  if (!is_server_query ) {
121  aservice.VerifyAccessKeyAction(stptr, lact.mutable_query()->accesskey());
122  }
123  }
124 
126  lservice.LookupAction(stptr, &lact);
127 
128  // aftermath
129  std::string output;
130  ::identt::query::PubKeyT pubkey;
131 
132  // set owners
133  pubkey.set_owner(stptr->hostname.Get());
134  pubkey.set_algo(THREEPID_DEFAULT_ALGO);
135  pubkey.set_identifier(THREEPID_DEFAULT_ALGO_ID);
136 
137  // test data
138  std::vector<::identt::query::SignatureT> signatures;
139  lservice.AddSign(stptr, lact.mutable_result() , &pubkey, output,signatures);
140  if (!output.length()) output="{}";
141 
142  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
143  } catch (SydentException& e)
144  {
145  int ecode = (e.ecode()>=IDENTT_SYDENT_ERROR_MIN && e.ecode()<=IDENTT_SYDENT_ERROR_MAX) ? e.ecode() : M_UNKNOWN;
146  std::string output = err2json(SydentErrors.at(ecode),e.what());
147  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
148  } catch (identt::JdException& e)
149  {
150  std::string output = err2json(SydentErrors.at(M_UNKNOWN),e.what());
151  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
152  } catch (std::exception& e)
153  {
154  std::string output = err2json(SydentErrors.at(M_UNKNOWN),e.what());
155  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
156  } catch (...)
157  {
158  this->HttpErrorAction(response,request,500,"INTERNAL SERVER ERROR");
159  }
160  });
161  };
162 
163  // Endpoint : GET _matrix/identity/api/v1/lookup_params
164  helpquery->add({scope,"GET _matrix/identity/api/v1/lookup_params", {
165  "Look up the Matrix user ID for a 3pid.",
166  "This is the GET version of lookup_params",
167  "query parameters: medium, address",
168  "medium Required. The literal string email.",
169  "address Required. The email address being looked up.",
170  "accesskey Required if lookup_requires_accesskey is set.",
171  "This variant sends back additional parameters from Params"
172  }
173  });
174 
175  server->resource["/_matrix/identity/api/v1/lookup_params\\\?(.*)$"]["GET"]
176  =[this,stptr](typename HttpServerT::RespPtr response, typename HttpServerT::ReqPtr request) {
177  IDENTT_PARALLEL_ONE([this,stptr,response,request] {
178  try {
179  LOG(INFO) << request->path;
180  std::string err;
181  std::string params = request->path_match[1];
182  identt::query::LookupDataT lact;
183  form2pb( params , lact.mutable_query()); // throws on error
184 
185  if (!stptr->is_ready.Get()) throw identt::BadDataException("System Not Ready");
186 
187  // action
188 
189  // if accesskey is shared_secret it is server request, else check
190  if (stptr->lookup_requires_key.Get()) {
191  bool is_server_query = false;
192  auto it=request->header.find("Shared-Secret");
193  if (it!=request->header.end()) {
194  is_server_query = (it->second == stptr->shared_secret.Get());
195  }
196  if (!is_server_query ) {
198  aservice.VerifyAccessKeyAction(stptr, lact.mutable_query()->accesskey());
199  }
200  }
201 
203  lservice.LookupAction(stptr, &lact);
204 
205  // aftermath
206  std::string output;
207  ::identt::query::PubKeyT pubkey;
208 
209  // set owners
210  pubkey.set_owner(stptr->hostname.Get());
211  pubkey.set_algo(THREEPID_DEFAULT_ALGO);
212  pubkey.set_identifier(THREEPID_DEFAULT_ALGO_ID);
213 
214  // test data
215  std::vector<::identt::query::SignatureT> signatures;
216  lservice.AddSign(stptr, lact.mutable_result() , &pubkey, output,signatures);
217 
218  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
219  } catch (SydentException& e)
220  {
221  int ecode = (e.ecode()>=IDENTT_SYDENT_ERROR_MIN && e.ecode()<=IDENTT_SYDENT_ERROR_MAX) ? e.ecode() : M_UNKNOWN;
222  std::string output = err2json(SydentErrors.at(ecode),e.what());
223  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
224  } catch (identt::JdException& e)
225  {
226  std::string output = err2json(SydentErrors.at(M_UNKNOWN),e.what());
227  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
228  } catch (std::exception& e)
229  {
230  std::string output = err2json(SydentErrors.at(M_UNKNOWN),e.what());
231  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
232  } catch (...)
233  {
234  this->HttpErrorAction(response,request,500,"INTERNAL SERVER ERROR");
235  }
236  });
237  };
238 
239  // Endpoint : POST _matrix/identity/api/v1/bulk_lookup_params
240  helpquery->add({scope,"POST _matrix/identity/api/v1/bulk_lookup_params", {
241  "Look up the Matrix user ID for a list of 3pid.",
242  "query parameters: list of {medium, address}",
243  "medium Required. The literal string email.",
244  "address Required. The email address being looked up.",
245  "accesskey Required if lookup_requires_accesskey is set.",
246  "This variant sends back additional parameters from Params"
247  }
248  });
249 
250  server->resource["/_matrix/identity/api/v1/bulk_lookup_params$"]["POST"]
251  =[this,stptr](typename HttpServerT::RespPtr response, typename HttpServerT::ReqPtr request) {
252  IDENTT_PARALLEL_ONE([this,stptr,response,request] {
253  try {
254  LOG(INFO) << request->path;
255  std::string err;
256  bool use_json = this->JsonRequest(request);
257 
258  identt::query::BulkLookupDataT blact;
259  if (use_json)
260  {
261  int stat = json2pb( request->content.string() , blact.mutable_query() , err);
262  if (stat<0) throw SydentException("Bad Json Format",M_BAD_JSON);
263  } else {
264  throw SydentException("Only Json Supported",M_BAD_JSON);
265  }
266  DLOG(INFO) << blact.DebugString();
267  if (!stptr->is_ready.Get()) throw identt::BadDataException("System Not Ready");
268 
269  // action
270 
271  // if accesskey is shared_secret it is server request, else check
272  if (stptr->lookup_requires_key.Get()) {
273  bool is_server_query = false;
274  auto it=request->header.find("Shared-Secret");
275  if (it!=request->header.end()) {
276  is_server_query = (it->second == stptr->shared_secret.Get());
277  }
278  if (!is_server_query ) {
280  aservice.VerifyAccessKeyAction(stptr, blact.mutable_query()->accesskey());
281  }
282  }
283 
285  lservice.BulkLookupAction(stptr, &blact);
286  std::string instring;
287  this->BulkLookupJson(blact.mutable_result(),instring);
288 
289  // aftermath
290  std::string output;
291  ::identt::query::PubKeyT pubkey;
292 
293  // set owners
294  pubkey.set_owner(stptr->hostname.Get());
295  pubkey.set_algo(THREEPID_DEFAULT_ALGO);
296  pubkey.set_identifier(THREEPID_DEFAULT_ALGO_ID);
297 
298 
299  // test data
300 
301  std::vector<::identt::query::SignatureT> signatures;
302  lservice.AddSign(stptr, instring , &pubkey, output,signatures);
303  if (!output.length()) output="{}";
304 
305  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
306  } catch (SydentException& e)
307  {
308  int ecode = (e.ecode()>=IDENTT_SYDENT_ERROR_MIN && e.ecode()<=IDENTT_SYDENT_ERROR_MAX) ? e.ecode() : M_UNKNOWN;
309  std::string output = err2json(SydentErrors.at(ecode),e.what());
310  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
311  } catch (identt::JdException& e)
312  {
313  std::string output = err2json(SydentErrors.at(M_UNKNOWN),e.what());
314  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
315  } catch (std::exception& e)
316  {
317  std::string output = err2json(SydentErrors.at(M_UNKNOWN),e.what());
318  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
319  } catch (...)
320  {
321  this->HttpErrorAction(response,request,500,"INTERNAL SERVER ERROR");
322  }
323  });
324  };
325 
326  }
327 
328 private:
341  void BulkLookupJson(identt::query::BulkLookupResultT* bulkres, std::string& output)
342  {
344  rapidjson::Document::AllocatorType& allocator = d.GetAllocator();
345  rapidjson::Pointer("/threepids").Create(d , allocator );
346  rapidjson::Value* threepids = rapidjson::Pointer("/threepids").Get(d);
347  if (!threepids->IsArray()) threepids->SetArray();
348 
349  for (auto& res : bulkres->threepids() ) {
351  entry
352  .PushBack( rapidjson::StringRef( res.medium().c_str() ) , allocator )
353  .PushBack( rapidjson::StringRef( res.address().c_str() ) , allocator )
354  .PushBack( rapidjson::StringRef( res.mxid().c_str() ) , allocator );
355  threepids->PushBack(entry,allocator);
356  }
357  rapidjson::StringBuffer buffer;
358  rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
359  d.Accept(writer);
360  output.clear();
361  output.append(buffer.GetString(), buffer.GetSize());
362  }
363 
364 };
365 } // namespace query
366 } // namespace identt
367 
368 #endif // _IDENTT_QUERY_PARAM_LOOKUP_SERVICE_HPP_
void HttpOKAction(typename HttpServerT::RespPtr response, typename HttpServerT::ReqPtr request, int ec, const char *em, const char *content_type, std::string &payload, bool add_cors)
HttpOKAction : OK Action template.
Definition: ServiceBase.hpp:154
ParamLookupService(identt::utils::SharedTable::pointer stptr, typename std::shared_ptr< HttpServerT > server, ::identt::query::HelpQuery::pointer helpquery, unsigned int scope)
ParamLookupService : constructor.
Definition: ParamLookupService.hpp:72
Allocator AllocatorType
Allocator type from template parameter.
Definition: document.h:2078
array
Definition: rapidjson.h:608
Sydent Exceptions.
Definition: SydentQuery.hpp:91
void HttpErrorAction(typename HttpServerT::RespPtr response, typename HttpServerT::ReqPtr request, int ec, const char *em)
HttpErrorAction : Error Action Template no payload maybe template.
Definition: ServiceBase.hpp:85
Definition: BaseUtils.hpp:52
GenericValue< UTF8<> > Value
GenericValue with UTF8 encoding.
Definition: document.h:2060
Definition: ServiceBase.hpp:55
Definition: CryptoBase.hpp:49
GenericDocument< UTF8<> > Document
GenericDocument with UTF8 encoding.
Definition: document.h:2452
Definition: BaseUtils.hpp:89
void BulkLookupAction(::identt::utils::SharedTable::pointer stptr, ::identt::query::BulkLookupDataT *blact)
BulkLookupAction : Service Endpoint Lookup.
Definition: LookupService.cc:62
void form2pb(const std::string &form, google::protobuf::Message *msg)
form2pb : Convert url-encoded form to protobuf
Definition: ProtoForm.cc:129
GenericStringRef< CharType > StringRef(const CharType *str)
Mark a character pointer as constant string.
Definition: document.h:354
void VerifyAccessKeyAction(::identt::utils::SharedTable::pointer stptr, std::string akey)
VerifyAccessKeyAction : verify the access key.
Definition: AccessKeyService.cc:44
Definition: LookupService.hpp:43
std::string err2json(const std::string errorcode, const std::string error)
err2json : Generate a Json for Error Message
Definition: ProtoJson.cc:511
void AddSign(::identt::utils::SharedTable::pointer stptr, const google::protobuf::Message *result, const ::identt::query::PubKeyT *pubkey, std::string &output, SignatureListT &signatures)
AddSign: Add Signature pb, also adds older signatures.
bool JsonRequest(typename HttpServerT::ReqPtr request)
JsonRequest : Check if request is json from Content-Type and Accept fields.
Definition: ServiceBase.hpp:178
Definition: ParamLookupService.hpp:49
void LookupAction(::identt::utils::SharedTable::pointer stptr, ::identt::query::LookupDataT *lact)
LookupAction : Service Endpoint Lookup.
Definition: LookupService.cc:47
int json2pb(const std::string &json, google::protobuf::Message *msg, std::string &err)
json2pb : Convert json to protobuf
Definition: ProtoJson.cc:446
Definition: AccessKeyService.hpp:42