94 lines
3.2 KiB
Python
Executable File
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)
|