[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    [KSecretService] 736890f: Dialog for ACL handling and assorted tests.
From:       Valentin Rusu <kde () rusu ! info>
Date:       2010-11-09 19:14:34
Message-ID: 20101109191434.922EFA610A () git ! kde ! org
[Download RAW message or body]


	A	 ui/tests/dialogaskaclprefstest.h	 [License: GPL(v2)]


	A	 ui/tests/dialogaskaclprefstest.cpp	 [License: GPL(v2)]


	A	 ui/dialogaskunlockaclprefs.ui	 [License: Trivialfile.]


	A	 ui/dialogaskunlockaclprefs.h	 [License: GPL(v2)]


	A	 ui/dialogaskunlockaclprefs.cpp	 [License: GPL(v2)]


	A	 ui/dialogaskcreateaclprefs.ui	 [License: Trivialfile.]


	A	 ui/dialogaskcreateaclprefs.h	 [License: GPL(v2)]


	A	 ui/dialogaskcreateaclprefs.cpp	 [License: GPL(v2)]


	A	 lib/acl.h	 [License: GPL(v2)]


	A	 backend/tests/ksecretuitest.h	 [License: GPL(v2)]


	A	 backend/tests/ksecretuitest.cpp	 [License: GPL(v2)]

commit 736890f8ca567994496c9a87120021ba8615186a
Author: Valentin Rusu <kde@rusu.info>
Date:   Mon Nov 1 06:54:04 2010 +0000

    Dialog for ACL handling and assorted tests. Unlock test fails though - perhaps \
collection lock/unlock on my copy needs revision  
    svn path=/trunk/playground/base/ksecretservice/; revision=1191747

diff --git a/backend/backendcollection.cpp b/backend/backendcollection.cpp
index 16478d4..4cf6ac6 100644
--- a/backend/backendcollection.cpp
+++ b/backend/backendcollection.cpp
@@ -31,14 +31,16 @@ BackendCollection::~BackendCollection()
 {
 }
 
-bool BackendCollection::isPeerAclAllowed(const Peer* peer) const
+bool BackendCollection::isPeerAclAllowed(const Peer *peer) const
 {
+    Q_UNUSED(peer);
     bool accessAllowed = false;
     return accessAllowed;
 }
 
-bool BackendCollection::askPeerAclAllowed(const Peer* peer) const
+bool BackendCollection::askPeerAclAllowed(const Peer *peer) const
 {
+    Q_UNUSED(peer);
     return false;
 }
 
diff --git a/backend/backendcollection.h b/backend/backendcollection.h
index a6ed7b8..f50c020 100644
--- a/backend/backendcollection.h
+++ b/backend/backendcollection.h
@@ -25,7 +25,8 @@
 #include "backendjob.h"
 
 #include <jobqueue.h>
-#include "jobinfostructs.h"
+#include <jobinfostructs.h>
+#include <acl.h>
 
 #include <QtCore/QObject>
 #include <QtCore/QString>
@@ -50,14 +51,6 @@ class BackendCollection : public QObject, public JobQueue
     Q_OBJECT
 
 public:
-    /**
-     * Application permissions stored inside the backend file
-     */
-    enum ApplicationPermission {
-        PermissionAsk = 0,   /// ask every time
-        PermissionDeny = 1,  /// deny every time
-        PermissionAllow = 2  /// always allow
-    };
 
     /**
      * Constructor
@@ -184,6 +177,20 @@ public:
      * the givent executable file does not exist on disc.
      */
     virtual bool setApplicationPermission(const QString& path, ApplicationPermission \
perm) = 0; +    
+    /**
+     * This member is called during collection creation to store the creator \
application path. +     * If the collection already has a creator set, then this \
method has no effect +     * @param exePath Path to the application that created this \
collection +     * @return false if the collection already has a creator set
+     */
+    virtual bool setCreatorApplication(QString exePath) =0;
+    
+    /**
+     * This method returns the executable path of the application which originally
+     * created this collection.
+     */
+    virtual const QString &creatorApplication() const =0;
 
 protected:
     /**
diff --git a/backend/backendjob.cpp b/backend/backendjob.cpp
index 6b30ee5..ccc05af 100644
--- a/backend/backendjob.cpp
+++ b/backend/backendjob.cpp
@@ -82,11 +82,6 @@ CreateCollectionJob::CreateCollectionJob(const \
CollectionCreateInfo &createColle  {
 }
 
-BackendCollection *CreateCollectionJob::collection()
-{
-    return m_collection;
-}
-
 const QString &CreateCollectionJob::label() const
 {
     return m_createCollectionInfo.m_label;
@@ -226,11 +221,6 @@ UnlockCollectionJob::UnlockCollectionJob(const \
CollectionUnlockInfo &unlockInfo,  {
 }
 
-BackendCollection *UnlockCollectionJob::collection()
-{
-    return m_collection;
-}
-
 UnlockItemJob::UnlockItemJob(const ItemUnlockInfo& unlockInfo)
     : BooleanResultJob(BackendJob::TypeUnlockItem, unlockInfo.m_item), \
m_unlockInfo(unlockInfo)  {
diff --git a/backend/backendjob.h b/backend/backendjob.h
index e980af1..ce2be1b 100644
--- a/backend/backendjob.h
+++ b/backend/backendjob.h
@@ -162,7 +162,9 @@ public:
      *
      * @return the collection created or 0 in case of an error
      */
-    BackendCollection *collection();
+    BackendCollection *collection() const { 
+        return m_collection; 
+    }
 
 protected:
     /**
@@ -383,7 +385,9 @@ public:
      *
      * @remarks public as needed by ServiceMultiPrompt
      */
-    BackendCollection *collection();
+    BackendCollection *collection() const {
+        return m_collection;
+    }
 
     /**
      * Get the collection unlock info
diff --git a/backend/backendreturn.h b/backend/backendreturn.h
index e365718..4c4c4d0 100644
--- a/backend/backendreturn.h
+++ b/backend/backendreturn.h
@@ -34,6 +34,7 @@ enum ErrorType {
     ErrorIsLocked,         /// the object (item/collection) must be unlocked before \
this  /// call can be made
     ErrorNotSupported,     /// the backend doesn't support calling this method
+    ErrorAclSetPermission /// the permission could not be set
 };
 
 
diff --git a/backend/ksecret/ksecretcollection.cpp \
b/backend/ksecret/ksecretcollection.cpp index 4369c57..0689ef1 100644
--- a/backend/ksecret/ksecretcollection.cpp
+++ b/backend/ksecret/ksecretcollection.cpp
@@ -784,6 +784,10 @@ bool KSecretCollection::deserializePartAcls(const QByteArray \
&partContents)  
     QBuffer aclsBuffer(&partAcls);
     KSecretFile aclsFile(&aclsBuffer, KSecretFile::Read);
+
+    if (!aclsFile.readString( &m_creatorApplication ))
+        return false;
+    
     quint32 numAcls;
     if(!aclsFile.isValid() || !aclsFile.readUint(&numAcls)) {
         return false;
@@ -1040,8 +1044,8 @@ bool KSecretCollection::serializeParts(KSecretFile &file) const
     filePartEntries[curFilePartEntry].m_position = (quint32)file.pos();
     QBuffer buffer;
     KSecretFile device(&buffer, KSecretFile::Write);
-    QHash<QString, KSecretCollection::ApplicationPermission>::const_iterator it = \
                m_acls.constBegin();
-    QHash<QString, KSecretCollection::ApplicationPermission>::const_iterator end = \
m_acls.constEnd(); +    QHash<QString, ApplicationPermission>::const_iterator it = \
m_acls.constBegin(); +    QHash<QString, ApplicationPermission>::const_iterator end = \
m_acls.constEnd();  for(; it != end; ++it) {
         if(!file.writeString(it.key()) || !file.writeUint((quint32)it.value())) {
             return false;
@@ -1135,6 +1139,9 @@ bool KSecretCollection::serializeAclsPart(KSecretFile &file, \
FilePartEntry &entr  }
     }
 
+    if (!tempFile.writeString( m_creatorApplication ))
+        return false;
+    
     if(!serializeAuthenticated(aclsBuffer.data(), file)) {
         return false;
     }
@@ -1335,22 +1342,34 @@ bool KSecretCollection::serializeAuthenticated(const \
QByteArray &data, KSecretFi  return file.writeSecret(dataHash);
 }
 
-BackendCollection::ApplicationPermission \
KSecretCollection::applicationPermission(const QString& path) const \
+ApplicationPermission KSecretCollection::applicationPermission(const QString& path) \
const  {
-    // TODO: implement
-    Q_ASSERT(0);
-    return BackendCollection::PermissionAllow;
+    ApplicationPermission result = PermissionDeny;
+    if ( m_acls.contains(  path ) )
+        result = m_acls[path];
+    return result;
 }
 
-bool KSecretCollection::setApplicationPermission(const QString& path, \
BackendCollection::ApplicationPermission perm) +bool \
KSecretCollection::setApplicationPermission(const QString& path, \
ApplicationPermission perm)  {
-    // TODO: implement
-    Q_ASSERT(0);
-    
-    // sync
-    m_dirty = true;
-    startSyncTimer();
-    
+    bool result = false;
+    if ( !path.isEmpty() && QFile::exists( path ) ) {
+        m_acls[ path ] = perm;
+        
+        // sync
+        m_dirty = true;
+        startSyncTimer();
+        
+        result = true;
+    }
+    return result;
+}
+
+bool KSecretCollection::setCreatorApplication(QString exePath)
+{
+    if ( m_creatorApplication.isEmpty() || exePath.isEmpty() )
+        return false;
+    m_creatorApplication = exePath;
     return true;
 }
 
diff --git a/backend/ksecret/ksecretcollection.h \
b/backend/ksecret/ksecretcollection.h index a9dd303..0007eca 100644
--- a/backend/ksecret/ksecretcollection.h
+++ b/backend/ksecret/ksecretcollection.h
@@ -196,7 +196,23 @@ public:
      */
     const QString &path() const;
 
-private Q_SLOTS:
+    /**
+     * This member is called during collection creation to store the creator \
application path. +     * If the collection aloready has a creator set, then this \
methid has no effect +     * @param exePath Path to the application that created this \
collection +     * @return false if the collection aloready has a creator set
+     */
+    bool setCreatorApplication(QString exePath);
+    
+    /**
+     * This method returns the executable path of the application which originally
+     * created this collection.
+     */
+    const QString &creatorApplication() const {
+        return m_creatorApplication;
+    }
+
+    private Q_SLOTS:
     /**
      * Remove an item from our list of known items.
      *
@@ -278,6 +294,7 @@ private:
     friend class KSecretLockCollectionJob;
     friend class KSecretDeleteCollectionJob;
     friend class KSecretCreateItemJob;
+    friend class KSecretCreateCollectionJob;
 
 
     /**
@@ -510,10 +527,11 @@ private:
     QByteArray m_propertiesMac;
 
     // the acls message authentication code
-    QHash<QString, BackendCollection::ApplicationPermission> m_acls;
+    QHash<QString, ApplicationPermission> m_acls;
     QMap<QString, int> m_unknownAcls;
     QByteArray m_aclsMac;
-
+    QString m_creatorApplication;
+    
     // unknown file parts stored as-is
     QList<UnknownFilePart*> m_unknownParts;
 
diff --git a/backend/ksecret/ksecretjobs.cpp b/backend/ksecret/ksecretjobs.cpp
index e041780..9790f7b 100644
--- a/backend/ksecret/ksecretjobs.cpp
+++ b/backend/ksecret/ksecretjobs.cpp
@@ -94,11 +94,12 @@ void KSecretCreateCollectionJob::newPasswordJobResult(QueuedJob \
*job)  m_manager->addCollection(coll);
 
     if(locked()) {
-        // TODO: lock
+        coll->lock();
     }
 
     setCollection(coll);
-    emitResult();
+    // not yet time for  emitResult(); 
+    // let the ACL dialog to pop before 
 }
 
 void KSecretCreateCollectionJob::askAclPrefsJobResult(QueuedJob* job)
@@ -106,20 +107,29 @@ void \
                KSecretCreateCollectionJob::askAclPrefsJobResult(QueuedJob* job)
     AbstractAskAclPrefsJob *aclJob = qobject_cast< AbstractAskAclPrefsJob* >(job);
     Q_ASSERT(aclJob);
 
-    // TODO: implement this
+    if (!collection()->setApplicationPermission(
+        createCollectionInfo().m_peer.exePath(),
+        aclJob->permission() ) ) {
+            setError(ErrorAclSetPermission, i18n("Cannot store application ACL \
policy into the back-end!") ); +            // FIXME: should we remove the freshly \
created collection ? +            emitResult();
+    }
+    collection()->setCreatorApplication( createCollectionInfo().m_peer.exePath() );
+    
+    emitResult();
 }
 
 
 KSecretUnlockCollectionJob::KSecretUnlockCollectionJob(const CollectionUnlockInfo \
&unlockInfo,  KSecretCollection *coll)
-    : UnlockCollectionJob(unlockInfo, coll), m_collection(coll), m_firstTry(true)
+    : UnlockCollectionJob(unlockInfo, coll), m_firstTry(true)
 {
 }
 
 bool KSecretUnlockCollectionJob::isImmediate() const
 {
     // unlocked collections don't need a job to open
-    if(!m_collection->isLocked()) {
+    if(collection()->isLocked()) {
         return true;
     } else {
         return false;
@@ -145,23 +155,25 @@ void KSecretUnlockCollectionJob::start()
 
     AbstractAskAclPrefsJob* askAclPrefsJob = 0;
     // default is always to ask the user
-    BackendCollection::ApplicationPermission perm = \
BackendCollection::PermissionAsk; +    ApplicationPermission perm = PermissionAsk;
     if(unlockInfo().m_peer.isValid()) {
         perm = collection()->applicationPermission(unlockInfo().m_peer.exePath());
     }
     switch(perm) {
-    case BackendCollection::PermissionDeny:
+    case PermissionDeny:
         setResult(false);
         emitResult();
         break;
-    case BackendCollection::PermissionAsk:
+    case PermissionAsk:
         askAclPrefsJob = uiManager->createAskAclPrefsJob(unlockInfo());
         connect(askAclPrefsJob, SIGNAL(result(QueuedJob*)), \
SLOT(askAclPrefsJobResult(QueuedJob*)));  askAclPrefsJob->enqueue();
         break;
-    case BackendCollection::PermissionAllow:
+    case PermissionAllow:
         // nothing to do, go further
         break;
+    case PermissionUndefined:
+        Q_ASSERT(0); // what's this ? why have we reached this point ?
     }
 
     if(0 == askAclPrefsJob) {
@@ -173,7 +185,7 @@ void KSecretUnlockCollectionJob::createAskPasswordJob()
 {
     AbstractUiManager *uiManager = BackendMaster::instance()->uiManager();
     // start a job for getting a new password for the collection from the user.
-    AbstractAskPasswordJob *subJob = \
uiManager->createAskPasswordJob(m_collection->label().value(), +    \
AbstractAskPasswordJob *subJob = \
                uiManager->createAskPasswordJob(collection()->label().value(),
                                      !m_firstTry);
     connect(subJob, SIGNAL(result(QueuedJob*)), \
SLOT(askPasswordJobResult(QueuedJob*)));  
@@ -189,11 +201,27 @@ void KSecretUnlockCollectionJob::askAclPrefsJobResult(QueuedJob \
*job)  Q_ASSERT(apj);
     if(apj->denied()) {
         setResult(false);
-        setError(ErrorOther, i18n("Unkocking the collection was denied."));
+        setError(ErrorOther, i18n("Unlocking the collection was denied."));
         emitResult();
-    } else {
-        // now that the access to this collection is allowed, go further and ask the \
                password
-        createAskPasswordJob();
+    } else 
+    if (apj->cancelled() ) {
+        setResult(false);
+        setError(ErrorOther, i18n("Unlocking the collection was canceled by the \
user.")); +        emitResult();
+    }
+    else {
+        // now that the access to this collection is allowed, store user choice and \
go further and ask the password +        if ( \
!collection()->setApplicationPermission(  +            unlockInfo().m_peer.exePath(),
+            apj->permission() ) )
+        {
+            setResult(false);
+            setError(ErrorAclSetPermission, i18n("Cannot store application ACL \
policy into the back-end!") ); +            emitResult();
+        }
+        else {
+            createAskPasswordJob();
+        }
     }
 }
 
@@ -204,18 +232,19 @@ void KSecretUnlockCollectionJob::askPasswordJobResult(QueuedJob \
*job)  
     if(apj->cancelled()) {
         setResult(false);
-        setError(ErrorOther, i18n("Unlocking the collection was cancelled by the \
user.")); +        setError(ErrorOther, i18n("Unlocking the collection was canceled \
by the user."));  emitResult();
         return;
     }
 
-    BackendReturn<bool> rc = m_collection->tryUnlockPassword(apj->password());
+    KSecretCollection *ksecretColl = dynamic_cast< KSecretCollection* \
>(collection()); +    BackendReturn<bool> rc = \
> ksecretColl->tryUnlockPassword(apj->password());
     if(rc.isError()) {
         setResult(false);
         setError(rc.error(), rc.errorMessage());
         emitResult();
     } else if(!rc.value()) {
-        // try againg the password
+        // try again the password
         createAskPasswordJob();
     } else {
         setResult(true);
diff --git a/backend/ksecret/ksecretjobs.h b/backend/ksecret/ksecretjobs.h
index 46ce096..a53a79b 100644
--- a/backend/ksecret/ksecretjobs.h
+++ b/backend/ksecret/ksecretjobs.h
@@ -76,7 +76,6 @@ private Q_SLOTS:
 private:
     void createAskPasswordJob();
 
-    KSecretCollection *m_collection;
     bool m_firstTry;
 };
 
diff --git a/backend/temporary/temporarycollection.h \
b/backend/temporary/temporarycollection.h index 7e157df..bf54398 100644
--- a/backend/temporary/temporarycollection.h
+++ b/backend/temporary/temporarycollection.h
@@ -147,6 +147,29 @@ public:
         return true;
     }
 
+    /**
+     * This member is called during collection creation to store the creator \
application path. +     * If the collection already has a creator set, then this \
method has no effect +     * @param exePath Path to the application that created this \
collection +     * @return false if the collection already has a creator set
+     */
+    virtual bool setCreatorApplication(QString exePath) {
+        if (m_creator.isEmpty()) {
+            m_creator = exePath;
+            return true;
+        }
+        else
+            return false;
+    }
+    
+    /**
+     * This method returns the executable path of the application which originally
+     * created this collection.
+     */
+    virtual const QString &creatorApplication() const {
+        return m_creator;
+    }
+
 protected:
     // Method for creating items. This is only called by TemporaryCreateItemJobs.
     BackendReturn<BackendItem*> createItem(const QString &label,
@@ -176,6 +199,7 @@ private:
     QString m_label;
     QDateTime m_created;
     QDateTime m_modified;
+    QString m_creator;
 
     QList<BackendItem*> m_items;
 };
diff --git a/backend/tests/CMakeLists.txt b/backend/tests/CMakeLists.txt
index 4854b7c..bea4b60 100644
--- a/backend/tests/CMakeLists.txt
+++ b/backend/tests/CMakeLists.txt
@@ -20,6 +20,16 @@ TARGET_LINK_LIBRARIES (ksecret_collection_test
 
 ADD_TEST (KSecretCollectionTest ksecret_collection_test)
 
+KDE4_ADD_EXECUTABLE (ksecret_collection_ui_test ksecretuitest.cpp)
+TARGET_LINK_LIBRARIES (ksecret_collection_ui_test
+   ksecretservicebackend
+   ksecretservicelib
+   ksecretserviceui
+   ${QT_QTTEST_LIBRARIES}
+)
+
+ADD_TEST (KSecretCollectionUiTest ksecret_collection_ui_test)
+
 KDE4_ADD_EXECUTABLE (securebuffer_test securebuffertest.cpp)
 TARGET_LINK_LIBRARIES (securebuffer_test ksecretservicebackend \
${QT_QTTEST_LIBRARIES})  
diff --git a/backend/tests/ksecrettest.cpp b/backend/tests/ksecrettest.cpp
index 9397cba..660218f 100644
--- a/backend/tests/ksecrettest.cpp
+++ b/backend/tests/ksecrettest.cpp
@@ -52,7 +52,7 @@ void KSecretTest::initTestCase()
 
 void KSecretTest::testCreateCollectionAsync()
 {
-    CollectionCreateInfo createCollectionInfo("test", Peer());
+    CollectionCreateInfo createCollectionInfo("test", Peer( \
                QCoreApplication::applicationPid() ));
     CreateCollectionJob *createColl = \
                m_manager->createCreateCollectionJob(createCollectionInfo);
     QSignalSpy managerSpy(m_manager, SIGNAL(collectionCreated(BackendCollection*)));
     QSignalSpy masterSpy(BackendMaster::instance(), \
SIGNAL(collectionCreated(BackendCollection*))); @@ -123,7 +123,7 @@ void \
KSecretTest::testLockCollectionAsync()  
 void KSecretTest::testUnlockCollectionAsync()
 {
-    CollectionUnlockInfo unlockInfo = CollectionUnlockInfo(Peer());
+    CollectionUnlockInfo unlockInfo = CollectionUnlockInfo(Peer( \
                QCoreApplication::applicationPid() ));
     UnlockCollectionJob *unlockColl = m_collection->createUnlockJob(unlockInfo);
     BackendMaster *master = BackendMaster::instance();
     QSignalSpy masterSpy(master, SIGNAL(collectionChanged(BackendCollection*)));
diff --git a/backend/tests/ksecretuitest.cpp b/backend/tests/ksecretuitest.cpp
new file mode 100644
index 0000000..6e129dc
--- /dev/null
+++ b/backend/tests/ksecretuitest.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2010, Dario Freddi <dario.freddi@collabora.co.uk>
+ * Copyright 2010, Valentin Rusu <kde@rusu.info>
+ *
+ * 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 2 of
+ * the License or (at your option) version 3 or any later version
+ * accepted by the membership of KDE e.V. (or its successor approved
+ * by the membership of KDE e.V.), which shall act as a proxy
+ * defined in Section 14 of version 3 of the license.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * 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/>.
+ */
+
+#include "ksecretuitest.h"
+#include <backendmaster.h>
+#include <ksecret/ksecretcollectionmanager.h>
+#include <backendcollection.h>
+#include <backenditem.h>
+#include <ui/dialoguimanager.h>
+#include <peer.h>
+
+#include <kstandarddirs.h>
+#include <qtest_kde.h>
+
+Q_DECLARE_METATYPE(BackendCollection*)
+Q_DECLARE_METATYPE(BackendItem*)
+
+void KSecretUiTest::initTestCase()
+{
+    qRegisterMetaType<BackendCollection*>();
+    qRegisterMetaType<BackendItem*>();
+    QCA::init();
+    BackendMaster *master = BackendMaster::instance();
+    master->setUiManager(new DialogUiManager);
+    // use special test-directory for the .ksecret files
+    m_manager = new KSecretCollectionManager("share/apps/ksecretservice-test", \
master); +    // remove all files in the resource directory so no previous
+    // collections are present when performing the test!
+    QDir dir = QDir(KGlobal::dirs()->saveLocation("ksecret"));
+    QStringList entries = dir.entryList(QStringList("*.ksecret"), QDir::Files);
+    Q_FOREACH(const QString &file, entries) {
+        QVERIFY(dir.remove(file));
+    }
+    master->addManager(m_manager);
+}
+
+void KSecretUiTest::testCreateCollectionAsync()
+{
+    CollectionCreateInfo createCollectionInfo("test", Peer( \
QCoreApplication::applicationPid() )); +    createCollectionInfo.m_locked = false;
+    CreateCollectionJob *createColl = \
m_manager->createCreateCollectionJob(createCollectionInfo); +    QSignalSpy \
managerSpy(m_manager, SIGNAL(collectionCreated(BackendCollection*))); +    QSignalSpy \
masterSpy(BackendMaster::instance(), SIGNAL(collectionCreated(BackendCollection*))); \
+    QTestEventLoop loop; +    QVERIFY(loop.connect(createColl, \
SIGNAL(result(QueuedJob*)), SLOT(exitLoop()))); +    createColl->enqueue();
+    while(!createColl->isFinished()) {
+        loop.enterLoop(120);
+    }
+
+    QVERIFY(createColl->isFinished());
+    QCOMPARE(createColl->error(), NoError);
+    QVERIFY(!createColl->isDismissed());
+    QVERIFY(createColl->collection() != 0);
+
+    // Verify signals
+    QCOMPARE(managerSpy.count(), 1);
+    QCOMPARE(managerSpy.takeFirst().at(0).value<BackendCollection*>(), \
createColl->collection()); +    QCOMPARE(masterSpy.count(), 1);
+    QCOMPARE(masterSpy.takeFirst().at(0).value<BackendCollection*>(), \
createColl->collection()); +
+    // Check the collection is present and alive
+    BackendMaster *master = BackendMaster::instance();
+    QCOMPARE(master->collections().size(), 1);
+    QCOMPARE(master->collections().first(), createColl->collection());
+    QCOMPARE(master->collections().first()->label().value(), QLatin1String("test"));
+
+    // TODO: check collection attributes (eg. timestamps)
+
+    // check that the collection has been written to disk
+    QStringList entries = QDir(KGlobal::dirs()->saveLocation("ksecret")).entryList(
+        QStringList("*.ksecret"), QDir::Files);
+    QCOMPARE(entries.count(), 1);
+    QCOMPARE(entries.at(0), createColl->collection()->id() + ".ksecret");
+
+    // remember the collection
+    m_collection = createColl->collection();
+}
+
+void KSecretUiTest::testUnlockCollectionAsync()
+{
+    CollectionUnlockInfo unlockInfo = CollectionUnlockInfo( Peer( \
QCoreApplication::applicationPid() )); +    UnlockCollectionJob *unlockColl = \
m_collection->createUnlockJob(unlockInfo); +    BackendMaster *master = \
BackendMaster::instance(); +    QSignalSpy masterSpy(master, \
SIGNAL(collectionChanged(BackendCollection*))); +    QSignalSpy managerSpy(m_manager, \
SIGNAL(collectionChanged(BackendCollection*))); +    QSignalSpy collSpy(m_collection, \
SIGNAL(collectionChanged(BackendCollection*))); +    QTestEventLoop loop;
+    QVERIFY(loop.connect(unlockColl, SIGNAL(result(QueuedJob*)), SLOT(exitLoop())));
+    unlockColl->enqueue();
+    if (!unlockColl->isFinished()) {
+        loop.enterLoop(200);
+    }
+
+    QVERIFY(unlockColl->isFinished());
+    QCOMPARE(unlockColl->error(), NoError);
+    QVERIFY(!unlockColl->isDismissed());
+    QVERIFY(unlockColl->result());
+    QVERIFY(!m_collection->isLocked());
+
+    // Verify signals
+    QCOMPARE(managerSpy.count(), 1);
+    QCOMPARE(managerSpy.takeFirst().at(0).value<BackendCollection*>(), \
m_collection); +    QCOMPARE(masterSpy.count(), 1);
+    QCOMPARE(masterSpy.takeFirst().at(0).value<BackendCollection*>(), m_collection);
+    QCOMPARE(collSpy.count(), 1);
+    QCOMPARE(collSpy.takeFirst().at(0).value<BackendCollection*>(), m_collection);
+}
+
+void KSecretUiTest::cleanupTestCase()
+{
+    // TODO: delete stuff so this can also be used for valgrind leak-checking
+}
+
+QTEST_KDEMAIN(KSecretUiTest, GUI)
+#include "ksecretuitest.moc"
diff --git a/backend/tests/ksecretuitest.h b/backend/tests/ksecretuitest.h
new file mode 100644
index 0000000..fd7ac2f
--- /dev/null
+++ b/backend/tests/ksecretuitest.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2010, Dario Freddi <dario.freddi@collabora.co.uk>
+ *
+ * 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 2 of
+ * the License or (at your option) version 3 or any later version
+ * accepted by the membership of KDE e.V. (or its successor approved
+ * by the membership of KDE e.V.), which shall act as a proxy
+ * defined in Section 14 of version 3 of the license.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * 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/>.
+ */
+
+#ifndef KSECRETUITEST_H
+#define KSECRETUITEST_H
+
+#include <QtTest/QtTest>
+
+class BackendCollectionManager;
+class BackendCollection;
+
+class KSecretUiTest : public QObject
+{
+    Q_OBJECT
+
+private Q_SLOTS:
+    void initTestCase();
+
+    void testCreateCollectionAsync();
+    void testUnlockCollectionAsync();
+
+    void cleanupTestCase();
+
+private:
+    BackendCollectionManager *m_manager;
+    BackendCollection *m_collection;
+
+    QDateTime m_collCreated;
+    QDateTime m_collModified;
+};
+
+#endif // KSECRETUITEST_H
diff --git a/frontend/tests/tempblockingcollection.cpp \
b/frontend/tests/tempblockingcollection.cpp index 5ecbc4d..5e3f8df 100644
--- a/frontend/tests/tempblockingcollection.cpp
+++ b/frontend/tests/tempblockingcollection.cpp
@@ -184,16 +184,25 @@ void \
TempBlockingCollection::deleteCollectionJobResult(QueuedJob *job)  emit \
collectionDeleted(this);  }
 
-BackendCollection::ApplicationPermission \
TempBlockingCollection::applicationPermission(const QString&) const \
+ApplicationPermission TempBlockingCollection::applicationPermission(const QString&) \
const  {
     // FIXME: is this the expected behavior in tempblockingcollection ?
-    return BackendCollection::PermissionAllow;
+    return PermissionAllow;
 }
 
-bool TempBlockingCollection::setApplicationPermission(const QString& , \
BackendCollection::ApplicationPermission) +bool \
TempBlockingCollection::setApplicationPermission(const QString& , \
ApplicationPermission)  {
     // FIXME: is this the expected behavior in tempblockingcollection ?
     return true;
 }
 
+bool TempBlockingCollection::setCreatorApplication(QString exePath)
+{
+    if ( m_creator.isEmpty() ) {
+        m_creator = exePath;
+        return true;
+    }
+    return false;
+}
+
 #include "tempblockingcollection.moc"
diff --git a/frontend/tests/tempblockingcollection.h \
b/frontend/tests/tempblockingcollection.h index c686eb5..25f3992 100644
--- a/frontend/tests/tempblockingcollection.h
+++ b/frontend/tests/tempblockingcollection.h
@@ -46,6 +46,10 @@ public:
     virtual ChangeAuthenticationCollectionJob *createChangeAuthenticationJob();
     virtual ApplicationPermission applicationPermission(const QString& path) const;
     virtual bool setApplicationPermission(const QString& path, ApplicationPermission \
perm); +    virtual bool setCreatorApplication(QString exePath);
+    virtual const QString &creatorApplication() const {
+        return m_creator;
+    }
 
 protected:
     BackendReturn<BackendItem*> createItem(const QString &label,
@@ -64,6 +68,7 @@ private:
     QString m_label;
     QDateTime m_created;
     QDateTime m_modified;
+    QString m_creator;
 
     QList<BackendItem*> m_items;
 };
diff --git a/lib/acl.h b/lib/acl.h
new file mode 100644
index 0000000..2b30623
--- /dev/null
+++ b/lib/acl.h
@@ -0,0 +1,35 @@
+/*
+ *  Copyright (C) 2010  Valentin Rusu <kde@rusu.info>
+ *
+ * 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 2 of
+ * the License or (at your option) version 3 or any later version
+ * accepted by the membership of KDE e.V. (or its successor approved
+ * by the membership of KDE e.V.), which shall act as a proxy
+ * defined in Section 14 of version 3 of the license.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * 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/>.
+ */
+
+#ifndef ACL_H
+#define ACL_H
+
+/**
+* Application permissions stored inside the backend file
+*/
+enum ApplicationPermission {
+    PermissionUndefined = -1, /// invalid value used to detect code inconsistencies
+    PermissionAsk = 0,   /// ask every time
+    PermissionDeny = 1,  /// deny every time
+    PermissionAllow = 2  /// always allow
+};
+
+
+#endif // ACL_H
diff --git a/lib/peer.h b/lib/peer.h
index d05b3ff..8e0c69d 100644
--- a/lib/peer.h
+++ b/lib/peer.h
@@ -18,8 +18,8 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef DEAMON_PEER_H
-#define DEAMON_PEER_H
+#ifndef DAEMON_PEER_H
+#define DAEMON_PEER_H
 
 #include <QtCore/QtGlobal>
 #include <QtCore/QSharedDataPointer>
@@ -92,5 +92,5 @@ private:
     QSharedDataPointer<PeerData> d;
 };
 
-#endif // DEAMON_PEER_H
+#endif // DAEMON_PEER_H
 
diff --git a/ui/CMakeLists.txt b/ui/CMakeLists.txt
index 9f60fee..342da98 100644
--- a/ui/CMakeLists.txt
+++ b/ui/CMakeLists.txt
@@ -2,14 +2,21 @@ INCLUDE_DIRECTORIES (${CMAKE_CURRENT_SOURCE_DIR})
 ADD_SUBDIRECTORY (tests)
 
 SET (ksecretservice_ui_SRCS
-   abstractuijobs.cpp
-   abstractacljobs.cpp
-   dialogaskaclprefsjob.cpp
-   nouiaskaclprefsjob.cpp
-   abstractacljobs.cpp
-   dialoguimanager.cpp
-   nouimanager.cpp
+    abstractuijobs.cpp
+    abstractacljobs.cpp
+    dialogaskaclprefsjob.cpp
+    nouiaskaclprefsjob.cpp
+    abstractacljobs.cpp
+    dialoguimanager.cpp
+    nouimanager.cpp
+    dialogaskcreateaclprefs.cpp
+    dialogaskunlockaclprefs.cpp
 )
 
+KDE4_ADD_UI_FILES( ksecretservice_ui_SRCS
+    dialogaskcreateaclprefs.ui
+    dialogaskunlockaclprefs.ui
+)
+    
 KDE4_ADD_LIBRARY (ksecretserviceui STATIC ${ksecretservice_ui_SRCS})
 TARGET_LINK_LIBRARIES (ksecretserviceui ${KDE4_KDEUI_LIBS} ${QCA2_LIBRARIES})
diff --git a/ui/abstractacljobs.cpp b/ui/abstractacljobs.cpp
index 3375ffc..9ea69a3 100644
--- a/ui/abstractacljobs.cpp
+++ b/ui/abstractacljobs.cpp
@@ -19,12 +19,14 @@
  */
 
 #include "abstractacljobs.h"
+#include "backend/backendcollection.h"
 #include <QtGui/QDialog>
 
 AbstractAskAclPrefsJob::AbstractAskAclPrefsJob(AbstractUiManager *manager,
         const CollectionCreateInfo &jobInfo) :
     AbstractUiJob(manager),
-    m_denied(false)
+    m_denied(false),
+    m_permission(PermissionUndefined)
 {
     m_jobHelper = new AskAclPrefsJobHelper< CollectionCreateInfo >(jobInfo);
 }
@@ -32,18 +34,31 @@ AbstractAskAclPrefsJob::AbstractAskAclPrefsJob(AbstractUiManager \
*manager,  AbstractAskAclPrefsJob::AbstractAskAclPrefsJob(AbstractUiManager *manager,
         const CollectionUnlockInfo &jobInfo) :
     AbstractUiJob(manager),
-    m_denied(false)
+    m_denied(false),
+    m_permission(PermissionUndefined)
 {
     m_jobHelper = new AskAclPrefsJobHelper< CollectionUnlockInfo >(jobInfo);
 }
 
-void AbstractAskAclPrefsJob::dialogFinished(int result)
-{
-    if(result == QDialog::Accepted) {
 
-    }
-    emitResult();
+template <> 
+QString AskAclPrefsJobHelper< CollectionCreateInfo >::collectionLabel() const {
+    return m_jobInfo.m_label;
+}
+
+template <> 
+QString AskAclPrefsJobHelper< CollectionCreateInfo >::collectionCreatorApplication() \
const { +    return m_jobInfo.m_peer.exePath();
 }
 
+template <>
+QString AskAclPrefsJobHelper< CollectionUnlockInfo >::collectionLabel() const {
+    return m_jobInfo.m_collection->label().value();
+}
+
+template <> 
+QString AskAclPrefsJobHelper< CollectionUnlockInfo >::collectionCreatorApplication() \
const { +    return m_jobInfo.m_collection->creatorApplication();
+}
 
 #include "abstractacljobs.moc"
diff --git a/ui/abstractacljobs.h b/ui/abstractacljobs.h
index a647e75..e224a47 100644
--- a/ui/abstractacljobs.h
+++ b/ui/abstractacljobs.h
@@ -23,6 +23,7 @@
 
 #include "abstractuijobs.h"
 #include <jobinfostructs.h>
+#include <acl.h>
 
 class AskAclPrefsJobHelperBase
 {
@@ -30,7 +31,9 @@ public:
     AskAclPrefsJobHelperBase() {}
     virtual ~AskAclPrefsJobHelperBase() {}
 
-    virtual const JobBaseInfo &jobInfo() const = 0;
+    virtual const Peer &peer() const = 0;
+    virtual QString collectionLabel() const = 0;
+    virtual QString collectionCreatorApplication() const =0;
 };
 
 template <class INFO>
@@ -39,14 +42,27 @@ class AskAclPrefsJobHelper : public AskAclPrefsJobHelperBase
 public:
     AskAclPrefsJobHelper(const INFO &jobInfo) : m_jobInfo(jobInfo) {}
 
-    virtual const JobBaseInfo &jobInfo() const {
-        return m_jobInfo;
+    virtual const Peer &peer() const {
+        return m_jobInfo.m_peer;
+    }
+    
+    virtual QString collectionLabel() const {
+        throw 1; // this must be implemented via template specialization
     }
 
+    virtual QString collectionCreatorApplication() const {
+        throw 1; // this must be implemented via template specialization
+    }
+    
 private:
     INFO m_jobInfo;
 };
 
+template <> QString AskAclPrefsJobHelper< CollectionCreateInfo >::collectionLabel() \
const; +
+template <> QString AskAclPrefsJobHelper< CollectionUnlockInfo >::collectionLabel() \
const; +template <> QString AskAclPrefsJobHelper< CollectionUnlockInfo \
>::collectionCreatorApplication() const; +
 /**
  * Job that asks ACL handling user preferences
  */
@@ -58,21 +74,26 @@ public:
     AbstractAskAclPrefsJob(AbstractUiManager *manager, const CollectionCreateInfo \
                &jobInfo);
     AbstractAskAclPrefsJob(AbstractUiManager *manager, const CollectionUnlockInfo \
&jobInfo);  
-    // const CollectionCreateInfo &createCollectionInfo() const { return \
                dynamic_cast<const CollectionCreateInfo&>( m_jobHelper->jobInfo() ); \
                }
-
     bool denied() const {
         return m_denied;
     }
     void setDenied(bool denied) {
         m_denied = denied;
     }
-
-protected Q_SLOTS:
-    void dialogFinished(int);
+    const AskAclPrefsJobHelperBase *jobHelper() const { 
+        return m_jobHelper; 
+    }
+    void setPermission( ApplicationPermission permission ) {
+        m_permission = permission;
+    }
+    ApplicationPermission permission() const {
+        return m_permission;
+    }
 
 private:
     AskAclPrefsJobHelperBase*  m_jobHelper;
     bool m_denied;
+    ApplicationPermission m_permission;
 };
 
 #endif // ABSTRACTACLJOBS_H
diff --git a/ui/abstractuijobs.cpp b/ui/abstractuijobs.cpp
index 26207ed..8dd96aa 100644
--- a/ui/abstractuijobs.cpp
+++ b/ui/abstractuijobs.cpp
@@ -24,7 +24,8 @@
 #include <QtCore/QEventLoop>
 #include <QtCore/QTimer>
 
-AbstractUiJob::AbstractUiJob(AbstractUiManager *manager) : QueuedJob(manager)
+AbstractUiJob::AbstractUiJob(AbstractUiManager *manager) : 
+    QueuedJob(manager), m_cancelled(false)
 {
 }
 
@@ -40,8 +41,7 @@ void AbstractUiJob::exec()
 AbstractAskPasswordJob::AbstractAskPasswordJob(AbstractUiManager *manager,
         const QString &collection,
         bool secondTry)
-    : AbstractUiJob(manager), m_collection(collection), m_secondTry(secondTry),
-      m_cancelled(false)
+    : AbstractUiJob(manager), m_collection(collection), m_secondTry(secondTry)
 {
 }
 
@@ -59,21 +59,11 @@ bool AbstractAskPasswordJob::isSecondTry() const
     return m_secondTry;
 }
 
-bool AbstractAskPasswordJob::cancelled() const
-{
-    return m_cancelled;
-}
-
 const QCA::SecureArray &AbstractAskPasswordJob::password() const
 {
     return m_password;
 }
 
-void AbstractAskPasswordJob::setCancelled(bool cancelled)
-{
-    m_cancelled = cancelled;
-}
-
 void AbstractAskPasswordJob::setPassword(const QCA::SecureArray &password)
 {
     m_password = password;
@@ -81,7 +71,7 @@ void AbstractAskPasswordJob::setPassword(const QCA::SecureArray \
&password)  
 AbstractNewPasswordJob::AbstractNewPasswordJob(AbstractUiManager* manager,
         const QString& collection)
-    : AbstractUiJob(manager), m_collection(collection), m_cancelled(false)
+    : AbstractUiJob(manager), m_collection(collection)
 {
 }
 
@@ -94,21 +84,11 @@ const QString &AbstractNewPasswordJob::collection() const
     return m_collection;
 }
 
-bool AbstractNewPasswordJob::cancelled() const
-{
-    return m_cancelled;
-}
-
 const QCA::SecureArray &AbstractNewPasswordJob::password() const
 {
     return m_password;
 }
 
-void AbstractNewPasswordJob::setCancelled(bool cancelled)
-{
-    m_cancelled = cancelled;
-}
-
 void AbstractNewPasswordJob::setPassword(const QCA::SecureArray &password)
 {
     m_password = password;
diff --git a/ui/abstractuijobs.h b/ui/abstractuijobs.h
index 5c0da14..23ec954 100644
--- a/ui/abstractuijobs.h
+++ b/ui/abstractuijobs.h
@@ -56,9 +56,28 @@ public:
      * run synchronously, exec() crashes.
      */
     virtual void exec();
+    /**
+     * Check if the dialog was cancelled by the user.
+     *
+     * @return true if the user cancelled false else
+     */
+    bool cancelled() const { 
+        return m_cancelled; 
+    }
 
+protected:
+    /**
+     * Set if the user cancels the UI operation.
+     *
+     * @param cancelled true if the user cancelled the dialog, false if not
+     */
+    void setCancelled(bool cancelled =true) {
+        m_cancelled = cancelled;
+    }
+    
 private:
     friend class UiJobManager;
+    bool m_cancelled;              // true if the operation was cancelled
 };
 
 /**
@@ -96,13 +115,6 @@ public:
     bool isSecondTry() const;
 
     /**
-     * Check if the dialog was cancelled by the user.
-     *
-     * @return true if the user cancelled instead of entering a password, false if \
                not
-     */
-    bool cancelled() const;
-
-    /**
      * Get the password the user entered.
      *
      * @return the password entered by the user or an empty array if the user
@@ -111,12 +123,6 @@ public:
     const QCA::SecureArray &password() const;
 
 protected:
-    /**
-     * Set if the user cancels entering a password.
-     *
-     * @param cancelled true if the user cancelled the dialog, false if not
-     */
-    void setCancelled(bool cancelled);
 
     /**
      * Set the password entered by the user.
@@ -129,7 +135,6 @@ protected:
 private:
     QString m_collection;          // name of the collection to be unlocked
     bool m_secondTry;              // true if this is not the first try
-    bool m_cancelled;              // the result of the operation
     QCA::SecureArray m_password;   // the password entered by the user
 };
 
@@ -160,13 +165,6 @@ public:
     const QString &collection() const;
 
     /**
-     * Check if the dialog was cancelled by the user.
-     *
-     * @return true if the user cancelled instead of entering a password, false else
-     */
-    bool cancelled() const;
-
-    /**
      * Get the password the user entered.
      *
      * @return the password entered by the user or an empty array if the user
@@ -175,12 +173,6 @@ public:
     const QCA::SecureArray &password() const;
 
 protected:
-    /**
-     * Set if the user cancels entering a password.
-     *
-     * @param cancelled true if the user cancelled the dialog, false if not
-     */
-    void setCancelled(bool cancelled);
 
     /**
      * Set the password entered by the user.
@@ -189,7 +181,6 @@ protected:
 
 private:
     QString m_collection;          // name of the collection the password is for
-    bool m_cancelled;              // true if the operation was cancelled
     QCA::SecureArray m_password;   // the new password entered by the user
 };
 
diff --git a/ui/dialogaskaclprefsjob.cpp b/ui/dialogaskaclprefsjob.cpp
index 3ecf691..2b39ab7 100644
--- a/ui/dialogaskaclprefsjob.cpp
+++ b/ui/dialogaskaclprefsjob.cpp
@@ -19,41 +19,77 @@
  */
 
 #include "dialogaskaclprefsjob.h"
+#include "dialogaskcreateaclprefs.h"
+#include "dialogaskunlockaclprefs.h"
+#include <peer.h>
+
 #include <QtGui/QDialog>
 
 DialogAskCreateAclPrefsJob::DialogAskCreateAclPrefsJob(AbstractUiManager* manager,
         const CollectionCreateInfo& jobInfo):
-    AbstractAskAclPrefsJob(manager, jobInfo)
+    AbstractAskAclPrefsJob(manager, jobInfo),
+    m_dialog(0)
 {
 
 }
 
-void DialogAskCreateAclPrefsJob::exec()
+void DialogAskCreateAclPrefsJob::start()
 {
-    AbstractUiJob::exec();
+    Q_ASSERT( m_dialog == 0 );
+    m_dialog = new DialogAskCreateAclPrefs;
+    m_dialog->setCollectionLabel( jobHelper()->collectionLabel() );
+    m_dialog->setApplication( jobHelper()->peer().exePath() );
+    m_dialog->setAttribute(Qt::WA_DeleteOnClose, true);
+    connect(m_dialog, SIGNAL(finished(int)), this, SLOT(dialogFinished(int)));
+    m_dialog->show();
 }
 
-void DialogAskCreateAclPrefsJob::start()
+void DialogAskCreateAclPrefsJob::dialogFinished(int result)
 {
-
+    Q_ASSERT( m_dialog );
+    if(result == QDialog::Accepted) {
+        setPermission( m_dialog->permission() );
+    } else {
+        // TODO Is it necessary for this dialog to be canceled ? 
+        // In my opinion that would not be necessary, as the collection has just
+        // been created and we now really need to know what ACL handling would 
+        // apply to it.
+        Q_ASSERT(0);
+    }
+    emitResult();
 }
 
+
+
 DialogAskUnlockAclPrefsJob::DialogAskUnlockAclPrefsJob(AbstractUiManager* manager,
         const CollectionUnlockInfo& jobInfo):
-    AbstractAskAclPrefsJob(manager, jobInfo)
+    AbstractAskAclPrefsJob(manager, jobInfo),
+    m_dialog(0)
 {
 
 }
 
-void DialogAskUnlockAclPrefsJob::exec()
+void DialogAskUnlockAclPrefsJob::start()
 {
-    AbstractUiJob::exec();
+    Q_ASSERT( m_dialog == 0 );
+    m_dialog = new DialogAskUnlockAclPrefs;
+    m_dialog->setCollectionLabel( jobHelper()->collectionLabel() );
+    m_dialog->setApplication( jobHelper()->peer().exePath() );
+    m_dialog->setOriginalApplication( jobHelper()->collectionCreatorApplication() );
+    m_dialog->setAttribute(Qt::WA_DeleteOnClose, true);
+    connect(m_dialog, SIGNAL(finished(int)), this, SLOT(dialogFinished(int)));
+    m_dialog->show();
 }
 
-void DialogAskUnlockAclPrefsJob::start()
+void DialogAskUnlockAclPrefsJob::dialogFinished(int result)
 {
-
+    Q_ASSERT( m_dialog );
+    if(result == QDialog::Accepted) {
+        setPermission( m_dialog->permission() );
+    } else {
+        setCancelled(true);
+    }
+    emitResult();
 }
 
-
 #include "dialogaskaclprefsjob.moc"
diff --git a/ui/dialogaskaclprefsjob.h b/ui/dialogaskaclprefsjob.h
index 9a77769..c4f7ed9 100644
--- a/ui/dialogaskaclprefsjob.h
+++ b/ui/dialogaskaclprefsjob.h
@@ -34,12 +34,16 @@ public:
 
 protected:
     virtual void start();
-    virtual void exec();
+
+private Q_SLOTS:
+    void dialogFinished(int);
 
 private:
     DialogAskCreateAclPrefs *m_dialog;
 };
 
+class DialogAskUnlockAclPrefs;
+
 class DialogAskUnlockAclPrefsJob : public AbstractAskAclPrefsJob
 {
     Q_OBJECT
@@ -48,7 +52,12 @@ public:
 
 protected:
     virtual void start();
-    virtual void exec();
+    
+private Q_SLOTS:
+    void dialogFinished(int);
+    
+private:
+    DialogAskUnlockAclPrefs *m_dialog;
 };
 
 #endif // DIALOGASKACLPREFSJOB_H
diff --git a/ui/dialogaskcreateaclprefs.cpp b/ui/dialogaskcreateaclprefs.cpp
new file mode 100644
index 0000000..bdc0165
--- /dev/null
+++ b/ui/dialogaskcreateaclprefs.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2010, Valentin Rusu <kde@rusu.info>
+ *
+ * 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 2 of
+ * the License or (at your option) version 3 or any later version
+ * accepted by the membership of KDE e.V. (or its successor approved
+ * by the membership of KDE e.V.), which shall act as a proxy
+ * defined in Section 14 of version 3 of the license.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * 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/>.
+ */
+
+#include "dialogaskcreateaclprefs.h"
+
+#include <klocalizedstring.h>
+#include <QLabel>
+
+DialogAskCreateAclPrefs::DialogAskCreateAclPrefs(QWidget* parent): 
+    KDialog(parent),
+    m_widget(0)
+{
+    setCaption( tr2i18n("New Collection Access Policy") );
+    setButtons( KDialog::Ok );
+    m_widget = new AskCreateAclPrefsWidget( this );    
+    setMainWidget( m_widget );
+}
+
+void DialogAskCreateAclPrefs::setCollectionLabel(const QString& label)
+{
+    QString locString = i18n( "You just created a KSecretService collection named \
'%1'.", label ); +    m_widget->m_explainCollectionLabel->setText( locString );
+}
+
+void DialogAskCreateAclPrefs::setApplication(QString exePath)
+{
+    QString locString = i18n( "You used '%1' application to create this \
collection.", exePath ); +    m_widget->m_explainApplicationLabel->setText( locString \
); +}
+
+ApplicationPermission DialogAskCreateAclPrefs::permission() const
+{
+    if ( m_widget->m_permissionAllowRadio->isChecked() )
+        return PermissionAllow;
+    if ( m_widget->m_permissionAskRadio->isChecked() )
+        return PermissionAsk;
+    // we should never get here as per current dialog design
+    Q_ASSERT(0);
+    return PermissionDeny;
+}
+
+AskCreateAclPrefsWidget::AskCreateAclPrefsWidget( QWidget *parent ) :
+    QWidget( parent )
+{
+    setupUi( this );
+}
+
diff --git a/ui/dialogaskcreateaclprefs.h b/ui/dialogaskcreateaclprefs.h
new file mode 100644
index 0000000..4a16408
--- /dev/null
+++ b/ui/dialogaskcreateaclprefs.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2010, Valentin Rusu <kde@rusu.info>
+ *
+ * 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 2 of
+ * the License or (at your option) version 3 or any later version
+ * accepted by the membership of KDE e.V. (or its successor approved
+ * by the membership of KDE e.V.), which shall act as a proxy
+ * defined in Section 14 of version 3 of the license.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * 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/>.
+ */
+
+#ifndef DIALOGASKCREATEACLPREFS_H
+#define DIALOGASKCREATEACLPREFS_H
+
+#include <ui_dialogaskcreateaclprefs.h>
+#include <acl.h>
+
+#include <kdialog.h>
+
+class AskCreateAclPrefsWidget;
+
+class DialogAskCreateAclPrefs : public KDialog
+{
+    Q_OBJECT
+public:
+    explicit DialogAskCreateAclPrefs(QWidget* parent = 0);
+
+    void setCollectionLabel( const QString& label );
+    void setApplication(QString exePath);
+    
+    ApplicationPermission permission() const;
+
+private:
+    AskCreateAclPrefsWidget* m_widget;
+};
+
+class AskCreateAclPrefsWidget : public QWidget, public Ui_AskCreateAclPrefsWidget
+{
+    Q_OBJECT
+public:
+    explicit AskCreateAclPrefsWidget( QWidget* parent );
+};
+
+#endif // DIALOGASKCREATEACLPREFS_H
diff --git a/ui/dialogaskcreateaclprefs.ui b/ui/dialogaskcreateaclprefs.ui
new file mode 100644
index 0000000..32d8982
--- /dev/null
+++ b/ui/dialogaskcreateaclprefs.ui
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AskCreateAclPrefsWidget</class>
+ <widget class="QWidget" name="AskCreateAclPrefsWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>385</width>
+    <height>169</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_2">
+   <item>
+    <widget class="QLabel" name="m_explainCollectionLabel">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="text">
+      <string>You just created a KSecretService collection named '%1'.</string>
+     </property>
+     <property name="wordWrap">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLabel" name="m_explainApplicationLabel">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="text">
+      <string>You used '%1' application to create this collection.</string>
+     </property>
+     <property name="wordWrap">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLabel" name="m_explainQuestionLabel">
+     <property name="text">
+      <string>What do you expect KSecretService to do each time this application \
accesses this collection ?</string> +     </property>
+     <property name="wordWrap">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupBox">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="title">
+      <string/>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout">
+      <item>
+       <widget class="QRadioButton" name="m_permissionAllowRadio">
+        <property name="text">
+         <string>Always allow access to this application
+without asking for the password</string>
+        </property>
+        <property name="checked">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QRadioButton" name="m_permissionAskRadio">
+        <property name="text">
+         <string>Ask for the password each time
+the application opens this collection</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer name="verticalSpacer">
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeType">
+         <enum>QSizePolicy::Expanding</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>1</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/ui/dialogaskunlockaclprefs.cpp b/ui/dialogaskunlockaclprefs.cpp
new file mode 100644
index 0000000..a342641
--- /dev/null
+++ b/ui/dialogaskunlockaclprefs.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2010, Valentin Rusu <kde@rusu.info>
+ *
+ * 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 2 of
+ * the License or (at your option) version 3 or any later version
+ * accepted by the membership of KDE e.V. (or its successor approved
+ * by the membership of KDE e.V.), which shall act as a proxy
+ * defined in Section 14 of version 3 of the license.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * 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/>.
+ */
+
+#include "dialogaskunlockaclprefs.h"
+
+#include <klocalizedstring.h>
+#include <QLabel>
+
+DialogAskUnlockAclPrefs::DialogAskUnlockAclPrefs(QWidget* parent): 
+    KDialog(parent),
+    m_widget(0)
+{
+    setCaption( tr2i18n("Unlock Collection Access Policy") );
+    setButtons( KDialog::Ok );
+    m_widget = new AskUnlockAclPrefsWidget( this );    
+    setMainWidget( m_widget );
+}
+
+void DialogAskUnlockAclPrefs::setApplication(QString exePath)
+{
+    // setCollectionLabel must have been called first
+    Q_ASSERT( ! m_collectionLabel.isEmpty() );
+    QString locString = i18n( "The application '%1' asked to open the KSecretService \
collection named '%2'.", +                              exePath, m_collectionLabel );
+    m_widget->m_explainCollectionLabel->setText( locString );
+}
+
+void DialogAskUnlockAclPrefs::setCollectionLabel(const QString& label)
+{
+    m_collectionLabel = label;
+}
+
+void DialogAskUnlockAclPrefs::setOriginalApplication(const QString& exePath)
+{
+    QString locString = i18n( "This collection was created by the application '%1'. \
What should KSecretService do now ?", +                              exePath );
+    m_widget->m_explainApplicationLabel->setText( locString );
+}
+
+ApplicationPermission DialogAskUnlockAclPrefs::permission() const
+{
+    if ( m_widget->m_permissionAllowRadio->isChecked() )
+        return PermissionAllow;
+    if ( m_widget->m_permissionAskRadio->isChecked() )
+        return PermissionAsk;
+    if ( m_widget->m_permissionDenyRadio->isChecked() )
+        return PermissionDeny;
+    Q_ASSERT(0); // we should never reach here !
+    return PermissionDeny;
+}
+
+AskUnlockAclPrefsWidget::AskUnlockAclPrefsWidget( QWidget *parent ) :
+    QWidget( parent )
+{
+    setupUi( this );
+}
+
+#include "dialogaskunlockaclprefs.moc"
diff --git a/ui/dialogaskunlockaclprefs.h b/ui/dialogaskunlockaclprefs.h
new file mode 100644
index 0000000..e0b6f10
--- /dev/null
+++ b/ui/dialogaskunlockaclprefs.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2010, Valentin Rusu <kde@rusu.info>
+ *
+ * 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 2 of
+ * the License or (at your option) version 3 or any later version
+ * accepted by the membership of KDE e.V. (or its successor approved
+ * by the membership of KDE e.V.), which shall act as a proxy
+ * defined in Section 14 of version 3 of the license.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * 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/>.
+ */
+
+#ifndef DIALOGASKUNLOCKACLPREFS_H
+#define DIALOGASKUNLOCKACLPREFS_H
+
+#include <ui_dialogaskunlockaclprefs.h>
+#include <acl.h>
+
+#include <kdialog.h>
+
+class AskUnlockAclPrefsWidget;
+
+class DialogAskUnlockAclPrefs : public KDialog
+{
+    Q_OBJECT
+public:
+    explicit DialogAskUnlockAclPrefs(QWidget* parent = 0);
+
+    void setCollectionLabel( const QString& label );
+    void setApplication(QString exePath);
+    void setOriginalApplication( const QString& exePath );
+    
+    ApplicationPermission permission() const;
+
+private:
+    AskUnlockAclPrefsWidget* m_widget;
+    QString m_collectionLabel;
+};
+
+class AskUnlockAclPrefsWidget : public QWidget, public Ui_AskUnlockAclPrefsWidget
+{
+    Q_OBJECT
+public:
+    explicit AskUnlockAclPrefsWidget( QWidget* parent );
+};
+
+#endif // DIALOGASKUNLOCKACLPREFS_H
diff --git a/ui/dialogaskunlockaclprefs.ui b/ui/dialogaskunlockaclprefs.ui
new file mode 100644
index 0000000..ce94bd5
--- /dev/null
+++ b/ui/dialogaskunlockaclprefs.ui
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>AskUnlockAclPrefsWidget</class>
+ <widget class="QWidget" name="AskUnlockAclPrefsWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>385</width>
+    <height>198</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string>Form</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_2">
+   <item>
+    <widget class="QLabel" name="m_explainCollectionLabel">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="text">
+      <string>The application '%1' asked to open the KSecretService collection named \
'%2'.</string> +     </property>
+     <property name="wordWrap">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLabel" name="m_explainApplicationLabel">
+     <property name="text">
+      <string>This collection was created by the application '%1'. What should \
KSecretService do now ?</string> +     </property>
+     <property name="wordWrap">
+      <bool>true</bool>
+     </property>
+    </widget>
+   </item>
+   <item>
+    <widget class="QGroupBox" name="groupBox">
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="title">
+      <string>Choose application access policy</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout">
+      <item>
+       <widget class="QRadioButton" name="m_permissionAllowRadio">
+        <property name="text">
+         <string>Allways allow access to this application
+without asking for the password</string>
+        </property>
+        <property name="checked">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QRadioButton" name="m_permissionAskRadio">
+        <property name="text">
+         <string>Ask for the password each time
+the application opens this collection</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QRadioButton" name="m_permissionDenyRadio">
+        <property name="text">
+         <string>Deny access to this application !</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <spacer name="verticalSpacer">
+        <property name="orientation">
+         <enum>Qt::Vertical</enum>
+        </property>
+        <property name="sizeHint" stdset="0">
+         <size>
+          <width>20</width>
+          <height>1</height>
+         </size>
+        </property>
+       </spacer>
+      </item>
+     </layout>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/ui/nouiaskaclprefsjob.cpp b/ui/nouiaskaclprefsjob.cpp
index ee57d1f..46ed363 100644
--- a/ui/nouiaskaclprefsjob.cpp
+++ b/ui/nouiaskaclprefsjob.cpp
@@ -37,6 +37,7 @@ NoUiAskAclPrefsJob::NoUiAskAclPrefsJob(AbstractUiManager* manager,
 void NoUiAskAclPrefsJob::start()
 {
     setDenied(false);
+    setPermission( PermissionAllow );
     emitResult();
 }
 
diff --git a/ui/tests/CMakeLists.txt b/ui/tests/CMakeLists.txt
index a05f9e8..08f45e8 100644
--- a/ui/tests/CMakeLists.txt
+++ b/ui/tests/CMakeLists.txt
@@ -16,4 +16,13 @@ TARGET_LINK_LIBRARIES (nouimanager_test
    ${QT_QTTEST_LIBRARIES}
 )
 
+KDE4_ADD_EXECUTABLE (dialogaskaclprefs_test dialogaskaclprefstest.cpp )
+TARGET_LINK_LIBRARIES( dialogaskaclprefs_test
+   ksecretserviceui
+   ksecretservicelib
+   ${QT_QTTEST_LIBRARIES}
+)
+
 ADD_TEST (NoUiManagerTest nouimanager_test)
+#ADD_TEST (DialogUiManagerTest dialoguimanager_test)
+ADD_TEST (DialogAskAclPrefsTest dialogaskaclprefs_test )
diff --git a/ui/tests/dialogaskaclprefstest.cpp b/ui/tests/dialogaskaclprefstest.cpp
new file mode 100644
index 0000000..3a751dd
--- /dev/null
+++ b/ui/tests/dialogaskaclprefstest.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2010, Valentin Rusu <kde@rusu.info>
+ *
+ * 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 2 of
+ * the License or (at your option) version 3 or any later version
+ * accepted by the membership of KDE e.V. (or its successor approved
+ * by the membership of KDE e.V.), which shall act as a proxy
+ * defined in Section 14 of version 3 of the license.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * 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/>.
+ */
+
+#include "dialogaskaclprefstest.h"
+#include "../dialoguimanager.h"
+
+#include <QtCrypto/QtCrypto>
+#include <qtest_kde.h>
+
+void DialogAskAclPrefsTest::initTestCase()
+{
+    QCA::init();
+}
+
+void DialogAskAclPrefsTest::testDialogAskCreateAclPrefsJob()
+{
+    DialogUiManager fact;
+    Peer peer( QCoreApplication::applicationPid() );
+    CollectionCreateInfo jobInfo( "TestCollection", peer );
+    AbstractAskAclPrefsJob *askJob = fact.createAskAclPrefsJob( jobInfo );
+    QEventLoop loop;
+    connect( askJob, SIGNAL(result(QueuedJob*)), &loop, SLOT(quit()) );
+    askJob->enqueue();
+    loop.exec();
+}
+
+void DialogAskAclPrefsTest::cleanupTestCase()
+{
+
+}
+
+
+QTEST_KDEMAIN(DialogAskAclPrefsTest, GUI)
+#include "dialogaskaclprefstest.moc"
diff --git a/ui/tests/dialogaskaclprefstest.h b/ui/tests/dialogaskaclprefstest.h
new file mode 100644
index 0000000..9eedcce
--- /dev/null
+++ b/ui/tests/dialogaskaclprefstest.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2010, Valentin Rusu <kde@rusu.info>
+ *
+ * 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 2 of
+ * the License or (at your option) version 3 or any later version
+ * accepted by the membership of KDE e.V. (or its successor approved
+ * by the membership of KDE e.V.), which shall act as a proxy
+ * defined in Section 14 of version 3 of the license.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * 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/>.
+ */
+
+
+#ifndef DIALOGASKACLPREFSTEST_H
+#define DIALOGASKACLPREFSTEST_H
+
+#include <QtCore/QObject>
+
+
+class DialogAskAclPrefsTest : public QObject
+{
+    Q_OBJECT
+private Q_SLOTS:
+    void initTestCase();
+    
+    void testDialogAskCreateAclPrefsJob();
+    
+    void cleanupTestCase();
+};
+
+#endif // DIALOGASKACLPREFSTEST_H


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic