otsdaq  v2_01_00
CorePropertySupervisorBase.cc
1 #include "otsdaq-core/CoreSupervisors/CorePropertySupervisorBase.h"
2 
3 using namespace ots;
4 
5 const CorePropertySupervisorBase::SupervisorProperties CorePropertySupervisorBase::SUPERVISOR_PROPERTIES = CorePropertySupervisorBase::SupervisorProperties();
6 
7 //========================================================================================================================
8 CorePropertySupervisorBase::CorePropertySupervisorBase(xdaq::Application* application)
9 : theConfigurationManager_ (new ConfigurationManager)
10 , supervisorClass_ (application->getApplicationDescriptor()->getClassName())
11 , supervisorClassNoNamespace_ (supervisorClass_.substr(supervisorClass_.find_last_of(":")+1, supervisorClass_.length()-supervisorClass_.find_last_of(":")))
12 , supervisorContextUID_ ("MUST BE INITIALIZED INSIDE THE CONTRUCTOR TO THROW EXCEPTIONS")
13 , supervisorApplicationUID_ ("MUST BE INITIALIZED INSIDE THE CONTRUCTOR TO THROW EXCEPTIONS")
14 , supervisorConfigurationPath_ ("MUST BE INITIALIZED INSIDE THE CONTRUCTOR TO THROW EXCEPTIONS")
15 , propertiesAreSetup_ (false)
16 {
17  INIT_MF("CorePropertySupervisorBase");
18 
19  __SUP_COUTV__(application->getApplicationContext()->getContextDescriptor()->getURL());
20  __SUP_COUTV__(application->getApplicationDescriptor()->getLocalId());
21  __SUP_COUTV__(supervisorClass_);
22  __SUP_COUTV__(supervisorClassNoNamespace_);
23 
24  //get all supervisor info, and wiz mode or not
25  allSupervisorInfo_.init(application->getApplicationContext());
26 
27  if(allSupervisorInfo_.isWizardMode())
28  {
29  __SUP_COUT__ << "Wiz mode detected. So skipping configuration location work for supervisor of class '" <<
30  supervisorClass_ << "'" << __E__;
31 
32  return;
33  }
34 
35  __SUP_COUT__ << "Getting configuration specific info for supervisor '" <<
36  (allSupervisorInfo_.getSupervisorInfo(application).getName()) <<
37  "' of class " << supervisorClass_ << "." << __E__;
38 
39  //get configuration specific info for the application supervisor
40 
41  try
42  {
43  CorePropertySupervisorBase::supervisorContextUID_ =
44  theConfigurationManager_->__GET_CONFIG__(XDAQContextConfiguration)->getContextUID(
45  application->getApplicationContext()->getContextDescriptor()->getURL());
46  }
47  catch(...)
48  {
49  __SUP_COUT_ERR__ << "XDAQ Supervisor could not access it's configuration through the theConfigurationManager_." <<
50  //" The XDAQContextConfigurationName = " << XDAQContextConfigurationName_ <<
51  ". The getApplicationContext()->getContextDescriptor()->getURL() = " <<
52  application->getApplicationContext()->getContextDescriptor()->getURL() << std::endl;
53  throw;
54  }
55 
56  try
57  {
58  CorePropertySupervisorBase::supervisorApplicationUID_ =
59  theConfigurationManager_->__GET_CONFIG__(XDAQContextConfiguration)->getApplicationUID
60  (
61  application->getApplicationContext()->getContextDescriptor()->getURL(),
62  application->getApplicationDescriptor()->getLocalId()
63  );
64  }
65  catch(...)
66  {
67  __SUP_COUT_ERR__ << "XDAQ Supervisor could not access it's configuration through the theConfigurationManager_." <<
68  " The supervisorContextUID_ = " << supervisorContextUID_ <<
69  ". The supervisorApplicationUID = " << supervisorApplicationUID_ << std::endl;
70  throw;
71  }
72 
73  CorePropertySupervisorBase::supervisorConfigurationPath_ = "/" +
74  CorePropertySupervisorBase::supervisorContextUID_ + "/LinkToApplicationConfiguration/" +
75  CorePropertySupervisorBase::supervisorApplicationUID_ + "/LinkToSupervisorConfiguration";
76 
77  __SUP_COUTV__(CorePropertySupervisorBase::supervisorContextUID_);
78  __SUP_COUTV__(CorePropertySupervisorBase::supervisorApplicationUID_);
79  __SUP_COUTV__(CorePropertySupervisorBase::supervisorConfigurationPath_);
80 }
81 
82 
83 //========================================================================================================================
84 CorePropertySupervisorBase::~CorePropertySupervisorBase(void)
85 {
86 }
87 
88 
89 //========================================================================================================================
90 //When overriding, setup default property values here
91 // called by CorePropertySupervisorBase constructor before loading user defined property values
92 void CorePropertySupervisorBase::setSupervisorPropertyDefaults(void)
93 {
94  //This can be done in the constructor because when you start xdaq it loads the configuration that can't be changed while running!
95 
96  //__SUP_COUT__ << "Setting up Core Supervisor Base property defaults for supervisor" <<
97  // "..." << __E__;
98 
99  //set core Supervisor base class defaults
100  CorePropertySupervisorBase::setSupervisorProperty(CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.UserPermissionsThreshold, "*=1");
101  CorePropertySupervisorBase::setSupervisorProperty(CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.UserGroupsAllowed, "");
102  CorePropertySupervisorBase::setSupervisorProperty(CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.UserGroupsDisallowed, "");
103 
104  CorePropertySupervisorBase::setSupervisorProperty(CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.CheckUserLockRequestTypes, "");
105  CorePropertySupervisorBase::setSupervisorProperty(CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.RequireUserLockRequestTypes, "");
106  CorePropertySupervisorBase::setSupervisorProperty(CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AutomatedRequestTypes, "");
107  CorePropertySupervisorBase::setSupervisorProperty(CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.AllowNoLoginRequestTypes, "");
108 
109  CorePropertySupervisorBase::setSupervisorProperty(CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.NoXmlWhiteSpaceRequestTypes, "");
110  CorePropertySupervisorBase::setSupervisorProperty(CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.NonXMLRequestTypes, "");
111 
112 
113 // __SUP_COUT__ << "Done setting up Core Supervisor Base property defaults for supervisor" <<
114 // "..." << __E__;
115 }
116 
117 //========================================================================================================================
118 //extractPermissionsMapFromString
119 // Static function that extract map function to standardize approach
120 // in case needed by supervisors for special permissions handling.
121 // For example, used to serve Desktop Icons.
122 //
123 // permissionsString format is as follows:
124 // <groupName>:<permissionsThreshold> pairs separated by ',' '&' or '|'
125 // for example, to give access admins and pixel team but not calorimeter team:
126 // allUsers:255 | pixelTeam:1 | calorimeterTeam:0
127 //
128 // Use with CorePropertySupervisorBase::doPermissionsGrantAccess to determine
129 // if access is allowed.
130 void CorePropertySupervisorBase::extractPermissionsMapFromString(const std::string& permissionsString,
131  std::map<std::string,WebUsers::permissionLevel_t>& permissionsMap)
132 {
133  permissionsMap.clear();
134  StringMacros::getMapFromString(
135  permissionsString,
136  permissionsMap);
137 }
138 
139 //========================================================================================================================
140 //doPermissionsGrantAccess
141 // Static function that checks permissionLevelsMap against permissionThresholdsMap and returns true if
142 // access requirements are met.
143 //
144 // This is useful in standardizing approach for supervisors in case of
145 // of special permissions handling.
146 // For example, used to serve Desktop Icons.
147 //
148 // permissionLevelsString format is as follows:
149 // <groupName>:<permissionsLevel> pairs separated by ',' '&' or '|'
150 // for example, to be a standard user and an admin on the pixel team and no access to calorimeter team:
151 // allUsers:1 | pixelTeam:255 | calorimeterTeam:0
152 //
153 // permissionThresoldsString format is as follows:
154 // <groupName>:<permissionsThreshold> pairs separated by ',' '&' or '|'
155 // for example, to give access admins and pixel team but not calorimeter team:
156 // allUsers:255 | pixelTeam:1 | calorimeterTeam:0
157 bool CorePropertySupervisorBase::doPermissionsGrantAccess(
158  std::map<std::string,WebUsers::permissionLevel_t>& permissionLevelsMap,
159  std::map<std::string,WebUsers::permissionLevel_t>& permissionThresholdsMap)
160 {
161  //return true if a permission level group name is found with a permission level
162  // greater than or equal to the permission level at a matching group name entry in the thresholds map.
163 
164  //__COUTV__(StringMacros::mapToString(permissionLevelsMap));
165  //__COUTV__(StringMacros::mapToString(permissionThresholdsMap));
166 
167  for(const auto& permissionLevelGroupPair: permissionLevelsMap)
168  {
169  //__COUTV__(permissionLevelGroupPair.first); __COUTV__(permissionLevelGroupPair.second);
170 
171  for(const auto& permissionThresholdGroupPair: permissionThresholdsMap)
172  {
173  //__COUTV__(permissionThresholdGroupPair.first); __COUTV__(permissionThresholdGroupPair.second);
174  if(permissionLevelGroupPair.first == permissionThresholdGroupPair.first &&
175  permissionThresholdGroupPair.second && //not explicitly disallowed
176  permissionLevelGroupPair.second >= permissionThresholdGroupPair.second)
177  return true; //access granted!
178  }
179  }
180  //if here, no access group match found
181  //so denied
182  return false;
183 } //end doPermissionsGrantAccess
184 
185 
186 //========================================================================================================================
187 void CorePropertySupervisorBase::checkSupervisorPropertySetup()
188 {
189  if(propertiesAreSetup_) return;
190 
191  //Immediately mark properties as setup, (prevent infinite loops due to
192  // other launches from within this function, e.g. from getSupervisorProperty)
193  // only redo if Context configuration group changes
194  propertiesAreSetup_ = true;
195 
196 
197  CorePropertySupervisorBase::setSupervisorPropertyDefaults(); //calls base class version defaults
198 
199  //__SUP_COUT__ << "Setting up supervisor specific property DEFAULTS for supervisor..." << __E__;
200  setSupervisorPropertyDefaults(); //calls override version defaults
201 // __SUP_COUT__ << "Done setting up supervisor specific property DEFAULTS for supervisor" <<
202 // "." << __E__;
203 
204  if(allSupervisorInfo_.isWizardMode())
205  __SUP_COUT__ << "Wiz mode detected. Skipping setup of supervisor properties for supervisor of class '" <<
206  supervisorClass_ <<
207  "'" << __E__;
208  else
209  CorePropertySupervisorBase::loadUserSupervisorProperties(); //loads user settings from configuration
210 
211 
212  //__SUP_COUT__ << "Setting up supervisor specific FORCED properties for supervisor..." << __E__;
213  forceSupervisorPropertyValues(); //calls override forced values
214 // __SUP_COUT__ << "Done setting up supervisor specific FORCED properties for supervisor" <<
215 // "." << __E__;
216 
217  CorePropertySupervisorBase::extractPermissionsMapFromString(
218  getSupervisorProperty(
219  CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.UserPermissionsThreshold),
220  propertyStruct_.UserPermissionsThreshold);
221 
222  propertyStruct_.UserGroupsAllowed.clear();
223  StringMacros::getMapFromString(
224  getSupervisorProperty(
225  CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.UserGroupsAllowed),
226  propertyStruct_.UserGroupsAllowed);
227 
228  propertyStruct_.UserGroupsDisallowed.clear();
229  StringMacros::getMapFromString(
230  getSupervisorProperty(
231  CorePropertySupervisorBase::SUPERVISOR_PROPERTIES.UserGroupsDisallowed),
232  propertyStruct_.UserGroupsDisallowed);
233 
234  auto nameIt = SUPERVISOR_PROPERTIES.allSetNames_.begin();
235  auto setIt = propertyStruct_.allSets_.begin();
236  while(nameIt != SUPERVISOR_PROPERTIES.allSetNames_.end() &&
237  setIt != propertyStruct_.allSets_.end())
238  {
239  (*setIt)->clear();
240  StringMacros::getSetFromString(
241  getSupervisorProperty(
242  *(*nameIt)),
243  *(*setIt));
244 
245  ++nameIt; ++setIt;
246  }
247 
248 
249  __SUP_COUT__ << "Final supervisor property settings:" << std::endl;
250  for(auto& property: propertyMap_)
251  __SUP_COUT__ << "\t" << property.first << " = " << property.second << __E__;
252 }
253 
254 //========================================================================================================================
255 //getSupervisorTreeNode ~
256 // try to get this Supervisors configuration tree node
257 ConfigurationTree CorePropertySupervisorBase::getSupervisorTreeNode(void)
258 try
259 {
260  if(supervisorContextUID_ == "" || supervisorApplicationUID_ == "")
261  {
262  __SUP_SS__ << "Empty supervisorContextUID_ or supervisorApplicationUID_." << __E__;
263  __SUP_SS_THROW__;
264  }
265  return theConfigurationManager_->getSupervisorNode(
266  supervisorContextUID_, supervisorApplicationUID_);
267 }
268 catch(...)
269 {
270  __SUP_COUT_ERR__ << "XDAQ Supervisor could not access it's configuration node through theConfigurationManager_ " <<
271  "(Did you remember to initialize using CorePropertySupervisorBase::init()?)." <<
272  " The supervisorContextUID_ = " << supervisorContextUID_ <<
273  ". The supervisorApplicationUID = " << supervisorApplicationUID_ << std::endl;
274  throw;
275 }
276 
277 //========================================================================================================================
278 //loadUserSupervisorProperties ~
279 // try to get user supervisor properties
280 void CorePropertySupervisorBase::loadUserSupervisorProperties(void)
281 {
282 // __SUP_COUT__ << "Loading user properties for supervisor '" <<
283 // supervisorContextUID_ << "/" << supervisorApplicationUID_ <<
284 // "'..." << __E__;
285 
286  //re-acquire the configuration supervisor node, in case the config has changed
287  auto supervisorNode = CorePropertySupervisorBase::getSupervisorTreeNode();
288 
289  try
290  {
291  auto /*map<name,node>*/ children = supervisorNode.getNode("LinkToPropertyConfiguration").getChildren();
292 
293  for(auto& child:children)
294  {
295  if(child.second.getNode("Status").getValue<bool>() == false) continue; //skip OFF properties
296 
297  auto propertyName = child.second.getNode("PropertyName").getValue();
298  setSupervisorProperty(propertyName, child.second.getNode("PropertyValue").getValue<std::string>());
299  }
300  }
301  catch(...)
302  {
303  __SUP_COUT__ << "No user supervisor property settings found in the configuration tree, going with the defaults." << __E__;
304  }
305 
306  // __SUP_COUT__ << "Done loading user properties for supervisor '" <<
307  // supervisorContextUID_ << "/" << supervisorApplicationUID_ <<
308  // "'" << __E__;
309 }
310 
311 //========================================================================================================================
312 void CorePropertySupervisorBase::setSupervisorProperty(const std::string& propertyName, const std::string& propertyValue)
313 {
314  propertyMap_[propertyName] = propertyValue;
315 // __SUP_COUT__ << "Set propertyMap_[" << propertyName <<
316 // "] = " << propertyMap_[propertyName] << __E__;
317 }
318 
319 //========================================================================================================================
320 void CorePropertySupervisorBase::addSupervisorProperty(const std::string& propertyName, const std::string& propertyValue)
321 {
322  propertyMap_[propertyName] = propertyValue + " | " + getSupervisorProperty(propertyName);
323 // __SUP_COUT__ << "Set propertyMap_[" << propertyName <<
324 // "] = " << propertyMap_[propertyName] << __E__;
325 }
326 
327 
328 //========================================================================================================================
329 //getSupervisorProperty
330 // string version of template function
331 std::string CorePropertySupervisorBase::getSupervisorProperty(const std::string& propertyName)
332 {
333  //check if need to setup properties
334  checkSupervisorPropertySetup ();
335 
336  auto it = propertyMap_.find(propertyName);
337  if(it == propertyMap_.end())
338  {
339  __SUP_SS__ << "Could not find property named " << propertyName << __E__;
340  throw std::runtime_error(ss.str());//__SUP_SS_THROW__;
341  }
342  return StringMacros::validateValueForDefaultStringDataType(it->second);
343 }
344 
345 //========================================================================================================================
346 //getSupervisorPropertyUserPermissionsThreshold
347 // returns the threshold based on the requestType
348 WebUsers::permissionLevel_t CorePropertySupervisorBase::getSupervisorPropertyUserPermissionsThreshold(
349  const std::string& requestType)
350 {
351  //check if need to setup properties
352  checkSupervisorPropertySetup();
353 
354  return StringMacros::getWildCardMatchFromMap(requestType,
355  propertyStruct_.UserPermissionsThreshold);
356 
357 // auto it = propertyStruct_.UserPermissionsThreshold.find(requestType);
358 // if(it == propertyStruct_.UserPermissionsThreshold.end())
359 // {
360 // __SUP_SS__ << "Could not find requestType named " << requestType << " in UserPermissionsThreshold map." << __E__;
361 // throw std::runtime_error(ss.str()); //__SUP_SS_THROW__;
362 // }
363 // return it->second;
364 }
365 
366 //========================================================================================================================
367 //getRequestUserInfo ~
368 // extract user info for request based on property configuration
369 void CorePropertySupervisorBase::getRequestUserInfo(WebUsers::RequestUserInfo& userInfo)
370 {
371  checkSupervisorPropertySetup();
372 
373  //__SUP_COUT__ << "userInfo.requestType_ " << userInfo.requestType_ << " files: " << cgiIn.getFiles().size() << std::endl;
374 
375  userInfo.automatedCommand_ = StringMacros::inWildCardSet(userInfo.requestType_, propertyStruct_.AutomatedRequestTypes); //automatic commands should not refresh cookie code.. only user initiated commands should!
376  userInfo.NonXMLRequestType_ = StringMacros::inWildCardSet(userInfo.requestType_, propertyStruct_.NonXMLRequestTypes); //non-xml request types just return the request return string to client
377  userInfo.NoXmlWhiteSpace_ = StringMacros::inWildCardSet(userInfo.requestType_, propertyStruct_.NoXmlWhiteSpaceRequestTypes);
378 
379  //**** start LOGIN GATEWAY CODE ***//
380  //check cookieCode, sequence, userWithLock, and permissions access all in one shot!
381  {
382  userInfo.checkLock_ = StringMacros::inWildCardSet(userInfo.requestType_, propertyStruct_.CheckUserLockRequestTypes);
383  userInfo.requireLock_ = StringMacros::inWildCardSet(userInfo.requestType_, propertyStruct_.RequireUserLockRequestTypes);
384  userInfo.allowNoUser_ = StringMacros::inWildCardSet(userInfo.requestType_, propertyStruct_.AllowNoLoginRequestTypes);
385 
386 
387 
388  userInfo.permissionsThreshold_ = -1; //default to max
389  try
390  {
391  userInfo.permissionsThreshold_ = CorePropertySupervisorBase::getSupervisorPropertyUserPermissionsThreshold(
392  userInfo.requestType_);
393  }
394  catch(std::runtime_error& e)
395  {
396  if(!userInfo.automatedCommand_)
397  __SUP_COUT__ << "No explicit permissions threshold for request '" <<
398  userInfo.requestType_ << "'... Defaulting to max threshold = " <<
399  (unsigned int)userInfo.permissionsThreshold_ << __E__;
400  }
401 
402  // __COUTV__(userInfo.requestType_);
403  // __COUTV__(userInfo.checkLock_);
404  // __COUTV__(userInfo.requireLock_);
405  // __COUTV__(userInfo.allowNoUser_);
406  // __COUTV__((unsigned int)userInfo.permissionsThreshold_);
407 
408  try
409  {
410  StringMacros::getSetFromString(
411  StringMacros::getWildCardMatchFromMap(userInfo.requestType_,
412  propertyStruct_.UserGroupsAllowed),
413  userInfo.groupsAllowed_);
414  }
415  catch(std::runtime_error& e)
416  {
417  userInfo.groupsAllowed_.clear();
418 
419 // if(!userInfo.automatedCommand_)
420 // __SUP_COUT__ << "No explicit groups allowed for request '" <<
421 // userInfo.requestType_ << "'... Defaulting to empty groups allowed. " << __E__;
422  }
423  try
424  {
425  StringMacros::getSetFromString(
426  StringMacros::getWildCardMatchFromMap(userInfo.requestType_,
427  propertyStruct_.UserGroupsDisallowed),
428  userInfo.groupsDisallowed_);
429  }
430  catch(std::runtime_error& e)
431  {
432  userInfo.groupsDisallowed_.clear();
433 
434 // if(!userInfo.automatedCommand_)
435 // __SUP_COUT__ << "No explicit groups disallowed for request '" <<
436 // userInfo.requestType_ << "'... Defaulting to empty groups disallowed. " << __E__;
437  }
438  } //**** end LOGIN GATEWAY CODE ***//
439 
440  //completed user info, for the request type, is returned to caller
441 }
442