libsecret を使用する小さなプログラムに取り組んでいます。このプログラムは Secret.Service を作成できるはずです...
from gi.repository import Secret
service = Secret.Service.get_sync(Secret.ServiceFlags.LOAD_COLLECTIONS)
...そのサービスから特定のコレクションを取得します...
# 2 is the index of a custom collection I created, not the default one.
collection = service.get_collections()[2]
...そして、そのコレクション内のすべてのアイテムをリストします。これは、ラベルを印刷するだけです。
# I'm just printing a single label here for testing, I'd need all of course.
print(collection.get_items()[0].get_label())
重要な詳細は、コレクションが最初にロックされている可能性があることです。そのため、その可能性をチェックしてコレクションのロックを解除しようとするコードを含める必要があります。
# The unlock method returns a tuple (number_of_objs_unlocked, [list_of_objs])
collection = service.unlock_sync([collection])[1][0]
コレクションが最初にロック解除されたときに、現在持っているコードで必要なことをすべて実行できるため、これは重要です。ただし、コレクションが最初にロックされている場合、ロックを解除した後でも、内部のアイテムからラベルを取得できません。私ができることは、Service を disconnect() し、Service を再作成し、ロックが解除された Collection を取得することです。このようにして、各 Item のラベルを読み取ることができます。もう 1 つの興味深い点は、ラベルが一度読み取られると、ラベルにアクセスするためにサービスを再接続する必要がなくなったことです。これは非常に洗練されていないように思われるので、別の解決策を探し始めました。
Collection は Gio.DBusProxy から継承され、このクラスはアクセスするオブジェクトからのデータをキャッシュすることに気付きました。だから私はそれが私にとって問題であると仮定しています.キャッシュを更新していません。ドキュメントには、Gio.DBusProxy が元のオブジェクトの変更を検出できるはずであると記載されているため、これは奇妙ですが、それは起こっていません。
そのクラスのキャッシュを更新する方法がわかりません。私はいくつかのタツノオトシゴ (libsecret を使用する別のアプリケーション) の vala コードを調べましたが、完全に解読できませんでした。vala をコーディングすることはできませんが、Object.emit() メソッドについて言及されています。その方法を使用して目標を達成する方法がまだわかりません。ドキュメント ( https://lazka.github.io/pgi-docs/Secret-1/# ) から、別の有望なメソッド Object.notify() を見つけました。これは、キャッシュを有効にする変更の通知を送信できるようです。更新されていますが、まだ適切に使用できていません。
これについて gnome-keyring メーリングリストにも投稿しました...
https://mail.gnome.org/archives/gnome-keyring-list/2015-November/msg00000.html
...これまでのところ回答がなく、この問題について言及しているbugzillaレポートがgnome.orgで見つかりました...
https://bugzilla.gnome.org/show_bug.cgi?id=747359
...これまでのところ(7か月)解決策はありません。
したがって、誰かがこの問題に光を当てることができれば、それは素晴らしいことです. そうしないと、残念なことに、いくつかの洗練されていないコードが私の小さなプログラムに侵入する可能性があります。
編集-0:
Python3 で問題を再現するためのコードを次に示します。このスニペットは、1 つのアイテム「test_item」を含むコレクション「test_col」を作成し、コレクションをロックします。libsecret は、この新しいコレクションに必要なパスワードを要求することに注意してください。
#!/usr/bin/env python3
from gi import require_version
require_version('Secret', '1')
from gi.repository import Secret
# Create schema
args = ['com.idlecore.test.schema']
args += [Secret.SchemaFlags.NONE]
args += [{'service': Secret.SchemaAttributeType.STRING,
'username': Secret.SchemaAttributeType.STRING}]
schema = Secret.Schema.new(*args)
# Create 'test_col' collection
flags = Secret.CollectionCreateFlags.COLLECTION_CREATE_NONE
collection = Secret.Collection.create_sync(None, 'test_col', None, flags, None)
# Create item 'test_item' inside collection 'test_col'
attributes = {'service': 'stackoverflow', 'username': 'xor'}
password = 'password123'
value = Secret.Value(password, len(password), 'text/plain')
flags = Secret.ItemCreateFlags.NONE
Secret.Item.create_sync(collection, schema, attributes,
'test_item', value, flags, None)
# Lock collection
service = collection.get_service()
service.lock_sync([collection])
次に、gnome-keyring-daemon を再起動する必要があります。ログアウトして再度ログインするか、コマンドラインを使用できます。
gnome-keyrin-daemon --replace
これによりキーリングがセットアップされ、最初にロックされているコレクションを開こうとすることができます。このコード スニペットでそれを行うことができます。以前に設定したパスワードをもう一度入力するように求められることに注意してください。
#!/usr/bin/env python3
from gi import require_version
require_version('Secret', '1')
from gi.repository import Secret
# Get the service
service = Secret.Service.get_sync(Secret.ServiceFlags.LOAD_COLLECTIONS)
# Find the correct collection
for c in service.get_collections():
if c.get_label() == 'test_col':
collection = c
break
# Unlock the collection and show the item label, note that it's empty.
collection = service.unlock_sync([collection])[1][0]
print('Item Label:', collection.get_items()[0].get_label())
# Do the same thing again, and it works.
# It's necessary to disconnect the service to clear the cache,
# Otherwise we keep getting the same empty label.
service.disconnect()
# Get the service
service = Secret.Service.get_sync(Secret.ServiceFlags.LOAD_COLLECTIONS)
# Find the correct collection
for c in service.get_collections():
if c.get_label() == 'test_col':
collection = c
break
# No need to unlock again, just show the item label
print('Item Label:', collection.get_items()[0].get_label())
このコードは、アイテム ラベルを 2 回読み取ろうとします。失敗する通常の方法では、空の文字列が表示され、回避策を使用してサービスを切断し、再接続する必要があります。