identt
BlobDataService.hpp
Go to the documentation of this file.
1 
33 #ifndef _IDENTT_QUERY_BLOBDATA_SERVICE_HPP_
34 #define _IDENTT_QUERY_BLOBDATA_SERVICE_HPP_
35 
36 #include <query/QueryBase.hpp>
38 #include <hrpc/HrpcClient.hpp>
39 
40 #include <rapidjson/writer.h>
41 #include <rapidjson/stringbuffer.h>
42 #include <rapidjson/pointer.h>
43 
44 namespace identt {
45 namespace query {
46 
47 template <class HttpServerT>
48 class BlobDataService : public identt::query::ServiceBase<HttpServerT> {
49 public:
50 
71  identt::utils::SharedTable::pointer stptr,
72  typename std::shared_ptr<HttpServerT> server,
73  ::identt::query::HelpQuery::pointer helpquery,
74  unsigned int scope)
75  : identt::query::ServiceBase<HttpServerT>(IDENTT_SERVICE_SCOPE_HTTP | IDENTT_SERVICE_SCOPE_HTTPS)
76  {
77  if (!(this->myscope & scope)) return; // scope mismatch
78 
79  // Endpoint : POST _identt/identity/api/v1/blobdata/getAccessKey
80  helpquery->add({scope,"POST _identt/identity/api/v1/blobdata/getAccessKey", {
81  "This is the POST version of getAccessKey",
82  "A client can get access key for storing arbitrary json data by getting an access key",
83  "params : sid , client_secret",
84  "returns the access key if ok"
85  }
86  });
87  server->resource["/_identt/identity/api/v1/blobdata/getAccessKey$"]["POST"]
88  =[this,stptr](typename HttpServerT::RespPtr response, typename HttpServerT::ReqPtr request) {
89  IDENTT_PARALLEL_ONE([this,stptr,response,request] {
90  try {
91  LOG(INFO) << request->path;
92  std::string err;
93  bool use_json = this->JsonRequest(request);
94 
95  identt::query::GetAccessDataT gva;
96  if (use_json)
97  {
98  int stat = json2pb( request->content.string() , gva.mutable_subtok() , err);
99  if (stat<0) throw SydentException("Bad Json Format",M_BAD_JSON);
100  } else {
101  form2pb( request->content.string() , gva.mutable_subtok()); // throws on error
102  }
103  if (!stptr->is_ready.Get()) throw identt::BadDataException("System Not Ready");
104 
105  // action
106  if (gva.mutable_subtok()->sid().length()==0)
107  throw ::identt::query::SydentException("sid value required", M_MISSING_PARAMS);
108  if (gva.mutable_subtok()->client_secret().length()==0)
109  throw ::identt::query::SydentException("client_secret value required", M_MISSING_PARAMS);
110 
111  if (stptr->is_master.Get())
112  {
114  bservice.GetAccessKeyAction(stptr, &gva);
115  } else {
116  identt::hrpc::HrpcClient hclient;
117  hclient.SendToMaster(stptr,::identt::hrpc::M_GETACCESSKEY,&gva);
118  }
119 
120  // aftermath
121  std::string output;
122  pb2json(gva.mutable_accessblob() , output);
123  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
124  } catch (SydentException& e)
125  {
126  int ecode = (e.ecode()>=IDENTT_SYDENT_ERROR_MIN && e.ecode()<=IDENTT_SYDENT_ERROR_MAX) ? e.ecode() : M_UNKNOWN;
127  std::string output = err2json(SydentErrors.at(ecode),e.what());
128  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
129  } catch (identt::JdException& e)
130  {
131  std::string output = err2json(SydentErrors.at(M_UNKNOWN),e.what());
132  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
133  } catch (std::exception& e)
134  {
135  std::string output = err2json(SydentErrors.at(M_UNKNOWN),e.what());
136  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
137  } catch (...)
138  {
139  this->HttpErrorAction(response,request,500,"INTERNAL SERVER ERROR");
140  }
141  });
142  };
143 
144  // Endpoint : GET _identt/identity/api/v1/blobdata/getAccessKey
145  helpquery->add({scope,"GET _identt/identity/api/v1/blobdata/getAccessKey", {
146  "This is the GET version of getAccessKey",
147  "A client can get access key for storing arbitrary json data by getting an access key",
148  "params : sid , client_secret",
149  "returns the access key if ok"
150  }
151  });
152 
153  server->resource["/_identt/identity/api/v1/blobdata/getAccessKey\\\?(.*)$"]["GET"]
154  =[this,stptr](typename HttpServerT::RespPtr response, typename HttpServerT::ReqPtr request) {
155  IDENTT_PARALLEL_ONE([this,stptr,response,request] {
156  try {
157  LOG(INFO) << request->path;
158  std::string err;
159  std::string params = request->path_match[1];
160 
161  identt::query::GetAccessDataT gva;
162  form2pb( params , gva.mutable_subtok()); // throws on error
163  if (!stptr->is_ready.Get()) throw identt::BadDataException("System Not Ready");
164 
165  // action
166  if (stptr->is_master.Get())
167  {
169  bservice.GetAccessKeyAction(stptr, &gva);
170  } else {
171  identt::hrpc::HrpcClient hclient;
172  hclient.SendToMaster(stptr,::identt::hrpc::M_GETACCESSKEY,&gva);
173  }
174 
175  // aftermath
176  std::string output;
177  pb2json(gva.mutable_accessblob() , output);
178  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
179  } catch (SydentException& e)
180  {
181  int ecode = (e.ecode()>=IDENTT_SYDENT_ERROR_MIN && e.ecode()<=IDENTT_SYDENT_ERROR_MAX) ? e.ecode() : M_UNKNOWN;
182  std::string output = err2json(SydentErrors.at(ecode),e.what());
183  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
184  } catch (identt::JdException& e)
185  {
186  std::string output = err2json(SydentErrors.at(M_UNKNOWN),e.what());
187  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
188  } catch (std::exception& e)
189  {
190  std::string output = err2json(SydentErrors.at(M_UNKNOWN),e.what());
191  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
192  } catch (...)
193  {
194  this->HttpErrorAction(response,request,500,"INTERNAL SERVER ERROR");
195  }
196  });
197  };
198 
199  // Endpoint : POST _identt/identity/api/v1/blobdata/getBlobData
200  helpquery->add({scope,"POST _identt/identity/api/v1/blobdata/getBlobData", {
201  "This is the POST version of getBlobData",
202  "A client can store arbitrary json data by access key and tag",
203  "params : accesskey, tag",
204  "returns the jsondata and textdata if ok"
205  }
206  });
207  server->resource["/_identt/identity/api/v1/blobdata/getBlobData$"]["POST"]
208  =[this,stptr](typename HttpServerT::RespPtr response, typename HttpServerT::ReqPtr request) {
209  IDENTT_PARALLEL_ONE([this,stptr,response,request] {
210  try {
211  LOG(INFO) << request->path;
212  std::string err;
213  bool use_json = this->JsonRequest(request);
214 
215  identt::query::GetBlobDataT bdata;
216  if (use_json)
217  {
218  int stat = json2pb( request->content.string() , bdata.mutable_accessblob() , err);
219  if (stat<0) throw SydentException("Bad Json Format",M_BAD_JSON);
220  } else {
221  form2pb( request->content.string() , bdata.mutable_accessblob()); // throws on error
222  }
223  if (!stptr->is_ready.Get()) throw identt::BadDataException("System Not Ready");
224 
225  // action
226 
228  bservice.GetBlobDataAction(stptr, &bdata);
229 
230  // aftermath
231  if ( bdata.mutable_accessblob()->accessdenied() ) throw identt::BadDataException("Access Denied");
232  std::string output;
233  this->HandleDataOut(bdata.mutable_accessblob() , output);
234 
235  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
236  } catch (SydentException& e)
237  {
238  int ecode = (e.ecode()>=IDENTT_SYDENT_ERROR_MIN && e.ecode()<=IDENTT_SYDENT_ERROR_MAX) ? e.ecode() : M_UNKNOWN;
239  std::string output = err2json(SydentErrors.at(ecode),e.what());
240  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
241  } catch (identt::JdException& e)
242  {
243  std::string output = err2json(SydentErrors.at(M_UNKNOWN),e.what());
244  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
245  } catch (std::exception& e)
246  {
247  std::string output = err2json(SydentErrors.at(M_UNKNOWN),e.what());
248  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
249  } catch (...)
250  {
251  this->HttpErrorAction(response,request,500,"INTERNAL SERVER ERROR");
252  }
253  });
254  };
255 
256  // Endpoint : GET _identt/identity/api/v1/blobdata/getBlobData
257  helpquery->add({scope,"GET _identt/identity/api/v1/blobdata/getBlobData", {
258  "This is the GET version of getBlobData",
259  "A client can store arbitrary json data by access key and tag",
260  "params : accesskey, tag",
261  "returns the jsondata and textdata if ok"
262  }
263  });
264 
265  server->resource["/_identt/identity/api/v1/blobdata/getBlobData\\\?(.*)$"]["GET"]
266  =[this,stptr](typename HttpServerT::RespPtr response, typename HttpServerT::ReqPtr request) {
267  IDENTT_PARALLEL_ONE([this,stptr,response,request] {
268  try {
269  LOG(INFO) << request->path;
270  std::string err;
271  std::string params = request->path_match[1];
272 
273  identt::query::GetBlobDataT bdata;
274  form2pb( params , bdata.mutable_accessblob()); // throws on error
275  if (!stptr->is_ready.Get()) throw identt::BadDataException("System Not Ready");
276 
277  // action
279  bservice.GetBlobDataAction(stptr, &bdata);
280 
281  // aftermath
282  if ( bdata.mutable_accessblob()->accessdenied() ) throw identt::BadDataException("Access Denied");
283  std::string output;
284  this->HandleDataOut(bdata.mutable_accessblob() , output);
285 
286  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
287  } catch (SydentException& e)
288  {
289  int ecode = (e.ecode()>=IDENTT_SYDENT_ERROR_MIN && e.ecode()<=IDENTT_SYDENT_ERROR_MAX) ? e.ecode() : M_UNKNOWN;
290  std::string output = err2json(SydentErrors.at(ecode),e.what());
291  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
292  } catch (identt::JdException& e)
293  {
294  std::string output = err2json(SydentErrors.at(M_UNKNOWN),e.what());
295  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
296  } catch (std::exception& e)
297  {
298  std::string output = err2json(SydentErrors.at(M_UNKNOWN),e.what());
299  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
300  } catch (...)
301  {
302  this->HttpErrorAction(response,request,500,"INTERNAL SERVER ERROR");
303  }
304  });
305  };
306 
307  // Endpoint : POST _identt/identity/api/v1/blobdata/setBlobData
308  helpquery->add({scope,"POST _identt/identity/api/v1/blobdata/setBlobData", {
309  "A client can store arbitrary json data by access key and tag",
310  "params : accesskey, tag , jsondata, textdata",
311  "returns status"
312  }
313  });
314 
315  server->resource["/_identt/identity/api/v1/blobdata/setBlobData$"]["POST"]
316  =[this,stptr](typename HttpServerT::RespPtr response, typename HttpServerT::ReqPtr request) {
317  IDENTT_PARALLEL_ONE([this,stptr,response,request] {
318  try {
319  LOG(INFO) << request->path;
320  std::string err;
321  bool use_json = this->JsonRequest(request);
322  if (!use_json) throw SydentException("Only Json Allowed",M_BAD_JSON);
323 
324  if (!stptr->is_ready.Get()) throw identt::BadDataException("System Not Ready");
325 
326  identt::query::SetBlobDataT bdata;
327  this->HandleDataIn(request->content.string(), bdata.mutable_accessblob() );
328 
329  // action
330 
331  if (stptr->is_master.Get())
332  {
334  bservice.SetBlobDataAction(stptr, &bdata);
335  } else {
336  identt::hrpc::HrpcClient hclient;
337  hclient.SendToMaster(stptr,::identt::hrpc::M_SETBLOBDATA,&bdata);
338  }
339 
340  // aftermath
341  if ( bdata.mutable_accessblob()->accessdenied() ) throw identt::BadDataException("Access Denied");
342 
343  std::string output = arr2json( {JsonElem("success",true)} );
344  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
345  } catch (SydentException& e)
346  {
347  int ecode = (e.ecode()>=IDENTT_SYDENT_ERROR_MIN && e.ecode()<=IDENTT_SYDENT_ERROR_MAX) ? e.ecode() : M_UNKNOWN;
348  std::string output = err2json(SydentErrors.at(ecode),e.what());
349  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
350  } catch (identt::JdException& e)
351  {
352  std::string output = err2json(SydentErrors.at(M_UNKNOWN),e.what());
353  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
354  } catch (std::exception& e)
355  {
356  std::string output = err2json(SydentErrors.at(M_UNKNOWN),e.what());
357  this->HttpOKAction(response,request,200,"OK","application/json",output,true);
358  } catch (...)
359  {
360  this->HttpErrorAction(response,request,500,"INTERNAL SERVER ERROR");
361  }
362  });
363  };
364 
365  }
366 private:
367 
380  void HandleDataOut(::identt::query::AccessBlobT* accessblob, std::string& output)
381  {
383 
384  if (accessblob->accessdenied() ) {
385  rapidjson::Pointer("/accessdenied").Set(d, true );
386  } else {
387  rapidjson::Pointer("/tag").Set(d, accessblob->tag() );
388  rapidjson::Pointer("/textdata").Set(d, accessblob->textdata() );
389 
390  if (accessblob->jsondata().length()>1) {
391  rapidjson::Pointer("/jsondata").Create(d);
392  rapidjson::Document jd(&d.GetAllocator() ); // for jsondata
393  jd.Parse(accessblob->jsondata().c_str());
394  rapidjson::Pointer("/jsondata").Swap(d , jd );
395  }
396  }
397 
398  rapidjson::StringBuffer buffer;
399  rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
400  d.Accept(writer);
401  output.clear();
402  output.append(buffer.GetString(), buffer.GetSize());
403  }
404 
417  void HandleDataIn(std::string input, ::identt::query::AccessBlobT* accessblob)
418  {
419 
421  d.Parse<0>(input.c_str());
422  if (d.HasParseError()) throw ::identt::query::SydentException("Bad Json Format",M_BAD_JSON);
423  if (d.HasMember("accesskey")) if (d["accesskey"].IsString()) accessblob->set_accesskey( d["accesskey"].GetString() );
424  if (d.HasMember("tag")) if (d["tag"].IsString()) accessblob->set_tag( d["tag"].GetString() );
425  if (d.HasMember("textdata")) if (d["textdata"].IsString()) accessblob->set_textdata( d["textdata"].GetString() );
426  // if jasondata exists make it a string
427  if (d.HasMember("jsondata")) {
428  rapidjson::StringBuffer buffer;
429  rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
430  d["jsondata"].Accept(writer);
431  std::string output;
432  accessblob->set_jsondata( buffer.GetString(), buffer.GetSize());
433  }
434 
435  // checks common
436  std::vector<std::string> splitres;
437  boost::algorithm::split(splitres, accessblob->accesskey() , boost::algorithm::is_any_of(":") );
438  if (splitres.size()!=3) throw ::identt::BadDataException("Bad Accesskey");
439  if (accessblob->tag().length()==0) throw ::identt::BadDataException("Blank Tag not allowed");
440  }
441 
442 };
443 
444 } // namespace query
445 } // namespace identt
446 
447 #endif // _IDENTT_QUERY_BLOBDATA_SERVICE_HPP_
448 
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
void GetAccessKeyAction(::identt::utils::SharedTable::pointer stptr, ::identt::query::GetAccessDataT *gva)
GetAccessKeyAction : get the access key.
Definition: BlobDataService.cc:50
void SetBlobDataAction(::identt::utils::SharedTable::pointer stptr, ::identt::query::SetBlobDataT *bdata)
SetBlobDataAction : set the access key.
Definition: BlobDataService.cc:108
void GetBlobDataAction(::identt::utils::SharedTable::pointer stptr, ::identt::query::GetBlobDataT *bdata)
GetBlobDataAction : get the access key.
Definition: BlobDataService.cc:156
Definition: BlobDataService.hpp:42
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
void pb2json(const google::protobuf::Message *msg, std::string &str)
pb2json : Convert protobuf to json
Definition: ProtoJson.cc:415
std::string arr2json(std::vector< JsonElem > data)
arr2json : Generate a Json for array
Definition: ServiceBase.hpp:55
Definition: CryptoBase.hpp:49
GenericDocument< UTF8<> > Document
GenericDocument with UTF8 encoding.
Definition: document.h:2452
Definition: BaseUtils.hpp:89
Definition: JsonElem.hpp:41
void form2pb(const std::string &form, google::protobuf::Message *msg)
form2pb : Convert url-encoded form to protobuf
Definition: ProtoForm.cc:129
std::string err2json(const std::string errorcode, const std::string error)
err2json : Generate a Json for Error Message
Definition: ProtoJson.cc:511
bool JsonRequest(typename HttpServerT::ReqPtr request)
JsonRequest : Check if request is json from Content-Type and Accept fields.
Definition: ServiceBase.hpp:178
Definition: HrpcClient.hpp:46
Definition: BlobDataService.hpp:48
int json2pb(const std::string &json, google::protobuf::Message *msg, std::string &err)
json2pb : Convert json to protobuf
Definition: ProtoJson.cc:446
bool SendToMaster(::identt::utils::SharedTable::pointer stptr, ::identt::hrpc::MasterCmdTypeE service_id, google::protobuf::Message *msg, bool nothrow=false)
SendToMaster : send to master and get output.
BlobDataService(identt::utils::SharedTable::pointer stptr, typename std::shared_ptr< HttpServerT > server, ::identt::query::HelpQuery::pointer helpquery, unsigned int scope)
BlobDataService : constructor.
Definition: BlobDataService.hpp:70