[libsecret/wip/dueno/simple-item: 3/7] secret-password: Add search functions



commit cadd32cf4c1254729e109116e42e5bc502f2de5f
Author: Daiki Ueno <dueno src gnome org>
Date:   Mon Jun 17 15:30:00 2019 +0200

    secret-password: Add search functions
    
    This adds a set of functions that expose secret_service_search* from
    the simple API.

 libsecret/secret-password.c | 217 ++++++++++++++++++++++++++++++++++++++++++++
 libsecret/secret-password.h |  29 ++++++
 libsecret/secret-service.h  |   7 --
 libsecret/secret-types.h    |   7 ++
 libsecret/test-password.c   |  88 ++++++++++++++++++
 5 files changed, 341 insertions(+), 7 deletions(-)
---
diff --git a/libsecret/secret-password.c b/libsecret/secret-password.c
index 149995d..640519e 100644
--- a/libsecret/secret-password.c
+++ b/libsecret/secret-password.c
@@ -17,6 +17,7 @@
 #include "secret-attributes.h"
 #include "secret-password.h"
 #include "secret-private.h"
+#include "secret-retrievable.h"
 #include "secret-value.h"
 
 #include <egg/egg-secure-memory.h>
@@ -844,6 +845,222 @@ 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.
+ *
+ * Stability: Unstable
+ */
+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.
+ *
+ * Stability: Unstable
+ */
+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.
+ *
+ * Stability: Unstable
+ *
+ * Returns: (transfer full) (element-type Secret.Retrievable): a list of #SecretRetrievable containing 
attributes of the matched items
+ */
+GList *
+secret_password_search_finish (GAsyncResult *result,
+                               GError **error)
+{
+        g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+        return secret_service_search_finish (NULL, result, error);
+}
+
+/**
+ * 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.
+ *
+ * Stability: Unstable
+ *
+ * Returns: (transfer full) (element-type Secret.Retrievable): a list of #SecretRetrievable containing 
attributes of the matched items
+ */
+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.
+ *
+ * Stability: Unstable
+ *
+ * Returns: (transfer full) (element-type Secret.Retrievable): a list of #SecretRetrievable containing 
attributes of the matched items
+ */
+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 4c3a827..44cbc1e 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 ab95859..fbd706d 100644
--- a/libsecret/test-password.c
+++ b/libsecret/test-password.c
@@ -354,6 +354,90 @@ test_clear_no_name (Test *test,
        g_assert_true (ret);
 }
 
+static void
+free_attributes (gpointer data,
+                 gpointer user_data)
+{
+        g_object_unref ((GObject *)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)
 {
@@ -378,6 +462,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]