Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
+184
@@ -0,0 +1,184 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
INCLUDE(MacroRTIDDSGen)
|
||||
INCLUDE(MacroCodeGenIdl)
|
||||
|
||||
SET(xml_FILE opm_service.xml)
|
||||
|
||||
#
|
||||
# --- Library svcOpmCommon --------------------------------------------------------------------------------
|
||||
#
|
||||
SET(SRCS_common
|
||||
opm_export.h
|
||||
logger.cpp
|
||||
logger.h
|
||||
)
|
||||
|
||||
# Generate opm_enums.idl / opm.idl
|
||||
CODEGEN_IDL_SVC(SRCS_common ${xml_FILE})
|
||||
# Generate opm_db_impl.cpp/.h, opm_db.h
|
||||
CODEGEN_DATABASE(SRCS_common ${xml_FILE})
|
||||
|
||||
# Generate *.cpp/*.hpp from idl
|
||||
RTIDDSGEN(SRCS_common opm_enums.idl)
|
||||
RTIDDSGEN(SRCS_common opm.idl)
|
||||
|
||||
# Generate opm_dt[s,c]_types.h, opm_ft[s,c]_types.h
|
||||
CODEGEN_TOPIC_TYPEDEFS(SRCS_common ${xml_FILE})
|
||||
# generate opm_[d|f]tc.h
|
||||
CODEGEN_CLIENT_TOPICS_IFC(SRCS_common ${xml_FILE})
|
||||
|
||||
NGL_ADD_LIBRARY(AAR SV WS svcOpmCommon SHARED ${SRCS_common})
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(svcOpmCommon
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../
|
||||
)
|
||||
NGL_TARGET_LINK_LIBRARIES(svcOpmCommon
|
||||
PRIVATE
|
||||
RTI::nddscpp2
|
||||
PUBLIC
|
||||
Qt5::Core
|
||||
ddscore
|
||||
ngldb
|
||||
LtsUtilsCore
|
||||
NGLLogger
|
||||
)
|
||||
NGL_INSTALL_TARGET(svcOpmCommon)
|
||||
|
||||
#
|
||||
# --- Library svcOpmClient --------------------------------------------------------------------------------
|
||||
#
|
||||
SET(SRCS_client
|
||||
opm_export.h
|
||||
opm_dtc_impl_custom.cpp
|
||||
opm_dtc_impl_custom.h
|
||||
)
|
||||
# generate opm_ftc_impl.[cpp|h]
|
||||
CODEGEN_CLIENT_TOPICS_IMPL(SRCS_client ${xml_FILE})
|
||||
|
||||
NGL_ADD_LIBRARY(AAR SV WS svcOpmClient SHARED ${SRCS_client})
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(svcOpmClient
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../
|
||||
)
|
||||
|
||||
NGL_TARGET_LINK_LIBRARIES(svcOpmClient
|
||||
PRIVATE
|
||||
RTI::nddscpp2
|
||||
ddsconnector
|
||||
PUBLIC
|
||||
svcOpmCommon
|
||||
ddsftc
|
||||
)
|
||||
NGL_INSTALL_TARGET(svcOpmClient)
|
||||
|
||||
#
|
||||
# --- Library svcOpmServer --------------------------------------------------------------------------------
|
||||
#
|
||||
SET(SRCS_server
|
||||
opm_export.h
|
||||
)
|
||||
# generate opm_[d|f]ts.h, opm_[d|f]ts_impl.[cpp|h]
|
||||
CODEGEN_SERVER_TOPICS(SRCS_server ${xml_FILE})
|
||||
|
||||
NGL_ADD_LIBRARY(AAR SV svcOpmServer SHARED ${SRCS_server})
|
||||
NGL_TARGET_INCLUDE_DIRECTORIES(svcOpmServer
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../
|
||||
)
|
||||
|
||||
NGL_TARGET_LINK_LIBRARIES(svcOpmServer
|
||||
PRIVATE
|
||||
RTI::nddscpp2
|
||||
ddsconnector
|
||||
ddsfts
|
||||
PUBLIC
|
||||
svcOpmCommon
|
||||
ngldb
|
||||
LtsUtilsCore
|
||||
)
|
||||
NGL_INSTALL_TARGET(svcOpmServer)
|
||||
|
||||
#
|
||||
# --- Topic Type Plugin --------------------------------------------------------------
|
||||
#
|
||||
CREATE_TOPIC_TYPE_PLUGIN(${xml_FILE})
|
||||
|
||||
#
|
||||
# --- Executable svcOperatorManagement (sOPM) -------------------------------------------------
|
||||
#
|
||||
SET(SRCS_exe
|
||||
main.cpp
|
||||
settings.cpp
|
||||
settings.h
|
||||
dds_handler.cpp
|
||||
dds_handler.h
|
||||
main_handler.cpp
|
||||
main_handler.h
|
||||
|
||||
handler_active_apps.cpp
|
||||
handler_active_apps.h
|
||||
handler_access_control_level.cpp
|
||||
handler_access_control_level.h
|
||||
handler_locked_topics.cpp
|
||||
handler_locked_topics.h
|
||||
handler_group.cpp
|
||||
handler_group.h
|
||||
handler_operator.cpp
|
||||
handler_operator.h
|
||||
|
||||
object_access_control_level.cpp
|
||||
object_access_control_level.h
|
||||
object_group.cpp
|
||||
object_group.h
|
||||
object_operator.cpp
|
||||
object_operator.h
|
||||
|
||||
WebSocketInterface/data_manager.cpp
|
||||
WebSocketInterface/data_manager.h
|
||||
WebSocketInterface/json_keys.h
|
||||
WebSocketInterface/websocket_interface_handler.cpp
|
||||
WebSocketInterface/websocket_interface_handler.h
|
||||
WebSocketInterface/Messages/client_message.cpp
|
||||
WebSocketInterface/Messages/client_message.h
|
||||
WebSocketInterface/Messages/reply_message.cpp
|
||||
WebSocketInterface/Messages/reply_message.h
|
||||
${xml_FILE}
|
||||
)
|
||||
|
||||
# Generate opm.sql, opm.xml
|
||||
CODEGEN_SQL(SRCS_exe ${xml_FILE})
|
||||
|
||||
NGL_ADD_SVC_ICON(SRCS_exe)
|
||||
NGL_ADD_EXECUTABLE(AAR SV svcOperatorManagement ${SRCS_exe})
|
||||
NGL_TARGET_LINK_LIBRARIES(svcOperatorManagement
|
||||
Qt5::Core
|
||||
ddsfts
|
||||
svcAsmClient
|
||||
svcCoreClient
|
||||
svcOpmCommon
|
||||
svcOpmClient
|
||||
svcOpmServer
|
||||
ddsconnector
|
||||
nglsettings
|
||||
ProjectConfig
|
||||
LtsCommandLineParser
|
||||
LtsWebSocketServer
|
||||
NGLLogger
|
||||
nglcoreapplication
|
||||
ngltools
|
||||
)
|
||||
NGL_INSTALL_TARGET(svcOperatorManagement)
|
||||
NGL_INSTALL(AAR SV FILES log4cxx_opm.props DESTINATION bin)
|
||||
NGL_ADD_TARGET_LINK(svcOperatorManagement sOPM)
|
||||
|
||||
# Uncomment if necessary
|
||||
#ADD_SUBDIRECTORY(UnitTests)
|
||||
ADD_SUBDIRECTORY(ModuleTests)
|
||||
@@ -0,0 +1,33 @@
|
||||
#
|
||||
# $Id$
|
||||
# $HeadURL$
|
||||
# $Author$
|
||||
#
|
||||
|
||||
SET(SRCS_OPM_TEST
|
||||
opm_tests.cpp
|
||||
)
|
||||
SET(HDRS_OPM_TEST
|
||||
opm_tests.h
|
||||
)
|
||||
|
||||
IF(BUILD_TESTING)
|
||||
IF(TARGET svcOpmClient)
|
||||
|
||||
# Testing FunctionTopic Functionality (FTC)
|
||||
ADD_EXECUTABLE(opmTests ${SRCS_OPM_TEST} ${HDRS_OPM_TEST})
|
||||
TARGET_LINK_LIBRARIES(opmTests
|
||||
Qt5::Core
|
||||
Qt5::Test
|
||||
RTI::nddscpp2
|
||||
svcOpmClient
|
||||
LtsCommandLineParser
|
||||
ddsconnector
|
||||
nglcoreapplication
|
||||
)
|
||||
IF(NOT BUILD_RPM)
|
||||
NGL_INSTALL(AAR SV TARGETS opmTests DESTINATION bin/test)
|
||||
NGL_INSTALL(AAR SV FILES ../log4cxx_opm.props DESTINATION bin/test)
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
ENDIF()
|
||||
+630
@@ -0,0 +1,630 @@
|
||||
/**
|
||||
* opm Function Topic test executable
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2016-04-18
|
||||
*/
|
||||
#include "opm_tests.h"
|
||||
|
||||
#include <nglapplication/nglcoreapplication.h>
|
||||
#include <LtsCommandLineParser/LtsCommandLineParser.h>
|
||||
|
||||
#include <OperatorManagement/opm_ftc.h>
|
||||
#include <OperatorManagement/opm_dtc.h>
|
||||
#include <AreaEffectSimulation/aes_operator_rights.h>
|
||||
|
||||
#include <QTimer>
|
||||
#include <QTest>
|
||||
#include <QCryptographicHash>
|
||||
#include <QVector>
|
||||
|
||||
using namespace OperatorManagement;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
OpmTests::OpmTests(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_exerciseId(0)
|
||||
, m_testId(0)
|
||||
, m_operatorId(0)
|
||||
, m_createdId(0)
|
||||
, m_eTestStep(eUnknown)
|
||||
, m_bTestsSuccessful(true)
|
||||
, m_logger(getLogger("OpmTests"))
|
||||
{
|
||||
qRegisterMetaType<Core::FunctionReply>("Core::FunctionReply");
|
||||
} // end of ctor()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
OpmTests::~OpmTests()
|
||||
{
|
||||
} // end of dtor()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool OpmTests::init(int domainId, int exerciseId, int testId, int operatorId, int createdId)
|
||||
{
|
||||
INFO_LOG(m_logger) << "OpmTests::init() "
|
||||
<< " domainId:" << domainId
|
||||
<< " exerciseId:" << exerciseId
|
||||
<< " testId: " << testId
|
||||
<< " operatorId: " << operatorId
|
||||
<< " createdId: " << createdId;
|
||||
|
||||
m_testId = testId;
|
||||
m_exerciseId = exerciseId;
|
||||
m_operatorId = operatorId;
|
||||
m_createdId = createdId;
|
||||
|
||||
// initialize DDS
|
||||
m_ddsConnector.reset(new DDSConnector::DdsConnector(domainId, IDL::PartitionType::Exercise, exerciseId));
|
||||
if (!m_ddsConnector->init())
|
||||
return false;
|
||||
m_ddsConnector->initPublisherSubscriber();
|
||||
|
||||
// Access to FTC
|
||||
DEBUG_LOG(m_logger) << "create ftc";
|
||||
m_ftc = OperatorManagement::Interface::Ftc::create(m_ddsConnector);
|
||||
DEBUG_LOG(m_logger) << "init ftc";
|
||||
bool bRet = m_ftc->enableAll();
|
||||
DEBUG_LOG(m_logger) << "init end - bRet = " << bRet;
|
||||
|
||||
// Access to DTC
|
||||
DEBUG_LOG(m_logger) << "create dtc";
|
||||
m_dtc = OperatorManagement::Interface::Dtc::create(m_ddsConnector);
|
||||
DEBUG_LOG(m_logger) << "init dtc";
|
||||
bRet = m_dtc->enableAll();
|
||||
DEBUG_LOG(m_logger) << "init end - bRet = " << bRet;
|
||||
|
||||
connect(m_dtc.get(), &Interface::Dtc::userChanged,
|
||||
this, &OpmTests::onReceiveOperatorChanged);
|
||||
|
||||
connect(m_dtc.get(), &Interface::Dtc::groupChanged,
|
||||
this, &OpmTests::onReceiveGroupChanged);
|
||||
|
||||
return bRet;
|
||||
} // end of init()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void OpmTests::startTest()
|
||||
{
|
||||
INFO_LOG(m_logger) << "startTest() exerciseId:" << m_exerciseId
|
||||
<< " testId:" << m_testId
|
||||
<< " operatorId:" << m_operatorId
|
||||
;
|
||||
if (m_testId <= 1)
|
||||
QTimer::singleShot(0, this, &OpmTests::tryCreate);
|
||||
else if (m_testId == 2)
|
||||
QTimer::singleShot(0, this, &OpmTests::tryModify);
|
||||
else if (m_testId == 3)
|
||||
QTimer::singleShot(0, this, &OpmTests::tryRemove);
|
||||
else if (m_testId == 4)
|
||||
QTimer::singleShot(0, this, &OpmTests::tryLogin);
|
||||
else if (m_testId == 5)
|
||||
QTimer::singleShot(0, this, &OpmTests::tryLogout);
|
||||
else if (m_testId == 6)
|
||||
QTimer::singleShot(0, this, &OpmTests::tryLoginForce);
|
||||
else if (m_testId == 7)
|
||||
QTimer::singleShot(0, this, &OpmTests::tryGetOperatorsByOperatorRight);
|
||||
|
||||
else if (m_testId == 10)
|
||||
QTimer::singleShot(0, this, &OpmTests::tryGetAllOperators);
|
||||
else if (m_testId == 11)
|
||||
QTimer::singleShot(0, this, &OpmTests::tryGetOperator);
|
||||
|
||||
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
|
||||
|
||||
} // end of startTest()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void OpmTests::tryCreate()
|
||||
{
|
||||
m_eTestStep = eCreate;
|
||||
OperatorCreateModifyRequest data;
|
||||
getOperatorCreateRequestData( data);
|
||||
|
||||
INFO_LOG(m_logger) << "trying to send OperatorCreateRequest";
|
||||
if (!m_ftc->operatorCreateModifyRequest(data, this))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error requesting create data";
|
||||
failExit();
|
||||
}
|
||||
QTest::qWait(1000);
|
||||
} // end of tryCreate()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void OpmTests::tryModify()
|
||||
{
|
||||
m_eTestStep = eModify;
|
||||
OperatorCreateModifyRequest data;
|
||||
getOperatorModifyRequestData(data);
|
||||
|
||||
INFO_LOG(m_logger) << "trying to send OperatorCreateModifyRequest";
|
||||
if (!m_ftc->operatorCreateModifyRequest(data, this))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error requesting modify data";
|
||||
failExit();
|
||||
}
|
||||
QTest::qWait(1000);
|
||||
} // end of tryModify()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void OpmTests::tryRemove()
|
||||
{
|
||||
m_eTestStep = eRemove;
|
||||
OperatorRemoveRequest data;
|
||||
|
||||
data.id(m_operatorId);
|
||||
|
||||
INFO_LOG(m_logger) << "trying to send remove request";
|
||||
if (!m_ftc->operatorRemoveRequest(data, this))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error requesting remove data";
|
||||
failExit();
|
||||
}
|
||||
QTest::qWait(1000);
|
||||
} // end of tryRemove()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void OpmTests::tryLogin()
|
||||
{
|
||||
NOTICE_LOG(m_logger) << "tryLogin";
|
||||
|
||||
m_eTestStep = eLogin;
|
||||
OperatorLoginRequest data;
|
||||
|
||||
data.id(m_operatorId);
|
||||
std::string pass("ctc");
|
||||
|
||||
const QByteArray ba(QByteArray::fromRawData(pass.c_str(), pass.size()));
|
||||
//pass = QCryptographicHash::hash(ba, QCryptographicHash::Md5).toHex().data();
|
||||
|
||||
data.password(pass);
|
||||
data.workstationIp(-1);
|
||||
data.workstationId(301);
|
||||
data.force(false);
|
||||
|
||||
NOTICE_LOG(m_logger) << "trying to send OperatorLoginRequest"
|
||||
<< ", operatorId:" << m_operatorId
|
||||
<< ", pass:" << pass
|
||||
<< ", workstationIp:" << data.workstationIp()
|
||||
<< ", workstationId:" << data.workstationId()
|
||||
<< ", force:" << data.force();
|
||||
if (!m_ftc->operatorLoginRequest(data, this))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error login operator id " << m_operatorId << " on workstation 1";
|
||||
failExit();
|
||||
}
|
||||
QTest::qWait(1000);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void OpmTests::tryLoginForce()
|
||||
{
|
||||
m_eTestStep = eLogin;
|
||||
OperatorLoginRequest data;
|
||||
|
||||
data.id(m_operatorId);
|
||||
std::string pass("password");
|
||||
|
||||
const QByteArray ba(QByteArray::fromRawData(pass.c_str(), pass.size()));
|
||||
pass = QCryptographicHash::hash(ba, QCryptographicHash::Md5).toHex().data();
|
||||
|
||||
data.password(pass);
|
||||
data.workstationIp(-1);
|
||||
data.workstationId(4);
|
||||
data.force(true);
|
||||
|
||||
INFO_LOG(m_logger) << "trying to send OperatorLoginRequest";
|
||||
if (!m_ftc->operatorLoginRequest(data, this))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error login operator id " << m_operatorId << " on workstation 1";
|
||||
failExit();
|
||||
}
|
||||
QTest::qWait(1000);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void OpmTests::tryLogout()
|
||||
{
|
||||
m_eTestStep = eLogout;
|
||||
OperatorLogoutRequest data;
|
||||
|
||||
data.id(m_operatorId);
|
||||
|
||||
INFO_LOG(m_logger) << "trying to send OperatorLogoutRequest";
|
||||
if (!m_ftc->operatorLogoutRequest(data, this))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error logout operator id " << m_operatorId;
|
||||
failExit();
|
||||
}
|
||||
QTest::qWait(1000);
|
||||
}
|
||||
|
||||
void OpmTests::tryGetOperatorsByOperatorRight()
|
||||
{
|
||||
m_eTestStep = eGetOperatoryByOperatorRight;
|
||||
|
||||
int operatorRight = OperatorRights::CContaminationsEdit;
|
||||
|
||||
m_dtc->waitForHistoricalDataUser();
|
||||
INFO_LOG(m_logger) << "trying to send get operators by operatorRight";
|
||||
QVector<int> operators = m_dtc->getOperatorsByOperatorRight(operatorRight);
|
||||
if (operators.empty())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error no operators for operatorRight: " << operatorRight;
|
||||
failExit();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int operatorId : operators)
|
||||
{
|
||||
INFO_LOG(m_logger) << "Operator " << operatorId << " found.";
|
||||
}
|
||||
}
|
||||
QTest::qWait(1000);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void OpmTests::tryGetAllOperators()
|
||||
{
|
||||
m_eTestStep = eGetAllOperators;
|
||||
DEBUG_LOG(m_logger) << "trying to get all operators";
|
||||
|
||||
m_dtc->waitForHistoricalDataUser();
|
||||
const QMap<qint32, OperatorManagement::User> opMap = m_dtc->users();
|
||||
if(opMap.isEmpty())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error requesting all operator data";
|
||||
failExit();
|
||||
}
|
||||
else
|
||||
{
|
||||
INFO_LOG(m_logger) << "Amout of existing operators = " << opMap.size();
|
||||
m_operatorId = opMap.firstKey();
|
||||
for(auto it = opMap.begin(); it != opMap.end(); ++it)
|
||||
{
|
||||
INFO_LOG(m_logger) << "opm(" << it.key() << ") :"
|
||||
<< " name:" << it.value().name()
|
||||
// << " password:" << it.value().password()
|
||||
// << " effectiveACLs:" << it.value().effectiveAcls()
|
||||
;
|
||||
}
|
||||
}
|
||||
QTest::qWait(1000);
|
||||
} // end of tryGetAllOperators()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void OpmTests::tryGetOperator()
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "trying to get operator with id:" << m_operatorId;
|
||||
|
||||
if(m_testId > 1)
|
||||
{
|
||||
m_eTestStep = eGetOperator;
|
||||
}
|
||||
|
||||
if(m_operatorId <= 0)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "invalid operatorId - test aborted.";
|
||||
failExit();
|
||||
}
|
||||
|
||||
m_dtc->waitForHistoricalDataUser();
|
||||
OperatorManagement::User op = m_dtc->user(m_operatorId);
|
||||
|
||||
if(op.id() <= 0)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error receiving data for operatorId " << m_operatorId << " returnVal:" << op.id();
|
||||
failExit();
|
||||
}
|
||||
else
|
||||
{
|
||||
INFO_LOG(m_logger) << "opm(" << op.id() << ") :"
|
||||
<< " name: " << op.name()
|
||||
// << " password: " << data.password()
|
||||
// << " effectiveACLs:" << it.value().effectiveAcls()
|
||||
;
|
||||
}
|
||||
|
||||
if(m_testId == 0)
|
||||
{
|
||||
if(m_eTestStep == eCreate)
|
||||
{
|
||||
if(! onCompareCreatedData(op))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Compare created data failed!";
|
||||
failExit();
|
||||
}
|
||||
else
|
||||
{
|
||||
//QTimer::singleShot(0, this, &OpmTests::tryChangeName); // not implemented...
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if(m_eTestStep == eModify)
|
||||
{
|
||||
if(! onCompareModifiedData(op))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Compare modified data failed!";
|
||||
failExit();
|
||||
}
|
||||
else
|
||||
{
|
||||
QTimer::singleShot(0, this, &OpmTests::tryRemove);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
|
||||
|
||||
QTest::qWait(1000);
|
||||
} // end of tryGetOperator()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void OpmTests::onOperatorCreateModifyReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
INFO_LOG(m_logger) << "Got create/modifyReply with id " << replyObject.id()
|
||||
<< " and errorString " << replyObject.translated();
|
||||
|
||||
m_operatorId = replyObject.id();
|
||||
|
||||
if(replyObject.error())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error requesting create/modify data";
|
||||
failExit();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Requesting create/modify data ok. Got id:" << replyObject.id() << " ... ok.";
|
||||
}
|
||||
|
||||
if(m_testId == 0)
|
||||
{
|
||||
if(m_eTestStep == eCreate)
|
||||
QTimer::singleShot(0, this, &OpmTests::tryModify);
|
||||
else if (m_eTestStep == eModify)
|
||||
QTimer::singleShot(0, this, &OpmTests::tryGetOperator);
|
||||
}
|
||||
else
|
||||
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
|
||||
|
||||
} // end of onOperatorCreateModifyReply()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void OpmTests::onOperatorRemoveReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
INFO_LOG(m_logger) << "Got removeReply with id " << replyObject.id()
|
||||
<< " and errorString " << replyObject.translated();
|
||||
|
||||
if(replyObject.error())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error requesting remove data for id:" << replyObject.id();
|
||||
failExit();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Requesting remove data for id:" << replyObject.id() << " ... ok.";
|
||||
}
|
||||
|
||||
if(m_testId == 0)
|
||||
{
|
||||
INFO_LOG(m_logger) << "***** FTC/DTC test successfully finished. (used id:" << replyObject.id() << ") *****";
|
||||
// ansonsten verheriger Ausstieg mit Errorlog.
|
||||
}
|
||||
|
||||
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
|
||||
|
||||
} // end of onOperatorRemoveReply()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void OpmTests::onOperatorLoginReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Got loginReply with id " << replyObject.id()
|
||||
<< " and errorString " << replyObject.translated();
|
||||
|
||||
if(replyObject.error())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error requesting login for id:" << replyObject.id();
|
||||
failExit();
|
||||
return;
|
||||
}
|
||||
|
||||
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void OpmTests::onOperatorLogoutReply(const Core::FunctionReplyObject &replyObject)
|
||||
{
|
||||
INFO_LOG(m_logger) << "Got logoutReply with id " << replyObject.id()
|
||||
<< " and errorString " << replyObject.translated();
|
||||
|
||||
if(replyObject.error())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error requesting logout for id:" << replyObject.id();
|
||||
failExit();
|
||||
return;
|
||||
}
|
||||
|
||||
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void OpmTests::onReceiveOperatorChanged(const User &data, DataModification modType)
|
||||
{
|
||||
// Check signal/slot connection
|
||||
if (m_operatorId == data.id())
|
||||
{
|
||||
TRACE_LOG(m_logger) << "Check signal/slot connection for DTC. Data for id = " << data.id() << " received";
|
||||
TRACE_LOG(m_logger) << "ModificationType: = " << (int)modType << " received";
|
||||
}
|
||||
} // end of onReceiveOperatorData()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void OpmTests::onReceiveGroupChanged(const Group &data, DataModification modType)
|
||||
{
|
||||
// Check signal/slot connection
|
||||
// if (m_operatorId == data.id())
|
||||
// {
|
||||
TRACE_LOG(m_logger) << "Check signal/slot connection for DTC. Data for id = " << data.id() << " received";
|
||||
TRACE_LOG(m_logger) << "ModificationType: = " << (int)modType << " received";
|
||||
// }
|
||||
} // end of onReceiveOperatorData()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void OpmTests::getOperatorCreateRequestData(OperatorCreateModifyRequest &data) const
|
||||
{
|
||||
time_t currentTime = time(nullptr);
|
||||
if(m_testId == 0)
|
||||
currentTime = currentTime/10;
|
||||
|
||||
data.name(std::string("TestOperatorCreate" + std::to_string(currentTime)));
|
||||
std::string pass("password");
|
||||
|
||||
const QByteArray ba(QByteArray::fromRawData(pass.c_str(), pass.size()));
|
||||
pass = QCryptographicHash::hash(ba, QCryptographicHash::Md5).toHex().data();
|
||||
|
||||
data.password(pass);
|
||||
data.description(std::string("Description"));
|
||||
// Todo: test anpassen
|
||||
PartiesByExercise pbe;
|
||||
pbe.exerciseId(0);
|
||||
pbe.visibleParties().set({0,1,2,3,4,5,6,7,8,9,10,11,12});
|
||||
data.visiblePartiesByExercise().push_back(pbe);
|
||||
data.rolePresetId(1001);
|
||||
|
||||
} // end of getOperatorCreateRequestData()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void OpmTests::getOperatorModifyRequestData(OperatorCreateModifyRequest &data) const
|
||||
{
|
||||
time_t currentTime = time(nullptr);
|
||||
if(m_testId == 0)
|
||||
currentTime = currentTime/10;
|
||||
|
||||
data.id(m_operatorId);
|
||||
// data.name(std::string("Operator"+std::to_string(m_operatorId)));
|
||||
// only changing the description
|
||||
data.description(std::string("Description" + std::to_string(m_operatorId)));
|
||||
|
||||
} // end of getOperatorChangeNameRequestData()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool OpmTests::onCompareCreatedData(User &data)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "start onCompareCreatedData() for id :" << data.id();
|
||||
|
||||
OperatorCreateModifyRequest createData;
|
||||
|
||||
getOperatorCreateRequestData(createData);
|
||||
|
||||
if (createData.name() != data.name())
|
||||
return false;
|
||||
|
||||
// if(createData.password() != data.password())
|
||||
// return false;
|
||||
|
||||
if (data.description() != createData.description())
|
||||
return false;
|
||||
|
||||
DEBUG_LOG(m_logger) << "successfull finished onCompareCreatedData() for id :" << data.id();
|
||||
|
||||
return true;
|
||||
} // end of onCompareCreatedData()
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool OpmTests::onCompareModifiedData(User &data)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "start onCompareModifiedData() for id :" << data.id();
|
||||
|
||||
OperatorCreateModifyRequest modifyData;
|
||||
|
||||
getOperatorModifyRequestData(modifyData);
|
||||
|
||||
if (modifyData.id() != data.id())
|
||||
return false;
|
||||
|
||||
if (modifyData.name() != data.name())
|
||||
return false;
|
||||
|
||||
if (data.description() != modifyData.description())
|
||||
return false;
|
||||
|
||||
DEBUG_LOG(m_logger) << "successfully finished onCompareModifiedData() for id :" << data.id();
|
||||
|
||||
return true;
|
||||
} // end of onCompareModifiedData()
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
void OpmTests::failExit()
|
||||
{
|
||||
m_bTestsSuccessful = false;
|
||||
QTimer::singleShot(0, qApp, &QCoreApplication::quit);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
class CmdLineParser : public LtsCommandLineParser::LtsCommandLineParser
|
||||
{
|
||||
public:
|
||||
CmdLineParser()
|
||||
: LtsCommandLineParser()
|
||||
{
|
||||
addOption( { QStringList() << QLatin1String("t") << QLatin1String("testId")
|
||||
, QLatin1String("TestId.")
|
||||
, QLatin1String("Default: 0 (all FTC/DTC tests), 1 create, 2 modify, 3 remove, 10 getAllOperators, 11 getOperator")
|
||||
, QLatin1String("0")
|
||||
} );
|
||||
|
||||
addOption( { QStringList() << QLatin1String("o") << QLatin1String("operatorId")
|
||||
, QLatin1String("OperatorId.")
|
||||
, QLatin1String("Used for tests 2, 3 & 11 only to select the operator")
|
||||
, QLatin1String("0")
|
||||
} );
|
||||
|
||||
addOption( { QStringList() << QLatin1String("c") << QLatin1String("createdId")
|
||||
, QLatin1String("CreatedId.")
|
||||
, QLatin1String("Used to create unique names for operators in test 1")
|
||||
, QLatin1String("0")
|
||||
} );
|
||||
}
|
||||
|
||||
int testId() const { return isSet(QLatin1String("t")) ? value(QLatin1String("t")).toInt() : -1; }
|
||||
int operatorId() const { return isSet(QLatin1String("o")) ? value(QLatin1String("o")).toInt() : -1; }
|
||||
int createdId() const { return isSet(QLatin1String("c")) ? value(QLatin1String("c")).toInt() : -1; }
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
NGLCoreApplication app(argc, argv);
|
||||
app.createLogger("OPM", "log4cxx_opm.props");
|
||||
|
||||
int iRet = -1;
|
||||
CmdLineParser options;
|
||||
if (!options.init())
|
||||
return iRet;
|
||||
|
||||
std::unique_ptr<OperatorManagement::OpmTests> OpmTests(new OperatorManagement::OpmTests);
|
||||
if(!OpmTests->init(options.domainId(), options.exerciseId(), options.testId(), options.operatorId(), options.createdId() ))
|
||||
{
|
||||
return iRet;
|
||||
}
|
||||
|
||||
QTimer::singleShot(0, OpmTests.get(), &OperatorManagement::OpmTests::startTest);
|
||||
|
||||
STARTUP_LOG(app.baseLogger());
|
||||
|
||||
app.exec();
|
||||
iRet = OpmTests->testsSuccessful() ? 0 : 1;
|
||||
fprintf(stderr, "%d\n", iRet);
|
||||
|
||||
DEBUG_LOG(app.baseLogger()) << "** TEST result = " << iRet;
|
||||
|
||||
SHUTDOWN_LOG(app.baseLogger());
|
||||
|
||||
return iRet;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
*
|
||||
* EXM Function Topic test executable
|
||||
*
|
||||
* ModuleTests for create/modify/remove marker
|
||||
* ---------------------------------------------------
|
||||
* Client FTC is implemented
|
||||
*
|
||||
* => (!) Preconditon:
|
||||
* - Service svcOperatorManagent running
|
||||
*
|
||||
* -------------------------------------------------
|
||||
*
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by hjl, SLSE, 2016-04-18
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <OperatorManagement/opm_ftc.h>
|
||||
#include <OperatorManagement/opm_ftc_types.h>
|
||||
#include <OperatorManagement/opm_dtc.h>
|
||||
#include <OperatorManagement/opm_dtc_types.h>
|
||||
#include <OperatorManagement/logger.h>
|
||||
|
||||
#include <DDS/DDSConnector/dds_connector.h>
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
class OpmTests : public QObject
|
||||
, protected OperatorManagement::Interface::Ftc::OperatorCreateModifyReplyHandler
|
||||
, protected OperatorManagement::Interface::Ftc::OperatorRemoveReplyHandler
|
||||
, protected OperatorManagement::Interface::Ftc::OperatorLoginReplyHandler
|
||||
, protected OperatorManagement::Interface::Ftc::OperatorLogoutReplyHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit OpmTests(QObject *parent = nullptr);
|
||||
~OpmTests();
|
||||
|
||||
bool init(int domainId, int exerciseId, int testId, int operatorId, int createdId);
|
||||
bool testsSuccessful() const { return m_bTestsSuccessful; }
|
||||
|
||||
public Q_SLOTS:
|
||||
void startTest();
|
||||
|
||||
protected Q_SLOTS:
|
||||
// used to check FTC
|
||||
void tryCreate();
|
||||
void tryModify();
|
||||
void tryRemove();
|
||||
void tryLogin();
|
||||
void tryLoginForce();
|
||||
void tryLogout();
|
||||
void tryGetOperatorsByOperatorRight();
|
||||
|
||||
// used to check DTC
|
||||
void tryGetAllOperators();
|
||||
void tryGetOperator();
|
||||
|
||||
// used to check DTC signal/slot connection
|
||||
//ToDo: Parameter passen noch nicht!! int muss DataModification sein ... no compile..
|
||||
void onReceiveOperatorChanged(const User &data, DataModification modType);
|
||||
void onReceiveGroupChanged(const Group &data, DataModification modType);
|
||||
|
||||
protected:
|
||||
// Callbackfunctions for FTC
|
||||
void onOperatorCreateModifyReply(const Core::FunctionReplyObject &replyObject) override final;
|
||||
void onOperatorRemoveReply(const Core::FunctionReplyObject &replyObject) override final;
|
||||
void onOperatorLoginReply(const Core::FunctionReplyObject &replyObject) override final;
|
||||
void onOperatorLogoutReply(const Core::FunctionReplyObject &replyObject) override final;
|
||||
|
||||
private Q_SLOTS:
|
||||
bool onCompareCreatedData(User &data);
|
||||
bool onCompareModifiedData(User &data);
|
||||
private:
|
||||
void getOperatorCreateRequestData(OperatorCreateModifyRequest &data) const;
|
||||
void getOperatorModifyRequestData(OperatorCreateModifyRequest &data) const;
|
||||
void failExit();
|
||||
|
||||
private:
|
||||
std::shared_ptr<DDSConnector::DdsConnector> m_ddsConnector;
|
||||
std::shared_ptr<OperatorManagement::Interface::Ftc> m_ftc;
|
||||
std::shared_ptr<OperatorManagement::Interface::Dtc> m_dtc;
|
||||
|
||||
qint32 m_exerciseId;
|
||||
int m_testId;
|
||||
int m_operatorId;
|
||||
int m_createdId;
|
||||
|
||||
enum TestStep
|
||||
{
|
||||
eUnknown,
|
||||
eCreate,
|
||||
eModify,
|
||||
eLogin,
|
||||
eLogout,
|
||||
eRemove,
|
||||
eGetAllOperators,
|
||||
eGetOperator,
|
||||
eGetOperatoryByOperatorRight
|
||||
} m_eTestStep;
|
||||
|
||||
bool m_bTestsSuccessful;
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
};
|
||||
|
||||
} // namespace OperatorManagement
|
||||
@@ -0,0 +1,6 @@
|
||||
Beispiel Aufruf zum Login mit dem User Gerlinde:
|
||||
Login:
|
||||
./opmTests -e 42 -o 20 -t 4
|
||||
|
||||
Logout:
|
||||
./opmTests -e 42 -o 20 -t 5
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The ClientMessage class is an abstract base class for concrete ClientMessage objects
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Dassow, SLST, 2017-12-05
|
||||
*/
|
||||
#include "client_message.h"
|
||||
|
||||
#include "WebSocketInterface/Messages/reply_message.h"
|
||||
#include "WebSocketInterface/json_keys.h"
|
||||
#include "WebSocketInterface/data_manager.h"
|
||||
|
||||
#include <QtCore/QJsonDocument>
|
||||
#include <QtCore/QUuid>
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
namespace WebSocketInterface
|
||||
{
|
||||
namespace ClientMessages
|
||||
{
|
||||
using namespace JsonKeys;
|
||||
|
||||
// ####### ClientMessageFactory begin #######
|
||||
ClientMessageFactory::ClientMessageFactory(DataManager *dataManager)
|
||||
: LtsWebSocket::AbstractClientMessageFactory(getLogger("ClientMessageFactory"))
|
||||
, m_dataManager(dataManager)
|
||||
{}
|
||||
|
||||
LtsWebSocket::AbstractClientMessage *ClientMessageFactory::createMessage(LtsWebSocket::ReplyHandler *client,
|
||||
const QString &message)
|
||||
{
|
||||
LtsWebSocket::AbstractClientMessage *result = checkAttributes(client, message);
|
||||
if (result)
|
||||
return result;
|
||||
|
||||
if (m_type == OcBaseDownload::WebSocketInterface::JsonKeys::BASE_DL_REQUEST())
|
||||
result = new BaseDlRequest(m_dataManager, client, m_type, m_typeId, m_uuid);
|
||||
|
||||
return checkResult(client, message, result);
|
||||
}
|
||||
// ####### ClientMessageFactory end #######
|
||||
|
||||
// ####### ClientMessage begin #######
|
||||
ClientMessage::ClientMessage(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data)
|
||||
: LtsWebSocket::AbstractClientMessage(client, type, typeId, uuid, data)
|
||||
, m_dataManager(dataManager)
|
||||
, m_logger(getLogger("ClientMessage"))
|
||||
{}
|
||||
// ####### ClientMessage end #######
|
||||
|
||||
// ####### BaseDlRequest begin #######
|
||||
BaseDlRequest::BaseDlRequest(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid)
|
||||
: ClientMessage(dataManager, client, type, typeId, uuid)
|
||||
{}
|
||||
|
||||
void BaseDlRequest::process()
|
||||
{
|
||||
m_client->addReply(m_dataManager->groupBaseData(m_uuid));
|
||||
m_client->addReply(m_dataManager->groupGroupBaseData(m_uuid));
|
||||
m_client->addReply(m_dataManager->operatorBaseData(m_uuid));
|
||||
m_client->addReply(m_dataManager->operatorExerciseBaseData(m_uuid));
|
||||
m_client->addReply(m_dataManager->settingsBaseData(m_uuid));
|
||||
m_client->addReply(m_dataManager->accessControlLevelBaseData(m_uuid));
|
||||
m_client->addReply(m_dataManager->aclAllowBaseData(m_uuid));
|
||||
m_client->addReply(m_dataManager->aclDenyBaseData(m_uuid));
|
||||
}
|
||||
|
||||
bool BaseDlRequest::hasValidData() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
// ####### BaseDlRequest end #######
|
||||
|
||||
} // namespace ClientMessages
|
||||
} // namespace WebSocketInterface
|
||||
} // namespace OperatorManagement
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The ClientMessage class is an abstract base class for concrete ClientMessage objects
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Dassow, SLST, 2017-12-05
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QJsonObject>
|
||||
|
||||
#include <LtsWebSocket/client_message_factory.h>
|
||||
#include <LtsWebSocket/client_message.h>
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
namespace WebSocketInterface
|
||||
{
|
||||
class DataManager;
|
||||
|
||||
namespace ClientMessages
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief The ClientMessageFactory class creates ClientMessages which will then be processed
|
||||
*/
|
||||
class ClientMessageFactory final : public LtsWebSocket::AbstractClientMessageFactory
|
||||
{
|
||||
public:
|
||||
explicit ClientMessageFactory(DataManager *dataManager);
|
||||
|
||||
/**
|
||||
* @brief create Only way to create a ClientMessage object
|
||||
* @param message Text message which will be converted to a ClientMessage object
|
||||
* @return A ClientMessage object, which represents a concrete ClientMessage
|
||||
*/
|
||||
LtsWebSocket::AbstractClientMessage *createMessage(LtsWebSocket::ReplyHandler *client,
|
||||
const QString &message);
|
||||
|
||||
private:
|
||||
DataManager *m_dataManager;
|
||||
|
||||
}; // class ClientMessageFactory
|
||||
|
||||
/**
|
||||
* @brief The ClientMessage class is an abstract base class for concrete ClientMessage objects
|
||||
*/
|
||||
class ClientMessage : public LtsWebSocket::AbstractClientMessage
|
||||
{
|
||||
protected: // method
|
||||
explicit ClientMessage(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid, const QJsonValue &data = QJsonValue());
|
||||
|
||||
protected: // attributes
|
||||
DataManager *m_dataManager;
|
||||
LOGGER_T m_logger;
|
||||
}; // class ClientMessage
|
||||
|
||||
/**
|
||||
* @brief The BaseDlRequest class handles the base DL request and sends multiple replys depending on the data requested
|
||||
*/
|
||||
class BaseDlRequest : public ClientMessage
|
||||
{
|
||||
public:
|
||||
explicit BaseDlRequest(DataManager *dataManager, LtsWebSocket::ReplyHandler *client, const QString &type, const int typeId, const QString &uuid);
|
||||
|
||||
void process();
|
||||
bool hasValidData() const;
|
||||
}; // class BaseDlRequest
|
||||
|
||||
} // namespace ClientMessages
|
||||
} // namespace WebSocketInterface
|
||||
} // namespace OperatorManagement
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The ReplyMessage class is an abstract base class for all possible messages which are sent to the client
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Dassow, SLST, 2017-12-05
|
||||
*/
|
||||
#include "reply_message.h"
|
||||
|
||||
#include <LtsWebSocket/json_keys.h>
|
||||
#include "WebSocketInterface/json_keys.h"
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
namespace WebSocketInterface
|
||||
{
|
||||
namespace ReplyMessages
|
||||
{
|
||||
using namespace JsonKeys;
|
||||
using namespace LtsWebSocket::JsonKeys;
|
||||
|
||||
// ####### GroupBaseData begin #######
|
||||
GroupBaseData::GroupBaseData(const QJsonArray &data, const QString &uuid)
|
||||
: LtsWebSocket::ReplyMessage (GROUP_BASE_DATA(), 1, uuid) // Todo: Check whether typeId is correct
|
||||
{
|
||||
m_jsonRepresentation.insert(DATA(), data);
|
||||
}
|
||||
// ####### GroupBaseData end #######
|
||||
|
||||
// ####### GroupGroupBaseData begin #######
|
||||
GroupGroupBaseData::GroupGroupBaseData(const QJsonArray &data, const QString &uuid)
|
||||
: LtsWebSocket::ReplyMessage (GROUP_GROUP_BASE_DATA(), 2, uuid) // Todo: Check whether typeId is correct
|
||||
{
|
||||
m_jsonRepresentation.insert(DATA(), data);
|
||||
}
|
||||
// ####### GroupGroupBaseData end #######
|
||||
|
||||
// ####### OperatorBaseData begin #######
|
||||
OperatorBaseData::OperatorBaseData(const QJsonArray &data, const QString &uuid)
|
||||
: LtsWebSocket::ReplyMessage (OPERATOR_BASE_DATA(), 3, uuid) // Todo: Check whether typeId is correct
|
||||
{
|
||||
m_jsonRepresentation.insert(DATA(), data);
|
||||
}
|
||||
// ####### OperatorBaseData end #######
|
||||
|
||||
// ####### OperatorExerciseBaseData begin #######
|
||||
OperatorExerciseBaseData::OperatorExerciseBaseData(const QJsonArray &data, const QString &uuid)
|
||||
: LtsWebSocket::ReplyMessage (OPERATOR_EXERCISE_BASE_DATA(), 4, uuid) // Todo: Check whether typeId is correct
|
||||
{
|
||||
m_jsonRepresentation.insert(DATA(), data);
|
||||
}
|
||||
// ####### OperatorExerciseBaseData end #######
|
||||
|
||||
// ####### SettingsBaseData begin #######
|
||||
SettingsBaseData::SettingsBaseData(const QJsonArray &data, const QString &uuid)
|
||||
: LtsWebSocket::ReplyMessage (SETTINGS_BASE_DATA(), 5, uuid) // Todo: Check whether typeId is correct
|
||||
{
|
||||
m_jsonRepresentation.insert(DATA(), data);
|
||||
}
|
||||
// ####### SettingsBaseData end #######
|
||||
|
||||
// ####### AccessControlLevelBaseData begin #######
|
||||
AccessControlLevelBaseData::AccessControlLevelBaseData(const QJsonArray &data, const QString &uuid)
|
||||
: LtsWebSocket::ReplyMessage (ACCESS_CONTROL_LEVEL_BASE_DATA(), 6, uuid) // Todo: Check whether typeId is correct
|
||||
{
|
||||
m_jsonRepresentation.insert(DATA(), data);
|
||||
}
|
||||
// ####### AccessControlLevelBaseData end #######
|
||||
|
||||
// ####### AclAllowBaseData begin #######
|
||||
AclAllowBaseData::AclAllowBaseData(const QJsonArray &data, const QString &uuid)
|
||||
: LtsWebSocket::ReplyMessage (ACL_ALLOW_BASE_DATA(), 7, uuid) // Todo: Check whether typeId is correct
|
||||
{
|
||||
m_jsonRepresentation.insert(DATA(), data);
|
||||
}
|
||||
// ####### AclAllowBaseData end #######
|
||||
|
||||
// ####### AclDenyBaseData begin #######
|
||||
AclDenyBaseData::AclDenyBaseData(const QJsonArray &data, const QString &uuid)
|
||||
: LtsWebSocket::ReplyMessage (ACL_DENY_BASE_DATA(), 8, uuid) // Todo: Check whether typeId is correct
|
||||
{
|
||||
m_jsonRepresentation.insert(DATA(), data);
|
||||
}
|
||||
// ####### AclDenyBaseData end #######
|
||||
|
||||
|
||||
} // namespace ReplyMessages
|
||||
} // namespace WebSocketInterface
|
||||
} // namespace OperatorManagement
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The ReplyMessage class is an abstract base class for all possible messages which are sent to the client
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Dassow, SLST, 2017-12-05
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <LtsWebSocket/reply_message.h>
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QString>
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
namespace WebSocketInterface
|
||||
{
|
||||
namespace ReplyMessages
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief The GroupBaseData class training area data for base DL
|
||||
*/
|
||||
class GroupBaseData : public LtsWebSocket::ReplyMessage
|
||||
{
|
||||
public:
|
||||
explicit GroupBaseData(const QJsonArray &data, const QString &uuid);
|
||||
}; // class GroupBaseData
|
||||
|
||||
/**
|
||||
* @brief The GroupGroupBaseData class map description data for base DL
|
||||
*/
|
||||
class GroupGroupBaseData : public LtsWebSocket::ReplyMessage
|
||||
{
|
||||
public:
|
||||
explicit GroupGroupBaseData(const QJsonArray &data, const QString &uuid);
|
||||
}; // class GroupGroupBaseData
|
||||
|
||||
/**
|
||||
* @brief The OperatorBaseData class location data for base DL
|
||||
*/
|
||||
class OperatorBaseData : public LtsWebSocket::ReplyMessage
|
||||
{
|
||||
public:
|
||||
explicit OperatorBaseData(const QJsonArray &data, const QString &uuid);
|
||||
}; // class OperatorBaseData
|
||||
|
||||
/**
|
||||
* @brief The OperatorExerciseBaseData class asset data for base DL
|
||||
*/
|
||||
class OperatorExerciseBaseData : public LtsWebSocket::ReplyMessage
|
||||
{
|
||||
public:
|
||||
explicit OperatorExerciseBaseData(const QJsonArray &data, const QString &uuid);
|
||||
}; // class OperatorExerciseBaseData
|
||||
|
||||
/**
|
||||
* @brief The SettingsBaseData class asset data for base DL
|
||||
*/
|
||||
class SettingsBaseData : public LtsWebSocket::ReplyMessage
|
||||
{
|
||||
public:
|
||||
explicit SettingsBaseData(const QJsonArray &data, const QString &uuid);
|
||||
}; // class SettingsBaseData
|
||||
|
||||
/**
|
||||
* @brief The AccessControlLevelBaseData class asset data for base DL
|
||||
*/
|
||||
class AccessControlLevelBaseData : public LtsWebSocket::ReplyMessage
|
||||
{
|
||||
public:
|
||||
explicit AccessControlLevelBaseData(const QJsonArray &data, const QString &uuid);
|
||||
}; // class AccessControlLevelBaseData
|
||||
|
||||
/**
|
||||
* @brief The AclAllowBaseData class asset data for base DL
|
||||
*/
|
||||
class AclAllowBaseData : public LtsWebSocket::ReplyMessage
|
||||
{
|
||||
public:
|
||||
explicit AclAllowBaseData(const QJsonArray &data, const QString &uuid);
|
||||
}; // class AclAllowBaseData
|
||||
|
||||
/**
|
||||
* @brief The AclDenyBaseData class asset data for base DL
|
||||
*/
|
||||
class AclDenyBaseData : public LtsWebSocket::ReplyMessage
|
||||
{
|
||||
public:
|
||||
explicit AclDenyBaseData(const QJsonArray &data, const QString &uuid);
|
||||
}; // class AclDenyBaseData
|
||||
|
||||
} // namespace ReplyMessages
|
||||
} // namespace WebSocketInterface
|
||||
} // namespace OperatorManagement
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The DataManager class handles data to be send to the websocket
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Dassow, SLST, 2017-12-05
|
||||
*/
|
||||
#include "data_manager.h"
|
||||
#include "Messages/reply_message.h"
|
||||
#include "main_handler.h"
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
namespace WebSocketInterface
|
||||
{
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
DataManager::DataManager(MainHandler *mainHandler)
|
||||
: LtsWebSocket::DataManagerBaseDl<DatabaseInterface>(mainHandler->db(), getLogger("DataManager"))
|
||||
{}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
LtsWebSocket::ReplyMessage *DataManager::groupBaseData(const QString &uuid) const
|
||||
{
|
||||
return toBaseDataMessageFromDb<Database::OpmGroup, ReplyMessages::GroupBaseData>(uuid);
|
||||
}
|
||||
|
||||
LtsWebSocket::ReplyMessage *DataManager::groupGroupBaseData(const QString &uuid) const
|
||||
{
|
||||
return toBaseDataMessageFromDb<Database::OpmGroupGroup, ReplyMessages::GroupGroupBaseData>(uuid);
|
||||
}
|
||||
|
||||
LtsWebSocket::ReplyMessage *DataManager::operatorBaseData(const QString &uuid) const
|
||||
{
|
||||
return toBaseDataMessageFromDb<Database::OpmOperator, ReplyMessages::OperatorBaseData>(uuid);
|
||||
}
|
||||
|
||||
LtsWebSocket::ReplyMessage *DataManager::operatorExerciseBaseData(const QString &uuid) const
|
||||
{
|
||||
return toBaseDataMessageFromDb<Database::OpmOperatorExercise, ReplyMessages::OperatorExerciseBaseData>(uuid);
|
||||
}
|
||||
|
||||
LtsWebSocket::ReplyMessage *DataManager::settingsBaseData(const QString &uuid) const
|
||||
{
|
||||
return toBaseDataMessageFromDb<Database::OpmSettings, ReplyMessages::SettingsBaseData>(uuid);
|
||||
}
|
||||
|
||||
LtsWebSocket::ReplyMessage *DataManager::accessControlLevelBaseData(const QString &uuid) const
|
||||
{
|
||||
return toBaseDataMessageFromDb<Database::OpmAccessControlLevel, ReplyMessages::AccessControlLevelBaseData>(uuid);
|
||||
}
|
||||
|
||||
LtsWebSocket::ReplyMessage *DataManager::aclAllowBaseData(const QString &uuid) const
|
||||
{
|
||||
return toBaseDataMessageFromDb<Database::OpmAclAllow, ReplyMessages::AclAllowBaseData>(uuid);
|
||||
}
|
||||
|
||||
LtsWebSocket::ReplyMessage *DataManager::aclDenyBaseData(const QString &uuid) const
|
||||
{
|
||||
return toBaseDataMessageFromDb<Database::OpmAclDeny, ReplyMessages::AclDenyBaseData>(uuid);
|
||||
}
|
||||
|
||||
} // namespace WebSocketInterface
|
||||
} // namespace OperatorManagement
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* The DataManager class handles data to be send to the websocket
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Dassow, SLST, 2017-12-05
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <LtsWebSocket/data_manager_base_dl.h>
|
||||
#include <OperatorManagement/opm_db.h>
|
||||
#include "logger.h"
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
class MainHandler;
|
||||
|
||||
namespace WebSocketInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @brief The DataManager class is a convenience class for managing base DL data
|
||||
*/
|
||||
class DataManager final : public LtsWebSocket::DataManagerBaseDl<DatabaseInterface>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief DataManager Constructor
|
||||
* @param mainHandler Source for needed handlers
|
||||
*/
|
||||
explicit DataManager(MainHandler *mainHandler);
|
||||
|
||||
LtsWebSocket::ReplyMessage* groupBaseData(const QString &uuid) const;
|
||||
LtsWebSocket::ReplyMessage* groupGroupBaseData(const QString &uuid) const;
|
||||
LtsWebSocket::ReplyMessage* operatorBaseData(const QString &uuid) const;
|
||||
LtsWebSocket::ReplyMessage* operatorExerciseBaseData(const QString &uuid) const;
|
||||
LtsWebSocket::ReplyMessage* settingsBaseData(const QString &uuid) const;
|
||||
LtsWebSocket::ReplyMessage* accessControlLevelBaseData(const QString &uuid) const;
|
||||
LtsWebSocket::ReplyMessage* aclAllowBaseData(const QString &uuid) const;
|
||||
LtsWebSocket::ReplyMessage* aclDenyBaseData(const QString &uuid) const;
|
||||
}; // class DataManager
|
||||
|
||||
} // namespace WebSocketInterface
|
||||
} // namespace OperatorManagement
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Header file which holds all occuring JSON keys
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Dassow, SLST, 2017-12-05
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include <OcBaseDownload/WebSocketInterface/json_keys.h>
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
namespace WebSocketInterface
|
||||
{
|
||||
/**
|
||||
* @brief Namespace which holds all occuring JSON keys as const QString objects
|
||||
*/
|
||||
namespace JsonKeys
|
||||
{
|
||||
// types for client --> server messages
|
||||
|
||||
// types for server --> client messages
|
||||
inline QString GROUP_BASE_DATA() { return QStringLiteral("groupBaseData"); }
|
||||
inline QString GROUP_GROUP_BASE_DATA() { return QStringLiteral("groupGroupBaseData"); }
|
||||
inline QString OPERATOR_BASE_DATA() { return QStringLiteral("operatorBaseData"); }
|
||||
inline QString OPERATOR_EXERCISE_BASE_DATA() { return QStringLiteral("operatorExerciseBaseData"); }
|
||||
inline QString SETTINGS_BASE_DATA() { return QStringLiteral("settingsBaseData"); }
|
||||
inline QString ACCESS_CONTROL_LEVEL_BASE_DATA() { return QStringLiteral("accessControlLevelBaseData"); }
|
||||
inline QString ACL_ALLOW_BASE_DATA() { return QStringLiteral("aclAllowBaseData"); }
|
||||
inline QString ACL_DENY_BASE_DATA() { return QStringLiteral("aclDenyBaseData"); }
|
||||
|
||||
// data keys
|
||||
|
||||
} // namespace JsonKeys
|
||||
} // namespace WebSocketInterface
|
||||
} // namespace OperatorManagement
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Handler for the WebSocket Interface
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Dassow, SLST, 2017-12-05
|
||||
*/
|
||||
#include "websocket_interface_handler.h"
|
||||
|
||||
#include "main_handler.h"
|
||||
#include "data_manager.h"
|
||||
#include "WebSocketInterface/Messages/client_message.h"
|
||||
#include "settings.h"
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
namespace WebSocketInterface
|
||||
{
|
||||
|
||||
WebSocketInterfaceHandler::WebSocketInterfaceHandler(MainHandler *mainHandler, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_webSocketServer(nullptr)
|
||||
, m_messageFactory(nullptr)
|
||||
, m_dataManager(nullptr)
|
||||
, m_mainHandler(mainHandler)
|
||||
, m_logger(getLogger("WebSocketInterfaceHandler"))
|
||||
{
|
||||
}
|
||||
|
||||
WebSocketInterfaceHandler::~WebSocketInterfaceHandler()
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
|
||||
bool WebSocketInterfaceHandler::init()
|
||||
{
|
||||
cleanup();
|
||||
|
||||
DEBUG_LOG(m_logger) << "... ok";
|
||||
|
||||
m_dataManager = new DataManager(m_mainHandler);
|
||||
|
||||
m_messageFactory = new ClientMessages::ClientMessageFactory(m_dataManager);
|
||||
|
||||
m_webSocketServer = new LtsWebSocket::LtsWebSocketServer(m_messageFactory, this);
|
||||
|
||||
DEBUG_LOG(m_logger) << "Initialising LtsWebSocketServer";
|
||||
if (!m_webSocketServer->init(QStringLiteral("ASM"), Settings::getWebSocketServerPortRange(1)))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Failed to initialise LtsWebSocketServer";
|
||||
return false;
|
||||
}
|
||||
DEBUG_LOG(m_logger) << "... ok";
|
||||
|
||||
DEBUG_LOG(m_logger) << "Connection signals and slots";
|
||||
DEBUG_LOG(m_logger) << "... ok";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WebSocketInterfaceHandler::cleanup()
|
||||
{
|
||||
delete m_webSocketServer;
|
||||
delete m_messageFactory;
|
||||
delete m_dataManager;
|
||||
}
|
||||
|
||||
} // namespace WebSocketInterface
|
||||
} // namespace OperatorManagement
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Handler for the WebSocket Interface
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Philipp Dassow, SLST, 2017-12-05
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <LtsWebSocket/lts_web_socket_server.h>
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
class MainHandler;
|
||||
namespace WebSocketInterface
|
||||
{
|
||||
namespace ClientMessages
|
||||
{
|
||||
class ClientMessageFactory;
|
||||
}
|
||||
class DataManager;
|
||||
|
||||
/**
|
||||
* @brief The WebSocketInterfaceHandler class is the main class for the WebSocketInterface
|
||||
*/
|
||||
class WebSocketInterfaceHandler final : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* @brief WebSocketInterfaceHandler Constructor
|
||||
* @param mainHandler MainHandler to get the HandlerStructureElement from
|
||||
*/
|
||||
explicit WebSocketInterfaceHandler(MainHandler *mainHandler, QObject *parent = nullptr);
|
||||
|
||||
/**
|
||||
* @brief ~WebSocketInterfaceHandler Destructor
|
||||
*/
|
||||
~WebSocketInterfaceHandler();
|
||||
|
||||
/**
|
||||
* @brief init Initialises all needed classes for the WebSocketInterface
|
||||
* @return True on success, otherwise false
|
||||
*/
|
||||
bool init();
|
||||
|
||||
/**
|
||||
* @brief webSocketPort returns the listen port
|
||||
* @return listen port
|
||||
*/
|
||||
unsigned short serverWebSocketPort() { return m_webSocketServer->webSocketPort(); }
|
||||
|
||||
private:
|
||||
void cleanup();
|
||||
|
||||
private:
|
||||
LtsWebSocket::LtsWebSocketServer *m_webSocketServer;
|
||||
ClientMessages::ClientMessageFactory *m_messageFactory;
|
||||
DataManager *m_dataManager;
|
||||
MainHandler *m_mainHandler;
|
||||
LOGGER_T m_logger;
|
||||
}; // class WebSocketInterfaceHandle
|
||||
|
||||
} // namespace WebSocketInterface
|
||||
} // namespace OperatorManagement
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
* DdsHandler for DDS
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Hanna E. Rathje, SLSE, 2015-09-02
|
||||
*/
|
||||
|
||||
#include "dds_handler.h"
|
||||
|
||||
#include <DDS/Core/pacemaker.h>
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
|
||||
DdsHandler::DdsHandler(int domainId)
|
||||
: m_ddsConnector(std::make_shared<DDSConnector::DdsConnector>(domainId, IDL::PartitionType::Any, 0))
|
||||
, m_logger(getLogger("DdsHandler"))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "DdsHandler(" << domainId << ") for partition: " << m_ddsConnector->getDefaultPartition();
|
||||
}
|
||||
|
||||
bool DdsHandler::init(const QStringList &qosFileList)
|
||||
{
|
||||
if(!m_ddsConnector->init(qosFileList))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error initializing dds connections - aborting";
|
||||
return false;
|
||||
}
|
||||
|
||||
// default initialize Publisher and Subscriber
|
||||
m_ddsConnector->initPublisherSubscriber();
|
||||
|
||||
// Pacemaker
|
||||
m_pacemaker = std::make_shared<Core::Pacemaker>(m_ddsConnector);
|
||||
m_topicLockMaster = std::make_shared<Core::TopicLockMaster>(m_ddsConnector);
|
||||
|
||||
m_ddsDtc = OperatorManagement::Interface::Dtc::create(m_ddsConnector);
|
||||
m_ddsDts = OperatorManagement::Interface::Dts::create(m_ddsConnector);
|
||||
m_ddsFts = OperatorManagement::Interface::Fts::create(m_ddsConnector);
|
||||
m_dtcAsm = AssetManagement::Interface::Dtc::create(m_ddsConnector);
|
||||
bool bRet = true;
|
||||
if (!m_ddsDtc->enableOperatorWorkstationAlive() ||
|
||||
!m_ddsDts->enableAccessControlLevel() ||
|
||||
!m_ddsDts->enableGroup() ||
|
||||
!m_ddsDts->enableUser() ||
|
||||
!m_ddsDts->enableActiveApp() ||
|
||||
!m_dtcAsm->enableAsset())
|
||||
bRet = false;
|
||||
INFO_LOG(m_logger) << "Dts initialised: " << bRet;;
|
||||
|
||||
bRet &= m_ddsFts->enableAll();
|
||||
INFO_LOG(m_logger) << "Fts initialised" << bRet;
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
} // Namespace OPM
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* DdsHandler for DDS
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Hanna E. Rathje, SLSE, 2015-09-02
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <DDS/DDSConnector/dds_connector.h>
|
||||
#include <DDS/Core/topic_lock_master.h>
|
||||
#include <OperatorManagement/opm_dtc.h>
|
||||
#include <OperatorManagement/opm_dts.h>
|
||||
#include <OperatorManagement/opm_fts.h>
|
||||
#include <AssetManagement/asm_dtc.h>
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
namespace Core
|
||||
{
|
||||
class Pacemaker;
|
||||
}
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
class DdsHandler final
|
||||
{
|
||||
public:
|
||||
explicit DdsHandler(int domainId);
|
||||
~DdsHandler() = default;
|
||||
|
||||
bool init(const QStringList &qosFileList = QStringList());
|
||||
|
||||
std::shared_ptr<Core::Pacemaker> pacemaker() const {return m_pacemaker; }
|
||||
std::shared_ptr<Core::TopicLockMaster> topicLockMaster() const { return m_topicLockMaster; }
|
||||
|
||||
std::shared_ptr<OperatorManagement::Interface::Dtc> dtc() const { return m_ddsDtc; }
|
||||
std::shared_ptr<OperatorManagement::Interface::Dts> dts() const { return m_ddsDts; }
|
||||
std::shared_ptr<OperatorManagement::Interface::Fts> fts() const { return m_ddsFts; }
|
||||
std::shared_ptr<AssetManagement::Interface::Dtc> dtcAsm() const { return m_dtcAsm; }
|
||||
std::shared_ptr<DDSConnector::DdsConnector> ddsConnector() const { return m_ddsConnector; }
|
||||
|
||||
private:
|
||||
std::shared_ptr<DDSConnector::DdsConnector> m_ddsConnector;
|
||||
std::shared_ptr<Core::Pacemaker> m_pacemaker;
|
||||
std::shared_ptr<Core::TopicLockMaster> m_topicLockMaster;
|
||||
std::shared_ptr<OperatorManagement::Interface::Dtc> m_ddsDtc;
|
||||
std::shared_ptr<OperatorManagement::Interface::Dts> m_ddsDts;
|
||||
std::shared_ptr<OperatorManagement::Interface::Fts> m_ddsFts;
|
||||
std::shared_ptr<AssetManagement::Interface::Dtc> m_dtcAsm;
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* Handler for all exercise objects
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Hanna E. Rathje, SLSE, 2015-09-03
|
||||
*/
|
||||
|
||||
#include "handler_access_control_level.h"
|
||||
#include "object_access_control_level.h"
|
||||
#include "opm_db.h"
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
|
||||
HandlerAccessControlLevel::HandlerAccessControlLevel(MainHandler *mainHandler)
|
||||
: m_mainHandler(mainHandler)
|
||||
, m_logger(getLogger("HandlerAccessControlLevel"))
|
||||
{}
|
||||
|
||||
HandlerAccessControlLevel::~HandlerAccessControlLevel()
|
||||
{
|
||||
qDeleteAll(m_accesscontrollevelObjMap);
|
||||
}
|
||||
|
||||
bool HandlerAccessControlLevel::init()
|
||||
{
|
||||
bool bRet = true;
|
||||
// read all AccessControlLevels from database
|
||||
auto cb = [this, &bRet] (const Database::OpmAccessControlLevel &data)
|
||||
{
|
||||
ObjectAccessControlLevel *ifs(new ObjectAccessControlLevel(m_mainHandler));
|
||||
Core::FunctionReplyObject ret = ifs->createObject(data);
|
||||
if(ret.error())
|
||||
{
|
||||
delete ifs;
|
||||
ERROR_LOG(m_logger) << ret();
|
||||
bRet = false;
|
||||
return;
|
||||
}
|
||||
m_accesscontrollevelObjMap.insert(ifs->getId(), ifs);
|
||||
};
|
||||
|
||||
if (!m_mainHandler->db()->select(cb) || !bRet)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error reading data from database!";
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "m_exeObjMap.size() = " << m_accesscontrollevelObjMap.size();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace OperatorManagement
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Handler for all Language HMI objects
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Hanna E. Rathje, SLSE, 2015-09-03
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QMap>
|
||||
|
||||
#include "main_handler.h"
|
||||
#include "logger.h"
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
class ObjectAccessControlLevel;
|
||||
|
||||
class HandlerAccessControlLevel final
|
||||
{
|
||||
public:
|
||||
explicit HandlerAccessControlLevel(MainHandler *mainHandler);
|
||||
~HandlerAccessControlLevel();
|
||||
|
||||
bool init();
|
||||
|
||||
private:
|
||||
QMap<int, ObjectAccessControlLevel*> m_accesscontrollevelObjMap;
|
||||
MainHandler *m_mainHandler;
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
};
|
||||
}
|
||||
+173
@@ -0,0 +1,173 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Handle aes filter data
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2017-06-16
|
||||
*/
|
||||
|
||||
|
||||
#include "handler_active_apps.h"
|
||||
|
||||
#include "dds_handler.h"
|
||||
#include "main_handler.h"
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
|
||||
HandlerActiveApps::HandlerActiveApps(MainHandler *mainHandler)
|
||||
: Interface::Fts::ActiveAppUpdateRequestHandler(mainHandler->dds()->fts())
|
||||
, Interface::Fts::ActiveAppRemoveRequestHandler(mainHandler->dds()->fts())
|
||||
, m_mainHandler(mainHandler)
|
||||
, m_logger(getLogger("HandlerActiveApps"))
|
||||
{
|
||||
}
|
||||
|
||||
HandlerActiveApps::~HandlerActiveApps()
|
||||
{
|
||||
cleanup();
|
||||
}
|
||||
|
||||
bool HandlerActiveApps::init()
|
||||
{
|
||||
// cleanup();
|
||||
|
||||
// broadcast startUpRequest
|
||||
// (all apps should re-register)
|
||||
ActiveApp startUpRequest(0, -1, -1, -1, -1, -1, 0);
|
||||
activeAppUpdateRequest(startUpRequest);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void HandlerActiveApps::cleanupOperator(int operatorId)
|
||||
{
|
||||
INFO_LOG(m_logger) << "cleanupOperator operatorId: " << operatorId
|
||||
<< ", m_activeApps.size = " << m_activeApps.size();
|
||||
|
||||
// Operator has logged in or out or WS is not alive anymore:
|
||||
|
||||
auto dtsPtr = dts();
|
||||
auto it = m_activeApps.begin();
|
||||
while (it != m_activeApps.end())
|
||||
{
|
||||
const ActiveApp &item = it.value();
|
||||
if (item.operatorId() == operatorId)
|
||||
{
|
||||
INFO_LOG(m_logger) << "cleanupOperator operatorId: " << operatorId << " ActiveApp=" << item;
|
||||
dtsPtr->removeActiveAppByKey(item.id());
|
||||
it = m_activeApps.erase(it);
|
||||
}
|
||||
else
|
||||
{
|
||||
++it;
|
||||
}
|
||||
} // while
|
||||
}
|
||||
|
||||
void HandlerActiveApps::cleanup()
|
||||
{
|
||||
auto dtsPtr = dts();
|
||||
for (const ActiveApp &item : qAsConst(m_activeApps))
|
||||
dtsPtr->removeActiveAppByKey(item.id());
|
||||
m_activeApps.clear();
|
||||
}
|
||||
|
||||
void HandlerActiveApps::removeZombieEntry(const ActiveApp &request)
|
||||
{
|
||||
for (auto it = m_activeApps.begin(); it != m_activeApps.end(); ++it)
|
||||
{
|
||||
const ActiveApp &item = it.value();
|
||||
if ((item.operatorId() == request.operatorId()) &&
|
||||
(item.screenId() == request.screenId()))
|
||||
{
|
||||
dts()->removeActiveAppByKey(item.id());
|
||||
m_activeApps.erase(it);
|
||||
break;
|
||||
}
|
||||
} // while
|
||||
}
|
||||
|
||||
void HandlerActiveApps::onActiveAppUpdateRequest(const rti::core::SampleIdentity &cookie,
|
||||
const ActiveApp &request)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "onActiveAppUpdateRequest: " << request;
|
||||
auto ret = activeAppUpdateRequest(request);
|
||||
if (ret.error())
|
||||
WARNING_LOG(m_logger) << ret();
|
||||
DEBUG_LOG(m_logger) << "onActiveAppUpdateRequest - returned id: " << ret.id();
|
||||
fts()->activeAppUpdateReply(cookie, ret);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject HandlerActiveApps::activeAppUpdateRequest(const ActiveApp &request)
|
||||
{
|
||||
const int reqId = request.id();
|
||||
|
||||
// handle 'remove' :
|
||||
if (request.appId() < 0) // LtsSession::App::Login is -1 but ok
|
||||
{
|
||||
Core::RemoveElementRequest removeRequest;
|
||||
removeRequest.id(reqId);
|
||||
return activeAppRemoveRequest(removeRequest);
|
||||
}
|
||||
// : handle 'remove'
|
||||
|
||||
|
||||
auto it = m_activeApps.find(reqId);
|
||||
if (it == m_activeApps.end())
|
||||
{
|
||||
static int s_idCounter = 99;
|
||||
// new entry
|
||||
removeZombieEntry(request);
|
||||
|
||||
it = m_activeApps.insert(++s_idCounter, request);
|
||||
it.value().id(s_idCounter);
|
||||
}
|
||||
else
|
||||
{
|
||||
// already exists
|
||||
if (it.value() == request)
|
||||
{
|
||||
// identical value, already registered:
|
||||
return Core::FunctionReplyObject(reqId);
|
||||
}
|
||||
// copy data
|
||||
it.value() = request;
|
||||
}
|
||||
DEBUG_LOG(m_logger) << "onActiveAppUpdateRequest - publish new data: " << it.value();
|
||||
dts()->publish(it.value());
|
||||
return Core::FunctionReplyObject(it.value().id());
|
||||
}
|
||||
|
||||
void HandlerActiveApps::onActiveAppRemoveRequest(const rti::core::SampleIdentity &cookie,
|
||||
const Core::RemoveElementRequest &request)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "onActiveAppRemoveRequest: " << request;
|
||||
auto ret = activeAppRemoveRequest(request);
|
||||
if (ret.error())
|
||||
WARNING_LOG(m_logger) << ret();
|
||||
fts()->activeAppRemoveReply(cookie, ret);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject HandlerActiveApps::activeAppRemoveRequest(const Core::RemoveElementRequest &request)
|
||||
{
|
||||
const int reqId = request.id();
|
||||
if (m_activeApps.remove(reqId) <= 0)
|
||||
return Core::FunctionReplyObject(reqId, tr_lts("dds", "ActiveApp with id %1 not found")).arg(reqId);
|
||||
|
||||
dts()->removeActiveAppByKey(reqId);
|
||||
return Core::FunctionReplyObject(reqId);
|
||||
}
|
||||
|
||||
std::shared_ptr<Interface::Dts> HandlerActiveApps::dts() const
|
||||
{
|
||||
return m_mainHandler->dds()->dts();
|
||||
}
|
||||
|
||||
std::shared_ptr<Interface::Fts> HandlerActiveApps::fts() const
|
||||
{
|
||||
return m_mainHandler->dds()->fts();
|
||||
}
|
||||
|
||||
} // namespace FilterManagement
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Handle aes filter data
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2017-06-16
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QHash>
|
||||
#include <OperatorManagement/opm_dts.h>
|
||||
#include <OperatorManagement/opm_fts.h>
|
||||
#include "logger.h"
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
class DatabaseInterface;
|
||||
class DdsHandler;
|
||||
class MainHandler;
|
||||
class HandlerActiveApps final
|
||||
: protected Interface::Fts::ActiveAppUpdateRequestHandler
|
||||
, protected Interface::Fts::ActiveAppRemoveRequestHandler
|
||||
{
|
||||
public:
|
||||
explicit HandlerActiveApps(OperatorManagement::MainHandler *mainHandler);
|
||||
~HandlerActiveApps();
|
||||
|
||||
bool init();
|
||||
void cleanupOperator(int operatorId);
|
||||
|
||||
private:
|
||||
void cleanup();
|
||||
void removeZombieEntry(const ActiveApp &request);
|
||||
void onActiveAppUpdateRequest(const rti::core::SampleIdentity &cookie,
|
||||
const ActiveApp &request) override;
|
||||
void onActiveAppRemoveRequest(const rti::core::SampleIdentity &cookie,
|
||||
const Core::RemoveElementRequest &request) override;
|
||||
Core::FunctionReplyObject activeAppUpdateRequest(const ActiveApp &request);
|
||||
Core::FunctionReplyObject activeAppRemoveRequest(const Core::RemoveElementRequest &request);
|
||||
|
||||
std::shared_ptr<Interface::Dts> dts() const;
|
||||
std::shared_ptr<Interface::Fts> fts() const;
|
||||
|
||||
private:
|
||||
QHash<int /*id*/, ActiveApp> m_activeApps;
|
||||
MainHandler *m_mainHandler;
|
||||
LOGGER_T m_logger;
|
||||
};
|
||||
}
|
||||
+269
@@ -0,0 +1,269 @@
|
||||
/**
|
||||
* Handler for all exercise objects
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Hanna E. Rathje, SLSE, 2015-09-03
|
||||
*/
|
||||
|
||||
#include "handler_group.h"
|
||||
#include "object_group.h"
|
||||
#include "handler_operator.h"
|
||||
#include "opm_db.h"
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
|
||||
HandlerGroup::HandlerGroup(MainHandler *mainHandler)
|
||||
: Interface::Fts::GroupChangeMembershipsRequestHandler(mainHandler->fts())
|
||||
, Interface::Fts::GroupChangeNameRequestHandler(mainHandler->fts())
|
||||
, Interface::Fts::GroupCreateRequestHandler(mainHandler->fts())
|
||||
, Interface::Fts::GroupRemoveRequestHandler(mainHandler->fts())
|
||||
, m_mainHandler(mainHandler)
|
||||
, m_logger(getLogger("HandlerGroup"))
|
||||
{}
|
||||
|
||||
HandlerGroup::~HandlerGroup()
|
||||
{
|
||||
qDeleteAll(m_groupObjMap);
|
||||
}
|
||||
|
||||
static inline std::vector<int> multiMapValuesToVector(const QMultiMap<int, int> &multiMap, int key)
|
||||
{
|
||||
std::vector<int> res;
|
||||
auto it = multiMap.find(key);
|
||||
if (it != multiMap.cend())
|
||||
{
|
||||
do
|
||||
{
|
||||
res.push_back(it.value());
|
||||
++it;
|
||||
}
|
||||
while (it != multiMap.constEnd() && it.key() == key);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool HandlerGroup::init()
|
||||
{
|
||||
// create group/group map
|
||||
auto cbGroupGroup = [this](const Database::OpmGroupGroup &groupGroup)
|
||||
{
|
||||
m_groupGroupMap.insert(groupGroup.groupId, groupGroup.isMemberOfGroupId);
|
||||
};
|
||||
if (!m_mainHandler->db()->select(cbGroupGroup))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error reading data from database!";
|
||||
return true;
|
||||
}
|
||||
|
||||
// create group/aclAllow map
|
||||
auto cbAclAllow = [this](const Database::OpmAclAllow &aclAllow)
|
||||
{
|
||||
m_aclAllowMap.insert(aclAllow.groupId, aclAllow.aclId);
|
||||
};
|
||||
if (!m_mainHandler->db()->select(cbAclAllow))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error reading data from database!";
|
||||
return true;
|
||||
}
|
||||
|
||||
// create group/aclDeny map
|
||||
auto cbAclDeny = [this](const Database::OpmAclDeny &aclDeny)
|
||||
{
|
||||
m_aclDenyMap.insert(aclDeny.groupId, aclDeny.aclId);
|
||||
};
|
||||
if (!m_mainHandler->db()->select(cbAclDeny))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error reading data from database!";
|
||||
return true;
|
||||
}
|
||||
|
||||
// create group objects
|
||||
bool bRet = true;
|
||||
auto cbGroup = [this, &bRet] (const Database::OpmGroup &group)
|
||||
{
|
||||
ObjectGroup *ifs(new ObjectGroup(m_mainHandler));
|
||||
Core::FunctionReplyObject ret = ifs->createObject(group,
|
||||
multiMapValuesToVector(m_groupGroupMap, group.id),
|
||||
multiMapValuesToVector(m_aclAllowMap, group.id),
|
||||
multiMapValuesToVector(m_aclDenyMap, group.id)
|
||||
);
|
||||
if (ret.error())
|
||||
{
|
||||
delete ifs;
|
||||
ERROR_LOG(m_logger) << ret();
|
||||
bRet = false;
|
||||
return;
|
||||
}
|
||||
m_groupObjMap.insert(ifs->getId(), ifs);
|
||||
};
|
||||
if (!m_mainHandler->db()->select(cbGroup) || !bRet)
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error reading data from database!";
|
||||
return false;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "m_exeObjMap.size() = " << m_groupObjMap.size();
|
||||
INFO_LOG(m_logger) << "Handler Group initialized";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void HandlerGroup::updateRolePresetId(const int operatorId, const int rolePresetId)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "updateRolePresetId "
|
||||
<< " operatorId=" << operatorId
|
||||
<< " rolePresetId=" << rolePresetId;
|
||||
m_mainHandler->getHandlerOperator()->operatorModifyRolePresetId( operatorId, rolePresetId);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject HandlerGroup::changeMembership(const OperatorManagement::GroupChangeMembersRequest &request)
|
||||
{
|
||||
ObjectGroup *ifs = m_groupObjMap.value(request.id());
|
||||
if (!ifs)
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "No valid group id for changing memberships."));
|
||||
|
||||
Core::FunctionReplyObject fro;
|
||||
if (request.memberships().size() > 0)
|
||||
fro = ifs->updateMemberships(request.memberships());
|
||||
else
|
||||
fro = ifs->removeAllMemberships();
|
||||
|
||||
// Use the sledgehammer to crack the nut. We don't know which operator is affected.
|
||||
// Finding out can be a hazzle...
|
||||
m_mainHandler->getHandlerOperator()->reloadAcls();
|
||||
return fro;
|
||||
}
|
||||
|
||||
void HandlerGroup::onGroupChangeMembershipsRequest(const rti::core::SampleIdentity &cookie,
|
||||
const GroupChangeMembersRequest &request)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "onGroupChangeMembershipsRequest " << request;
|
||||
Core::FunctionReplyObject ret = changeMembership(request);
|
||||
if (request.operatorId().is_set() && request.rolePresetId().is_set())
|
||||
updateRolePresetId(request.operatorId().get(), request.rolePresetId().get());
|
||||
if (ret.error())
|
||||
WARNING_LOG(m_logger) << ret();
|
||||
m_mainHandler->fts()->groupChangeMembershipsReply(cookie, ret);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject HandlerGroup::create(const GroupCreateRequest &request)
|
||||
{
|
||||
Database::OpmGroup group;
|
||||
group.name = QString::fromStdString(request.name());
|
||||
for (const ObjectGroup *g : qAsConst(m_groupObjMap))
|
||||
{
|
||||
if (g->name().compare(group.name, Qt::CaseInsensitive) == 0)
|
||||
return Core::FunctionReplyObject(-1, tr_lts("dds", "Name '%1' already exists")).arg(group.name);
|
||||
}
|
||||
group.description = QString::fromStdString(request.description());
|
||||
group.typeId = request.type();
|
||||
group.isHidden = request.isHidden().is_set() ? request.isHidden().get() : false;
|
||||
|
||||
ObjectGroup *ifs(new ObjectGroup(m_mainHandler));
|
||||
Core::FunctionReplyObject ret = ifs->createObject(group, request.memberships().is_set() ? request.memberships().get() : std::vector<int32_t>());
|
||||
if (ret.error())
|
||||
{
|
||||
delete ifs;
|
||||
return ret;
|
||||
}
|
||||
m_groupObjMap.insert(ifs->getId(), ifs);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void HandlerGroup::onGroupCreateRequest(const rti::core::SampleIdentity &cookie,
|
||||
const GroupCreateRequest &request)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "onGroupCreateRequest" << request;
|
||||
Core::FunctionReplyObject ret = create(request);
|
||||
if (ret.error())
|
||||
WARNING_LOG(m_logger) << ret();
|
||||
m_mainHandler->fts()->groupCreateReply(cookie, ret);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject HandlerGroup::changeName(const OperatorManagement::GroupChangeNameRequest &request)
|
||||
{
|
||||
ObjectGroup *ifs = m_groupObjMap.value(request.id());
|
||||
if (!ifs)
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "No valid group id for renaming."));
|
||||
|
||||
Database::OpmGroup group = ifs->data();
|
||||
group.name = QString::fromStdString(request.name());
|
||||
group.description = QString::fromStdString(request.description());
|
||||
|
||||
for (const ObjectGroup *g : qAsConst(m_groupObjMap))
|
||||
{
|
||||
if (g == ifs)
|
||||
continue;
|
||||
if (g->name().compare(group.name, Qt::CaseInsensitive) == 0)
|
||||
return Core::FunctionReplyObject(-1, tr_lts("dds", "Name '%1' already exists")).arg(group.name);
|
||||
}
|
||||
|
||||
return ifs->updateObject(group);
|
||||
}
|
||||
|
||||
void HandlerGroup::onGroupChangeNameRequest(const rti::core::SampleIdentity &cookie,
|
||||
const GroupChangeNameRequest &request)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "onGroupChangeNameRequest" << request;
|
||||
|
||||
Core::FunctionReplyObject ret;
|
||||
ObjectGroup *ifs = m_groupObjMap.value(request.id());
|
||||
if (!ifs)
|
||||
{
|
||||
ret = Core::FunctionReplyObject(0, tr_lts("dds", "No valid group id for renaming."));
|
||||
m_mainHandler->fts()->groupChangeNameReply(cookie, ret);
|
||||
return;
|
||||
}
|
||||
|
||||
Database::OpmGroup group = ifs->data();
|
||||
if (group.typeId == GroupType_def::OperatorGroup && (group.name != QString::fromStdString(request.name())))
|
||||
{
|
||||
ret = Core::FunctionReplyObject(0, tr_lts("dds", "Operator group may not be renamed."));
|
||||
m_mainHandler->fts()->groupChangeNameReply(cookie, ret);
|
||||
return;
|
||||
}
|
||||
ret = changeName(request);
|
||||
m_mainHandler->fts()->groupChangeNameReply(cookie, ret);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject HandlerGroup::remove(const Core::RemoveElementRequest &request)
|
||||
{
|
||||
ObjectGroup *ifs = m_groupObjMap.value(request.id());
|
||||
if (!ifs)
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "No valid group id for deleting."));
|
||||
|
||||
OperatorManagement::Group ddsData;
|
||||
ddsData.id(request.id());
|
||||
|
||||
if (m_mainHandler->dds()->topicLockMaster()->isLocked(ddsData, 0))
|
||||
return Core::FunctionReplyObject(request.id(), tr_lts("dds", "Group '%1' is used by another user!")).arg(ifs->name());
|
||||
|
||||
Core::FunctionReplyObject ret = ifs->removeObject();
|
||||
if (ret.error())
|
||||
return ret;
|
||||
m_groupObjMap.remove(request.id());
|
||||
m_groupGroupMap.remove(request.id());
|
||||
for (auto it = m_groupGroupMap.begin(); it != m_groupGroupMap.end();)
|
||||
if (it.value() == request.id())
|
||||
it = m_groupGroupMap.erase(it);
|
||||
else
|
||||
++it;
|
||||
|
||||
delete ifs;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void HandlerGroup::onGroupRemoveRequest(const rti::core::SampleIdentity &cookie,
|
||||
const Core::RemoveElementRequest &request)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "onGroupRemoveRequest" << request;
|
||||
Core::FunctionReplyObject ret = remove(request);
|
||||
if (ret.error())
|
||||
WARNING_LOG(m_logger) << ret();
|
||||
m_mainHandler->fts()->groupRemoveReply(cookie, ret);
|
||||
}
|
||||
|
||||
} // Namespace OperatorManagement
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* Handler for all Language HMI objects
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Hanna E. Rathje, SLSE, 2015-09-03
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QMap>
|
||||
|
||||
#include "main_handler.h"
|
||||
#include "logger.h"
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
class ObjectGroup;
|
||||
|
||||
class HandlerGroup final
|
||||
: protected Interface::Fts::GroupChangeMembershipsRequestHandler
|
||||
, protected Interface::Fts::GroupChangeNameRequestHandler
|
||||
, protected Interface::Fts::GroupCreateRequestHandler
|
||||
, protected Interface::Fts::GroupRemoveRequestHandler
|
||||
{
|
||||
public:
|
||||
explicit HandlerGroup(MainHandler *mainHandler);
|
||||
~HandlerGroup();
|
||||
|
||||
bool init();
|
||||
public:
|
||||
Core::FunctionReplyObject changeMembership(const GroupChangeMembersRequest &request);
|
||||
Core::FunctionReplyObject create(const GroupCreateRequest &request);
|
||||
Core::FunctionReplyObject changeName(const GroupChangeNameRequest &request);
|
||||
Core::FunctionReplyObject remove(const Core::RemoveElementRequest &request);
|
||||
|
||||
private:
|
||||
void onGroupChangeMembershipsRequest(const rti::core::SampleIdentity &cookie,
|
||||
const GroupChangeMembersRequest &request) override;
|
||||
void onGroupCreateRequest(const rti::core::SampleIdentity &cookie,
|
||||
const GroupCreateRequest &request) override;
|
||||
void onGroupChangeNameRequest(const rti::core::SampleIdentity &cookie,
|
||||
const GroupChangeNameRequest &request) override;
|
||||
void onGroupRemoveRequest(const rti::core::SampleIdentity &cookie,
|
||||
const Core::RemoveElementRequest &request) override;
|
||||
|
||||
void updateRolePresetId( const int operatorId, const int rolePresetId);
|
||||
|
||||
private:
|
||||
QMap<int, ObjectGroup*> m_groupObjMap;
|
||||
QMultiMap<int, int> m_groupGroupMap;
|
||||
QMultiMap<int, int> m_aclAllowMap;
|
||||
QMultiMap<int, int> m_aclDenyMap;
|
||||
MainHandler *m_mainHandler;
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
};
|
||||
}
|
||||
+426
@@ -0,0 +1,426 @@
|
||||
/**
|
||||
* Block/unblock topics
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2018-01-15
|
||||
*/
|
||||
|
||||
#include "handler_locked_topics.h"
|
||||
#include "main_handler.h"
|
||||
#include "handler_operator.h"
|
||||
#include <DDS/FTS/generic_fts_impl.h>
|
||||
#include <DDS/DTS/generic_dts_impl.h>
|
||||
#include <DDS/Core/function_reply_object.h>
|
||||
|
||||
#include <QMutableHashIterator>
|
||||
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
HandlerLockedTopics::HandlerLockedTopics(MainHandler &mainHandler,
|
||||
QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_mainHandler(mainHandler)
|
||||
, m_logger(getLogger("HandlerLockedTopics"))
|
||||
{}
|
||||
|
||||
bool HandlerLockedTopics::init()
|
||||
{
|
||||
m_db = m_mainHandler.db();
|
||||
auto ddsConnector = m_mainHandler.dds()->ddsConnector();
|
||||
if (!m_db || !ddsConnector)
|
||||
return false;
|
||||
|
||||
ddsConnector->initSubscriber();
|
||||
|
||||
{
|
||||
m_ftsTryLockEntity.reset(ddsConnector->createFTS<FTS::TryLockEntity>());
|
||||
const auto cb = [this](const rti::core::SampleIdentity & cookie, const Core::TryLockEntityRequest & request)
|
||||
{
|
||||
this->onTryLockEntityRequest(cookie, request);
|
||||
};
|
||||
m_ftsTryLockEntity->setSubscriberCallback(cb);
|
||||
}
|
||||
|
||||
{
|
||||
m_ftsTryUnlockEntity.reset(ddsConnector->createFTS<FTS::TryUnlockEntity>());
|
||||
const auto cb = [this](const rti::core::SampleIdentity & cookie, const Core::TryUnlockEntityRequest & request)
|
||||
{
|
||||
this->onTryUnlockEntityRequest(cookie, request);
|
||||
};
|
||||
m_ftsTryUnlockEntity->setSubscriberCallback(cb);
|
||||
}
|
||||
|
||||
auto cbDatabase = [this](const Database::OpmLockedTopics & data)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Locked topic from db: " << data.exerciseId.toInt() << ", " << data.workstationId
|
||||
<< ", " << data.operatorId << data.entityTypeName;
|
||||
m_lockedTopics.insert(Core::key(data.entityId, data.exerciseId.isNull() ? 0 : data.exerciseId.toInt(), data.entityTypeName), data);
|
||||
};
|
||||
m_db->selectByLocked(cbDatabase, true);
|
||||
|
||||
m_dtsLockedEntity.reset(ddsConnector->createDTS<DTS::LockedEntityImpl>());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool needsUnlock(int operatorId, int workstationId, const Database::OpmLockedTopics &data)
|
||||
{
|
||||
// same operator -> check if other workstation
|
||||
if (operatorId == data.operatorId)
|
||||
{
|
||||
return true; // NT, 18.09.20 remove. From former (crashed) session, independent from workstation
|
||||
|
||||
// if (workstationId == 0) // logout
|
||||
// return true;
|
||||
// if (workstationId != data.workstationId) // logged in on another workstation
|
||||
// return true;
|
||||
// return false;
|
||||
|
||||
}
|
||||
// other operator on a workstation previously locked by another operator -> unlock
|
||||
if (workstationId != 0 && workstationId == data.workstationId)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void HandlerLockedTopics::operatorLoggedInOut(int operatorId, int workstationId)
|
||||
{
|
||||
// check if there are stale locks (e.g. by crashing client) - then remove all of them - if there are any
|
||||
|
||||
DEBUG_LOG(m_logger) << "operatorLoggedInOut: " << workstationId << ", " << operatorId;
|
||||
|
||||
// Ueberall wurden - ohne erase wohlgemerkt - mutable Iteratoren verwendet. Nur hier - wo erase verwendet wurde - nicht! :')
|
||||
QMutableHashIterator<Core::key, Database::OpmLockedTopics> it(m_lockedTopics);
|
||||
|
||||
while (it.hasNext())
|
||||
{
|
||||
const auto lockedTopic = it.next().value();
|
||||
|
||||
DEBUG_LOG(m_logger) << "check if unlock: id=" << lockedTopic.id
|
||||
<< ", exId=" << lockedTopic.exerciseId.toInt()
|
||||
<< ", wsId=" << lockedTopic.workstationId
|
||||
<< ", opId=" << lockedTopic.operatorId;
|
||||
if (!needsUnlock(operatorId, workstationId, lockedTopic))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "Unlocking topic: id=" << lockedTopic.id
|
||||
<< ", exId=" << lockedTopic.exerciseId.toInt()
|
||||
<< ", wsId=" << lockedTopic.workstationId
|
||||
<< ", opId=" << lockedTopic.operatorId;
|
||||
unlockInDb(lockedTopic);
|
||||
removeLockedEntity(lockedTopic.id);
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
void HandlerLockedTopics::onTryLockEntityRequest(const rti::core::SampleIdentity &cookie,
|
||||
const Core::TryLockEntityRequest &request)
|
||||
{
|
||||
if (m_logger.isDebugEnabled())
|
||||
dumpLockedTopics(__LINE__);
|
||||
|
||||
auto ret = tryLock(request);
|
||||
if (!ret.errorString().empty())
|
||||
{
|
||||
WARNING_LOG(m_logger) << Core::FunctionReplyObject(ret.FunctionReply::id(), ret.errorString(), ret.errorParams()).translated() << " - " << request;
|
||||
}
|
||||
else if (ret.alreadyLocked())
|
||||
{
|
||||
WARNING_LOG(m_logger) << "onTryLockEntityRequest failed because the topic was already locked by ws " << ret.alreadyLocked().get().workstationName() << " and op " << ret.alreadyLocked().get().operatorName() << " - " << request;
|
||||
}
|
||||
m_ftsTryLockEntity->sendReply(cookie, ret);
|
||||
|
||||
if (m_logger.isDebugEnabled())
|
||||
dumpLockedTopics(__LINE__);
|
||||
}
|
||||
|
||||
Core::TryLockEntityReply lockErrorReply(const long topicId, const std::string &msg)
|
||||
{
|
||||
return Core::TryLockEntityReply(-1, msg, { std::to_string(topicId) }, {}, {});
|
||||
}
|
||||
|
||||
Core::TryLockEntityReply lockAlreadyLockedReply(const std::string &ws, const QString &op)
|
||||
{
|
||||
return Core::TryLockEntityReply(-1, {}, {},{}, Core::LockEntityError(ws, op.toStdString()));
|
||||
}
|
||||
|
||||
Core::TryLockEntityReply lockSuccessReply(const Database::OpmLockedTopics &dbStruct)
|
||||
{
|
||||
return Core::TryLockEntityReply(dbStruct.id, {}, {}, {}, {});
|
||||
}
|
||||
|
||||
Core::TryLockEntityReply HandlerLockedTopics::tryLock(const Core::TryLockEntityRequest &request)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "tryLock : " << request;
|
||||
|
||||
const auto topicId = request.entityId();
|
||||
|
||||
const Core::key k(request.entityId(), request.exerciseId(), QString::fromStdString(request.entityTypeName()));
|
||||
Database::OpmLockedTopics dbStruct(toDb(request));
|
||||
auto it = m_lockedTopics.constFind(k);
|
||||
if (it == m_lockedTopics.constEnd())
|
||||
{
|
||||
// noch nicht vorhanden -> add
|
||||
dbStruct.timeStampLock = QDateTime::currentMSecsSinceEpoch();
|
||||
if (!m_db->insert(dbStruct))
|
||||
{
|
||||
return lockErrorReply(topicId, tr_lts("dds", "Failed to lock element with id %1 in database"));
|
||||
}
|
||||
|
||||
m_lockedTopics.insert(k, dbStruct);
|
||||
Core::LockedEntity lckEntity(request.operatorId(), request.workstationId(),
|
||||
request.exerciseId(), request.entityId(),
|
||||
request.entityTypeName(), dbStruct.id);
|
||||
publishLockedEntity(lckEntity);
|
||||
return lockSuccessReply(dbStruct);
|
||||
}
|
||||
|
||||
// NOTE: don't check if there is already a lock for that exact same key (same op, ws, topic, ...): Reason: Szenario: in 2 sitmaps "Exercise Purpose" aufschalten... 2. Dlg muss gelockt werden !!!
|
||||
|
||||
// already locked by another user
|
||||
const Database::OpmLockedTopics &data = *it;
|
||||
const auto opName = m_mainHandler.getHandlerOperator()->operatorNameById(data.operatorId);
|
||||
const auto wsName = m_mainHandler.dds()->dtcAsm()->asset(data.workstationId).name();
|
||||
|
||||
return lockAlreadyLockedReply(wsName, opName);
|
||||
}
|
||||
|
||||
//Core::TryLockEntityReply HandlerLockedTopics::tryLockModify(const Core::TryLockEntityRequest &request)
|
||||
//{
|
||||
// DEBUG_LOG(m_logger) << "tryLockModify: " << request;
|
||||
|
||||
// const auto lockEntityId = request.id();
|
||||
|
||||
// // requestedKey == new key
|
||||
// const Core::key requestedKey(request.entityId(), request.exerciseId(), QString::fromStdString(request.entityTypeName()));
|
||||
|
||||
// // is requested topic already locked?
|
||||
// {
|
||||
// auto it = m_lockedTopics.constFind(requestedKey);
|
||||
// if (it != m_lockedTopics.constEnd())
|
||||
// {
|
||||
// // vorhanden -> locked by another user/dlg
|
||||
// // or be me??? (locked by this dialog instance / topicId ?
|
||||
// const Database::OpmLockedTopics &data = it.value();
|
||||
// if (lockEntityId != data.id)
|
||||
// {
|
||||
// // vorhanden and locked by another user/dlg:
|
||||
// // "release" my *former* lock:
|
||||
// removeReleaseOutdatedLock(lockEntityId);
|
||||
|
||||
// const auto opName = m_mainHandler->getHandlerOperator()->operatorNameById(data.operatorId);
|
||||
// const auto wsName = m_mainHandler->dds()->dtcAsm()->asset(data.workstationId).name();
|
||||
|
||||
// return lockAlreadyLockedReply(wsName, opName);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // not already lock -> 'update' the entry:
|
||||
// //
|
||||
// // 1) DB-Update
|
||||
// //
|
||||
// Database::OpmLockedTopics dbStruct(toDb(request));
|
||||
// dbStruct.id = lockEntityId; // to enable dbUpdate :-)
|
||||
// dbStruct.timeStampLock = QDateTime::currentMSecsSinceEpoch();
|
||||
|
||||
// if (!m_db->update(dbStruct))
|
||||
// {
|
||||
// return lockErrorReply(lockEntityId, tr_lts("dds", "Failed to update lock entity (%1) in database"));
|
||||
// }
|
||||
|
||||
// //
|
||||
// // 2) DDS-Update
|
||||
// //
|
||||
// Core::LockedEntity lckEntity(request.operatorId(), request.workstationId(),
|
||||
// request.exerciseId(), request.entityId(),
|
||||
// request.entityTypeName(), dbStruct.id);
|
||||
// publishLockedEntity(lckEntity);
|
||||
|
||||
|
||||
// //
|
||||
// // 3) QHash-Update
|
||||
// //
|
||||
|
||||
// // update both: key and value!!! by removing the key-value-pair with topicId ...
|
||||
// {
|
||||
// auto lockedTopicIt = std::find_if(m_lockedTopics.constBegin(), m_lockedTopics.constEnd(),
|
||||
// [&lockEntityId](const Database::OpmLockedTopics &lockedTopic)
|
||||
// {
|
||||
// return (lockEntityId == lockedTopic.id);
|
||||
// });
|
||||
|
||||
// if (lockedTopicIt == m_lockedTopics.constEnd())
|
||||
// {
|
||||
// return lockErrorReply(lockEntityId, tr_lts("dds", "Failed to update lock entity (%1) on the heap"));
|
||||
// }
|
||||
|
||||
// const Database::OpmLockedTopics &lockedTopic = *lockedTopicIt;
|
||||
// DEBUG_LOG(m_logger) << LOGFUNCTION << ": locked topic id " << lockedTopic.id;
|
||||
// // ... and then reinserting the updated lock entity (as the id has now changed) - while the key (op, ws, exc, topic id) stays the same!
|
||||
// m_lockedTopics[requestedKey] = dbStruct;
|
||||
// }
|
||||
|
||||
// return lockSuccessReply(dbStruct); // success
|
||||
//}
|
||||
|
||||
//bool HandlerLockedTopics::removeReleaseOutdatedLock(const int lockEntityId)
|
||||
//{
|
||||
// DEBUG_LOG(m_logger) << "removeReleaseOutdatedLock: lockEntityId = " << lockEntityId;
|
||||
|
||||
// auto lockedTopicIt = std::find_if(m_lockedTopics.constBegin(), m_lockedTopics.constEnd(),
|
||||
// [&lockEntityId](const Database::OpmLockedTopics &lockedTopic)
|
||||
// {
|
||||
// return (lockEntityId == lockedTopic.id);
|
||||
// });
|
||||
|
||||
// if (lockedTopicIt == m_lockedTopics.constEnd())
|
||||
// {
|
||||
// ERROR_LOG(m_logger) << LOGFUNCTION << ": Failed to release outdated lock as lock entity id ("<<lockedTopicIt<<") was not found!";
|
||||
// Q_ASSERT(false);
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// const Database::OpmLockedTopics &lockedTopic = *lockedTopicIt;
|
||||
// DEBUG_LOG(m_logger) << LOGFUNCTION << ": found lock entity " << lockEntityId;
|
||||
|
||||
// unlockInDb(lockedTopic);
|
||||
// removeLockedEntity(lockEntityId);
|
||||
|
||||
// m_lockedTopics.erase(lockedTopicIt);
|
||||
|
||||
// return true;
|
||||
//}
|
||||
|
||||
void HandlerLockedTopics::onTryUnlockEntityRequest(const rti::core::SampleIdentity &cookie,
|
||||
const Core::TryUnlockEntityRequest &request)
|
||||
{
|
||||
if (m_logger.isDebugEnabled())
|
||||
dumpLockedTopics(__LINE__);
|
||||
|
||||
auto ret = tryUnlock(request);
|
||||
if (!ret.errorString().empty())
|
||||
{
|
||||
WARNING_LOG(m_logger) << Core::FunctionReplyObject(ret.FunctionReply::id(), ret.errorString(), ret.errorParams()).translated() << " - " << request;
|
||||
}
|
||||
m_ftsTryUnlockEntity->sendReply(cookie, ret);
|
||||
|
||||
if (m_logger.isDebugEnabled())
|
||||
dumpLockedTopics(__LINE__);
|
||||
}
|
||||
|
||||
Core::FunctionReply HandlerLockedTopics::tryUnlock(const Core::TryUnlockEntityRequest &request)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "tryUnlock: " << request;
|
||||
|
||||
const auto lockEntityId = request.id();
|
||||
|
||||
auto lockedTopicIt = std::find_if(m_lockedTopics.constBegin(), m_lockedTopics.constEnd(),
|
||||
[lockEntityId](const Database::OpmLockedTopics &lockedTopic)
|
||||
{
|
||||
return (lockEntityId == lockedTopic.id);
|
||||
});
|
||||
|
||||
if (lockedTopicIt == m_lockedTopics.constEnd())
|
||||
{
|
||||
// nicht vorhanden => unlock nicht möglich
|
||||
return Core::FunctionReply(-1, tr_lts("dds", "Failed to unlock unknown lock with id %1."), {}, { std::to_string(lockEntityId) });
|
||||
}
|
||||
|
||||
// found => unlock
|
||||
const Database::OpmLockedTopics &lockedTopic = *lockedTopicIt;
|
||||
unlockInDb(lockedTopic);
|
||||
removeLockedEntity(lockedTopic.id);
|
||||
m_lockedTopics.erase(lockedTopicIt);
|
||||
return Core::FunctionReply(); // success!
|
||||
}
|
||||
|
||||
void HandlerLockedTopics::unlockInDb(const Database::OpmLockedTopics &data)
|
||||
{
|
||||
Database::OpmLockedTopics dbStruct(data);
|
||||
dbStruct.locked = false;
|
||||
dbStruct.timeStampUnlock = QDateTime::currentMSecsSinceEpoch();
|
||||
m_db->update(dbStruct);
|
||||
}
|
||||
|
||||
Database::OpmLockedTopics HandlerLockedTopics::toDb(const Core::LockedEntityBase &request)
|
||||
{
|
||||
Database::OpmLockedTopics ret;
|
||||
ret.locked = true;
|
||||
ret.entityId = request.entityId();
|
||||
ret.entityTypeName = QString::fromStdString(request.entityTypeName());
|
||||
ret.operatorId = request.operatorId();
|
||||
ret.workstationId = request.workstationId();
|
||||
ret.exerciseId = request.exerciseId() ? QVariant(request.exerciseId()) : QVariant();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool HandlerLockedTopics::publishLockedEntity(const Core::LockedEntity &entity)
|
||||
{
|
||||
if (m_dtsLockedEntity)
|
||||
{
|
||||
m_dtsLockedEntity->write(entity);
|
||||
return true;
|
||||
}
|
||||
ERROR_LOG(m_logger) << "Publishing LockedEntity " << entity.id() << " failed: DTS not available!";
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HandlerLockedTopics::removeLockedEntity(int64_t id)
|
||||
{
|
||||
Core::LockedEntity entity;
|
||||
entity.id(id);
|
||||
if (m_dtsLockedEntity)
|
||||
{
|
||||
m_dtsLockedEntity->remove(entity);
|
||||
return true;
|
||||
}
|
||||
ERROR_LOG(m_logger) << "Removing LockedEntity " << entity.id() << " failed: DTS not available!";
|
||||
return false;
|
||||
}
|
||||
|
||||
//Core::key HandlerLockedTopics::topicIdToKey(long id)
|
||||
//{
|
||||
// QHashIterator<Core::key, Database::OpmLockedTopics> it (m_lockedTopics);
|
||||
|
||||
// while (it.hasNext())
|
||||
// {
|
||||
// it.next();
|
||||
// const Database::OpmLockedTopics &topicRef = it.value();
|
||||
// if (topicRef.id == id)
|
||||
// {
|
||||
// return it.key();
|
||||
// }
|
||||
// } // while (it.hasNext())
|
||||
|
||||
// return {};
|
||||
//}
|
||||
|
||||
void HandlerLockedTopics::dumpLockedTopics(int line)
|
||||
{
|
||||
QHashIterator<Core::key, Database::OpmLockedTopics> it (m_lockedTopics);
|
||||
|
||||
INFO_LOG(m_logger) << " dump m_lockedTopics, START size= " << m_lockedTopics.size()
|
||||
<< " (callerline=" << line << ")";
|
||||
while (it.hasNext())
|
||||
{
|
||||
it.next();
|
||||
const Core::key &keyRef = it.key();
|
||||
const Database::OpmLockedTopics &valRef = it.value();
|
||||
INFO_LOG(m_logger) << " entityTypeName=" << keyRef.entityTypeName << "'"
|
||||
<< ", entityId=" << keyRef.entityId
|
||||
<< ", exerciseId=" << keyRef.exerciseId
|
||||
<< " - eTN=" << valRef.entityTypeName
|
||||
<< ", entityId=" << valRef.entityId
|
||||
<< ", exId=" << valRef.exerciseId.toInt()
|
||||
<< ", opId=" << valRef.operatorId;
|
||||
}
|
||||
INFO_LOG(m_logger) << " dump m_lockedTopics, END size= " << m_lockedTopics.size();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* Block/unblock topics
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Christian Ehrlicher, SLSE, 2018-01-15
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include "logger.h"
|
||||
#include "opm_db.h"
|
||||
|
||||
#include <DDS/Core/core_fts_types.h>
|
||||
#include <DDS/Core/core_dts_types.h>
|
||||
#include <DDS/Core/topic_lock_master.h>
|
||||
#include <DDS/DTS/generic_dts_impl.h>
|
||||
#include <DDS/FTS/generic_fts_impl.h>
|
||||
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
class MainHandler;
|
||||
class HandlerLockedTopics final : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit HandlerLockedTopics(MainHandler &mainHandler,
|
||||
QObject *parent = nullptr);
|
||||
bool init();
|
||||
|
||||
void operatorLoggedIn(int operatorId, int workstationId) { operatorLoggedInOut(operatorId, workstationId); }
|
||||
void operatorLoggedOut(int operatorId) { operatorLoggedInOut(operatorId, 0); }
|
||||
|
||||
private:
|
||||
// we logged out - unlock all still locked topics (workstationId should be zero then)
|
||||
// we logged in again - unlock all still locked topics which are not for current workstation
|
||||
void operatorLoggedInOut(int operatorId, int workstationId);
|
||||
|
||||
/// Lock
|
||||
void onTryLockEntityRequest(const rti::core::SampleIdentity &cookie, const Core::TryLockEntityRequest &request);
|
||||
Core::TryLockEntityReply tryLock(const Core::TryLockEntityRequest &request);
|
||||
//Core::TryLockEntityReply tryLockModify(const Core::TryLockEntityRequest &request);
|
||||
|
||||
/// Unlock
|
||||
void onTryUnlockEntityRequest(const rti::core::SampleIdentity &cookie, const Core::TryUnlockEntityRequest &request);
|
||||
Core::FunctionReply tryUnlock(const Core::TryUnlockEntityRequest &request);
|
||||
|
||||
//bool removeReleaseOutdatedLock(int topicId);
|
||||
void unlockInDb(const Database::OpmLockedTopics &data);
|
||||
static Database::OpmLockedTopics toDb(const Core::LockedEntityBase &request);
|
||||
bool publishLockedEntity(const Core::LockedEntity &entity);
|
||||
bool removeLockedEntity(int64_t id);
|
||||
|
||||
//Core::key topicIdToKey(long id);
|
||||
void dumpLockedTopics(int line);
|
||||
|
||||
private:
|
||||
QHash<Core::key, Database::OpmLockedTopics> m_lockedTopics;
|
||||
|
||||
MainHandler &m_mainHandler;
|
||||
std::shared_ptr<DatabaseInterface> m_db;
|
||||
std::unique_ptr<FTS::TryLockEntity> m_ftsTryLockEntity;
|
||||
std::unique_ptr<FTS::TryUnlockEntity>m_ftsTryUnlockEntity;
|
||||
std::unique_ptr<DTS::LockedEntity> m_dtsLockedEntity;
|
||||
LOGGER_T m_logger;
|
||||
};
|
||||
} // namespace OperatorManagement
|
||||
+685
@@ -0,0 +1,685 @@
|
||||
/**
|
||||
* Handler for all exercise objects
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Hanna E. Rathje, SLSE, 2015-09-03
|
||||
*/
|
||||
|
||||
#include "handler_operator.h"
|
||||
#include "handler_locked_topics.h"
|
||||
#include "handler_active_apps.h"
|
||||
#include "object_operator.h"
|
||||
#include "handler_group.h"
|
||||
#include "opm_db.h"
|
||||
#include <QCryptographicHash>
|
||||
#include <QSet>
|
||||
#include <QTimer>
|
||||
#include <LtsUtilsCore/dds_vector.h>
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
|
||||
HandlerOperator::HandlerOperator(MainHandler *mainHandler)
|
||||
: Interface::Fts::OperatorChangePasswordRequestHandler(mainHandler->fts())
|
||||
, Interface::Fts::OperatorCreateModifyRequestHandler(mainHandler->fts())
|
||||
, Interface::Fts::OperatorRemoveRequestHandler(mainHandler->fts())
|
||||
, Interface::Fts::OperatorLoginRequestHandler(mainHandler->fts())
|
||||
, Interface::Fts::OperatorLogoutRequestHandler(mainHandler->fts())
|
||||
, Interface::Fts::OperatorGetSetSettingsRequestHandler(mainHandler->fts())
|
||||
, Interface::Fts::OperatorApplyForeignAclsRequestHandler(mainHandler->fts())
|
||||
, Interface::Fts::OperatorUpdateVisiblePartiesByExerciseRequestHandler(mainHandler->fts())
|
||||
, m_aliveCheckTimer(new QTimer(this))
|
||||
, m_mainHandler(mainHandler)
|
||||
, m_logger(getLogger("HandlerOperator"))
|
||||
{
|
||||
connect(m_aliveCheckTimer, &QTimer::timeout, this, &HandlerOperator::onCheckAliveTimeout);
|
||||
m_aliveCheckTimer->setInterval(10000);
|
||||
m_aliveCheckTimer->setSingleShot(false);
|
||||
m_aliveCheckTimer->start();
|
||||
}
|
||||
|
||||
HandlerOperator::~HandlerOperator()
|
||||
{
|
||||
qDeleteAll(m_operatorObjMap);
|
||||
}
|
||||
|
||||
bool HandlerOperator::init()
|
||||
{
|
||||
QVector<Database::OpmOperatorExercise> exMappingVec;
|
||||
m_mainHandler->db()->select(exMappingVec);
|
||||
|
||||
QVector<Database::OpmOperator> dataVec;
|
||||
// read all Operators from database
|
||||
if (!m_mainHandler->db()->select(dataVec))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error reading data from database!";
|
||||
return true;
|
||||
}
|
||||
|
||||
QVector<Database::OpmOperatorExercise> partyExerciseVec;
|
||||
// read all Operators from database
|
||||
if (!m_mainHandler->db()->select(partyExerciseVec))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error reading data from database!";
|
||||
return true;
|
||||
}
|
||||
QMap<int, QVector<Database::OpmOperatorExercise> > opMap;
|
||||
for (const auto &elem : partyExerciseVec)
|
||||
{
|
||||
INFO_LOG(m_logger) << "---------- elem.operatorId:" << elem.operatorId
|
||||
<< ", elem size " << elem.visibleParties().size();
|
||||
opMap[elem.operatorId] << elem;
|
||||
}
|
||||
INFO_LOG(m_logger) << "------- opMap size" << opMap.size();
|
||||
|
||||
OperatorManagement::OperatorWorkstationAlive alive;
|
||||
alive.lastAlive(QDateTime::currentMSecsSinceEpoch());
|
||||
for (const Database::OpmOperator &op : qAsConst(dataVec))
|
||||
{
|
||||
ObjectOperator *ifs(new ObjectOperator(m_mainHandler));
|
||||
Core::FunctionReplyObject ret = ifs->createObject(op, opMap[op.id]);
|
||||
if (ret.error())
|
||||
{
|
||||
delete ifs;
|
||||
ERROR_LOG(m_logger) << ret();
|
||||
return false;
|
||||
}
|
||||
if (m_logger.isDebugEnabled())
|
||||
{
|
||||
QStringList stringList;
|
||||
const auto &acls = ifs->effectiveAcls();
|
||||
stringList.reserve(acls.size());
|
||||
for (int acl : acls)
|
||||
stringList << QString::number(acl);
|
||||
DEBUG_LOG(m_logger) << "Effective ACLs for Operator " << op.name << "(id: " << op.id << "): "
|
||||
<< stringList.join(QLatin1String(", "));
|
||||
}
|
||||
ifs->updateExercises(getExercisesForOperator(exMappingVec, op.id), true);
|
||||
m_operatorObjMap.insert(ifs->getId(), ifs);
|
||||
if (!op.workstationId.isNull())
|
||||
{
|
||||
alive.operatorId(op.id);
|
||||
alive.workstationId(op.workstationId.toInt());
|
||||
onOperatorWorkstationAliveChanged(alive, DataModification::eAdded);
|
||||
}
|
||||
}
|
||||
|
||||
auto dtc = m_mainHandler->dtc();
|
||||
connect(dtc.get(), &Interface::Dtc::operatorWorkstationAliveChanged,
|
||||
this, &HandlerOperator::onOperatorWorkstationAliveChanged);
|
||||
dtc->enableOperatorWorkstationAlive();
|
||||
|
||||
DEBUG_LOG(m_logger) << "m_exeObjMap.size() = " << m_operatorObjMap.size();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QString HandlerOperator::operatorNameById(int operatorId) const
|
||||
{
|
||||
ObjectOperator *obj = m_operatorObjMap.value(operatorId);
|
||||
if (!obj)
|
||||
return QStringLiteral("?");
|
||||
return obj->data().name;
|
||||
}
|
||||
|
||||
|
||||
std::vector<int> HandlerOperator::getExercisesForOperator(const QVector<Database::OpmOperatorExercise> &mapping, int operatorId)
|
||||
{
|
||||
std::vector<int> exercises;
|
||||
|
||||
for (const Database::OpmOperatorExercise &exMapping : mapping)
|
||||
if (exMapping.operatorId == operatorId)
|
||||
exercises.push_back(exMapping.exerciseId);
|
||||
|
||||
return exercises;
|
||||
}
|
||||
|
||||
void HandlerOperator::onOperatorChangePasswordRequest(const rti::core::SampleIdentity &cookie,
|
||||
const OperatorChangePasswordRequest &request)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "onOperatorChangePasswordRequest()";
|
||||
ObjectOperator *ifs = m_operatorObjMap.value(request.id());
|
||||
if (!ifs)
|
||||
{
|
||||
m_mainHandler->fts()->operatorChangePasswordReply(cookie,
|
||||
Core::FunctionReplyObject(0, tr_lts("dds", "No valid operator id for changing password.")));
|
||||
return;
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject ret;
|
||||
Database::OpmOperator op = ifs->data();
|
||||
|
||||
const auto &pw = request.oldPassword();
|
||||
const QByteArray ba(QByteArray::fromRawData(pw.c_str(), pw.size()));
|
||||
const QString enteredPassword(QString::fromLatin1(QCryptographicHash::hash(ba, QCryptographicHash::Md5).toHex()));
|
||||
|
||||
const auto &pwNew = request.password();
|
||||
const QByteArray baNew(QByteArray::fromRawData(pwNew.c_str(), pwNew.size()));
|
||||
const QString enteredPasswordNew(QString::fromLatin1(QCryptographicHash::hash(baNew, QCryptographicHash::Md5).toHex()));
|
||||
|
||||
if (request.forceSet() || op.password == enteredPassword)
|
||||
{
|
||||
if (enteredPassword == enteredPasswordNew)
|
||||
ret = Core::FunctionReplyObject(0, tr_lts("dds", "Password is identical to old password."));
|
||||
// else if (request.password().size() < n && $minimum1digit && minimum1extrachar && ...)
|
||||
// {
|
||||
// ret = Core::FunctionReplyObject(0, tr_lts("dds", "Password must be at least n characters"));
|
||||
// }
|
||||
else
|
||||
{
|
||||
op.password = enteredPasswordNew;
|
||||
ret = ifs->updateObject(op);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = Core::FunctionReplyObject(0, tr_lts("dds", "Old password does not match."));
|
||||
}
|
||||
|
||||
m_mainHandler->fts()->operatorChangePasswordReply(cookie, ret);
|
||||
}
|
||||
|
||||
void HandlerOperator::onOperatorCreateModifyRequest(const rti::core::SampleIdentity &cookie,
|
||||
const OperatorCreateModifyRequest &request)
|
||||
{
|
||||
Core::FunctionReplyObject ret;
|
||||
DEBUG_LOG(m_logger) << "onOperatorCreateModifyRequest()";
|
||||
if (!request.id().is_set())
|
||||
ret = operatorCreateRequest(request);
|
||||
else
|
||||
ret = operatorModifyRequest(request);
|
||||
|
||||
if (ret.error())
|
||||
WARNING_LOG(m_logger) << ret();
|
||||
m_mainHandler->fts()->operatorCreateModifyReply(cookie, ret);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject HandlerOperator::operatorCreateRequest(const OperatorCreateModifyRequest &request)
|
||||
{
|
||||
if (!request.name().is_set() ||
|
||||
!request.password().is_set())
|
||||
return Core::FunctionReplyObject(tr_lts("dds", "Can not create operator - name or password is empty."));
|
||||
|
||||
// Group anlegen
|
||||
GroupCreateRequest groupRequest;
|
||||
groupRequest.name(request.name().get());
|
||||
groupRequest.description(request.description().get());
|
||||
groupRequest.type(GroupType_def::OperatorGroup);
|
||||
|
||||
const Core::FunctionReplyObject groupRet = m_mainHandler->getHandlerGroup()->create(groupRequest);
|
||||
if (groupRet.error())
|
||||
return groupRet;
|
||||
|
||||
// Operator anlegen
|
||||
Database::OpmOperator op;
|
||||
op.name = QString::fromStdString(request.name().get());
|
||||
if (request.description().is_set())
|
||||
op.description = QString::fromStdString(request.description().get());
|
||||
|
||||
|
||||
const auto &pw = request.password().get();
|
||||
const QByteArray ba(QByteArray::fromRawData(pw.c_str(), pw.size()));
|
||||
const QString enteredPassword(QString::fromLatin1(QCryptographicHash::hash(ba, QCryptographicHash::Md5).toHex()));
|
||||
|
||||
op.password = enteredPassword;
|
||||
op.primaryGroupId = groupRet.id();
|
||||
if (request.image().is_set())
|
||||
op.image = LtsUtils::toQByteArray(request.image().get());
|
||||
const auto vpbe = request.visiblePartiesByExercise();
|
||||
for (const auto &pbe : vpbe)
|
||||
{
|
||||
if (!pbe.visibleParties().is_set() || pbe.exerciseId() != 0) //has_value not support on windows yet so we need depricated is_set
|
||||
continue;
|
||||
|
||||
op.visibleParties = LtsUtils::IntArray(pbe.visibleParties().get());
|
||||
}
|
||||
if (request.rolePresetId().is_set())
|
||||
{
|
||||
op.rolePresetId = request.rolePresetId().get();
|
||||
}
|
||||
op.projectionPriority = request.projectionPriority().is_set() ? request.projectionPriority().get() : 1;
|
||||
op.audioChannelPriority = request.audioChannelPriority().is_set() ? request.audioChannelPriority().get() : 1;
|
||||
|
||||
ObjectOperator *ifs(new ObjectOperator(m_mainHandler));
|
||||
const Core::FunctionReplyObject ret = ifs->createObject(op, {});
|
||||
if (ret.error())
|
||||
{
|
||||
Core::RemoveElementRequest groupRemoveRequest(groupRet.id());
|
||||
m_mainHandler->getHandlerGroup()->remove(groupRemoveRequest);
|
||||
delete ifs;
|
||||
return ret;
|
||||
}
|
||||
if (request.visibleExercises().is_set())
|
||||
ifs->updateExercises(request.visibleExercises().get());
|
||||
|
||||
if (request.operatorRights().is_set())
|
||||
{
|
||||
GroupChangeMembersRequest grChReq;
|
||||
grChReq.id(op.primaryGroupId);
|
||||
grChReq.memberships(request.operatorRights().get());
|
||||
// We don't actually care, if this fails...
|
||||
m_mainHandler->getHandlerGroup()->changeMembership(grChReq);
|
||||
ifs->reloadAcls(true);
|
||||
}
|
||||
m_operatorObjMap.insert(ifs->getId(), ifs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void HandlerOperator::operatorModifyRolePresetId( int operatorId, int rolePresetId)
|
||||
{
|
||||
DEBUG_LOG(m_logger)<< "HandlerOperator::operatorModifyRolePresetId"
|
||||
<< " operatorId=" << operatorId
|
||||
<< " rolePresetId=" << rolePresetId;
|
||||
ObjectOperator *ifs = m_operatorObjMap.value(operatorId);
|
||||
if (!ifs)
|
||||
{
|
||||
ERROR_LOG(m_logger)<< "No valid operator id given: "<< operatorId;
|
||||
return;
|
||||
}
|
||||
|
||||
Database::OpmOperator op = ifs->data();
|
||||
op.rolePresetId = rolePresetId;
|
||||
|
||||
ifs->updateObject(op);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject HandlerOperator::operatorModifyRequest(const OperatorCreateModifyRequest &request)
|
||||
{
|
||||
if (request.password().is_set())
|
||||
return Core::FunctionReplyObject(tr_lts("dds", "Can not modify operator password with this function."));
|
||||
|
||||
ObjectOperator *ifs = m_operatorObjMap.value(request.id().get());
|
||||
if (!ifs)
|
||||
return Core::FunctionReplyObject(request.id().get(), tr_lts("dds", "No valid operator id given."));
|
||||
|
||||
Database::OpmOperator op = ifs->data();
|
||||
|
||||
if (request.name().is_set())
|
||||
{
|
||||
op.name = QString::fromStdString(request.name().get());
|
||||
|
||||
for (const ObjectOperator *o : qAsConst(m_operatorObjMap))
|
||||
{
|
||||
if (o == ifs)
|
||||
continue;
|
||||
if (o->name().compare(op.name, Qt::CaseInsensitive) == 0)
|
||||
return Core::FunctionReplyObject(-1, tr_lts("dds", "Name '%1' already exists")).arg(op.name);
|
||||
}
|
||||
}
|
||||
|
||||
if (request.description().is_set())
|
||||
op.description = QString::fromStdString(request.description().get());
|
||||
if (request.image().is_set())
|
||||
op.image = LtsUtils::toQByteArray(request.image().get());
|
||||
const auto vpbe = request.visiblePartiesByExercise();
|
||||
for (const auto &pbe : vpbe)
|
||||
{
|
||||
// only ex0 updated
|
||||
if (!pbe.visibleParties().is_set() || pbe.exerciseId() != 0) //has_value not support on windows yet so we need depricated is_set
|
||||
continue;
|
||||
|
||||
op.visibleParties = LtsUtils::IntArray(pbe.visibleParties().get());
|
||||
}
|
||||
|
||||
if (request.rolePresetId().is_set())
|
||||
{
|
||||
op.rolePresetId = request.rolePresetId().get();
|
||||
}
|
||||
|
||||
if (request.visibleExercises().is_set())
|
||||
ifs->updateExercises(request.visibleExercises().get());
|
||||
if (request.projectionPriority().is_set())
|
||||
op.projectionPriority = request.projectionPriority().get();
|
||||
if (request.audioChannelPriority().is_set())
|
||||
op.audioChannelPriority = request.audioChannelPriority().get();
|
||||
op.properties = QString::fromStdString(request.properties());
|
||||
|
||||
return ifs->updateObject(op);
|
||||
}
|
||||
|
||||
void HandlerOperator::onOperatorRemoveRequest(const rti::core::SampleIdentity &cookie,
|
||||
const Core::RemoveElementRequest &request)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "onOperatorRemoveRequest()" << request;
|
||||
|
||||
ObjectOperator *ifs = m_operatorObjMap.value(request.id());
|
||||
if (!ifs)
|
||||
{
|
||||
m_mainHandler->fts()->operatorRemoveReply(cookie,
|
||||
Core::FunctionReplyObject(0, tr_lts("dds", "No valid operator id for deleting.")));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ifs->data().workstationId.isNull())
|
||||
{
|
||||
m_mainHandler->fts()->operatorRemoveReply(cookie,
|
||||
Core::FunctionReplyObject(0, tr_lts("dds", "A logged in operator may not be deleted.")));
|
||||
return;
|
||||
}
|
||||
|
||||
OperatorManagement::User ddsData;
|
||||
ddsData.id(request.id());
|
||||
|
||||
if (m_mainHandler->dds()->topicLockMaster()->isLocked(ddsData, 0))
|
||||
{
|
||||
m_mainHandler->fts()->operatorRemoveReply(cookie,
|
||||
Core::FunctionReplyObject(request.id(), tr_lts("dds", "Operator '%1' is used by another user!")).arg(ifs->name()));
|
||||
return;
|
||||
}
|
||||
|
||||
Core::RemoveElementRequest groupRemoveRequest(ifs->data().primaryGroupId);
|
||||
Core::FunctionReplyObject ret = m_mainHandler->getHandlerGroup()->remove(groupRemoveRequest);
|
||||
if (ret.error())
|
||||
{
|
||||
ERROR_LOG(m_logger) << ret();
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = ifs->removeObject();
|
||||
// Aus der lokalen Map löschen
|
||||
m_operatorObjMap.remove(ifs->getId());
|
||||
// und aus TopicLock entfernen
|
||||
m_mainHandler->getHandlerLockedTopics()->operatorLoggedOut(ifs->getId());
|
||||
delete ifs;
|
||||
}
|
||||
m_mainHandler->fts()->operatorRemoveReply(cookie, ret);
|
||||
}
|
||||
|
||||
void HandlerOperator::onOperatorLoginRequest(const rti::core::SampleIdentity &cookie,
|
||||
const OperatorLoginRequest &request)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "OperatorLoginRequest: " << request;
|
||||
|
||||
ObjectOperator *ifs = m_operatorObjMap.value(request.id());
|
||||
if (!ifs)
|
||||
{
|
||||
m_mainHandler->fts()->operatorLoginReply(cookie,
|
||||
Core::FunctionReplyObject(0, tr_lts("dds", "No operator found by the given id.")));
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &pw = request.password();
|
||||
const QByteArray ba(QByteArray::fromRawData(pw.c_str(), pw.size()));
|
||||
const QString enteredPassword(QString::fromLatin1(QCryptographicHash::hash(ba, QCryptographicHash::Md5).toHex()));
|
||||
if (enteredPassword != ifs->data().password)
|
||||
{
|
||||
m_mainHandler->fts()->operatorLoginReply(cookie,
|
||||
Core::FunctionReplyObject(ifs->data().workstationId.toInt(), tr_lts("dds", "The password you have entered is invalid.")));
|
||||
return;
|
||||
}
|
||||
// If no WS is claimed, just return operator ID
|
||||
Core::FunctionReplyObject ret(ifs->data().id);
|
||||
|
||||
// Request claim a WS
|
||||
if (!ifs->data().workstationId.isNull() && ifs->data().workstationId.toInt() > 0)
|
||||
// operator already logged in
|
||||
{
|
||||
if (ifs->data().workstationId == request.workstationId())
|
||||
{
|
||||
// do nothing if same operator claims same workstation
|
||||
}
|
||||
else if (!request.force())
|
||||
{
|
||||
// Already claimed: Return WSid as ID
|
||||
const auto ws = m_mainHandler->dds()->dtcAsm()->asset(ifs->data().workstationId.toInt());
|
||||
ret = Core::FunctionReplyObject(ifs->data().workstationId.toInt(),
|
||||
tr_lts("dds", "Operator already logged in on workstation %1.")).arg(QString::fromStdString(ws.name()));
|
||||
}
|
||||
else
|
||||
{
|
||||
// force login, logout the other operator logged in on this WS, if there is any
|
||||
int otherOperatorId = getLoggedOperatorId(ifs->data().workstationId.toInt());
|
||||
if (otherOperatorId != 0 && otherOperatorId != ifs->data().id)
|
||||
{
|
||||
ObjectOperator *other = m_operatorObjMap.value(otherOperatorId);
|
||||
if (other)
|
||||
{
|
||||
OperatorLogoutRequest req;
|
||||
req.id(otherOperatorId);
|
||||
onOperatorLogoutRequest(cookie, req);
|
||||
}
|
||||
}
|
||||
Database::OpmOperator op = ifs->data();
|
||||
op.workstationIp = request.workstationIp();
|
||||
op.workstationId = request.workstationId();
|
||||
ret = ifs->updateObject(op);
|
||||
}
|
||||
}
|
||||
else
|
||||
// operator not logged in on any workstation
|
||||
{
|
||||
// if other operator is logged in on same WS -> logout other operator and login our operator
|
||||
int otherOperatorId = getLoggedOperatorId(request.workstationId());
|
||||
|
||||
if (otherOperatorId != 0 && otherOperatorId != ifs->data().id)
|
||||
{
|
||||
ObjectOperator *other = m_operatorObjMap.value(otherOperatorId);
|
||||
if (other)
|
||||
{
|
||||
OperatorLogoutRequest req;
|
||||
req.id(otherOperatorId);
|
||||
onOperatorLogoutRequest(cookie, req);
|
||||
WARNING_LOG(m_logger) << "Logged out operator " << otherOperatorId << " on workstation id " << request.workstationId();
|
||||
}
|
||||
}
|
||||
// Claim WS:
|
||||
Database::OpmOperator op = ifs->data();
|
||||
op.workstationIp = request.workstationIp();
|
||||
op.workstationId = request.workstationId();
|
||||
ret = ifs->updateObject(op);
|
||||
}
|
||||
|
||||
if (ret.error())
|
||||
WARNING_LOG(m_logger) << ret();
|
||||
else
|
||||
{
|
||||
m_mainHandler->getHandlerLockedTopics()->operatorLoggedIn(request.id(), request.workstationId());
|
||||
m_mainHandler->getHandlerActiveApps()->cleanupOperator(request.id());
|
||||
}
|
||||
|
||||
m_mainHandler->fts()->operatorLoginReply(cookie, ret);
|
||||
}
|
||||
|
||||
int HandlerOperator::getLoggedOperatorId(int workstationId) const
|
||||
{
|
||||
auto it = std::find_if(m_operatorObjMap.begin(), m_operatorObjMap.end(),
|
||||
[workstationId](const ObjectOperator *oper) { return oper->data().workstationId == workstationId; });
|
||||
return (it == m_operatorObjMap.end() ? 0 : it.value()->getId());
|
||||
}
|
||||
|
||||
void HandlerOperator::onOperatorLogoutRequest(const rti::core::SampleIdentity &cookie,
|
||||
const OperatorLogoutRequest &request)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "OperatorLogoutRequest: " << request;
|
||||
|
||||
ObjectOperator *ifs = m_operatorObjMap.value(request.id());
|
||||
if (!ifs)
|
||||
{
|
||||
m_mainHandler->fts()->operatorLogoutReply(cookie, Core::FunctionReplyObject(0, tr_lts("dds", "No valid operator id for logout.")));
|
||||
return;
|
||||
}
|
||||
|
||||
if (ifs->data().workstationId.isNull() || ifs->data().workstationId == 0) // && ifs->data().workstationIp == 0 ?
|
||||
{
|
||||
m_mainHandler->fts()->operatorLogoutReply(cookie, Core::FunctionReplyObject(ifs->data().id));
|
||||
return;
|
||||
}
|
||||
Database::OpmOperator op = ifs->data();
|
||||
op.workstationIp = 0;
|
||||
op.workstationId = QVariant();
|
||||
|
||||
m_mainHandler->getHandlerLockedTopics()->operatorLoggedOut(request.id()); // workstationId = 0 -> logout
|
||||
m_mainHandler->getHandlerActiveApps()->cleanupOperator(op.id);
|
||||
|
||||
m_mainHandler->fts()->operatorLogoutReply(cookie, ifs->updateObject(op));
|
||||
}
|
||||
|
||||
void HandlerOperator::onOperatorGetSetSettingsRequest(const rti::core::SampleIdentity &cookie,
|
||||
const OperatorGetSetSettingsRequest &request)
|
||||
{
|
||||
Core::FunctionReplyObject fro;
|
||||
OperatorGetSetSettingsReply reply;
|
||||
reply.id(request.id());
|
||||
|
||||
ObjectOperator *ifs = m_operatorObjMap.value(request.id());
|
||||
if (ifs)
|
||||
{
|
||||
if (request.settings().is_set())
|
||||
{
|
||||
const auto &data = request.settings().get();
|
||||
const QByteArray settings(QByteArray(reinterpret_cast<const char*>(&data[0]), data.size()));
|
||||
if (!ifs->saveSettings(settings))
|
||||
fro = Core::FunctionReplyObject(request.id(), tr_lts("dds", "Error saving settings in database.") );
|
||||
}
|
||||
else
|
||||
{
|
||||
QByteArray settings;
|
||||
if (!ifs->loadSettings(settings))
|
||||
{
|
||||
fro = Core::FunctionReplyObject(request.id(), tr_lts("dds", "Error loading settings from database.") );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!settings.isEmpty())
|
||||
{
|
||||
reply.settings().set({});
|
||||
reply.settings().get() = LtsUtils::convert<std::vector<uint8_t>>(settings);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fro = Core::FunctionReplyObject(request.id(), tr_lts("dds", "No valid operator id for retrieving settings."));
|
||||
}
|
||||
|
||||
if (fro.error())
|
||||
{
|
||||
reply.id(fro.id());
|
||||
reply.errorString(fro.str());
|
||||
reply.errorParams(fro.args());
|
||||
}
|
||||
|
||||
m_mainHandler->fts()->operatorGetSetSettingsReply(cookie, reply);
|
||||
}
|
||||
|
||||
void HandlerOperator::onOperatorApplyForeignAclsRequest(const rti::core::SampleIdentity &cookie, const OperatorApplyForeignAclsRequest &request)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "peratorApplyForeignAclsRequest: " << request;
|
||||
auto reply = operatorApplyForeignAclsRequest(request);
|
||||
if (reply.error())
|
||||
WARNING_LOG(m_logger) << reply();
|
||||
m_mainHandler->fts()->operatorApplyForeignAclsReply(cookie, reply);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject HandlerOperator::operatorApplyForeignAclsRequest(const OperatorApplyForeignAclsRequest &request)
|
||||
{
|
||||
ObjectOperator *receiver = m_operatorObjMap.value(request.id());
|
||||
if (!receiver)
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "Receiving operator not present."));
|
||||
|
||||
ObjectOperator *remoteOperator = m_operatorObjMap.value(request.remoteOperatorId());
|
||||
if (!remoteOperator)
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "Remote operator not present."));
|
||||
|
||||
return receiver->setPrimaryGroupId(remoteOperator->data().primaryGroupId);
|
||||
}
|
||||
|
||||
void HandlerOperator::onOperatorUpdateVisiblePartiesByExerciseRequest(const rti::core::SampleIdentity &cookie,
|
||||
const OperatorUpdateVisiblePartiesByExerciseRequest &request)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << request;
|
||||
// DEBUG_LOG(m_logger) << "onOperatorUpdateVisiblePartiesByExerciseRequest: " << request;
|
||||
Core::FunctionReplyObject reply = operatorUpdateVisiblePartiesByExerciseRequest(request);
|
||||
if (reply.error())
|
||||
WARNING_LOG(m_logger) << reply();
|
||||
m_mainHandler->fts()->operatorUpdateVisiblePartiesByExerciseReply(cookie, reply);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject HandlerOperator::operatorUpdateVisiblePartiesByExerciseRequest(const OperatorUpdateVisiblePartiesByExerciseRequest &request)
|
||||
{
|
||||
ObjectOperator *ifs = m_operatorObjMap.value(request.id());
|
||||
if (!ifs)
|
||||
return Core::FunctionReplyObject(request.id(), tr_lts("dds", "No valid operator id given."));
|
||||
|
||||
Database::OpmOperatorExercise opEx;
|
||||
opEx.operatorId = request.id();
|
||||
opEx.exerciseId = request.exerciseId();
|
||||
std::vector<int> hiddenParties;
|
||||
if (request.hiddenParties().is_set())
|
||||
opEx.hiddenParties = LtsUtils::IntArray(request.hiddenParties().get());
|
||||
if (request.visibleParties().is_set())
|
||||
opEx.visibleParties = LtsUtils::IntArray(request.visibleParties().get());
|
||||
|
||||
opEx.properties = QString::fromStdString(request.properties());
|
||||
|
||||
return ifs->updateOperatorExercise(opEx);
|
||||
}
|
||||
|
||||
void HandlerOperator::reloadAcls()
|
||||
{
|
||||
for (ObjectOperator *ifs : qAsConst(m_operatorObjMap))
|
||||
ifs->reloadAcls();
|
||||
}
|
||||
|
||||
void HandlerOperator::onOperatorWorkstationAliveChanged(const OperatorManagement::OperatorWorkstationAlive &data, DataModification modType)
|
||||
{
|
||||
INFO_LOG(m_logger) << "onOperatorWorkstationAliveChanged: " << data << ", " << modType;
|
||||
if (data.operatorId() < 0)
|
||||
{
|
||||
m_aliveData.remove(data.workstationId());
|
||||
return;
|
||||
}
|
||||
|
||||
auto &events = m_aliveData[data.workstationId()];
|
||||
events.push_back(data);
|
||||
// do not store more than 30 history events
|
||||
if (events.size() > 30)
|
||||
events = events.mid(10);
|
||||
}
|
||||
|
||||
void HandlerOperator::onCheckAliveTimeout()
|
||||
{
|
||||
if (m_aliveData.isEmpty())
|
||||
return;
|
||||
|
||||
const qint64 tTimeoutTime = QDateTime::currentMSecsSinceEpoch() - 90 * 1000; // 90s
|
||||
DEBUG_LOG(m_logger) << "onCheckAliveTimeout, timeoutTime: " << tTimeoutTime;
|
||||
auto it = m_aliveData.begin();
|
||||
while (it != m_aliveData.end())
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Checking alive for workstation " << it.key();
|
||||
auto &events = it.value();
|
||||
if (events.isEmpty() || events.last().lastAlive() >= tTimeoutTime)
|
||||
{
|
||||
++it;
|
||||
continue;
|
||||
}
|
||||
// no reference, will be a dangling one after m_aliveData.erase(it) !
|
||||
const OperatorWorkstationAlive owa = events.last();
|
||||
|
||||
WARNING_LOG(m_logger) << "Timeout for workstation " << owa.workstationId()
|
||||
<< " and operator " << owa.operatorId() << " - logging out";
|
||||
if (m_logger.isDebugEnabled())
|
||||
{
|
||||
for (const auto &event : events)
|
||||
DEBUG_LOG(m_logger) << "Alive history: " << event;
|
||||
}
|
||||
ObjectOperator *ifs = m_operatorObjMap.value(owa.operatorId());
|
||||
it = m_aliveData.erase(it);
|
||||
|
||||
if (!ifs)
|
||||
continue;
|
||||
Database::OpmOperator op = ifs->data();
|
||||
op.workstationIp = 0;
|
||||
op.workstationId = QVariant();
|
||||
m_mainHandler->getHandlerLockedTopics()->operatorLoggedOut(owa.operatorId()); // workstationId = 0 -> logout
|
||||
m_mainHandler->getHandlerActiveApps()->cleanupOperator(owa.operatorId());
|
||||
|
||||
ifs->updateObject(op);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // Namespace OperatorManagement
|
||||
+84
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* Handler for all Language HMI objects
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Hanna E. Rathje, SLSE, 2015-09-03
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QHash>
|
||||
#include <QObject>
|
||||
#include <QQueue>
|
||||
|
||||
#include "main_handler.h"
|
||||
#include "logger.h"
|
||||
|
||||
class QTimer;
|
||||
namespace OperatorManagement
|
||||
{
|
||||
class ObjectOperator;
|
||||
|
||||
class HandlerOperator final : public QObject
|
||||
, protected Interface::Fts::OperatorChangePasswordRequestHandler
|
||||
, protected Interface::Fts::OperatorCreateModifyRequestHandler
|
||||
, protected Interface::Fts::OperatorRemoveRequestHandler
|
||||
, protected Interface::Fts::OperatorLoginRequestHandler
|
||||
, protected Interface::Fts::OperatorLogoutRequestHandler
|
||||
, protected Interface::Fts::OperatorGetSetSettingsRequestHandler
|
||||
, protected Interface::Fts::OperatorApplyForeignAclsRequestHandler
|
||||
, protected Interface::Fts::OperatorUpdateVisiblePartiesByExerciseRequestHandler
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit HandlerOperator(MainHandler *mainHandler);
|
||||
~HandlerOperator();
|
||||
|
||||
bool init();
|
||||
|
||||
void reloadAcls();
|
||||
|
||||
void operatorModifyRolePresetId( int operatorId, int rolePresetId);
|
||||
QString operatorNameById(int operatorId) const;
|
||||
|
||||
private:
|
||||
void onOperatorChangePasswordRequest(const rti::core::SampleIdentity &cookie,
|
||||
const OperatorChangePasswordRequest &request) override;
|
||||
void onOperatorCreateModifyRequest(const rti::core::SampleIdentity &cookie,
|
||||
const OperatorCreateModifyRequest &request) override;
|
||||
Core::FunctionReplyObject operatorCreateRequest(const OperatorCreateModifyRequest &request);
|
||||
Core::FunctionReplyObject operatorModifyRequest(const OperatorCreateModifyRequest &request);
|
||||
void onOperatorRemoveRequest(const rti::core::SampleIdentity &cookie,
|
||||
const Core::RemoveElementRequest &request) override;
|
||||
void onOperatorLoginRequest(const rti::core::SampleIdentity &cookie,
|
||||
const OperatorLoginRequest &request) override;
|
||||
void onOperatorLogoutRequest(const rti::core::SampleIdentity &cookie,
|
||||
const OperatorLogoutRequest &request) override;
|
||||
void onOperatorGetSetSettingsRequest(const rti::core::SampleIdentity &cookie,
|
||||
const OperatorGetSetSettingsRequest &request) override;
|
||||
|
||||
void onOperatorApplyForeignAclsRequest(const rti::core::SampleIdentity &cookie,
|
||||
const OperatorApplyForeignAclsRequest &request) override;
|
||||
Core::FunctionReplyObject operatorApplyForeignAclsRequest(const OperatorApplyForeignAclsRequest &request);
|
||||
|
||||
void onOperatorUpdateVisiblePartiesByExerciseRequest(const rti::core::SampleIdentity &cookie,
|
||||
const OperatorUpdateVisiblePartiesByExerciseRequest &request) override;
|
||||
Core::FunctionReplyObject operatorUpdateVisiblePartiesByExerciseRequest(const OperatorUpdateVisiblePartiesByExerciseRequest &request);
|
||||
|
||||
QSet<int> getEffectiveAcls(int primaryGroupId) const;
|
||||
static std::vector<int> getExercisesForOperator(const QVector<Database::OpmOperatorExercise> &mapping, int operatorId);
|
||||
int getLoggedOperatorId(int workstationId) const;
|
||||
|
||||
// dtc
|
||||
void onOperatorWorkstationAliveChanged(const OperatorManagement::OperatorWorkstationAlive &data, DataModification modType);
|
||||
|
||||
private Q_SLOTS:
|
||||
void onCheckAliveTimeout();
|
||||
private:
|
||||
QHash<int, QVector<OperatorWorkstationAlive>> m_aliveData;
|
||||
QHash<int, ObjectOperator*> m_operatorObjMap;
|
||||
QTimer *m_aliveCheckTimer;
|
||||
MainHandler *m_mainHandler;
|
||||
NGL::INGLLogger &m_logger;
|
||||
};
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
log4j.reset=true
|
||||
log4j.rootLogger=WARN, file
|
||||
|
||||
# Service: OperatorManagement
|
||||
###########################################################
|
||||
|
||||
#log4j.logger.OPM=WARN
|
||||
#log4j.logger.OPM.main=WARN
|
||||
#log4j.logger.OPM.DbHandler=DEBUG
|
||||
#log4j.logger.OPM.HandlerActiveApps=INFO
|
||||
#log4j.logger.OPM.HandlerOperator=DEBUG
|
||||
#log4j.logger.OPM.HandlerGroup=DEBUG
|
||||
#log4j.logger.OPM.HandlerLockedTopics=DEBUG
|
||||
#log4j.logger.OPM.ObjectOperator=DEBUG
|
||||
#log4j.logger.OPM.ObjectGroup=DEBUG
|
||||
#log4j.logger.OPM.Settings=INFO
|
||||
#log4j.logger.OPM.Fts=INFO
|
||||
#log4j.logger.OPM.Test=DEBUG
|
||||
|
||||
# File
|
||||
###########################################################
|
||||
log4j.appender.file=Lts::RollingFileAppender
|
||||
log4j.appender.file.MaxFileSize=1MB
|
||||
log4j.appender.file.MaxBackupIndex=9
|
||||
log4j.appender.file.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.file.layout.ConversionPattern=%d %-5p %c |#| %m (%.50F:%L) %n
|
||||
|
||||
|
||||
# Appnd_Console
|
||||
###########################################################
|
||||
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
|
||||
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.stdout.layout.ConversionPattern= %d %p %c %c{1} - %m (%-.30F:%L) %n
|
||||
|
||||
|
||||
# Appnd_Syslog
|
||||
###########################################################
|
||||
log4j.appender.syslog=org.apache.log4j.SyslogAppender
|
||||
log4j.appender.syslog.Threshold=ERROR
|
||||
log4j.appender.syslog.SysLogHost=localhost
|
||||
log4j.appender.syslog.Facility=LOCAL7
|
||||
log4j.appender.syslog.layout=org.apache.log4j.PatternLayout
|
||||
log4j.appender.syslog.layout.ConversionPattern= %-4r %-5p %c %x - %m
|
||||
log4j.appender.syslog.LevelRangeFilter.AcceptOnMatch=true
|
||||
log4j.appender.syslog.LevelRangeFilter.LevelMin=INFO
|
||||
log4j.appender.syslog.LevelRangeFilter.LevelMax=FATAL
|
||||
|
||||
|
||||
###########################################################
|
||||
###########################################################
|
||||
###########################################################
|
||||
# 1) Available Levels in LOG4CXX Version 0.10.0:
|
||||
# TRACE,
|
||||
# DEBUG,
|
||||
# INFO,
|
||||
# WARN,
|
||||
# ERROR
|
||||
# FATAL
|
||||
#
|
||||
# d = date/time
|
||||
# p = priority (Level)
|
||||
# c = category/channel
|
||||
# m = message
|
||||
# F = file
|
||||
# L = line
|
||||
# n = platform dependent line separator character or characters.
|
||||
# ....
|
||||
#
|
||||
# Examples for console:
|
||||
# a)
|
||||
# %d %p %c #%m# (%.50F:%L)%n
|
||||
# date/time
|
||||
# priority
|
||||
# category/channel
|
||||
# #message#
|
||||
# (Maximal 50Character des Filename von rechts:Line)
|
||||
# line separator
|
||||
#
|
||||
# b)
|
||||
# %d (%.15F:%L) %-5p %c |#| %m%n
|
||||
# date/time
|
||||
# (Maximal 15Character des Filename von rechts:Line)
|
||||
# priority, Right pad with spaces if the priority name is less than 5 characters long.
|
||||
# category/channel
|
||||
# message
|
||||
# line separator
|
||||
#
|
||||
# Examples for files:
|
||||
Executable
+35
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Building Config - logging facility
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
#include <NGLLogger/NGLLoggerBootstrap.h>
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
|
||||
LOGGER_T getLogger(const char *name)
|
||||
{
|
||||
static const char ns[] = "OPM.";
|
||||
std::string loggerName;
|
||||
const size_t len = strlen(name);
|
||||
loggerName.reserve(sizeof(ns) + len);
|
||||
loggerName.append(ns, sizeof(ns) - 1);
|
||||
loggerName.append(name, len);
|
||||
|
||||
try {
|
||||
return NGL::NGLLoggerBootstrap::getNGLRootLogger().
|
||||
getNGLLogger( loggerName );
|
||||
} catch ( const std::exception &ex )
|
||||
{
|
||||
fprintf(stderr, "Error retrieving logger: %s", ex.what());
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace OperatorManagement
|
||||
Executable
+23
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* Logging for OperatorManagement
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <NGLLogger/INGLLogger.h>
|
||||
#include "opm_export.h"
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
using LOGGER_T = NGL::INGLLogger &;
|
||||
|
||||
OPM_COMMON_EXPORT LOGGER_T getLogger(const char *name);
|
||||
inline LOGGER_T getLogger(const QString &loggerName)
|
||||
{
|
||||
return getLogger(loggerName.toUtf8().constData());
|
||||
}
|
||||
} // namespace OperatorManagement
|
||||
Executable
+42
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* main for OperatorManagement
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include <nglapplication/nglcoreapplication.h>
|
||||
#include <LtsCommandLineParser/LtsCommandLineParser.h>
|
||||
|
||||
#include "main_handler.h"
|
||||
#include "logger.h"
|
||||
#include "settings.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
NGLCoreApplication app(argc, argv);
|
||||
|
||||
LtsCommandLineParser::LtsCommandLineParser options;
|
||||
if (!options.init())
|
||||
return -1;
|
||||
app.createLogger("OPM", options.exerciseId());
|
||||
|
||||
OperatorManagement::Settings::setIniFile(options.iniFile());
|
||||
|
||||
int iRet = -1;
|
||||
{
|
||||
std::unique_ptr<OperatorManagement::MainHandler> mainHandler(new OperatorManagement::MainHandler);
|
||||
|
||||
if (!mainHandler->init(options.domainId()))
|
||||
return iRet;
|
||||
|
||||
STARTUP_LOG(app.baseLogger());
|
||||
|
||||
iRet = app.exec();
|
||||
|
||||
SHUTDOWN_LOG(app.baseLogger());
|
||||
}
|
||||
|
||||
return iRet;
|
||||
}
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* MainHandler for ExerciseManagement
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include "main_handler.h"
|
||||
|
||||
#include "handler_access_control_level.h"
|
||||
#include "handler_operator.h"
|
||||
#include "handler_group.h"
|
||||
#include "handler_locked_topics.h"
|
||||
#include "handler_active_apps.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include <DDS/DDSConnector/dds_connector.h>
|
||||
#include <DDS/Core/pacemaker.h>
|
||||
#include <ngldb/db_service_handler.h>
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
|
||||
MainHandler::MainHandler()
|
||||
: m_logger(getLogger("MainHandler"))
|
||||
{}
|
||||
|
||||
MainHandler::~MainHandler()
|
||||
{
|
||||
// destruction in reverse order:
|
||||
m_handlerActiveApps = nullptr;
|
||||
m_handlerLockedTopics = nullptr;
|
||||
m_handlerWebSocket = nullptr;
|
||||
m_handlerOperator = nullptr;
|
||||
m_handlerGroup = nullptr;
|
||||
m_handlerAcl = nullptr;
|
||||
|
||||
// Finally 'serving' objects:
|
||||
m_ddsHandler = nullptr;
|
||||
m_dbHandler = nullptr;
|
||||
}
|
||||
|
||||
|
||||
bool MainHandler::init(int domainId)
|
||||
{
|
||||
// initialize database
|
||||
m_dbHandler = std::make_shared<DbHandler>();
|
||||
|
||||
if (!m_dbHandler->init(0, Settings::settings()))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Initialisation dbHandler failed.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// initialize DDS
|
||||
m_ddsHandler = std::make_shared<DdsHandler>(domainId);
|
||||
if (!m_ddsHandler->init())
|
||||
return false;
|
||||
|
||||
// read project specific data from database
|
||||
// publish project specific data
|
||||
// initialize the specific handler
|
||||
if (!initAclHandler())
|
||||
return false;
|
||||
|
||||
{
|
||||
DDSConnector::CoherentSet cs(m_ddsHandler->ddsConnector());
|
||||
if (!initOperatorHandler())
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!initGroupHandler())
|
||||
return false;
|
||||
|
||||
if (!initWebSocketHandler())
|
||||
return false;
|
||||
|
||||
if (!initLockedTopicsHandler())
|
||||
return false;
|
||||
|
||||
if (!initActiveApps())
|
||||
return false;
|
||||
|
||||
m_ddsHandler->pacemaker()->setNewState(Core::RunningState::Running);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MainHandler::initAclHandler()
|
||||
{
|
||||
m_handlerAcl = std::make_shared<HandlerAccessControlLevel>(this);
|
||||
|
||||
return m_handlerAcl->init();
|
||||
}
|
||||
|
||||
bool MainHandler::initOperatorHandler()
|
||||
{
|
||||
m_handlerOperator = std::make_shared<HandlerOperator>(this);
|
||||
|
||||
return m_handlerOperator->init();
|
||||
}
|
||||
|
||||
bool MainHandler::initGroupHandler()
|
||||
{
|
||||
m_handlerGroup = std::make_shared<HandlerGroup>(this);
|
||||
|
||||
return m_handlerGroup->init();
|
||||
}
|
||||
|
||||
bool MainHandler::initLockedTopicsHandler()
|
||||
{
|
||||
m_handlerLockedTopics = std::make_shared<HandlerLockedTopics>(*this);
|
||||
|
||||
return m_handlerLockedTopics->init();
|
||||
}
|
||||
|
||||
bool MainHandler::initWebSocketHandler()
|
||||
{
|
||||
// WebSocketServer
|
||||
m_handlerWebSocket = std::make_shared<WebSocketInterface::WebSocketInterfaceHandler>(this);
|
||||
DEBUG_LOG(m_logger) << "Reset WebSocketInterfaceHandler succesful.";
|
||||
if (!m_handlerWebSocket->init())
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Initialisation WebSocketInterfaceHandler failed.";
|
||||
return false;
|
||||
}
|
||||
m_ddsHandler->pacemaker()->addPort(m_handlerWebSocket->serverWebSocketPort(), Core::PortType::WebSocketServer);
|
||||
DEBUG_LOG(m_logger) << "Initialisation WebSocketInterfaceHandler succesful.";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MainHandler::initActiveApps()
|
||||
{
|
||||
m_handlerActiveApps = std::make_shared<HandlerActiveApps>(this);
|
||||
|
||||
return m_handlerActiveApps->init();
|
||||
}
|
||||
|
||||
std::shared_ptr<DatabaseInterface> MainHandler::db() const
|
||||
{
|
||||
return m_dbHandler->db();
|
||||
}
|
||||
|
||||
} // namespace OperatorManagement
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* MainHandler for AereaEffectSimulation
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "dds_handler.h"
|
||||
#include "opm_db.h"
|
||||
#include "WebSocketInterface/websocket_interface_handler.h"
|
||||
|
||||
#include "logger.h"
|
||||
|
||||
namespace NGLDB
|
||||
{
|
||||
template <typename DB> class DbServiceHandler;
|
||||
}
|
||||
namespace OperatorManagement
|
||||
{
|
||||
using DbHandler = NGLDB::DbServiceHandler<DatabaseInterface>;
|
||||
class HandlerAccessControlLevel;
|
||||
class HandlerOperator;
|
||||
class HandlerGroup;
|
||||
class HandlerLockedTopics;
|
||||
class HandlerActiveApps;
|
||||
|
||||
class MainHandler final
|
||||
{
|
||||
public:
|
||||
explicit MainHandler();
|
||||
~MainHandler();
|
||||
|
||||
bool init(int domainId);
|
||||
|
||||
std::shared_ptr<Interface::Dtc> dtc() const { return m_ddsHandler->dtc(); }
|
||||
std::shared_ptr<Interface::Dts> dts() const { return m_ddsHandler->dts(); }
|
||||
std::shared_ptr<Interface::Fts> fts() const { return m_ddsHandler->fts(); }
|
||||
std::shared_ptr<DdsHandler> dds() const { return m_ddsHandler; }
|
||||
std::shared_ptr<DatabaseInterface> db() const;
|
||||
|
||||
std::shared_ptr<HandlerGroup> getHandlerGroup() const { return m_handlerGroup; }
|
||||
std::shared_ptr<HandlerOperator> getHandlerOperator() const { return m_handlerOperator; }
|
||||
std::shared_ptr<HandlerAccessControlLevel> getHandlerAcl() const { return m_handlerAcl; }
|
||||
std::shared_ptr<HandlerLockedTopics> getHandlerLockedTopics() const { return m_handlerLockedTopics; }
|
||||
std::shared_ptr<HandlerActiveApps> getHandlerActiveApps() const { return m_handlerActiveApps; }
|
||||
|
||||
private:
|
||||
bool initAclHandler();
|
||||
bool initOperatorHandler();
|
||||
bool initGroupHandler();
|
||||
bool initLockedTopicsHandler();
|
||||
bool initWebSocketHandler();
|
||||
bool initActiveApps();
|
||||
|
||||
private:
|
||||
std::shared_ptr<HandlerAccessControlLevel> m_handlerAcl;
|
||||
std::shared_ptr<HandlerOperator> m_handlerOperator;
|
||||
std::shared_ptr<HandlerGroup> m_handlerGroup;
|
||||
std::shared_ptr<HandlerLockedTopics> m_handlerLockedTopics;
|
||||
std::shared_ptr<DdsHandler> m_ddsHandler;
|
||||
std::shared_ptr<DbHandler> m_dbHandler;
|
||||
std::shared_ptr<WebSocketInterface::WebSocketInterfaceHandler> m_handlerWebSocket;
|
||||
std::shared_ptr<HandlerActiveApps> m_handlerActiveApps;
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
};
|
||||
} // namespace ExerciseManagement
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* Handler for the HMI language
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include "object_access_control_level.h"
|
||||
|
||||
#include "main_handler.h"
|
||||
#include "logger.h"
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
|
||||
ObjectAccessControlLevel::ObjectAccessControlLevel(MainHandler *mainHandler)
|
||||
: m_mainHandler(mainHandler)
|
||||
, m_logger(getLogger("ObjectAccessControlLevel"))
|
||||
{
|
||||
}
|
||||
|
||||
ObjectAccessControlLevel::~ObjectAccessControlLevel()
|
||||
{
|
||||
m_mainHandler->dds()->dts()->removeAccessControlLevelByKey(m_data.id);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject ObjectAccessControlLevel::createObject(const Database::OpmAccessControlLevel &data)
|
||||
{
|
||||
m_data = data;
|
||||
if (m_data.id <= 0)
|
||||
return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "It is not intended to insert data this way."));
|
||||
|
||||
// Publish Data via DTS
|
||||
onPublishData();
|
||||
|
||||
return Core::FunctionReplyObject(m_data.id);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject ObjectAccessControlLevel::updateObject(const Database::OpmAccessControlLevel &)
|
||||
{
|
||||
return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "You are not allowed to change this datum."));
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject ObjectAccessControlLevel::removeObject()
|
||||
{
|
||||
return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "Data removal denied."));
|
||||
}
|
||||
|
||||
void ObjectAccessControlLevel::onPublishData()
|
||||
{
|
||||
|
||||
OperatorManagement::AccessControlLevel ddsData;
|
||||
|
||||
ddsData.id(m_data.id);
|
||||
ddsData.name(m_data.name.toStdString());
|
||||
ddsData.description(m_data.description.toStdString());
|
||||
|
||||
// Todo: Copy as above
|
||||
INFO_LOG(m_logger) << "Publish OpmAccessControlLevel-data to dds (" << m_data.id << ") ...";
|
||||
|
||||
if (!m_mainHandler->dts()->publish(ddsData))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error publishing OpmAccessControlLevel-data to dds";
|
||||
}
|
||||
}
|
||||
|
||||
} // Namespace OperatorManagement
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* Exercise object
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <DDS/Core/function_reply_object.h>
|
||||
|
||||
// Generated
|
||||
#include <OperatorManagement/opm_db.h>
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
class MainHandler;
|
||||
|
||||
class ObjectAccessControlLevel final
|
||||
{
|
||||
public:
|
||||
explicit ObjectAccessControlLevel(MainHandler *mainHandler);
|
||||
~ObjectAccessControlLevel();
|
||||
|
||||
Core::FunctionReplyObject createObject(const Database::OpmAccessControlLevel &data);
|
||||
Core::FunctionReplyObject updateObject(const Database::OpmAccessControlLevel &data);
|
||||
Core::FunctionReplyObject removeObject();
|
||||
|
||||
qint64 getId() const { return m_data.id; }
|
||||
|
||||
protected:
|
||||
void onPublishData();
|
||||
|
||||
private:
|
||||
MainHandler *m_mainHandler;
|
||||
Database::OpmAccessControlLevel m_data;
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
};
|
||||
}
|
||||
+240
@@ -0,0 +1,240 @@
|
||||
/**
|
||||
* Handler for the HMI language
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include "object_group.h"
|
||||
|
||||
#include "main_handler.h"
|
||||
#include <ngldb/dbtransaction.h>
|
||||
#include "logger.h"
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
|
||||
ObjectGroup::ObjectGroup(MainHandler *mainHandler)
|
||||
: m_mainHandler(mainHandler)
|
||||
, m_logger(getLogger("ObjectGroup"))
|
||||
{
|
||||
}
|
||||
|
||||
ObjectGroup::~ObjectGroup()
|
||||
{
|
||||
m_mainHandler->dds()->dts()->removeGroupByKey(m_data.id);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject ObjectGroup::createObject(const Database::OpmGroup &data,
|
||||
const std::vector<qint32> &isMemberOf,
|
||||
const std::vector<qint32> &aclAllow,
|
||||
const std::vector<qint32> &aclDeny)
|
||||
{
|
||||
m_data = data;
|
||||
m_isMemberOf = isMemberOf;
|
||||
m_aclAllow = aclAllow;
|
||||
m_aclDeny = aclDeny;
|
||||
|
||||
if(m_data.id <= 0)
|
||||
{
|
||||
// Todo: m_mainHandler->db()->startTransaction();
|
||||
DBTransaction transaction(m_mainHandler->db()->database());
|
||||
|
||||
if(!m_mainHandler->db()->insert(m_data))
|
||||
{
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting group into database."));
|
||||
}
|
||||
|
||||
for(qint32 isMemberOfGroupId : isMemberOf)
|
||||
{
|
||||
Database::OpmGroupGroup gg;
|
||||
gg.groupId = m_data.id;
|
||||
gg.isMemberOfGroupId = isMemberOfGroupId;
|
||||
|
||||
if (!m_mainHandler->db()->insert(gg))
|
||||
{
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting group membership into database."));
|
||||
}
|
||||
}
|
||||
for(qint32 aclId : aclAllow)
|
||||
{
|
||||
Database::OpmAclAllow allow;
|
||||
allow.groupId = m_data.id;
|
||||
allow.aclId = aclId;
|
||||
|
||||
if (!m_mainHandler->db()->insert(allow))
|
||||
{
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting ACL allowance data into database."));
|
||||
}
|
||||
}
|
||||
for(qint32 aclId : aclDeny)
|
||||
{
|
||||
Database::OpmAclDeny deny;
|
||||
deny.groupId = m_data.id;
|
||||
deny.aclId = aclId;
|
||||
|
||||
if (!m_mainHandler->db()->insert(deny))
|
||||
{
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting ACL denial data into database."));
|
||||
}
|
||||
}
|
||||
transaction.commit();
|
||||
}
|
||||
|
||||
// Publish Data via DTS
|
||||
onPublishData();
|
||||
|
||||
return Core::FunctionReplyObject(m_data.id);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject ObjectGroup::updateObject(const Database::OpmGroup &data)
|
||||
{
|
||||
if(!m_mainHandler->db()->update(data))
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "Error updating group in database."));
|
||||
m_data = data;
|
||||
|
||||
// Publish Data via DTS
|
||||
onPublishData();
|
||||
|
||||
return Core::FunctionReplyObject(m_data.id);
|
||||
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject ObjectGroup::updateMemberships(const std::vector<qint32> &isMemberOf)
|
||||
{
|
||||
DBTransaction transaction(m_mainHandler->db()->database());
|
||||
if (!m_mainHandler->db()->removeOpmGroupGroupByGroupId(m_data.id))
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "Error removing all group memberships."));
|
||||
|
||||
for(qint32 isMemberOfGroupId : isMemberOf)
|
||||
{
|
||||
Database::OpmGroupGroup gg;
|
||||
gg.groupId = m_data.id;
|
||||
gg.isMemberOfGroupId = isMemberOfGroupId;
|
||||
if (!m_mainHandler->db()->insert(gg))
|
||||
{
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting group membership into database."));
|
||||
}
|
||||
}
|
||||
transaction.commit();
|
||||
|
||||
m_isMemberOf = isMemberOf;
|
||||
// Publish Data via DTS
|
||||
onPublishData();
|
||||
|
||||
return Core::FunctionReplyObject(m_data.id);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject ObjectGroup::updateAcls(const std::vector<qint32> &aclAllow, const std::vector<qint32> &aclDeny)
|
||||
{
|
||||
DBTransaction transaction(m_mainHandler->db()->database());
|
||||
if (!m_mainHandler->db()->removeOpmAclAllowByGroupId(m_data.id))
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "Error removing all group memberships."));
|
||||
|
||||
for(qint32 aclId : aclAllow)
|
||||
{
|
||||
Database::OpmAclAllow allow;
|
||||
allow.groupId = m_data.id;
|
||||
allow.aclId = aclId;
|
||||
|
||||
if (!m_mainHandler->db()->insert(allow))
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting ACL allowance data into database."));
|
||||
}
|
||||
if (!m_mainHandler->db()->removeOpmAclDenyByGroupId(m_data.id))
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "Error removing all group memberships."));
|
||||
|
||||
for(qint32 aclId : aclDeny)
|
||||
{
|
||||
Database::OpmAclDeny deny;
|
||||
deny.groupId = m_data.id;
|
||||
deny.aclId = aclId;
|
||||
|
||||
if (!m_mainHandler->db()->insert(deny))
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting ACL denial data into database."));
|
||||
}
|
||||
transaction.commit();
|
||||
|
||||
m_aclAllow = aclAllow;
|
||||
m_aclDeny = aclDeny;
|
||||
|
||||
// Publish Data via DTS
|
||||
onPublishData();
|
||||
|
||||
return Core::FunctionReplyObject(m_data.id);
|
||||
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject ObjectGroup::removeObject()
|
||||
{
|
||||
// on Delete Cascade?
|
||||
// removeAllAclAllows();
|
||||
// removeAllAclDenys();
|
||||
|
||||
|
||||
// removeAllMemberships();
|
||||
|
||||
if (!m_mainHandler->db()->removeOpmGroup(m_data.id))
|
||||
return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "Group with id %1 can not be removed.")).arg(m_data.id);
|
||||
|
||||
if (!m_mainHandler->dts()->removeGroupByKey(m_data.id))
|
||||
return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "Group with id %1 can not be taken from DDS.")).arg(m_data.id);
|
||||
|
||||
return Core::FunctionReplyObject(m_data.id);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject ObjectGroup::removeAllMemberships()
|
||||
{
|
||||
if (!m_mainHandler->db()->removeOpmGroupGroupByGroupId(m_data.id))
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "Error removing all group memberships."));
|
||||
|
||||
// Todo: Really?
|
||||
if (!m_mainHandler->db()->removeOpmGroupGroupByIsMemberOfGroupId(m_data.id))
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "Error removing group out of other groups."));
|
||||
|
||||
m_isMemberOf.clear();
|
||||
|
||||
return Core::FunctionReplyObject(m_data.id);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject ObjectGroup::removeAllAclAllows()
|
||||
{
|
||||
if (!m_mainHandler->db()->removeOpmAclAllowByGroupId(m_data.id))
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "Error removing all ACL allowances data."));
|
||||
|
||||
m_aclAllow.clear();
|
||||
|
||||
return Core::FunctionReplyObject(m_data.id);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject ObjectGroup::removeAllAclDenys()
|
||||
{
|
||||
if (!m_mainHandler->db()->removeOpmAclDenyByGroupId(m_data.id))
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "Error removing all ACL denies data."));
|
||||
|
||||
m_aclDeny.clear();
|
||||
|
||||
return Core::FunctionReplyObject(m_data.id);
|
||||
}
|
||||
|
||||
void ObjectGroup::onPublishData()
|
||||
{
|
||||
OperatorManagement::Group ddsData;
|
||||
|
||||
ddsData.id(m_data.id);
|
||||
ddsData.name(m_data.name.toStdString());
|
||||
ddsData.description(m_data.description.toStdString());
|
||||
ddsData.aclAllow(m_aclAllow);
|
||||
ddsData.aclDeny(m_aclDeny);
|
||||
ddsData.isHidden(m_data.isHidden);
|
||||
ddsData.type(m_data.typeId);
|
||||
ddsData.isMemberOf(m_isMemberOf);
|
||||
|
||||
INFO_LOG(m_logger) << "Publish OpmGroup-data to dds (" << m_data.id << ") ...";
|
||||
|
||||
if (!m_mainHandler->dts()->publish(ddsData))
|
||||
{
|
||||
ERROR_LOG(m_logger) << "Error publishing OpmGroup-data to dds";
|
||||
}
|
||||
}
|
||||
|
||||
} // Namespace OperatorManagement
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Exercise object
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <DDS/Core/function_reply_object.h>
|
||||
|
||||
// Generated
|
||||
#include <OperatorManagement/opm_db.h>
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
class MainHandler;
|
||||
|
||||
class ObjectGroup final
|
||||
{
|
||||
public:
|
||||
explicit ObjectGroup(MainHandler *mainHandler);
|
||||
~ObjectGroup();
|
||||
|
||||
Core::FunctionReplyObject createObject(const Database::OpmGroup &data,
|
||||
const std::vector<qint32> &isMemberOf,
|
||||
const std::vector<qint32> &aclAllow = std::vector<qint32>(),
|
||||
const std::vector<qint32> &aclDeny = std::vector<qint32>());
|
||||
Core::FunctionReplyObject updateObject(const Database::OpmGroup &data);
|
||||
|
||||
Core::FunctionReplyObject updateMemberships(const std::vector<qint32> &isMemberOf);
|
||||
|
||||
Core::FunctionReplyObject updateAcls(const std::vector<qint32> &aclAllow,
|
||||
const std::vector<qint32> &aclDeny);
|
||||
Core::FunctionReplyObject removeObject();
|
||||
Core::FunctionReplyObject removeAllMemberships();
|
||||
Core::FunctionReplyObject removeAllAclAllows();
|
||||
Core::FunctionReplyObject removeAllAclDenys();
|
||||
|
||||
qint64 getId() const { return m_data.id; }
|
||||
Database::OpmGroup data() const { return m_data; }
|
||||
QString name() const { return m_data.name; }
|
||||
|
||||
protected:
|
||||
void onPublishData();
|
||||
|
||||
private:
|
||||
MainHandler *m_mainHandler;
|
||||
Database::OpmGroup m_data;
|
||||
std::vector<qint32> m_isMemberOf;
|
||||
std::vector<qint32> m_aclAllow;
|
||||
std::vector<qint32> m_aclDeny;
|
||||
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
};
|
||||
}
|
||||
+375
@@ -0,0 +1,375 @@
|
||||
/**
|
||||
* Handler for the HMI language
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include "object_operator.h"
|
||||
|
||||
#include "main_handler.h"
|
||||
#include <LtsUtilsCore/dds_vector.h>
|
||||
#include <ngldb/dbtransaction.h>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
|
||||
ObjectOperator::ObjectOperator(MainHandler *mainHandler)
|
||||
: m_mainHandler(mainHandler)
|
||||
, m_originalPrimaryGroupId(0)
|
||||
, m_logger(getLogger("ObjectOperator"))
|
||||
{
|
||||
}
|
||||
|
||||
ObjectOperator::~ObjectOperator()
|
||||
{
|
||||
m_mainHandler->dds()->dts()->removeUserByKey(m_data.id);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject ObjectOperator::createObject(const Database::OpmOperator &data,
|
||||
const QVector<Database::OpmOperatorExercise> &vec)
|
||||
{
|
||||
m_data = data;
|
||||
m_dataExercise = vec;
|
||||
m_originalPrimaryGroupId = data.primaryGroupId;
|
||||
|
||||
if (m_data.id <= 0)
|
||||
{
|
||||
if (!m_mainHandler->db()->insert(m_data))
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "Error inserting operator into database."));
|
||||
}
|
||||
|
||||
return updateEffectiveAcls(calculateEffectiveAcls());
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject ObjectOperator::updateEffectiveAcls(const QSet<int> &effectiveAcls)
|
||||
{
|
||||
m_effectiveAcls = effectiveAcls;
|
||||
onPublishData();
|
||||
return Core::FunctionReplyObject(m_data.id);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject ObjectOperator::updateExercises(const std::vector<int> &exercises, bool dontUpdateDb)
|
||||
{
|
||||
if (m_exercises == exercises)
|
||||
return Core::FunctionReplyObject(m_data.id);
|
||||
|
||||
if (dontUpdateDb)
|
||||
{
|
||||
m_exercises = exercises;
|
||||
onPublishData();
|
||||
return Core::FunctionReplyObject(m_data.id);
|
||||
}
|
||||
|
||||
// Remove all an set them all new...
|
||||
if (!m_mainHandler->db()->removeOpmOperatorExerciseByOperatorId(m_data.id))
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "Could not remove exercises from operator with id %1 in database.")).arg(m_data.id);
|
||||
|
||||
m_exercises.clear();
|
||||
// insert can fail due to (deleted) exerciseId
|
||||
m_mainHandler->db()->setEmitMessageOnError(false);
|
||||
|
||||
for (int exerciseId : exercises)
|
||||
{
|
||||
Database::OpmOperatorExercise mapping;
|
||||
mapping.operatorId = m_data.id;
|
||||
mapping.exerciseId = exerciseId;
|
||||
bool add_to_map = true;
|
||||
//for (const auto &ooe : copy)
|
||||
for(int i = 0; i< m_dataExercise.size(); ++i)
|
||||
{
|
||||
if (m_dataExercise.at(i).exerciseId != exerciseId)
|
||||
continue;
|
||||
add_to_map = false;
|
||||
mapping.visibleParties = m_dataExercise.at(i).visibleParties;
|
||||
//replace internal vector
|
||||
auto data = m_dataExercise.at(i);
|
||||
data.visibleParties = mapping.visibleParties;
|
||||
m_dataExercise.replace(i,data);
|
||||
}
|
||||
if (mapping.visibleParties().empty())
|
||||
{
|
||||
DEBUG_LOG(m_logger)<< "Update Operator visible Parties for Execise: No parties found for " << exerciseId << " use default (ex0)";
|
||||
// Add default visibleParties from ex0
|
||||
mapping.visibleParties = m_data.visibleParties;
|
||||
}
|
||||
|
||||
if (!m_mainHandler->db()->insert(mapping))
|
||||
INFO_LOG(m_logger) << "Can not add operator " << mapping.operatorId << " to exercise " << exerciseId << " - exercise does no longer exist";
|
||||
else
|
||||
{
|
||||
if (std::find(m_exercises.begin(), m_exercises.end(), exerciseId) == m_exercises.end())
|
||||
m_exercises.push_back(exerciseId);
|
||||
if (add_to_map)
|
||||
m_dataExercise.push_back(mapping);
|
||||
}
|
||||
}
|
||||
m_mainHandler->db()->setEmitMessageOnError(true);
|
||||
|
||||
onPublishData();
|
||||
return Core::FunctionReplyObject(m_data.id);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject ObjectOperator::updateObject(const Database::OpmOperator &data)
|
||||
{
|
||||
m_data.name = data.name;
|
||||
DEBUG_LOG(m_logger) << "ObjectOperator::updateObject"
|
||||
<< " data.id = " << data.id
|
||||
<< " data.rolePresetId = " << data.rolePresetId;
|
||||
m_data.description = data.description;
|
||||
m_data.password = data.password;
|
||||
m_data.image = data.image;
|
||||
m_data.visibleParties = data.visibleParties;
|
||||
m_data.workstationIp = data.workstationIp;
|
||||
m_data.workstationId = data.workstationId;
|
||||
m_data.projectionPriority = data.projectionPriority;
|
||||
m_data.audioChannelPriority = data.audioChannelPriority;
|
||||
m_data.primaryGroupId = m_originalPrimaryGroupId;
|
||||
m_data.rolePresetId = data.rolePresetId;
|
||||
m_data.properties = data.properties;
|
||||
|
||||
if (!m_mainHandler->db()->update(m_data))
|
||||
{
|
||||
ERROR_LOG(m_logger)<< "Error updating Operator in database: " << m_mainHandler->db()->getLastError().text();
|
||||
return Core::FunctionReplyObject(0, tr_lts("dds", "Error updating operator in database."));
|
||||
}
|
||||
m_data.primaryGroupId = data.primaryGroupId;
|
||||
|
||||
onPublishData();
|
||||
return Core::FunctionReplyObject(m_data.id);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject ObjectOperator::updateOperatorExercise(const Database::OpmOperatorExercise &data)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << data.operatorId << " " << data.exerciseId;
|
||||
|
||||
// insert can fail due to (deleted) exerciseId
|
||||
m_mainHandler->db()->setEmitMessageOnError(false);
|
||||
for (int i=0; i < m_dataExercise.size(); ++i)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "** m_dataExercise.at(" << i << "): " << m_dataExercise.at(i).exerciseId << "==" << data.exerciseId;
|
||||
if (m_dataExercise.at(i).exerciseId != data.exerciseId)
|
||||
continue;
|
||||
Database::OpmOperatorExercise mapping = m_dataExercise.at(i);
|
||||
mapping.hiddenParties = data.hiddenParties;
|
||||
mapping.visibleParties = data.visibleParties;
|
||||
mapping.properties = data.properties;
|
||||
m_dataExercise.replace(i, mapping);
|
||||
|
||||
DEBUG_LOG(m_logger) << "** m_dataExercise.at(" << i << "): " << m_dataExercise.at(i).operatorId << ", "
|
||||
<< m_dataExercise.at(i).exerciseId << ", "
|
||||
<< m_dataExercise.at(i).visibleParties.toPgString() << ", "
|
||||
<< m_dataExercise.at(i).hiddenParties.toPgString();
|
||||
DEBUG_LOG(m_logger) << "** mapping: " << mapping.operatorId << ", "
|
||||
<< mapping.exerciseId << ", "
|
||||
<< mapping.visibleParties.toPgString() << ", "
|
||||
<< mapping.hiddenParties.toPgString();
|
||||
if (!m_mainHandler->db()->update(mapping))
|
||||
ERROR_LOG(m_logger)<< "Error updating OperatorExecise in database: " << m_mainHandler->db()->getLastError().text();
|
||||
}
|
||||
m_mainHandler->db()->setEmitMessageOnError(true);
|
||||
|
||||
onPublishData();
|
||||
return Core::FunctionReplyObject(m_data.id);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject ObjectOperator::removeObject()
|
||||
{
|
||||
if (!m_mainHandler->db()->removeOpmOperator(m_data.id))
|
||||
return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "Operator with id %1 can not be removed.")).arg(m_data.id);
|
||||
|
||||
if (!m_mainHandler->dts()->removeUserByKey(m_data.id))
|
||||
return Core::FunctionReplyObject(m_data.id, tr_lts("dds", "Operator with id %1 can not be taken from DDS.")).arg(m_data.id);
|
||||
|
||||
return Core::FunctionReplyObject(m_data.id);
|
||||
}
|
||||
|
||||
Core::FunctionReplyObject ObjectOperator::setPrimaryGroupId(int primaryGroupId)
|
||||
{
|
||||
// Todo: Sanity: Check, if primaryGroupId is type OperatorGroup.
|
||||
m_data.primaryGroupId = primaryGroupId;
|
||||
return updateEffectiveAcls(calculateEffectiveAcls());
|
||||
}
|
||||
|
||||
bool ObjectOperator::saveSettings(const QByteArray &settings)
|
||||
{
|
||||
if (!m_settings.id)
|
||||
{
|
||||
QVector<Database::OpmSettings> tmp;
|
||||
m_mainHandler->db()->selectByOperatorId(tmp, m_data.id);
|
||||
// nothing loaded -> insert new
|
||||
if (tmp.isEmpty())
|
||||
{
|
||||
m_settings.operatorId = m_data.id;
|
||||
if (!m_mainHandler->db()->insert(m_settings))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
m_settings = tmp.first();
|
||||
}
|
||||
m_settings.settings = settings;
|
||||
return m_mainHandler->db()->update(m_settings);
|
||||
}
|
||||
|
||||
bool ObjectOperator::loadSettings(QByteArray &settings)
|
||||
{
|
||||
if (!m_settings.id)
|
||||
{
|
||||
QVector<Database::OpmSettings> tmp;
|
||||
if (!m_mainHandler->db()->selectByOperatorId(tmp, m_data.id))
|
||||
return false;
|
||||
if (!tmp.isEmpty())
|
||||
m_settings = tmp.first();
|
||||
m_settings.operatorId = m_data.id;
|
||||
}
|
||||
settings = m_settings.settings;
|
||||
return true;
|
||||
}
|
||||
|
||||
void ObjectOperator::reloadAcls(bool force)
|
||||
{
|
||||
const QSet<int> calculatedAcls = calculateEffectiveAcls();
|
||||
|
||||
// QStringList stringList;
|
||||
// for (int acl : calculatedAcls)
|
||||
// stringList << QString::number(acl);
|
||||
// DEBUG_LOG(m_logger) << "Effective ACLs for Operator " << m_data.name << "(id: " << m_data.id << "): " << stringList.join(QLatin1String(", "));
|
||||
|
||||
if (force || m_effectiveAcls != calculatedAcls)
|
||||
updateEffectiveAcls(calculatedAcls);
|
||||
|
||||
}
|
||||
|
||||
static inline void addValuesToSet(const QMultiMap<int, int> &in, const int key, QSet<int> &out)
|
||||
{
|
||||
auto it = in.find(key);
|
||||
while (it != in.end() && it.key() == key)
|
||||
{
|
||||
out += it.value();
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
QSet<int> ObjectOperator::calculateEffectiveAcls() const
|
||||
{
|
||||
QMultiMap<int, int> groupMap;
|
||||
QMultiMap<int, int> allowMap;
|
||||
QMultiMap<int, int> denyMap;
|
||||
|
||||
auto cbGroup = [&groupMap] (const Database::OpmGroupGroup &group)
|
||||
{
|
||||
groupMap.insert(group.groupId, group.isMemberOfGroupId);
|
||||
};
|
||||
m_mainHandler->db()->select(cbGroup);
|
||||
|
||||
|
||||
int i = 0;
|
||||
// Initial
|
||||
QList<int> effectiveGroups(groupMap.values(m_data.primaryGroupId));
|
||||
// Now rekursive
|
||||
while (i < effectiveGroups.size())
|
||||
{
|
||||
const QList<int> values = groupMap.values(effectiveGroups.at(i++));
|
||||
for (int value : values)
|
||||
if (!effectiveGroups.contains(value))
|
||||
effectiveGroups << value;
|
||||
}
|
||||
|
||||
auto cbAllow = [&allowMap] (const Database::OpmAclAllow &all)
|
||||
{
|
||||
allowMap.insert(all.groupId, all.aclId);
|
||||
};
|
||||
m_mainHandler->db()->select(cbAllow);
|
||||
auto cbDeny = [&denyMap] (const Database::OpmAclDeny &den)
|
||||
{
|
||||
denyMap.insert(den.groupId, den.aclId);
|
||||
};
|
||||
m_mainHandler->db()->select(cbDeny);
|
||||
|
||||
QSet<int> allowances;
|
||||
QSet<int> denials;
|
||||
|
||||
for (int group : qAsConst(effectiveGroups))
|
||||
{
|
||||
addValuesToSet(allowMap, group, allowances);
|
||||
addValuesToSet(denyMap, group, denials);
|
||||
}
|
||||
|
||||
allowances -= denials;
|
||||
|
||||
return allowances;
|
||||
}
|
||||
|
||||
void ObjectOperator::onPublishData()
|
||||
{
|
||||
OperatorManagement::User op;
|
||||
|
||||
op.id(m_data.id);
|
||||
op.name(m_data.name.toStdString());
|
||||
op.description(m_data.description.toStdString());
|
||||
op.primaryGroupId(m_data.primaryGroupId);
|
||||
op.rolePresetId(m_data.rolePresetId);
|
||||
op.effectiveAcls() = LtsUtils::convert<std::vector<int32_t>>(m_effectiveAcls);
|
||||
|
||||
auto vpbe = toDdsData(m_dataExercise);
|
||||
// Append Visible Parties Template (= exId == 0)
|
||||
QJsonArray adlerAllowedArray;
|
||||
for (int currentParty : m_data.visibleParties())
|
||||
adlerAllowedArray.append(currentParty);
|
||||
QJsonObject adlerAllowedObject;
|
||||
adlerAllowedObject.insert(QStringLiteral("adlerAllowed"), adlerAllowedArray);
|
||||
QJsonDocument adlerAllowedDocument(adlerAllowedObject);
|
||||
|
||||
vpbe.push_back(OperatorManagement::PartiesByExercise(0, m_data.visibleParties(), std::vector<int>(),
|
||||
adlerAllowedDocument.toJson(QJsonDocument::Compact).toStdString()));
|
||||
op.visiblePartiesByExercise(vpbe);
|
||||
|
||||
op.exerciseIds(m_exercises);
|
||||
op.image() = LtsUtils::convert<std::vector<uint8_t>>(m_data.image);
|
||||
op.workstationIp(m_data.workstationIp);
|
||||
op.workstationId(m_data.workstationId.toInt());
|
||||
op.projectionPriority(m_data.projectionPriority);
|
||||
op.audioChannelPriority(m_data.audioChannelPriority);
|
||||
op.rolePresetId(m_data.rolePresetId);
|
||||
op.properties(m_data.properties.toStdString());
|
||||
|
||||
INFO_LOG(m_logger) << "Publish OpmOperator-data to dds (" << m_data.id
|
||||
<< " rolePresetId =" << m_data.rolePresetId
|
||||
<< ") ...";
|
||||
|
||||
if (!m_mainHandler->dts()->publish(op))
|
||||
ERROR_LOG(m_logger) << "Error publishing OpmOperator-data to dds";
|
||||
}
|
||||
|
||||
std::vector<OperatorManagement::PartiesByExercise> ObjectOperator::toDdsData(const QVector<Database::OpmOperatorExercise> &dbData)
|
||||
{
|
||||
std::vector<PartiesByExercise> ddsData;
|
||||
|
||||
for (const Database::OpmOperatorExercise &ooe : dbData)
|
||||
{
|
||||
PartiesByExercise pbe;
|
||||
pbe.exerciseId(ooe.exerciseId);
|
||||
pbe.visibleParties();
|
||||
pbe.hiddenParties();
|
||||
std::vector<int> visibleParty;
|
||||
for (const auto &elem : ooe.visibleParties())
|
||||
{
|
||||
visibleParty.push_back(elem);
|
||||
}
|
||||
pbe.visibleParties().set(visibleParty);
|
||||
std::vector<int> hiddenParty;
|
||||
for (const auto &elem : ooe.hiddenParties())
|
||||
{
|
||||
hiddenParty.push_back(elem);
|
||||
}
|
||||
pbe.hiddenParties().set(hiddenParty);
|
||||
pbe.properties(ooe.properties.toStdString());
|
||||
ddsData.push_back(pbe);
|
||||
}
|
||||
return ddsData;
|
||||
}
|
||||
|
||||
} // Namespace OperatorManagement
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
* Exercise object
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <DDS/Core/function_reply_object.h>
|
||||
#include <QSet>
|
||||
|
||||
// Generated
|
||||
#include <OperatorManagement/opm_db.h>
|
||||
#include <OperatorManagement/opm.hpp>
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
class MainHandler;
|
||||
|
||||
class ObjectOperator final
|
||||
{
|
||||
public:
|
||||
explicit ObjectOperator(MainHandler *mainHandler);
|
||||
~ObjectOperator();
|
||||
|
||||
Core::FunctionReplyObject createObject(const Database::OpmOperator &data, const QVector<Database::OpmOperatorExercise> &vec);
|
||||
Core::FunctionReplyObject updateObject(const Database::OpmOperator &data);
|
||||
Core::FunctionReplyObject updateOperatorExercise(const Database::OpmOperatorExercise &data);
|
||||
|
||||
Core::FunctionReplyObject updateEffectiveAcls(const QSet<int> &effectiveAcls);
|
||||
Core::FunctionReplyObject updateExercises(const std::vector<int> &exercises, bool dontUpdateDb = false);
|
||||
Core::FunctionReplyObject removeObject();
|
||||
Core::FunctionReplyObject setPrimaryGroupId(int primaryGroupId);
|
||||
|
||||
bool saveSettings(const QByteArray &settings);
|
||||
bool loadSettings(QByteArray &settings);
|
||||
|
||||
int getId() const { return m_data.id; }
|
||||
const Database::OpmOperator &data() const { return m_data; }
|
||||
QString name() const { return m_data.name; }
|
||||
QSet<int> effectiveAcls() const { return m_effectiveAcls; }
|
||||
void reloadAcls(bool force = false);
|
||||
protected:
|
||||
void onPublishData();
|
||||
|
||||
private:
|
||||
QSet<int> calculateEffectiveAcls() const;
|
||||
|
||||
|
||||
MainHandler *m_mainHandler;
|
||||
Database::OpmOperator m_data;
|
||||
QVector<Database::OpmOperatorExercise> m_dataExercise;
|
||||
|
||||
Database::OpmSettings m_settings;
|
||||
QSet<int> m_effectiveAcls;
|
||||
std::vector<int> m_exercises;
|
||||
int m_originalPrimaryGroupId;
|
||||
NGL::INGLLogger &m_logger;
|
||||
|
||||
//Database::OpmOperatorExercise toDbData(const PartiesByExercise &ddsData);
|
||||
std::vector<OperatorManagement::PartiesByExercise> toDdsData(const QVector<Database::OpmOperatorExercise> &dbData);
|
||||
};
|
||||
}
|
||||
+220
@@ -0,0 +1,220 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* PDM Custom functions (extends pdmm_dtc_impl.cpp/.h)
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Iuliana Ojog, SLSE, 2016-11-26
|
||||
*/
|
||||
|
||||
#include "opm_dtc_impl_custom.h"
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QVariantList>
|
||||
#include <QVector>
|
||||
#include <DDS/DTC/generic_dtc.h>
|
||||
#include <DDS/Generic/generic_data_reader.h>
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
namespace Interface
|
||||
{
|
||||
DtcImplCustom::DtcImplCustom(const std::shared_ptr<DDSConnector::DdsConnector> &ddsConnector)
|
||||
: DtcImpl(ddsConnector)
|
||||
{
|
||||
}
|
||||
|
||||
QVector<int> DtcImplCustom::getOperatorsByOperatorRight(int operatorRight)
|
||||
{
|
||||
QVector<int> ret;
|
||||
|
||||
DEBUG_LOG(m_logger) << "OperatorRight: " << operatorRight;
|
||||
for (const User &user : qAsConst(m_userCont))
|
||||
{
|
||||
for (int acl : user.effectiveAcls())
|
||||
{
|
||||
if (operatorRight != acl)
|
||||
continue;
|
||||
|
||||
DEBUG_LOG(m_logger) << "Found acl in Operator " << user.id() << ", operatorRight=" << operatorRight << ", acl=" << acl;
|
||||
ret.append(user.id());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QVector<int> DtcImplCustom::operatorForExerciseParty(int exerciseId, int partyId)
|
||||
{
|
||||
QVector<int> ret = {};
|
||||
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " exerciseId: " << exerciseId << ", partyId: " << partyId;
|
||||
|
||||
for (const User &user : qAsConst(m_userCont))
|
||||
{
|
||||
const auto visiblePartiesByExercise = user.visiblePartiesByExercise();
|
||||
for (const auto &pbe : visiblePartiesByExercise)
|
||||
{
|
||||
if (pbe.exerciseId() != exerciseId)
|
||||
continue;
|
||||
|
||||
if (!pbe.visibleParties().is_set())
|
||||
continue;
|
||||
|
||||
std::vector<int32_t> hiddenParties = {};
|
||||
if (pbe.hiddenParties().is_set())
|
||||
hiddenParties = pbe.hiddenParties().get();
|
||||
|
||||
for (const auto &id : pbe.visibleParties().get())
|
||||
{
|
||||
if (id != partyId)
|
||||
continue;
|
||||
|
||||
bool isHidden = false;
|
||||
for (const int &hiddenId : hiddenParties)
|
||||
{
|
||||
if (hiddenId != partyId)
|
||||
continue;
|
||||
isHidden = true;
|
||||
}
|
||||
|
||||
if (!isHidden)
|
||||
ret.append(user.id());
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool DtcImplCustom::sendAdlerNotification(const QString &jsonStr, const int exerciseId, const int partyId, const int notificationType)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
DEBUG_LOG(m_logger) << "sendAdlerNotification"
|
||||
<< ", jsonStr:" << jsonStr
|
||||
<< ", exercieId: " << exerciseId
|
||||
<< ", partyId: " << partyId
|
||||
<< ", notificationType" << notificationType;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(jsonStr.toUtf8());
|
||||
if (!doc.isObject())
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "sendAdlerNotification !doc.isObject()";
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!doc.object().contains(QStringLiteral("Exercises")))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "sendAdlerNotification no Exercises";
|
||||
return true;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "sendAdlerNotification";
|
||||
|
||||
const QJsonArray &exercisesArr = doc.object().value(QStringLiteral("Exercises")).toArray();
|
||||
for (const QJsonValue &exercisesVal : qAsConst(exercisesArr))
|
||||
{
|
||||
const QJsonObject exercisesObj = exercisesVal.toObject();
|
||||
|
||||
// 1. exerciseId pruefen
|
||||
if (exercisesObj.value(QStringLiteral("exerciseId")).toInt() != exerciseId)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "continue exerciseId=" << exerciseId
|
||||
<< ", properties exerciseId=" << exercisesObj.value(QStringLiteral("exerciseId")).toInt();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!exercisesObj.contains(QStringLiteral("suppressNotifications")))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "return !exercisesObj.contains suppressNotifications";
|
||||
return true;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "sendAdlerNotification Array durchlaufen";
|
||||
// 2. Array durchlaufen
|
||||
QJsonArray notifications = exercisesObj.value(QStringLiteral("suppressNotifications")).toArray();
|
||||
|
||||
for (const QJsonValue &val : qAsConst(notifications))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "sendAdlerNotification notifications";
|
||||
const QJsonObject entry = val.toObject();
|
||||
if (entry.value(QStringLiteral("partyId")).toInt() == partyId)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "sendAdlerNotification partyId=" << partyId;
|
||||
if (entry.contains(QStringLiteral("NotificationType")))
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "sendAdlerNotification contains NotificationType"
|
||||
<< ", NotificationType=" << entry.value(QStringLiteral("NotificationType")).toInt()
|
||||
<< ", notificationType" << notificationType;
|
||||
if (entry.value(QStringLiteral("NotificationType")).toInt() == notificationType)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "sendAdlerNotification contains NotificationType = AdlerNotification found = true";
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return !found;
|
||||
}
|
||||
|
||||
QVector<int> DtcImplCustom::getNotificationRecipents(const int exerciseId, const int partyId, const int operatorRight, const int notificationType)
|
||||
{
|
||||
const QVector<int> operatorsByOperatorRight = getOperatorsByOperatorRight(operatorRight);
|
||||
QVector<int> operatorIds;
|
||||
|
||||
for (const auto &userId : operatorsByOperatorRight)
|
||||
{
|
||||
bool inExercise = false;
|
||||
const auto user = m_userCont.value(userId);
|
||||
// Only include operators who are assigned to the exercise.
|
||||
for (const auto &exerciseIdUser : qAsConst(user.exerciseIds()))
|
||||
{
|
||||
if (exerciseIdUser == exerciseId)
|
||||
{
|
||||
inExercise = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!inExercise)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << "Operator name=" << user.name() << " not in Exercise id=" << exerciseId;
|
||||
continue;
|
||||
}
|
||||
DEBUG_LOG(m_logger) << "getNotificationRecipents OperatorId" << user.id() << ", Name=" << user.name() << ", properties=" << user.properties();
|
||||
if (isAdlerAllowedParty(exerciseId, partyId, user.id()) &&
|
||||
sendAdlerNotification(QString::fromStdString(user.properties()), exerciseId, partyId, notificationType))
|
||||
operatorIds.push_back(user.id());
|
||||
}
|
||||
return operatorIds;
|
||||
}
|
||||
|
||||
bool DtcImplCustom::isAdlerAllowedParty(int exerciseId, int partyId, int operatorId)
|
||||
{
|
||||
DEBUG_LOG(m_logger) << LOGFUNCTION << " exerciseId: " << exerciseId << ", partyId: "
|
||||
<< partyId << ", operatorId: " << operatorId;
|
||||
|
||||
const auto visiblePartiesByExercise = m_userCont[operatorId].visiblePartiesByExercise();
|
||||
for (const auto &pbe : visiblePartiesByExercise)
|
||||
{
|
||||
if (pbe.exerciseId() != exerciseId)
|
||||
continue;
|
||||
|
||||
const QJsonObject propsObj(QJsonDocument::fromJson(QByteArray::fromStdString(pbe.properties())).object());
|
||||
const QJsonArray parties = propsObj.value(QStringLiteral("adlerAllowed")).toArray();
|
||||
|
||||
for (const QJsonValue &val : parties)
|
||||
{
|
||||
const int id = val.toInt();
|
||||
if (id != partyId)
|
||||
continue;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace Interface
|
||||
} // namespace OperatorManagement
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* @RDE_HEADER@
|
||||
* PDM Custom functions (extends pdmm_dtc_impl.cpp/.h)
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Hanna E. Rathje, ESZS, 2025-06-30
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <OperatorManagement/opm_dtc_impl.h>
|
||||
#include <QHash>
|
||||
#include <QVector>
|
||||
|
||||
//-------------------------------------------------------------------------------------------------------------
|
||||
namespace OperatorManagement
|
||||
{
|
||||
namespace Interface
|
||||
{
|
||||
class DtcImplCustom final : public Interface::DtcImpl
|
||||
{
|
||||
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit DtcImplCustom(const std::shared_ptr<DDSConnector::DdsConnector> &ddsConnector);
|
||||
|
||||
// custom procs, body must be implemented by user
|
||||
QVector<int> getOperatorsByOperatorRight(int operatorRight) override;
|
||||
QVector<int> operatorForExerciseParty(int exerciseId, int partyId) override;
|
||||
QVector<int> getNotificationRecipents (const int exerciseId, const int partyId, const int operatorRight, const int notificationType) override;
|
||||
bool isAdlerAllowedParty(int exerciseId, int partyId, int operatorId) override;
|
||||
|
||||
private:
|
||||
bool sendAdlerNotification(const QString &jsonStr, const int exerciseId, const int partyId, const int notificationType);
|
||||
|
||||
|
||||
};
|
||||
} // Interface
|
||||
} // namespace OperatorManagement
|
||||
Executable
+52
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
* Export definitions
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Hanna E. Rathje, SLSE, 2015-08-04
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#ifndef OPM_COMMON_EXPORT
|
||||
# ifdef BUILD_STATIC_LIBRARIES
|
||||
# define OPM_COMMON_EXPORT
|
||||
# else
|
||||
# if defined(MAKE_SVCOPMCOMMON_LIB)
|
||||
# define OPM_COMMON_EXPORT Q_DECL_EXPORT
|
||||
# ifndef WIN32
|
||||
# ifdef NDDSUSERDllExport
|
||||
# undef NDDSUSERDllExport
|
||||
# endif
|
||||
# define NDDSUSERDllExport Q_DECL_EXPORT
|
||||
# endif
|
||||
# else
|
||||
# define OPM_COMMON_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef OPM_CLIENT_EXPORT
|
||||
# ifdef BUILD_STATIC_LIBRARIES
|
||||
# define OPM_CLIENT_EXPORT
|
||||
# else
|
||||
# if defined(MAKE_SVCOPMCLIENT_LIB)
|
||||
# define OPM_CLIENT_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define OPM_CLIENT_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef OPM_SERVER_EXPORT
|
||||
# ifdef BUILD_STATIC_LIBRARIES
|
||||
# define OPM_SERVER_EXPORT
|
||||
# else
|
||||
# if defined(MAKE_SVCOPMSERVER_LIB)
|
||||
# define OPM_SERVER_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define OPM_SERVER_EXPORT Q_DECL_IMPORT
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
+405
@@ -0,0 +1,405 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<service namespace="OperatorManagement" abbreviation="OPM" procNames="OperatorManagement" exerciseDependency="Global" groups="Core" prio="2">
|
||||
<rcs>
|
||||
<Id Id="$Id$"/>
|
||||
<HeadURL HeadURL="$HeadURL$"/>
|
||||
<Author Author="$Author$"/>
|
||||
</rcs>
|
||||
<operatorRights offset="25">
|
||||
<guiPlugin name="Login" offset="2">
|
||||
<operatorRightGroup name="Administrator Mode" description="Obtain administrative rights">
|
||||
<operatorRight right="Administrator" value="1" description="Administrator rights"/>
|
||||
<operatorRight right="ShutdownWorkstations" value="2" description="Shut down workstations"/>
|
||||
</operatorRightGroup>
|
||||
</guiPlugin>
|
||||
<guiPlugin name="OperatorEdit" offset="1">
|
||||
<operatorRightGroup name="Edit Operators" description="Create, Modify, Change Password, Delete on any Operator, Create, Modify, Delete Groups, Edit Group Memberships">
|
||||
<operatorRight right="OperatorsEdit" value="1" description="Create, Change Name, Change Image, Change Password, Delete on any Operator"/>
|
||||
<operatorRight right="OperatorsShow" value="2" description="Get Overview over any Operator"/>
|
||||
<operatorRight right="GroupEdit" value="4" description="Create, Remove Groups, Change their Name"/>
|
||||
<operatorRight right="GroupMembershipsEdit" value="5" description="Change Memberships of Groups."/>
|
||||
<operatorRight right="GroupShow" value="6" description="See all Groups and their Relationships."/>
|
||||
</operatorRightGroup>
|
||||
<operatorRightGroup name="Operator Self Service" description="Change own Password and Image">
|
||||
<operatorRight right="OperatorSelfEdit" value="3" description="Change own Password and Image"/>
|
||||
</operatorRightGroup>
|
||||
</guiPlugin>
|
||||
<guiPlugin name="OperatorSettings" offset="3">
|
||||
<operatorRightGroup name="Operator Settings" description="Save and Restore own Operator Settings">
|
||||
<operatorRight right="OperatorSettingsRead" value="1" description="Obtain own Operator Settings"/>
|
||||
<operatorRight right="OperatorSettingsWrite" value="2" description="Save own Operator Settings"/>
|
||||
<operatorRight right="OperatorSettingsRestore" value="3" description="Restore default Operator Settings"/>
|
||||
</operatorRightGroup>
|
||||
</guiPlugin>
|
||||
<guiPlugin name="TerminalWindow" offset="4">
|
||||
<operatorRightGroup name="Terminal Window" description="Right to open a terminal session">
|
||||
<operatorRight right="TerminalWindowOpen" value="1" description="Right to open a terminal session"/>
|
||||
</operatorRightGroup>
|
||||
</guiPlugin>
|
||||
</operatorRights>
|
||||
<tables>
|
||||
<table name="opm_access_control_level">
|
||||
<column name="id" datatype="integer" isPrimaryKey="1">
|
||||
<sequence start="1" increment="1"/>
|
||||
</column>
|
||||
<column name="name" datatype="text"/>
|
||||
<column name="description" datatype="text"/>
|
||||
<constraint name="UQ_opm_access_control_level_name" type="unique">
|
||||
<column name="name"/>
|
||||
</constraint>
|
||||
</table>
|
||||
<table name="opm_acl_allow">
|
||||
<column name="id" datatype="integer" isPrimaryKey="1">
|
||||
<sequence start="1" increment="1"/>
|
||||
</column>
|
||||
<column name="group_id" datatype="integer" isForeignKey="1"/>
|
||||
<column name="acl_id" datatype="integer" isForeignKey="1"/>
|
||||
<constraint name="IDX_opm_acl_allow_group_id" type="index">
|
||||
<column name="group_id"/>
|
||||
</constraint>
|
||||
<foreignKey name="FK_opm_acl_allow_opm_group">
|
||||
<source table="opm_acl_allow" column="group_id"/>
|
||||
<destination table="opm_group" column="id"/>
|
||||
</foreignKey>
|
||||
<foreignKey name="FK_opm_acl_allow_opm_access_control_level">
|
||||
<source table="opm_acl_allow" column="acl_id"/>
|
||||
<destination table="opm_access_control_level" column="id"/>
|
||||
</foreignKey>
|
||||
</table>
|
||||
<table name="opm_acl_deny">
|
||||
<column name="id" datatype="integer" isPrimaryKey="1">
|
||||
<sequence start="1" increment="1"/>
|
||||
</column>
|
||||
<column name="group_id" datatype="integer" isForeignKey="1"/>
|
||||
<column name="acl_id" datatype="integer" isForeignKey="1"/>
|
||||
<constraint name="IDX_opm_acl_deny_group_id" type="index">
|
||||
<column name="group_id"/>
|
||||
</constraint>
|
||||
<foreignKey name="FK_opm_acl_deny_opm_group">
|
||||
<source table="opm_acl_deny" column="group_id"/>
|
||||
<destination table="opm_group" column="id"/>
|
||||
</foreignKey>
|
||||
<foreignKey name="FK_opm_acl_deny_opm_access_control_level">
|
||||
<source table="opm_acl_deny" column="acl_id"/>
|
||||
<destination table="opm_access_control_level" column="id"/>
|
||||
</foreignKey>
|
||||
</table>
|
||||
<table name="opm_group">
|
||||
<column name="id" datatype="integer" isPrimaryKey="1">
|
||||
<sequence start="1" increment="1"/>
|
||||
</column>
|
||||
<column name="description" datatype="text"/>
|
||||
<column name="name" datatype="text"/>
|
||||
<column name="type_id" datatype="integer" isForeignKey="1"/>
|
||||
<column name="is_hidden" datatype="boolean" comment="Can be used for "xxxDataPluginRead" that is hidden to user unlike "XxxGuiPluginRead" (ie. "ExerciseManagementRead") (dtc containing Plugins vs. Gui Plugins)."/>
|
||||
<constraint name="UQ_opm_group_name" type="unique">
|
||||
<column name="name"/>
|
||||
</constraint>
|
||||
<foreignKey name="FK_opm_group_opm_group_type">
|
||||
<source table="opm_group" column="type_id"/>
|
||||
<destination table="opm_group_type" column="id"/>
|
||||
</foreignKey>
|
||||
</table>
|
||||
<table name="opm_group_group">
|
||||
<column name="id" datatype="integer" isPrimaryKey="1">
|
||||
<sequence start="1" increment="1"/>
|
||||
</column>
|
||||
<column name="group_id" datatype="integer" isForeignKey="1"/>
|
||||
<column name="is_member_of_group_id" datatype="integer" isForeignKey="1"/>
|
||||
<constraint name="IDX_opm_group_group_group_id" type="index">
|
||||
<column name="group_id"/>
|
||||
</constraint>
|
||||
<constraint name="IDX_opm_group_group_is_member_of_group_id" type="index">
|
||||
<column name="is_member_of_group_id"/>
|
||||
</constraint>
|
||||
<constraint name="UQ_opm_group_group_group_id_is_member_of_group_id" type="unique">
|
||||
<column name="group_id"/>
|
||||
<column name="is_member_of_group_id"/>
|
||||
</constraint>
|
||||
<foreignKey name="FK_opm_group_group_opm_group">
|
||||
<source table="opm_group_group" column="group_id"/>
|
||||
<destination table="opm_group" column="id"/>
|
||||
</foreignKey>
|
||||
<foreignKey name="FK_is_member_of_opm_group">
|
||||
<source table="opm_group_group" column="is_member_of_group_id"/>
|
||||
<destination table="opm_group" column="id"/>
|
||||
</foreignKey>
|
||||
</table>
|
||||
<table name="opm_group_type">
|
||||
<column name="id" datatype="integer" isPrimaryKey="1"/>
|
||||
<column name="name" datatype="text"/>
|
||||
</table>
|
||||
<table name="opm_locked_topics">
|
||||
<column name="id" datatype="bigint" isPrimaryKey="1">
|
||||
<sequence start="1" increment="1"/>
|
||||
</column>
|
||||
<column name="operator_id" datatype="integer"/>
|
||||
<column name="workstation_id" datatype="integer"/>
|
||||
<column name="exercise_id" datatype="integer" isOptional="1" isForeignKey="1"/>
|
||||
<column name="entity_id" datatype="bigint"/>
|
||||
<column name="entity_type_name" datatype="text"/>
|
||||
<column name="locked" datatype="boolean"/>
|
||||
<column name="time_stamp_lock" datatype="bigint"/>
|
||||
<column name="time_stamp_unlock" datatype="bigint"/>
|
||||
<constraint name="IDX_opm_locked_topics_locked" type="index">
|
||||
<column name="locked"/>
|
||||
</constraint>
|
||||
<foreignKey name="FK_opm_locked_topics_exercise" referential_integrity="DeleteCascade">
|
||||
<source table="opm_locked_topics" column="exercise_id"/>
|
||||
<destination service="ExerciseManagement" serviceAbbr="exm" schema="exm" table="exercise" column="id"/>
|
||||
</foreignKey>
|
||||
</table>
|
||||
<table name="opm_operator">
|
||||
<column name="id" datatype="integer" isPrimaryKey="1">
|
||||
<sequence start="1" increment="1"/>
|
||||
</column>
|
||||
<column name="name" datatype="text"/>
|
||||
<column name="password" datatype="text"/>
|
||||
<column name="primary_group_id" datatype="integer" isForeignKey="1"/>
|
||||
<column name="projection_priority" datatype="integer"/>
|
||||
<column name="audio_channel_priority" datatype="integer"/>
|
||||
<column name="description" datatype="text"/>
|
||||
<column name="image" datatype="bytea"/>
|
||||
<column name="workstation_id" datatype="integer" isOptional="1" isForeignKey="1"/>
|
||||
<column name="workstation_ip" datatype="integer" comment="full ipv4 address of workstation"/>
|
||||
<column name="visible_parties" datatype="integer[]" comment="the global visible parties for this operator"/>
|
||||
<column name="role_preset_id" datatype="integer" comment="Role Preset like Organisator, Techniker, Leitung, Uebungsleitung, Auswewertung Table opm.opm_group"/>
|
||||
<column name="properties" datatype="jsonb" comment="special properties stored as JSON"/>
|
||||
<constraint name="UQ_opm_operator_name" type="unique">
|
||||
<column name="name"/>
|
||||
</constraint>
|
||||
<constraint name="UQ_opm_operator_primary_group_id" type="unique">
|
||||
<column name="primary_group_id"/>
|
||||
</constraint>
|
||||
<foreignKey name="FK_opm_operator_asm_asset">
|
||||
<source table="opm_operator" column="workstation_id"/>
|
||||
<destination service="AssetManagement" serviceAbbr="asm" schema="asm" table="asm_asset" column="id"/>
|
||||
</foreignKey>
|
||||
<foreignKey name="FK_opm_operator_opm_group" referential_integrity="DeleteCascade">
|
||||
<source table="opm_operator" column="primary_group_id"/>
|
||||
<destination table="opm_group" column="id"/>
|
||||
</foreignKey>
|
||||
</table>
|
||||
<table name="opm_operator_exercise">
|
||||
<column name="id" datatype="integer" isPrimaryKey="1">
|
||||
<sequence start="1" increment="1"/>
|
||||
</column>
|
||||
<column name="operator_id" datatype="integer" isForeignKey="1"/>
|
||||
<column name="exercise_id" datatype="integer" isForeignKey="1"/>
|
||||
<column name="visible_parties" datatype="integer[]" comment="the visible parties for this operator"/>
|
||||
<column name="hidden_parties" datatype="integer[]" comment="the hidden parties for this operator"/>
|
||||
<column name="properties" datatype="jsonb" comment="special properties stored as JSON"/>
|
||||
<constraint name="IDX_opm_operator_operator_id" type="index">
|
||||
<column name="operator_id"/>
|
||||
</constraint>
|
||||
<foreignKey name="FK_opm_operator_exercise_opm_operator">
|
||||
<source table="opm_operator_exercise" column="operator_id"/>
|
||||
<destination table="opm_operator" column="id"/>
|
||||
</foreignKey>
|
||||
<foreignKey name="FK_opm_operator_exercise_exercise">
|
||||
<source table="opm_operator_exercise" column="exercise_id"/>
|
||||
<destination service="ExerciseManagement" serviceAbbr="exm" schema="exm" table="exercise" column="id"/>
|
||||
</foreignKey>
|
||||
</table>
|
||||
<table name="opm_settings">
|
||||
<column name="id" datatype="integer" isPrimaryKey="1">
|
||||
<sequence start="1" increment="1"/>
|
||||
</column>
|
||||
<column name="operator_id" datatype="integer" isForeignKey="1"/>
|
||||
<column name="settings" datatype="bytea"/>
|
||||
<constraint name="IDX_operator_id" type="index">
|
||||
<column name="operator_id"/>
|
||||
</constraint>
|
||||
<foreignKey name="FK_opm_settings_opm_operator">
|
||||
<source table="opm_settings" column="operator_id"/>
|
||||
<destination table="opm_operator" column="id"/>
|
||||
</foreignKey>
|
||||
</table>
|
||||
</tables>
|
||||
<views/>
|
||||
<dbServiceStructs>
|
||||
<serviceStruct name="OpmAccessControlLevel" table="opm_access_control_level"/>
|
||||
<serviceStruct name="OpmAclAllow" table="opm_acl_allow"/>
|
||||
<serviceStruct name="OpmAclDeny" table="opm_acl_deny"/>
|
||||
<serviceStruct name="OpmGroup" table="opm_group"/>
|
||||
<serviceStruct name="OpmGroupGroup" table="opm_group_group"/>
|
||||
<serviceStruct name="OpmLockedTopics" table="opm_locked_topics"/>
|
||||
<serviceStruct name="OpmOperator" table="opm_operator"/>
|
||||
<serviceStruct name="OpmOperatorExercise" table="opm_operator_exercise"/>
|
||||
<serviceStruct name="OpmSettings" table="opm_settings"/>
|
||||
<table name="opm_access_control_level"/>
|
||||
<table name="opm_acl_allow"/>
|
||||
<table name="opm_acl_deny"/>
|
||||
<table name="opm_group"/>
|
||||
<table name="opm_group_group"/>
|
||||
<table name="opm_locked_topics"/>
|
||||
<table name="opm_operator"/>
|
||||
<table name="opm_operator_exercise"/>
|
||||
<table name="opm_settings"/>
|
||||
</dbServiceStructs>
|
||||
<topicTypes>
|
||||
<topicType name="ActiveApp" isDataObject="1" routeToClient="1" routeToServer="0" routeInReplay="1">
|
||||
<column name="id" idlType="long" isKey="1"/>
|
||||
<column name="operatorId" idlType="long"/>
|
||||
<column name="screenTypeId" idlType="long"/>
|
||||
<column name="screenId" idlType="long"/>
|
||||
<column name="screenContainerId" idlType="long"/>
|
||||
<column name="exerciseId" idlType="long"/>
|
||||
<column name="appId" idlType="long"/>
|
||||
</topicType>
|
||||
<topicType name="AccessControlLevel" isDataObject="1" routeToClient="1" routeToServer="0" routeInReplay="0">
|
||||
<column name="id" idlType="long" isKey="1"/>
|
||||
<column name="name" idlType="string"/>
|
||||
<column name="description" idlType="string"/>
|
||||
</topicType>
|
||||
<topicType name="Group" isDataObject="1" routeToClient="1" routeToServer="0" routeInReplay="0" baseValueType="Core::BaseEntityTranslatable">
|
||||
<column name="description" idlType="string" isTranslatable="1"/>
|
||||
<column name="aclAllow" idlType="sequence<long>"/>
|
||||
<column name="aclDeny" idlType="sequence<long>"/>
|
||||
<column name="isHidden" idlType="boolean"/>
|
||||
<column name="isMemberOf" idlType="sequence<long>"/>
|
||||
<column name="type" idlType="GroupType"/>
|
||||
</topicType>
|
||||
<topicType name="GroupChangeMembersRequest">
|
||||
<column name="id" idlType="long"/>
|
||||
<column name="memberships" idlType="sequence<long>"/>
|
||||
<column name="rolePresetId" idlType="long" isOptional="1"/>
|
||||
<column name="operatorId" idlType="long" isOptional="1"/>
|
||||
</topicType>
|
||||
<topicType name="GroupChangeNameRequest">
|
||||
<column name="id" idlType="long"/>
|
||||
<column name="name" idlType="string"/>
|
||||
<column name="description" idlType="string"/>
|
||||
</topicType>
|
||||
<topicType name="GroupCreateRequest">
|
||||
<column name="name" idlType="string"/>
|
||||
<column name="description" idlType="string"/>
|
||||
<column name="type" idlType="GroupType"/>
|
||||
<column name="isHidden" idlType="boolean" isOptional="1"/>
|
||||
<column name="memberships" idlType="sequence<long>" isOptional="1"/>
|
||||
</topicType>
|
||||
<topicType name="OperatorApplyForeignAclsRequest">
|
||||
<column name="id" idlType="long" comment="The Operator that receives the OperatorRights"/>
|
||||
<column name="remoteOperatorId" idlType="long" comment="The Operator Id from whom the ACLs shall be obtained."/>
|
||||
</topicType>
|
||||
<topicType name="OperatorChangePasswordRequest">
|
||||
<column name="id" idlType="long"/>
|
||||
<column name="password" idlType="string" comment="password in Function Topic unencrypted! (?)"/>
|
||||
<column name="oldPassword" idlType="string"/>
|
||||
<column name="forceSet" idlType="boolean"/>
|
||||
</topicType>
|
||||
<topicType name="OperatorCreateModifyRequest">
|
||||
<column name="id" idlType="long" isOptional="1"/>
|
||||
<column name="name" idlType="string" isOptional="1"/>
|
||||
<column name="description" idlType="string" isOptional="1"/>
|
||||
<column name="password" idlType="string" isOptional="1"/>
|
||||
<column name="image" idlType="sequence<octet>" isOptional="1"/>
|
||||
<column name="visiblePartiesByExercise" idlType="sequence<PartiesByExercise>"/>
|
||||
<column name="visibleExercises" idlType="sequence<long>" isOptional="1"/>
|
||||
<column name="operatorRights" idlType="sequence<long>" isOptional="1"/>
|
||||
<column name="projectionPriority" idlType="short" isOptional="1"/>
|
||||
<column name="audioChannelPriority" idlType="short" isOptional="1"/>
|
||||
<column name="rolePresetId" idlType="long" isOptional="1"/>
|
||||
<column name="properties" idlType="string"/>
|
||||
</topicType>
|
||||
<topicType name="OperatorUpdateVisiblePartiesByExerciseRequest">
|
||||
<column name="id" idlType="long" comment="operator id"/>
|
||||
<column name="exerciseId" idlType="long"/>
|
||||
<column name="hiddenParties" idlType="sequence<long>" isOptional="1"/>
|
||||
<column name="visibleParties" idlType="sequence<long>" isOptional="1"/>
|
||||
<column name="properties" idlType="string"/>
|
||||
</topicType>
|
||||
<topicType name="OperatorGetSetSettingsReply" baseValueType="Core::FunctionReply">
|
||||
<column name="settings" idlType="sequence<octet>" isOptional="1"/>
|
||||
</topicType>
|
||||
<topicType name="OperatorGetSetSettingsRequest">
|
||||
<column name="id" idlType="long" comment="operator id"/>
|
||||
<column name="settings" idlType="sequence<octet>" isOptional="1"/>
|
||||
</topicType>
|
||||
<topicType name="OperatorLoginRequest">
|
||||
<column name="id" idlType="long" comment="instead of operator name. Since operators are with all attributes (but passwords) on DDS, ID can be obtained in advance"/>
|
||||
<column name="password" idlType="string" comment="unencrypted"/>
|
||||
<column name="workstationId" idlType="long"/>
|
||||
<column name="workstationIp" idlType="long" comment="Logon should claim a workstation, logon claiming another workstation will be denied"/>
|
||||
<column name="force" idlType="boolean" comment="true will force login in case other operator is logged in"/>
|
||||
</topicType>
|
||||
<topicType name="OperatorLogoutRequest">
|
||||
<column name="id" idlType="long" comment="Operator Id"/>
|
||||
</topicType>
|
||||
<topicType name="OperatorWorkstationAlive" isDataObject="1" routeToClient="0" routeToServer="1" routeInReplay="0">
|
||||
<column name="workstationId" idlType="long" isKey="1"/>
|
||||
<column name="operatorId" idlType="long"/>
|
||||
<column name="lastAlive" idlType="long long"/>
|
||||
</topicType>
|
||||
<topicType name="PartiesByExercise" isDataObject="0">
|
||||
<column name="exerciseId" idlType="long" isKey="1"/>
|
||||
<column name="visibleParties" idlType="sequence<long>" isOptional="1"/>
|
||||
<column name="hiddenParties" idlType="sequence<long>" isOptional="1"/>
|
||||
<column name="properties" idlType="string"/>
|
||||
</topicType>
|
||||
<topicType name="User" isDataObject="1" routeToClient="1" routeToServer="0" routeInReplay="1" baseValueType="Core::BaseEntity">
|
||||
<column name="description" idlType="string"/>
|
||||
<column name="effectiveAcls" idlType="sequence<long>"/>
|
||||
<column name="visiblePartiesByExercise" idlType="sequence<PartiesByExercise>"/>
|
||||
<column name="primaryGroupId" idlType="long"/>
|
||||
<column name="projectionPriority" idlType="short" comment="1..5"/>
|
||||
<column name="audioChannelPriority" idlType="short" comment="1..5"/>
|
||||
<column name="image" idlType="sequence<octet>" comment="-&gt; QByteArray, JPG encodiert"/>
|
||||
<column name="workstationIp" idlType="long"/>
|
||||
<column name="workstationId" idlType="long"/>
|
||||
<column name="exerciseIds" idlType="sequence<long>" comment="exercises, the Operator may log into."/>
|
||||
<column name="rolePresetId" idlType="long" isOptional="1"/>
|
||||
<column name="properties" idlType="string"/>
|
||||
</topicType>
|
||||
</topicTypes>
|
||||
<functionTopics>
|
||||
<functionTopic name="ActiveAppRemove" requestTopicType="Core::RemoveElementRequest" replyTopicType="Core::FunctionReply" requestTopicName="ActiveAppRemoveRequest" replyTopicName="ActiveAppRemoveReply" routeInReplay="0"/>
|
||||
<functionTopic name="ActiveAppUpdate" requestTopicType="ActiveApp" replyTopicType="Core::FunctionReply" requestTopicName="ActiveAppUpdateRequest" replyTopicName="ActiveAppUpdateReply" routeInReplay="0"/>
|
||||
<functionTopic name="GroupChangeMemberships" requestTopicType="GroupChangeMembersRequest" replyTopicType="Core::FunctionReply" requestTopicName="GroupChangeMembershipsRequest" replyTopicName="GroupChangeMembershipsReply" routeInReplay="0"/>
|
||||
<functionTopic name="GroupChangeName" requestTopicType="GroupChangeNameRequest" replyTopicType="Core::FunctionReply" requestTopicName="GroupChangeNameRequest" replyTopicName="GroupChangeNameReply" routeInReplay="0"/>
|
||||
<functionTopic name="GroupCreate" requestTopicType="GroupCreateRequest" replyTopicType="Core::FunctionReply" requestTopicName="GroupCreateRequest" replyTopicName="GroupCreateReply" routeInReplay="0"/>
|
||||
<functionTopic name="GroupRemove" requestTopicType="Core::RemoveElementRequest" replyTopicType="Core::FunctionReply" requestTopicName="GroupRemoveRequest" replyTopicName="GroupRemoveReply" routeInReplay="0"/>
|
||||
<functionTopic name="OperatorApplyForeignAcls" requestTopicType="OperatorApplyForeignAclsRequest" replyTopicType="Core::FunctionReply" requestTopicName="OperatorApplyForeignAclsRequest" replyTopicName="OperatorApplyForeignAclsReply" routeInReplay="0"/>
|
||||
<functionTopic name="OperatorChangePassword" requestTopicType="OperatorChangePasswordRequest" replyTopicType="Core::FunctionReply" requestTopicName="OperatorChangePasswordRequest" replyTopicName="OperatorChangePasswordReply" routeInReplay="0"/>
|
||||
<functionTopic name="OperatorCreateModify" requestTopicType="OperatorCreateModifyRequest" replyTopicType="Core::FunctionReply" requestTopicName="OperatorCreateModifyRequest" replyTopicName="OperatorCreateModifyReply" routeInReplay="0"/>
|
||||
<functionTopic name="OperatorUpdateVisiblePartiesByExercise" requestTopicType="OperatorUpdateVisiblePartiesByExerciseRequest" replyTopicType="Core::FunctionReply" requestTopicName="OperatorUpdateVisiblePartiesByExerciseRequest" replyTopicName="OperatorUpdateVisiblePartiesByExerciseReply" routeInReplay="0"/>
|
||||
<functionTopic name="OperatorGetSetSettings" requestTopicType="OperatorGetSetSettingsRequest" replyTopicType="OperatorGetSetSettingsReply" requestTopicName="OperatorGetSetSettingsRequest" replyTopicName="OperatorGetSetSettingsReply" routeInReplay="0"/>
|
||||
<functionTopic name="OperatorLogin" requestTopicType="OperatorLoginRequest" replyTopicType="Core::FunctionReply" requestTopicName="OperatorLoginRequest" replyTopicName="OperatorLoginReply" routeInReplay="0"/>
|
||||
<functionTopic name="OperatorLogout" requestTopicType="OperatorLogoutRequest" replyTopicType="Core::FunctionReply" requestTopicName="OperatorLogoutRequest" replyTopicName="OperatorLogoutReply" routeInReplay="0"/>
|
||||
<functionTopic name="OperatorRemove" requestTopicType="Core::RemoveElementRequest" replyTopicType="Core::FunctionReply" requestTopicName="OperatorRemoveRequest" replyTopicName="OperatorRemoveReply" routeInReplay="0"/>
|
||||
</functionTopics>
|
||||
<customDtcFunctions>
|
||||
<customDtcFunction>
|
||||
<function name="getOperatorsByOperatorRight" returns="QVector<int>">
|
||||
<parameter pos="1" name="operatorRight" type="int"/>
|
||||
</function>
|
||||
<function name="getNotificationRecipents" returns="QVector<int>">
|
||||
<parameter pos="1" name="exerciseId" type="const int"/>
|
||||
<parameter pos="2" name="partyId" type="const int"/>
|
||||
<parameter pos="3" name="operatorRight" type="const int"/>
|
||||
<parameter pos="4" name="notificationType" type="const int"/>
|
||||
</function>
|
||||
</customDtcFunction>
|
||||
<customDtcFunction>
|
||||
<function name="operatorForExerciseParty" returns="QVector<int>">
|
||||
<parameter pos="1" name="exerciseId" type="int"/>
|
||||
<parameter pos="2" name="partyId" type="int"/>
|
||||
</function>
|
||||
</customDtcFunction>
|
||||
<customDtcFunction>
|
||||
<function name="isAdlerAllowedParty" returns="bool">
|
||||
<parameter pos="1" name="exerciseId" type="int"/>
|
||||
<parameter pos="2" name="partyId" type="int"/>
|
||||
<parameter pos="3" name="operatorId" type="int"/>
|
||||
</function>
|
||||
</customDtcFunction>
|
||||
</customDtcFunctions>
|
||||
<enumerations>
|
||||
<enumeration name="GroupType" table="opm_group_type">
|
||||
<attribute key="AclGroup" value="1"/>
|
||||
<attribute key="OperatorGroup" value="2"/>
|
||||
<attribute key="PresetGroup" value="3"/>
|
||||
<attribute key="StandardGroup" value="4"/>
|
||||
</enumeration>
|
||||
</enumerations>
|
||||
</service>
|
||||
Executable
+54
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Settings for OperatorManagement
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#include "settings.h"
|
||||
|
||||
#include <QtCore/QSettings>
|
||||
#include <nglsettings/nglsettings_settings.h>
|
||||
#include <ngltools/ngltools_filesystem.h>
|
||||
|
||||
#include "LtsUtilsCore/lts_portrange.h"
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
class NGLSettingsClass : public NGL::Settings
|
||||
{
|
||||
public:
|
||||
NGLSettingsClass()
|
||||
: NGL::Settings(s_iniFile.isEmpty() ? NGL::findProjectConfigFile() : s_iniFile)
|
||||
{}
|
||||
static void setIniFile(const QString &fn)
|
||||
{
|
||||
s_iniFile = fn;
|
||||
}
|
||||
static QString s_iniFile;
|
||||
};
|
||||
QString NGLSettingsClass::s_iniFile;
|
||||
Q_GLOBAL_STATIC(NGLSettingsClass, s)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NGL::Settings *Settings::settings()
|
||||
{
|
||||
return s();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void Settings::setIniFile(const QString &ini)
|
||||
{
|
||||
NGLSettingsClass::setIniFile(ini);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
QPair<quint16, quint16> Settings::getWebSocketServerPortRange(int type)
|
||||
{
|
||||
return LtsUtils::fromQPoint(settings()->settings()->value(QString(QStringLiteral("OPM/webSocketServerPortRange/%1")).arg(type), QPoint()).toPoint());
|
||||
}
|
||||
|
||||
} // namespace OperatorManagement
|
||||
Executable
+27
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Settings for OperatorManagement
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <QString>
|
||||
#include <QPair>
|
||||
|
||||
namespace NGL
|
||||
{
|
||||
class Settings;
|
||||
}
|
||||
|
||||
namespace OperatorManagement
|
||||
{
|
||||
namespace Settings
|
||||
{
|
||||
//!< The real NGL::Settings - object
|
||||
NGL::Settings *settings();
|
||||
void setIniFile(const QString &ini);
|
||||
QPair<quint16, quint16> getWebSocketServerPortRange(int type);
|
||||
}
|
||||
|
||||
} // namespace OperatorManagement
|
||||
Reference in new issue
Block a user