Sending register, handling register result, sending login
This commit is contained in:
parent
89aa830bfa
commit
73e91e658f
@ -1,9 +1,11 @@
|
||||
set(HEADERS
|
||||
api.h
|
||||
codes.h
|
||||
)
|
||||
|
||||
set(SOURCES
|
||||
api.cpp
|
||||
codes.cpp
|
||||
)
|
||||
|
||||
target_sources(magpie PRIVATE ${SOURCES})
|
||||
|
82
API/api.cpp
82
API/api.cpp
@ -4,6 +4,8 @@
|
||||
#include <QJsonObject>
|
||||
#include <QUrlQuery>
|
||||
|
||||
#include "codes.h"
|
||||
|
||||
constexpr const char* json = "application/json";
|
||||
constexpr const char* urlEncoded = "application/x-www-form-urlencoded";
|
||||
|
||||
@ -93,18 +95,21 @@ void API::onTestFinished(QNetworkReply* reply, const QUrl& addr, const QJSValue&
|
||||
setAddress(addr);
|
||||
}
|
||||
|
||||
void API::sendRegister(const QString& login, const QString& password, const QJSValue &finished) {
|
||||
void API::sendRegister(const QString& login, const QString& password, const QJSValue& finished) {
|
||||
qDebug() << "Registering...";
|
||||
if (state != NotAuthenticated)
|
||||
callCallback(finished, "Can not register in current state");
|
||||
return;
|
||||
return callCallback(finished, "Can not register in current state");
|
||||
|
||||
QUrlQuery params({
|
||||
{"login", login},
|
||||
{"password", password}
|
||||
});
|
||||
|
||||
QNetworkRequest request(address.path() + "/register");
|
||||
QString path = address.path();
|
||||
QUrl regUrl = address;
|
||||
regUrl.setPath(path + "/register");
|
||||
|
||||
QNetworkRequest request(regUrl);
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, urlEncoded);
|
||||
|
||||
QNetworkReply* reply = network.post(request, params.toString(QUrl::FullyEncoded).toUtf8());
|
||||
@ -113,7 +118,30 @@ void API::sendRegister(const QString& login, const QString& password, const QJSV
|
||||
);
|
||||
}
|
||||
|
||||
void API::onRegisterFinished(QNetworkReply *reply, const QJSValue &finished) const {
|
||||
void API::sendLogin(const QString& login, const QString& password, const QJSValue& finished) {
|
||||
qDebug() << "Logging in...";
|
||||
if (state != NotAuthenticated)
|
||||
return callCallback(finished, "Can not register in current state");
|
||||
|
||||
QUrlQuery params({
|
||||
{"login", login},
|
||||
{"password", password}
|
||||
});
|
||||
|
||||
QString path = address.path();
|
||||
QUrl url = address;
|
||||
url.setPath(path + "/login");
|
||||
|
||||
QNetworkRequest request(url);
|
||||
request.setHeader(QNetworkRequest::ContentTypeHeader, urlEncoded);
|
||||
|
||||
QNetworkReply* reply = network.post(request, params.toString(QUrl::FullyEncoded).toUtf8());
|
||||
connect(reply, &QNetworkReply::finished,
|
||||
std::bind(&API::onLoginFinished, this, reply, finished)
|
||||
);
|
||||
}
|
||||
|
||||
void API::onRegisterFinished(QNetworkReply* reply, const QJSValue& finished) const {
|
||||
std::unique_ptr<QNetworkReply, NetworkReplyDeleter> rpl(reply);
|
||||
QNetworkReply::NetworkError error = reply->error();
|
||||
if (error != QNetworkReply::NoError)
|
||||
@ -125,24 +153,50 @@ void API::onRegisterFinished(QNetworkReply *reply, const QJSValue &finished) con
|
||||
!contentType.canConvert<QString>() ||
|
||||
contentType.toString() != json
|
||||
) {
|
||||
QString err("wrong response content type");
|
||||
qDebug() << "Register failed:" << err;
|
||||
callCallback(finished, err);
|
||||
return;
|
||||
return callCallback(finished, "wrong response content type");
|
||||
}
|
||||
|
||||
QByteArray data = reply->readAll();
|
||||
QJsonDocument document = QJsonDocument::fromJson(data);
|
||||
QJsonObject rootObj = document.object();
|
||||
|
||||
QJsonValue result = rootObj.value("result");
|
||||
if (!result.isString())
|
||||
QJsonValue res = rootObj.value("result");
|
||||
if (!res.isDouble())
|
||||
return callCallback(finished, "malformed json");
|
||||
|
||||
if (result.toString() != "ok")
|
||||
return callCallback(finished, "Registration result was not okay");
|
||||
Codes::Register result = Codes::convertRegister(res.toInt());
|
||||
bool success = result == Codes::Register::success;
|
||||
QString err;
|
||||
if (!success)
|
||||
err = Codes::description(result);
|
||||
|
||||
callCallback(finished, QString(), {QJSValue(true)});
|
||||
callCallback(finished, err, {QJSValue(success)});
|
||||
}
|
||||
|
||||
void API::onLoginFinished(QNetworkReply* reply, const QJSValue& finished) {
|
||||
std::unique_ptr<QNetworkReply, NetworkReplyDeleter> rpl(reply);
|
||||
QNetworkReply::NetworkError error = reply->error();
|
||||
if (error != QNetworkReply::NoError)
|
||||
return callCallback(finished, reply->errorString());
|
||||
|
||||
QVariant contentType = reply->header(QNetworkRequest::ContentTypeHeader);
|
||||
if (!
|
||||
contentType.isValid() ||
|
||||
!contentType.canConvert<QString>() ||
|
||||
contentType.toString() != json
|
||||
) {
|
||||
return callCallback(finished, "wrong response content type");
|
||||
}
|
||||
|
||||
QByteArray data = reply->readAll();
|
||||
QJsonDocument document = QJsonDocument::fromJson(data);
|
||||
QJsonObject rootObj = document.object();
|
||||
|
||||
QJsonValue res = rootObj.value("result");
|
||||
if (!res.isDouble())
|
||||
return callCallback(finished, "malformed json");
|
||||
|
||||
//todo
|
||||
}
|
||||
|
||||
void API::callCallback(const QJSValue& callback, const QString& error, const QJSValueList& arguments) const {
|
||||
|
@ -34,10 +34,12 @@ signals:
|
||||
public slots:
|
||||
void test(const QString& path, const QJSValue& finished = QJSValue());
|
||||
void sendRegister(const QString& login, const QString& password, const QJSValue& finished = QJSValue());
|
||||
void sendLogin(const QString& login, const QString& password, const QJSValue& finished = QJSValue());
|
||||
|
||||
private slots:
|
||||
void onTestFinished(QNetworkReply* reply, const QUrl& addr, const QJSValue& finished);
|
||||
void onRegisterFinished(QNetworkReply* reply, const QJSValue& finished) const;
|
||||
void onLoginFinished(QNetworkReply* reply, const QJSValue& finished);
|
||||
|
||||
private:
|
||||
void callCallback(const QJSValue& callback, const QString& error = QString(), const QJSValueList& arguments = QJSValueList()) const;
|
||||
|
33
API/codes.cpp
Normal file
33
API/codes.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
#include "codes.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
constexpr std::array<const char*, uint8_t(Codes::Register::unknownError) + 1> registerErrors({
|
||||
"Successfully registered an account",
|
||||
"Login have not been provided",
|
||||
"The login can not be empty",
|
||||
"User with provided login already exists",
|
||||
"Provided login doesn't comply with server policies",
|
||||
"Password have not been provided",
|
||||
"Password can not be empty",
|
||||
"Provided password doesn't comply with server policies",
|
||||
"Unknown registration error"
|
||||
});
|
||||
|
||||
Codes::Register Codes::convertRegister (int source) {
|
||||
if (source < 0) {
|
||||
std::cerr << "Converting Register response code which is smaller than zero, falling back to unknownError" << std::endl;
|
||||
return Register::unknownError;
|
||||
}
|
||||
|
||||
if (source > (int)Register::unknownError) {
|
||||
std::cerr << "Converting Register response code which is bigger than biggest known, falling back to unknownError" << std::endl;
|
||||
return Register::unknownError;
|
||||
}
|
||||
|
||||
return static_cast<Register>(source);
|
||||
}
|
||||
|
||||
QString Codes::description(Register code) {
|
||||
return registerErrors[(uint8_t)code];
|
||||
}
|
22
API/codes.h
Normal file
22
API/codes.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
|
||||
namespace Codes {
|
||||
enum class Register {
|
||||
success,
|
||||
noLogin,
|
||||
emptyLogin,
|
||||
loginExists,
|
||||
loginPolicyViolation,
|
||||
noPassword,
|
||||
emptyPassword,
|
||||
passwordPolicyViolation,
|
||||
unknownError
|
||||
};
|
||||
|
||||
Register convertRegister (int source);
|
||||
|
||||
QString description (Register code);
|
||||
|
||||
}
|
2
main.cpp
2
main.cpp
@ -4,6 +4,6 @@
|
||||
#include "root.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
Root app(u"qrc:qml/main.qml"_qs, argc, argv);
|
||||
Root app(u"qrc:magpie/main.qml"_qs, argc, argv);
|
||||
return app.exec();
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ int main(int argc, char *argv[]) {
|
||||
Root* app;
|
||||
|
||||
try {
|
||||
app = new Root(u"qrc:qml/main.qml"_qs, argc, argv);
|
||||
app = new Root(u"qrc:magpie/main.qml"_qs, argc, argv);
|
||||
} catch (const std::exception& exception) {
|
||||
std::cerr << "Couldn't start megpie: " << exception.what() << std::endl;
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
qt_add_qml_module(magpieQml
|
||||
URI qml
|
||||
URI magpie
|
||||
VERSION 1.0
|
||||
STATIC
|
||||
RESOURCE_PREFIX /
|
||||
OUTPUT_DIRECTORY magpie
|
||||
NO_PLUGIN
|
||||
QML_FILES
|
||||
main.qml
|
||||
@ -10,6 +11,10 @@ qt_add_qml_module(magpieQml
|
||||
Welcome.qml
|
||||
)
|
||||
|
||||
list(APPEND QML_DIRS ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(QML_IMPORT_PATH "${QML_DIRS}" CACHE STRING "Qt Creator 11 extra qml import paths")
|
||||
|
||||
target_link_libraries(magpie PRIVATE magpieQml)
|
||||
|
||||
add_subdirectory(Forms)
|
||||
add_subdirectory(Components)
|
||||
|
12
qml/Components/CMakeLists.txt
Normal file
12
qml/Components/CMakeLists.txt
Normal file
@ -0,0 +1,12 @@
|
||||
qt_add_qml_module(magpieComponents
|
||||
URI magpie.Components
|
||||
VERSION 1.0
|
||||
STATIC
|
||||
RESOURCE_PREFIX /
|
||||
OUTPUT_DIRECTORY ../magpie/Components
|
||||
NO_PLUGIN
|
||||
QML_FILES
|
||||
Modal.qml
|
||||
)
|
||||
|
||||
target_link_libraries(magpie PRIVATE magpieComponents)
|
61
qml/Components/Modal.qml
Normal file
61
qml/Components/Modal.qml
Normal file
@ -0,0 +1,61 @@
|
||||
import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
Popup {
|
||||
property bool inProgress: false
|
||||
property string status: ""
|
||||
|
||||
id: modal
|
||||
anchors.centerIn: parent
|
||||
modal: true
|
||||
focus: true
|
||||
width: column.width + 60
|
||||
height: column.height + 60
|
||||
closePolicy: Popup.CloseOnEscape
|
||||
onClosed: inProgress = false
|
||||
|
||||
Column {
|
||||
id: column
|
||||
anchors.centerIn: parent
|
||||
spacing: 10
|
||||
Label {
|
||||
text: status
|
||||
width: 300
|
||||
wrapMode: Label.WordWrap
|
||||
horizontalAlignment: Label.AlignHCenter
|
||||
}
|
||||
BusyIndicator {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: inProgress
|
||||
running: inProgress
|
||||
}
|
||||
Button {
|
||||
text: qsTr("Close")
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: !inProgress
|
||||
onClicked: modal.close()
|
||||
focus: true
|
||||
Keys.onReturnPressed: {
|
||||
if (!inProgress)
|
||||
modal.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enter: Transition {
|
||||
NumberAnimation {
|
||||
property: "opacity"
|
||||
from: 0.0
|
||||
to: 1.0
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
exit: Transition {
|
||||
NumberAnimation {
|
||||
property: "opacity"
|
||||
from: 1.0
|
||||
to: 0.0
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
}
|
@ -1,8 +1,9 @@
|
||||
qt_add_qml_module(magpieForms
|
||||
URI "qml.Forms"
|
||||
URI magpie.Forms
|
||||
VERSION 1.0
|
||||
STATIC
|
||||
RESOURCE_PREFIX /
|
||||
OUTPUT_DIRECTORY ../magpie/Forms
|
||||
NO_PLUGIN
|
||||
QML_FILES
|
||||
Login.qml
|
||||
|
@ -2,10 +2,37 @@ import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
import magpie.API
|
||||
import magpie.Components as Components
|
||||
|
||||
Column {
|
||||
signal register()
|
||||
|
||||
function login(login, password) {
|
||||
if (modal.inProgress)
|
||||
return;
|
||||
|
||||
loginField.text = login;
|
||||
passwordField.text = password;
|
||||
|
||||
modal.inProgress = true;
|
||||
modal.status = qsTr("Logging in as") + " " + login + "...";
|
||||
modal.open();
|
||||
|
||||
API.sendLogin(login, password, function (err, result) {
|
||||
if (!modal.inProgress)
|
||||
return;
|
||||
|
||||
modal.inProgress = false;
|
||||
if (err)
|
||||
modal.status = err;
|
||||
else
|
||||
modal.status = qsTr("Success");
|
||||
|
||||
if (!!result)
|
||||
modal.close();
|
||||
});
|
||||
}
|
||||
|
||||
spacing: 5
|
||||
|
||||
Label {
|
||||
@ -29,7 +56,7 @@ Column {
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: login
|
||||
id: loginField
|
||||
}
|
||||
|
||||
Label {
|
||||
@ -37,7 +64,7 @@ Column {
|
||||
}
|
||||
|
||||
TextField {
|
||||
id: password
|
||||
id: passwordField
|
||||
echoMode: TextField.Password
|
||||
}
|
||||
}
|
||||
@ -45,9 +72,11 @@ Column {
|
||||
Button {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: qsTr("Login")
|
||||
onClicked: function () {
|
||||
console.log("Not implemented");
|
||||
}
|
||||
onClicked: login(loginField.text, passwordField.text)
|
||||
}
|
||||
|
||||
Components.Modal {
|
||||
id: modal
|
||||
}
|
||||
|
||||
Row {
|
||||
|
@ -2,9 +2,11 @@ import QtQuick
|
||||
import QtQuick.Controls
|
||||
|
||||
import magpie.API
|
||||
import magpie.Components as Components
|
||||
|
||||
Column {
|
||||
signal login()
|
||||
signal success(login: string, password: string)
|
||||
|
||||
spacing: 5
|
||||
|
||||
@ -45,12 +47,35 @@ Column {
|
||||
Button {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: qsTr("Register")
|
||||
onClicked: API.sendRegister(newLogin.text, newPassword.text, function (err, result) {
|
||||
if (err)
|
||||
console.error("err")
|
||||
onClicked: modal.check()
|
||||
}
|
||||
|
||||
console.log(result);
|
||||
})
|
||||
Components.Modal {
|
||||
id: modal
|
||||
function check () {
|
||||
if (inProgress)
|
||||
return;
|
||||
|
||||
inProgress = true;
|
||||
status = qsTr("Registering") + " " + newLogin.text + "...";
|
||||
open()
|
||||
|
||||
API.sendRegister(newLogin.text, newPassword.text, function (err, result) {
|
||||
if (!modal.inProgress)
|
||||
return;
|
||||
|
||||
modal.inProgress = false;
|
||||
if (err)
|
||||
modal.status = err;
|
||||
else
|
||||
modal.status = qsTr("Success");
|
||||
|
||||
if (!!result) {
|
||||
modal.close();
|
||||
success(newLogin.text, newPassword.text);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
|
@ -3,6 +3,7 @@ import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import magpie.API
|
||||
import magpie.Components as Components
|
||||
|
||||
Page {
|
||||
property string address
|
||||
@ -47,71 +48,14 @@ Page {
|
||||
}
|
||||
}
|
||||
|
||||
Popup {
|
||||
property bool inProgress: false
|
||||
|
||||
Components.Modal {
|
||||
id: modal
|
||||
anchors.centerIn: parent
|
||||
modal: true
|
||||
focus: true
|
||||
width: column.width + 60
|
||||
height: column.height + 60
|
||||
closePolicy: Popup.CloseOnEscape
|
||||
onClosed: modal.inProgress = false
|
||||
|
||||
Column {
|
||||
id: column
|
||||
anchors.centerIn: parent
|
||||
spacing: 10
|
||||
Label {
|
||||
id: status
|
||||
width: 300
|
||||
wrapMode: Label.WordWrap
|
||||
horizontalAlignment: Label.AlignHCenter
|
||||
}
|
||||
BusyIndicator {
|
||||
id: indicator
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: modal.inProgress
|
||||
running: modal.inProgress
|
||||
}
|
||||
Button {
|
||||
id: button
|
||||
text: qsTr("Close")
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: !modal.inProgress
|
||||
onClicked: modal.close()
|
||||
focus: true
|
||||
Keys.onReturnPressed: {
|
||||
if (!modal.inProgress)
|
||||
modal.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enter: Transition {
|
||||
NumberAnimation {
|
||||
property: "opacity"
|
||||
from: 0.0
|
||||
to: 1.0
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
exit: Transition {
|
||||
NumberAnimation {
|
||||
property: "opacity"
|
||||
from: 1.0
|
||||
to: 0.0
|
||||
duration: 200
|
||||
}
|
||||
}
|
||||
|
||||
function check () {
|
||||
if (modal.inProgress)
|
||||
return;
|
||||
|
||||
modal.inProgress = true;
|
||||
status.text = qsTr("Checking") + " " + address + "...";
|
||||
modal.status = qsTr("Checking") + " " + address + "...";
|
||||
modal.open()
|
||||
|
||||
API.test(input.text, function (err, success) {
|
||||
@ -120,9 +64,9 @@ Page {
|
||||
|
||||
modal.inProgress = false;
|
||||
if (err)
|
||||
status.text = err;
|
||||
modal.status = err;
|
||||
else
|
||||
status.text = qsTr("Success");
|
||||
modal.status = qsTr("Success");
|
||||
|
||||
if (!!success)
|
||||
modal.close()
|
||||
|
@ -3,7 +3,7 @@ import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
||||
import magpie.API
|
||||
import "Forms" as Forms
|
||||
import magpie.Forms as Forms
|
||||
|
||||
Page {
|
||||
id: page
|
||||
@ -55,6 +55,9 @@ Page {
|
||||
height: stack.currentItem ? stack.currentItem.implicitHeight: 0
|
||||
|
||||
StackView {
|
||||
property string pendingLogin: ""
|
||||
property string pendingPassword: ""
|
||||
|
||||
id: stack
|
||||
initialItem: loginForm
|
||||
anchors.fill: parent
|
||||
@ -64,6 +67,13 @@ Page {
|
||||
id: loginForm
|
||||
Forms.Login {
|
||||
onRegister: stack.replace(registerForm)
|
||||
Component.onCompleted: {
|
||||
if (stack.pendingLogin && stack.pendingPassword)
|
||||
this.login(stack.pendingLogin, stack.pendingPassword)
|
||||
|
||||
stack.pendingLogin = "";
|
||||
stack.pendingPassword = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,6 +81,11 @@ Page {
|
||||
id: registerForm
|
||||
Forms.Register {
|
||||
onLogin: stack.replace(loginForm, StackView.PopTransition)
|
||||
onSuccess: function(login, password) {
|
||||
stack.pendingLogin = login;
|
||||
stack.pendingPassword = password;
|
||||
stack.replace(loginForm, StackView.PopTransition);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user