32 #define INIT_ERROR() ErrorMonitor errorMonitor(this)
33 #define RETURN_IF_NO_SECRETS_DB(retval) \
34 if (!isSecretsDBOpen()) { \
35 TRACE() << "Secrets DB is not available"; \
36 _lastError = noSecretsDB; return retval; \
39 #define S(s) QLatin1String(s)
43 static const QString driver = QLatin1String(
"QSQLITE");
47 QString &password)
const
49 QHash<quint32, AuthCache>::const_iterator i;
52 if (i == m_cache.end())
return false;
54 username = i->m_username;
55 password = i->m_password;
61 return m_cache.value(
id).m_blobData.value(method);
65 const QString &username,
66 const QString &password,
72 credentials.m_username = username;
73 credentials.m_password = password;
74 credentials.m_storePassword = storePassword;
78 const QVariantMap &data)
83 credentials.m_blobData[method] = data;
89 if (m_cache.isEmpty())
return;
91 TRACE() <<
"Storing cached credentials into permanent storage";
93 QHash<quint32, AuthCache>::const_iterator i;
94 for (i = m_cache.constBegin();
95 i != m_cache.constEnd();
101 QString password = cache.m_storePassword ?
102 cache.m_password : QString();
103 if (!cache.m_username.isEmpty() || !password.isEmpty()) {
104 secretsStorage->updateCredentials(
id,
110 QHash<quint32, QVariantMap>::const_iterator j;
111 for (j = cache.m_blobData.constBegin();
112 j != cache.m_blobData.constEnd();
114 quint32 method = j.key();
115 secretsStorage->storeData(
id, method, j.value());
126 const QString &connectionName,
128 m_lastError(
SignOn::CredentialsDBError()),
130 m_database(QSqlDatabase::addDatabase(driver, connectionName))
134 TRACE() <<
"DATABASE NAME [" << databaseName <<
"]";
150 TRACE() <<
"Database connection succeeded.";
153 TRACE() <<
"Creating SQL table structure...";
159 <<
".This could lead to data loss.";
161 TRACE() <<
"SQL table structure already created...";
163 QSqlQuery q =
exec(
S(
"PRAGMA user_version"));
164 int oldVersion = q.first() ? q.value(0).toInt() : 0;
174 TRACE() <<
"Update DB from version " << version <<
" to " <<
m_version;
175 exec(QString::fromLatin1(
"PRAGMA user_version = %1").arg(m_version));
182 TRACE() <<
"Could not open database connection.\n";
207 TRACE() <<
"Rollback failed, db data integrity could be compromised.";
214 if (!query.prepare(queryStr))
215 TRACE() <<
"Query prepare warning: " << query.lastQuery();
218 TRACE() <<
"Query exec error: " << query.lastQuery();
231 TRACE() <<
"Query exec error: " << query.lastQuery();
245 TRACE() <<
"Could not start transaction";
250 foreach (QString queryStr, queryList) {
251 TRACE() << QString::fromLatin1(
"TRANSACT Query [%1]").arg(queryStr);
252 QSqlQuery query =
exec(queryStr);
261 TRACE() <<
"Commit SUCCEEDED.";
267 TRACE() <<
"Transactional exec FAILED!";
278 if (sqlError.isValid()) {
279 if (sqlError.type() == QSqlError::ConnectionError) {
280 m_lastError.setType(SignOn::CredentialsDBError::ConnectionError);
282 m_lastError.setType(SignOn::CredentialsDBError::StatementError);
284 m_lastError.setText(sqlError.text());
292 if (!error.isValid())
293 return QLatin1String(
"SQL Error invalid.");
296 QTextStream stream(&text);
297 stream <<
"SQL error description:";
298 stream <<
"\n\tType: ";
301 switch (error.type()) {
303 case QSqlError::ConnectionError: errType =
"ConnectionError";
break;
304 case QSqlError::StatementError: errType =
"StatementError";
break;
305 case QSqlError::TransactionError: errType =
"TransactionError";
break;
308 default: errType =
"UnknownError";
311 stream <<
"\n\tDatabase text: " << error.databaseText();
312 stream <<
"\n\tDriver text: " << error.driverText();
313 stream <<
"\n\tNumber: " << error.number();
321 if (!query.prepare(query_str))
322 TRACE() <<
"Query prepare warning: " << query.lastQuery();
329 QSqlQuery query =
exec(q);
331 while (query.next()) {
332 list.append(query.value(0).toString());
338 QStringList MetaDataDB::tableUpdates2()
340 QStringList tableUpdates = QStringList()
341 << QString::fromLatin1(
343 "(rowid INTEGER PRIMARY KEY AUTOINCREMENT,"
344 "identity_id INTEGER CONSTRAINT fk_identity_id REFERENCES CREDENTIALS(id) ON DELETE CASCADE,"
345 "token_id INTEGER CONSTRAINT fk_token_id REFERENCES TOKENS(id) ON DELETE CASCADE)")
347 << QString::fromLatin1(
349 "CREATE TRIGGER fki_OWNER_token_id_TOKENS_id "
350 "BEFORE INSERT ON [OWNER] "
351 "FOR EACH ROW BEGIN "
352 " SELECT RAISE(ROLLBACK, 'insert on table OWNER violates foreign key constraint fki_OWNER_token_id_TOKENS_id') "
353 " WHERE NEW.token_id IS NOT NULL AND (SELECT id FROM TOKENS WHERE id = NEW.token_id) IS NULL; "
356 << QString::fromLatin1(
358 "CREATE TRIGGER fku_OWNER_token_id_TOKENS_id "
359 "BEFORE UPDATE ON [OWNER] "
360 "FOR EACH ROW BEGIN "
361 " SELECT RAISE(ROLLBACK, 'update on table OWNER violates foreign key constraint fku_OWNER_token_id_TOKENS_id') "
362 " WHERE NEW.token_id IS NOT NULL AND (SELECT id FROM TOKENS WHERE id = NEW.token_id) IS NULL; "
365 << QString::fromLatin1(
367 "CREATE TRIGGER fkdc_OWNER_token_id_TOKENS_id "
368 "BEFORE DELETE ON TOKENS "
369 "FOR EACH ROW BEGIN "
370 " DELETE FROM OWNER WHERE OWNER.token_id = OLD.id; "
380 QStringList createTableQuery = QStringList()
381 << QString::fromLatin1(
382 "CREATE TABLE CREDENTIALS"
383 "(id INTEGER PRIMARY KEY AUTOINCREMENT,"
388 << QString::fromLatin1(
389 "CREATE TABLE METHODS"
390 "(id INTEGER PRIMARY KEY AUTOINCREMENT,"
391 "method TEXT UNIQUE)")
392 << QString::fromLatin1(
393 "CREATE TABLE MECHANISMS"
394 "(id INTEGER PRIMARY KEY AUTOINCREMENT,"
395 "mechanism TEXT UNIQUE)")
396 << QString::fromLatin1(
397 "CREATE TABLE TOKENS"
398 "(id INTEGER PRIMARY KEY AUTOINCREMENT,"
399 "token TEXT UNIQUE)")
400 << QString::fromLatin1(
401 "CREATE TABLE REALMS"
402 "(identity_id INTEGER CONSTRAINT fk_identity_id REFERENCES CREDENTIALS(id) ON DELETE CASCADE,"
405 "PRIMARY KEY (identity_id, realm, hostname))")
406 << QString::fromLatin1(
408 "(rowid INTEGER PRIMARY KEY AUTOINCREMENT,"
409 "identity_id INTEGER CONSTRAINT fk_identity_id REFERENCES CREDENTIALS(id) ON DELETE CASCADE,"
410 "method_id INTEGER CONSTRAINT fk_method_id REFERENCES METHODS(id) ON DELETE CASCADE,"
411 "mechanism_id INTEGER CONSTRAINT fk_mechanism_id REFERENCES MECHANISMS(id) ON DELETE CASCADE,"
412 "token_id INTEGER CONSTRAINT fk_token_id REFERENCES TOKENS(id) ON DELETE CASCADE)")
413 << QString::fromLatin1(
415 "(identity_id INTEGER CONSTRAINT fk_identity_id REFERENCES CREDENTIALS(id) ON DELETE CASCADE,"
416 "token_id INTEGER CONSTRAINT fk_token_id REFERENCES TOKENS(id) ON DELETE CASCADE,"
418 "PRIMARY KEY (identity_id, token_id, ref))")
425 << QString::fromLatin1(
427 "CREATE TRIGGER fki_REALMS_identity_id_CREDENTIALS_id "
428 "BEFORE INSERT ON [REALMS] "
429 "FOR EACH ROW BEGIN "
430 " SELECT RAISE(ROLLBACK, 'insert on table REALMS violates foreign key constraint fki_REALMS_identity_id_CREDENTIALS_id') "
431 " WHERE NEW.identity_id IS NOT NULL AND (SELECT id FROM CREDENTIALS WHERE id = NEW.identity_id) IS NULL; "
434 << QString::fromLatin1(
436 "CREATE TRIGGER fku_REALMS_identity_id_CREDENTIALS_id "
437 "BEFORE UPDATE ON [REALMS] "
438 "FOR EACH ROW BEGIN "
439 " SELECT RAISE(ROLLBACK, 'update on table REALMS violates foreign key constraint fku_REALMS_identity_id_CREDENTIALS_id') "
440 " WHERE NEW.identity_id IS NOT NULL AND (SELECT id FROM CREDENTIALS WHERE id = NEW.identity_id) IS NULL; "
443 << QString::fromLatin1(
445 "CREATE TRIGGER fkdc_REALMS_identity_id_CREDENTIALS_id "
446 "BEFORE DELETE ON CREDENTIALS "
447 "FOR EACH ROW BEGIN "
448 " DELETE FROM REALMS WHERE REALMS.identity_id = OLD.id; "
451 << QString::fromLatin1(
453 "CREATE TRIGGER fki_ACL_identity_id_CREDENTIALS_id "
454 "BEFORE INSERT ON [ACL] "
455 "FOR EACH ROW BEGIN "
456 " SELECT RAISE(ROLLBACK, 'insert on table ACL violates foreign key constraint fki_ACL_identity_id_CREDENTIALS_id') "
457 " WHERE NEW.identity_id IS NOT NULL AND (SELECT id FROM CREDENTIALS WHERE id = NEW.identity_id) IS NULL; "
460 << QString::fromLatin1(
462 "CREATE TRIGGER fku_ACL_identity_id_CREDENTIALS_id "
463 "BEFORE UPDATE ON [ACL] "
464 "FOR EACH ROW BEGIN "
465 " SELECT RAISE(ROLLBACK, 'update on table ACL violates foreign key constraint fku_ACL_identity_id_CREDENTIALS_id') "
466 " WHERE NEW.identity_id IS NOT NULL AND (SELECT id FROM CREDENTIALS WHERE id = NEW.identity_id) IS NULL; "
469 << QString::fromLatin1(
471 "CREATE TRIGGER fkdc_ACL_identity_id_CREDENTIALS_id "
472 "BEFORE DELETE ON CREDENTIALS "
473 "FOR EACH ROW BEGIN "
474 " DELETE FROM ACL WHERE ACL.identity_id = OLD.id; "
477 << QString::fromLatin1(
479 "CREATE TRIGGER fki_ACL_method_id_METHODS_id "
480 "BEFORE INSERT ON [ACL] "
481 "FOR EACH ROW BEGIN "
482 " SELECT RAISE(ROLLBACK, 'insert on table ACL violates foreign key constraint fki_ACL_method_id_METHODS_id') "
483 " WHERE NEW.method_id IS NOT NULL AND (SELECT id FROM METHODS WHERE id = NEW.method_id) IS NULL; "
486 << QString::fromLatin1(
488 "CREATE TRIGGER fku_ACL_method_id_METHODS_id "
489 "BEFORE UPDATE ON [ACL] "
490 "FOR EACH ROW BEGIN "
491 " SELECT RAISE(ROLLBACK, 'update on table ACL violates foreign key constraint fku_ACL_method_id_METHODS_id') "
492 " WHERE NEW.method_id IS NOT NULL AND (SELECT id FROM METHODS WHERE id = NEW.method_id) IS NULL; "
495 << QString::fromLatin1(
497 "CREATE TRIGGER fkdc_ACL_method_id_METHODS_id "
498 "BEFORE DELETE ON METHODS "
499 "FOR EACH ROW BEGIN "
500 " DELETE FROM ACL WHERE ACL.method_id = OLD.id; "
503 << QString::fromLatin1(
505 "CREATE TRIGGER fki_ACL_mechanism_id_MECHANISMS_id "
506 "BEFORE INSERT ON [ACL] "
507 "FOR EACH ROW BEGIN "
508 " SELECT RAISE(ROLLBACK, 'insert on table ACL violates foreign key constraint fki_ACL_mechanism_id_MECHANISMS_id') "
509 " WHERE NEW.mechanism_id IS NOT NULL AND (SELECT id FROM MECHANISMS WHERE id = NEW.mechanism_id) IS NULL; "
512 << QString::fromLatin1(
514 "CREATE TRIGGER fku_ACL_mechanism_id_MECHANISMS_id "
515 "BEFORE UPDATE ON [ACL] "
516 "FOR EACH ROW BEGIN "
517 " SELECT RAISE(ROLLBACK, 'update on table ACL violates foreign key constraint fku_ACL_mechanism_id_MECHANISMS_id') "
518 " WHERE NEW.mechanism_id IS NOT NULL AND (SELECT id FROM MECHANISMS WHERE id = NEW.mechanism_id) IS NULL; "
521 << QString::fromLatin1(
523 "CREATE TRIGGER fkdc_ACL_mechanism_id_MECHANISMS_id "
524 "BEFORE DELETE ON MECHANISMS "
525 "FOR EACH ROW BEGIN "
526 " DELETE FROM ACL WHERE ACL.mechanism_id = OLD.id; "
529 << QString::fromLatin1(
531 "CREATE TRIGGER fki_ACL_token_id_TOKENS_id "
532 "BEFORE INSERT ON [ACL] "
533 "FOR EACH ROW BEGIN "
534 " SELECT RAISE(ROLLBACK, 'insert on table ACL violates foreign key constraint fki_ACL_token_id_TOKENS_id') "
535 " WHERE NEW.token_id IS NOT NULL AND (SELECT id FROM TOKENS WHERE id = NEW.token_id) IS NULL; "
538 << QString::fromLatin1(
540 "CREATE TRIGGER fku_ACL_token_id_TOKENS_id "
541 "BEFORE UPDATE ON [ACL] "
542 "FOR EACH ROW BEGIN "
543 " SELECT RAISE(ROLLBACK, 'update on table ACL violates foreign key constraint fku_ACL_token_id_TOKENS_id') "
544 " WHERE NEW.token_id IS NOT NULL AND (SELECT id FROM TOKENS WHERE id = NEW.token_id) IS NULL; "
547 << QString::fromLatin1(
549 "CREATE TRIGGER fkdc_ACL_token_id_TOKENS_id "
550 "BEFORE DELETE ON TOKENS "
551 "FOR EACH ROW BEGIN "
552 " DELETE FROM ACL WHERE ACL.token_id = OLD.id; "
555 << QString::fromLatin1(
557 "CREATE TRIGGER fki_REFS_identity_id_CREDENTIALS_id "
558 "BEFORE INSERT ON [REFS] "
559 "FOR EACH ROW BEGIN "
560 " SELECT RAISE(ROLLBACK, 'insert on table REFS violates foreign key constraint fki_REFS_identity_id_CREDENTIALS_id') "
561 " WHERE NEW.identity_id IS NOT NULL AND (SELECT id FROM CREDENTIALS WHERE id = NEW.identity_id) IS NULL; "
564 << QString::fromLatin1(
566 "CREATE TRIGGER fku_REFS_identity_id_CREDENTIALS_id "
567 "BEFORE UPDATE ON [REFS] "
568 "FOR EACH ROW BEGIN "
569 " SELECT RAISE(ROLLBACK, 'update on table REFS violates foreign key constraint fku_REFS_identity_id_CREDENTIALS_id') "
570 " WHERE NEW.identity_id IS NOT NULL AND (SELECT id FROM CREDENTIALS WHERE id = NEW.identity_id) IS NULL; "
573 << QString::fromLatin1(
575 "CREATE TRIGGER fkdc_REFS_identity_id_CREDENTIALS_id "
576 "BEFORE DELETE ON CREDENTIALS "
577 "FOR EACH ROW BEGIN "
578 " DELETE FROM REFS WHERE REFS.identity_id = OLD.id; "
581 << QString::fromLatin1(
583 "CREATE TRIGGER fki_REFS_token_id_TOKENS_id "
584 "BEFORE INSERT ON [REFS] "
585 "FOR EACH ROW BEGIN "
586 " SELECT RAISE(ROLLBACK, 'insert on table REFS violates foreign key constraint fki_REFS_token_id_TOKENS_id') "
587 " WHERE NEW.token_id IS NOT NULL AND (SELECT id FROM TOKENS WHERE id = NEW.token_id) IS NULL; "
590 << QString::fromLatin1(
592 "CREATE TRIGGER fku_REFS_token_id_TOKENS_id "
593 "BEFORE UPDATE ON [REFS] "
594 "FOR EACH ROW BEGIN "
595 " SELECT RAISE(ROLLBACK, 'update on table REFS violates foreign key constraint fku_REFS_token_id_TOKENS_id') "
596 " WHERE NEW.token_id IS NOT NULL AND (SELECT id FROM TOKENS WHERE id = NEW.token_id) IS NULL; "
599 << QString::fromLatin1(
601 "CREATE TRIGGER fkdc_REFS_token_id_TOKENS_id "
602 "BEFORE DELETE ON TOKENS "
603 "FOR EACH ROW BEGIN "
604 " DELETE FROM REFS WHERE REFS.token_id = OLD.id; "
611 createTableQuery << tableUpdates2();
613 foreach (QString createTable, createTableQuery) {
614 QSqlQuery query =
exec(createTable);
616 TRACE() <<
"Error occurred while creating the database.";
622 TRACE() <<
"Creation successful";
633 TRACE() <<
"Upgrading from version < 1 not supported. Clearing DB";
637 QFile::remove(fileName);
638 m_database = QSqlDatabase(QSqlDatabase::addDatabase(driver,
650 QStringList createTableQuery = tableUpdates2();
651 foreach (QString createTable, createTableQuery) {
652 QSqlQuery query =
exec(createTable);
654 TRACE() <<
"Error occurred while inseting new tables.";
660 TRACE() <<
"Table insert successful";
663 QSqlQuery ownerInsert =
exec(
S(
"INSERT OR IGNORE INTO OWNER "
664 "(identity_id, token_id) "
665 " SELECT identity_id, token_id FROM ACL"));
667 BLAME() <<
"Table copy failed.";
681 if (securityToken.isEmpty()) {
683 QString::fromLatin1(
"SELECT DISTINCT METHODS.method FROM "
684 "( ACL JOIN METHODS ON ACL.method_id = METHODS.id ) "
685 "WHERE ACL.identity_id = '%1'").arg(
id)
690 q.prepare(
S(
"SELECT DISTINCT METHODS.method FROM "
691 "( ACL JOIN METHODS ON ACL.method_id = METHODS.id) "
692 "WHERE ACL.identity_id = :id AND ACL.token_id = "
693 "(SELECT id FROM TOKENS where token = :token)"));
694 q.bindValue(
S(
":id"),
id);
695 q.bindValue(
S(
":token"), securityToken);
703 TRACE() <<
"method:" << method;
706 q.prepare(
S(
"SELECT id FROM METHODS WHERE method = :method"));
707 q.bindValue(
S(
":method"), method);
710 TRACE() <<
"No result or invalid method query.";
714 return q.value(0).toUInt();
721 query_str = QString::fromLatin1(
722 "SELECT caption, username, flags, type "
723 "FROM credentials WHERE id = %1").arg(
id);
724 QSqlQuery query =
exec(query_str);
726 if (!query.first()) {
727 TRACE() <<
"No result or invalid credentials query.";
731 QString caption = query.value(0).toString();
732 QString
username = query.value(1).toString();
733 int flags = query.value(2).toInt();
737 if (isUserNameSecret) username = QString();
738 int type = query.value(3).toInt();
742 QString::fromLatin1(
"SELECT realm FROM REALMS "
743 "WHERE identity_id = %1").arg(
id));
746 QString::fromLatin1(
"SELECT token FROM TOKENS "
748 "(SELECT token_id FROM OWNER WHERE identity_id = '%1' )")
751 query_str = QString::fromLatin1(
"SELECT token FROM TOKENS "
753 "(SELECT token_id FROM ACL WHERE identity_id = '%1' )")
755 query =
exec(query_str);
756 QStringList securityTokens;
757 while (query.next()) {
758 securityTokens.append(query.value(0).toString());
762 query_str = QString::fromLatin1(
763 "SELECT DISTINCT ACL.method_id, METHODS.method FROM "
764 "( ACL JOIN METHODS ON ACL.method_id = METHODS.id ) "
765 "WHERE ACL.identity_id = '%1'").arg(
id);
766 query =
exec(query_str);
767 while (query.next()) {
769 QString::fromLatin1(
"SELECT DISTINCT MECHANISMS.mechanism FROM "
770 "( MECHANISMS JOIN ACL "
771 "ON ACL.mechanism_id = MECHANISMS.id ) "
772 "WHERE ACL.method_id = '%1' AND ACL.identity_id = '%2' ")
773 .arg(query.value(0).toInt()).arg(
id));
774 methods.insert(query.value(1).toString(), mechanisms);
783 if (!isUserNameSecret)
805 QString queryStr(QString::fromLatin1(
"SELECT id FROM credentials"));
809 queryStr += QString::fromLatin1(
" ORDER BY id");
811 QSqlQuery query =
exec(queryStr);
813 TRACE() <<
"Error occurred while fetching credentials from database.";
817 while (query.next()) {
831 TRACE() <<
"Could not start transaction. Error inserting credentials.";
835 quint32
id = updateCredentials(info);
844 if (!updateRealms(
id, info.
realms(), info.
isNew())) {
845 TRACE() <<
"Error in updating realms";
853 tokenInsert.prepare(
S(
"INSERT OR IGNORE INTO TOKENS (token) "
854 "VALUES ( :token )"));
855 tokenInsert.bindValue(
S(
":token"), token);
859 foreach (QString token, info.
ownerList()) {
860 if (!token.isEmpty()) {
862 tokenInsert.prepare(
S(
"INSERT OR IGNORE INTO TOKENS (token) "
863 "VALUES ( :token )"));
864 tokenInsert.bindValue(
S(
":token"), token);
871 QString queryStr = QString::fromLatin1(
872 "DELETE FROM ACL WHERE "
873 "identity_id = '%1'")
875 QSqlQuery insertQuery =
exec(queryStr);
878 queryStr = QString::fromLatin1(
879 "DELETE FROM OWNER WHERE "
880 "identity_id = '%1'")
882 insertQuery =
exec(queryStr);
887 QMapIterator<QString, QStringList> it(info.
methods());
888 while (it.hasNext()) {
892 foreach (QString mech, it.value()) {
894 aclInsert.prepare(
S(
"INSERT OR REPLACE INTO ACL "
895 "(identity_id, method_id, mechanism_id, token_id) "
897 "( SELECT id FROM METHODS WHERE method = :method ),"
898 "( SELECT id FROM MECHANISMS WHERE mechanism= :mech ), "
899 "( SELECT id FROM TOKENS WHERE token = :token ))"));
900 aclInsert.bindValue(
S(
":id"),
id);
901 aclInsert.bindValue(
S(
":method"), it.key());
902 aclInsert.bindValue(
S(
":mech"), mech);
903 aclInsert.bindValue(
S(
":token"), token);
907 if (it.value().isEmpty()) {
909 aclInsert.prepare(
S(
"INSERT OR REPLACE INTO ACL (identity_id, method_id, token_id) "
911 "( SELECT id FROM METHODS WHERE method = :method ),"
912 "( SELECT id FROM TOKENS WHERE token = :token ))"));
913 aclInsert.bindValue(
S(
":id"),
id);
914 aclInsert.bindValue(
S(
":method"), it.key());
915 aclInsert.bindValue(
S(
":token"), token);
920 foreach (QString mech, it.value()) {
922 aclInsert.prepare(
S(
"INSERT OR REPLACE INTO ACL "
923 "(identity_id, method_id, mechanism_id) "
925 "( SELECT id FROM METHODS WHERE method = :method ),"
926 "( SELECT id FROM MECHANISMS WHERE mechanism= :mech )"
928 aclInsert.bindValue(
S(
":id"),
id);
929 aclInsert.bindValue(
S(
":method"), it.key());
930 aclInsert.bindValue(
S(
":mech"), mech);
934 if (it.value().isEmpty()) {
936 aclInsert.prepare(
S(
"INSERT OR REPLACE INTO ACL (identity_id, method_id) "
938 "( SELECT id FROM METHODS WHERE method = :method )"
940 aclInsert.bindValue(
S(
":id"),
id);
941 aclInsert.bindValue(
S(
":method"), it.key());
947 if (info.
methods().isEmpty()) {
950 aclInsert.prepare(
S(
"INSERT OR REPLACE INTO ACL "
951 "(identity_id, token_id) "
953 "( SELECT id FROM TOKENS WHERE token = :token ))"));
954 aclInsert.bindValue(
S(
":id"),
id);
955 aclInsert.bindValue(
S(
":token"), token);
961 foreach (QString token, info.
ownerList()) {
962 if (!token.isEmpty()) {
964 ownerInsert.prepare(
S(
"INSERT OR REPLACE INTO OWNER "
965 "(identity_id, token_id) "
967 "( SELECT id FROM TOKENS WHERE token = :token ))"));
968 ownerInsert.bindValue(
S(
":id"),
id);
969 ownerInsert.bindValue(
S(
":token"), token);
978 TRACE() <<
"Credentials insertion failed.";
987 QStringList queries = QStringList()
988 << QString::fromLatin1(
989 "DELETE FROM CREDENTIALS WHERE id = %1").arg(
id)
990 << QString::fromLatin1(
991 "DELETE FROM ACL WHERE identity_id = %1").arg(
id)
992 << QString::fromLatin1(
993 "DELETE FROM REALMS WHERE identity_id = %1").arg(
id)
994 << QString::fromLatin1(
995 "DELETE FROM owner WHERE identity_id = %1").arg(
id);
1004 QStringList clearCommands = QStringList()
1005 << QLatin1String(
"DELETE FROM CREDENTIALS")
1006 << QLatin1String(
"DELETE FROM METHODS")
1007 << QLatin1String(
"DELETE FROM MECHANISMS")
1008 << QLatin1String(
"DELETE FROM ACL")
1009 << QLatin1String(
"DELETE FROM REALMS")
1010 << QLatin1String(
"DELETE FROM TOKENS")
1011 << QLatin1String(
"DELETE FROM OWNER");
1018 return queryList(QString::fromLatin1(
"SELECT token FROM TOKENS "
1020 "(SELECT token_id FROM ACL WHERE identity_id = '%1' )")
1026 return queryList(QString::fromLatin1(
"SELECT token FROM TOKENS "
1028 "(SELECT token_id FROM OWNER WHERE identity_id = '%1' )")
1033 const QString &token,
1034 const QString &reference)
1037 TRACE() <<
"Could not start transaction. Error inserting data.";
1041 TRACE() <<
"Storing:" <<
id <<
", " << token <<
", " << reference;
1046 QSqlQuery tokenInsert =
newQuery();
1047 tokenInsert.prepare(
S(
"INSERT OR IGNORE INTO TOKENS (token) "
1048 "VALUES ( :token )"));
1049 tokenInsert.bindValue(
S(
":token"), token);
1056 refsInsert.prepare(
S(
"INSERT OR REPLACE INTO REFS "
1057 "(identity_id, token_id, ref) "
1059 "( SELECT id FROM TOKENS WHERE token = :token ),"
1062 refsInsert.bindValue(
S(
":id"),
id);
1063 refsInsert.bindValue(
S(
":token"), token);
1064 refsInsert.bindValue(
S(
":reference"), reference);
1071 TRACE() <<
"Data insertion ok.";
1075 TRACE() <<
"Data insertion failed.";
1080 const QString &token,
1081 const QString &reference)
1083 TRACE() <<
"Removing:" <<
id <<
", " << token <<
", " << reference;
1088 if (!reference.isNull() && !refs.contains(reference))
1092 TRACE() <<
"Could not start transaction. Error removing data.";
1099 if (reference.isEmpty()) {
1100 refsDelete.prepare(
S(
"DELETE FROM REFS "
1101 "WHERE identity_id = :id AND "
1102 "token_id = ( SELECT id FROM TOKENS WHERE token = :token )"));
1103 refsDelete.bindValue(
S(
":id"),
id);
1104 refsDelete.bindValue(
S(
":token"), token);
1106 refsDelete.prepare(
S(
"DELETE FROM REFS "
1107 "WHERE identity_id = :id AND "
1108 "token_id = ( SELECT id FROM TOKENS WHERE token = :token ) "
1110 refsDelete.bindValue(
S(
":id"),
id);
1111 refsDelete.bindValue(
S(
":token"), token);
1112 refsDelete.bindValue(
S(
":ref"), reference);
1121 TRACE() <<
"Data delete ok.";
1125 TRACE() <<
"Data delete failed.";
1131 if (token.isEmpty())
1132 return queryList(QString::fromLatin1(
"SELECT ref FROM REFS "
1133 "WHERE identity_id = '%1'")
1136 q.prepare(
S(
"SELECT ref FROM REFS "
1137 "WHERE identity_id = :id AND "
1138 "token_id = (SELECT id FROM TOKENS WHERE token = :token )"));
1139 q.bindValue(
S(
":id"),
id);
1140 q.bindValue(
S(
":token"), token);
1148 if (methods.isEmpty())
return false;
1150 QMapIterator<QString, QStringList> it(methods);
1151 while (it.hasNext()) {
1153 QSqlQuery methodInsert =
newQuery();
1154 methodInsert.prepare(
S(
"INSERT OR IGNORE INTO METHODS (method) "
1155 "VALUES( :method )"));
1156 methodInsert.bindValue(
S(
":method"), it.key());
1160 foreach (QString mech, it.value()) {
1162 mechInsert.prepare(
S(
"INSERT OR IGNORE INTO MECHANISMS (mechanism) "
1163 "VALUES( :mech )"));
1164 mechInsert.bindValue(
S(
":mech"), mech);
1175 q.prepare(
S(
"INSERT INTO METHODS (method) VALUES(:method)"));
1176 q.bindValue(
S(
":method"), method);
1180 if (ok != 0) *ok =
false;
1183 return q.lastInsertId().toUInt(ok);
1196 if (!info.
isNew()) {
1197 TRACE() <<
"UPDATE:" << info.
id() ;
1198 q.prepare(
S(
"UPDATE CREDENTIALS SET caption = :caption, "
1199 "username = :username, "
1201 "type = :type WHERE id = :id"));
1202 q.bindValue(
S(
":id"), info.
id());
1204 TRACE() <<
"INSERT:" << info.
id();
1205 q.prepare(
S(
"INSERT INTO CREDENTIALS "
1206 "(caption, username, flags, type) "
1207 "VALUES(:caption, :username, :flags, :type)"));
1209 q.bindValue(
S(
":username"),
1211 q.bindValue(
S(
":caption"), info.
caption());
1212 q.bindValue(
S(
":flags"), flags);
1213 q.bindValue(
S(
":type"), info.
type());
1216 TRACE() <<
"Error occurred while updating crendentials";
1222 QVariant idVariant = q.lastInsertId();
1223 if (!idVariant.isValid()) {
1224 TRACE() <<
"Error occurred while inserting crendentials";
1227 id = idVariant.toUInt();
1235 bool MetaDataDB::updateRealms(quint32
id,
const QStringList &realms,
bool isNew)
1241 queryStr = QString::fromLatin1(
1242 "DELETE FROM REALMS WHERE identity_id = '%1'")
1249 q.prepare(
S(
"INSERT OR IGNORE INTO REALMS (identity_id, realm) "
1250 "VALUES (:id, :realm)"));
1251 foreach (QString realm, realms) {
1252 q.bindValue(
S(
":id"),
id);
1253 q.bindValue(
S(
":realm"), realm);
1262 CredentialsDB::ErrorMonitor::ErrorMonitor(CredentialsDB *db)
1265 db->metaDataDB->clearError();
1266 if (db->secretsStorage != 0)
1267 db->secretsStorage->clearError();
1271 CredentialsDB::ErrorMonitor::~ErrorMonitor()
1276 if (_db->_lastError.isValid())
1279 if (_db->secretsStorage != 0 &&
1280 _db->secretsStorage->lastError().isValid()) {
1281 _db->_lastError = _db->secretsStorage->lastError();
1285 _db->_lastError = _db->metaDataDB->lastError();
1291 SignOn::AbstractSecretsStorage *secretsStorage):
1292 secretsStorage(secretsStorage),
1296 noSecretsDB = SignOn::CredentialsDBError(
1297 QLatin1String(
"Secrets DB not opened"),
1298 SignOn::CredentialsDBError::ConnectionError);
1305 delete m_secretsCache;
1310 QSqlDatabase::removeDatabase(connectionName);
1316 return metaDataDB->
init();
1321 QVariantMap configuration;
1322 configuration.insert(QLatin1String(
"name"), secretsDbName);
1323 if (!secretsStorage->initialize(configuration)) {
1324 TRACE() <<
"SecretsStorage initialization failed: " <<
1325 secretsStorage->lastError().text();
1329 m_secretsCache->
storeToDB(secretsStorage);
1330 m_secretsCache->
clear();
1336 return secretsStorage != 0 && secretsStorage->isOpen();
1341 if (secretsStorage != 0) secretsStorage->close();
1350 const QString &securityToken)
1353 return metaDataDB->
methods(
id, securityToken);
1357 const QString &username,
1358 const QString &password)
1364 return secretsStorage->checkPassword(
id, username, password);
1366 return username == info.
userName() &&
1367 secretsStorage->checkPassword(
id, QString(), password);
1374 TRACE() <<
"id:" <<
id <<
"queryPassword:" << queryPassword;
1377 if (queryPassword && !info.
isNew()) {
1378 QString username, password;
1380 TRACE() <<
"Loading credentials from DB.";
1381 secretsStorage->loadCredentials(
id, username, password);
1383 TRACE() <<
"Looking up credentials from cache.";
1390 #ifdef DEBUG_ENABLED
1391 if (password.isEmpty()) {
1392 TRACE() <<
"Password is empty";
1418 if (
id == 0)
return id;
1421 QString password = info.
password();
1427 secretsStorage->updateCredentials(
id, userName, password);
1448 return secretsStorage->removeCredentials(
id) &&
1461 return secretsStorage->clear() && metaDataDB->
clear();
1466 TRACE() <<
"Loading:" <<
id <<
"," << method;
1469 if (
id == 0)
return QVariantMap();
1471 quint32 methodId = metaDataDB->
methodId(method);
1472 if (methodId == 0)
return QVariantMap();
1475 return secretsStorage->loadData(
id, methodId);
1477 TRACE() <<
"Looking up data from cache";
1478 return m_secretsCache->
lookupData(
id, methodId);
1483 const QVariantMap &data)
1485 TRACE() <<
"Storing:" <<
id <<
"," << method;
1488 if (
id == 0)
return false;
1490 quint32 methodId = metaDataDB->
methodId(method);
1491 if (methodId == 0) {
1499 return secretsStorage->storeData(
id, methodId, data);
1501 TRACE() <<
"Storing data into cache";
1502 m_secretsCache->
updateData(
id, methodId, data);
1509 TRACE() <<
"Removing:" <<
id <<
"," << method;
1513 if (
id == 0)
return false;
1516 if (!method.isEmpty()) {
1517 methodId = metaDataDB->
methodId(method);
1518 if (methodId == 0)
return false;
1523 return secretsStorage->removeData(
id, methodId);
1535 return metaDataDB->
ownerList(identityId);
1541 QStringList owners =
ownerList(identityId);
1542 return owners.count() ? owners.at(0) : QString();
1546 const QString &token,
1547 const QString &reference)
1554 const QString &token,
1555 const QString &reference)
bool removeData(const quint32 id, const QString &method=QString())
bool isUserNameSecret() const
QSqlQuery exec(const QString &query)
Executes a specific database query.
static QStringList supportedDrivers()
QStringList references(const quint32 id, const QString &token=QString())
void setRealms(const QStringList &realms)
bool lookupCredentials(quint32 id, QString &username, QString &password) const
Definition of the CredentialsDB object.
QStringList accessControlList() const
virtual ~SqlDatabase()
Destroys the SqlDatabase object, closing the database connection.
QStringList accessControlList(const quint32 identityId)
void setRefCount(int refCount)
bool storePassword() const
void setStorePassword(bool storePassword)
void setMethods(const MethodMap &methods)
quint32 insertCredentials(const SignonIdentityInfo &info)
quint32 updateCredentials(const SignonIdentityInfo &info)
Caches credentials or BLOB authentication data.
QStringList realms() const
SignOn::CredentialsDBError lastError() const
void credentialsUpdated(quint32 id)
void setCaption(const QString &caption)
bool storeData(const quint32 id, const QString &method, const QVariantMap &data)
bool addReference(const quint32 id, const QString &token, const QString &reference)
void storeToDB(SignOn::AbstractSecretsStorage *secretsStorage) const
QStringList ownerList() const
bool removeCredentials(const quint32 id)
QVariantMap loadData(const quint32 id, const QString &method)
SignOn::CredentialsDBError lastError() const
QString credentialsOwnerSecurityToken(const quint32 identityId)
void setPassword(const QString &password)
SignonIdentityInfo credentials(const quint32 id, bool queryPassword=true)
SqlDatabase(const QString &hostname, const QString &connectionName, int version)
Constructs a SqlDatabase object using the given hostname.
bool init()
Connects to the DB and if necessary creates the tables.
bool removeReference(const quint32 id, const QString &token, const QString &reference=QString())
#define RETURN_IF_NO_SECRETS_DB(retval)
bool connect()
Creates the database connection.
bool errorOccurred() const
bool openSecretsDB(const QString &secretsDbName)
This method will open the DB file containing the user secrets.
MethodMap methods() const
QVariantMap lookupData(quint32 id, quint32 method) const
void setAccessControlList(const QStringList &accessControlList)
bool transactionalExec(const QStringList &queryList)
Executes a specific database set of queryes (INSERTs, UPDATEs, DELETEs) in a transaction context (No ...
CredentialsDB(const QString &metaDataDbName, SignOn::AbstractSecretsStorage *secretsStorage)
void disconnect()
Destroys the database connection.
QStringList methods(const quint32 id, const QString &securityToken=QString())
Daemon side representation of identity information.
bool checkPassword(const quint32 id, const QString &username, const QString &password)
QSqlQuery newQuery() const
void updateCredentials(quint32 id, const QString &username, const QString &password, bool storePassword)
QStringList ownerList(const quint32 identityId)
QString connectionName() const
virtual bool updateDB(int version)
void setLastError(const QSqlError &sqlError)
void setUserName(const QString &userName)
static QString errorInfo(const QSqlError &error)
Serializes a SQL error into a string.
virtual bool createTables()=0
void updateData(quint32 id, quint32 method, const QVariantMap &data)
QStringList queryList(const QString &query_str)
void setUserNameSecret(bool secret)
void setValidated(bool validated)
void setOwnerList(const QStringList &owners)