diff --git a/application/appRc.qrc b/application/appRc.qrc new file mode 100644 index 0000000..8954102 --- /dev/null +++ b/application/appRc.qrc @@ -0,0 +1,6 @@ + + + icons/login_32.png + icons/login_64.png + + diff --git a/application/application.pro b/application/application.pro index 2205f9a..8f70e76 100644 --- a/application/application.pro +++ b/application/application.pro @@ -22,10 +22,13 @@ win32 { SOURCES += main.cpp\ mainwindow.cpp \ + logindialog.cpp -HEADERS += mainwindow.h +HEADERS += mainwindow.h \ + logindialog.h -FORMS += mainwindow.ui +FORMS += mainwindow.ui \ + logindialog.ui unix { @@ -43,3 +46,6 @@ else:unix: LIBS += -L$$OUT_PWD/../core/ -lcore INCLUDEPATH += $$PWD/../core DEPENDPATH += $$PWD/../core + +RESOURCES += \ + appRc.qrc diff --git a/application/icons/login_32.png b/application/icons/login_32.png new file mode 100644 index 0000000..6cef08c Binary files /dev/null and b/application/icons/login_32.png differ diff --git a/application/icons/login_64.png b/application/icons/login_64.png new file mode 100644 index 0000000..1f1c17e Binary files /dev/null and b/application/icons/login_64.png differ diff --git a/application/logindialog.cpp b/application/logindialog.cpp new file mode 100644 index 0000000..b46ea77 --- /dev/null +++ b/application/logindialog.cpp @@ -0,0 +1,45 @@ +#include "logindialog.h" +#include "ui_logindialog.h" +#include "../core/core.h" +#include + +LoginDialog::LoginDialog(QWidget *parent) : + QDialog(parent), + ui(new Ui::LoginDialog) +{ + ui->setupUi(this); +} + +LoginDialog::~LoginDialog() +{ + delete ui; +} + +QString LoginDialog::login() const +{ + return ui->editLogin->text(); +} + +QString LoginDialog::password() const +{ + return ui->editPassword->text(); +} + +void LoginDialog::reset() +{ + ui->editLogin->setText(""); + ui->editPassword->setText(""); +} + +void LoginDialog::accept() +{ + PermissionService srv; + if (srv.checkLogin(ui->editLogin->text(), ui->editPassword->text())) + { + QDialog::accept(); + } + else + { + QMessageBox::critical(this, "Bad login", "Bad login or password"); + } +} diff --git a/application/logindialog.h b/application/logindialog.h new file mode 100644 index 0000000..c905835 --- /dev/null +++ b/application/logindialog.h @@ -0,0 +1,29 @@ +#ifndef LOGINDIALOG_H +#define LOGINDIALOG_H + +#include + +namespace Ui { +class LoginDialog; +} + +class LoginDialog : public QDialog +{ + Q_OBJECT + +public: + explicit LoginDialog(QWidget *parent = 0); + ~LoginDialog(); + QString login() const; + QString password() const; + void reset(); + +private: + Ui::LoginDialog *ui; + + // QDialog interface +public slots: + void accept() override; +}; + +#endif // LOGINDIALOG_H diff --git a/application/logindialog.ui b/application/logindialog.ui new file mode 100644 index 0000000..b4fd75e --- /dev/null +++ b/application/logindialog.ui @@ -0,0 +1,146 @@ + + + LoginDialog + + + + 0 + 0 + 408 + 220 + + + + Login + + + true + + + + 0 + + + 0 + + + 0 + + + + + background-color: rgb(255, 255, 255); + + + + + + + + + :/icons/login_64.png + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + Login + + + + + + + + + + Password + + + + + + + QLineEdit::Password + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + + + + buttonBox + accepted() + LoginDialog + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + LoginDialog + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/application/main.cpp b/application/main.cpp index f332ade..ac8a17e 100644 --- a/application/main.cpp +++ b/application/main.cpp @@ -1,5 +1,6 @@ #include "mainwindow.h" #include +#include #include @@ -7,6 +8,7 @@ int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; + w.move(QApplication::desktop()->screen()->rect().center() - w.rect().center()); w.show(); return a.exec(); diff --git a/application/mainwindow.cpp b/application/mainwindow.cpp index 05adcbd..2d26eb6 100644 --- a/application/mainwindow.cpp +++ b/application/mainwindow.cpp @@ -13,6 +13,22 @@ MainWindow::MainWindow(QWidget *parent) : ui(new Ui::MainWindow) { ui->setupUi(this); + m_lblUser = new QLabel(this); + ui->statusBar->addWidget(m_lblUser); + + m_loginDialog = new LoginDialog(this); + + connect(m_loginDialog, &LoginDialog::accepted, [this]{ + PermissionService service; + QSharedPointer u = service.loadUser(m_loginDialog->login()); + m_lblUser->setText(u->name()); + m_loginDialog->reset(); + Context::instance().setCurrentUser(u); + }); + + connect(m_loginDialog, &LoginDialog::rejected, [this]{ + close(); + }); Context::instance().loadPlugins(); int i = 0; @@ -27,6 +43,11 @@ MainWindow::MainWindow(QWidget *parent) : } ((QVBoxLayout*)ui->navigation->layout())->addStretch(1); + + if (Context::instance().db() != NULL) + { + ui->navigation->setEnabled(true); + } } MainWindow::~MainWindow() @@ -59,13 +80,37 @@ void MainWindow::openPlugin() void MainWindow::on_actionOpen_database_triggered() { - QFileDialog dialog(this); + /*QFileDialog dialog(this); dialog.setNameFilter(tr("Database Files (*.db)")); - dialog.setWindowTitle(tr("Open Database")); - Context::instance().openDb(dialog.getOpenFileName()); + dialog.setWindowTitle(tr("Open Database"));*/ + + QString dbFile = QFileDialog::getOpenFileName(this, "Open Database", "", "Database Files (*.db)"); + if (!dbFile.isEmpty()) + { + Context::instance().openDb(dbFile); + ui->navigation->setEnabled(true); + on_actionLogin_triggered(); + } } void MainWindow::on_tabWidget_tabCloseRequested(int index) { ui->tabWidget->removeTab(index); } + +void MainWindow::on_actionLogin_triggered() +{ + QSharedPointer u; + Context::instance().setCurrentUser(u); + m_lblUser->setText(""); + m_loginDialog->show(); +} + +void MainWindow::showEvent(QShowEvent *evt) +{ + QWidget::showEvent(evt); + if (Context::instance().db() != NULL && Context::instance().currentUser().data() == NULL) + { + m_loginDialog->show(); + } +} diff --git a/application/mainwindow.h b/application/mainwindow.h index af6786d..dd14b47 100644 --- a/application/mainwindow.h +++ b/application/mainwindow.h @@ -2,6 +2,9 @@ #define MAINWINDOW_H #include +#include + +#include "logindialog.h" #define PLUGIN_INDEX "plug_index" @@ -25,8 +28,16 @@ private slots: void on_tabWidget_tabCloseRequested(int index); + void on_actionLogin_triggered(); + private: Ui::MainWindow *ui; + LoginDialog *m_loginDialog; + QLabel *m_lblUser; + + // QWidget interface +protected: + void showEvent(QShowEvent *evt); }; #endif // MAINWINDOW_H diff --git a/application/mainwindow.ui b/application/mainwindow.ui index d408b6b..901b429 100644 --- a/application/mainwindow.ui +++ b/application/mainwindow.ui @@ -15,8 +15,17 @@ + + 0 + + + 0 + + + false + @@ -52,6 +61,8 @@ File + + @@ -63,6 +74,7 @@ false + @@ -75,8 +87,19 @@ Open database... + + + + :/icons/login_32.png:/icons/login_32.png + + + Login... + + - + + + diff --git a/core/context.cpp b/core/context.cpp index dc607a8..a28b97c 100644 --- a/core/context.cpp +++ b/core/context.cpp @@ -15,6 +15,11 @@ #include "roles/roles.h" #include "permissionservice.h" +Context::~Context() +{ + this->destroy(); +} + Context &Context::instance() { static Context ctx; @@ -91,7 +96,10 @@ void Context::destroy() m_dbOpened = false; } - delete m_settings; + if (m_settings != NULL && m_settings->parent() == NULL) + { + delete m_settings; + } foreach (IPlugin *plugin, m_plugins) { @@ -112,6 +120,16 @@ Context::Context() m_dbOpened = false; } +QSharedPointer Context::currentUser() const +{ + return m_currentUser; +} + +void Context::setCurrentUser(const QSharedPointer ¤tUser) +{ + m_currentUser = currentUser; +} + void Context::checkDb(const QString &path) { { @@ -226,4 +244,6 @@ void Context::checkPermissions() } } } + + permService.checkForAdmin(); } diff --git a/core/context.h b/core/context.h index 4ef2cfb..17b9062 100644 --- a/core/context.h +++ b/core/context.h @@ -7,10 +7,12 @@ #include #include #include +#include #include "define.h" #include "core_global.h" #include "transaction.h" +#include "data/core-data.h" #include #include @@ -20,6 +22,7 @@ class IPlugin; class CORESHARED_EXPORT Context { public: + ~Context(); static Context &instance(); QList plugins(); IPlugin *plugin(const QString &pluginId); @@ -31,6 +34,9 @@ public: void destroy(); QStringList defaultPerms(); + QSharedPointer currentUser() const; + void setCurrentUser(const QSharedPointer ¤tUser); + private: Context(); QList m_plugins; @@ -38,6 +44,7 @@ private: QSettings *m_settings; bool m_dbOpened; odb::session m_session; + QSharedPointer m_currentUser; QStringList m_solved; diff --git a/core/core.h b/core/core.h index a8f6fcd..0bfc109 100644 --- a/core/core.h +++ b/core/core.h @@ -7,5 +7,6 @@ #include "imetadataplugin.h" #include "transaction.h" #include "gridform.h" +#include "permissionservice.h" #endif // CORE_H diff --git a/core/filterui.ui b/core/filterui.ui index 5c3e4a9..c39fdcd 100644 --- a/core/filterui.ui +++ b/core/filterui.ui @@ -70,14 +70,11 @@ Apply - - 1 - Go - + :/icons/ok.svg:/icons/ok.svg @@ -119,14 +116,11 @@ Save - - 1 - Save - + :/icons/save.svg:/icons/save.svg @@ -145,14 +139,11 @@ Manage - - 1 - Manage - + :/icons/list.svg:/icons/list.svg @@ -229,6 +220,8 @@ - + + + diff --git a/core/gridform.h b/core/gridform.h index cb80568..953098f 100644 --- a/core/gridform.h +++ b/core/gridform.h @@ -30,6 +30,16 @@ public: } virtual ~GridForm() { + if (m_form != NULL && m_form->parent() == NULL) + { + delete m_form; + } + + if (m_tableModel != NULL && m_tableModel->parent() == NULL) + { + delete m_tableModel; + } + delete m_formHandler; } diff --git a/core/gridform.ui b/core/gridform.ui index adb0a8f..a201617 100644 --- a/core/gridform.ui +++ b/core/gridform.ui @@ -19,6 +19,9 @@ + + Add record + false @@ -45,6 +48,9 @@ + + Edit record + E @@ -65,6 +71,9 @@ + + Delete record + D @@ -85,6 +94,9 @@ + + Filter + F @@ -108,6 +120,9 @@ + + Print + P diff --git a/core/igridform.cpp b/core/igridform.cpp index 560a794..986b03c 100644 --- a/core/igridform.cpp +++ b/core/igridform.cpp @@ -21,6 +21,7 @@ IGridForm::IGridForm(QWidget *parent) : IGridForm::~IGridForm() { + delete ui; } void IGridForm::setPluginId(const QString &pluginId) diff --git a/core/imetadataplugin.cpp b/core/imetadataplugin.cpp index 2c92307..0f4fcfd 100644 --- a/core/imetadataplugin.cpp +++ b/core/imetadataplugin.cpp @@ -10,14 +10,11 @@ IMetaDataPlugin::IMetaDataPlugin() { m_service = NULL; + m_ui = NULL; } IMetaDataPlugin::~IMetaDataPlugin() { - if (m_service != NULL) - { - delete m_service; - } } QString IMetaDataPlugin::pluginName() diff --git a/core/imetadataplugin.h b/core/imetadataplugin.h index a9c7f2d..ece23ca 100644 --- a/core/imetadataplugin.h +++ b/core/imetadataplugin.h @@ -10,7 +10,7 @@ class CORESHARED_EXPORT IMetaDataPlugin : public IPlugin { public: IMetaDataPlugin(); - ~IMetaDataPlugin(); + virtual ~IMetaDataPlugin(); // IPlugin interface public: diff --git a/core/iplugin.h b/core/iplugin.h index fce9a2f..990fa44 100644 --- a/core/iplugin.h +++ b/core/iplugin.h @@ -19,7 +19,18 @@ public: m_service = NULL; } - virtual ~IPlugin() { } + virtual ~IPlugin() { + if (m_service != NULL) + { + delete m_service; + } + + if (m_ui != NULL && m_ui->parent() == NULL) + { + delete m_ui; + } + } + virtual QString pluginName() = 0; virtual QString pluginId() = 0; virtual QString pluginDescription() = 0; diff --git a/core/permissionservice.cpp b/core/permissionservice.cpp index f3a0b60..c222b3c 100644 --- a/core/permissionservice.cpp +++ b/core/permissionservice.cpp @@ -1,4 +1,9 @@ +#include "core-odb.hxx" #include "permissionservice.h" +#include + +typedef odb::query permQuery; +typedef odb::result permResult; PermissionService::PermissionService() { @@ -36,3 +41,51 @@ QSharedPointer PermissionService::forNameAndPlugin(const QString &na return p; } +bool PermissionService::checkLogin(const QString &login, const QString &password) +{ + + QSharedPointer user = loadUser(login); + if (user.data()) + { + return user->password() == encryptPassword(password) && user->active(); + } + + return false; +} + +QSharedPointer PermissionService::loadUser(const QString &login) +{ + odb::database *db = Context::instance().db(); + + Transaction tr; + return db->query_one("login = " + odb::query::_ref(login)); +} + +void PermissionService::checkForAdmin() +{ + odb::database *db = Context::instance().db(); + + Transaction tr; + odb::query q(odb::query::isAdmin == true); + odb::result r = db->query(q); + + if (r.empty()) + { + QSharedPointer admin(new User); + admin->setLogin("admin"); + admin->setName("Administrator"); + admin->setIsAdmin(true); + admin->setPassword(encryptPassword("admin")); + admin->setActive(true); + + db->persist(admin); + } + + tr.commit(); +} + +QString PermissionService::encryptPassword(const QString &plainPasswd) +{ + return QString(QCryptographicHash::hash(plainPasswd.toUtf8(),QCryptographicHash::Sha256).toBase64()); +} + diff --git a/core/permissionservice.h b/core/permissionservice.h index f48af7f..000660a 100644 --- a/core/permissionservice.h +++ b/core/permissionservice.h @@ -2,8 +2,7 @@ #define PERMISSIONSERVICE_H #include "service.h" -#include "permission.h" -#include "core-odb.hxx" +#include "data/core-data.h" #include "core_global.h" #include #include @@ -14,9 +13,6 @@ #include #include -typedef odb::query permQuery; -typedef odb::result permResult; - class CORESHARED_EXPORT PermissionService : public Service { public: @@ -25,6 +21,10 @@ public: QList > forPlugin(const QString &pluginId); QSharedPointer forNameAndPlugin(const QString &name, const QString &pluginId); + bool checkLogin(const QString &login, const QString &password); + QSharedPointer loadUser(const QString &login); + void checkForAdmin(); + QString encryptPassword(const QString &plainPasswd); }; #endif // PERMISSIONSERVICE_H diff --git a/core/users/userform.cpp b/core/users/userform.cpp index dd3edc8..1b8ce7d 100644 --- a/core/users/userform.cpp +++ b/core/users/userform.cpp @@ -5,9 +5,9 @@ #include #include "../data/core-data.h" #include "../service.h" +#include "../permissionservice.h" #include "../emptystringvalidator.h" #include "../samestringvalidator.h" -#include UserForm::UserForm(QWidget *parent) : AutoForm(parent), @@ -69,8 +69,9 @@ bool UserForm::bindOtherToData() this->entity()->addRole(srv.loadById(ui->tableWidget->item(i,0)->data(Qt::UserRole).toInt())); } } + PermissionService permService; if (m_passChanged){ - this->entity()->setPassword(QString(QCryptographicHash::hash(ui->password->text().toUtf8(),QCryptographicHash::Sha256).toBase64())); + this->entity()->setPassword(permService.encryptPassword(ui->password->text())); } return true; }