mirror of
https://gitlab.gnome.org/GNOME/libsecret.git
synced 2024-12-22 20:58:52 +00:00
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
This commit is contained in:
parent
5ce2540785
commit
7716449b1d
@ -844,6 +844,231 @@ 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.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)
|
* 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
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
|
|
||||||
#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___ */
|
||||||
|
@ -354,6 +354,90 @@ test_clear_no_name (Test *test,
|
|||||||
g_assert (ret == TRUE);
|
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
|
static void
|
||||||
test_password_free_null (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/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 ();
|
||||||
|
Loading…
Reference in New Issue
Block a user