Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
Whitespace-only changes.
+129
@@ -0,0 +1,129 @@
|
||||
#ifndef APIROUTES_H
|
||||
#define APIROUTES_H
|
||||
|
||||
#include "authMethods.h"
|
||||
#include "dbConnection.h"
|
||||
#include "objectMethods.h"
|
||||
#include "replayMethods.h"
|
||||
|
||||
#include <QDebug>
|
||||
#include <QString>
|
||||
#include <QJsonDocument>
|
||||
#include <QHttpServerResponse>
|
||||
#include <qhttpserver.h>
|
||||
#include <qjsonobject.h>
|
||||
|
||||
// Loggt die HTTP-Anfragen
|
||||
void logRequest(const QHttpServerRequest &request) {
|
||||
const auto method = request.method();
|
||||
const QString url = request.url().toString();
|
||||
|
||||
qDebug() << "Request received:"
|
||||
<< "Method:" << method
|
||||
<< "URL:" << url;
|
||||
|
||||
}
|
||||
|
||||
// Fügt CORS-Routen hinzu
|
||||
void addCorsRoutes(QHttpServer &server) {
|
||||
const QStringList corsRoutes = {
|
||||
"/objects", "/objects/replayinit", "/objects/replay",
|
||||
"/replays", "/replays/delete", "/replays/user",
|
||||
"/login", "/auth", "/replays/replay/avg",
|
||||
"/bookmark", "/replays/replay/bookmark"
|
||||
};
|
||||
|
||||
auto handleOptionsRequest = [](const QHttpServerRequest &request) {
|
||||
logRequest(request);
|
||||
QHttpServerResponse response("");
|
||||
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||
response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, DELETE");
|
||||
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
||||
return response;
|
||||
};
|
||||
|
||||
for (const auto &route : corsRoutes) {
|
||||
server.route(route, QHttpServerRequest::Method::Options, handleOptionsRequest);
|
||||
}
|
||||
}
|
||||
|
||||
// Fügt API-Routen hinzu
|
||||
void addApiRoutes(QHttpServer &server) {
|
||||
// Stellt sicher, dass die Datenbank verbunden und initialisiert ist
|
||||
QSqlDatabase db = connectToDb();
|
||||
initializeDatabase(db);
|
||||
|
||||
// Routenregistrierungen
|
||||
server.route("/objects", QHttpServerRequest::Method::Post, [](const QHttpServerRequest &request) {
|
||||
logRequest(request);
|
||||
return ObjectMethods::postObjects(request);
|
||||
});
|
||||
|
||||
server.route("/objects/replayinit", QHttpServerRequest::Method::Get, [](const QHttpServerRequest &request) {
|
||||
logRequest(request);
|
||||
return ObjectMethods::getReplayInitInformation(request);
|
||||
});
|
||||
|
||||
server.route("/objects/replay", QHttpServerRequest::Method::Get, [](const QHttpServerRequest &request) {
|
||||
logRequest(request);
|
||||
return ObjectMethods::getGeoObjectsInterval(request);
|
||||
});
|
||||
|
||||
server.route("/replays", QHttpServerRequest::Method::Post, [](const QHttpServerRequest &request) {
|
||||
logRequest(request);
|
||||
return postReplays(request);
|
||||
});
|
||||
|
||||
server.route("/replays", QHttpServerRequest::Method::Get, [](const QHttpServerRequest &request) {
|
||||
logRequest(request);
|
||||
return getAllReplays(request);
|
||||
});
|
||||
|
||||
server.route("/replays/delete", QHttpServerRequest::Method::Delete, [](const QHttpServerRequest &request) {
|
||||
logRequest(request);
|
||||
return deleteReplay(request);
|
||||
});
|
||||
|
||||
server.route("/replays/replay", QHttpServerRequest::Method::Get, [](const QHttpServerRequest &request) {
|
||||
logRequest(request);
|
||||
return getSingleReplay(request);
|
||||
});
|
||||
|
||||
server.route("/replays/replay/bookmark", QHttpServerRequest::Method::Get, [](const QHttpServerRequest &request) {
|
||||
logRequest(request);
|
||||
return ObjectMethods::getBookmarks(request);
|
||||
});
|
||||
|
||||
server.route("/replays/user", QHttpServerRequest::Method::Get, [](const QHttpServerRequest &request) {
|
||||
logRequest(request);
|
||||
return getUserReplays(request);
|
||||
});
|
||||
|
||||
server.route("/bookmark", QHttpServerRequest::Method::Post, [](const QHttpServerRequest &request) {
|
||||
logRequest(request);
|
||||
return ObjectMethods::postBookmark(request);
|
||||
});
|
||||
|
||||
server.route("/login", QHttpServerRequest::Method::Post, [](const QHttpServerRequest &request) {
|
||||
logRequest(request);
|
||||
return loginUser(request);
|
||||
});
|
||||
|
||||
server.route("/auth", QHttpServerRequest::Method::Get, [](const QHttpServerRequest &request) {
|
||||
logRequest(request);
|
||||
return authUser(request);
|
||||
});
|
||||
|
||||
server.route("/replays/replay/avg", QHttpServerRequest::Method::Get, [](const QHttpServerRequest &request) {
|
||||
logRequest(request);
|
||||
return getAvg(request);
|
||||
});
|
||||
}
|
||||
|
||||
// Hauptfunktion zum Einrichten der API-Routen und CORS-Policy
|
||||
void setupApiRoutes(QHttpServer &server) {
|
||||
addApiRoutes(server);
|
||||
addCorsRoutes(server);
|
||||
}
|
||||
|
||||
#endif // APIROUTES_H
|
||||
+161
@@ -0,0 +1,161 @@
|
||||
#ifndef AUTHMETHODS_H
|
||||
#define AUTHMETHODS_H
|
||||
|
||||
#include <qhttpserverrequest.h>
|
||||
#include <qhttpserverresponse.h>
|
||||
#include <qcryptographichash.h>
|
||||
#include <qjsondocument.h>
|
||||
#include <QJsonObject>
|
||||
#include <qsqldatabase.h>
|
||||
#include <qsqlerror.h>
|
||||
#include <qsqlquery.h>
|
||||
#include <QUuid>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
|
||||
QString hashPassword(const QString &password) {
|
||||
return QString(QCryptographicHash::hash(password.toUtf8(), QCryptographicHash::Sha256).toHex());
|
||||
}
|
||||
|
||||
QString generateToken() {
|
||||
return QUuid::createUuid().toString(QUuid::WithoutBraces);
|
||||
}
|
||||
|
||||
QHttpServerResponse login(const QJsonObject &json) {
|
||||
QString username = json["username"].toString();
|
||||
QString password = json["password"].toString();
|
||||
|
||||
QSqlDatabase db = QSqlDatabase::database();
|
||||
|
||||
QSqlQuery query(db);
|
||||
|
||||
query.prepare(QString("SELECT id, password FROM public.users WHERE username = '%1'").arg(username));
|
||||
|
||||
if (!query.exec() || !query.next()) {
|
||||
QHttpServerResponse response("Invalid username or password", QHttpServerResponse::StatusCode::Unauthorized);
|
||||
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||
response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, DELETE");
|
||||
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
||||
return response;
|
||||
}
|
||||
|
||||
QString hashedPassword = query.value("password").toString();
|
||||
|
||||
if (hashedPassword != hashPassword(password)) {
|
||||
QHttpServerResponse response("Invalid username or password", QHttpServerResponse::StatusCode::Unauthorized);
|
||||
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||
response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, DELETE");
|
||||
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
||||
return response;
|
||||
}
|
||||
|
||||
QString token = generateToken();
|
||||
int userId = query.value("id").toInt();
|
||||
QDateTime expiryDate = QDateTime::currentDateTimeUtc().addSecs(24 * 3600);
|
||||
|
||||
query.prepare("INSERT INTO public.tokens (user_id, token, expiry_date) VALUES (:user_id, :token, :expiry_date)");
|
||||
query.bindValue(":user_id", userId);
|
||||
query.bindValue(":token", token);
|
||||
query.bindValue(":expiry_date", expiryDate);
|
||||
|
||||
if (!query.exec()) {
|
||||
qDebug() << "Error inserting token";
|
||||
QHttpServerResponse response("Token generation failed", QHttpServerResponse::StatusCode::InternalServerError);
|
||||
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||
response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, DELETE");
|
||||
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
||||
return response;
|
||||
}
|
||||
|
||||
QJsonObject jsonResponse;
|
||||
jsonResponse["token"] = token;
|
||||
QByteArray responseBody = QJsonDocument(jsonResponse).toJson();
|
||||
|
||||
QHttpServerResponse response(responseBody, QHttpServerResponse::StatusCode::Ok);
|
||||
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||
response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, DELETE");
|
||||
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
QHttpServerResponse loginUser(const QHttpServerRequest &request) {
|
||||
auto body = request.body();
|
||||
QJsonDocument jsonRequest = QJsonDocument::fromJson(body);
|
||||
qDebug() << jsonRequest;
|
||||
|
||||
if (!jsonRequest.isObject()) {
|
||||
QHttpServerResponse response("Invalid Request!", QHttpServerResponse::StatusCode::BadRequest);
|
||||
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||
response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS, DELETE");
|
||||
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
||||
return response;
|
||||
}
|
||||
|
||||
return login(jsonRequest.object());
|
||||
}
|
||||
|
||||
|
||||
QHttpServerResponse checkAuth(const QString &token) {
|
||||
QSqlDatabase db = QSqlDatabase::database();
|
||||
QSqlQuery query(db);
|
||||
|
||||
query.prepare(QString("SELECT user_id, expiry_date FROM tokens WHERE token = :token"));
|
||||
query.bindValue(":token", token);
|
||||
|
||||
if (!query.exec() || !query.next()) {
|
||||
QHttpServerResponse response("Invalid token", QHttpServerResponse::StatusCode::Unauthorized);
|
||||
|
||||
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||
response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
||||
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
||||
return response;
|
||||
}
|
||||
|
||||
QDateTime expiryDate = query.value("expiry_date").toDateTime();
|
||||
if (QDateTime::currentDateTimeUtc() > expiryDate) {
|
||||
QHttpServerResponse response("Token expired", QHttpServerResponse::StatusCode::Unauthorized);
|
||||
|
||||
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||
response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
||||
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
||||
return response;
|
||||
}
|
||||
|
||||
QJsonObject jsonResponse;
|
||||
jsonResponse["status"] = "Authenticated";
|
||||
QHttpServerResponse response(QJsonDocument(jsonResponse).toJson(), QHttpServerResponse::StatusCode::Ok);
|
||||
|
||||
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||
response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
||||
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
QHttpServerResponse authUser(const QHttpServerRequest &request) {
|
||||
QList<QPair<QByteArray, QByteArray>> headers = request.headers();
|
||||
QString token;
|
||||
|
||||
for (const auto &header : headers) {
|
||||
if (header.first.toLower() == "authorization") {
|
||||
QString authHeader = QString::fromUtf8(header.second);
|
||||
if (authHeader.startsWith("Bearer ")) {
|
||||
token = authHeader.mid(7);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (token.isEmpty()) {
|
||||
QHttpServerResponse response("No token provided", QHttpServerResponse::StatusCode::Unauthorized);
|
||||
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||
response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
||||
response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
|
||||
return response;
|
||||
}
|
||||
|
||||
return checkAuth(token);
|
||||
}
|
||||
|
||||
#endif // AUTHMETHODS_H
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
#ifndef DBCONNECTION_H
|
||||
#define DBCONNECTION_H
|
||||
|
||||
#include <QDebug>
|
||||
#include <QSqlDatabase>
|
||||
#include <QFile>
|
||||
#include <QSqlError>
|
||||
#include <QSqlQuery>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QDir>
|
||||
#include <QCoreApplication>
|
||||
|
||||
QSqlDatabase connectToDb() {
|
||||
QString path = QDir::cleanPath(QCoreApplication::applicationDirPath() + QDir::separator() + "../../config" + QDir::separator() + "db_config.json");
|
||||
|
||||
QFile inFile(path);
|
||||
|
||||
if (!inFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
qDebug() << "Kann die Datei nicht öffnen:" << inFile.errorString();
|
||||
}
|
||||
|
||||
QByteArray data = inFile.readAll();
|
||||
inFile.close();
|
||||
|
||||
QJsonParseError errorPtr;
|
||||
|
||||
QJsonDocument doc = QJsonDocument::fromJson(data, &errorPtr);
|
||||
|
||||
if (doc.isNull()) {
|
||||
qDebug() << "Parse failed";
|
||||
}
|
||||
|
||||
QJsonObject rootObj = doc.object();
|
||||
|
||||
QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL");
|
||||
|
||||
db.setHostName(rootObj.value("host").toString());
|
||||
db.setPort(rootObj.value("port").toInt());
|
||||
db.setDatabaseName(rootObj.value("dbname").toString());
|
||||
db.setUserName(rootObj.value("user").toString());
|
||||
db.setPassword(rootObj.value("password").toString());
|
||||
|
||||
if (!db.open()) {
|
||||
qDebug() << "Datenbankverbindung konnte nicht hergestellt werden";
|
||||
return db;
|
||||
}
|
||||
|
||||
qDebug() << "Datenbankverbindung wurde hergestellt";
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
QMap<QString, QString> getTableCreationQueries() {
|
||||
QMap<QString, QString> tableQueries;
|
||||
tableQueries["extensions"] = R"(
|
||||
CREATE EXTENSION IF NOT EXISTS postgis;
|
||||
)";
|
||||
|
||||
tableQueries["geojson-seq"] =R"(
|
||||
CREATE SEQUENCE geojson_objects_id_seq;
|
||||
)";
|
||||
// Tabelle für Benutzer
|
||||
tableQueries["users"] = R"(
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id SERIAL PRIMARY KEY,
|
||||
username TEXT NOT NULL UNIQUE,
|
||||
password TEXT NOT NULL
|
||||
)
|
||||
)";
|
||||
|
||||
// Tabelle für Tokens
|
||||
tableQueries["tokens"] = R"(
|
||||
CREATE TABLE IF NOT EXISTS tokens (
|
||||
id SERIAL PRIMARY KEY,
|
||||
user_id INT NOT NULL,
|
||||
token TEXT NOT NULL,
|
||||
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
expiry_date TIMESTAMP WITHOUT TIME ZONE NOT NULL,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||
)
|
||||
)";
|
||||
|
||||
// Tabelle für Replays
|
||||
tableQueries["replays"] = R"(
|
||||
CREATE TABLE IF NOT EXISTS replays (
|
||||
uuid TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
created_by INT NOT NULL,
|
||||
time_created BIGINT,
|
||||
FOREIGN KEY (created_by) REFERENCES groups(id) ON DELETE CASCADE
|
||||
)
|
||||
)";
|
||||
|
||||
// Tabelle für Gruppen
|
||||
tableQueries["groups"] = R"(
|
||||
CREATE TABLE IF NOT EXISTS groups (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name TEXT NOT NULL UNIQUE
|
||||
)
|
||||
)";
|
||||
|
||||
// Tabelle für die Zuordnung von Benutzern zu Gruppen
|
||||
tableQueries["user_groups"] = R"(
|
||||
CREATE TABLE IF NOT EXISTS user_groups (
|
||||
user_id INT NOT NULL,
|
||||
group_id INT NOT NULL,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (group_id) REFERENCES groups(id) ON DELETE CASCADE,
|
||||
PRIMARY KEY (user_id, group_id)
|
||||
)
|
||||
)";
|
||||
|
||||
// Tabelle für die Zuordnung von Replays zu Gruppen
|
||||
tableQueries["group_replays"] = R"(
|
||||
CREATE TABLE IF NOT EXISTS group_replays (
|
||||
group_id INT NOT NULL,
|
||||
replay_uuid TEXT NOT NULL,
|
||||
FOREIGN KEY (group_id) REFERENCES groups(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (replay_uuid) REFERENCES replays(uuid) ON DELETE CASCADE,
|
||||
PRIMARY KEY (group_id, replay_uuid)
|
||||
)
|
||||
)";
|
||||
|
||||
// Root-User erstellen (falls nicht bereits vorhanden)
|
||||
tableQueries["root_user"] = R"(
|
||||
INSERT INTO users (username, password)
|
||||
VALUES ('root', '4813494d137e1631bba301d5acab6e7bb7aa74ce1185d456565ef51d737677b2')
|
||||
ON CONFLICT (username) DO NOTHING
|
||||
)";
|
||||
|
||||
// Root-Gruppe erstellen (falls nicht bereits vorhanden)
|
||||
tableQueries["root_group"] = R"(
|
||||
INSERT INTO groups (name)
|
||||
VALUES ('Root')
|
||||
ON CONFLICT (name) DO NOTHING
|
||||
)";
|
||||
|
||||
// Root-User der Root-Gruppe zuordnen
|
||||
tableQueries["root_user_group"] = R"(
|
||||
INSERT INTO user_groups (user_id, group_id)
|
||||
SELECT u.id, g.id
|
||||
FROM users u, groups g
|
||||
WHERE u.username = 'root' AND g.name = 'Root'
|
||||
ON CONFLICT (user_id, group_id) DO NOTHING
|
||||
)";
|
||||
|
||||
return tableQueries;
|
||||
}
|
||||
|
||||
bool initializeDatabase(QSqlDatabase db) {
|
||||
if (!db.isOpen()) {
|
||||
qDebug() << "Die Datenbank ist nicht geöffnet.";
|
||||
return false;
|
||||
}
|
||||
|
||||
QSqlQuery setupQuery(db);
|
||||
if (!setupQuery.exec(R"(
|
||||
CREATE TABLE IF NOT EXISTS executed_queries (
|
||||
query_name TEXT PRIMARY KEY
|
||||
);
|
||||
)")) {
|
||||
qDebug() << "Fehler beim Erstellen der Tabelle executed_queries:" << setupQuery.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
QStringList executionOrder = {
|
||||
"extensions", "geojson_seq", "users", "tokens", "replays",
|
||||
"groups", "user_groups", "group_replays", "root_group",
|
||||
"root_user", "root_user_group"
|
||||
};
|
||||
|
||||
QMap<QString, QString> tableQueries = getTableCreationQueries();
|
||||
|
||||
for (const QString& key : executionOrder) {
|
||||
QSqlQuery checkQuery(db);
|
||||
checkQuery.prepare("SELECT 1 FROM executed_queries WHERE query_name = :queryName");
|
||||
checkQuery.bindValue(":queryName", key);
|
||||
|
||||
if (!checkQuery.exec() || !checkQuery.next()) {
|
||||
QSqlQuery execQuery(db);
|
||||
if (!execQuery.exec(tableQueries[key])) {
|
||||
qDebug() << "Fehler beim Ausführen der Query für" << key << ":" << execQuery.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
QSqlQuery insertQuery(db);
|
||||
insertQuery.prepare("INSERT INTO executed_queries (query_name) VALUES (:queryName)");
|
||||
insertQuery.bindValue(":queryName", key);
|
||||
if (!insertQuery.exec()) {
|
||||
qDebug() << "Fehler beim Einfügen in executed_queries:" << insertQuery.lastError().text();
|
||||
}
|
||||
|
||||
qDebug() << "Query für" << key << "erfolgreich ausgeführt.";
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << "Datenbank wurde erfolgreich initialisiert.";
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
+444
@@ -0,0 +1,444 @@
|
||||
#ifndef DBQUERY_H
|
||||
#define DBQUERY_H
|
||||
|
||||
#include <qjsonobject.h>
|
||||
#include <qdebug.h>
|
||||
#include <qsqldatabase.h>
|
||||
#include <qsqlquery.h>
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#include <qjsondocument.h>
|
||||
#include <QSqlError>
|
||||
#include <QUuid>
|
||||
#include <QDateTime>
|
||||
|
||||
bool insertGeoObjectToDb(const QJsonObject &obj) {
|
||||
QSqlDatabase db = QSqlDatabase::database();
|
||||
|
||||
if(!db.isOpen()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QSqlQuery query(db);
|
||||
|
||||
QJsonObject propertiesObj = obj["properties"].toObject();
|
||||
QJsonObject geoJsonObj = obj["geometry"].toObject();
|
||||
|
||||
QString replayId = propertiesObj["replay_id"].toString();
|
||||
qint64 timestamp = propertiesObj["timestamp"].toInteger();
|
||||
|
||||
QString properties = QString::fromUtf8(QJsonDocument(propertiesObj).toJson());
|
||||
QString geoJson = QString::fromUtf8(QJsonDocument(geoJsonObj).toJson());
|
||||
|
||||
query.prepare(QString("INSERT INTO %1.geojson_objects (properties, geom, timestamp) VALUES (:properties, ST_GeomFromGeoJson(:geoJson), :timestamp)").arg(replayId));
|
||||
|
||||
query.bindValue(":properties", properties);
|
||||
query.bindValue(":geoJson", geoJson);
|
||||
query.bindValue(":timestamp", timestamp);
|
||||
|
||||
if(!query.exec()) {
|
||||
qDebug() << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
QJsonArray getGeoObjectsIntervallFromDb(const QString &replayId, const QString &start_timestamp, const QString &end_timestamp) {
|
||||
QJsonArray array;
|
||||
|
||||
QSqlDatabase db = QSqlDatabase::database();
|
||||
|
||||
if (!db.isOpen()) {
|
||||
return array;
|
||||
}
|
||||
|
||||
QSqlQuery query(db);
|
||||
|
||||
query.prepare(QString(
|
||||
"SELECT properties, ST_AsGeoJSON(geom) as geojson "
|
||||
"FROM %1.geojson_objects "
|
||||
"WHERE timestamp BETWEEN :start_timestamp AND :end_timestamp "
|
||||
"ORDER BY timestamp ASC"
|
||||
).arg(replayId));
|
||||
|
||||
// Werte binden
|
||||
query.bindValue(":start_timestamp", start_timestamp);
|
||||
query.bindValue(":end_timestamp", end_timestamp);
|
||||
|
||||
// Query ausführen
|
||||
if (!query.exec()) {
|
||||
return array;
|
||||
}
|
||||
|
||||
// Ergebnisse verarbeiten
|
||||
while (query.next()) {
|
||||
GeoJSONFeature feature;
|
||||
|
||||
QJsonObject geometry = QJsonDocument::fromJson(query.value("geojson").toByteArray()).object();
|
||||
QJsonObject properties = QJsonDocument::fromJson(query.value("properties").toByteArray()).object();
|
||||
|
||||
feature.properties = properties;
|
||||
feature.geometry = geometry;
|
||||
|
||||
array.append(feature.toJson());
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
QJsonObject getReplayInitInformationsFromDb(const QString &replayId) {
|
||||
QJsonObject result;
|
||||
QJsonObject timestamps;
|
||||
QJsonArray geojsons;
|
||||
QSqlDatabase db = QSqlDatabase::database();
|
||||
|
||||
if (!db.isOpen()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
QSqlQuery query(db);
|
||||
|
||||
// Abrufen von min_timestamp und max_timestamp
|
||||
if (query.exec(QString("SELECT MIN(timestamp) as min_timestamp, MAX(timestamp) as max_timestamp FROM %1.geojson_objects").arg(replayId))) {
|
||||
if (query.next()) {
|
||||
timestamps["min_timestamp"] = query.value("min_timestamp").toString();
|
||||
timestamps["max_timestamp"] = query.value("max_timestamp").toString();
|
||||
}
|
||||
}
|
||||
|
||||
// Abrufen der GeoJSON-Objekte
|
||||
if (query.exec(QString("SELECT properties, ST_AsGeoJSON(geom) as geojson FROM %1.geojson_objects WHERE timestamp BETWEEN (SELECT MIN(timestamp) FROM %1.geojson_objects) AND (SELECT MIN(timestamp) FROM %1.geojson_objects) + 300000;").arg(replayId))) {
|
||||
while (query.next()) {
|
||||
GeoJSONFeature feature;
|
||||
|
||||
QJsonObject geometry = QJsonDocument::fromJson(query.value("geojson").toByteArray()).object();
|
||||
QJsonObject properties = QJsonDocument::fromJson(query.value("properties").toByteArray()).object();
|
||||
|
||||
feature.properties = properties;
|
||||
feature.geometry = geometry;
|
||||
|
||||
geojsons.append(feature.toJson());
|
||||
}
|
||||
}
|
||||
|
||||
// Ergebnis zusammensetzen
|
||||
result["timestamps"] = timestamps;
|
||||
result["geojsons"] = geojsons;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool insertReplayToDb(const QJsonObject &obj) {
|
||||
QString uuid = "r" + QUuid::createUuid().toString(QUuid::WithoutBraces);
|
||||
uuid = uuid.replace("-", "_");
|
||||
|
||||
QSqlDatabase db = QSqlDatabase::database();
|
||||
|
||||
QString replayName = obj["name"].toString();
|
||||
int createdBy = obj["created_by"].toInt();
|
||||
|
||||
uint now = std::chrono::duration_cast<std::chrono::seconds> (std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
|
||||
if(!db.isOpen()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QSqlQuery query(db);
|
||||
|
||||
if(!query.exec(QString("CREATE SCHEMA IF NOT EXISTS %1;").arg(uuid))) {
|
||||
qDebug() << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!query.exec(QString("CREATE TABLE IF NOT EXISTS %1.geojson_objects(id integer NOT NULL DEFAULT nextval('geojson_objects_id_seq'::regclass),properties jsonb, geom geometry(Geometry,4326),timestamp BIGINT, CONSTRAINT geojson_objects_pkey PRIMARY KEY (id))").arg(uuid))) {
|
||||
qDebug() << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!query.exec(QString("CREATE TABLE IF NOT EXISTS %1.marker(id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, description TEXT, timestamp BIGINT NOT NULL)").arg(uuid))) {
|
||||
qDebug() << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
query.prepare(QString("INSERT INTO public.replays VALUES (:uuid, :name, :created_by, :time_created);"));
|
||||
|
||||
query.bindValue(":name", replayName);
|
||||
query.bindValue(":uuid", uuid);
|
||||
query.bindValue(":created_by", createdBy);
|
||||
query.bindValue(":time_created", now);
|
||||
|
||||
if(!query.exec()) {
|
||||
qDebug() << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
query.prepare(QString("INSERT INTO group_replays (group_id, replay_uuid) VALUES (:group_id, :replay_uuid)"));
|
||||
|
||||
query.bindValue(":group_id", createdBy);
|
||||
query.bindValue(":replay_uuid", uuid);
|
||||
|
||||
if(!query.exec()) {
|
||||
qDebug() << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QJsonArray getReplaysfromDb() {
|
||||
QJsonArray array;
|
||||
QSqlDatabase db = QSqlDatabase::database();
|
||||
|
||||
if(!db.isOpen()) {
|
||||
return array;
|
||||
}
|
||||
|
||||
QSqlQuery query(db);
|
||||
|
||||
if(!query.exec(QString("SELECT * FROM public.replays ORDER BY uuid ASC"))) {
|
||||
return array;
|
||||
}
|
||||
while(query.next()) {
|
||||
QJsonObject obj;
|
||||
|
||||
obj["name"] = query.value("name").toString();
|
||||
obj["uuid"] = query.value("uuid").toString();
|
||||
obj["created_by"] = query.value("created_by").toString();
|
||||
obj["time_created"] = query.value("time_created").toString();
|
||||
|
||||
array.append(obj);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
QJsonArray getReplayfromDb(const QString &replayId) {
|
||||
QJsonArray array;
|
||||
QSqlDatabase db = QSqlDatabase::database();
|
||||
if(!db.isOpen()) {
|
||||
return array;
|
||||
}
|
||||
|
||||
QSqlQuery query(db);
|
||||
|
||||
if(!query.exec(QString("SELECT * FROM public.replays WHERE uuid = '%1' " ).arg(replayId))) {
|
||||
qDebug() << query.lastError().text();
|
||||
return array;
|
||||
}
|
||||
|
||||
while(query.next()) {
|
||||
QJsonObject obj;
|
||||
|
||||
obj["name"] = query.value("name").toString();
|
||||
obj["uuid"] = query.value("uuid").toString();
|
||||
obj["created_by"] = query.value("created_by").toString();
|
||||
obj["time_created"] = query.value("time_created").toString();
|
||||
|
||||
array.append(obj);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
QJsonArray getUserReplaysfromDb(const QString &token) {
|
||||
QJsonArray array;
|
||||
QString userId;
|
||||
QString groupId;
|
||||
|
||||
QSqlDatabase db = QSqlDatabase::database();
|
||||
if(!db.isOpen()) {
|
||||
return array;
|
||||
}
|
||||
|
||||
QSqlQuery query(db);
|
||||
|
||||
// 1. Hole den user_id für das gegebene Token
|
||||
query.prepare("SELECT user_id FROM public.tokens WHERE token = :token");
|
||||
query.bindValue(":token", token);
|
||||
|
||||
if (!query.exec()) {
|
||||
qDebug() << "Query execution failed:" << query.lastError().text();
|
||||
return array;
|
||||
}
|
||||
|
||||
if (query.next()) {
|
||||
userId = query.value("user_id").toString();
|
||||
} else {
|
||||
qDebug() << "No user found for token:" << token;
|
||||
return array;
|
||||
}
|
||||
|
||||
// 2. Finde die Gruppe, der der Benutzer angehört
|
||||
query.prepare("SELECT group_id FROM public.user_groups WHERE user_id = :user_id");
|
||||
query.bindValue(":user_id", userId);
|
||||
|
||||
if (!query.exec()) {
|
||||
qDebug() << "Query execution failed to find group for user:" << query.lastError().text();
|
||||
return array;
|
||||
}
|
||||
|
||||
if (query.next()) {
|
||||
groupId = query.value("group_id").toString();
|
||||
} else {
|
||||
qDebug() << "No group found for user:" << userId;
|
||||
return array;
|
||||
}
|
||||
|
||||
// 3. Hole alle replays, die der Gruppe zugeordnet sind
|
||||
query.prepare("SELECT replay_uuid FROM public.group_replays WHERE group_id = :group_id");
|
||||
query.bindValue(":group_id", groupId);
|
||||
|
||||
if (!query.exec()) {
|
||||
qDebug() << "Query execution failed to get replays for group:" << query.lastError().text();
|
||||
return array;
|
||||
}
|
||||
|
||||
// 4. Hole die vollständigen Informationen für jedes Replay
|
||||
while (query.next()) {
|
||||
QString replayUuid = query.value("replay_uuid").toString();
|
||||
|
||||
// Finde die Replay-Daten anhand der UUID
|
||||
QSqlQuery replayQuery(db);
|
||||
replayQuery.prepare("SELECT * FROM public.replays WHERE uuid = :uuid");
|
||||
replayQuery.bindValue(":uuid", replayUuid);
|
||||
|
||||
if (!replayQuery.exec()) {
|
||||
qDebug() << "Query execution failed to get replay details:" << replayQuery.lastError().text();
|
||||
continue; // Falls das Replay nicht gefunden wird, überspringe es
|
||||
}
|
||||
|
||||
if (replayQuery.next()) {
|
||||
QJsonObject obj;
|
||||
|
||||
obj["name"] = replayQuery.value("name").toString();
|
||||
obj["uuid"] = replayQuery.value("uuid").toString();
|
||||
obj["created_by"] = replayQuery.value("created_by").toInt();
|
||||
obj["time_created"] = replayQuery.value("time_created").toString();
|
||||
|
||||
array.append(obj);
|
||||
}
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
bool deleteReplayFromDb(const QString &replayId, QString &error) {
|
||||
QSqlDatabase db = QSqlDatabase::database();
|
||||
|
||||
|
||||
if(!db.isOpen()) {
|
||||
error = "Database connection went wrong";
|
||||
return false;
|
||||
}
|
||||
|
||||
QSqlQuery query(db);
|
||||
|
||||
if(!query.exec(QString("DELETE FROM public.replays WHERE uuid = '%1' ").arg(replayId))) {
|
||||
qDebug() << query.lastError().text();
|
||||
error = "Deleting replay from public.replay went wrong";
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!query.exec(QString("DROP SCHEMA if exists %1 cascade;").arg(replayId))) {
|
||||
qDebug() << query.lastError().text();
|
||||
error = "Droping replay Schema went wrong";
|
||||
return false;
|
||||
}
|
||||
error = "Successful replay delete";
|
||||
return true;
|
||||
}
|
||||
QJsonArray getAvgLatLng(const QString &replayId, QString &error) {
|
||||
QJsonArray array;
|
||||
QSqlDatabase db = QSqlDatabase::database();
|
||||
if(!db.isOpen()) {
|
||||
return array;
|
||||
}
|
||||
|
||||
QSqlQuery query(db);
|
||||
|
||||
if(!query.exec(QString("SELECT AVG(ST_X(geom::geometry)) AS avg_longitude, AVG(ST_Y(geom::geometry)) AS avg_latitude FROM %1.geojson_objects").arg(replayId))) {
|
||||
qDebug() << query.lastError().text();
|
||||
return array;
|
||||
}
|
||||
|
||||
while(query.next()) {
|
||||
QJsonObject obj;
|
||||
|
||||
obj["lat"] = query.value("avg_longitude").toDouble();
|
||||
obj["lng"] = query.value("avg_latitude").toDouble();
|
||||
|
||||
array.append(obj);
|
||||
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
bool insertBookmark(const QJsonObject &obj) {
|
||||
|
||||
qDebug() << obj["name"].toString();
|
||||
qDebug() << obj["description"].toString();
|
||||
qDebug() << obj["timestamp"].toInteger();
|
||||
|
||||
QSqlDatabase db = QSqlDatabase::database();
|
||||
|
||||
if(!db.isOpen()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
QSqlQuery query(db);
|
||||
|
||||
|
||||
QString replayId = obj["uuid"].toString();
|
||||
qint64 timestamp = obj["timestamp"].toInteger();
|
||||
QString name = obj["name"].toString();
|
||||
QString description = obj["description"].toString();
|
||||
|
||||
query.prepare(QString("INSERT INTO %1.marker (name, description, timestamp) VALUES (:name, :description, :timestamp)").arg(replayId));
|
||||
|
||||
query.bindValue(":name", name);
|
||||
query.bindValue(":description", description);
|
||||
query.bindValue(":timestamp", timestamp);
|
||||
|
||||
if(!query.exec()) {
|
||||
qDebug() << query.lastError().text();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QJsonArray getBookmarkFromDB(const QString &replayId) {
|
||||
QJsonArray array;
|
||||
|
||||
QSqlDatabase db = QSqlDatabase::database();
|
||||
|
||||
if(!db.isOpen()) {
|
||||
return array;
|
||||
}
|
||||
|
||||
QSqlQuery query(db);
|
||||
|
||||
if(!query.exec(QString("SELECT * FROM %1.marker ORDER BY timestamp DESC").arg(replayId))) {
|
||||
return array;
|
||||
}
|
||||
|
||||
while(query.next()) {
|
||||
QJsonObject obj;
|
||||
|
||||
obj["name"] = query.value("name").toString();
|
||||
obj["description"] = query.value("description").toString();
|
||||
obj["timestamp"] = query.value("timestamp").toLongLong();
|
||||
|
||||
array.append(obj);
|
||||
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // DBQUERY_H
|
||||
@@ -0,0 +1,38 @@
|
||||
#ifndef ISVALIDGEOJSONOBJECT_H
|
||||
#define ISVALIDGEOJSONOBJECT_H
|
||||
|
||||
#include <qjsonobject.h>
|
||||
#include <qjsonarray.h>
|
||||
|
||||
bool isValidGeoJSONFeature(const QJsonObject &json, QString &error) {
|
||||
|
||||
if(!json.contains("type") || json["type"].toString() != "Feature") {
|
||||
error = "Invalid GeoJson: 'type', must be 'Feature'";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!json.contains("geometry") || !json["geometry"].isObject()) {
|
||||
error = "Invalid GeoJSON: 'geometry' field is missing or not an object";
|
||||
return false;
|
||||
}
|
||||
|
||||
QJsonObject geometry = json["geometry"].toObject();
|
||||
|
||||
if(!geometry.contains("coordinates") || !geometry["coordinates"].isArray()) {
|
||||
error = "Invalid GeoJSON: 'geometry.coordinates' must be an an array or is missing";
|
||||
return false;
|
||||
}
|
||||
|
||||
QJsonArray coordinates = geometry["coordinates"].toArray();
|
||||
|
||||
if(json.contains("properties") && !json["properties"].isObject()) {
|
||||
error = "InvalidGeoJSON: 'properties must be an object";
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
error = "GeoJSON is valid and successfully added to database ";
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // ISVALIDGEOJSONOBJECT_H
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef ISVALIDREPLAYOBJECT_H
|
||||
#define ISVALIDREPLAYOBJECT_H
|
||||
|
||||
#include <qjsonobject.h>
|
||||
|
||||
bool isValidReplayObject(const QJsonObject &json, QString &error) {
|
||||
if(!json.contains("name") || !json.contains("created_by")) {
|
||||
error = "Replay is missing something -> name || location || created_by";
|
||||
return false;
|
||||
}
|
||||
|
||||
error = "Replay is valid and successfully created";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // ISVALIDREPLAYOBJECT_H
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
#ifndef OBJECTMETHODS_H
|
||||
#define OBJECTMETHODS_H
|
||||
|
||||
#include <qhttpserverresponse.h>
|
||||
#include <qsqldatabase.h>
|
||||
|
||||
#include "dbQuery.h"
|
||||
#include "isValidGeoJsonObject.h"
|
||||
#include "types.h"
|
||||
|
||||
#include <qhttpserverrequest.h>
|
||||
#include <qjsondocument.h>
|
||||
#include <qjsonobject.h>
|
||||
#include <QDebug>
|
||||
#include <qjsonarray.h>
|
||||
|
||||
namespace ObjectMethods {
|
||||
|
||||
// Set common response headers for CORS and content-type
|
||||
void setCommonHeaders(QHttpServerResponse &response) {
|
||||
response.setHeader("Access-Control-Allow-Origin", "*");
|
||||
response.setHeader("Content-Type", "application/json");
|
||||
}
|
||||
|
||||
// Handle errors and return a response with a specific status code
|
||||
QHttpServerResponse createErrorResponse(const QString &errorMessage, QHttpServerResponse::StatusCode statusCode) {
|
||||
QHttpServerResponse response(errorMessage, statusCode);
|
||||
setCommonHeaders(response);
|
||||
return response;
|
||||
}
|
||||
|
||||
// Validate and insert GeoJSON feature into the database
|
||||
QHttpServerResponse handleGeoJSONFeature(const QJsonObject &jsonObj) {
|
||||
QString error;
|
||||
GeoJSONFeature geoJsonObj = geoJsonObj.fromJson(jsonObj);
|
||||
|
||||
if (!isValidGeoJSONFeature(geoJsonObj.toJson(), error)) {
|
||||
return createErrorResponse(error, QHttpServerResponse::StatusCode::BadRequest);
|
||||
}
|
||||
|
||||
insertGeoObjectToDb(geoJsonObj.toJson());
|
||||
return QHttpServerResponse(QString(), QHttpServerResponse::StatusCode::Ok);
|
||||
}
|
||||
|
||||
QHttpServerResponse postObjects(const QHttpServerRequest &request) {
|
||||
auto body = request.body();
|
||||
QJsonDocument jsonRequest = QJsonDocument::fromJson(body);
|
||||
|
||||
if (!jsonRequest.isObject() && !jsonRequest.isArray()) {
|
||||
return createErrorResponse("Invalid JSON", QHttpServerResponse::StatusCode::BadRequest);
|
||||
}
|
||||
|
||||
// Handle single object or an array of objects
|
||||
if (jsonRequest.isObject()) {
|
||||
return handleGeoJSONFeature(jsonRequest.object());
|
||||
} else if (jsonRequest.isArray()) {
|
||||
for (const QJsonValue &obj : jsonRequest.array()) {
|
||||
if (obj.isObject()) {
|
||||
QHttpServerResponse response = handleGeoJSONFeature(obj.toObject());
|
||||
if (response.statusCode() == QHttpServerResponse::StatusCode::BadRequest) {
|
||||
return response; // Return error response immediately if one is found
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QHttpServerResponse(QString(), QHttpServerResponse::StatusCode::Ok);
|
||||
}
|
||||
|
||||
QHttpServerResponse getGeoObjectsInterval(const QHttpServerRequest &request) {
|
||||
if (!request.query().hasQueryItem("replayId") || !request.query().hasQueryItem("start") || !request.query().hasQueryItem("end")) {
|
||||
return createErrorResponse("Query param is missing", QHttpServerResponse::StatusCode::BadRequest);
|
||||
}
|
||||
|
||||
QString replayId = request.query().queryItemValue("replayId");
|
||||
QString start_timestamp = request.query().queryItemValue("start");
|
||||
QString end_timestamp = request.query().queryItemValue("end");
|
||||
|
||||
QJsonArray array = getGeoObjectsIntervallFromDb(replayId, start_timestamp, end_timestamp);
|
||||
|
||||
QHttpServerResponse response(array, QHttpServerResponse::StatusCode::Ok);
|
||||
setCommonHeaders(response);
|
||||
return response;
|
||||
}
|
||||
|
||||
QHttpServerResponse getReplayInitInformation(const QHttpServerRequest &request) {
|
||||
if (!request.query().hasQueryItem("replayId")) {
|
||||
return createErrorResponse("replayId is missing", QHttpServerResponse::StatusCode::BadRequest);
|
||||
}
|
||||
|
||||
QJsonObject obj = getReplayInitInformationsFromDb(request.query().queryItemValue("replayId"));
|
||||
QHttpServerResponse response(obj, QHttpServerResponse::StatusCode::Ok);
|
||||
setCommonHeaders(response);
|
||||
return response;
|
||||
}
|
||||
|
||||
QHttpServerResponse postBookmark(const QHttpServerRequest &request) {
|
||||
auto body = request.body();
|
||||
QJsonDocument jsonRequest = QJsonDocument::fromJson(body);
|
||||
QString error;
|
||||
|
||||
if (jsonRequest["name"].isNull() || jsonRequest["timestamp"].isNull()) {
|
||||
error = "values are missing";
|
||||
return createErrorResponse(error, QHttpServerResponse::StatusCode::BadRequest);
|
||||
}
|
||||
|
||||
insertBookmark(jsonRequest.object());
|
||||
QHttpServerResponse response(error, QHttpServerResponse::StatusCode::Ok);
|
||||
setCommonHeaders(response);
|
||||
return response;
|
||||
}
|
||||
|
||||
QHttpServerResponse getBookmarks(const QHttpServerRequest &request) {
|
||||
if (!request.query().hasQueryItem("replayId")) {
|
||||
return createErrorResponse("replayId is missing", QHttpServerResponse::StatusCode::BadRequest);
|
||||
}
|
||||
|
||||
QJsonArray array = getBookmarkFromDB(request.query().queryItemValue("replayId"));
|
||||
|
||||
QHttpServerResponse response(array, QHttpServerResponse::StatusCode::Ok);
|
||||
setCommonHeaders(response);
|
||||
return response;
|
||||
}
|
||||
|
||||
} // namespace ObjectMethods
|
||||
|
||||
#endif // OBJECTMETHODS_H
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
#ifndef REPLAYMETHODS_H
|
||||
#define REPLAYMETHODS_H
|
||||
|
||||
#include <qhttpserverrequest.h>
|
||||
#include <qhttpserverresponse.h>
|
||||
#include <qjsonarray.h>
|
||||
#include <qjsondocument.h>
|
||||
#include "dbQuery.h"
|
||||
#include "isValidReplayObject.h"
|
||||
|
||||
namespace {
|
||||
const QByteArray ACCESS_CONTROL_ALLOW_ORIGIN = "*";
|
||||
const QByteArray CONTENT_TYPE_JSON = "application/json";
|
||||
|
||||
QHttpServerResponse createBadRequestResponse(const QString& message) {
|
||||
QHttpServerResponse response(message, QHttpServerResponder::StatusCode::BadRequest);
|
||||
response.setHeader(QByteArray("Access-Control-Allow-Origin"), ACCESS_CONTROL_ALLOW_ORIGIN);
|
||||
response.setHeader(QByteArray("Content-Type"), CONTENT_TYPE_JSON);
|
||||
return response;
|
||||
}
|
||||
|
||||
QHttpServerResponse createOkResponse(const QJsonArray& array) {
|
||||
QHttpServerResponse response(array, QHttpServerResponder::StatusCode::Ok);
|
||||
response.setHeader(QByteArray("Access-Control-Allow-Origin"), ACCESS_CONTROL_ALLOW_ORIGIN);
|
||||
response.setHeader(QByteArray("Content-Type"), CONTENT_TYPE_JSON);
|
||||
return response;
|
||||
}
|
||||
|
||||
QHttpServerResponse createOkResponse(const QString& message) {
|
||||
QHttpServerResponse response(message, QHttpServerResponder::StatusCode::Ok);
|
||||
response.setHeader(QByteArray("Access-Control-Allow-Origin"), ACCESS_CONTROL_ALLOW_ORIGIN);
|
||||
response.setHeader(QByteArray("Content-Type"), CONTENT_TYPE_JSON);
|
||||
return response;
|
||||
}
|
||||
|
||||
QHttpServerResponse createInternalErrorResponse(const QString& error) {
|
||||
QHttpServerResponse response(error, QHttpServerResponder::StatusCode::InternalServerError);
|
||||
response.setHeader(QByteArray("Access-Control-Allow-Origin"), ACCESS_CONTROL_ALLOW_ORIGIN);
|
||||
response.setHeader(QByteArray("Access-Control-Allow-Methods"), QByteArray("GET, POST, DELETE, OPTIONS"));
|
||||
response.setHeader(QByteArray("Access-Control-Allow-Headers"), QByteArray("Content-Type, Authorization"));
|
||||
return response;
|
||||
}
|
||||
|
||||
bool hasReplayId(const QHttpServerRequest &request) {
|
||||
return request.query().hasQueryItem("replayId");
|
||||
}
|
||||
|
||||
bool hasToken(const QHttpServerRequest &request) {
|
||||
return request.query().hasQueryItem("token");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QHttpServerResponse getSingleReplay(const QHttpServerRequest &request) {
|
||||
if (!hasReplayId(request)) {
|
||||
return createBadRequestResponse("replayId is missing");
|
||||
}
|
||||
|
||||
return createOkResponse(getReplayfromDb(request.query().queryItemValue("replayId")));
|
||||
}
|
||||
|
||||
QHttpServerResponse getAllReplays(const QHttpServerRequest &request) {
|
||||
return createOkResponse(getReplaysfromDb());
|
||||
}
|
||||
|
||||
QHttpServerResponse getUserReplays(const QHttpServerRequest &request) {
|
||||
if (!hasToken(request)) {
|
||||
return createBadRequestResponse("token is missing");
|
||||
}
|
||||
|
||||
return createOkResponse(getUserReplaysfromDb(request.query().queryItemValue("token")));
|
||||
}
|
||||
|
||||
QHttpServerResponse postReplays(const QHttpServerRequest &request) {
|
||||
auto body = request.body();
|
||||
QJsonDocument jsonRequest = QJsonDocument::fromJson(body);
|
||||
|
||||
if (!jsonRequest.isObject() && !jsonRequest.isArray()) {
|
||||
return createBadRequestResponse("Invalid JSON");
|
||||
}
|
||||
|
||||
QString error;
|
||||
if (jsonRequest.isObject()) {
|
||||
QJsonObject jsonObj = jsonRequest.object();
|
||||
if (!isValidReplayObject(jsonObj, error)) {
|
||||
return createBadRequestResponse(error);
|
||||
}
|
||||
insertReplayToDb(jsonObj);
|
||||
} else if (jsonRequest.isArray()) {
|
||||
for (const QJsonValue &obj : jsonRequest.array()) {
|
||||
if (obj.isObject()) {
|
||||
QJsonObject jsonObj = obj.toObject();
|
||||
if (!isValidReplayObject(jsonObj, error)) {
|
||||
return createBadRequestResponse(error);
|
||||
}
|
||||
insertReplayToDb(jsonObj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return createOkResponse("Replays added successfully");
|
||||
}
|
||||
|
||||
QHttpServerResponse deleteReplay(const QHttpServerRequest &request) {
|
||||
if (!hasReplayId(request)) {
|
||||
return createBadRequestResponse("replayId is missing");
|
||||
}
|
||||
|
||||
QString replayId = request.query().queryItemValue("replayId");
|
||||
QString error;
|
||||
|
||||
if (!deleteReplayFromDb(replayId, error)) {
|
||||
return createInternalErrorResponse(error);
|
||||
}
|
||||
|
||||
return createOkResponse("Replay deleted successfully");
|
||||
}
|
||||
|
||||
QHttpServerResponse getAvg(const QHttpServerRequest &request) {
|
||||
if (!hasReplayId(request)) {
|
||||
return createBadRequestResponse("replayId is missing");
|
||||
}
|
||||
|
||||
QString error;
|
||||
QJsonArray array = getAvgLatLng(request.query().queryItemValue("replayId"), error);
|
||||
return createOkResponse(array);
|
||||
}
|
||||
|
||||
#endif // REPLAYMETHODS_H
|
||||
@@ -0,0 +1,32 @@
|
||||
#ifndef SETUPSSLCERTIFICATE_H
|
||||
#define SETUPSSLCERTIFICATE_H
|
||||
#include <QCoreApplication>
|
||||
#include <qdir.h>
|
||||
#include <qsslconfiguration.h>
|
||||
#include <qsslkey.h>
|
||||
|
||||
QSslConfiguration setupSslCertificate() {
|
||||
QSslConfiguration sslConfiguration;
|
||||
|
||||
QString cert = QDir::cleanPath(QCoreApplication::applicationDirPath() + QDir::separator() + "../../config" + QDir::separator() + "server.crt");
|
||||
QString key = QDir::cleanPath(QCoreApplication::applicationDirPath() + QDir::separator() + "../../config" + QDir::separator() + "private.key");
|
||||
|
||||
QFile certFile(cert);
|
||||
QFile keyFile(key);
|
||||
|
||||
if (!certFile.open(QIODevice::ReadOnly) || !keyFile.open(QIODevice::ReadOnly)) {
|
||||
qCritical() << "Failed to open certificate or key file";
|
||||
return sslConfiguration;
|
||||
}
|
||||
|
||||
QSslCertificate certificate(&certFile, QSsl::Pem);
|
||||
QSslKey privateKey(&keyFile, QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, "RME2024");
|
||||
|
||||
sslConfiguration.setLocalCertificate(certificate);
|
||||
sslConfiguration.setPrivateKey(privateKey);
|
||||
sslConfiguration.setProtocol(QSsl::TlsV1_2);
|
||||
|
||||
return sslConfiguration;
|
||||
}
|
||||
|
||||
#endif // SETUPSSLCERTIFICATE_H
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
#ifndef TYPES_H
|
||||
#define TYPES_H
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
|
||||
struct GeoJSONFeature {
|
||||
QJsonObject geometry;
|
||||
QJsonObject properties;
|
||||
|
||||
QJsonObject toJson() const {
|
||||
QJsonObject feature;
|
||||
|
||||
feature["type"] = "Feature";
|
||||
feature["geometry"] = geometry;
|
||||
feature["properties"] = properties;
|
||||
|
||||
return feature;
|
||||
}
|
||||
|
||||
static GeoJSONFeature fromJson(const QJsonObject &json) {
|
||||
GeoJSONFeature feature;
|
||||
|
||||
if(json["type"] == "Feature") {
|
||||
|
||||
feature.geometry = json["geometry"].toObject();
|
||||
feature.properties = json["properties"].toObject();
|
||||
}
|
||||
|
||||
return feature;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // TYPES_H
|
||||
|
||||
Executable
+33
@@ -0,0 +1,33 @@
|
||||
#include "include/apiroutes.h"
|
||||
// #include "include/setupSslCertificate.h"
|
||||
#include <QCoreApplication>
|
||||
#include <qhttpserver.h>
|
||||
#include <QTcpServer>
|
||||
#include <QtSql/QSqlDatabase>
|
||||
#include <QSslConfiguration>
|
||||
#include <QSslCertificate>
|
||||
#include <QSslKey>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication a(argc, argv);
|
||||
|
||||
QHttpServer server;
|
||||
qDebug() << hashPassword("root");
|
||||
// server.sslSetup(setupSslCertificate()); -> Ssl Certificate einfügen
|
||||
|
||||
setupApiRoutes(server);
|
||||
|
||||
const auto port = server.listen(QHostAddress::Any, 8080);
|
||||
|
||||
if (!port) {
|
||||
qDebug() << "Server failed to listen on port" << port;
|
||||
return 0;
|
||||
}
|
||||
qDebug() << "Server started on Port " << port;
|
||||
|
||||
return a.exec();
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user