modules.ejabberd

mod_http_api (read path) and ejabberdctl (write path) clients – see Read-only status integration and XMPP user management for what each function is used for and the security model behind them.

ban_account(user: str, reason: str) None[source]

Puts user into ejabberd’s account-disabled state on EJABBERD_DOMAIN, recording reason – reversible via unban_account, which restores the account’s original password (verified live; not a “swap in a random password” as ejabberd’s own docs might suggest – see DEV_EJABBERD_USER_MANAGEMENT.md’s Current state). Note check_password must never be used to detect this state (it throws an unhandled exception against a banned account) – use get_ban_details instead.

change_password(user: str, new_password: str) None[source]

Changes user’s XMPP password on EJABBERD_DOMAIN. Prints nothing on success (verified live – contradicts ejabberdctl’s own help text example, which shows a printed ‘ok’; this ejabberd version prints nothing), so an empty message alongside a zero exit code is the expected success case, not a sign anything went wrong. Raises ValueError on failure (e.g. the account doesn’t exist – verified live: exit 1, stdout a raw Erlang tuple literal {not_found,”unknown_user”}).

check_account(user: str) bool[source]

True if user is a registered account on EJABBERD_DOMAIN. The HTTP API and ejabberdctl signal this two different ways (see DEV_EJABBERD_INTEGRATION.md, Data layer): HTTP always returns 200 with a bare 0/1 body; ejabberdctl instead uses its process exit code (0/1), with no reliable stdout content to parse either way.

get_ban_details(user: str) dict | None[source]

Returns a dict of ban details (reason/bandate/lastdate/lastreason) if user is currently banned on EJABBERD_DOMAIN, or None if not. The safe way to check ban status – check_password throws an unhandled exception against a banned account instead of returning a clean answer (verified live, see DEV_EJABBERD_USER_MANAGEMENT.md’s “Verified live”). Read-only, but ejabberdctl-only like the write commands above rather than mod_http_api, since it exists purely to support them and isn’t in the existing mod_http_api whitelist either.

kick_session(user: str, resource: str, reason: str) None[source]

Force-disconnects one specific session of user (identified by its XMPP resource, always “pyobs” for a pyobs module – confirmed live, see DEV_EJABBERD_INTEGRATION.md’s Data layer) on EJABBERD_DOMAIN, recording reason in the disconnect message. Doesn’t touch the account itself (still registered, same password), unlike ban/unregister.

Uses kick_session rather than kick_user deliberately: kick_user takes no reason at all and reports a generic “policy-violation” cause, which the module side can’t distinguish from any other disconnect. Verified live against a real connected session: exit 0, empty stdout on success (same silent-rescode pattern as change_password, despite ejabberdctl’s own help text example showing a printed ‘ok’) – and the reason text does appear verbatim afterward in the module’s own get_last (“Stream closed by local host: <reason> (conflict)”), confirming the module side can actually key off of it. Raises ValueError on failure.

register(user: str, password: str) None[source]

Registers a new XMPP account for user on EJABBERD_DOMAIN. Raises ValueError on failure (e.g. the account already exists – verified live: exit 1, stdout “Error: conflict: User <user>@<host> already registered”).

stats(name: str) int[source]

name is one of “registeredusers”, “onlineusers”, “uptimeseconds” (see DEV_EJABBERD_INTEGRATION.md, Data layer).

unban_account(user: str) None[source]

Lifts a ban placed by ban_account, restoring the account’s original password (verified live).

unregister(user: str) None[source]

Permanently deletes user’s account – auth, roster, and vcard data – on EJABBERD_DOMAIN. Not reversible. Verified live: silently succeeds (exit 0, empty output) even if the account was never registered in the first place – ejabberd itself doesn’t distinguish “removed” from “was never there,” so a caller that needs to know which happened must call check_account first, not infer it from this function’s result.