/
Shymer123
/
Messenger
Обзор
Документация
Войти
/
Shymer123
/
Messenger
Код
Запросы
0
Задачи
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
UI_Client/SourceFiles/authorization.cpp
321 строка
9 KB
Shymer123
it is possible to add chats and messages, even if there was no Internet (but confirmation from the server is needed to save)
27 мар 2025, 17:43
27 мар 2025, 17:43
59ff8da
Код
Авторство
О чём код?
#include "authorization.h" #include "Ui/MainWindow.h" #include "RequestResponseHandler/dependencyManager.h" #include "DataModels/user_data.h" #include "Ui/Widgets/Inputs/PhoneLineEdit/PhoneLineEdit.h" #include <QFormLayout> #include <QJsonObject> #include <QPushButton> #include <QLabel> Authorization::Authorization(QWidget *parent) : QWidget{parent} { connectServer(); buildWidgets(); Entrance(); handler = DependencyManager::instance().communicationHandler(); connection(); } void Authorization::connectServer() { clientSocket = new QTcpSocket(this); clientSocket->connectToHost("127.0.0.1", PORT); connect(clientSocket, &QTcpSocket::connected, this, []() { qDebug() << "CLIENT: Connected to the server"; }); connect(clientSocket, &QTcpSocket::disconnected, this, [&]() { clientSocket->connectToHost("127.0.0.1", PORT); }); DependencyManager::instance().initializeCommunicationHandler(clientSocket); } void Authorization::Registration() { authPageLabel->setText(tr("already have an account?")); topNameLabel->setText(tr("Registration")); authButton->setText(tr("Register")); authPageButton->setText(tr("enter")); nickEdit->setText(""); passwordEdit->setText(""); phoneLabel->show(); phoneEdit->show(); infoLabel->setText(""); } void Authorization::Entrance() { authPageLabel->setText(tr("no account?")); topNameLabel->setText(tr("Entrance")); authButton->setText(tr("Enter")); authPageButton->setText(tr("register")); nickEdit->setText(""); passwordEdit->setText(""); phoneLabel->hide(); phoneEdit->hide(); infoLabel->setText(""); } void Authorization::buildWidgets() { vLayout = new QVBoxLayout(this); hLayout = new QHBoxLayout(this); formLayout = new QFormLayout(this); topNameLabel = new QLabel(this); topNameLabel->setAlignment(Qt::AlignCenter); topNameLabel->setFont(QFont(tr("Terminus"), 20)); authPageLabel = new QLabel(this); authPageLabel->setAlignment(Qt::AlignCenter); nickEdit = new QLineEdit(this); passwordEdit = new QLineEdit(this); authPageButton = new QPushButton(this); authButton = new QPushButton(this); infoLabel = new QLabel(this); phoneLabel = new QLabel(tr("Phone Number"), this); phoneEdit = new Ui::Widgets::PhoneLineEdit(this); formLayout->addRow(tr("Nickname"), nickEdit); formLayout->addRow(tr("Password"), passwordEdit); formLayout->addRow(phoneLabel, phoneEdit); hLayout->addWidget(authPageLabel, 0); hLayout->addWidget(authPageButton, 0, Qt::AlignLeft); vLayout->addWidget(topNameLabel, 5, Qt::AlignVCenter); vLayout->addLayout(formLayout, 0); vLayout->addLayout(hLayout, 2); vLayout->addWidget(infoLabel); vLayout->addWidget(authButton); } void Authorization::connection() { connect(authPageButton, &QPushButton::clicked, this, &Authorization::regimeChange); connect(authButton, &QPushButton::clicked, this, &Authorization::authActions); connect(handler, &CommunicationHandler::getIsPhoneNumberAlreadyUseReceived, this, &Authorization::onIsPhoneAlreadyUseReceived); connect(handler, &CommunicationHandler::getIsNameAlreadyUseReceived, this, &Authorization::onIsNameAlreadyUseReceived); connect(handler, &CommunicationHandler::getStoredPasswordDataReceived, this, &Authorization::onStoredPasswordDataReceived); connect(handler, &CommunicationHandler::getUserIDReceived, this, &Authorization::onUserIDReceived); connect(handler, &CommunicationHandler::getPhoneNumberReceived, this, &Authorization::onPhoneNumberReceived); } //slots void Authorization::regimeChange() { QPushButton* button = static_cast<QPushButton*>(sender()); if(button->text() == "register") { Registration(); } else if(button->text() == "enter") { Entrance(); } } void Authorization::authActions() { QPushButton* button = static_cast<QPushButton*>(sender()); m_userName = nickEdit->text(); m_password = passwordEdit->text(); m_phoneNumber = phoneEdit->text(); if(button->text() == "Register") { if(!isNameValid()) { infoLabel->setText(tr("Only numbers and letters are allowed in the name(no more than 2 underscores),\n " "the nickname must not be less than 5\n and no more than 15 characters")); return; } if(!isPasswordValid()) { infoLabel->setText(tr("Spaces are not allowed in the password,\n " "the password must not be less than 8\n and no more than 15 characters")); return; } isPhoneNumberAlreadyUse(); } else if(button->text() == "Enter") { getStoredPasswordData(); } } bool Authorization::isNameValid() { int countUnderlining = 0; if(m_userName.size() > 15 || m_userName == "" || m_userName.size() < 5) { return false; } for(const QChar& ch : std::as_const(m_userName)) { if(!ch.isLetterOrNumber()) { if(ch == '_' && countUnderlining < 2) { ++countUnderlining; } else { return false; } } } return true; } bool Authorization::isPasswordValid() { if(m_password.size() > 15 || m_password == "" || m_password.size() < 8) { return false; } for(const QChar& ch : std::as_const(m_password)) { if(ch.isSpace()) { return false; } } return true; } void Authorization::isPhoneNumberAlreadyUse() { if(m_phoneNumber.length() > 3) { handler->getIsPhoneNumberAlreadyUse(m_phoneNumber); } } void Authorization::isNameAlreadyUse() { handler->getIsNameAlreadyUse(m_userName); } QByteArray Authorization::generateSalt(int length = 16) { QByteArray salt(length, 0); RAND_bytes(reinterpret_cast<unsigned char*>(salt.data()), length); return salt; } QByteArray Authorization::hashPassword(const QString& password, const QByteArray& salt) { const EVP_MD* md = EVP_sha256(); QByteArray hash(EVP_MAX_MD_SIZE, 0); unsigned int hashLength = 0; EVP_MD_CTX* ctx = EVP_MD_CTX_new(); EVP_DigestInit_ex(ctx, md, nullptr); EVP_DigestUpdate(ctx, salt.data(), salt.size()); EVP_DigestUpdate(ctx, password.toUtf8().data(), password.toUtf8().size()); EVP_DigestFinal_ex(ctx, reinterpret_cast<unsigned char*>(hash.data()), &hashLength); EVP_MD_CTX_free(ctx); hash.resize(hashLength); return hash; } void Authorization::savePassword(const QString& username, const QString& password, const QString& phoneNumber) { QByteArray salt = generateSalt(); QByteArray hashedPassword = hashPassword(password, salt); handler->addUserInDatabase(username, hashedPassword.toHex(), salt.toHex(), phoneNumber); } void Authorization::getStoredPasswordData() { handler->getStoredPasswordData(m_userName); } void Authorization::onIsPhoneAlreadyUseReceived(const QJsonObject& response) { bool isPhoneNumberUse = response.value("isPhoneNumberUse").toBool(); if(!isPhoneNumberUse) { isNameAlreadyUse(); } else { infoLabel->setText(tr("An account with this phone number already\nexists or the number was entered incorrectly")); return; } } void Authorization::onIsNameAlreadyUseReceived(const QJsonObject& response) { bool isNameUse = response.value("isNameUse").toBool(); if(!isNameUse) { infoLabel->setText(tr("successful registration")); savePassword(m_userName, m_password, m_phoneNumber); handler->getUserID(m_userName); } else { infoLabel->setText(tr("this nickname is already in use")); return; } } void Authorization::onStoredPasswordDataReceived(const QJsonObject& response) { QByteArray storedHash = QByteArray::fromHex(response.value("storedHash").toString().toUtf8()); QByteArray storedSalt = QByteArray::fromHex(response.value("storedSalt").toString().toUtf8()); QByteArray inputHash = hashPassword(m_password, storedSalt); bool isValid = (storedHash == inputHash); if(!isValid) { passwordEdit->setText(""); infoLabel->setText(tr("Invalid nickname or password")); return; } handler->getUserID(m_userName); } void Authorization::onUserIDReceived(const QJsonObject& response) { m_userID = response.value("userID").toInt(); handler->getPhoneNumber(m_userID); } void Authorization::onPhoneNumberReceived(const QJsonObject& response) { handler->addUserInServerCache(m_userID); m_phoneNumber = response.value("phoneNumber").toString(); UserData::instance().setID(m_userID); UserData::instance().setUserName(m_userName); UserData::instance().setPhoneNumber(m_phoneNumber); Ui::MainWindow* window = new Ui::MainWindow(); window->show(); this->close(); }