accounts.cpp 18.9 KB
Newer Older
1
/*
2
 * Copyright (C) 2014-2018 CZ.NIC
3 4 5 6 7 8 9 10
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 *
 * In addition, as a special exception, the copyright holders give
 * permission to link the code of portions of this program with the
 * OpenSSL library under certain conditions as described in each
 * individual source file, and distribute linked combinations including
 * the two.
 */

#include <QSettings>
#include <QUrl>

#include "src/accounts.h"
28
#include "src/datovka_shared/log/log.h"
29
#include "src/dialogues/dialogues.h"
30
#include "src/global.h"
31
#include "src/models/accountmodel.h"
32 33 34
#include "src/net/isds_session.h"
#include "src/settings.h"
#include "src/sqlite/account_db.h"
35
#include "src/sqlite/file_db_container.h"
36 37
#include "src/sqlite/message_db_container.h"

Karel Slaný's avatar
Karel Slaný committed
38 39
Accounts::Accounts(QObject *parent)
    : QObject(parent)
40
{
41 42
}

Martin Straka's avatar
Martin Straka committed
43 44
QString Accounts::boxId(const QString &userName)
{
45 46 47 48 49 50
	if (GlobInstcs::accountDbPtr != Q_NULLPTR) {
		return GlobInstcs::accountDbPtr->dbId(userName);
	} else {
		Q_ASSERT(0);
		return QString();
	}
Martin Straka's avatar
Martin Straka committed
51 52
}

53 54
bool Accounts::boxEffectiveOVM(const QString &userName)
{
55 56 57 58 59 60
	if (GlobInstcs::accountDbPtr != Q_NULLPTR) {
		return GlobInstcs::accountDbPtr->boxEffectiveOVM(userName);
	} else {
		Q_ASSERT(0);
		return false;
	}
61 62
}

63 64
void Accounts::updateAccountCounters(const QVariant &acntModelVariant)
{
65 66 67 68 69
	if (Q_UNLIKELY(GlobInstcs::logPtr == Q_NULLPTR)) {
		Q_ASSERT(0);
		return;
	}

70
	debugFuncCall();
71 72 73 74

	AccountListModel *accountModel =
	    AccountListModel::fromVariant(acntModelVariant);
	if (accountModel == Q_NULLPTR) {
75
		/* accountModel can be NULL when app is shutdown */
76
		logWarningNL("%s", "Cannot access account model.");
77 78 79 80 81 82
		return;
	}

	loadModelCounters(accountModel);
}

83 84
void Accounts::updateNewMessageCounter(const QVariant &acntModelVariant,
    const QString &userName)
85
{
86
	if (Q_UNLIKELY((GlobInstcs::setPtr == Q_NULLPTR) ||
87
	        (GlobInstcs::logPtr == Q_NULLPTR) ||
88 89
	        (GlobInstcs::messageDbsPtr == Q_NULLPTR) ||
	        (GlobInstcs::acntMapPtr == Q_NULLPTR))) {
90 91 92 93
		Q_ASSERT(0);
		return;
	}

94 95
	debugFuncCall();

96 97 98
	AccountListModel *accountModel =
	    AccountListModel::fromVariant(acntModelVariant);
	if (accountModel == Q_NULLPTR) {
99
		/* accountModel can be NULL when app is shutdown */
100
		logWarningNL("%s", "Cannot access account model.");
101 102 103
		return;
	}

104 105
	MessageDb *msgDb = GlobInstcs::messageDbsPtr->accessMessageDb(
	    GlobInstcs::setPtr->dbsLocation, userName,
106
	    (*GlobInstcs::acntMapPtr)[userName].storeToDisk());
107
	if (msgDb == Q_NULLPTR) {
108
		logErrorNL("%s", "Cannot access message database.");
109
		return;
110 111
	}

112
	accountModel->updateCounters(userName,
113 114
	    msgDb->getNewMessageCountFromDb(MessageDb::TYPE_RECEIVED), -1,
	    msgDb->getNewMessageCountFromDb(MessageDb::TYPE_SENT), -1);
115 116
}

117
QString Accounts::fillAccountInfo(const QString &userName)
Martin Straka's avatar
Martin Straka committed
118
{
119
	debugFuncCall();
Martin Straka's avatar
Martin Straka committed
120

121
	if (GlobInstcs::accountDbPtr != Q_NULLPTR) {
122
		return GlobInstcs::accountDbPtr->accountDetailHtml(userName);
123 124 125 126
	} else {
		Q_ASSERT(0);
		return QString();
	}
Martin Straka's avatar
Martin Straka committed
127 128
}

129 130
void Accounts::getAccountData(const QString &userName)
{
131
	debugFuncCall();
132

133 134 135 136 137 138
	if (Q_UNLIKELY(GlobInstcs::acntMapPtr == Q_NULLPTR)) {
		Q_ASSERT(0);
		return;
	}

	if (!GlobInstcs::acntMapPtr->contains(userName)) {
139 140 141
		return;
	}

142
	const AcntData &acntData((*GlobInstcs::acntMapPtr)[userName]);
143 144

	emit sendAccountData(acntData.accountName(), userName,
145
	    acntData.loginMethod(), acntData.password(), acntData.isTestAccount(),
146 147 148
	    acntData.rememberPwd(), acntData.storeToDisk(), acntData.certPath());
}

149 150 151 152 153 154 155 156 157 158 159 160
/*!
 * @brief Check if username has correct length.
 *
 * @param[in] username Account login.
 * @return True if length is correct.
 */
static
bool usernameCorrectLength(const QString &userName)
{
	return userName.length() == 6;
}

Martin Straka's avatar
Martin Straka committed
161 162 163 164
bool Accounts::createAccount(const QVariant &acntModelVariant,
    const QString &loginMetod, const QString &acntName, const QString &userName,
    const QString &pwd, bool isTestAccount,  bool rememberPwd, bool storeToDisk,
    const QString &certPath)
165
{
166
	debugFuncCall();
167

168 169 170 171
	AcntData acntData;
	QString errTxt;
	QString newUserName = userName.trimmed();

172 173 174 175
	AccountListModel *accountModel =
	    AccountListModel::fromVariant(acntModelVariant);
	if (accountModel == Q_NULLPTR) {
		Q_ASSERT(0);
176
		logErrorNL("%s", "Cannot access account model.");
177 178 179
		return false;
	}

180
	if (newUserName.isEmpty() || acntName.isEmpty() || pwd.isEmpty()) {
181
		errTxt = tr("Username, password or account name has not been specified. These fields must be filled in.");
182 183 184
		goto fail;
	}

185
	if (!usernameCorrectLength(newUserName)) {
186
		errTxt = tr("Username '%1' has wrong length.").arg(newUserName);
187
		goto fail;
188 189
	}

Martin Straka's avatar
Martin Straka committed
190
	acntData.setAccountName(acntName.trimmed());
191
	acntData.setUserName(newUserName);
Martin Straka's avatar
Martin Straka committed
192 193 194 195 196 197
	acntData.setPassword(pwd.trimmed());
	acntData.setLoginMethod(loginMetod);
	acntData.setTestAccount(isTestAccount);
	acntData.setRememberPwd(rememberPwd);
	acntData.setStoreToDisk(storeToDisk);
	acntData.setCertPath(certPath);
198

199
	if (accountModel->addAccount(acntData) == AccountListModel::AA_EXISTS) {
200
		errTxt = tr("Account with username '%1' already exists.").arg(newUserName);
201
		goto fail;
202 203
	}

204
	return true;
205 206 207 208 209 210 211 212
fail:

	Dialogues::errorMessage(Dialogues::CRITICAL,
	    tr("Creating account: %1").arg(newUserName),
	    tr("Account '%1' could not be created.").arg(acntName),
	    errTxt);

	return false;
213 214
}

215
bool Accounts::updateAccount(const QVariant &acntModelVariant,
216
    const QString &loginMetod, const QString &acntName, const QString &userName,
217
    const QString &pwd, bool isTestAccount, bool rememberPwd, bool storeToDisk,
218
    const QString &certPath)
219
{
220
	debugFuncCall();
221

222 223
	if (Q_UNLIKELY((GlobInstcs::setPtr == Q_NULLPTR) ||
	        (GlobInstcs::messageDbsPtr == Q_NULLPTR) ||
224 225
	        (GlobInstcs::fileDbsPtr == Q_NULLPTR) ||
	        (GlobInstcs::acntMapPtr == Q_NULLPTR))) {
226 227 228 229
		Q_ASSERT(0);
		return false;
	}

230 231 232 233
	AccountListModel *accountModel =
	    AccountListModel::fromVariant(acntModelVariant);
	if (accountModel == Q_NULLPTR) {
		Q_ASSERT(0);
234
		logErrorNL("%s", "Cannot access account model.");
235
		return false;
236 237
	}

238
	if (acntName.isEmpty()) {
239
		Dialogues::errorMessage(Dialogues::CRITICAL,
240
		    tr("Problem while updating account"),
241
		    tr("Account name has not been specified!"),
242
		    tr("This field must be filled in."));
243
		return false;
244 245
	}

246 247
	if (!GlobInstcs::acntMapPtr->contains(userName)) {
		return false;
248 249
	}

250
	AcntData &acntData((*GlobInstcs::acntMapPtr)[userName]);
251 252 253 254 255 256 257

	/* update account map */
	acntData.setLoginMethod(loginMetod);
	acntData.setAccountName(acntName.trimmed());
	acntData.setPassword(pwd.trimmed());
	acntData.setTestAccount(isTestAccount);
	acntData.setRememberPwd(rememberPwd);
258

259
	bool oldStoreToDisk = acntData.storeToDisk();
260
	/* Reopen database if storeToDisk changed. */
261
	if (acntData.storeToDisk() != storeToDisk) {
262 263
		MessageDb *mDb = GlobInstcs::messageDbsPtr->accessMessageDb(
		    GlobInstcs::setPtr->dbsLocation, userName, oldStoreToDisk);
264
		if (mDb != Q_NULLPTR) {
265 266
			QString mDbFileName(mDb->fileName());
			/* Reopen database. */
267 268 269
			GlobInstcs::messageDbsPtr->deleteDb(mDb);
			GlobInstcs::messageDbsPtr->accessMessageDb(
			    GlobInstcs::setPtr->dbsLocation,
270 271
			    userName, storeToDisk);
			if (oldStoreToDisk) {
272 273 274 275
				/* Delete databases from storage. */
				QFile::remove(mDbFileName);
			}
		}
276 277
		FileDb *fDb = GlobInstcs::fileDbsPtr->accessFileDb(
		    GlobInstcs::setPtr->dbsLocation, userName, oldStoreToDisk);
278
		if (fDb != Q_NULLPTR) {
279 280
			QString fDbFileName(fDb->fileName());
			/* Reopen database. */
281 282 283
			GlobInstcs::fileDbsPtr->deleteDb(fDb);
			GlobInstcs::fileDbsPtr->accessFileDb(
			    GlobInstcs::setPtr->dbsLocation,
284 285
			    userName, storeToDisk);
			if (oldStoreToDisk) {
286 287 288
				/* Delete databases from storage. */
				QFile::remove(fDbFileName);
			}
289 290
		}

291
		/* Inform the model that message counters have changed. */
292
		accountModel->updateCounters(userName, 0, 0, 0, 0);
293
	}
294

295
	acntData.setStoreToDisk(storeToDisk);
296
	acntData.setCertPath(certPath);
297 298

	/* Model data have changed. */
299
	emit GlobInstcs::acntMapPtr->accountDataChanged(userName);
300 301 302 303

	/* Delete isds session context */
	emit removeIsdsCtx(userName);

304
	return true;
305 306
}

Martin Straka's avatar
Martin Straka committed
307 308
bool Accounts::removeAccount(const QVariant &acntModelVariant,
    const QString &userName, bool showDialogue)
309
{
310
	debugFuncCall();
311

312 313 314
	if (Q_UNLIKELY((GlobInstcs::setPtr == Q_NULLPTR) ||
	        (GlobInstcs::accountDbPtr == Q_NULLPTR) ||
	        (GlobInstcs::messageDbsPtr == Q_NULLPTR) ||
315 316
	        (GlobInstcs::fileDbsPtr == Q_NULLPTR) ||
	        (GlobInstcs::acntMapPtr == Q_NULLPTR))) {
317 318 319 320
		Q_ASSERT(0);
		return false;
	}

321 322 323 324
	AccountListModel *accountModel =
	    AccountListModel::fromVariant(acntModelVariant);
	if (accountModel == Q_NULLPTR) {
		Q_ASSERT(0);
325
		logErrorNL("%s", "Cannot access account model.");
326 327 328
		return false;
	}

Martin Straka's avatar
Martin Straka committed
329 330 331 332 333 334 335 336 337
	if (showDialogue) {
		int msgResponse = Dialogues::message(Dialogues::QUESTION,
		    tr("Remove account: %1").arg(userName),
		    tr("Do you want to remove the account '%1'?").arg(userName),
		    tr("Note: It will also remove all related local databases and account information."),
		    Dialogues::NO | Dialogues::YES, Dialogues::NO);
		if (msgResponse == Dialogues::NO) {
			return false;
		}
338 339
	}

340
	if (!GlobInstcs::acntMapPtr->contains(userName)) {
Martin Straka's avatar
Martin Straka committed
341 342
		return false;
	}
343

Martin Straka's avatar
Martin Straka committed
344
	/* Delete file database */
345 346
	FileDb *fDb = GlobInstcs::fileDbsPtr->accessFileDb(
	    GlobInstcs::setPtr->dbsLocation, userName,
347
	    (*GlobInstcs::acntMapPtr)[userName].storeToDisk());
Martin Straka's avatar
Martin Straka committed
348
	if (fDb == Q_NULLPTR) {
349
		logErrorNL("%s", "Cannot access file database.");
Martin Straka's avatar
Martin Straka committed
350 351
		return false;
	}
352
	if (!GlobInstcs::fileDbsPtr->deleteDb(fDb)) {
353
		logErrorNL("%s", "Could not delete file database.");
354
		return false;
355
	}
356

Martin Straka's avatar
Martin Straka committed
357
	/* Delete message database */
358 359
	MessageDb *msgDb = GlobInstcs::messageDbsPtr->accessMessageDb(
	    GlobInstcs::setPtr->dbsLocation, userName,
360
	    (*GlobInstcs::acntMapPtr)[userName].storeToDisk());
Martin Straka's avatar
Martin Straka committed
361
	if (msgDb == Q_NULLPTR) {
362
		logErrorNL("%s", "Cannot access message database.");
Martin Straka's avatar
Martin Straka committed
363 364
		return false;
	}
365
	if (!GlobInstcs::messageDbsPtr->deleteDb(msgDb)) {
366
		logErrorNL("%s", "Could not delete message database.");
Martin Straka's avatar
Martin Straka committed
367 368
		return false;
	}
369

Martin Straka's avatar
Martin Straka committed
370
	/* Delete account info from account database */
371
	if (!GlobInstcs::accountDbPtr->deleteAccountInfoFromDb(userName)) {
372
		logErrorNL("%s", "Could not delete account info.");
Martin Straka's avatar
Martin Straka committed
373 374
		return false;
	}
375

Martin Straka's avatar
Martin Straka committed
376
	/* Delete user info from account database */
377
	if (!GlobInstcs::accountDbPtr->deleteUserInfoFromDb(userName)) {
378
		logErrorNL("%s", "Could not delete user info.");
Martin Straka's avatar
Martin Straka committed
379
		return false;
380
	}
Martin Straka's avatar
Martin Straka committed
381 382 383 384 385 386 387 388

	/* Delete isds session context */
	emit removeIsdsCtx(userName);

	/* Delete account from settings */
	accountModel->deleteAccount(userName);

	return true;
389 390
}

391
void Accounts::loadModelCounters(AccountListModel *accountModel)
392
{
393
	debugFuncCall();
394

395
	if (Q_UNLIKELY((GlobInstcs::setPtr == Q_NULLPTR) ||
396 397
	        (GlobInstcs::messageDbsPtr == Q_NULLPTR) ||
	        (GlobInstcs::acntMapPtr == Q_NULLPTR))) {
398 399 400 401
		Q_ASSERT(0);
		return;
	}

402 403
	if (accountModel == Q_NULLPTR) {
		Q_ASSERT(0);
404
		logErrorNL("%s", "Cannot access account model.");
405 406
		return;
	}
407

408 409 410
	for (int row = 0; row < accountModel->rowCount(); ++row) {
		const QString userName(accountModel->userName(
		    accountModel->index(row, 0)));
411 412 413 414 415
		if (userName.isEmpty()) {
			Q_ASSERT(0);
			continue;
		}

416 417
		MessageDb *msgDb = GlobInstcs::messageDbsPtr->accessMessageDb(
		    GlobInstcs::setPtr->dbsLocation, userName,
418
		    (*GlobInstcs::acntMapPtr)[userName].storeToDisk());
419
		if (msgDb == Q_NULLPTR) {
420
			logWarningNL("Cannot open message database for '%s'.",
421 422 423 424
			    userName.toUtf8().constData());
			continue;
		}

425
		accountModel->updateCounters(userName,
426 427 428 429
		    msgDb->getNewMessageCountFromDb(MessageDb::TYPE_RECEIVED),
		    msgDb->getMessageCountFromDb(MessageDb::TYPE_RECEIVED),
		    msgDb->getNewMessageCountFromDb(MessageDb::TYPE_SENT),
		    msgDb->getMessageCountFromDb(MessageDb::TYPE_SENT));
430 431
	}
}
432

433 434 435 436
bool Accounts::prepareChangeUserName(const QVariant &acntModelVariant,
    const QString &loginMetod, const QString &acntName, const QString &newUserName,
    const QString &pwd, bool isTestAccount,  bool rememberPwd, bool storeToDisk,
    const QString &certPath, const QString &oldUserName)
437
{
Martin Straka's avatar
Martin Straka committed
438
	debugFuncCall();
439 440

	/* Show confirm dialogue about use name changing */
441
	int msgResponse = Dialogues::message(Dialogues::QUESTION,
442
	    tr("Change user name: %1").arg(oldUserName),
443 444
	    tr("Do you want to change the username from '%1' to '%2' for the account '%3'?")
	        .arg(oldUserName).arg(newUserName).arg(acntName),
445 446 447 448 449 450
	    tr("Note: It will also change all related local database names and account information."),
	    Dialogues::NO | Dialogues::YES, Dialogues::NO);
	if (msgResponse == Dialogues::NO) {
		return false;
	}

451 452 453 454 455
	return createAccount(acntModelVariant, loginMetod, acntName,
	    newUserName, pwd, isTestAccount, rememberPwd, storeToDisk,
	    certPath);
}

456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473
/*!
 * @brief Check whether the box identifier matches the username of a known account.
 *
 * @param[in] dbId Data box ID.
 * @param[in] username User name of already existing account.
 * @return True if username corresponds to data box id, false on any error.
 */
static
bool boxMatchesUser(const QString &dbId, const QString &username)
{
	if (Q_UNLIKELY(dbId.isEmpty() || username.isEmpty())) {
		Q_ASSERT(0);
		return false;
	}

	return dbId == GlobInstcs::accountDbPtr->dbId(username);
}

474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491
/*!
 * @brief Change file database name to new username.
 *
 * @param[in]  oldUserName Original user name of account.
 * @param[in]  newUserName New user name identifying account.
 * @param[in]  storeToDisk True if database store to local storage.
 * @param[out] errTxt Error description.
 * @return True on success.
 */
static
bool changeFileDbName(const QString &oldUserName,
    const QString &newUserName, bool storeToDisk, QString &errTxt)
{
	debugFuncCall();

	FileDb *fDb = GlobInstcs::fileDbsPtr->accessFileDb(
	    GlobInstcs::setPtr->dbsLocation, oldUserName, storeToDisk);
	if (Q_UNLIKELY(fDb == Q_NULLPTR)) {
492
		errTxt = Accounts::tr("Cannot access file database for the username '%1'.")
493 494 495 496 497 498 499 500
		    .arg(oldUserName);
		return false;
	}

	/* Rename file database */
	QString currentDbFileName = fDb->fileName();
	currentDbFileName.replace(oldUserName, newUserName);
	if (!fDb->moveDb(currentDbFileName)) {
501
		errTxt = Accounts::tr("Cannot change file database to username '%1'.")
502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526
		    .arg(newUserName);
		return false;
	}

	return true;
}

/*!
 * @brief Change message database name to new user name.
 *
 * @param[in] oldUserName Original user name of account.
 * @param[in] newUserName New user name identifying account.
 * @param[in] storeToDisk True if database store to local storage.
 * @param[out] errTxt Error description.
 * @return True if success.
 */
static
bool changeMessageDbName(const QString &oldUserName,
    const QString &newUserName, bool storeToDisk, QString &errTxt)
{
	debugFuncCall();

	MessageDb *msgDb = GlobInstcs::messageDbsPtr->accessMessageDb(
	    GlobInstcs::setPtr->dbsLocation, oldUserName, storeToDisk);
	if (Q_UNLIKELY(msgDb == Q_NULLPTR)) {
527
		errTxt = Accounts::tr("Cannot access message database for username '%1'.")
528 529 530 531 532 533 534 535
		    .arg(oldUserName);
		return false;
	}

	/* Rename message database */
	QString currentDbFileName = msgDb->fileName();
	currentDbFileName.replace(oldUserName, newUserName);
	if (!msgDb->moveDb(currentDbFileName)) {
536
		errTxt = Accounts::tr("Cannot change message database to username '%1'.")
537 538 539 540 541 542 543
		    .arg(newUserName);
		return false;
	}

	return true;
}

544 545 546 547
bool Accounts::changeAccountUserName(const QVariant &acntModelVariant,
    const QString &acntName, const QString &newUserName, bool storeToDisk,
    const QString &oldUserName, const QString &newDbId)
{
Martin Straka's avatar
Martin Straka committed
548 549
	debugFuncCall();

550 551 552 553 554 555 556 557 558 559
	QString errTxt;
	AccountListModel *accountModel = Q_NULLPTR;

	if (Q_UNLIKELY((GlobInstcs::acntMapPtr == Q_NULLPTR) ||
	        (GlobInstcs::fileDbsPtr == Q_NULLPTR) ||
	        (GlobInstcs::messageDbsPtr == Q_NULLPTR))) {
		Q_ASSERT(0);
		goto exit;
	}

560
	/* Get account model */
561
	accountModel = AccountListModel::fromVariant(acntModelVariant);
562
	if (Q_UNLIKELY(accountModel == Q_NULLPTR)) {
563 564
		Q_ASSERT(0);
		logErrorNL("%s", "Cannot access account model.");
565
		goto exit;
566 567
	}

568 569
	/* Check if new user name corresponds with data box id. */
	if (!boxMatchesUser(newDbId, oldUserName)) {
570 571
		errTxt = tr("New data box identifier '%1' does not correspond with the old username '%2'.")
		    .arg(newDbId).arg(oldUserName);
572
		goto fail;
573 574
	}

575 576
	/* First: Change user name in the account database (user_info, account_info) */
	if (!GlobInstcs::accountDbPtr->changeUserName(oldUserName, newUserName)) {
577 578
		errTxt = tr("Cannot change username '%1' in the account database.")
		    .arg(newUserName);
579
		goto fail;
580 581
	}

582
	/* Second: Change file database name or rollback in an error */
583 584
	if (!changeFileDbName(oldUserName, newUserName, storeToDisk, errTxt)) {
		goto rollbackAccountChanges;
585 586 587
	}

	/* Third: Change message database name or rollback in an error */
588 589
	if (!changeMessageDbName(oldUserName, newUserName, storeToDisk, errTxt)) {
		goto rollbackFilesChanges;
590 591
	}

Martin Straka's avatar
Martin Straka committed
592 593
	/* Last: Delete original/old account from model and settings */
	deleteAccountFromModel(accountModel, oldUserName);
594

595
	logInfoNL("Username has been changed to '%s'.",
596 597
	     newUserName.toUtf8().constData());

598
	Dialogues::errorMessage(Dialogues::INFORMATION,
599 600
	    tr("Change username: %1").arg(oldUserName),
	    tr("A new username '%1' for the account '%2' has been set.")
601
	        .arg(newUserName).arg(acntName),
602 603
	    tr("Account will use the new settings."));

604 605
	return true;

606
rollbackFilesChanges:
607

608 609
	/* Change back file database name */
	if (changeFileDbName(newUserName, oldUserName, storeToDisk, errTxt)) {
610
		logErrorNL("Cannot restore file database name '%s'.",
611
		    oldUserName.toUtf8().constData());
612 613
	}

614
rollbackAccountChanges:
615

616
	/* Change back original user name in the account database. */
617
	if (!GlobInstcs::accountDbPtr->changeUserName(newUserName, oldUserName)) {
618 619
		logErrorNL("%s",
		    "Cannot restore user name in the account database.");
620 621
	}

622
fail:
623
	/* Show error dialogue with message what happened */
624
	Dialogues::errorMessage(Dialogues::CRITICAL,
625 626
	    tr("Username problem: %1").arg(oldUserName),
	    tr("The new username '%1' for account '%2' has not been set!")
627 628 629
	        .arg(newUserName).arg(acntName),
	    errTxt + QStringLiteral(" ") +
	    tr("Account will use the original settings."));
630

631 632
exit:
	/* Remove new account */
Martin Straka's avatar
Martin Straka committed
633
	deleteAccountFromModel(accountModel, newUserName);
634

635 636
	return false;
}
637

Martin Straka's avatar
Martin Straka committed
638 639 640
void Accounts::deleteAccountFromModel(AccountListModel *accountModel,
    const QString &userName)
{
641 642 643 644 645
	if (Q_UNLIKELY((accountModel == Q_NULLPTR) || userName.isEmpty())) {
		Q_ASSERT(0);
		return;
	}

Martin Straka's avatar
Martin Straka committed
646 647
	/* Remove old account from model */
	accountModel->deleteAccount(userName);
648
	/* Delete ISDS session context of old account  */
Martin Straka's avatar
Martin Straka committed
649 650 651 652
	emit removeIsdsCtx(userName);
	/* Load message counters of all accounts */
	loadModelCounters(accountModel);
}