GitLab repository storage has been migrated to hashed layout. Please contact Infrastructure team if you notice any issues with repositories or hooks.

Commit 5fedca8f authored by Daiki Ueno's avatar Daiki Ueno Committed by Daiki Ueno

secret-password: Add search functions

This adds a set of functions that expose secret_service_search* from
the simple API.
parent 092d4ef4
...@@ -133,6 +133,11 @@ secret_password_clearv ...@@ -133,6 +133,11 @@ secret_password_clearv
secret_password_clear_finish secret_password_clear_finish
secret_password_clear_sync secret_password_clear_sync
secret_password_clearv_sync secret_password_clearv_sync
secret_password_search
secret_password_search_finish
secret_password_search_sync
secret_password_searchv
secret_password_searchv_sync
secret_password_wipe secret_password_wipe
secret_password_free secret_password_free
</SECTION> </SECTION>
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "secret-attributes.h" #include "secret-attributes.h"
#include "secret-password.h" #include "secret-password.h"
#include "secret-private.h" #include "secret-private.h"
#include "secret-retrievable.h"
#include "secret-value.h" #include "secret-value.h"
#include <egg/egg-secure-memory.h> #include <egg/egg-secure-memory.h>
...@@ -844,6 +845,225 @@ secret_password_clearv_sync (const SecretSchema *schema, ...@@ -844,6 +845,225 @@ secret_password_clearv_sync (const SecretSchema *schema,
return result; 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.19.0
*/
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.19.0
*/
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 Secret.Retrievable): a list of
* #SecretRetrievable containing attributes of the matched items
*
* Since: 0.19.0
*/
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.
*
* Returns: (transfer full) (element-type Secret.Retrievable): a list of
* #SecretRetrievable containing attributes of the matched items
*
* Since: 0.19.0
*/
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 Secret.Retrievable): a list of
* #SecretRetrievable containing attributes of the matched items
*
* Since: 0.19.0
*/
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) * secret_password_free: (skip)
* @password: (allow-none): password to free * @password: (allow-none): password to free
......
...@@ -126,6 +126,35 @@ gboolean secret_password_clearv_sync (const SecretSchema *sche ...@@ -126,6 +126,35 @@ gboolean secret_password_clearv_sync (const SecretSchema *sche
GCancellable *cancellable, GCancellable *cancellable,
GError **error); 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_free (gchar *password);
void secret_password_wipe (gchar *password); void secret_password_wipe (gchar *password);
......
...@@ -35,13 +35,6 @@ typedef enum { ...@@ -35,13 +35,6 @@ typedef enum {
SECRET_SERVICE_LOAD_COLLECTIONS = 1 << 2, SECRET_SERVICE_LOAD_COLLECTIONS = 1 << 2,
} SecretServiceFlags; } 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_TYPE_SERVICE (secret_service_get_type ())
#define SECRET_SERVICE(inst) (G_TYPE_CHECK_INSTANCE_CAST ((inst), SECRET_TYPE_SERVICE, SecretService)) #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)) #define SECRET_SERVICE_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), SECRET_TYPE_SERVICE, SecretServiceClass))
......
...@@ -38,6 +38,13 @@ typedef enum { ...@@ -38,6 +38,13 @@ typedef enum {
#define SECRET_COLLECTION_SESSION "session" #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 G_END_DECLS
#endif /* __G_SERVICE_H___ */ #endif /* __G_SERVICE_H___ */
...@@ -356,6 +356,90 @@ test_clear_no_name (Test *test, ...@@ -356,6 +356,90 @@ test_clear_no_name (Test *test,
g_assert_true (ret); 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 static void
test_password_free_null (void) test_password_free_null (void)
{ {
...@@ -380,6 +464,10 @@ main (int argc, char **argv) ...@@ -380,6 +464,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/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/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); g_test_add_func ("/password/free-null", test_password_free_null);
return egg_tests_run_with_loop (); return egg_tests_run_with_loop ();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment