1 #include "otsdaq-core/WizardSupervisor/WizardSupervisor.h"
3 #include "otsdaq-core/GatewaySupervisor/GatewaySupervisor.h"
5 #include "otsdaq-core/MessageFacility/MessageFacility.h"
6 #include "otsdaq-core/Macros/CoutMacros.h"
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"
28 #define SECURITY_FILE_NAME std::string(getenv("SERVICE_DATA_PATH")) + "/OtsWizardData/security.dat"
29 #define SEQUENCE_FILE_NAME std::string(getenv("SERVICE_DATA_PATH")) + "/OtsWizardData/sequence.dat"
30 #define SEQUENCE_OUT_FILE_NAME std::string(getenv("SERVICE_DATA_PATH")) + "/OtsWizardData/sequence.out"
31 #define USER_DATA_PATH std::string(getenv("SERVICE_DATA_PATH")) + std::string("/")
34 #define XML_STATUS "editUserData_status"
36 #define XML_ADMIN_STATUS "logbook_admin_status"
37 #define XML_MOST_RECENT_DAY "most_recent_day"
38 #define XML_EXPERIMENTS_ROOT "experiments"
39 #define XML_EXPERIMENT "experiment"
40 #define XML_ACTIVE_EXPERIMENT "active_experiment"
41 #define XML_EXPERIMENT_CREATE "create_time"
42 #define XML_EXPERIMENT_CREATOR "creator"
44 #define XML_LOGBOOK_ENTRY "logbook_entry"
45 #define XML_LOGBOOK_ENTRY_SUBJECT "logbook_entry_subject"
46 #define XML_LOGBOOK_ENTRY_TEXT "logbook_entry_text"
47 #define XML_LOGBOOK_ENTRY_FILE "logbook_entry_file"
48 #define XML_LOGBOOK_ENTRY_TIME "logbook_entry_time"
49 #define XML_LOGBOOK_ENTRY_CREATOR "logbook_entry_creator"
50 #define XML_LOGBOOK_ENTRY_HIDDEN "logbook_entry_hidden"
51 #define XML_LOGBOOK_ENTRY_HIDER "logbook_entry_hider"
52 #define XML_LOGBOOK_ENTRY_HIDDEN_TIME "logbook_entry_hidden_time"
54 #define XML_PREVIEW_INDEX "preview_index"
55 #define LOGBOOK_PREVIEW_FILE "preview.xml"
64 #define __MF_SUBJECT__ "Wizard"
68 WizardSupervisor::WizardSupervisor(xdaq::ApplicationStub * s)
throw (xdaq::exception::Exception)
69 : xdaq::Application (s )
71 , supervisorClass_ (getApplicationDescriptor()->getClassName())
72 , supervisorClassNoNamespace_ (supervisorClass_.substr(supervisorClass_.find_last_of(
":")+1, supervisorClass_.length()-supervisorClass_.find_last_of(
":")))
74 __SUP_COUT__ <<
"Constructor started." << __E__;
76 INIT_MF(
"OtsConfigurationWizard");
80 mkdir((std::string(getenv(
"SERVICE_DATA_PATH"))).c_str(), 0755);
81 mkdir((std::string(getenv(
"SERVICE_DATA_PATH")) +
"/OtsWizardData").c_str(), 0755);
84 xgi::bind (
this, &WizardSupervisor::Default,
"Default" );
85 xgi::bind (
this, &WizardSupervisor::verification,
"Verify" );
86 xgi::bind (
this, &WizardSupervisor::requestIcons,
"requestIcons" );
87 xgi::bind (
this, &WizardSupervisor::editSecurity,
"editSecurity" );
88 xgi::bind (
this, &WizardSupervisor::UserSettings,
"UserSettings" );
89 xgi::bind (
this, &WizardSupervisor::tooltipRequest,
"TooltipRequest" );
90 xgi::bind (
this, &WizardSupervisor::toggleSecurityCodeGeneration,
"ToggleSecurityCodeGeneration" );
91 xoap::bind(
this, &WizardSupervisor::supervisorSequenceCheck,
"SupervisorSequenceCheck", XDAQ_NS_URI);
92 xoap::bind(
this, &WizardSupervisor::supervisorLastConfigGroupRequest,
"SupervisorLastConfigGroupRequest", XDAQ_NS_URI);
95 __SUP_COUT__ <<
"Constructor complete." << __E__;
99 WizardSupervisor::~WizardSupervisor(
void)
105 void WizardSupervisor::init(
void)
110 allowedFileUploadTypes_.push_back(
"image/png"); matchingFileUploadTypes_.push_back(
"png");
111 allowedFileUploadTypes_.push_back(
"image/jpeg"); matchingFileUploadTypes_.push_back(
"jpeg");
112 allowedFileUploadTypes_.push_back(
"image/gif"); matchingFileUploadTypes_.push_back(
"gif");
113 allowedFileUploadTypes_.push_back(
"image/bmp"); matchingFileUploadTypes_.push_back(
"bmp");
114 allowedFileUploadTypes_.push_back(
"application/pdf"); matchingFileUploadTypes_.push_back(
"pdf");
115 allowedFileUploadTypes_.push_back(
"application/zip"); matchingFileUploadTypes_.push_back(
"zip");
116 allowedFileUploadTypes_.push_back(
"text/plain"); matchingFileUploadTypes_.push_back(
"txt");
122 void WizardSupervisor::generateURL()
125 defaultSequence_ =
true;
128 FILE *fp = fopen((SEQUENCE_FILE_NAME).c_str(),
"r");
131 __COUT_INFO__ <<
"Sequence length file found: " << SEQUENCE_FILE_NAME << std::endl;
134 sscanf(line,
"%d",&length);
139 defaultSequence_ =
false;
144 __COUT_INFO__ <<
"(Reverting to default wiz security) Sequence length file NOT found: " << SEQUENCE_FILE_NAME << std::endl;
148 __COUT__ <<
"Sequence length = " << length << std::endl;
152 static const char alphanum[] =
154 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
155 "abcdefghijklmnopqrstuvwxyz";
158 for (
int i = 0; i < length; ++i) {
159 securityCode_ += alphanum[rand() % (
sizeof(alphanum) - 1)];
162 std::cout << __COUT_HDR_FL__ <<
163 getenv(
"OTS_CONFIGURATION_WIZARD_SUPERVISOR_SERVER") <<
":" << getenv(
"PORT") <<
164 "/urn:xdaq-application:lid="
165 << this->getApplicationDescriptor()->getLocalId() <<
"/Verify?code=" << securityCode_ << std::endl;
171 fp = fopen((SEQUENCE_OUT_FILE_NAME).c_str(),
"w");
174 fprintf(fp,
"%s",securityCode_.c_str());
178 __COUT_ERR__ <<
"Sequence output file NOT found: " << SEQUENCE_OUT_FILE_NAME << std::endl;
185 std::string securityCode)
187 INIT_MF(
"ConfigurationWizard");
192 std::this_thread::sleep_for (std::chrono::seconds(2));
193 std::cout << __COUT_HDR_FL__ <<
194 getenv(
"OTS_CONFIGURATION_WIZARD_SUPERVISOR_SERVER") <<
":" << getenv(
"PORT") <<
195 "/urn:xdaq-application:lid="
196 << ptr->getApplicationDescriptor()->getLocalId() <<
"/Verify?code=" << securityCode << std::endl;
201 void WizardSupervisor::destroy(
void)
209 void WizardSupervisor::tooltipRequest(xgi::Input * in, xgi::Output * out)
210 throw (xgi::exception::Exception)
212 cgicc::Cgicc cgi(in);
214 std::string Command = CgiDataUtilities::getData(cgi,
"RequestType");
215 __COUT__ <<
"Command = " << Command << std::endl;
217 std::string submittedSequence = CgiDataUtilities::postData(cgi,
"sequence");
220 if(securityCode_.compare(submittedSequence) != 0)
222 __COUT__ <<
"Unauthorized Request made, security sequence doesn't match!" << std::endl;
227 __COUT__ <<
"***Successfully authenticated security sequence." << std::endl;
233 if(Command ==
"check")
235 WebUsers::tooltipCheckForUsername(
236 WebUsers::DEFAULT_ADMIN_USERNAME,
238 CgiDataUtilities::getData(cgi,
"srcFile"),
239 CgiDataUtilities::getData(cgi,
"srcFunc"),
240 CgiDataUtilities::getData(cgi,
"srcId"));
242 else if(Command ==
"setNeverShow")
244 WebUsers::tooltipSetNeverShowForUsername(
245 WebUsers::DEFAULT_ADMIN_USERNAME,
247 CgiDataUtilities::getData(cgi,
"srcFile"),
248 CgiDataUtilities::getData(cgi,
"srcFunc"),
249 CgiDataUtilities::getData(cgi,
"srcId"),
250 CgiDataUtilities::getData(cgi,
"doNeverShow") ==
"1"?
true:
false,
251 CgiDataUtilities::getData(cgi,
"temporarySilence") ==
"1"?
true:
false);
255 __COUT__ <<
"Command Request, " << Command <<
", not recognized." << std::endl;
257 xmldoc.outputXmlDocument((std::ostringstream*) out,
false,
true);
261 void WizardSupervisor::toggleSecurityCodeGeneration(xgi::Input * in, xgi::Output * out)
262 throw (xgi::exception::Exception)
264 cgicc::Cgicc cgi(in);
266 std::string Command = CgiDataUtilities::getData(cgi,
"RequestType");
267 __COUT__ <<
"Got to Command = " << Command << std::endl;
269 std::string submittedSequence = CgiDataUtilities::postData(cgi,
"sequence");
272 if(securityCode_.compare(submittedSequence) != 0)
274 __COUT__ <<
"Unauthorized Request made, security sequence doesn't match!" << std::endl;
279 __COUT__ <<
"***Successfully authenticated security sequence." << std::endl;
285 if(Command ==
"TurnGenerationOn")
287 __COUT__ <<
"Turning automatic URL Generation on with a sequence depth of 16!" << std::endl;
288 std::ofstream outfile ((SEQUENCE_FILE_NAME).c_str());
289 outfile <<
"16" << std::endl;
299 {printURL(ptr,securityCode);},
this,securityCode_).detach();
301 xmldoc.addTextElementToData(
"Status",
"Generation_Success");
304 __COUT__ <<
"Command Request, " << Command <<
", not recognized." << std::endl;
306 xmldoc.outputXmlDocument((std::ostringstream*) out,
false,
true);
312 xoap::MessageReference WizardSupervisor::supervisorSequenceCheck(xoap::MessageReference message)
313 throw (xoap::exception::Exception)
317 parameters.addParameter(
"sequence");
318 receive(message, parameters);
320 std::string submittedSequence = parameters.getValue(
"sequence");
324 std::map<std::string ,WebUsers::permissionLevel_t> permissionMap;
326 if(securityCode_ == submittedSequence)
327 permissionMap.emplace(
328 std::pair<std::string /*groupName*/,WebUsers::permissionLevel_t>(
329 WebUsers::DEFAULT_USER_GROUP,
330 WebUsers::PERMISSION_LEVEL_ADMIN));
333 __COUT__ <<
"Unauthorized Request made, security sequence doesn't match!" << std::endl;
335 permissionMap.emplace(
336 std::pair<std::string /*groupName*/,WebUsers::permissionLevel_t>(
337 WebUsers::DEFAULT_USER_GROUP,
338 WebUsers::PERMISSION_LEVEL_INACTIVE));
343 retParameters.addParameter(
"Permissions", StringMacros::mapToString(permissionMap));
346 return SOAPUtilities::makeSOAPMessageReference(
"SequenceResponse",
355 xoap::MessageReference WizardSupervisor::supervisorLastConfigGroupRequest(
356 xoap::MessageReference message)
357 throw (xoap::exception::Exception)
360 parameters.addParameter(
"ActionOfLastGroup");
361 receive(message, parameters);
363 return GatewaySupervisor::lastConfigGroupRequestHandler(parameters);
367 void WizardSupervisor::Default(xgi::Input * in, xgi::Output * out )
368 throw (xgi::exception::Exception)
370 __COUT__ <<
"Unauthorized Request made, security sequence doesn't match!" << std::endl;
371 *out <<
"Unauthorized Request.";
375 void WizardSupervisor::verification(xgi::Input * in, xgi::Output * out )
376 throw (xgi::exception::Exception)
378 cgicc::Cgicc cgi(in);
379 std::string submittedSequence = CgiDataUtilities::getData(cgi,
"code");
380 __COUT__ <<
"submittedSequence=" << submittedSequence <<
381 " " << time(0) << std::endl;
383 std::string securityWarning =
"";
385 if(securityCode_.compare(submittedSequence) != 0)
387 __COUT__ <<
"Unauthorized Request made, security sequence doesn't match!" << std::endl;
388 *out <<
"Invalid code.";
394 __COUT__ <<
"*** Successfully authenticated security sequence " <<
395 "@ " << time(0) << std::endl;
397 if (defaultSequence_)
400 securityWarning =
"&secure=False";
404 *out <<
"<!DOCTYPE HTML><html lang='en'><head><title>ots wiz</title>" <<
407 "<link rel='apple-touch-icon' sizes='57x57' href='/WebPath/images/otsdaqIcons/apple-icon-57x57.png'>\
408 <link rel='apple-touch-icon' sizes='60x60' href='/WebPath/images/otsdaqIcons/apple-icon-60x60.png'>\
409 <link rel='apple-touch-icon' sizes='72x72' href='/WebPath/images/otsdaqIcons/apple-icon-72x72.png'>\
410 <link rel='apple-touch-icon' sizes='76x76' href='/WebPath/images/otsdaqIcons/apple-icon-76x76.png'>\
411 <link rel='apple-touch-icon' sizes='114x114' href='/WebPath/images/otsdaqIcons/apple-icon-114x114.png'>\
412 <link rel='apple-touch-icon' sizes='120x120' href='/WebPath/images/otsdaqIcons/apple-icon-120x120.png'>\
413 <link rel='apple-touch-icon' sizes='144x144' href='/WebPath/images/otsdaqIcons/apple-icon-144x144.png'>\
414 <link rel='apple-touch-icon' sizes='152x152' href='/WebPath/images/otsdaqIcons/apple-icon-152x152.png'>\
415 <link rel='apple-touch-icon' sizes='180x180' href='/WebPath/images/otsdaqIcons/apple-icon-180x180.png'>\
416 <link rel='icon' type='image/png' sizes='192x192' href='/WebPath/images/otsdaqIcons/android-icon-192x192.png'>\
417 <link rel='icon' type='image/png' sizes='32x32' href='/WebPath/images/otsdaqIcons/favicon-32x32.png'>\
418 <link rel='icon' type='image/png' sizes='96x96' href='/WebPath/images/otsdaqIcons/favicon-96x96.png'>\
419 <link rel='icon' type='image/png' sizes='16x16' href='/WebPath/images/otsdaqIcons/favicon-16x16.png'>\
420 <link rel='manifest' href='/WebPath/images/otsdaqIcons/manifest.json'>\
421 <meta name='msapplication-TileColor' content='#ffffff'>\
422 <meta name='msapplication-TileImage' content='/ms-icon-144x144.png'>\
423 <meta name='theme-color' content='#ffffff'>" <<
426 "<frameset col='100%' row='100%'><frame src='/WebPath/html/Wizard.html?urn=" <<
427 this->getApplicationDescriptor()->getLocalId() << securityWarning <<
"'></frameset></html>";
432 void WizardSupervisor::requestIcons(xgi::Input * in, xgi::Output * out )
433 throw (xgi::exception::Exception)
435 cgicc::Cgicc cgi(in);
437 std::string submittedSequence = CgiDataUtilities::postData(cgi,
"sequence");
440 if(securityCode_.compare(submittedSequence) != 0)
442 __COUT__ <<
"Unauthorized Request made, security sequence doesn't match! " <<
443 time(0) << std::endl;
448 __COUT__ <<
"***Successfully authenticated security sequence. " <<
449 time(0) << std::endl;
463 *out <<
"Security Settings,SEC,1,1,icon-SecuritySettings.png,/WebPath/html/SecuritySettings.html,/" <<
464 ",Edit User Data,USER,1,1,icon-EditUserData.png,/WebPath/html/EditUserData.html,/" <<
465 ",Configure,CFG,0,1,icon-Configure.png,/urn:xdaq-application:lid=280/,/" <<
466 ",Table Editor,TBL,0,1,icon-IconEditor.png,/urn:xdaq-application:lid=280/?configWindowName=tableEditor,/" <<
471 ",Front-end Wizard,CFG,0,1,icon-Configure.png,/WebPath/html/RecordWiz_ConfigurationGUI.html?urn=280&subsetBasePath=FEInterfaceConfiguration&recordAlias=Front%2Dend,Config Wizards" <<
472 ",Producer Wizard,CFG,0,1,icon-Configure.png,/WebPath/html/RecordWiz_ConfigurationGUI.html?urn=280&subsetBasePath=FEInterfaceConfiguration&recordAlias=Producer,Config Wizards" <<
473 ",Consumer Wizard,CFG,0,1,icon-Configure.png,/WebPath/html/RecordWiz_ConfigurationGUI.html?urn=280&subsetBasePath=FEInterfaceConfiguration&recordAlias=Consumer,Config Wizards" <<
474 ",Console,C,1,1,icon-Console.png,/urn:xdaq-application:lid=260/,/" <<
481 void WizardSupervisor::editSecurity(xgi::Input * in, xgi::Output * out )
482 throw (xgi::exception::Exception)
486 cgicc::Cgicc cgi(in);
487 std::string submittedSequence = CgiDataUtilities::postData(cgi,
"sequence");
488 std::string submittedSecurity = CgiDataUtilities::postData(cgi,
"selection");
489 std::string securityFileName = SECURITY_FILE_NAME;
493 if(securityCode_.compare(submittedSequence) != 0)
495 __COUT__ <<
"Unauthorized Request made, security sequence doesn't match!" << std::endl;
500 __COUT__ <<
"***Successfully authenticated security sequence." << std::endl;
506 if(submittedSecurity !=
"")
508 __COUT__ <<
"Selection exists!" << std::endl;
509 __COUT__ << submittedSecurity << std::endl;
511 if(submittedSecurity ==
"ResetAllUserData")
513 WebUsers::deleteUserData();
514 __COUT__ <<
"Turning URL Generation back to default!" << std::endl;
517 std::ofstream newFile ((SEQUENCE_FILE_NAME).c_str());
518 newFile <<
"4" << std::endl;
523 {printURL(ptr,securityCode);},
this,securityCode_).detach();
524 *out <<
"Default_URL_Generation";
526 else if(submittedSecurity ==
"ResetAllUserTooltips")
528 WebUsers::resetAllUserTooltips();
529 *out << submittedSecurity;
532 else if(submittedSecurity ==
"DigestAccessAuthentication" ||
533 submittedSecurity ==
"NoSecurity")
535 std::ofstream writeSecurityFile;
537 writeSecurityFile.open(securityFileName.c_str());
538 if(writeSecurityFile.is_open())
539 writeSecurityFile << submittedSecurity;
541 __COUT__ <<
"Error writing file!" << std::endl;
543 writeSecurityFile.close();
547 __COUT_ERR__ <<
"Invalid submittedSecurity string: " <<
548 submittedSecurity << std::endl;
556 std::ifstream securityFile;
558 std::string security =
"";
561 securityFile.open(securityFileName.c_str());
570 security =
"DigestAccessAuthentication";
572 if(securityFile.is_open())
575 while(std::getline(securityFile, line))
583 securityFile.close();
589 void WizardSupervisor::UserSettings(xgi::Input * in, xgi::Output * out )
590 throw (xgi::exception::Exception)
594 cgicc::Cgicc cgi(in);
595 std::string submittedSequence = CgiDataUtilities::postData(cgi,
"sequence");
596 std::string securityFileName = SECURITY_FILE_NAME;
598 if((Command = CgiDataUtilities::postData(cgi,
"RequestType")) ==
"")
599 Command = cgi(
"RequestType");
601 __COUT__ << Command << std::endl;
602 __COUT__ <<
"We are vewing Users' Settings!" << std::endl;
605 if(securityCode_.compare(submittedSequence) != 0)
607 __COUT__ <<
"Unauthorized Request made, security sequence doesn't match!" << std::endl;
608 __COUT__ << submittedSequence << std::endl;
613 __COUT__ <<
"***Successfully authenticated security sequence." << std::endl;
619 uint64_t activeSessionIndex;
621 uint8_t userPermissions;
625 __COUT__ <<
"Action exists!" << std::endl;
626 __COUT__ << Command << std::endl;
628 if(Command ==
"Import")
645 __COUT__ << cgi(
"Entry") << std::endl;
646 __COUT__ << cgi(
"Filename") << std::endl;
647 __COUT__ << cgi(
"Imported_File") << std::endl;
650 const std::vector<cgicc::FormFile> files = cgi.getFiles();
651 __COUT__ <<
"FormFiles: " <<
sizeof(files) << std::endl;
652 __COUT__ <<
"Number of files: " << files.size() << std::endl;
654 for(
unsigned int i = 0; i < files.size(); ++i)
656 std::string filename = USER_DATA_PATH + files[i].getFilename();
657 __COUT__ << filename << std::endl;
658 std::ofstream myFile;
659 myFile.open(filename.c_str());
660 files[0].writeToStream(myFile);
664 __COUT__ << files[0].getFilename() << std::endl;
665 __COUT__ <<
"********************Files Begin********************" << std::endl;
666 for (
unsigned int i=0; i<files.size(); ++i)
669 __COUT__ << files[i].getDataType() << std::endl;
672 __COUT__ <<
"*********************Files End*********************" << std::endl;
678 else if(Command ==
"Export")
680 __SS__ <<
"This doesn't compile Dan." << __E__;
720 __COUT__ <<
"Command request not recognized: " << Command << std::endl;
735 std::string WizardSupervisor::validateUploadFileType(
const std::string fileType)
737 for (
unsigned int i=0; i<allowedFileUploadTypes_.size(); ++i)
738 if (allowedFileUploadTypes_[i] == fileType)
739 return matchingFileUploadTypes_[i];
747 void WizardSupervisor::cleanUpPreviews()
749 std::string userData = (std::string)USER_DATA_PATH;
751 DIR *dir = opendir(userData.c_str());
754 __COUT__ <<
"Error - User Data directory missing: " << userData << std::endl;
758 struct dirent *entry;
759 time_t dirCreateTime;
762 while((entry = readdir(dir)))
764 if( strcmp(entry->d_name,
".") != 0 && strcmp(entry->d_name,
"..") != 0
765 && strcmp(entry->d_name,
".svn") != 0 )
768 for(i=0;i<strlen(entry->d_name);++i)
769 if(entry->d_name[i] ==
'_')
770 { entry->d_name[i] =
' ';
break; }
771 sscanf(entry->d_name,
"%li",&dirCreateTime);
773 if((time(0) - dirCreateTime) > USER_DATA_EXPIRATION_TIME)
775 __COUT__ <<
"Expired" << std::endl;
777 entry->d_name[i] =
'_';
779 __COUT__ <<
"rm -rf " << USER_DATA_PATH + (std::string)entry->d_name << std::endl << std::endl;
780 system(((std::string)(
"rm -rf " + userData + (std::string)entry->d_name)).c_str());
791 void WizardSupervisor::savePostPreview(std::string &subject, std::string &text,
const std::vector<cgicc::FormFile> &files, std::string creator,
801 sprintf(fileIndex,
"%lu_%lu",time(0),clock());
802 std::string userDataPath = (std::string)USER_DATA_PATH + (std::string)fileIndex;
804 __COUT__ <<
"userDataPath " << userDataPath << std::endl;
805 if(-1 == mkdir(userDataPath.c_str(),0755))
807 if(xmldoc) xmldoc->addTextElementToData(XML_STATUS,
"Failed - directory could not be generated.");
877 std::string WizardSupervisor::exec(
const char* cmd)
879 std::array<char, 128> buffer;
881 std::shared_ptr<FILE> pipe(popen(cmd,
"r"), pclose);
882 if (!pipe)
throw std::runtime_error(
"popen() failed!");
883 while (!feof(pipe.get())) {
884 if (fgets(buffer.data(), 128, pipe.get()) !=
nullptr)
885 result += buffer.data();