Make use of QKeyChain if its there.

This commit is contained in:
Klaas Freitag 2012-12-04 17:27:59 +01:00
parent 22128781be
commit 5d958a4c07
6 changed files with 140 additions and 24 deletions

View file

@ -123,10 +123,10 @@ void CredentialStore::fetchCredentials()
if( !_user.isEmpty() ) {
ReadPasswordJob *job = new ReadPasswordJob(Theme::instance()->appName());
// job->setAutoDelete( false );
job->setKey( _user );
job->setKey( keyChainKey( cfgFile.ownCloudUrl() ) );
connect( job, SIGNAL(finished(QKeychain::Job*)), this,
SLOT(slotKeyChainFinished(QKeychain::Job*)));
SLOT(slotKeyChainReadFinished(QKeychain::Job*)));
job->start();
}
#else
@ -156,7 +156,21 @@ void CredentialStore::fetchCredentials()
}
}
void CredentialStore::slotKeyChainFinished(QKeychain::Job* job)
void CredentialStore::reset()
{
_state = NotFetched;
_user = QString::null;
_passwd = QString::null;
_tries = 0;
}
QString CredentialStore::keyChainKey( const QString& url ) const
{
QString key = _user+QLatin1Char(':')+url;
return key;
}
void CredentialStore::slotKeyChainReadFinished(QKeychain::Job* job)
{
#ifdef WITH_QTKEYCHAIN
ReadPasswordJob *pwdJob = static_cast<ReadPasswordJob*>(job);
@ -188,11 +202,71 @@ QByteArray CredentialStore::basicAuthHeader() const
return data;
}
void CredentialStore::setCredentials( const QString& user, const QString& pwd )
void CredentialStore::setCredentials( const QString& url, const QString& user, const QString& pwd, bool noLocalPwd )
{
_passwd = pwd;
_user = user;
_state = Ok;
#ifdef WITH_QTKEYCHAIN
MirallConfigFile::CredentialType t;
t = MirallConfigFile::KeyChain;
if( noLocalPwd ) t = MirallConfigFile::User;
switch( t ) {
case MirallConfigFile::User:
deleteKeyChainCredential(keyChainKey( url ));
break;
case MirallConfigFile::KeyChain: {
// Set password in KeyChain
WritePasswordJob *job = new WritePasswordJob(Theme::instance()->appName());
// job->setAutoDelete( false );
job->setKey( keyChainKey( url ) );
job->setTextData(pwd);
connect( job, SIGNAL(finished(QKeychain::Job*)), this,
SLOT(slotKeyChainWriteFinished(QKeychain::Job*)));
job->start();
break;
}
default:
// unsupported.
break;
}
#else
(void) url;
#endif
}
void CredentialStore::slotKeyChainWriteFinished( QKeychain::Job *job )
{
#ifdef WITH_QTKEYCHAIN
WritePasswordJob *pwdJob = static_cast<WritePasswordJob*>(job);
if( pwdJob ) {
if( pwdJob->error() ) {
qDebug() << "Error with keychain: " << pwdJob->errorString();
} else {
qDebug() << "Successfully stored password for user " << _user;
// Try to remove password formerly stored in the config file.
MirallConfigFile cfgFile;
cfgFile.clearPasswordFromConfig();
}
} else {
qDebug() << "Error: KeyChain Write Password Job failed!";
}
#else
(void) job;
#endif
}
// Called if a user chooses to not store the password locally.
void CredentialStore::deleteKeyChainCredential( const QString& key )
{
// Start the remove job, do not care so much about the result.
DeletePasswordJob *job = new DeletePasswordJob(Theme::instance()->appName());
job->setKey( key );
job->start();
}
}

View file

@ -96,13 +96,14 @@ public:
* @param user - the user name
* @param password - the password.
*/
void setCredentials( const QString&, const QString& );
void setCredentials( const QString&, const QString&, const QString&, bool );
/**
* @brief canTryAgain - check if another try to get credentials makes sense.
*/
bool canTryAgain();
void reset();
signals:
/**
* @brief fetchCredentialsFinished
@ -115,10 +116,13 @@ signals:
void fetchCredentialsFinished(bool);
protected slots:
void slotKeyChainFinished(QKeychain::Job* job);
void slotKeyChainReadFinished( QKeychain::Job* );
void slotKeyChainWriteFinished( QKeychain::Job* );
private:
explicit CredentialStore(QObject *parent = 0);
void deleteKeyChainCredential( const QString& );
QString keyChainKey( const QString& ) const;
static CredentialStore *_instance;
static CredState _state;

View file

@ -147,18 +147,43 @@ void MirallConfigFile::writeOwncloudConfig( const QString& connection,
pwd.clear();
}
#ifdef WITH_QTKEYCHAIN
// Password is stored to QtKeyChain now by default in CredentialStore
// The CredentialStore calls clearPasswordFromConfig after the creds
// were successfully wiritten to delete the passwd entry from config.
qDebug() << "Going to delete the password from settings file.";
#else
// store password into settings file.
QByteArray pwdba = pwd.toUtf8();
settings.setValue( QLatin1String("passwd"), QVariant(pwdba.toBase64()) );
#endif
settings.setValue( QLatin1String("nostoredpassword"), QVariant(skipPwd) );
settings.sync();
// check the perms, only read-write for the owner.
QFile::setPermissions( file, QFile::ReadOwner|QFile::WriteOwner );
// inform the credential store about the password change.
CredentialStore::instance()->setCredentials( user, pwd );
CredentialStore::instance()->setCredentials( cloudsUrl, user, pwd, skipPwd );
}
// This method is called after the password was successfully stored into the
// QKeyChain in CredentialStore.
void MirallConfigFile::clearPasswordFromConfig( const QString& connection )
{
const QString file = configFile();
QString con( defaultConnection() );
if( !connection.isEmpty() )
con = connection;
QSettings settings( file, QSettings::IniFormat);
settings.setIniCodec( "UTF-8" );
settings.beginGroup( con ); // FIXME: Connection!
settings.remove(QLatin1String("passwd"));
settings.remove(QLatin1String("password"));
settings.sync();
}
// set the url, called from redirect handling.
void MirallConfigFile::setOwnCloudUrl( const QString& connection, const QString & url )
{
@ -315,11 +340,16 @@ int MirallConfigFile::pollTimerExceedFactor( const QString& connection ) const
return pte;
}
MirallConfigFile::CredentialType MirallConfigFile::credentialType() const
MirallConfigFile::CredentialType MirallConfigFile::credentialType( const QString& connection) const
{
QString con; /* ( connection ); */
/* if( connection.isEmpty() ) */ con = defaultConnection();
QString con( connection );
if( connection.isEmpty() ) con = defaultConnection();
CredentialType ct = Settings;
#ifdef WITH_QTKEYCHAIN
// In case QtKeyChain is there, use it mandatory.
ct = KeyChain;
#endif
QSettings settings( configFile(), QSettings::IniFormat );
settings.setIniCodec( "UTF-8" );

View file

@ -69,7 +69,7 @@ public:
QByteArray caCerts();
void setCaCerts( const QByteArray& );
CredentialType credentialType() const;
CredentialType credentialType(const QString &connection = QString::null) const;
QString ownCloudVersion() const;
void setOwnCloudVersion( const QString& );
@ -107,7 +107,7 @@ public:
protected:
QString ownCloudPasswd( const QString& connection = QString() ) const;
QString ownCloudUser( const QString& connection = QString() ) const;
void clearPasswordFromConfig( const QString& connect = QString() );
private:
QVariant getValue(const QString& param, const QString& group) const;

View file

@ -16,6 +16,7 @@
#include "mirall/mirallconfigfile.h"
#include "mirall/owncloudinfo.h"
#include "mirall/folderman.h"
#include "mirall/credentialstore.h"
#include <QtCore>
#include <QProcess>
@ -391,15 +392,20 @@ void OwncloudSetupWizard::setupLocalSyncFolder()
if( localFolderOk ) {
_remoteFolder = Theme::instance()->defaultServerFolder();
if( !_remoteFolder.isEmpty() && createRemoteFolder( _remoteFolder ) ) {
// the creation started successfully, does not mean it will work
qDebug() << "Creation of remote folder started successfully.";
} else {
// the start of the http request failed.
_ocWizard->appendToResultWidget(tr("Creation of remote folder %1 could not be started.").arg(_remoteFolder));
qDebug() << "Creation of remote folder failed.";
}
CredentialStore::instance()->reset();
connect( CredentialStore::instance(), SIGNAL(fetchCredentialsFinished(int)),
this, SLOT(slotCreateRemoteFolder(int)));
CredentialStore::instance()->fetchCredentials();
}
}
void OwncloudSetupWizard::slotCreateRemoteFolder(int res)
{
disconnect(CredentialStore::instance(), SIGNAL(fetchCredentialsFinished(bool)));
if( createRemoteFolder( _remoteFolder ) ) {
qDebug() << "Started remote folder creation ok";
} else {
_ocWizard->appendToResultWidget(tr("Creation of remote folder %1 could not be started.").arg(_remoteFolder));
}
}
@ -450,14 +456,14 @@ void OwncloudSetupWizard::finalizeSetup( bool success )
}
_ocWizard->appendToResultWidget( QLatin1String(" "));
_ocWizard->appendToResultWidget( QLatin1String("<p><font color=\"green\"><b>")
+ tr("Succesfully connected to %1!")
.arg(Theme::instance()->appName())
+ QLatin1String("</b></font></p>"));
+ tr("Succesfully connected to %1!")
.arg(Theme::instance()->appName())
+ QLatin1String("</b></font></p>"));
_ocWizard->appendToResultWidget( tr("Press Finish to permanently accept this connection."));
} else {
_ocWizard->appendToResultWidget(QLatin1String("<p><font color=\"red\">")
+ tr("Connection to %1 could not be established. Please check again.")
.arg(Theme::instance()->appName())
.arg(Theme::instance()->appName())
+ QLatin1String("</font></p>"));
}
}

View file

@ -80,6 +80,8 @@ protected slots:
void slotConnectToOCUrl( const QString& );
void slotCreateOCLocalhost();
void slotCreateRemoteFolder(int);
private slots:
void slotOwnCloudFound( const QString&, const QString&, const QString&, const QString& );
void slotNoOwnCloudFound( QNetworkReply* );