Утилита хороша, но как проверить в ней пересечение нескольких ролей?
Привожу код метода, который у меня работал и на R2, и сейчас работает на R3.
X++:
public boolean runas(UserId _userId)
{
UserInfo locUserInfo;
UserInfo tmpUserInfo;
UserInfo userInfoRunAs;
UserInfo tmpUserInfoRunAs;
FileName fileConfiguration;
int iResult;
int64 numSessions;
SysClientSessions sysClientSessions;
int timeStart;
OverwriteSystemfieldsPermission permission;
xInfo xInfo = new xInfo();
#WinAPI
#Admin
;
if(_userid == curuserid() || _userId == #AdminUser || curuserid() == #AdminUser)
{
throw error("!!!"); // тут метка про невозможность запуска
}
permission = new OverwriteSystemfieldsPermission();
permission.assert();
tmpUserInfo.setTmp(); // для временного хранения текущего состояния
tmpUserInfoRunAs.setTmp();
try
{
ttsbegin;
locUserInfo = xUserInfo::find(true, curuserid());
tmpUserInfo.data(locUserInfo);
userInfoRunAs = xUserInfo::find(true, _userId);
tmpUserInfoRunAs.data(userInfoRunAs);
// подменить network привязку login'а
userInfoRunAs.networkDomain = locUserInfo.networkDomain;
userInfoRunAs.networkAlias = locUserInfo.networkAlias;
userInfoRunAs.sid = locUserInfo.sid;
userInfoRunAs.enable = NoYes::Yes;
if(userInfoRunAs.validateWrite())
userInfoRunAs.update();
// отключить активность текущего пользователя
locUserInfo.sid = '';
locUserInfo.enable = NoYes::No;
if(locUserInfo.validateWrite())
locUserInfo.update();
ttscommit;
}
catch
{
return false;
}
fileConfiguration = '"' + xInfo::configuration() + '"';
if (!WinApi::fileExists(fileConfiguration))
{
fileConfiguration = '-aos2=' + strreplace(conpeek(SysEmailSMTPPassword::currentAOSInstance(), 1), '@', ':');
}
select count(RecId) from sysClientSessions
where sysClientSessions.userId == userInfoRunAs.Id &&
sysClientSessions.sid == userInfoRunAs.sid &&
sysClientSessions.Status == 1;
numSessions = sysClientSessions.RecId;
iResult = WinAPI::shellExecute(xInfo::componentName(), fileConfiguration, '', #ShellExeOpen, #SW_SHOWNORMAL, false);
if (iResult)
{
sysClientSessions.disableCache(true);
timeStart = timenow();
do
{
select count(recId) from sysClientSessions
where sysClientSessions.userId == userInfoRunAs.Id &&
sysClientSessions.sid == userInfoRunAs.sid &&
sysClientSessions.Status == 1;
if (abs(timenow() - timeStart) > 10)
{
if (box::yesNo("...", DialogButton::No) == DialogButton::Yes) // тут текст, что клиент не успел стартовать - ждать еще или нет
{
timeStart = timenow();
}
else
{
break;
}
}
}
while (sysClientSessions.RecId <= numSessions);
}
// восстановить исходное состояние данных
ttsbegin ;
locUserInfo = xUserInfo::find(true, curuserid());
locUserInfo.enable = tmpUserInfo.enable;
locUserInfo.sid = tmpUserInfo.sid;
locUserInfo.defaultPartition = tmpUserInfo.defaultPartition;
if(locUserInfo.validateWrite())
locUserInfo.update();
userInfoRunAs = xUserInfo::find(true, _userId);
userInfoRunAs.networkDomain = tmpUserInfoRunAs.networkDomain;
userInfoRunAs.networkAlias = tmpUserInfoRunAs.networkAlias;
userInfoRunAs.sid = tmpUserInfoRunAs.sid;
userInfoRunAs.enable = tmpUserInfoRunAs.enable;
userinfoRunAs.defaultPartition = tmpUserInfoRunAs.defaultPartition;
if(userInfoRunAs.validateWrite())
userInfoRunAs.update();
ttscommit;
CodeAccessPermission::revertAssert();
return !iResult;
}