Commit 795fae5c authored by Martin Straka's avatar Martin Straka

Added get service info and records management database.

parent 96eb5982
......@@ -88,10 +88,17 @@ SOURCES += \
src/accounts.cpp \
src/auxiliaries/attachment_helper.cpp \
src/auxiliaries/email_helper.cpp \
src/datovka_shared/io/records_management_db.cpp \
src/datovka_shared/io/sqlite/db.cpp \
src/datovka_shared/io/sqlite/db_single.cpp \
src/datovka_shared/io/sqlite/table.cpp \
src/datovka_shared/records_management/conversion.cpp \
src/datovka_shared/records_management/io/records_management_connection.cpp \
src/datovka_shared/records_management/json/entry_error.cpp \
src/datovka_shared/records_management/json/helper.cpp \
src/datovka_shared/records_management/json/service_info.cpp \
src/datovka_shared/settings/pin.cpp \
src/datovka_shared/settings/records_management.cpp \
src/datovka_shared/utility/strings.cpp \
src/datovka_shared/worker/pool.cpp \
src/dialogues/dialogues.cpp \
......@@ -123,6 +130,7 @@ SOURCES += \
src/qml_interaction/message_envelope.cpp \
src/qml_interaction/message_info.cpp \
src/qml_interaction/string_manipulation.cpp \
src/records_management.cpp \
src/settings.cpp \
src/setwrapper.cpp \
src/sqlite/account_db.cpp \
......@@ -153,10 +161,17 @@ HEADERS += \
src/auxiliaries/attachment_helper.h \
src/auxiliaries/email_helper.h \
src/common.h \
src/datovka_shared/io/records_management_db.h \
src/datovka_shared/io/sqlite/db.h \
src/datovka_shared/io/sqlite/db_single.h \
src/datovka_shared/io/sqlite/table.h \
src/datovka_shared/records_management/conversion.h \
src/datovka_shared/records_management/io/records_management_connection.h \
src/datovka_shared/records_management/json/entry_error.h \
src/datovka_shared/records_management/json/helper.h \
src/datovka_shared/records_management/json/service_info.h \
src/datovka_shared/settings/pin.h \
src/datovka_shared/settings/records_management.h \
src/datovka_shared/utility/strings.h \
src/datovka_shared/worker/pool.h \
src/dialogues/dialogues.h \
......@@ -188,6 +203,7 @@ HEADERS += \
src/qml_interaction/message_envelope.h \
src/qml_interaction/message_info.h \
src/qml_interaction/string_manipulation.h \
src/records_management.h \
src/settings.h \
src/setwrapper.h \
src/sqlite/account_db.h \
......
......@@ -32,8 +32,24 @@ Item {
/* These properties must be set by caller. */
property var pageView
property var statusBar
/* Remember last service url from settings */
property string lastUrlFromSettings: ""
/* Enable button if all required fields are filled */
function areReguiredFieldsFilled() {
infoButton.enabled = (urlTextField.text.toString() !== "" && tokenTextField.text.toString() !== "")
clearButton.enabled = infoButton.enabled
return infoButton.enabled
}
Component.onCompleted: {
urlTextField.text = settings.rmUrl()
lastUrlFromSettings = settings.rmUrl()
tokenTextField.text = settings.rmToken()
serviceInfo1.visible = false
serviceInfo2.visible = serviceInfo1.visible
serviceLogo.visible = serviceInfo1.visible
recordsManagement.loadStoredServiceInfo()
}
PageHeader {
......@@ -53,6 +69,12 @@ Item {
sourceSize.height: imgHeightHeader
source: "qrc:/ui/checkbox-marked-circle.svg"
accessibleName: qsTr("Accept changes")
onClicked: {
recordsManagement.updateServiceInfo(urlTextField.text, lastUrlFromSettings, "", serviceName.text, tokenName.text)
settings.setRmUrl(urlTextField.text)
settings.setRmToken(tokenTextField.text)
pageView.pop(StackView.Immediate)
}
}
}
} // PageHeader
......@@ -82,7 +104,7 @@ Item {
color: datovkaPalette.text
text: qsTr("URL")
}
TextField {
AccessibleTextField {
id: urlTextField
width: parent.width
height: inputItemHeight
......@@ -99,12 +121,15 @@ Item {
urlMenu.open()
}
}
onTextChanged: {
areReguiredFieldsFilled()
}
}
AccessibleText {
color: datovkaPalette.text
text: qsTr("Token")
}
TextField {
AccessibleTextField {
id: tokenTextField
width: parent.width
height: inputItemHeight
......@@ -121,30 +146,33 @@ Item {
tokenMenu.open()
}
}
onTextChanged: {
areReguiredFieldsFilled()
}
}
Row {
spacing: formItemVerticalSpacing * 5
anchors.horizontalCenter: parent.horizontalCenter
AccessibleButton {
id: info
id: infoButton
height: inputItemHeight
font.pointSize: defaultTextFont.font.pointSize
text: qsTr("Get service info")
onClicked: {
// TODO - connect to service
recordsManagement.callServiceInfo(urlTextField.text, tokenTextField.text)
}
}
AccessibleButton {
id: clear
id: clearButton
height: inputItemHeight
font.pointSize: defaultTextFont.font.pointSize
text: qsTr("Clear")
onClicked: {
// TODO - delete records from settings
urlTextField.clear()
tokenTextField.clear()
serviceInfo1.visible = false
serviceInfo2.visible = false
serviceInfo2.visible = serviceInfo1.visible
serviceLogo.visible = serviceInfo1.visible
}
}
} // Row
......@@ -161,7 +189,7 @@ Item {
id: serviceName
height: inputItemHeight
font.pointSize: defaultTextFont.font.pointSize
text: "Service"
text: ""
}
} // Row
Row {
......@@ -177,11 +205,30 @@ Item {
id: tokenName
height: inputItemHeight
font.pointSize: defaultTextFont.font.pointSize
text: "Token"
text: ""
}
} // Row
AccessibleImageButton {
id: serviceLogo
anchors.horizontalCenter: parent.horizontalCenter
width: imgHeightHeader * 1.4
height: imgHeightHeader * 1.4
source: "qrc:/ui/briefcase.svg"
accessibleName: qsTr("Records management logo.")
}
} // Column layout
} // Pane
ScrollIndicator.vertical: ScrollIndicator {}
} // Flickable
Connections {
target: recordsManagement
onServiceInfo: {
serviceInfo1.visible = true
serviceInfo2.visible = serviceInfo1.visible
serviceLogo.visible = serviceInfo1.visible
serviceName.text = srName
tokenName.text = srToken
//serviceLogo.source = srLogo
}
}
} // Item
/*
* Copyright (C) 2014-2018 CZ.NIC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations including
* the two.
*/
#include <QSqlDatabase>
#include <QSqlError>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QVariant>
#include "src/sqlite/db_tables.h"
#include "src/datovka_shared/io/records_management_db.h"
#include "src/log/log.h"
/*!
* @brief Delete all entries from table.
*
* @param[in,out] db SQL database.
* @param[in] tblName Name of table whose content should be erased.
* @return True on success.
*/
static
bool deleteTableContent(QSqlDatabase &db, const QString &tblName)
{
if (tblName.isEmpty()) {
return false;
}
QSqlQuery query(db);
QString queryStr = "DELETE FROM " + tblName;
if (!query.prepare(queryStr)) {
logErrorNL("Cannot prepare SQL query: %s.",
query.lastError().text().toUtf8().constData());
return false;
}
if (!query.exec()) {
logErrorNL("Cannot execute SQL query: %s.",
query.lastError().text().toUtf8().constData());
return false;
}
return true;
}
bool RecordsManagementDb::deleteAllEntries(void)
{
deleteTableContent(m_db, QStringLiteral("service_info"));
deleteTableContent(m_db, QStringLiteral("stored_files_messages"));
return true;
}
/*!
* @brief Insert a new service info record into service info table.
*
* @param[in,out] db SQL database.
* @param[in] entry Service info entry.
* @return True on success.
*/
static
bool insertServiceInfo(QSqlDatabase &db,
const RecordsManagementDb::ServiceInfoEntry &entry)
{
if (!entry.isValid()) {
Q_ASSERT(0);
return false;
}
QSqlQuery query(db);
QString queryStr = "INSERT INTO service_info "
"(url, name, token_name, logo_svg) VALUES "
"(:url, :name, :tokenName, :logoSvg)";
if (!query.prepare(queryStr)) {
logErrorNL("Cannot prepare SQL query: %s.",
query.lastError().text().toUtf8().constData());
return false;
}
query.bindValue(":url", entry.url);
query.bindValue(":name", entry.name);
query.bindValue(":tokenName", entry.tokenName);
query.bindValue(":logoSvg", entry.logoSvg.toBase64());
if (!query.exec()) {
logErrorNL("Cannot execute SQL query: %s.",
query.lastError().text().toUtf8().constData());
return false;
}
return true;
}
bool RecordsManagementDb::updateServiceInfo(const ServiceInfoEntry &entry)
{
if (!entry.isValid()) {
return false;
}
if (!beginTransaction()) {
return false;
}
if (!deleteTableContent(m_db, QStringLiteral("service_info"))) {
goto rollback;
}
if (!insertServiceInfo(m_db, entry)) {
goto rollback;
}
return commitTransaction();
rollback:
rollbackTransaction();
return false;
}
RecordsManagementDb::ServiceInfoEntry RecordsManagementDb::serviceInfo(void) const
{
QSqlQuery query(m_db);
QString queryStr = "SELECT url, name, token_name, logo_svg "
"FROM service_info";
if (!query.prepare(queryStr)) {
logErrorNL("Cannot prepare SQL query: %s.",
query.lastError().text().toUtf8().constData());
return ServiceInfoEntry();
}
if (query.exec() && query.isActive()) {
query.first();
if (query.isValid()) {
ServiceInfoEntry entry;
entry.url = query.value(0).toString();
entry.name = query.value(1).toString();
entry.tokenName = query.value(2).toString();
entry.logoSvg = QByteArray::fromBase64(
query.value(3).toByteArray());
Q_ASSERT(entry.isValid());
return entry;
} else {
return ServiceInfoEntry();
}
} else {
logErrorNL(
"Cannot execute SQL query and/or read SQL data: %s.",
query.lastError().text().toUtf8().constData());
return ServiceInfoEntry();
}
}
bool RecordsManagementDb::deleteAllStoredMsg(void)
{
return deleteTableContent(m_db,
QStringLiteral("stored_files_messages"));
}
bool RecordsManagementDb::deleteStoredMsg(qint64 dmId)
{
QSqlQuery query(m_db);
QString queryStr = "DELETE FROM stored_files_messages "
"WHERE dm_id = :dm_id";
if (!query.prepare(queryStr)) {
logErrorNL("Cannot prepare SQL query: %s.",
query.lastError().text().toUtf8().constData());
return false;
}
query.bindValue(":dm_id", dmId);
if (!query.exec()) {
logErrorNL("Cannot execute SQL query: %s.",
query.lastError().text().toUtf8().constData());
return false;
}
return true;
}
bool RecordsManagementDb::updateStoredMsg(qint64 dmId,
const QStringList &locations)
{
#define LIST_SEPARATOR QLatin1String("^")
QSqlQuery query(m_db);
QString queryStr = "INSERT OR REPLACE INTO stored_files_messages "
"(dm_id, separator, joined_locations) VALUES "
"(:dm_id, :separator, :joined_locations)";
if (!query.prepare(queryStr)) {
logErrorNL("Cannot prepare SQL query: %s.",
query.lastError().text().toUtf8().constData());
return false;
}
query.bindValue(":dm_id", dmId);
query.bindValue(":separator", LIST_SEPARATOR);
query.bindValue(":joined_locations", locations.join(LIST_SEPARATOR));
if (!query.exec()) {
logErrorNL("Cannot exec SQL query: %s.",
query.lastError().text().toUtf8().constData());
return false;
}
return true;
#undef LIST_SEPARATOR
}
QList<qint64> RecordsManagementDb::getAllDmIds(void) const
{
QSqlQuery query(m_db);
QList<qint64> dmIdList;
QString queryStr = "SELECT dm_id FROM stored_files_messages";
if (!query.prepare(queryStr)) {
logErrorNL("Cannot prepare SQL query: %s.",
query.lastError().text().toUtf8().constData());
return dmIdList;
}
if (query.exec() && query.isActive()) {
query.first();
while (query.isValid()) {
dmIdList.append(query.value(0).toLongLong());
query.next();
}
}
return dmIdList;
}
QStringList RecordsManagementDb::storedMsgLocations(qint64 dmId) const
{
QSqlQuery query(m_db);
QString queryStr = "SELECT separator, joined_locations "
"FROM stored_files_messages WHERE dm_id = :dm_id";
if (!query.prepare(queryStr)) {
logErrorNL("Cannot prepare SQL query: %s.",
query.lastError().text().toUtf8().constData());
return QStringList();
}
query.bindValue(":dm_id", dmId);
if (query.exec() && query.isActive()) {
query.first();
if (query.isValid()) {
QString separator(query.value(0).toString());
return query.value(1).toString().split(separator);
} else {
return QStringList();
}
} else {
logErrorNL(
"Cannot execute SQL query and/or read SQL data: %s.",
query.lastError().text().toUtf8().constData());
return QStringList();
}
}
QList<class SQLiteTbl *> RecordsManagementDb::listOfTables(void) const
{
QList<class SQLiteTbl *> tables;
tables.append(&srvcInfTbl);
tables.append(&strdFlsMsgsTbl);
return tables;
}
RecordsManagementDb *globRecordsManagementDbPtr = Q_NULLPTR;
/*
* Copyright (C) 2014-2018 CZ.NIC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations including
* the two.
*/
#pragma once
#include <QList>
#include <QString>
#include <QStringList>
#include "src/datovka_shared/io/sqlite/db_single.h"
#define RECORDS_MANAGEMENT_DB_FILE "records_management.db"
/*!
* @brief Encapsulates records management database.
*/
class RecordsManagementDb : public SQLiteDbSingle {
public:
class ServiceInfoEntry {
public:
/*!
* @brief Constructor.
*/
ServiceInfoEntry(void)
: url(), name(), tokenName(), logoSvg()
{
}
/*!
* @brief Return true in entry is valid.
*/
inline
bool isValid(void) const {
return !url.isEmpty();
}
QString url; /*!< Service URL. */
QString name; /*!< Service name. */
QString tokenName; /*!< Token name. */
QByteArray logoSvg; /*!< Raw SVG data. */
};
/* Use parent class constructor. */
using SQLiteDbSingle::SQLiteDbSingle;
/*!
* @brief Erases all database entries.
*
* @return True on success.
*/
bool deleteAllEntries(void);
/*!
* @brief Update service info entry.
*
* @note There can be only one service info entry.
*
* @param[in] entry Service info entry.
*/
bool updateServiceInfo(const ServiceInfoEntry &entry);
/*!
* @brief Obtain service information from database.
*
* @return Invalid service info if no valid service information found.
*/
ServiceInfoEntry serviceInfo(void) const;
/*!
* @brief Deletes all message-related data.
*
* @return True on success.
*/
bool deleteAllStoredMsg(void);
/*!
* @brief Deletes stored locations for given message.
*
* @param[in] dmId Message identifier.
* @return True on success.
*/
bool deleteStoredMsg(qint64 dmId);
/*!
* @brief Inserts or replaces stored locations for given message.
*
* @param[in] dmId Message identifier.
* @param[in] locations List of locations to be stored.
* @return True on success.
*/
bool updateStoredMsg(qint64 dmId, const QStringList &locations);
/*!
* @brief Obtains all message identifiers.
*
* @return List of message identifiers, empty list on error.
*/
QList<qint64> getAllDmIds(void) const;
/*!
* @brief Reads stored location or given message.
*
* @param[in] dmId Message identifier.
* @return List of locations, empty list on error.
*/
QStringList storedMsgLocations(qint64 dmId) const;
protected:
/*!
* @brief Returns list of tables.
*
* @return List of pointers to tables.
*/
virtual
QList<class SQLiteTbl *> listOfTables(void) const Q_DECL_OVERRIDE;
};
/*!
* @brief Global records management database.
*/
extern RecordsManagementDb *globRecordsManagementDbPtr;
/*
* Copyright (C) 2014-2018 CZ.NIC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations including
* the two.
*/
#include <QString>
#include "src/datovka_shared/records_management/conversion.h"
QList<qint64> createIdList(const QStringList &strList, bool *ok)
{
QList<qint64> idList;
bool iOk = false;
foreach (const QString &str, strList) {
qint64 id = str.toLongLong(&iOk);
idList.append(id);
if (!iOk) {
if (ok != Q_NULLPTR) {
*ok = false;
}
qCritical("Cannot convert '%s' into qint64.",
str.toUtf8().constData());
return QList<qint64>();
}
if (id < 0) {
if (ok != Q_NULLPTR) {
*ok = false;
}
qCritical("%s", "Received negative identifier.");
return QList<qint64>();
}
}
if (ok != Q_NULLPTR) {
*ok = true;
}
return idList;
}
/*
* Copyright (C) 2014-2018 CZ.NIC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* In addition, as a special exception, the copyright holders give
* permission to link the code of portions of this program with the
* OpenSSL library under certain conditions as described in each
* individual source file, and distribute linked combinations including
* the two.
*/
#pragma once
#include <QList>
#include <QStringList>
/*!
* @brief Convert list of strings into list of qint64.
*
* @param[in] strList String list.
* @param[out] ok Set to true if all entries are successfully converted.
* @return List if qint64.
*/
QList<qint64> createIdList(const QStringList &strList, bool *ok);