[libsecret/wip/dueno/search] password: Add secret_password_search* functions



commit 7716449b1ddfec4dea0f226cad7daa473f07772d
Author: Daiki Ueno <dueno src gnome org>
Date:   Fri Oct 19 08:33:49 2018 +0200

    password: Add secret_password_search* functions
    
    Previously there were no functions in the simple API that return the
    matched attributes other than the secret value, while there were needs
    for augumenting user input with additional information (such as
    completing web forms).
    
    This adds a set of functions which wrap secret_service_search*.  Note
    that the return value is a list of GHashTable not of SecretItem,
    because SecretItem is a subclass of GDBusProxy, which we don't want to
    expose from the simple API.
    
    Fixes #16

 libsecret/secret-password.c | 225 ++++++++++++++++++++++++++++++++++++++++++++
 libsecret/secret-password.h |  29 ++++++
 libsecret/secret-service.h  |   7 --
 libsecret/secret-types.h    |   7 ++
 libsecret/test-password.c   |  88 +++++++++++++++++
 5 files changed, 349 insertions(+), 7 deletions(-)
---
diff --git a/libsecret/secret-password.c b/libsecret/secret-password.c
index 149995d..4e388e1 100644
--- a/libsecret/secret-password.c
+++ b/libsecret/secret-password.c
@@ -844,6 +844,231 @@ secret_password_clearv_sync (const SecretSchema *schema,
        return result;
 }
 
+/**
+ * secret_password_search: (skip)
+ * @schema: the schema for the attributes
+ * @flags: search option flags
+ * @cancellable: optional cancellation object
+ * @callback: called when the operation completes
+ * @user_data: data to be passed to the callback
+ * @...: the attribute keys and values, terminated with %NULL
+ *
+ * Search for items in the secret service.
+ *
+ * The variable argument list should contain pairs of a) The attribute name as
+ * a null-terminated string, followed by b) attribute value, either a character
+ * string, an int number, or a gboolean value, as defined in the password
+ * @schema. The list of attribtues should be terminated with a %NULL.
+ *
+ * This method will return immediately and complete asynchronously.
+ *
+ * Since: 0.18.7
+ */
+void
+secret_password_search (const SecretSchema *schema,
+                        SecretSearchFlags flags,
+                        GCancellable *cancellable,
+                        GAsyncReadyCallback callback,
+                        gpointer user_data,
+                        ...)
+{
+        GHashTable *attributes;
+        va_list va;
+
+        g_return_if_fail (schema != NULL);
+        g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+        va_start (va, user_data);
+        attributes = secret_attributes_buildv (schema, va);
+        va_end (va);
+
+        /* Precondition failed, already warned */
+        if (!attributes)
+                return;
+
+        secret_password_searchv (schema, attributes, flags, cancellable,
+                                 callback, user_data);
+
+        g_hash_table_unref (attributes);
+}
+
+/**
+ * secret_password_searchv: (rename-to secret_password_search)
+ * @schema: the schema for attributes
+ * @attributes: (element-type utf8 utf8): the attribute keys and values
+ * @flags: search option flags
+ * @cancellable: optional cancellation object
+ * @callback: called when the operation completes
+ * @user_data: data to be passed to the callback
+ *
+ * Search for items in the secret service.
+ *
+ * The @attributes should be a set of key and value string pairs.
+ *
+ * This method will return immediately and complete asynchronously.
+ *
+ * Since: 0.18.7
+ */
+void
+secret_password_searchv (const SecretSchema *schema,
+                         GHashTable *attributes,
+                         SecretSearchFlags flags,
+                         GCancellable *cancellable,
+                         GAsyncReadyCallback callback,
+                         gpointer user_data)
+{
+        g_return_if_fail (schema != NULL);
+        g_return_if_fail (attributes != NULL);
+        g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+        /* Warnings raised already */
+        if (!_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
+                return;
+
+        secret_service_search (NULL, schema, attributes, flags,
+                               cancellable, callback, user_data);
+}
+
+/**
+ * secret_password_search_finish:
+ * @result: the asynchronous result passed to the callback
+ * @error: location to place an error on failure
+ *
+ * Finish an asynchronous operation to search for items in the secret service.
+ *
+ * Returns: (transfer full) (element-type GHashTable): a list of hash tables containing attributes of the 
matched items
+ * Since: 0.18.7
+ */
+GList *
+secret_password_search_finish (GAsyncResult *result,
+                               GError **error)
+{
+        GList *value;
+        GList *items = NULL;
+
+        g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+        value = secret_service_search_finish (NULL, result, error);
+        while (value) {
+                SecretItem *item = SECRET_ITEM (value->data);
+                GHashTable *attributes = secret_item_get_attributes (item);
+                items = g_list_append (items, attributes);
+                g_object_unref (item);
+                value = g_list_delete_link (value, value);
+        }
+
+        return items;
+}
+
+/**
+ * secret_password_search_sync: (skip)
+ * @schema: the schema for the attributes
+ * @flags: search option flags
+ * @cancellable: optional cancellation object
+ * @error: location to place an error on failure
+ * @...: the attribute keys and values, terminated with %NULL
+ *
+ * Search for items in the secret service.
+ *
+ * The variable argument list should contain pairs of a) The attribute name as
+ * a null-terminated string, followed by b) attribute value, either a character
+ * string, an int number, or a gboolean value, as defined in the password
+ * @schema. The list of attributes should be terminated with a %NULL.
+ *
+ * If no secret is found then %NULL is returned.
+ *
+ * This method may block indefinitely and should not be used in user interface
+ * threads.
+ *
+ * Returns: (transfer full) (element-type GHashTable): a list of hash tables containing attributes of the 
matched items
+ * Since: 0.18.7
+ */
+GList *
+secret_password_search_sync (const SecretSchema *schema,
+                             SecretSearchFlags flags,
+                             GCancellable *cancellable,
+                             GError **error,
+                             ...)
+{
+        GHashTable *attributes;
+        GList *items;
+        va_list va;
+
+        g_return_val_if_fail (schema != NULL, NULL);
+        g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+        g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+        va_start (va, error);
+        attributes = secret_attributes_buildv (schema, va);
+        va_end (va);
+
+        /* Precondition failed, already warned */
+        if (!attributes)
+                return NULL;
+
+        items = secret_password_searchv_sync (schema, attributes, flags,
+                                              cancellable, error);
+
+        g_hash_table_unref (attributes);
+
+        return items;
+}
+
+/**
+ * secret_password_searchv_sync: (rename-to secret_password_search_sync)
+ * @schema: the schema for attributes
+ * @attributes: (element-type utf8 utf8): the attribute keys and values
+ * @flags: search option flags
+ * @cancellable: optional cancellation object
+ * @error: location to place an error on failure
+ *
+ * Search for items in the secret service.
+ *
+ * The @attributes should be a set of key and value string pairs.
+ *
+ * If no secret is found then %NULL is returned.
+ *
+ * This method may block indefinitely and should not be used in user interface
+ * threads.
+ *
+ * Returns: (transfer full) (element-type GHashTable): a list of hash tables containing attributes of the 
matched items
+ * Since: 0.18.7
+ */
+GList *
+secret_password_searchv_sync (const SecretSchema *schema,
+                              GHashTable *attributes,
+                              SecretSearchFlags flags,
+                              GCancellable *cancellable,
+                              GError **error)
+{
+        SecretSync *sync;
+        GList *items;
+
+        g_return_val_if_fail (schema != NULL, NULL);
+        g_return_val_if_fail (attributes != NULL, NULL);
+        g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), NULL);
+        g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+        /* Warnings raised already */
+        if (!_secret_attributes_validate (schema, attributes, G_STRFUNC, TRUE))
+                return NULL;
+
+        sync = _secret_sync_new ();
+        g_main_context_push_thread_default (sync->context);
+
+        secret_password_searchv (schema, attributes, flags, cancellable,
+                                 _secret_sync_on_result, sync);
+
+        g_main_loop_run (sync->loop);
+
+        items = secret_password_search_finish (sync->result, error);
+
+        g_main_context_pop_thread_default (sync->context);
+        _secret_sync_free (sync);
+
+        return items;
+}
+
 /**
  * secret_password_free: (skip)
  * @password: (allow-none): password to free
diff --git a/libsecret/secret-password.h b/libsecret/secret-password.h
index d47abb3..725d11b 100644
--- a/libsecret/secret-password.h
+++ b/libsecret/secret-password.h
@@ -126,6 +126,35 @@ gboolean    secret_password_clearv_sync                (const SecretSchema *sche
                                                         GCancellable *cancellable,
                                                         GError **error);
 
+void        secret_password_search                     (const SecretSchema *schema,
+                                                        SecretSearchFlags flags,
+                                                        GCancellable *cancellable,
+                                                        GAsyncReadyCallback callback,
+                                                        gpointer user_data,
+                                                        ...) G_GNUC_NULL_TERMINATED;
+
+void        secret_password_searchv                    (const SecretSchema *schema,
+                                                        GHashTable *attributes,
+                                                        SecretSearchFlags flags,
+                                                        GCancellable *cancellable,
+                                                        GAsyncReadyCallback callback,
+                                                        gpointer user_data);
+
+GList *     secret_password_search_sync                (const SecretSchema *schema,
+                                                        SecretSearchFlags flags,
+                                                        GCancellable *cancellable,
+                                                        GError **error,
+                                                        ...) G_GNUC_NULL_TERMINATED;
+
+GList *     secret_password_searchv_sync               (const SecretSchema *schema,
+                                                        GHashTable *attributes,
+                                                        SecretSearchFlags flags,
+                                                        GCancellable *cancellable,
+                                                        GError **error);
+
+GList *     secret_password_search_finish              (GAsyncResult *result,
+                                                        GError **error);
+
 void        secret_password_free                       (gchar *password);
 
 void        secret_password_wipe                       (gchar *password);
diff --git a/libsecret/secret-service.h b/libsecret/secret-service.h
index e35f415..d46705e 100644
--- a/libsecret/secret-service.h
+++ b/libsecret/secret-service.h
@@ -35,13 +35,6 @@ typedef enum {
        SECRET_SERVICE_LOAD_COLLECTIONS = 1 << 2,
 } SecretServiceFlags;
 
-typedef enum {
-       SECRET_SEARCH_NONE = 0,
-       SECRET_SEARCH_ALL = 1 << 1,
-       SECRET_SEARCH_UNLOCK = 1 << 2,
-       SECRET_SEARCH_LOAD_SECRETS = 1 << 3,
-} SecretSearchFlags;
-
 #define SECRET_TYPE_SERVICE            (secret_service_get_type ())
 #define SECRET_SERVICE(inst)           (G_TYPE_CHECK_INSTANCE_CAST ((inst), SECRET_TYPE_SERVICE, 
SecretService))
 #define SECRET_SERVICE_CLASS(class)    (G_TYPE_CHECK_CLASS_CAST ((class), SECRET_TYPE_SERVICE, 
SecretServiceClass))
diff --git a/libsecret/secret-types.h b/libsecret/secret-types.h
index 708c53f..cbbd3b1 100644
--- a/libsecret/secret-types.h
+++ b/libsecret/secret-types.h
@@ -38,6 +38,13 @@ typedef enum {
 
 #define SECRET_COLLECTION_SESSION "session"
 
+typedef enum {
+       SECRET_SEARCH_NONE = 0,
+       SECRET_SEARCH_ALL = 1 << 1,
+       SECRET_SEARCH_UNLOCK = 1 << 2,
+       SECRET_SEARCH_LOAD_SECRETS = 1 << 3,
+} SecretSearchFlags;
+
 G_END_DECLS
 
 #endif /* __G_SERVICE_H___ */
diff --git a/libsecret/test-password.c b/libsecret/test-password.c
index b745427..7e346c9 100644
--- a/libsecret/test-password.c
+++ b/libsecret/test-password.c
@@ -354,6 +354,90 @@ test_clear_no_name (Test *test,
        g_assert (ret == TRUE);
 }
 
+static void
+free_attributes (gpointer data,
+                 gpointer user_data)
+{
+        g_hash_table_unref ((GHashTable *)data);
+}
+
+static void
+test_search_sync (Test *test,
+                  gconstpointer used)
+{
+        GList *items;
+        GError *error = NULL;
+
+        items = secret_password_search_sync (&MOCK_SCHEMA, SECRET_SEARCH_ALL,
+                                            NULL, &error,
+                                             "even", FALSE,
+                                             "string", "one",
+                                             "number", 1,
+                                             NULL);
+
+        g_assert_no_error (error);
+        g_assert_cmpint (g_list_length (items), ==, 1);
+
+        g_list_foreach (items, free_attributes, NULL);
+        g_list_free (items);
+}
+
+static void
+test_search_async (Test *test,
+                   gconstpointer used)
+{
+        GAsyncResult *result = NULL;
+        GError *error = NULL;
+        GList *items;
+
+        secret_password_search (&MOCK_SCHEMA, SECRET_SEARCH_ALL,
+                               NULL, on_complete_get_result, &result,
+                                "even", FALSE,
+                                "string", "one",
+                                "number", 1,
+                                NULL);
+        g_assert (result == NULL);
+
+        egg_test_wait ();
+
+        items = secret_password_search_finish (result, &error);
+        g_assert_no_error (error);
+        g_object_unref (result);
+
+        g_assert_cmpint (g_list_length (items), ==, 1);
+
+        g_list_foreach (items, free_attributes, NULL);
+        g_list_free (items);
+}
+
+static void
+test_search_no_name (Test *test,
+                     gconstpointer used)
+{
+        GError *error = NULL;
+        GList *items;
+
+        /* should return null, because nothing with mock schema and 5 */
+        items = secret_password_search_sync (&MOCK_SCHEMA, SECRET_SEARCH_ALL,
+                                            NULL, &error,
+                                             "number", 5,
+                                             NULL);
+        g_assert_no_error (error);
+        g_assert (items == NULL);
+
+        /* should return an item, because we have a prime schema with 5, and flags not to match name */
+        items = secret_password_search_sync (&NO_NAME_SCHEMA, SECRET_SEARCH_ALL,
+                                            NULL, &error,
+                                             "number", 5,
+                                             NULL);
+
+        g_assert_no_error (error);
+        g_assert_cmpint (g_list_length (items), ==, 1);
+
+        g_list_foreach (items, free_attributes, NULL);
+        g_list_free (items);
+}
+
 static void
 test_password_free_null (void)
 {
@@ -381,6 +465,10 @@ main (int argc, char **argv)
        g_test_add ("/password/delete-async", Test, "mock-service-delete.py", setup, test_delete_async, 
teardown);
        g_test_add ("/password/clear-no-name", Test, "mock-service-delete.py", setup, test_clear_no_name, 
teardown);
 
+       g_test_add ("/password/search-sync", Test, "mock-service-normal.py", setup, test_search_sync, 
teardown);
+       g_test_add ("/password/search-async", Test, "mock-service-normal.py", setup, test_search_async, 
teardown);
+       g_test_add ("/password/search-no-name", Test, "mock-service-normal.py", setup, test_search_no_name, 
teardown);
+
        g_test_add_func ("/password/free-null", test_password_free_null);
 
        return egg_tests_run_with_loop ();


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]