You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-07-03 23:50:33 +02:00
Handle switching API domain
This commit is contained in:
@ -85,4 +85,19 @@ Item {
|
|||||||
onClicked: root.loginButtonClicked()
|
onClicked: root.loginButtonClicked()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: apiBaseUrlTF
|
||||||
|
onAccepted: root.loginButtonClicked()
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: emailTF
|
||||||
|
onAccepted: root.loginButtonClicked()
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: passwordTF
|
||||||
|
onAccepted: root.loginButtonClicked()
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ Application::Application(int &argc, char **argv) :
|
|||||||
|
|
||||||
qDebug() << "Config dir:" << paths::configDir();
|
qDebug() << "Config dir:" << paths::configDir();
|
||||||
qDebug() << "Database file:" << paths::databaseFile();
|
qDebug() << "Database file:" << paths::databaseFile();
|
||||||
|
qDebug() << "SSL:" << QSslSocket::sslLibraryBuildVersionString() << QSslSocket::sslLibraryVersionNumber();
|
||||||
|
|
||||||
jop::db().initialize(paths::databaseFile());
|
jop::db().initialize(paths::databaseFile());
|
||||||
|
|
||||||
@ -152,9 +153,21 @@ void Application::dispatcher_loginClicked(const QString &apiBaseUrl, const QStri
|
|||||||
qDebug() << apiBaseUrl << email << password;
|
qDebug() << apiBaseUrl << email << password;
|
||||||
dispatcher().emitLoginStarted();
|
dispatcher().emitLoginStarted();
|
||||||
|
|
||||||
|
QString newBaseUrl = filters::apiBaseUrl(apiBaseUrl);
|
||||||
|
|
||||||
Settings settings;
|
Settings settings;
|
||||||
|
|
||||||
|
if (newBaseUrl != settings.value("api.baseUrl").toString()) {
|
||||||
|
// TODO: add confirmation dialog
|
||||||
|
qDebug() << "Base URL has changed from" << settings.value("api.baseUrl").toString() << "to" << newBaseUrl;
|
||||||
|
BaseModel::deleteAll(jop::FoldersTable);
|
||||||
|
BaseModel::deleteAll(jop::ChangesTable);
|
||||||
|
settings.remove("lastRevId");
|
||||||
|
settings.setValue("clientId", uuid::createUuid());
|
||||||
|
}
|
||||||
|
|
||||||
settings.setValue("user.email", filters::email(email));
|
settings.setValue("user.email", filters::email(email));
|
||||||
settings.setValue("api.baseUrl", filters::apiBaseUrl(apiBaseUrl));
|
settings.setValue("api.baseUrl", newBaseUrl);
|
||||||
|
|
||||||
api_.setBaseUrl(apiBaseUrl);
|
api_.setBaseUrl(apiBaseUrl);
|
||||||
|
|
||||||
@ -168,6 +181,9 @@ void Application::dispatcher_logoutClicked() {
|
|||||||
|
|
||||||
Settings settings;
|
Settings settings;
|
||||||
settings.setValue("session.id", "");
|
settings.setValue("session.id", "");
|
||||||
|
api_.setSessionId("");
|
||||||
|
synchronizer_.setSessionId("");
|
||||||
|
|
||||||
view_.showPage("login");
|
view_.showPage("login");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,13 +131,13 @@ bool Database::commit() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Database::execQuery(QSqlQuery &query) {
|
bool Database::execQuery(QSqlQuery &query) {
|
||||||
qDebug().noquote() << "SQL:" << query.lastQuery();
|
// qDebug().noquote() << "SQL:" << query.lastQuery();
|
||||||
|
|
||||||
QMapIterator<QString, QVariant> i(query.boundValues());
|
// QMapIterator<QString, QVariant> i(query.boundValues());
|
||||||
while (i.hasNext()) {
|
// while (i.hasNext()) {
|
||||||
i.next();
|
// i.next();
|
||||||
qDebug().noquote() << "SQL:" << i.key() << "=" << i.value().toString();
|
// qDebug().noquote() << "SQL:" << i.key() << "=" << i.value().toString();
|
||||||
}
|
// }
|
||||||
|
|
||||||
return query.exec();
|
return query.exec();
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,10 @@ void Dispatcher::emitFolderDeleted(const QString &folderId) {
|
|||||||
emit folderDeleted(folderId);
|
emit folderDeleted(folderId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Dispatcher::emitAllFoldersDeleted() {
|
||||||
|
emit allFoldersDeleted();
|
||||||
|
}
|
||||||
|
|
||||||
void Dispatcher::emitLoginClicked(const QString &apiBaseUrl, const QString &email, const QString &password) {
|
void Dispatcher::emitLoginClicked(const QString &apiBaseUrl, const QString &email, const QString &password) {
|
||||||
emit loginClicked(apiBaseUrl, email, password);
|
emit loginClicked(apiBaseUrl, email, password);
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ public slots:
|
|||||||
void emitFolderCreated(const QString& folderId);
|
void emitFolderCreated(const QString& folderId);
|
||||||
void emitFolderUpdated(const QString& folderId);
|
void emitFolderUpdated(const QString& folderId);
|
||||||
void emitFolderDeleted(const QString& folderId);
|
void emitFolderDeleted(const QString& folderId);
|
||||||
|
void emitAllFoldersDeleted();
|
||||||
void emitLoginClicked(const QString& domain, const QString& email, const QString &password);
|
void emitLoginClicked(const QString& domain, const QString& email, const QString &password);
|
||||||
void emitLogoutClicked();
|
void emitLogoutClicked();
|
||||||
void emitLoginStarted();
|
void emitLoginStarted();
|
||||||
@ -29,6 +30,7 @@ signals:
|
|||||||
void folderCreated(const QString& folderId);
|
void folderCreated(const QString& folderId);
|
||||||
void folderUpdated(const QString& folderId);
|
void folderUpdated(const QString& folderId);
|
||||||
void folderDeleted(const QString& folderId);
|
void folderDeleted(const QString& folderId);
|
||||||
|
void allFoldersDeleted();
|
||||||
void loginClicked(const QString& domain, const QString& email, const QString& password);
|
void loginClicked(const QString& domain, const QString& email, const QString& password);
|
||||||
void logoutClicked();
|
void logoutClicked();
|
||||||
void loginStarted();
|
void loginStarted();
|
||||||
|
@ -246,6 +246,16 @@ bool BaseModel::isValidFieldName(Table table, const QString &name) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BaseModel::deleteAll(Table table) {
|
||||||
|
QString tableName = BaseModel::tableName(table);
|
||||||
|
jop::db().execQuery("DELETE FROM " + tableName);
|
||||||
|
BaseModel::cache_.clear();
|
||||||
|
|
||||||
|
if (table == jop::FoldersTable) {
|
||||||
|
dispatcher().emitAllFoldersDeleted();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// When loading a QSqlQuery, all the values are cleared and replaced by those
|
// When loading a QSqlQuery, all the values are cleared and replaced by those
|
||||||
// from the QSqlQuery. All the fields are marked as NOT changed as it's assumed
|
// from the QSqlQuery. All the fields are marked as NOT changed as it's assumed
|
||||||
// the object is already in the database (since loaded from there).
|
// the object is already in the database (since loaded from there).
|
||||||
|
@ -57,6 +57,7 @@ public:
|
|||||||
static bool hasField(jop::Table table, const QString& name);
|
static bool hasField(jop::Table table, const QString& name);
|
||||||
static QStringList tableFieldNames(Table table);
|
static QStringList tableFieldNames(Table table);
|
||||||
static bool isValidFieldName(Table table, const QString& name);
|
static bool isValidFieldName(Table table, const QString& name);
|
||||||
|
static void deleteAll(Table table);
|
||||||
|
|
||||||
void loadSqlQuery(const QSqlQuery& query);
|
void loadSqlQuery(const QSqlQuery& query);
|
||||||
void loadJsonObject(const QJsonObject& jsonObject);
|
void loadJsonObject(const QJsonObject& jsonObject);
|
||||||
|
@ -10,6 +10,7 @@ FolderModel::FolderModel(Database &database) : QAbstractListModel(), db_(databas
|
|||||||
connect(&dispatcher(), SIGNAL(folderCreated(QString)), this, SLOT(dispatcher_folderCreated(QString)));
|
connect(&dispatcher(), SIGNAL(folderCreated(QString)), this, SLOT(dispatcher_folderCreated(QString)));
|
||||||
connect(&dispatcher(), SIGNAL(folderUpdated(QString)), this, SLOT(dispatcher_folderUpdated(QString)));
|
connect(&dispatcher(), SIGNAL(folderUpdated(QString)), this, SLOT(dispatcher_folderUpdated(QString)));
|
||||||
connect(&dispatcher(), SIGNAL(folderDeleted(QString)), this, SLOT(dispatcher_folderDeleted(QString)));
|
connect(&dispatcher(), SIGNAL(folderDeleted(QString)), this, SLOT(dispatcher_folderDeleted(QString)));
|
||||||
|
connect(&dispatcher(), SIGNAL(allFoldersDeleted()), this, SLOT(dispatcher_allFoldersDeleted()));
|
||||||
}
|
}
|
||||||
|
|
||||||
int FolderModel::rowCount(const QModelIndex & parent) const { Q_UNUSED(parent);
|
int FolderModel::rowCount(const QModelIndex & parent) const { Q_UNUSED(parent);
|
||||||
@ -208,3 +209,10 @@ void FolderModel::dispatcher_folderDeleted(const QString &folderId) {
|
|||||||
beginRemoveRows(QModelIndex(), index, index);
|
beginRemoveRows(QModelIndex(), index, index);
|
||||||
endRemoveRows();
|
endRemoveRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FolderModel::dispatcher_allFoldersDeleted() {
|
||||||
|
qDebug() << "FolderModel All folders deleted";
|
||||||
|
cache_.clear();
|
||||||
|
beginResetModel();
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
@ -57,6 +57,7 @@ public slots:
|
|||||||
void dispatcher_folderCreated(const QString& folderId);
|
void dispatcher_folderCreated(const QString& folderId);
|
||||||
void dispatcher_folderUpdated(const QString& folderId);
|
void dispatcher_folderUpdated(const QString& folderId);
|
||||||
void dispatcher_folderDeleted(const QString& folderId);
|
void dispatcher_folderDeleted(const QString& folderId);
|
||||||
|
void dispatcher_allFoldersDeleted();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -209,7 +209,13 @@ void Synchronizer::api_requestDone(const QJsonObject& response, const QString& t
|
|||||||
|
|
||||||
qDebug() << "WebApi: done" << category << action << arg1 << arg2;
|
qDebug() << "WebApi: done" << category << action << arg1 << arg2;
|
||||||
|
|
||||||
// TODO: check for error
|
QString error = "";
|
||||||
|
|
||||||
|
if (response.contains("error")) {
|
||||||
|
error = response.value("error").toString();
|
||||||
|
qCritical().noquote() << "Sync error:" << error;
|
||||||
|
// Each action might handle errors differently so let it proceed below
|
||||||
|
}
|
||||||
|
|
||||||
// =============================================================================================
|
// =============================================================================================
|
||||||
// HANDLE UPLOAD RESPONSE
|
// HANDLE UPLOAD RESPONSE
|
||||||
@ -218,22 +224,24 @@ void Synchronizer::api_requestDone(const QJsonObject& response, const QString& t
|
|||||||
if (state_ == UploadingChanges) {
|
if (state_ == UploadingChanges) {
|
||||||
uploadsRemaining_--;
|
uploadsRemaining_--;
|
||||||
|
|
||||||
qDebug() << "Synced folder" << arg1;
|
if (error == "") {
|
||||||
|
qDebug() << "Synced folder" << arg1;
|
||||||
|
|
||||||
if (action == "putFolder") {
|
if (action == "putFolder") {
|
||||||
Change::disposeByItemId(arg1);
|
Change::disposeByItemId(arg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action == "patchFolder") {
|
if (action == "patchFolder") {
|
||||||
Change::disposeByItemId(arg1);
|
Change::disposeByItemId(arg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action == "deleteFolder") {
|
if (action == "deleteFolder") {
|
||||||
Change::disposeByItemId(arg1);
|
Change::disposeByItemId(arg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uploadsRemaining_ < 0) {
|
if (uploadsRemaining_ < 0) {
|
||||||
qWarning() << "Mismatch on operations done:" << uploadsRemaining_;
|
qWarning() << "Mismatch on operations done:" << uploadsRemaining_;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkNextState();
|
checkNextState();
|
||||||
@ -243,48 +251,51 @@ void Synchronizer::api_requestDone(const QJsonObject& response, const QString& t
|
|||||||
// =============================================================================================
|
// =============================================================================================
|
||||||
|
|
||||||
} else if (state_ == DownloadingChanges) {
|
} else if (state_ == DownloadingChanges) {
|
||||||
if (action == "getSynchronizer") {
|
if (error != "") {
|
||||||
QJsonArray items = response["items"].toArray();
|
checkNextState();
|
||||||
QString maxRevId = "";
|
} else {
|
||||||
foreach (QJsonValue it, items) {
|
if (action == "getSynchronizer") {
|
||||||
QJsonObject obj = it.toObject();
|
QJsonArray items = response["items"].toArray();
|
||||||
QString itemId = obj["item_id"].toString();
|
QString maxRevId = "";
|
||||||
QString itemType = obj["item_type"].toString();
|
foreach (QJsonValue it, items) {
|
||||||
QString operationType = obj["type"].toString();
|
QJsonObject obj = it.toObject();
|
||||||
QString revId = obj["id"].toString();
|
QString itemId = obj["item_id"].toString();
|
||||||
QJsonObject item = obj["item"].toObject();
|
QString itemType = obj["item_type"].toString();
|
||||||
|
QString operationType = obj["type"].toString();
|
||||||
|
QString revId = obj["id"].toString();
|
||||||
|
QJsonObject item = obj["item"].toObject();
|
||||||
|
|
||||||
if (itemType == "folder") {
|
if (itemType == "folder") {
|
||||||
if (operationType == "create") {
|
if (operationType == "create") {
|
||||||
Folder folder;
|
Folder folder;
|
||||||
folder.loadJsonObject(item);
|
folder.loadJsonObject(item);
|
||||||
folder.save(false);
|
folder.save(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operationType == "update") {
|
||||||
|
Folder folder;
|
||||||
|
folder.load(itemId);
|
||||||
|
folder.patchJsonObject(item);
|
||||||
|
folder.save(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operationType == "delete") {
|
||||||
|
Folder folder;
|
||||||
|
folder.load(itemId);
|
||||||
|
folder.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (operationType == "update") {
|
if (revId > maxRevId) maxRevId = revId;
|
||||||
Folder folder;
|
|
||||||
folder.load(itemId);
|
|
||||||
folder.patchJsonObject(item);
|
|
||||||
folder.save(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (operationType == "delete") {
|
|
||||||
Folder folder;
|
|
||||||
folder.load(itemId);
|
|
||||||
folder.dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (revId > maxRevId) maxRevId = revId;
|
if (maxRevId != "") {
|
||||||
|
Settings settings;
|
||||||
|
settings.setValue("lastRevId", maxRevId);
|
||||||
|
}
|
||||||
|
|
||||||
|
checkNextState();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxRevId != "") {
|
|
||||||
Settings settings;
|
|
||||||
settings.setValue("lastRevId", maxRevId);
|
|
||||||
}
|
|
||||||
|
|
||||||
checkNextState();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
qCritical() << "Invalid category" << category;
|
qCritical() << "Invalid category" << category;
|
||||||
|
@ -140,8 +140,9 @@ void WebApi::request_finished(QNetworkReply *reply) {
|
|||||||
QJsonParseError err;
|
QJsonParseError err;
|
||||||
QJsonDocument doc = QJsonDocument::fromJson(responseBodyBA, &err);
|
QJsonDocument doc = QJsonDocument::fromJson(responseBodyBA, &err);
|
||||||
if (err.error != QJsonParseError::NoError) {
|
if (err.error != QJsonParseError::NoError) {
|
||||||
qWarning() << "Could not parse JSON:" << err.errorString();
|
QString errorMessage = "Could not parse JSON: " + err.errorString() + "\n" + QString(responseBodyBA);
|
||||||
qWarning().noquote() << QString(responseBodyBA);
|
qWarning().noquote() << errorMessage;
|
||||||
|
response["error"] = errorMessage;
|
||||||
} else {
|
} else {
|
||||||
response = doc.object();
|
response = doc.object();
|
||||||
if (response.contains("error") && !response["error"].isNull()) {
|
if (response.contains("error") && !response["error"].isNull()) {
|
||||||
|
Binary file not shown.
Binary file not shown.
BIN
QtClient/dependencies/dll-debug/ssleay32.dll
Executable file
BIN
QtClient/dependencies/dll-debug/ssleay32.dll
Executable file
Binary file not shown.
@ -48,7 +48,7 @@ function saveCurlCmd($cmd) {
|
|||||||
|
|
||||||
function execRequest($method, $path, $query = array(), $data = null) {
|
function execRequest($method, $path, $query = array(), $data = null) {
|
||||||
$url = config('baseUrl') . '/' . $path;
|
$url = config('baseUrl') . '/' . $path;
|
||||||
if (!empty($_SESSION['sessionId'])) {
|
if (!empty($_SESSION['sessionId']) && !isset($query['session'])) {
|
||||||
$query['session'] = $_SESSION['sessionId'];
|
$query['session'] = $_SESSION['sessionId'];
|
||||||
}
|
}
|
||||||
if (count($query)) $url .= '?' . http_build_query($query);
|
if (count($query)) $url .= '?' . http_build_query($query);
|
||||||
@ -133,7 +133,8 @@ if (isset($_POST['delete_folder'])) $action = 'delete_folder';
|
|||||||
if (isset($_POST['update_folder'])) $action = 'update_folder';
|
if (isset($_POST['update_folder'])) $action = 'update_folder';
|
||||||
|
|
||||||
$pageParams = array(
|
$pageParams = array(
|
||||||
'title' => ucfirst($action),
|
'pageTitle' => parse_url(config('baseUrl'), PHP_URL_HOST) . ' - ' . ucfirst($action),
|
||||||
|
'headerTitle' => ucfirst($action),
|
||||||
'contentHtml' => '',
|
'contentHtml' => '',
|
||||||
'baseUrl' => config('baseUrl'),
|
'baseUrl' => config('baseUrl'),
|
||||||
);
|
);
|
||||||
@ -153,6 +154,17 @@ switch ($action) {
|
|||||||
$pageParams['contentHtml'] = renderView('folder', array('folder' => $folder));
|
$pageParams['contentHtml'] = renderView('folder', array('folder' => $folder));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'changes':
|
||||||
|
|
||||||
|
$session = execRequest('POST', 'sessions', null, array(
|
||||||
|
'email' => 'laurent@cozic.net',
|
||||||
|
'password' => '12345678',
|
||||||
|
'client_id' => 'ABCDABCDABCDABCDABCDABCDABCDABCD',
|
||||||
|
));
|
||||||
|
$changes = execRequest('GET', 'synchronizer', array('session' => $session['id']));
|
||||||
|
$pageParams['contentHtml'] = renderView('changes', array('changes' => $changes));
|
||||||
|
break;
|
||||||
|
|
||||||
case 'notes':
|
case 'notes':
|
||||||
|
|
||||||
$notes = execRequest('GET', 'folders/' . $_GET['folder_id'] . '/notes');
|
$notes = execRequest('GET', 'folders/' . $_GET['folder_id'] . '/notes');
|
||||||
|
18
debug_client/views/changes.php
Executable file
18
debug_client/views/changes.php
Executable file
@ -0,0 +1,18 @@
|
|||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<th>ID</th>
|
||||||
|
<th>Type</th>
|
||||||
|
<th>Item type</th>
|
||||||
|
<th>Item ID</th>
|
||||||
|
<th>Item</th>
|
||||||
|
</tr>
|
||||||
|
<?php for ($i = count($changes['items']) - 1; $i >= 0; $i--): $it = $changes['items'][$i]; $t = $it['type']; ?>
|
||||||
|
<tr>
|
||||||
|
<td><?php echo htmlentities($it['id']); ?></td>
|
||||||
|
<td><?php echo htmlentities($it['type']); ?></td>
|
||||||
|
<td><?php echo htmlentities($it['item_type']); ?></td>
|
||||||
|
<td><?php echo htmlentities($it['item_id']); ?></td>
|
||||||
|
<td><?php echo htmlentities($t == 'update' ? json_encode($it['item']) : ''); ?></td>
|
||||||
|
</tr>
|
||||||
|
<?php endfor; ?>
|
||||||
|
</table>
|
@ -1,12 +1,13 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title><?php echo htmlentities($title); ?></title>
|
<title><?php echo htmlentities($pageTitle); ?></title>
|
||||||
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
<link rel="stylesheet" type="text/css" href="/css/style.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<a href="/">Home</a>
|
<a href="/">Home</a>
|
||||||
<h1><?php echo htmlentities($title); ?></h1>
|
<a href="/?action=changes">Changes</a>
|
||||||
|
<h1><?php echo htmlentities($headerTitle); ?></h1>
|
||||||
<?php echo $contentHtml; ?>
|
<?php echo $contentHtml; ?>
|
||||||
<hr/>
|
<hr/>
|
||||||
<div class="debug">
|
<div class="debug">
|
||||||
|
Reference in New Issue
Block a user