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)