add tool for logging out (other devices)
This commit is contained in:
parent
1bfae104fc
commit
c890c49c7b
4 changed files with 132 additions and 0 deletions
|
|
@ -60,6 +60,7 @@ usage:
|
||||||
mxdiscover --help
|
mxdiscover --help
|
||||||
mxpassitem --help
|
mxpassitem --help
|
||||||
mxwhoami --help
|
mxwhoami --help
|
||||||
|
mxlogout --help
|
||||||
mxtoken
|
mxtoken
|
||||||
mxaccountinfo
|
mxaccountinfo
|
||||||
mxclearaccount
|
mxclearaccount
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ mxdiscover = "pymxutils.mxutils:discoverhs"
|
||||||
mxwhoami = "pymxutils.mxutils:whoami"
|
mxwhoami = "pymxutils.mxutils:whoami"
|
||||||
mxtoken = "pymxutils.mxutils:mktoken"
|
mxtoken = "pymxutils.mxutils:mktoken"
|
||||||
mxaccountinfo = "pymxutils.mxutils:accountinfo"
|
mxaccountinfo = "pymxutils.mxutils:accountinfo"
|
||||||
|
mxlogout = "pymxutils.mxutils:logout"
|
||||||
mxclearaccount = "pymxutils.mxutils:clearaccount"
|
mxclearaccount = "pymxutils.mxutils:clearaccount"
|
||||||
mxserverinfo = "pymxutils.mxutils:serverinfo"
|
mxserverinfo = "pymxutils.mxutils:serverinfo"
|
||||||
mxpassitem = "pymxutils.mxutils:passitem"
|
mxpassitem = "pymxutils.mxutils:passitem"
|
||||||
|
|
|
||||||
|
|
@ -5,3 +5,4 @@ from .accountinfo import accountinfo as accountinfo
|
||||||
from .clearaccount import clearaccount as clearaccount
|
from .clearaccount import clearaccount as clearaccount
|
||||||
from .serverinfo import serverinfo as serverinfo
|
from .serverinfo import serverinfo as serverinfo
|
||||||
from .passitem import passitem as passitem
|
from .passitem import passitem as passitem
|
||||||
|
from .logout import logout as logout
|
||||||
|
|
|
||||||
129
smal/src/pymxutils/mxutils/logout.py
Normal file
129
smal/src/pymxutils/mxutils/logout.py
Normal file
|
|
@ -0,0 +1,129 @@
|
||||||
|
# Copyright (C) 2026 saces@c-base.org
|
||||||
|
# SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
import getpass
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
import click
|
||||||
|
|
||||||
|
from pygomx import CliV0
|
||||||
|
|
||||||
|
|
||||||
|
@click.command()
|
||||||
|
@click.option("-u", "--url", "hs_url", metavar="url", help="homeserver url")
|
||||||
|
@click.option("-t", "--token", "token", metavar="token", help="access token")
|
||||||
|
@click.option(
|
||||||
|
"--json", "show_json", is_flag=True, help="show json as returned from server."
|
||||||
|
)
|
||||||
|
@click.argument("devices", metavar="DeviceID", nargs=-1)
|
||||||
|
@click.option(
|
||||||
|
"-l",
|
||||||
|
"--logout",
|
||||||
|
"logout_type",
|
||||||
|
type=click.Choice(["all", "other", "self"]),
|
||||||
|
help="logout devices",
|
||||||
|
)
|
||||||
|
def logout(hs_url, token, devices, logout_type, show_json):
|
||||||
|
"""List or logout devices.
|
||||||
|
|
||||||
|
\b
|
||||||
|
mxlogout [--json]
|
||||||
|
list all devices
|
||||||
|
mxlogout --all
|
||||||
|
logout all devices
|
||||||
|
mxlogout --self
|
||||||
|
logout this device
|
||||||
|
mxlogout --other
|
||||||
|
logout all other devices (requires auth)
|
||||||
|
mxlogout deviceid [deviceid]...
|
||||||
|
logout given devices (requires auth)
|
||||||
|
"""
|
||||||
|
|
||||||
|
if len(devices) > 0 and logout_type is not None:
|
||||||
|
raise ValueError("you can't get both.")
|
||||||
|
|
||||||
|
if hs_url is None and token is None:
|
||||||
|
cli = CliV0.from_mxpass(".mxpass", "*", "*", "*")
|
||||||
|
else:
|
||||||
|
cli = CliV0(hs_url, token)
|
||||||
|
|
||||||
|
match logout_type:
|
||||||
|
case "self":
|
||||||
|
do_logout(cli, all=False)
|
||||||
|
return
|
||||||
|
case "all":
|
||||||
|
do_logout(cli, all=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
if len(devices) > 0:
|
||||||
|
device_list = list(devices)
|
||||||
|
whoami_dict = cli.Whoami()
|
||||||
|
self_user_id = whoami_dict["user_id"]
|
||||||
|
do_logout_devices(cli, device_list, self_user_id)
|
||||||
|
return
|
||||||
|
|
||||||
|
reqData = {"method": "GET", "path": ["_matrix", "client", "v3", "devices"]}
|
||||||
|
raw_device_dict = cli.Generic(reqData)
|
||||||
|
|
||||||
|
if logout_type == "other":
|
||||||
|
whoami_dict = cli.Whoami()
|
||||||
|
self_device_id = whoami_dict["device_id"]
|
||||||
|
self_user_id = whoami_dict["user_id"]
|
||||||
|
device_list = []
|
||||||
|
for device in raw_device_dict["devices"]:
|
||||||
|
if device["device_id"] != self_device_id:
|
||||||
|
device_list += [
|
||||||
|
device["device_id"],
|
||||||
|
]
|
||||||
|
if len(device_list) > 0:
|
||||||
|
do_logout_devices(cli, device_list, self_user_id)
|
||||||
|
return
|
||||||
|
|
||||||
|
if show_json:
|
||||||
|
print(raw_device_dict)
|
||||||
|
return
|
||||||
|
|
||||||
|
max_len = 0
|
||||||
|
for device in raw_device_dict["devices"]:
|
||||||
|
max_len = max(max_len, len(device["device_id"]))
|
||||||
|
|
||||||
|
for device in raw_device_dict["devices"]:
|
||||||
|
date_object = datetime.fromtimestamp(device["last_seen_ts"] / 1000)
|
||||||
|
print(
|
||||||
|
device["device_id"],
|
||||||
|
" " * (max_len - len(device["device_id"])),
|
||||||
|
date_object,
|
||||||
|
device["last_seen_ip"],
|
||||||
|
device["display_name"],
|
||||||
|
)
|
||||||
|
date_object = datetime.fromtimestamp(device["last_seen_ts"] / 1000)
|
||||||
|
|
||||||
|
|
||||||
|
def do_logout(cli, all):
|
||||||
|
reqData = {
|
||||||
|
"method": "POST",
|
||||||
|
"path": ["_matrix", "client", "v3", "logout"],
|
||||||
|
}
|
||||||
|
if all:
|
||||||
|
reqData["path"] += ["all"]
|
||||||
|
res = cli.Generic(reqData)
|
||||||
|
print(res)
|
||||||
|
|
||||||
|
|
||||||
|
def do_logout_devices(cli, devices, user_id):
|
||||||
|
reqData = {
|
||||||
|
"method": "POST",
|
||||||
|
"path": ["_matrix", "client", "v3", "delete_devices"],
|
||||||
|
"payload": {
|
||||||
|
"devices": devices,
|
||||||
|
"auth": {
|
||||||
|
"type": "m.login.password",
|
||||||
|
"password": getpass.getpass(prompt="Password: "),
|
||||||
|
"identifier": {
|
||||||
|
"type": "m.id.user",
|
||||||
|
"user": user_id,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
res = cli.Generic(reqData)
|
||||||
|
print(res)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue