Files
coredesktop/configure.d/lib/goa-account
T
2026-10-29 06:36:51 -06:00

94 lines
3.2 KiB
Python
Executable File

#!/usr/bin/env python3
"""Add or remove an account in GNOME Online Accounts, the way Settings does.
Settings adds accounts by calling AddAccount on the Online Accounts service,
which saves the account and keeps its password in the GNOME keyring. This
calls the same method. The account comes on stdin rather than as arguments,
so its password doesn't show up in the process list.
Usage:
goa-account exists <provider> <presentation-identity>
goa-account add < account.json
goa-account remove <provider> <presentation-identity>
account.json:
{"provider": "owncloud", "identity": "...", "presentation_identity": "...",
"credentials": {"password": "..."}, "details": {"Uri": "...", ...}}
"""
import json
import sys
import gi
gi.require_version("Gio", "2.0")
from gi.repository import Gio, GLib # noqa: E402
BUS_NAME = "org.gnome.OnlineAccounts"
def call(bus, path, interface, method, parameters, reply_type):
return bus.call_sync(BUS_NAME, path, interface, method, parameters,
GLib.VariantType(reply_type), Gio.DBusCallFlags.NONE,
-1, None).unpack()
def accounts(bus):
(objects,) = call(bus, "/org/gnome/OnlineAccounts",
"org.freedesktop.DBus.ObjectManager", "GetManagedObjects",
None, "(a{oa{sa{sv}}})")
for path, interfaces in objects.items():
account = interfaces.get("org.gnome.OnlineAccounts.Account")
if account:
yield path, account
def find(bus, provider, presentation_identity):
return [path for path, account in accounts(bus)
if account.get("ProviderType") == provider
and account.get("PresentationIdentity") == presentation_identity]
def exists(bus, provider, presentation_identity):
return bool(find(bus, provider, presentation_identity))
def add(bus, account):
credentials = {key: GLib.Variant("s", value)
for key, value in account["credentials"].items()}
parameters = GLib.Variant("(sssa{sv}a{ss})", (
account["provider"], account["identity"],
account["presentation_identity"], credentials, account["details"]))
call(bus, "/org/gnome/OnlineAccounts/Manager",
"org.gnome.OnlineAccounts.Manager", "AddAccount", parameters, "(o)")
def remove(bus, provider, presentation_identity):
for path in find(bus, provider, presentation_identity):
call(bus, path, "org.gnome.OnlineAccounts.Account", "Remove", None, "()")
def main():
bus = Gio.bus_get_sync(Gio.BusType.SESSION, None)
if len(sys.argv) == 4 and sys.argv[1] == "exists":
return 0 if exists(bus, sys.argv[2], sys.argv[3]) else 1
if len(sys.argv) == 2 and sys.argv[1] == "add":
account = json.load(sys.stdin)
if exists(bus, account["provider"], account["presentation_identity"]):
return 0
add(bus, account)
return 0
if len(sys.argv) == 4 and sys.argv[1] == "remove":
remove(bus, sys.argv[2], sys.argv[3])
return 0
print(__doc__.strip().split("\n\n")[2], file=sys.stderr)
return 2
if __name__ == "__main__":
try:
sys.exit(main())
except GLib.Error as error:
print(f"GNOME Online Accounts: {error.message}", file=sys.stderr)
sys.exit(1)