Add registration dialog and bare-minimum auth

This commit is contained in:
E. Kozlovskaya 2021-01-04 22:14:24 +07:00
parent 42bf5da2a3
commit 1e30ca20e7
13 changed files with 658 additions and 41 deletions

View file

@ -99,7 +99,7 @@ bool Database::removeProfession(PID pid) {
void Database::save() {
QFile f(Database::mFilename);
f.open(QIODevice::ReadOnly);
f.open(QIODevice::WriteOnly);
QDataStream stream(&f);
stream << mProfessions << mUsers;
f.close();
@ -112,7 +112,7 @@ void Database::load() {
mUsers.clear();
mProfessions.clear();
QFile f(Database::mFilename);
f.open(QIODevice::WriteOnly);
f.open(QIODevice::ReadOnly);
QDataStream stream(&f);
stream >> mProfessions >> mUsers;
f.close();

View file

@ -14,17 +14,22 @@ SOURCES += \
objects/profession.cpp \
objects/user.cpp \
objects/userprofession.cpp \
db/database.cpp
db/database.cpp \
registrationdialog.cpp \
viewmodels/userprofessionviewmodel.cpp
HEADERS += \
loginwindow.h \
objects/profession.h \
objects/user.h \
objects/userprofession.h \
db/database.h
db/database.h \
registrationdialog.h \
viewmodels/userprofessionviewmodel.h
FORMS += \
loginwindow.ui
loginwindow.ui \
registrationdialog.ui
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin

View file

@ -1,15 +1,57 @@
#include "loginwindow.h"
#include "ui_loginwindow.h"
LoginWindow::LoginWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::LoginWindow)
{
LoginWindow::LoginWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::LoginWindow) {
ui->setupUi(this);
checkForFirstRun();
}
LoginWindow::~LoginWindow()
{
LoginWindow::~LoginWindow() {
delete ui;
}
void LoginWindow::checkForFirstRun() {
auto admins = Database::instance()->getUsersByType(UserType::ADMINISTRATOR);
if (admins.isEmpty()) {
QMessageBox::information(this, "Info", "No administrators found. "
"Starting registration process.");
User *user = new User();
RegistrationDialog rd(this);
rd.setEditMode(false);
rd.setUser(user);
rd.lockUserType(UserType::ADMINISTRATOR);
rd.setWindowTitle("New administrator");
if (rd.exec() != RegistrationDialog::Accepted) {
QMessageBox::critical(this, "Error", "System cannot work without administrator "
"profile.\nPlease, restart application.");
return;
}
Database::instance()->addUser(*user);
QMessageBox::information(this, "Info", "Now you can login as administrator.");
}
}
void LoginWindow::doLogin() {
QString login = ui->login->text().trimmed();
QString password = ui->password->text().trimmed();
auto user = Database::instance()->getUser(login);
if (user == nullptr || !user->checkPassword(password)) {
QMessageBox::critical(this, "Error", "Wrong pair login/password");
return;
}
QMessageBox::information(this, "Info", "Success");
// TODO: Open valid window
}
void LoginWindow::validateForm() {
if (ui->login->text().trimmed().isEmpty() || ui->password->text().trimmed().isEmpty()) {
QMessageBox::critical(this, "Error", "Fields should not be empty");
return;
}
doLogin();
}

View file

@ -2,20 +2,31 @@
#define LOGINWINDOW_H
#include <QMainWindow>
#include <QMessageBox>
#include "objects/user.h"
#include "db/database.h"
#include "registrationdialog.h"
QT_BEGIN_NAMESPACE
namespace Ui { class LoginWindow; }
QT_END_NAMESPACE
class LoginWindow : public QMainWindow
{
class LoginWindow : public QMainWindow {
private:
Q_OBJECT
Ui::LoginWindow *ui;
void checkForFirstRun();
void doLogin();
public:
LoginWindow(QWidget *parent = nullptr);
~LoginWindow();
private:
Ui::LoginWindow *ui;
public slots:
void validateForm();
};
#endif // LOGINWINDOW_H

View file

@ -6,17 +6,107 @@
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
<width>520</width>
<height>169</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>520</width>
<height>169</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>520</width>
<height>169</height>
</size>
</property>
<property name="windowTitle">
<string>LoginWindow</string>
</property>
<widget class="QWidget" name="centralwidget"/>
<widget class="QMenuBar" name="menubar"/>
<widget class="QStatusBar" name="statusbar"/>
<widget class="QWidget" name="centralwidget">
<layout class="QFormLayout" name="formLayout">
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Login:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="login"/>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Password:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="password">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<widget class="QPushButton" name="btnLogIn">
<property name="text">
<string>Log in</string>
</property>
</widget>
</item>
<item row="0" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="4" column="0">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</widget>
<resources/>
<connections/>
<connections>
<connection>
<sender>btnLogIn</sender>
<signal>clicked()</signal>
<receiver>LoginWindow</receiver>
<slot>validateForm()</slot>
<hints>
<hint type="sourcelabel">
<x>292</x>
<y>132</y>
</hint>
<hint type="destinationlabel">
<x>475</x>
<y>171</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>validateForm()</slot>
</slots>
</ui>

View file

@ -1,12 +1,18 @@
#include <QApplication>
#include "loginwindow.h"
#include <QApplication>
#include "db/database.h"
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
Database::instance()->load();
LoginWindow w;
w.show();
QObject::connect(&a, &QApplication::aboutToQuit, []() {
Database::instance()->save();
});
return a.exec();
}

View file

@ -37,17 +37,17 @@ PID User::getCurrentProfession() const {
return mCurrentProfession;
}
User User::createUser(QString login, QString password, UserType userType,
User* User::createUser(QString login, QString password, UserType userType,
QString firstName, QString secondName, QString patronymic) {
User u;
User *u = new User();
u.mUID = QUuid::createUuid();
u.mLogin = login;
u.mPassword = password;
u.mUserType = userType;
u.mFirstName = firstName;
u.mSecondName = secondName;
u.mPatronymic = patronymic;
u->mUID = QUuid::createUuid();
u->mLogin = login;
u->mPassword = password;
u->mUserType = userType;
u->mFirstName = firstName;
u->mSecondName = secondName;
u->mPatronymic = patronymic;
return u;
}
@ -62,15 +62,20 @@ bool User::hasProfession(PID pid) {
return false;
}
bool User::addProfession(const Profession &p, ProfRank rank) {
if (hasProfession(p.pID())) {
bool User::addProfession(PID pid, ProfRank rank) {
if (hasProfession(pid)) {
return false;
}
if (mProfessions.size() >= 4) {
if (mCurrentProfession == mProfessions[0].getProfession()) {
mProfessions.remove(1);
}
else {
mProfessions.remove(0);
}
UserProfession up(p.pID(), rank);
}
UserProfession up(pid, rank);
mProfessions.push_back(up);
return true;

View file

@ -13,9 +13,9 @@ typedef QUuid UID;
typedef QVector<UserProfession> ProfessionsList;
enum class UserType {
ADMINISTRATOR,
DISPATCHER,
WORKER
ADMINISTRATOR = 0,
DISPATCHER = 1,
WORKER = 2
};
class User {
@ -30,6 +30,8 @@ private:
ProfessionsList mProfessions;
PID mCurrentProfession = 0;
friend class RegistrationDialog;
public:
User() = default;
@ -43,11 +45,11 @@ public:
ProfessionsList getProfessions() const;
PID getCurrentProfession() const;
static User createUser(QString login, QString password, UserType userType,
static User* createUser(QString login, QString password, UserType userType,
QString firstName, QString secondName, QString patronymic);
bool hasProfession(PID pid);
bool addProfession(const Profession &p, ProfRank rank);
bool addProfession(PID pid, ProfRank rank);
bool setCurrentProfession(PID pid);
void removeProfession(PID pid);

View file

@ -0,0 +1,98 @@
#include "registrationdialog.h"
#include "ui_registrationdialog.h"
RegistrationDialog::RegistrationDialog(QWidget *parent) :
QDialog(parent), ui(new Ui::RegistrationDialog) {
ui->setupUi(this);
upvm = new UserProfessionViewModel(this);
ui->userProfessions->setModel(upvm);
}
RegistrationDialog::~RegistrationDialog() {
delete ui;
delete upvm;
}
void RegistrationDialog::lockUserType(UserType type) {
ui->userGroup->setCurrentIndex((int)type);
ui->userGroup->setEnabled(false);
}
void RegistrationDialog::setUser(User *usr) {
user = usr;
if (mEditMode) {
ui->firstName->setText(user->firstName());
ui->secondName->setText(user->secondName());
ui->patronymic->setText(user->patronymic());
ui->login->setText(user->getLogin());
ui->login->setEnabled(false);
ui->password->setText(user->mPassword);
ui->password->setEnabled(usr->getUserType() == UserType::ADMINISTRATOR);
ui->userGroup->setCurrentIndex((int)user->getUserType());
ui->userGroup->setEnabled(false);
upvm->setProfessionsList(user->getProfessions());
}
}
void RegistrationDialog::setEditMode(bool editMode) {
mEditMode = editMode;
}
void RegistrationDialog::accept() {
QString fname = ui->firstName->text().trimmed();
QString sname = ui->secondName->text().trimmed();
QString patr = ui->patronymic->text().trimmed();
QString login = ui->login->text().trimmed();
QString pass = ui->password->text().trimmed();
UserType type = (UserType)ui->userGroup->currentIndex();
if (fname.isEmpty() || sname.isEmpty() || patr.isEmpty()
|| login.isEmpty() || pass.isEmpty()) {
QMessageBox::critical(this, "Error", "Check field data correctness");
return;
}
if (mEditMode) {
QMessageBox::information(this, "Info", "Please note: login nor pasword cannot be "
"changed. Your changes will be omited.");
user->mPassword = pass;
user->mFirstName = fname;
user->mSecondName = sname;
user->mPatronymic = patr;
}
else {
auto u = User::createUser(login, pass, type, fname, sname, patr);
std::swap(*user, *u);
delete u;
}
QDialog::accept();
}
void RegistrationDialog::addNewProfession() {
QStringList professions;
foreach (auto prof, Database::instance()->professions()) {
professions << prof.title() + "|" + prof.pID().toString();
}
if (professions.isEmpty()) {
QMessageBox::critical(this, "Error", "No professions found");
return;
}
bool ok;
QString p = QInputDialog::getItem(this, "Choose profession", "Profession title",
professions, 0, false, &ok);
if (ok) {
PID pid = p.split("|").last();
int r = QInputDialog::getInt(this, "Profession rank", "", 1, 1, 2e5, 1, &ok);
if (ok) {
user->addProfession(pid, r);
return;
}
}
QMessageBox::critical(this, "Error", "Aborted by user or selected non-existant profession");
}
void RegistrationDialog::removeOldProfession() {
}

View file

@ -0,0 +1,37 @@
#ifndef REGISTRATIONDIALOG_H
#define REGISTRATIONDIALOG_H
#include <QDialog>
#include <QInputDialog>
#include <QMessageBox>
#include "objects/user.h"
#include "viewmodels/userprofessionviewmodel.h"
namespace Ui { class RegistrationDialog; }
class RegistrationDialog : public QDialog {
private:
Q_OBJECT
Ui::RegistrationDialog *ui;
UserProfessionViewModel *upvm;
User *user = nullptr;
bool mEditMode = false;
public:
explicit RegistrationDialog(QWidget *parent = nullptr);
~RegistrationDialog();
void lockUserType(UserType type);
void setUser(User *usr);
void setEditMode(bool editMode);
public slots:
void accept() Q_DECL_OVERRIDE;
void addNewProfession();
void removeOldProfession();
};
#endif // REGISTRATIONDIALOG_H

View file

@ -0,0 +1,240 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>RegistrationDialog</class>
<widget class="QDialog" name="RegistrationDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>648</width>
<height>436</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>648</width>
<height>436</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>648</width>
<height>436</height>
</size>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Full name</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QLineEdit" name="firstName">
<property name="placeholderText">
<string>First name</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="secondName">
<property name="placeholderText">
<string>Second name</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLineEdit" name="patronymic">
<property name="placeholderText">
<string>Patronymic</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>Login data</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="login">
<property name="placeholderText">
<string>Login</string>
</property>
</widget>
</item>
<item>
<widget class="QLineEdit" name="password">
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
<property name="placeholderText">
<string>Password</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string>User type</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="0" column="0">
<widget class="QComboBox" name="userGroup">
<item>
<property name="text">
<string>Administrator</string>
</property>
</item>
<item>
<property name="text">
<string>Dispatcher</string>
</property>
</item>
<item>
<property name="text">
<string>Worker</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Professions</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="0" column="0" rowspan="2">
<widget class="QTableView" name="userProfessions"/>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="btnAddProfession">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Add</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="btnRemoveProfession">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="minimumSize">
<size>
<width>630</width>
<height>23</height>
</size>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>RegistrationDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>257</x>
<y>426</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>RegistrationDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>325</x>
<y>426</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>btnAddProfession</sender>
<signal>clicked()</signal>
<receiver>RegistrationDialog</receiver>
<slot>addNewProfession()</slot>
<hints>
<hint type="sourcelabel">
<x>587</x>
<y>245</y>
</hint>
<hint type="destinationlabel">
<x>520</x>
<y>184</y>
</hint>
</hints>
</connection>
<connection>
<sender>btnRemoveProfession</sender>
<signal>clicked()</signal>
<receiver>RegistrationDialog</receiver>
<slot>removeOldProfession()</slot>
<hints>
<hint type="sourcelabel">
<x>600</x>
<y>363</y>
</hint>
<hint type="destinationlabel">
<x>279</x>
<y>184</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>addNewProfession()</slot>
<slot>removeOldProfession()</slot>
</slots>
</ui>

View file

@ -0,0 +1,56 @@
#include "userprofessionviewmodel.h"
UserProfessionViewModel::UserProfessionViewModel(QObject *parent) : QAbstractTableModel(parent) {
}
int UserProfessionViewModel::rowCount(const QModelIndex &/*parent*/) const {
return mProfList.length();
}
int UserProfessionViewModel::columnCount(const QModelIndex &/*parent*/) const {
return 3;
}
QVariant UserProfessionViewModel::headerData(int section,
Qt::Orientation orientation, int role) const {
if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
switch (section) {
case 0:
return QString("Profession");
case 1:
return QString("Date of acquirement");
case 2:
return QString("Rank");
}
}
return QVariant();
}
QVariant UserProfessionViewModel::data(const QModelIndex &index, int role) const {
if (role == Qt::DisplayRole) {
auto item = mProfList[index.row()];
auto prof = Database::instance()->getProfession(item.getProfession());
int col = index.column();
switch (col) {
case 0:
return prof == nullptr? "ERROR:UNKNOWN" : prof->title();
case 1:
return item.getAcquiredDate();
case 2:
return item.getRank();
}
return "UNKNOWN FIELD";
}
return QVariant();
}
void UserProfessionViewModel::setProfessionsList(const ProfessionsList &profList) {
beginResetModel();
mProfList.clear();
mProfList += profList;
endResetModel();
}

View file

@ -0,0 +1,25 @@
#ifndef USERPROFESSIONVIEWMODEL_H
#define USERPROFESSIONVIEWMODEL_H
#include <QAbstractTableModel>
#include "../objects/user.h"
#include "../db/database.h"
class UserProfessionViewModel : public QAbstractTableModel {
private:
Q_OBJECT
ProfessionsList mProfList;
public:
UserProfessionViewModel(QObject *parent);
int rowCount(const QModelIndex &parent = QModelIndex()) const;
int columnCount(const QModelIndex &parent = QModelIndex()) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
void setProfessionsList(const ProfessionsList &profList);
};
#endif // USERPROFESSIONVIEWMODEL_H