Mercurial > libervia-backend
comparison libervia/backend/stdui/ui_profile_manager.py @ 4071:4b842c1fb686
refactoring: renamed `sat` package to `libervia.backend`
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 02 Jun 2023 11:49:51 +0200 |
parents | sat/stdui/ui_profile_manager.py@524856bd7b19 |
children |
comparison
equal
deleted
inserted
replaced
4070:d10748475025 | 4071:4b842c1fb686 |
---|---|
1 #!/usr/bin/env python3 | |
2 | |
3 | |
4 # SAT standard user interface for managing contacts | |
5 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org) | |
6 # Copyright (C) 2013-2016 Adrien Cossa (souliane@mailoo.org) | |
7 | |
8 # This program is free software: you can redistribute it and/or modify | |
9 # it under the terms of the GNU Affero General Public License as published by | |
10 # the Free Software Foundation, either version 3 of the License, or | |
11 # (at your option) any later version. | |
12 | |
13 # This program is distributed in the hope that it will be useful, | |
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 # GNU Affero General Public License for more details. | |
17 | |
18 # You should have received a copy of the GNU Affero General Public License | |
19 # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
20 | |
21 from libervia.backend.core.i18n import D_ | |
22 from libervia.backend.core.constants import Const as C | |
23 from libervia.backend.core.log import getLogger | |
24 from libervia.backend.core import exceptions | |
25 from libervia.backend.tools import xml_tools | |
26 from libervia.backend.memory.memory import ProfileSessions | |
27 from twisted.internet import defer | |
28 from twisted.words.protocols.jabber import jid | |
29 | |
30 | |
31 log = getLogger(__name__) | |
32 | |
33 | |
34 class ProfileManager(object): | |
35 """Manage profiles.""" | |
36 | |
37 def __init__(self, host): | |
38 self.host = host | |
39 self.profile_ciphers = {} | |
40 self._sessions = ProfileSessions() | |
41 host.register_callback( | |
42 self._authenticate_profile, force_id=C.AUTHENTICATE_PROFILE_ID, with_data=True | |
43 ) | |
44 host.register_callback( | |
45 self._change_xmpp_password, force_id=C.CHANGE_XMPP_PASSWD_ID, with_data=True | |
46 ) | |
47 self.__new_xmpp_passwd_id = host.register_callback( | |
48 self._change_xmpp_password_cb, with_data=True | |
49 ) | |
50 | |
51 def _start_session_eb(self, fail, first, profile): | |
52 """Errback method for start_session during profile authentication | |
53 | |
54 @param first(bool): if True, this is the first try and we have tryied empty password | |
55 in this case we ask for a password to the user. | |
56 @param profile(unicode, None): %(doc_profile)s | |
57 must only be used if first is True | |
58 """ | |
59 if first: | |
60 # first call, we ask for the password | |
61 form_ui = xml_tools.XMLUI( | |
62 "form", title=D_("Profile password for {}").format(profile), submit_id="" | |
63 ) | |
64 form_ui.addPassword("profile_password", value="") | |
65 d = xml_tools.deferred_ui(self.host, form_ui, chained=True) | |
66 d.addCallback(self._authenticate_profile, profile) | |
67 return {"xmlui": form_ui.toXml()} | |
68 | |
69 assert profile is None | |
70 | |
71 if fail.check(exceptions.PasswordError): | |
72 dialog = xml_tools.XMLUI("popup", title=D_("Connection error")) | |
73 dialog.addText(D_("The provided profile password doesn't match.")) | |
74 else: | |
75 log.error("Unexpected exceptions: {}".format(fail)) | |
76 dialog = xml_tools.XMLUI("popup", title=D_("Internal error")) | |
77 dialog.addText(D_("Internal error: {}".format(fail))) | |
78 return {"xmlui": dialog.toXml(), "validated": C.BOOL_FALSE} | |
79 | |
80 def _authenticate_profile(self, data, profile): | |
81 if C.bool(data.get("cancelled", "false")): | |
82 return {} | |
83 if self.host.memory.is_session_started(profile): | |
84 return {"validated": C.BOOL_TRUE} | |
85 try: | |
86 password = data[xml_tools.form_escape("profile_password")] | |
87 except KeyError: | |
88 # first request, we try empty password | |
89 password = "" | |
90 first = True | |
91 eb_profile = profile | |
92 else: | |
93 first = False | |
94 eb_profile = None | |
95 d = self.host.memory.start_session(password, profile) | |
96 d.addCallback(lambda __: {"validated": C.BOOL_TRUE}) | |
97 d.addErrback(self._start_session_eb, first, eb_profile) | |
98 return d | |
99 | |
100 def _change_xmpp_password(self, data, profile): | |
101 session_data = self._sessions.profile_get_unique(profile) | |
102 if not session_data: | |
103 server = self.host.memory.param_get_a( | |
104 C.FORCE_SERVER_PARAM, "Connection", profile_key=profile | |
105 ) | |
106 if not server: | |
107 server = jid.parse( | |
108 self.host.memory.param_get_a( | |
109 "JabberID", "Connection", profile_key=profile | |
110 ) | |
111 )[1] | |
112 session_id, session_data = self._sessions.new_session( | |
113 {"count": 0, "server": server}, profile=profile | |
114 ) | |
115 if ( | |
116 session_data["count"] > 2 | |
117 ): # 3 attempts with a new password after the initial try | |
118 self._sessions.profile_del_unique(profile) | |
119 _dialog = xml_tools.XMLUI("popup", title=D_("Connection error")) | |
120 _dialog.addText( | |
121 D_("Can't connect to %s. Please check your connection details.") | |
122 % session_data["server"] | |
123 ) | |
124 return {"xmlui": _dialog.toXml()} | |
125 session_data["count"] += 1 | |
126 counter = " (%d)" % session_data["count"] if session_data["count"] > 1 else "" | |
127 title = D_("XMPP password for %(profile)s%(counter)s") % { | |
128 "profile": profile, | |
129 "counter": counter, | |
130 } | |
131 form_ui = xml_tools.XMLUI( | |
132 "form", title=title, submit_id=self.__new_xmpp_passwd_id | |
133 ) | |
134 form_ui.addText( | |
135 D_( | |
136 "Can't connect to %s. Please check your connection details or try with another password." | |
137 ) | |
138 % session_data["server"] | |
139 ) | |
140 form_ui.addPassword("xmpp_password", value="") | |
141 return {"xmlui": form_ui.toXml()} | |
142 | |
143 def _change_xmpp_password_cb(self, data, profile): | |
144 xmpp_password = data[xml_tools.form_escape("xmpp_password")] | |
145 d = self.host.memory.param_set( | |
146 "Password", xmpp_password, "Connection", profile_key=profile | |
147 ) | |
148 d.addCallback(lambda __: defer.ensureDeferred(self.host.connect(profile))) | |
149 d.addCallback(lambda __: {}) | |
150 d.addErrback(lambda __: self._change_xmpp_password({}, profile)) | |
151 return d |