mirror of
https://gitlab.gnome.org/GNOME/libsecret.git
synced 2025-01-03 02:28:53 +00:00
When storing a secret, create default keyring if necessary
* If the default keyring does not exist when storing a secret try and create it. * We handle both secrets that correctly return NoSuchObject and ones that just return the silly DBus UnknownMethod error. https://bugzilla.gnome.org/show_bug.cgi?id=688165
This commit is contained in:
parent
4eb3c4577e
commit
afc1d65679
@ -1042,8 +1042,8 @@ on_create_service (GObject *source,
|
|||||||
g_object_unref (async);
|
g_object_unref (async);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GHashTable *
|
GHashTable *
|
||||||
collection_properties_new (const gchar *label)
|
_secret_collection_properties_new (const gchar *label)
|
||||||
{
|
{
|
||||||
GHashTable *properties;
|
GHashTable *properties;
|
||||||
GVariant *value;
|
GVariant *value;
|
||||||
@ -1104,7 +1104,7 @@ secret_collection_create (SecretService *service,
|
|||||||
secret_collection_create);
|
secret_collection_create);
|
||||||
closure = g_slice_new0 (CreateClosure);
|
closure = g_slice_new0 (CreateClosure);
|
||||||
closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
|
closure->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
|
||||||
closure->properties = collection_properties_new (label);
|
closure->properties = _secret_collection_properties_new (label);
|
||||||
closure->alias = g_strdup (alias);
|
closure->alias = g_strdup (alias);
|
||||||
closure->flags = flags;
|
closure->flags = flags;
|
||||||
g_simple_async_result_set_op_res_gpointer (res, closure, create_closure_free);
|
g_simple_async_result_set_op_res_gpointer (res, closure, create_closure_free);
|
||||||
@ -1208,7 +1208,7 @@ secret_collection_create_sync (SecretService *service,
|
|||||||
g_object_ref (service);
|
g_object_ref (service);
|
||||||
}
|
}
|
||||||
|
|
||||||
properties = collection_properties_new (label);
|
properties = _secret_collection_properties_new (label);
|
||||||
|
|
||||||
path = secret_service_create_collection_dbus_path_sync (service, properties, alias,
|
path = secret_service_create_collection_dbus_path_sync (service, properties, alias,
|
||||||
flags, cancellable, error);
|
flags, cancellable, error);
|
||||||
|
@ -955,6 +955,7 @@ typedef struct {
|
|||||||
gchar *collection_path;
|
gchar *collection_path;
|
||||||
SecretValue *value;
|
SecretValue *value;
|
||||||
GHashTable *properties;
|
GHashTable *properties;
|
||||||
|
gboolean created_collection;
|
||||||
} StoreClosure;
|
} StoreClosure;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -971,19 +972,73 @@ store_closure_free (gpointer data)
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
on_store_create (GObject *source,
|
on_store_create (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_store_keyring (GObject *source,
|
||||||
GAsyncResult *result,
|
GAsyncResult *result,
|
||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
|
GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
|
||||||
|
StoreClosure *store = g_simple_async_result_get_op_res_gpointer (async);
|
||||||
|
SecretService *service = SECRET_SERVICE (source);
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
gchar *path;
|
gchar *path;
|
||||||
|
|
||||||
path = secret_service_create_item_dbus_path_finish (SECRET_SERVICE (source), result, &error);
|
path = secret_service_create_collection_dbus_path_finish (service, result, &error);
|
||||||
|
if (error == NULL) {
|
||||||
|
store->created_collection = TRUE;
|
||||||
|
secret_service_create_item_dbus_path (service, store->collection_path,
|
||||||
|
store->properties, store->value,
|
||||||
|
SECRET_ITEM_CREATE_REPLACE, store->cancellable,
|
||||||
|
on_store_create, g_object_ref (async));
|
||||||
|
} else {
|
||||||
|
g_simple_async_result_take_error (async, error);
|
||||||
|
g_simple_async_result_complete (async);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (async);
|
||||||
|
g_free (path);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_store_create (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GSimpleAsyncResult *async = G_SIMPLE_ASYNC_RESULT (user_data);
|
||||||
|
StoreClosure *store = g_simple_async_result_get_op_res_gpointer (async);
|
||||||
|
SecretService *service = SECRET_SERVICE (source);
|
||||||
|
GError *error = NULL;
|
||||||
|
GHashTable *properties;
|
||||||
|
gchar *path;
|
||||||
|
|
||||||
|
path = secret_service_create_item_dbus_path_finish (service, result, &error);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This happens when the collection doesn't exist. If the collection is
|
||||||
|
* the default alias, we should try and create it
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!store->created_collection &&
|
||||||
|
(g_error_matches (error, SECRET_ERROR, SECRET_ERROR_NO_SUCH_OBJECT) ||
|
||||||
|
g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD)) &&
|
||||||
|
g_strcmp0 (store->collection_path, SECRET_ALIAS_PREFIX "default") == 0) {
|
||||||
|
properties = _secret_collection_properties_new ("Default keyring");
|
||||||
|
secret_service_create_collection_dbus_path (service, properties, "default",
|
||||||
|
SECRET_COLLECTION_CREATE_NONE, store->cancellable,
|
||||||
|
on_store_keyring, g_object_ref (async));
|
||||||
|
g_hash_table_unref (properties);
|
||||||
|
g_error_free (error);
|
||||||
|
|
||||||
|
} else {
|
||||||
if (error != NULL)
|
if (error != NULL)
|
||||||
g_simple_async_result_take_error (async, error);
|
g_simple_async_result_take_error (async, error);
|
||||||
g_free (path);
|
|
||||||
|
|
||||||
g_simple_async_result_complete (async);
|
g_simple_async_result_complete (async);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (path);
|
||||||
g_object_unref (async);
|
g_object_unref (async);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +31,8 @@ typedef struct {
|
|||||||
|
|
||||||
typedef struct _SecretSession SecretSession;
|
typedef struct _SecretSession SecretSession;
|
||||||
|
|
||||||
|
#define SECRET_ALIAS_PREFIX "/org/freedesktop/secrets/aliases/"
|
||||||
|
|
||||||
#define SECRET_SERVICE_PATH "/org/freedesktop/secrets"
|
#define SECRET_SERVICE_PATH "/org/freedesktop/secrets"
|
||||||
|
|
||||||
#define SECRET_SERVICE_BUS_NAME "org.freedesktop.secrets"
|
#define SECRET_SERVICE_BUS_NAME "org.freedesktop.secrets"
|
||||||
@ -166,6 +168,8 @@ gint _secret_service_xlock_paths_finish (SecretService *se
|
|||||||
gchar ***xlocked,
|
gchar ***xlocked,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
GHashTable * _secret_collection_properties_new (const gchar *label);
|
||||||
|
|
||||||
SecretItem * _secret_collection_find_item_instance (SecretCollection *self,
|
SecretItem * _secret_collection_find_item_instance (SecretCollection *self,
|
||||||
const gchar *item_path);
|
const gchar *item_path);
|
||||||
|
|
||||||
|
17
libsecret/tests/mock-service-empty.py
Normal file
17
libsecret/tests/mock-service-empty.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright 2012 Red Hat Inc.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser General Public License as published
|
||||||
|
# by the Free Software Foundation; either version 2.1 of the licence or (at
|
||||||
|
# your option) any later version.
|
||||||
|
#
|
||||||
|
# See the included COPYING file for more information.
|
||||||
|
#
|
||||||
|
|
||||||
|
import mock
|
||||||
|
|
||||||
|
service = mock.SecretService()
|
||||||
|
service.listen()
|
@ -865,6 +865,55 @@ test_store_async (Test *test,
|
|||||||
g_strfreev (paths);
|
g_strfreev (paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
test_store_no_default (Test *test,
|
||||||
|
gconstpointer used)
|
||||||
|
{
|
||||||
|
SecretValue *value = secret_value_new ("apassword", -1, "text/plain");
|
||||||
|
GHashTable *attributes;
|
||||||
|
GError *error = NULL;
|
||||||
|
gchar **paths;
|
||||||
|
gboolean ret;
|
||||||
|
gsize length;
|
||||||
|
|
||||||
|
attributes = secret_attributes_build (&MOCK_SCHEMA,
|
||||||
|
"even", FALSE,
|
||||||
|
"string", "seventeen",
|
||||||
|
"number", 17,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
ret = secret_service_store_sync (test->service, &MOCK_SCHEMA, attributes, SECRET_COLLECTION_DEFAULT,
|
||||||
|
"New Item Label", value, NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
secret_value_unref (value);
|
||||||
|
g_hash_table_unref (attributes);
|
||||||
|
|
||||||
|
attributes = g_hash_table_new (g_str_hash, g_str_equal);
|
||||||
|
g_hash_table_insert (attributes, "even", "false");
|
||||||
|
g_hash_table_insert (attributes, "string", "seventeen");
|
||||||
|
g_hash_table_insert (attributes, "number", "17");
|
||||||
|
|
||||||
|
ret = secret_service_search_for_dbus_paths_sync (test->service, &MOCK_SCHEMA, attributes,
|
||||||
|
NULL, &paths, NULL, &error);
|
||||||
|
g_hash_table_unref (attributes);
|
||||||
|
g_assert (ret == TRUE);
|
||||||
|
|
||||||
|
g_assert (paths != NULL);
|
||||||
|
g_assert (paths[0] != NULL);
|
||||||
|
g_assert (paths[1] == NULL);
|
||||||
|
|
||||||
|
value = secret_service_get_secret_for_dbus_path_sync (test->service, paths[0],
|
||||||
|
NULL, &error);
|
||||||
|
g_assert_no_error (error);
|
||||||
|
|
||||||
|
g_assert (value != NULL);
|
||||||
|
g_assert_cmpstr (secret_value_get (value, &length), ==, "apassword");
|
||||||
|
g_assert_cmpuint (length, ==, 9);
|
||||||
|
|
||||||
|
secret_value_unref (value);
|
||||||
|
g_strfreev (paths);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
test_set_alias_sync (Test *test,
|
test_set_alias_sync (Test *test,
|
||||||
gconstpointer used)
|
gconstpointer used)
|
||||||
@ -941,6 +990,7 @@ main (int argc, char **argv)
|
|||||||
g_test_add ("/service/store-sync", Test, "mock-service-normal.py", setup, test_store_sync, teardown);
|
g_test_add ("/service/store-sync", Test, "mock-service-normal.py", setup, test_store_sync, teardown);
|
||||||
g_test_add ("/service/store-async", Test, "mock-service-normal.py", setup, test_store_async, teardown);
|
g_test_add ("/service/store-async", Test, "mock-service-normal.py", setup, test_store_async, teardown);
|
||||||
g_test_add ("/service/store-replace", Test, "mock-service-normal.py", setup, test_store_replace, teardown);
|
g_test_add ("/service/store-replace", Test, "mock-service-normal.py", setup, test_store_replace, teardown);
|
||||||
|
g_test_add ("/service/store-no-default", Test, "mock-service-empty.py", setup, test_store_no_default, teardown);
|
||||||
|
|
||||||
g_test_add ("/service/set-alias-sync", Test, "mock-service-normal.py", setup, test_set_alias_sync, teardown);
|
g_test_add ("/service/set-alias-sync", Test, "mock-service-normal.py", setup, test_set_alias_sync, teardown);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user