Mercurial > libervia-web
comparison browser/sat_browser/register.py @ 1124:28e3eb3bb217
files reorganisation and installation rework:
- files have been reorganised to follow other SàT projects and usual Python organisation (no more "/src" directory)
- VERSION file is now used, as for other SàT projects
- replace the overcomplicated setup.py be a more sane one. Pyjamas part is not compiled anymore by setup.py, it must be done separatly
- removed check for data_dir if it's empty
- installation tested working in virtual env
- libervia launching script is now in bin/libervia
author | Goffi <goffi@goffi.org> |
---|---|
date | Sat, 25 Aug 2018 17:59:48 +0200 |
parents | src/browser/sat_browser/register.py@f2170536ba23 |
children | 2af117bfe6cc |
comparison
equal
deleted
inserted
replaced
1123:63a4b8fe9782 | 1124:28e3eb3bb217 |
---|---|
1 #!/usr/bin/python | |
2 # -*- coding: utf-8 -*- | |
3 | |
4 # Libervia: a Salut à Toi frontend | |
5 # Copyright (C) 2011-2018 Jérôme Poisson <goffi@goffi.org> | |
6 # Copyright (C) 2011, 2012 Adrien Vigneron <adrienvigneron@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 #This page manage subscription and new account creation | |
22 | |
23 import pyjd # this is dummy in pyjs | |
24 from sat.core.i18n import _ | |
25 | |
26 from pyjamas.ui.SimplePanel import SimplePanel | |
27 from pyjamas.ui.VerticalPanel import VerticalPanel | |
28 from pyjamas.ui.HorizontalPanel import HorizontalPanel | |
29 from pyjamas.ui.StackPanel import StackPanel | |
30 from pyjamas.ui.PasswordTextBox import PasswordTextBox | |
31 from pyjamas.ui.TextBox import TextBox | |
32 from pyjamas.ui.FormPanel import FormPanel | |
33 from pyjamas.ui.Button import Button | |
34 from pyjamas.ui.Label import Label | |
35 from pyjamas.ui.HTML import HTML | |
36 from pyjamas.ui.PopupPanel import PopupPanel | |
37 from pyjamas.ui.Image import Image | |
38 from pyjamas.ui.Hidden import Hidden | |
39 from pyjamas import Window | |
40 from pyjamas.ui.KeyboardListener import KEY_ENTER | |
41 from pyjamas.Timer import Timer | |
42 | |
43 from __pyjamas__ import JS | |
44 | |
45 from constants import Const as C | |
46 | |
47 | |
48 | |
49 class RegisterPanel(FormPanel): | |
50 | |
51 def __init__(self, callback, session_data): | |
52 """ | |
53 @param callback(callable): method to call if login successful | |
54 @param session_data(dict): session metadata | |
55 """ | |
56 FormPanel.__init__(self) | |
57 self.setSize('600px', '350px') | |
58 self.callback = callback | |
59 self.setMethod(FormPanel.METHOD_POST) | |
60 main_panel = HorizontalPanel() | |
61 main_panel.setStyleName('registerPanel_main') | |
62 left_side = Image("media/libervia/register_left.png") | |
63 main_panel.add(left_side) | |
64 | |
65 ##StackPanel## | |
66 self.right_side = StackPanel(StyleName='registerPanel_right_side') | |
67 main_panel.add(self.right_side) | |
68 main_panel.setCellWidth(self.right_side, '100%') | |
69 | |
70 ##Login stack## | |
71 login_stack = SimplePanel() | |
72 login_stack.setStyleName('registerPanel_content') | |
73 login_vpanel = VerticalPanel() | |
74 login_stack.setWidget(login_vpanel) | |
75 | |
76 self.login_warning_msg = HTML('') | |
77 self.login_warning_msg.setStyleName('formWarning') | |
78 login_vpanel.add(self.login_warning_msg) | |
79 | |
80 login_label = Label('Login:') | |
81 self.login_box = TextBox() | |
82 self.login_box.setName("login") | |
83 self.login_box.addKeyboardListener(self) | |
84 login_pass_label = Label('Password:') | |
85 self.login_pass_box = PasswordTextBox() | |
86 self.login_pass_box.setName("login_password") | |
87 self.login_pass_box.addKeyboardListener(self) | |
88 | |
89 login_vpanel.add(login_label) | |
90 login_vpanel.add(self.login_box) | |
91 login_vpanel.add(login_pass_label) | |
92 login_vpanel.add(self.login_pass_box) | |
93 login_but = Button("Log in", getattr(self, "onLogin")) | |
94 login_but.setStyleName('button') | |
95 login_but.addStyleName('red') | |
96 login_vpanel.add(login_but) | |
97 self.right_side.add(login_stack, 'Return to the login screen') | |
98 | |
99 #The hidden submit_type field | |
100 self.submit_type = Hidden('submit_type') | |
101 login_vpanel.add(self.submit_type) | |
102 | |
103 ##Register stack## | |
104 if session_data["allow_registration"]: | |
105 register_stack = SimplePanel() | |
106 register_stack.setStyleName('registerPanel_content') | |
107 register_vpanel = VerticalPanel() | |
108 register_stack.setWidget(register_vpanel) | |
109 | |
110 self.register_warning_msg = HTML('') | |
111 self.register_warning_msg.setStyleName('formWarning') | |
112 register_vpanel.add(self.register_warning_msg) | |
113 | |
114 register_login_label = Label('Login:') | |
115 self.register_login_box = TextBox() | |
116 self.register_login_box.setName("register_login") | |
117 self.register_login_box.addKeyboardListener(self) | |
118 email_label = Label('E-mail:') | |
119 self.email_box = TextBox() | |
120 self.email_box.setName("email") | |
121 self.email_box.addKeyboardListener(self) | |
122 register_pass_label = Label('Password:') | |
123 self.register_pass_box = PasswordTextBox() | |
124 self.register_pass_box.setName("register_password") | |
125 self.register_pass_box.addKeyboardListener(self) | |
126 register_vpanel.add(register_login_label) | |
127 register_vpanel.add(self.register_login_box) | |
128 register_vpanel.add(email_label) | |
129 register_vpanel.add(self.email_box) | |
130 register_vpanel.add(register_pass_label) | |
131 register_vpanel.add(self.register_pass_box) | |
132 | |
133 register_but = Button("Register a new account", getattr(self, "onRegister")) | |
134 register_but.setStyleName('button') | |
135 register_but.addStyleName('red') | |
136 register_vpanel.add(register_but) | |
137 | |
138 self.right_side.add(register_stack, 'No account yet? Create a new one!') | |
139 self.right_side.addStackChangeListener(self) | |
140 register_stack.setWidth(None) | |
141 login_stack.setWidth(None) | |
142 | |
143 self.add(main_panel) | |
144 self.addFormHandler(self) | |
145 self.setAction('register_api/login') | |
146 | |
147 def onStackChanged(self, sender, index): | |
148 if index == 0: | |
149 self.login_box.setFocus(True) | |
150 elif index == 1: | |
151 self.register_login_box.setFocus(True) | |
152 | |
153 def onKeyPress(self, sender, keycode, modifiers): | |
154 # XXX: this is triggered before the textbox value has changed | |
155 if keycode == KEY_ENTER: | |
156 # Browsers offer an auto-completion feature to any | |
157 # text box, but the selected value is not set when | |
158 # the widget looses the focus. Using a timer with | |
159 # any delay value > 0 would do the trick. | |
160 if sender == self.login_box: | |
161 Timer(5, lambda timer: self.login_pass_box.setFocus(True)) | |
162 elif sender == self.login_pass_box: | |
163 self.onLogin(None) | |
164 elif sender == self.register_login_box: | |
165 Timer(5, lambda timer: self.email_box.setFocus(True)) | |
166 elif sender == self.email_box: | |
167 Timer(5, lambda timer: self.register_pass_box.setFocus(True)) | |
168 elif sender == self.register_pass_box: | |
169 self.onRegister(None) | |
170 | |
171 def onKeyUp(self, sender, keycode, modifiers): | |
172 # XXX: this is triggered after the textbox value has changed | |
173 if sender == self.login_box: | |
174 if "@" in self.login_box.getText(): | |
175 self.login_warning_msg.setHTML(_('<span class="formInfo">Entering a full JID is only needed to connect with an external XMPP account.</span>')) | |
176 else: | |
177 self.login_warning_msg.setHTML("") | |
178 | |
179 def onKeyDown(self, sender, keycode, modifiers): | |
180 pass | |
181 | |
182 def onLogin(self, button): | |
183 if not self.checkJID(self.login_box.getText()): | |
184 self.login_warning_msg.setHTML('Invalid login, valid characters<br>are a-z A-Z 0-9 _ - or a bare JID') | |
185 else: | |
186 self.submit_type.setValue('login') | |
187 self.submit(None) | |
188 | |
189 def onRegister(self, button): | |
190 # XXX: for now libervia forces the creation to lower case | |
191 self.register_login_box.setText(self.register_login_box.getText().lower()) | |
192 if not self.checkLogin(self.register_login_box.getText()): | |
193 self.register_warning_msg.setHTML(_('Invalid login, valid characters<br>are a-z A-Z 0-9 _ -')) | |
194 elif not self.checkEmail(self.email_box.getText()): | |
195 self.register_warning_msg.setHTML(_('Invalid email address<br>(or not accepted yet)')) | |
196 elif len(self.register_pass_box.getText()) < C.PASSWORD_MIN_LENGTH: | |
197 self.register_warning_msg.setHTML(_('Your password must contain<br>at least %d characters.') % C.PASSWORD_MIN_LENGTH) | |
198 else: | |
199 self.register_warning_msg.setHTML("") | |
200 self.submit_type.setValue('register') | |
201 self.submit(None) | |
202 | |
203 def onSubmit(self, event): | |
204 pass | |
205 | |
206 def onSubmitComplete(self, event): | |
207 result = event.getResults() | |
208 if result == C.PROFILE_AUTH_ERROR: | |
209 self.login_warning_msg.setHTML(_('Your login and/or password is incorrect. Please try again.')) | |
210 elif result == C.XMPP_AUTH_ERROR: | |
211 # TODO: call stdui action CHANGE_XMPP_PASSWD_ID as it's done in primitivus | |
212 Window.alert(_(u'Your XMPP account failed to connect. Did you enter the good password? If you have changed your XMPP password since your last connection on Libervia, please use another SàT frontend to update your profile.')) | |
213 elif result == C.PROFILE_LOGGED_EXT_JID: | |
214 self.callback() | |
215 Window.alert(_('A profile has been created on this Libervia service using your existing XMPP account. Since you are not using our XMPP server, we can not guaranty that all the extra features (blog, directory...) will fully work.')) | |
216 elif result == C.PROFILE_LOGGED: | |
217 self.callback() | |
218 elif result == C.SESSION_ACTIVE: | |
219 Window.alert(_('Session already active, this should not happen, please contact the author to fix it.')) | |
220 elif result == C.NO_REPLY: | |
221 Window.alert(_("Did not receive a reply (the timeout expired or the connection is broken).")) | |
222 elif result == C.ALREADY_EXISTS: | |
223 self.register_warning_msg.setHTML(_('This login already exists,<br>please choose another one.')) | |
224 elif result == C.INTERNAL_ERROR: | |
225 self.register_warning_msg.setHTML(_('An registration error occurred, please contact the server administrator.')) | |
226 elif result == C.REGISTRATION_SUCCEED: | |
227 self.login_warning_msg.setHTML("") | |
228 self.register_warning_msg.setHTML("") | |
229 self.login_box.setText(self.register_login_box.getText()) | |
230 self.login_pass_box.setText('') | |
231 self.register_login_box.setText('') | |
232 self.register_pass_box.setText('') | |
233 self.email_box.setText('') | |
234 self.right_side.showStack(0) | |
235 self.login_pass_box.setFocus(True) | |
236 Window.alert(_('An email has been sent to you with your login informations\nPlease remember that this is ONLY A TECHNICAL DEMO.')) | |
237 else: | |
238 Window.alert(_("An error occurred and we couldn't process your request. Please report the following error name to the administrators of your network: '%s'" % result)) | |
239 | |
240 def checkLogin(self, text): | |
241 """Check if the given text is a valid login | |
242 | |
243 @param text (unicode) | |
244 @return bool | |
245 """ | |
246 # FIXME: Pyjamas re module is not stable so we use pure JS instead | |
247 # FIXME: login is restricted to this regex until we fix the account creation | |
248 JS("""return /^(\w|-)+$/.test(text);""") | |
249 | |
250 def checkEmail(self, text): | |
251 """Check if the given text is a valid email address. | |
252 | |
253 @param text (unicode) | |
254 @return bool | |
255 """ | |
256 # FIXME: Pyjamas re module is not stable so we use pure JS instead | |
257 # FIXME: send a message to validate the email instead of using a bad regex | |
258 JS("""return /^(\w|-|\.|\+)+@(\w|-)+\.(\w|-)+$/.test(text);""") | |
259 | |
260 def checkJID(self, text): | |
261 """Check if the given text is a valid JID. | |
262 | |
263 @param text (unicode) | |
264 @return bool | |
265 """ | |
266 # FIXME: Pyjamas re module is not stable so we use pure JS instead | |
267 # FIXME: this regex is too restrictive for people using external XMPP account | |
268 JS("""return /^(\w|-|\.|\+)+(@(\w|-)+\.(\w|-)+)?$/.test(text);""") | |
269 | |
270 | |
271 class RegisterBox(PopupPanel): | |
272 | |
273 def __init__(self, callback, session_data, *args, **kwargs): | |
274 PopupPanel.__init__(self, *args, **kwargs) | |
275 self._form = RegisterPanel(callback, session_data) | |
276 self.setWidget(self._form) | |
277 | |
278 def onWindowResized(self, width, height): | |
279 super(RegisterBox, self).onWindowResized(width, height) | |
280 self.centerBox() | |
281 | |
282 def show(self): | |
283 super(RegisterBox, self).show() | |
284 self.centerBox() | |
285 self._form.login_box.setFocus(True) |