diff --git a/ComunicWatcher.pro b/ComunicWatcher.pro index af00971..9d7a548 100644 --- a/ComunicWatcher.pro +++ b/ComunicWatcher.pro @@ -1,6 +1,4 @@ -QT += core gui - -greaterThan(QT_MAJOR_VERSION, 4): QT += widgets +QT += core gui widgets network CONFIG += c++11 @@ -16,10 +14,15 @@ DEFINES += QT_DEPRECATED_WARNINGS #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ + apirequest.cpp \ + apiresponse.cpp \ main.cpp \ loginwindow.cpp HEADERS += \ + apirequest.h \ + apiresponse.h \ + config.h \ loginwindow.h FORMS += \ diff --git a/apirequest.cpp b/apirequest.cpp new file mode 100644 index 0000000..fa68376 --- /dev/null +++ b/apirequest.cpp @@ -0,0 +1,54 @@ +#include "apirequest.h" +#include "config.h" + +#include +#include + +QNetworkAccessManager APIRequest::mNetworkManager; + +APIRequest::APIRequest(const QString &uri, QObject *parent) : QObject(parent), mURI(uri) +{ + addString("serviceName", API_SERVICE_NAME); + addString("serviceToken", API_SERVICE_TOKEN); +} + +void APIRequest::addString(const QString &name, const QString &value) +{ + mArgs[name] = value; +} + +void APIRequest::exec() +{ + QUrl url; + url.setScheme(API_SERVER_SCHEME); + url.setHost(API_HOST); + url.setPath(API_BASE_PATH + mURI); + + QNetworkRequest req(url); + req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); + + QString query = ""; + for(QString val : mArgs.keys()) { + if(!query.isEmpty()) + query += "&"; + + query += QUrl::toPercentEncoding(val) + "=" + QUrl::toPercentEncoding(mArgs[val]); + } + + + // Execute request + mReply = mNetworkManager.post(req, query.toUtf8()); + mReply->setParent(this); + connect(mReply, &QNetworkReply::finished, this, &APIRequest::onResponse); +} + +void APIRequest::onResponse() +{ + int code = mReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); + QByteArray content = mReply->readAll(); + + emit done(APIResponse(code, content)); + deleteLater(); + + qDebug("Request: %s - %d - %s", mURI.toStdString().c_str(), code, content.toStdString().c_str()); +} diff --git a/apirequest.h b/apirequest.h new file mode 100644 index 0000000..b65da1f --- /dev/null +++ b/apirequest.h @@ -0,0 +1,43 @@ +/** + * Simple API request + * + * @author Pierre Hubert + */ + +#pragma once + +#include "apiresponse.h" + +#include +#include +#include + +class APIRequest : public QObject +{ + Q_OBJECT +public: + explicit APIRequest(const QString &uri, QObject *parent = nullptr); + + /** + * Add a new parameter to this request + */ + void addString(const QString &name, const QString &value); + + /** + * Execute the request + */ + void exec(); + +signals: + void done(APIResponse response); + +private slots: + void onResponse(); + +private: + QString mURI; + QMap mArgs; + static QNetworkAccessManager mNetworkManager; + QNetworkReply *mReply; +}; + diff --git a/apiresponse.cpp b/apiresponse.cpp new file mode 100644 index 0000000..cddb7bb --- /dev/null +++ b/apiresponse.cpp @@ -0,0 +1,22 @@ +#include "apiresponse.h" + +APIResponse::APIResponse(int code, QByteArray content) : + mCode(code), mContent(content) +{ + +} + +int APIResponse::getCode() const +{ + return mCode; +} + +QByteArray APIResponse::getContent() const +{ + return mContent; +} + +bool APIResponse::isError() +{ + return mCode != 200; +} diff --git a/apiresponse.h b/apiresponse.h new file mode 100644 index 0000000..7a332ed --- /dev/null +++ b/apiresponse.h @@ -0,0 +1,25 @@ +/** + * This class contains the response to an API request + * + * @author Pierre Hubert + */ + +#include + +#pragma once + +class APIResponse +{ +public: + APIResponse(int mCode, QByteArray content); + + int getCode() const; + + QByteArray getContent() const; + + bool isError(); + +private: + int mCode; + QByteArray mContent; +}; diff --git a/config.h b/config.h new file mode 100644 index 0000000..1c67c5d --- /dev/null +++ b/config.h @@ -0,0 +1,29 @@ +/** + * Configuration + * + * @author Pierre Hubert + */ + +#pragma once + + +/** + * Release configuration + */ +#ifdef QT_NO_DEBUG +// TODO : complete +#endif + + +/** + * Debug configuration + */ +#ifndef QT_NO_DEBUG + +#define API_SERVER_SCHEME "https" +#define API_HOST "devweb.local" +#define API_BASE_PATH "/comunic/api-v2/" +#define API_SERVICE_NAME "ComunicWatcher" +#define API_SERVICE_TOKEN "ComunicWatcher" + +#endif diff --git a/loginwindow.cpp b/loginwindow.cpp index 4a236e0..30337c3 100644 --- a/loginwindow.cpp +++ b/loginwindow.cpp @@ -1,3 +1,4 @@ +#include "apirequest.h" #include "loginwindow.h" #include "ui_loginwindow.h" @@ -8,8 +9,8 @@ LoginWindow::LoginWindow(QWidget *parent) , ui(new Ui::LoginWindow) { ui->setupUi(this); - setWindowFlag(Qt::FramelessWindowHint); + setLoading(false); } LoginWindow::~LoginWindow() @@ -47,9 +48,51 @@ void LoginWindow::submitForm() QMessageBox::warning(this, tr("Error"), tr("Please specify your password!")); return; } + + setLoading(true); + + auto req = new APIRequest("account/login"); + req->addString("userMail", ui->emailEdit->text()); + req->addString("userPassword", ui->passwordEdit->text()); + req->exec(); + connect(req, &APIRequest::done, this, &LoginWindow::onResponse); +} + +void LoginWindow::onResponse(APIResponse res) +{ + if(res.isError()) { + QString msg; + + switch(res.getCode()) { + case 401: + msg = tr("Invalid credentials!"); + break; + + case 429: + msg = tr("Too many login attempt, please try again later!"); + break; + + default: + msg = tr("An error occured while trying to sign you in!"); + break; + } + + setLoading(false); + QMessageBox::warning(this, tr("Login failed"), msg); + + return; + } + + QMessageBox::information(this, "ok", "success"); } void LoginWindow::on_submitButton_clicked() { submitForm(); } + +void LoginWindow::setLoading(bool loading) +{ + ui->loginProgress->setVisible(loading); + ui->loginFormContainer->setVisible(!loading); +} diff --git a/loginwindow.h b/loginwindow.h index 4167c8c..b2294c2 100644 --- a/loginwindow.h +++ b/loginwindow.h @@ -6,6 +6,8 @@ #pragma once +#include "apiresponse.h" + #include #include @@ -31,11 +33,16 @@ private slots: */ void submitForm(); + void onResponse(APIResponse res); + void on_closeButton_clicked(); void on_submitButton_clicked(); private: + void setLoading(bool loading); + + // Class members Ui::LoginWindow *ui; QPoint mOldPos; }; diff --git a/loginwindow.ui b/loginwindow.ui index 7f09c54..15be018 100644 --- a/loginwindow.ui +++ b/loginwindow.ui @@ -122,34 +122,50 @@ QToolButton:hover:!pressed { - - - Email address + + + 0 + + + 0 - - - - - - Password - - - - - - - QLineEdit::Password - - - - - - - Login - + + + + + + Email address + + + + + + + + + + Password + + + + + + + QLineEdit::Password + + + + + + + Login + + + + diff --git a/main.cpp b/main.cpp index d3cb900..1476162 100644 --- a/main.cpp +++ b/main.cpp @@ -6,6 +6,11 @@ int main(int argc, char *argv[]) { QApplication a(argc, argv); + // Initialize configuration + QCoreApplication::setOrganizationName("Comuniquons"); + QCoreApplication::setOrganizationDomain("communiquons.org"); + QCoreApplication::setApplicationName("ComunicWatcher"); + LoginWindow w; w.show();