Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

+184
View File
@@ -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)
+33
View File
@@ -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
View File
@@ -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
View File
@@ -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
+6
View File
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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:
+35
View File
@@ -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
+23
View File
@@ -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
+42
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+52
View File
@@ -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
View File
@@ -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 &quot;xxxDataPluginRead&quot; that is hidden to user unlike &quot;XxxGuiPluginRead&quot; (ie. &quot;ExerciseManagementRead&quot;) (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&lt;long&gt;"/>
<column name="aclDeny" idlType="sequence&lt;long&gt;"/>
<column name="isHidden" idlType="boolean"/>
<column name="isMemberOf" idlType="sequence&lt;long&gt;"/>
<column name="type" idlType="GroupType"/>
</topicType>
<topicType name="GroupChangeMembersRequest">
<column name="id" idlType="long"/>
<column name="memberships" idlType="sequence&lt;long&gt;"/>
<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&lt;long&gt;" 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&lt;octet&gt;" isOptional="1"/>
<column name="visiblePartiesByExercise" idlType="sequence&lt;PartiesByExercise&gt;"/>
<column name="visibleExercises" idlType="sequence&lt;long&gt;" isOptional="1"/>
<column name="operatorRights" idlType="sequence&lt;long&gt;" 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&lt;long&gt;" isOptional="1"/>
<column name="visibleParties" idlType="sequence&lt;long&gt;" isOptional="1"/>
<column name="properties" idlType="string"/>
</topicType>
<topicType name="OperatorGetSetSettingsReply" baseValueType="Core::FunctionReply">
<column name="settings" idlType="sequence&lt;octet&gt;" isOptional="1"/>
</topicType>
<topicType name="OperatorGetSetSettingsRequest">
<column name="id" idlType="long" comment="operator id"/>
<column name="settings" idlType="sequence&lt;octet&gt;" 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&lt;long&gt;" isOptional="1"/>
<column name="hiddenParties" idlType="sequence&lt;long&gt;" 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&lt;long&gt;"/>
<column name="visiblePartiesByExercise" idlType="sequence&lt;PartiesByExercise&gt;"/>
<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&lt;octet&gt;" comment="-&amp;gt; QByteArray, JPG encodiert"/>
<column name="workstationIp" idlType="long"/>
<column name="workstationId" idlType="long"/>
<column name="exerciseIds" idlType="sequence&lt;long&gt;" 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&lt;int&gt;">
<parameter pos="1" name="operatorRight" type="int"/>
</function>
<function name="getNotificationRecipents" returns="QVector&lt;int&gt;">
<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&lt;int&gt;">
<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>
+54
View File
@@ -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
+27
View File
@@ -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