Coverage for slidge/core/dispatcher/registration.py: 58%
73 statements
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-09 03:59 +0000
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-09 03:59 +0000
1from __future__ import annotations
3import logging
4from typing import TYPE_CHECKING
6from slixmpp import JID, Iq
7from slixmpp.exceptions import XMPPError
9from ...db import GatewayUser
10from .. import config
11from .util import DispatcherMixin
13if TYPE_CHECKING:
14 from slidge.util.types import AnyGateway
17class RegistrationMixin(DispatcherMixin):
18 __slots__: list[str] = []
20 def __init__(self, xmpp: AnyGateway) -> None:
21 super().__init__(xmpp)
22 xmpp.plugin["xep_0077"].api.register(
23 self.xmpp.make_registration_form, # type:ignore[arg-type]
24 "make_registration_form",
25 )
26 xmpp.plugin["xep_0077"].api.register(self._user_get, "user_get") # type:ignore[arg-type]
27 xmpp.plugin["xep_0077"].api.register(self._user_validate, "user_validate") # type:ignore[arg-type]
28 xmpp.plugin["xep_0077"].api.register(self._user_modify, "user_modify") # type:ignore[arg-type]
29 # kept for slixmpp internal API compat
30 # TODO: either fully use slixmpp internal API or rewrite registration without it at all
31 xmpp.plugin["xep_0077"].api.register(lambda *a: None, "user_remove")
33 xmpp.add_event_handler("user_register", self._on_user_register)
34 xmpp.add_event_handler("user_unregister", self._on_user_unregister)
36 def get_user(self, jid: JID) -> GatewayUser | None:
37 session = self.xmpp.get_session_from_jid(jid)
38 if session is None:
39 return None
40 return session.user
42 async def _user_get(
43 self,
44 _gateway_jid: JID,
45 _node: str,
46 ifrom: JID,
47 iq: Iq,
48 ) -> GatewayUser | None:
49 if ifrom is None:
50 ifrom = iq.get_from()
51 return self.get_user(ifrom)
53 async def _user_validate(
54 self,
55 _gateway_jid: JID,
56 _node: str,
57 ifrom: JID,
58 iq: Iq,
59 ) -> None:
60 xmpp = self.xmpp
61 log.debug("User validate: %s", ifrom.bare)
62 form_dict = {f.var: iq.get(f.var) for f in xmpp.REGISTRATION_FIELDS}
63 xmpp.raise_if_not_allowed_jid(ifrom)
64 try:
65 legacy_module_data = await xmpp.user_prevalidate(ifrom, form_dict)
66 except ValueError as e:
67 raise XMPPError("bad-request", str(e))
68 except XMPPError:
69 raise
70 except Exception as e:
71 raise XMPPError("internal-server-error", str(e))
72 if legacy_module_data is None:
73 legacy_module_data = form_dict
74 with self.xmpp.store.session() as orm:
75 user = GatewayUser(
76 jid=ifrom.bare,
77 legacy_module_data=legacy_module_data,
78 )
79 orm.add(user)
80 orm.commit()
81 log.info("New user: %s", user)
83 async def _user_modify(
84 self,
85 _gateway_jid: JID,
86 _node: str,
87 ifrom: JID,
88 form_dict: dict[str, str | None],
89 ) -> None:
90 try:
91 await self.xmpp.user_prevalidate(ifrom, form_dict)
92 except ValueError as e:
93 raise XMPPError("bad-request", str(e))
94 except XMPPError:
95 raise
96 except Exception as e:
97 raise XMPPError("internal-server-error", str(e))
98 log.debug("Modify user: %s", ifrom)
99 with self.xmpp.store.session() as orm:
100 user = orm.query(GatewayUser).one_or_none()
101 if user is None:
102 raise XMPPError("internal-server-error", "User not found")
103 user.legacy_module_data.update(form_dict)
104 self.xmpp.store.users.update(user)
106 async def _on_user_register(self, iq: Iq) -> None:
107 session = await self._get_session(iq, wait_for_ready=False)
108 for jid in config.ADMINS:
109 self.xmpp.send_message(
110 mto=jid,
111 mbody=f"{iq.get_from()} has registered",
112 mtype="chat",
113 mfrom=self.xmpp.boundjid.bare,
114 )
115 session.send_gateway_message(self.xmpp.WELCOME_MESSAGE)
116 await self.xmpp.login_wrap(session)
118 async def _on_user_unregister(self, iq: Iq) -> None:
119 await self.xmpp.kill_session(iq.get_from())
122log = logging.getLogger(__name__)