otsdaq  3.03.00
RemoteWebUsers.cc
1 #include "otsdaq/WebUsersUtilities/RemoteWebUsers.h"
2 
3 #include "otsdaq/CgiDataUtilities/CgiDataUtilities.h"
4 #include "otsdaq/SOAPUtilities/SOAPCommand.h"
5 #include "otsdaq/SOAPUtilities/SOAPParameters.h" //must include in .h for static function
6 #include "otsdaq/SOAPUtilities/SOAPUtilities.h"
7 #include "otsdaq/XmlUtilities/HttpXmlDocument.h"
8 
9 #include <cstdio>
10 #include <cstdlib>
11 #include <tuple>
12 #include <vector>
13 
14 #include "otsdaq/SupervisorInfo/AllSupervisorInfo.h"
15 
16 using namespace ots;
17 
18 #undef __MF_SUBJECT__
19 #define __MF_SUBJECT__ "RemoteWebUsers"
20 
21 //==============================================================================
29 //==============================================================================
31  xdaq::Application* application,
32  XDAQ_CONST_CALL xdaq::ApplicationDescriptor* gatewaySupervisorDescriptor)
33  : SOAPMessenger(application)
34  , gatewaySupervisorDescriptor_(gatewaySupervisorDescriptor)
35 {
36  ActiveUserLastUpdateTime_ = 0; // init to never
37  ActiveUserList_ = ""; // init to empty
38 } // end constructor()
39 
40 //==============================================================================
44 bool RemoteWebUsers::xmlRequestToGateway(cgicc::Cgicc& cgi,
45  std::ostringstream* out,
46  HttpXmlDocument* xmldoc,
47  const AllSupervisorInfo& allSupervisorInfo,
48  WebUsers::RequestUserInfo& userInfo)
49 {
50  //__COUT__ << std::endl;
51  // initialize user info parameters to failed results
53 
54  XDAQ_CONST_CALL xdaq::ApplicationDescriptor* gatewaySupervisor;
55 
56  SOAPParameters parameters;
57  xoap::MessageReference retMsg;
58 
59  //**** start LOGIN GATEWAY CODE ***//
60  // If TRUE, cookie code is good, and refreshed code is in cookieCode
61  // Else, error message is returned in cookieCode
62 
64  // if Wiz or Macormaker mode, use sequence instead of cookieCode
65  if(allSupervisorInfo.isWizardMode() || allSupervisorInfo.isMacroMakerMode())
66  {
67  // if missing CookieCode... check if in Wizard mode and using sequence
68  std::string sequence =
69  CgiDataUtilities::getOrPostData(cgi, "sequence"); // from GET or POST
70  //__COUT__ << "sequence=" << sequence << std::endl;
71  if(!sequence.length())
72  {
73  __COUT_ERR__ << "Invalid access attempt (@" << userInfo.ip_ << ")."
74  << std::endl;
75  *out << WebUsers::REQ_NO_LOGIN_RESPONSE;
76  // invalid cookie and also invalid sequence
77  goto HANDLE_ACCESS_FAILURE; // return false, access failed
78  }
79 
80  // have sequence, try it out
81 
82  if(allSupervisorInfo.isWizardMode())
83  gatewaySupervisor = allSupervisorInfo.getWizardInfo().getDescriptor();
84  else //is MacroMaker mode
85  gatewaySupervisor = allSupervisorInfo.getAllMacroMakerTypeSupervisorInfo()
86  .begin()
87  ->second.getDescriptor();
88 
89  if(!gatewaySupervisor)
90  {
91  __COUT_ERR__ << "Missing gateway supervisor." << std::endl;
92  *out << WebUsers::REQ_NO_LOGIN_RESPONSE;
93  // sequence code present, but no wizard supervisor
94  goto HANDLE_ACCESS_FAILURE; // return false, access failed
95  }
96 
97  parameters.addParameter("sequence", sequence);
98  parameters.addParameter("IPAddress", userInfo.ip_);
99  retMsg = SOAPMessenger::sendWithSOAPReply(
100  gatewaySupervisor, "SupervisorSequenceCheck", parameters);
101  parameters.clear();
102  parameters.addParameter("Permissions");
103  SOAPUtilities::receive(retMsg, parameters);
104 
105  userInfo.setGroupPermissionLevels(parameters.getValue("Permissions"));
106 
108  cgi, out, xmldoc, userInfo, true /*isWizardMode*/, sequence))
109  return true; //successful sequence login!
110  else
111  goto HANDLE_ACCESS_FAILURE; // return false, access failed
112  } //end Wiz or Macormaker mode
113 
114  // else proceed with inquiry to Gateway Supervisor
115 
116  gatewaySupervisor = allSupervisorInfo.getGatewayInfo().getDescriptor();
117 
118  if(!gatewaySupervisor)
119  {
120  __COUT_ERR__ << "Missing gateway supervisor." << std::endl;
121  *out << WebUsers::REQ_NO_LOGIN_RESPONSE;
122  goto HANDLE_ACCESS_FAILURE; // return false, access failed
123  }
124 
125  parameters.clear();
126  parameters.addParameter("CookieCode", userInfo.cookieCode_);
127  parameters.addParameter("RefreshOption", userInfo.automatedCommand_ ? "0" : "1");
128  parameters.addParameter("IPAddress", userInfo.ip_);
129 
130  retMsg = SOAPMessenger::sendWithSOAPReply(
131  gatewaySupervisor, "SupervisorCookieCheck", parameters);
132 
133  parameters.clear();
134  parameters.addParameter("CookieCode");
135  parameters.addParameter("Permissions");
136  parameters.addParameter("UserGroups");
137  parameters.addParameter("UserWithLock");
138  parameters.addParameter("Username");
139  parameters.addParameter("DisplayName");
140  // parameters.addParameter("ActiveSessionIndex");
141  SOAPUtilities::receive(retMsg, parameters);
142 
143  // first extract a few things always from parameters
144  // like permissionLevel for this request... must consider allowed groups!!
145  userInfo.setGroupPermissionLevels(parameters.getValue("Permissions"));
146  userInfo.cookieCode_ = parameters.getValue("CookieCode");
147  userInfo.username_ = parameters.getValue("Username");
148  userInfo.displayName_ = parameters.getValue("DisplayName");
149  userInfo.usernameWithLock_ = parameters.getValue("UserWithLock");
150  // userInfo.activeUserSessionIndex_ = strtoul(parameters.getValue("ActiveSessionIndex").c_str(), 0, 0);
151 
152  if(!WebUsers::checkRequestAccess(cgi, out, xmldoc, userInfo))
153  goto HANDLE_ACCESS_FAILURE; // return false, access failed
154  // else successful access request!
155 
156  return true; // request granted
157 
159 
160 HANDLE_ACCESS_FAILURE:
161 
162  // print out return string on failure
163  if(!userInfo.automatedCommand_)
164  __COUT_ERR__ << "Failed request (requestType = " << userInfo.requestType_
165  << "): " << out->str() << __E__;
166  return false; // access failed
167 } // end xmlRequestToGateway()
168 
169 //==============================================================================
174 {
175  if(time(0) - ActiveUserLastUpdateTime_ >
176  ACTIVE_USERS_UPDATE_THRESHOLD) // need to update
177  {
178  __COUTS__(2) << "Need to update active user list" << std::endl;
179 
180  xoap::MessageReference retMsg = ots::SOAPMessenger::sendWithSOAPReply(
181  gatewaySupervisorDescriptor_, "SupervisorGetActiveUsers");
182 
183  SOAPParameters retParameters("UserList");
184  SOAPUtilities::receive(retMsg, retParameters);
185 
186  ActiveUserLastUpdateTime_ = time(0);
187  return (ActiveUserList_ = retParameters.getValue("UserList"));
188  }
189  else
190  return ActiveUserList_;
191 } // end getActiveUserList()
192 
193 //==============================================================================
200  std::map<std::string /* group type */,
201  std::tuple<std::string /*group name*/,
203  std::string /* time string*/>>& theGroups)
204 {
205  xoap::MessageReference retMsg =
206  ots::SOAPMessenger::sendWithSOAPReply(gatewaySupervisorDescriptor_,
207  "SupervisorLastTableGroupRequest",
208  SOAPParameters("ActionOfLastGroup", "ALL"));
209 
210  SOAPParameters retParameters;
211  retParameters.addParameter("GroupName");
212  retParameters.addParameter("GroupKey");
213  retParameters.addParameter("GroupAction");
214  retParameters.addParameter("GroupActionTime");
215  SOAPUtilities::receive(retMsg, retParameters);
216 
217  //parse as CSV
218  std::vector<std::string> groupNames =
219  StringMacros::getVectorFromString(retParameters.getValue("GroupName"), {','});
220  std::vector<std::string> groupKeys =
221  StringMacros::getVectorFromString(retParameters.getValue("GroupKey"), {','});
222  std::vector<std::string> groupActions =
223  StringMacros::getVectorFromString(retParameters.getValue("GroupAction"), {','});
224  std::vector<std::string> groupTimes = StringMacros::getVectorFromString(
225  retParameters.getValue("GroupActionTime"), {','});
226 
227  if(groupNames.size() < 2)
228  {
229  //expecting something like 7?
230  __SS__ << "Failure in handling request for recent config group activity. "
231  "Response received was this: \n"
232  << SOAPUtilities::translate(retMsg) << __E__;
233  __SS_THROW__;
234  }
235 
236  if(groupNames.size() != groupKeys.size() ||
237  groupNames.size() != groupActions.size() || groupNames.size() != groupTimes.size())
238  {
239  __SS__ << "Illegal list size mismatch while retrieving recent config group info. "
240  "Should not be possible! Notify admins."
241  << __E__;
242  __SS_THROW__;
243  }
244 
245  for(size_t i = 0; i < groupNames.size(); ++i)
246  {
247  theGroups[groupActions[i]] = std::make_tuple(
248  groupNames[i], strtol(groupKeys[i].c_str(), 0, 0), groupTimes[i]);
249  }
250 
251  __COUTT__ << "Done with getLastTableGroups()" << __E__;
252 } // end getLastTableGroup()
253 
254 //==============================================================================
260 std::pair<std::string /*group name*/, TableGroupKey> RemoteWebUsers::getLastTableGroup(
261  const std::string& actionOfLastGroup, std::string& actionTimeString)
262 {
263  actionTimeString = "";
264  xoap::MessageReference retMsg = ots::SOAPMessenger::sendWithSOAPReply(
266  "SupervisorLastTableGroupRequest",
267  SOAPParameters("ActionOfLastGroup", actionOfLastGroup));
268 
269  SOAPParameters retParameters;
270  retParameters.addParameter("GroupName");
271  retParameters.addParameter("GroupKey");
272  retParameters.addParameter("GroupAction");
273  retParameters.addParameter("GroupActionTime");
274  SOAPUtilities::receive(retMsg, retParameters);
275 
276  std::pair<std::string /*group name*/, TableGroupKey> theGroup;
277  if(retParameters.getValue("GroupAction") !=
278  actionOfLastGroup) // if action doesn't match.. weird
279  {
280  __SS__ << "Returned group action '" << retParameters.getValue("GroupAction")
281  << "' does not match requested group action '" << actionOfLastGroup << ".'"
282  << std::endl;
283  __SS_THROW__;
284  }
285  // else we have an action match
286 
287  theGroup.first = retParameters.getValue("GroupName");
288  theGroup.second = strtol(retParameters.getValue("GroupKey").c_str(), 0, 0);
289  actionTimeString = retParameters.getValue("GroupActionTime");
290  return theGroup;
291 } // end getLastTableGroup()
292 
293 //==============================================================================
297 void RemoteWebUsers::sendSystemMessage(const std::string& toUser,
298  const std::string& message,
299  bool doEmail /*=false*/)
300 {
301  sendSystemMessage(toUser, "" /*subject*/, message, doEmail);
302 } // end sendSystemMessage)
303 
304 //==============================================================================
308 void RemoteWebUsers::sendSystemMessage(const std::string& toUser,
309  const std::string& subject,
310  const std::string& message,
311  bool doEmail /*=false*/)
312 {
313  SOAPParameters parameters;
314  parameters.addParameter("ToUser", toUser); // CSV list or *
315  parameters.addParameter("Subject", subject);
316  parameters.addParameter("Message", message);
317  parameters.addParameter("DoEmail", doEmail ? "1" : "0");
318 
319  xoap::MessageReference retMsg = SOAPMessenger::sendWithSOAPReply(
320  gatewaySupervisorDescriptor_, "SupervisorSystemMessage", parameters);
321 
322  //__COUT__ << SOAPUtilities::translate(retMsg) << __E__;
323 } // end sendSystemMessage)
324 
325 //==============================================================================
328 void RemoteWebUsers::makeSystemLogEntry(const std::string& entryText)
329 {
330  SOAPParameters parameters;
331  parameters.addParameter("EntryText", entryText);
332 
333  xoap::MessageReference retMsg = SOAPMessenger::sendWithSOAPReply(
334  gatewaySupervisorDescriptor_, "SupervisorSystemLogbookEntry", parameters);
335 
336  //__COUT__ << SOAPUtilities::translate(retMsg) << __E__;
337 } // end makeSystemLogEntry()
bool isWizardMode(void) const
BOOLs.
static std::string getOrPostData(cgicc::Cgicc &cgi, const std::string &needle)
XDAQ_CONST_CALL xdaq::ApplicationDescriptor * gatewaySupervisorDescriptor_
void getLastTableGroups(std::map< std::string, std::tuple< std::string, TableGroupKey, std::string >> &theGroups)
RemoteWebUsers(xdaq::Application *application, XDAQ_CONST_CALL xdaq::ApplicationDescriptor *gatewaySupervisorDescriptor)
std::pair< std::string, TableGroupKey > getLastTableGroup(const std::string &actionOfLastGroup, std::string &returnedActionTimeString)
actionOfLastGroup = "Configured" or "Started", for example
std::string getActiveUserList(void)
void sendSystemMessage(const std::string &toUser, const std::string &message, bool doEmail=false)
void makeSystemLogEntry(const std::string &entryText)
bool xmlRequestToGateway(cgicc::Cgicc &cgi, std::ostringstream *out, HttpXmlDocument *xmldoc, const AllSupervisorInfo &allSupervisorInfo, WebUsers::RequestUserInfo &userInfo)
XDAQ_CONST_CALL xdaq::ApplicationDescriptor * getDescriptor(void) const
Getters ----------------—.
static bool checkRequestAccess(cgicc::Cgicc &cgi, std::ostringstream *out, HttpXmlDocument *xmldoc, WebUsers::RequestUserInfo &userInfo, bool isWizardMode=false, const std::string &wizardModeSequence="")
Definition: WebUsers.cc:255
static void initializeRequestUserInfo(cgicc::Cgicc &cgi, WebUsers::RequestUserInfo &userInfo)
used by gateway and other supervisors to verify requests consistently
Definition: WebUsers.cc:234
static void getVectorFromString(const std::string &inputString, std::vector< std::string > &listToReturn, const std::set< char > &delimiter={',', '|', '&'}, const std::set< char > &whitespace={' ', '\t', '\n', '\r'}, std::vector< char > *listOfDelimiters=0, bool decodeURIComponents=false)
bool setGroupPermissionLevels(const std::string &groupPermissionLevelsString)
end setGroupPermissionLevels()
Definition: WebUsers.h:256