otsdaq  v2_00_00
WizardSupervisor.cc
1 #include "otsdaq-core/WizardSupervisor/WizardSupervisor.h"
2 
3 #include "otsdaq-core/GatewaySupervisor/GatewaySupervisor.h"
4 
5 #include "otsdaq-core/MessageFacility/MessageFacility.h"
6 #include "otsdaq-core/Macros/CoutHeaderMacros.h"
7 
8 #include <xdaq/NamespaceURI.h>
9 #include "otsdaq-core/CgiDataUtilities/CgiDataUtilities.h"
10 #include "otsdaq-core/XmlUtilities/HttpXmlDocument.h"
11 #include "otsdaq-core/WebUsersUtilities/WebUsers.h"
12 #include "otsdaq-core/SOAPUtilities/SOAPUtilities.h"
13 #include "otsdaq-core/SOAPUtilities/SOAPCommand.h"
14 
15 #include <iostream>
16 #include <fstream>
17 #include <string>
18 #include <thread> // std::this_thread::sleep_for
19 #include <chrono> // std::chrono::seconds
20 #include <sys/stat.h> // mkdir
21 
22 
23 using namespace ots;
24 
25 
26 #define SECURITY_FILE_NAME std::string(getenv("SERVICE_DATA_PATH")) + "/OtsWizardData/security.dat"
27 #define SEQUENCE_FILE_NAME std::string(getenv("SERVICE_DATA_PATH")) + "/OtsWizardData/sequence.dat"
28 #define SEQUENCE_OUT_FILE_NAME std::string(getenv("SERVICE_DATA_PATH")) + "/OtsWizardData/sequence.out"
29 
30 XDAQ_INSTANTIATOR_IMPL(WizardSupervisor)
31 
32 
33 
34 #undef __MF_SUBJECT__
35 #define __MF_SUBJECT__ "Wizard"
36 
37 
38 //========================================================================================================================
39 WizardSupervisor::WizardSupervisor(xdaq::ApplicationStub * s) throw (xdaq::exception::Exception):
40 xdaq::Application(s ),
41 SOAPMessenger (this)
42 {
43  INIT_MF("OtsConfigurationWizard");
44 
45 
46  //attempt to make directory structure (just in case)
47  mkdir((std::string(getenv("SERVICE_DATA_PATH"))).c_str(), 0755);
48  mkdir((std::string(getenv("SERVICE_DATA_PATH")) + "/OtsWizardData").c_str(), 0755);
49 
50  generateURL();
51  xgi::bind (this, &WizardSupervisor::Default, "Default" );
52  xgi::bind (this, &WizardSupervisor::verification, "Verify" );
53  xgi::bind (this, &WizardSupervisor::requestIcons, "requestIcons" );
54  xgi::bind (this, &WizardSupervisor::editSecurity, "editSecurity" );
55  xgi::bind (this, &WizardSupervisor::tooltipRequest, "TooltipRequest" );
56  xgi::bind (this, &WizardSupervisor::toggleSecurityCodeGeneration, "ToggleSecurityCodeGeneration" );
57  xoap::bind(this, &WizardSupervisor::supervisorSequenceCheck, "SupervisorSequenceCheck", XDAQ_NS_URI);
58  xoap::bind(this, &WizardSupervisor::supervisorLastConfigGroupRequest, "SupervisorLastConfigGroupRequest", XDAQ_NS_URI);
59  init();
60 
61 }
62 
63 //========================================================================================================================
64 WizardSupervisor::~WizardSupervisor(void)
65 {
66  destroy();
67 }
68 
69 //========================================================================================================================
70 void WizardSupervisor::init(void)
71 {
72  getApplicationContext();
73 }
74 
75 //========================================================================================================================
76 void WizardSupervisor::generateURL()
77 {
78  defaultSequence_ = true;
79  int length = 4;
80  FILE *fp = fopen((SEQUENCE_FILE_NAME).c_str(),"r");
81  if(fp)
82  {
83  __COUT_INFO__ << "Sequence length file found: " << SEQUENCE_FILE_NAME << std::endl;
84  char line[100];
85  fgets(line,100,fp);
86  sscanf(line,"%d",&length);
87  fclose(fp);
88  if(length < 4)
89  length = 4; //don't allow shorter than 4
90  else
91  defaultSequence_ = false;
92  srand(time(0)); //randomize differently each "time"
93  }
94  else
95  {
96  __COUT_INFO__ << "(Reverting to default wiz security) Sequence length file NOT found: " << SEQUENCE_FILE_NAME << std::endl;
97  srand(0); //use same seed for convenience if file not found
98  }
99 
100  __COUT__ << "Sequence length = " << length << std::endl;
101 
102  securityCode_ = "";
103 
104  static const char alphanum[] =
105  "0123456789"
106  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
107  "abcdefghijklmnopqrstuvwxyz";
108 
109 
110  for (int i = 0; i < length; ++i) {
111  securityCode_ += alphanum[rand() % (sizeof(alphanum) - 1)];
112  }
113 
114  std::cout << __COUT_HDR_FL__ <<
115  getenv("OTS_CONFIGURATION_WIZARD_SUPERVISOR_SERVER") << ":" << getenv("PORT") <<
116  "/urn:xdaq-application:lid="
117  << this->getApplicationDescriptor()->getLocalId() << "/Verify?code=" << securityCode_ << std::endl;
118 
119  //Note: print out handled by StartOTS.sh now
120  //std::thread([&](WizardSupervisor *ptr, std::string securityCode)
121  // {printURL(ptr,securityCode);},this,securityCode_).detach();
122 
123  fp = fopen((SEQUENCE_OUT_FILE_NAME).c_str(),"w");
124  if(fp)
125  {
126  fprintf(fp,"%s",securityCode_.c_str());
127  fclose(fp);
128  }
129  else
130  __COUT_ERR__ << "Sequence output file NOT found: " << SEQUENCE_OUT_FILE_NAME << std::endl;
131 
132 
133  return;
134 }
135 
136 void WizardSupervisor::printURL(WizardSupervisor *ptr,
137  std::string securityCode)
138 {
139  INIT_MF("ConfigurationWizard");
140  // child process
141  int i = 0;
142  for (; i < 5; ++i)
143  {
144  std::this_thread::sleep_for (std::chrono::seconds(2));
145  std::cout << __COUT_HDR_FL__ <<
146  getenv("OTS_CONFIGURATION_WIZARD_SUPERVISOR_SERVER") << ":" << getenv("PORT") <<
147  "/urn:xdaq-application:lid="
148  << ptr->getApplicationDescriptor()->getLocalId() << "/Verify?code=" << securityCode << std::endl;
149  }
150 }
151 
152 //========================================================================================================================
153 void WizardSupervisor::destroy(void)
154 {
155  //called by destructor
156 
157 }
158 
159 
160 //========================================================================================================================
161 void WizardSupervisor::tooltipRequest(xgi::Input * in, xgi::Output * out)
162 throw (xgi::exception::Exception)
163 {
164  cgicc::Cgicc cgi(in);
165 
166  std::string Command = CgiDataUtilities::getData(cgi, "RequestType");
167  __COUT__ << "Command = " << Command << std::endl;
168 
169  std::string submittedSequence = CgiDataUtilities::postData(cgi, "sequence");
170 
171  //SECURITY CHECK START ****
172  if(securityCode_.compare(submittedSequence) != 0)
173  {
174  __COUT__ << "Unauthorized Request made, security sequence doesn't match!" << std::endl;
175  return;
176  }
177  else
178  {
179  __COUT__ << "***Successfully authenticated security sequence." << std::endl;
180  }
181  //SECURITY CHECK END ****
182 
183  HttpXmlDocument xmldoc;
184 
185  if(Command == "check")
186  {
187  WebUsers::tooltipCheckForUsername(
188  WebUsers::DEFAULT_ADMIN_USERNAME,
189  &xmldoc,
190  CgiDataUtilities::getData(cgi, "srcFile"),
191  CgiDataUtilities::getData(cgi, "srcFunc"),
192  CgiDataUtilities::getData(cgi, "srcId"));
193  }
194  else if(Command == "setNeverShow")
195  {
196  WebUsers::tooltipSetNeverShowForUsername(
197  WebUsers::DEFAULT_ADMIN_USERNAME,
198  &xmldoc,
199  CgiDataUtilities::getData(cgi, "srcFile"),
200  CgiDataUtilities::getData(cgi, "srcFunc"),
201  CgiDataUtilities::getData(cgi, "srcId"),
202  CgiDataUtilities::getData(cgi, "doNeverShow") == "1"?true:false,
203  CgiDataUtilities::getData(cgi, "temporarySilence") == "1"?true:false);
204 
205  }
206  else
207  __COUT__ << "Command Request, " << Command << ", not recognized." << std::endl;
208 
209  xmldoc.outputXmlDocument((std::ostringstream*) out, false, true);
210 }
211 
212 //========================================================================================================================
213 void WizardSupervisor::toggleSecurityCodeGeneration(xgi::Input * in, xgi::Output * out)
214 throw (xgi::exception::Exception)
215 {
216  cgicc::Cgicc cgi(in);
217 
218  std::string Command = CgiDataUtilities::getData(cgi, "RequestType");
219  __COUT__ << "Got to Command = " << Command << std::endl;
220 
221  std::string submittedSequence = CgiDataUtilities::postData(cgi, "sequence");
222 
223  //SECURITY CHECK START ****
224  if(securityCode_.compare(submittedSequence) != 0)
225  {
226  __COUT__ << "Unauthorized Request made, security sequence doesn't match!" << std::endl;
227  return;
228  }
229  else
230  {
231  __COUT__ << "***Successfully authenticated security sequence." << std::endl;
232  }
233  //SECURITY CHECK END ****
234 
235  HttpXmlDocument xmldoc;
236 
237  if(Command == "TurnGenerationOn")
238  {
239  __COUT__ << "Turning automatic URL Generation on with a sequence depth of 16!" << std::endl;
240  std::ofstream outfile ((SEQUENCE_FILE_NAME).c_str());
241  outfile << "16" << std::endl;
242  outfile.close();
243  generateURL();
244 
245  //std::stringstream url;
246  // url << getenv("OTS_CONFIGURATION_WIZARD_SUPERVISOR_SERVER") << ":" << getenv("PORT")
247  // << "/urn:xdaq-application:lid=" << this->getApplicationDescriptor()->getLocalId()
248  // << "/Verify?code=" << securityCode_;
249  // printURL(this, securityCode_);
250  std::thread([&](WizardSupervisor *ptr, std::string securityCode)
251  {printURL(ptr,securityCode);},this,securityCode_).detach();
252 
253  xmldoc.addTextElementToData("Status", "Generation_Success");
254  }
255  else
256  __COUT__ << "Command Request, " << Command << ", not recognized." << std::endl;
257 
258  xmldoc.outputXmlDocument((std::ostringstream*) out, false, true);
259 }
260 
261 //========================================================================================================================
262 //xoap::supervisorSequenceCheck
263 // verify cookie
264 xoap::MessageReference WizardSupervisor::supervisorSequenceCheck(xoap::MessageReference message)
265 throw (xoap::exception::Exception)
266 {
267  //receive request parameters
268  SOAPParameters parameters;
269  parameters.addParameter("sequence");
270  receive(message, parameters);
271 
272  std::string submittedSequence = parameters.getValue("sequence");
273 
274  //If submittedSequence matches securityCode_ then return full permissions (255)
275  // else, return permissions 0
276  uint8_t userPermissions = 0;
277  std::string userWithLock = "";
278 
279  if(securityCode_ == submittedSequence)
280  userPermissions = 255;
281  else
282  __COUT__ << "Unauthorized Request made, security sequence doesn't match!" << std::endl;
283 
284  //fill return parameters
285  SOAPParameters retParameters;
286  char tmp[5];
287  sprintf(tmp, "%d", userPermissions);
288  retParameters.addParameter("Permissions", tmp);
289 
290 
291  return SOAPUtilities::makeSOAPMessageReference("SequenceResponse",
292  retParameters);
293 }
294 
295 //===================================================================================================================
296 //xoap::supervisorLastConfigGroupRequest
297 // return the group name and key for the last state machine activity
298 //
299 // Note: same as Supervisor::supervisorLastConfigGroupRequest
300 xoap::MessageReference WizardSupervisor::supervisorLastConfigGroupRequest(
301  xoap::MessageReference message)
302 throw (xoap::exception::Exception)
303 {
304  SOAPParameters parameters;
305  parameters.addParameter("ActionOfLastGroup");
306  receive(message, parameters);
307 
308  return GatewaySupervisor::lastConfigGroupRequestHandler(parameters);
309 }
310 
311 //========================================================================================================================
312 void WizardSupervisor::Default(xgi::Input * in, xgi::Output * out )
313 throw (xgi::exception::Exception)
314 {
315  __COUT__ << "Unauthorized Request made, security sequence doesn't match!" << std::endl;
316  *out << "Unauthorized Request.";
317 }
318 
319 //========================================================================================================================
320 void WizardSupervisor::verification(xgi::Input * in, xgi::Output * out )
321 throw (xgi::exception::Exception)
322 {
323  cgicc::Cgicc cgi(in);
324  std::string submittedSequence = CgiDataUtilities::getData(cgi, "code");
325  __COUT__ << "submittedSequence=" << submittedSequence <<
326  " " << time(0) << std::endl;
327 
328  std::string securityWarning = "";
329 
330  if(securityCode_.compare(submittedSequence) != 0)
331  {
332  __COUT__ << "Unauthorized Request made, security sequence doesn't match!" << std::endl;
333  *out << "Invalid code.";
334  return;
335  }
336  else
337  {
338  //defaultSequence_ = false;
339  __COUT__ << "***Successfully authenticated security sequence. Default Sequence: "<< defaultSequence_ <<
340  time(0) << std::endl;
341 
342  if (defaultSequence_)
343  {
344  __COUT__ << " UNSECURE!!!" << std::endl;
345  securityWarning = "&secure=False";
346  }
347  }
348 
349  *out << "<!DOCTYPE HTML><html lang='en'><head><title>ots wiz</title>" <<
350  //show ots icon
351  // from http://www.favicon-generator.org/
352  "<link rel='apple-touch-icon' sizes='57x57' href='/WebPath/images/otsdaqIcons/apple-icon-57x57.png'>\
353  <link rel='apple-touch-icon' sizes='60x60' href='/WebPath/images/otsdaqIcons/apple-icon-60x60.png'>\
354  <link rel='apple-touch-icon' sizes='72x72' href='/WebPath/images/otsdaqIcons/apple-icon-72x72.png'>\
355  <link rel='apple-touch-icon' sizes='76x76' href='/WebPath/images/otsdaqIcons/apple-icon-76x76.png'>\
356  <link rel='apple-touch-icon' sizes='114x114' href='/WebPath/images/otsdaqIcons/apple-icon-114x114.png'>\
357  <link rel='apple-touch-icon' sizes='120x120' href='/WebPath/images/otsdaqIcons/apple-icon-120x120.png'>\
358  <link rel='apple-touch-icon' sizes='144x144' href='/WebPath/images/otsdaqIcons/apple-icon-144x144.png'>\
359  <link rel='apple-touch-icon' sizes='152x152' href='/WebPath/images/otsdaqIcons/apple-icon-152x152.png'>\
360  <link rel='apple-touch-icon' sizes='180x180' href='/WebPath/images/otsdaqIcons/apple-icon-180x180.png'>\
361  <link rel='icon' type='image/png' sizes='192x192' href='/WebPath/images/otsdaqIcons/android-icon-192x192.png'>\
362  <link rel='icon' type='image/png' sizes='32x32' href='/WebPath/images/otsdaqIcons/favicon-32x32.png'>\
363  <link rel='icon' type='image/png' sizes='96x96' href='/WebPath/images/otsdaqIcons/favicon-96x96.png'>\
364  <link rel='icon' type='image/png' sizes='16x16' href='/WebPath/images/otsdaqIcons/favicon-16x16.png'>\
365  <link rel='manifest' href='/WebPath/images/otsdaqIcons/manifest.json'>\
366  <meta name='msapplication-TileColor' content='#ffffff'>\
367  <meta name='msapplication-TileImage' content='/ms-icon-144x144.png'>\
368  <meta name='theme-color' content='#ffffff'>" <<
369  //end show ots icon
370  "</head>" <<
371  "<frameset col='100%' row='100%'><frame src='/WebPath/html/Wizard.html?urn=" <<
372  this->getApplicationDescriptor()->getLocalId() << securityWarning <<"'></frameset></html>";
373 
374 }
375 
376 //========================================================================================================================
377 void WizardSupervisor::requestIcons(xgi::Input * in, xgi::Output * out )
378 throw (xgi::exception::Exception)
379 {
380  cgicc::Cgicc cgi(in);
381 
382  std::string submittedSequence = CgiDataUtilities::postData(cgi, "sequence");
383 
384  //SECURITY CHECK START ****
385  if(securityCode_.compare(submittedSequence) != 0)
386  {
387  __COUT__ << "Unauthorized Request made, security sequence doesn't match! " <<
388  time(0) << std::endl;
389  return;
390  }
391  else
392  {
393  __COUT__ << "***Successfully authenticated security sequence. " <<
394  time(0) << std::endl;
395  }
396  //SECURITY CHECK END ****
397 
398 
399  //an icon is 7 fields.. give comma-separated
400  //0 - subtext = text below icon
401  //1 - altText = text for icon if image set to 0
402  //2 - uniqueWin = if true, only one window is allowed, else multiple instances of window
403  //3 - permissions = security level needed to see icon
404  //4 - picfn = icon image filename, 0 for no image
405  //5 - linkurl = url of the window to open
406  //6 - folderPath = folder and subfolder location
407 
408  *out << "Security Settings,SEC,1,1,icon-SecuritySettings.png,/WebPath/html/SecuritySettings.html,/" <<
409  ",Edit User Data,USER,1,1,icon-EditUserData.png,/WebPath/html/EditUserData.html,/" <<
410  ",Configure,CFG,0,1,icon-Configure.png,/urn:xdaq-application:lid=280/,/" <<
411  ",Table Editor,TBL,0,1,icon-IconEditor.png,/urn:xdaq-application:lid=280/?configWindowName=tableEditor,/" <<
412  //",Iterate,IT,0,1,icon-Iterate.png,/urn:xdaq-application:lid=280/?configWindowName=iterate,/" <<
413  //",Configure,CFG,0,1,icon-Configure.png,/urn:xdaq-application:lid=280/,myFolder" <<
414  //",Configure,CFG,0,1,icon-Configure.png,/urn:xdaq-application:lid=280/,/myFolder/mySub.folder" <<
415  //",Configure,CFG,0,1,icon-Configure.png,/urn:xdaq-application:lid=280/,myFolder/" <<
416  ",Front-end Wizard,CFG,0,1,icon-Configure.png,/WebPath/html/RecordWiz_ConfigurationGUI.html?urn=280&subsetBasePath=FEInterfaceConfiguration&recordAlias=Front%2Dend,Config Wizards" <<
417  ",Producer Wizard,CFG,0,1,icon-Configure.png,/WebPath/html/RecordWiz_ConfigurationGUI.html?urn=280&subsetBasePath=FEInterfaceConfiguration&recordAlias=Producer,Config Wizards" <<
418  ",Consumer Wizard,CFG,0,1,icon-Configure.png,/WebPath/html/RecordWiz_ConfigurationGUI.html?urn=280&subsetBasePath=FEInterfaceConfiguration&recordAlias=Consumer,Config Wizards" <<
419  ",Console,C,1,1,icon-Console.png,/urn:xdaq-application:lid=260/,/" <<
420  //",DB Utilities,DB,1,1,0,http://127.0.0.1:8080/db/client.html" <<
421  "";
422  return;
423 }
424 
425 //========================================================================================================================
426 void WizardSupervisor::editSecurity(xgi::Input * in, xgi::Output * out )
427 throw (xgi::exception::Exception)
428 {
429 
430  //if sequence doesn't match up -> return
431  cgicc::Cgicc cgi(in);
432  std::string submittedSequence = CgiDataUtilities::postData(cgi, "sequence");
433  std::string submittedSecurity = CgiDataUtilities::postData(cgi, "selection");
434  std::string securityFileName = SECURITY_FILE_NAME;
435 
436 
437  //SECURITY CHECK START ****
438  if(securityCode_.compare(submittedSequence) != 0)
439  {
440  __COUT__ << "Unauthorized Request made, security sequence doesn't match!" << std::endl;
441  return;
442  }
443  else
444  {
445  __COUT__ << "***Successfully authenticated security sequence." << std::endl;
446  }
447  //SECURITY CHECK END ****
448 
449 
450 
451  if(submittedSecurity != "")
452  {
453  __COUT__ << "Selection exists!" << std::endl;
454  __COUT__ << submittedSecurity << std::endl;
455 
456  if(submittedSecurity == "ResetAllUserData")
457  {
458  WebUsers::deleteUserData();
459  __COUT__ << "Turning URL Generation back to default!" << std::endl;
460  //std::remove((SEQUENCE_FILE_NAME).c_str());
461  //std::remove((SEQUENCE_OUT_FILE_NAME).c_str());
462  std::ofstream newFile ((SEQUENCE_FILE_NAME).c_str());
463  newFile << "4" << std::endl;
464  newFile.close();
465 
466  generateURL();
467  std::thread([&](WizardSupervisor *ptr, std::string securityCode)
468  {printURL(ptr,securityCode);},this,securityCode_).detach();
469  *out << "Default_URL_Generation";
470  }
471  else if(submittedSecurity == "ResetAllUserTooltips")
472  {
473  WebUsers::resetAllUserTooltips();
474  *out << submittedSecurity;
475  return;
476  }
477  else if(submittedSecurity == "DigestAccessAuthentication" ||
478  submittedSecurity == "NoSecurity")
479  {
480  std::ofstream writeSecurityFile;
481 
482  writeSecurityFile.open(securityFileName.c_str());
483  if(writeSecurityFile.is_open())
484  writeSecurityFile << submittedSecurity;
485  else
486  __COUT__ << "Error writing file!" << std::endl;
487 
488  writeSecurityFile.close();
489  }
490  else
491  {
492  __COUT_ERR__ << "Invalid submittedSecurity string: " <<
493  submittedSecurity << std::endl;
494  *out << "Error";
495  return;
496  }
497  }
498 
499 
500  //Always return the file
501  std::ifstream securityFile;
502  std::string line;
503  std::string security = "";
504  int lineNumber = 0;
505 
506  securityFile.open(securityFileName.c_str());
507 
508  if(!securityFile)
509  {
510  __SS__ << "Error opening file: "<< securityFileName << std::endl;
511  __COUT_ERR__ << "\n" << ss.str();
512  //throw std::runtime_error(ss.str());
513  //return;
514  security = "DigestAccessAuthentication"; //default security when no file exists
515  }
516  if(securityFile.is_open())
517  {
518  //__COUT__ << "Opened File: " << securityFileName << std::endl;
519  while(std::getline(securityFile, line))
520  {
521  security += line;
522  lineNumber++;
523  }
524  //__COUT__ << std::to_string(lineNumber) << ":" << iconList << std::endl;
525 
526  //Close file
527  securityFile.close();
528  }
529 
530  *out << security;
531 }