julen / pootle

Web-based translation and translation management tool

This URL has Read+Write access

julen (author)
Thu Aug 14 09:16:41 -0700 2008
commit  5b47b2fc4b2d24ca3065e8690126ab0c1e2a1565
tree    63982c99911b551ecbab713bce3418e5ad2dbbc1
parent  e03ed0b458352e4cc73becbb76430875edf70f42
pootle / users.py
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 1 #!/usr/bin/env python
a953d6ab » davidfraser 2005-07-01 added encoding markers for ... 2 # -*- coding: utf-8 -*-
d8ec3e47 » dwaynebailey 2006-06-15 [Forwardport] Update copyri... 3 #
4 # Copyright 2004-2006 Zuza Software Foundation
5 #
6 # This file is part of translate.
7 #
8 # translate is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2 of the License, or
11 # (at your option) any later version.
12 #
13 # translate 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 General Public License for more details.
17 #
18 # You should have received a copy of the GNU General Public License
19 # along with translate; if not, write to the Free Software
20 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 21
88aa19f2 » andreaspauley 2007-01-16 General code improvements t... 22 from jToolkit import web
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 23 from jToolkit.web import server
24 from jToolkit import mailer
69188f52 » davidfraser 2005-07-01 add support for unicode use... 25 from jToolkit import prefs
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 26 from Pootle import pagelayout
ca4ee7c6 » friedelwolff 2007-05-16 Translate language names an... 27 from translate.lang import data as langdata
d5a68e88 » friedelwolff 2007-08-02 Instantiate the language mo... 28 from translate.lang import factory
b6b28c3d » andreaspauley 2007-04-19 Encode the Subject Header o... 29 from email.Header import Header
ca4ee7c6 » friedelwolff 2007-05-16 Translate language names an... 30 import locale
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 31
32 class RegistrationError(ValueError):
d4b5e43b » friedelwolff 2006-09-15 Allow users to change their... 33 def __init__(self, message):
34 message = message.encode('utf-8')
35 ValueError.__init__(self, message)
36
37 # This mimimum passwordlength is mandated by the interface when registering or
38 # changing password
39 minpasswordlen = 6
40
41 def validatepassword(session, password, passwordconfirm):
42 if not password or len(password) < minpasswordlen:
43 raise RegistrationError(session.localize("You must supply a valid password of at least %d characters.", minpasswordlen))
44 if not password == passwordconfirm:
45 raise RegistrationError(session.localize("The password is not the same as the confirmation."))
46
47 def forcemessage(message):
48 """Tries to extract some kind of message and converts to unicode"""
49 if message and not isinstance(message, unicode):
50 return str(message).decode('utf-8')
51 else:
52 return message
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 53
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 54 class LoginPage(pagelayout.PootlePage):
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 55 """wraps the normal login page in a PootlePage layout"""
986213fe » friedelwolff 2006-07-19 Support introtext on login ... 56 def __init__(self, session, languagenames=None, message=None):
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 57 self.localize = session.localize
1e0066f2 » friedelwolff 2007-07-17 Provide translated language... 58 self.tr_lang = session.tr_lang
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 59 self.languagenames = languagenames
60 pagetitle = self.localize("Login to Pootle")
61 templatename = "login"
d4b5e43b » friedelwolff 2006-09-15 Allow users to change their... 62 message = forcemessage(message)
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 63 instancetitle = getattr(session.instance, "title", session.localize("Pootle Demo"))
64 sessionvars = {"status": session.status, "isopen": session.isopen, "issiteadmin": session.issiteadmin()}
986213fe » friedelwolff 2006-07-19 Support introtext on login ... 65 templatevars = {"pagetitle": pagetitle, "introtext": message,
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 66 "username_title": self.localize("Username:"),
67 "username": getattr(session, 'username', ''),
68 "password_title": self.localize("Password:"),
69 "language_title": self.localize('Language:'),
70 "languages": self.getlanguageoptions(session),
71 "login_text": self.localize('Login'),
31976563 » friedelwolff 2006-08-11 Use instancetitle instead o... 72 "session": sessionvars, "instancetitle": instancetitle}
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 73 pagelayout.PootlePage.__init__(self, templatename, templatevars, session)
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 74
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 75 def getlanguageoptions(self, session):
99714754 » friedelwolff 2006-10-12 Revert 4019:4021 by Gasper ... 76 """returns the language selector..."""
1e0066f2 » friedelwolff 2007-07-17 Provide translated language... 77 tr_default = session.localize("Default")
78 if tr_default != "Default":
79 tr_default = u"%s | \u202dDefault" % tr_default
80 languageoptions = [('', tr_default)]
99714754 » friedelwolff 2006-10-12 Revert 4019:4021 by Gasper ... 81 if isinstance(self.languagenames, dict):
82 languageoptions += self.languagenames.items()
83 else:
84 languageoptions += self.languagenames
b1f34932 » friedelwolff 2007-04-04 Only use the session langua... 85 if session.language in ["en", session.server.defaultlanguage]:
86 preferredlanguage = ""
87 else:
88 preferredlanguage = session.language
1e0066f2 » friedelwolff 2007-07-17 Provide translated language... 89 finallist = []
90 for key, value in languageoptions:
91 if key == 'templates':
92 continue
93 tr_name = session.tr_lang(value)
94 if tr_name != value:
95 # We have to use the LRO (left-to-right override) to ensure that
96 # brackets in the English part of the name is rendered correctly
97 # in an RTL layout like Arabic. We can't use markup because this
98 # is used inside an option tag.
99 value = u"%s | \u202d%s" % (tr_name, value)
100 selected = key==preferredlanguage or None
101 finallist.append({"code": key, "name": value, "selected": selected})
102 # rewritten for compatibility with Python 2.3
103 # finallist.sort(cmp=locale.strcoll, key=lambda dict: dict["name"])
104 finallist.sort(lambda x,y: locale.strcoll(x["name"], y["name"]))
105 return finallist
53814567 » davidfraser 2005-06-26 added ability to set a lang... 106
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 107 class RegisterPage(pagelayout.PootlePage):
108 """page for new registrations"""
986213fe » friedelwolff 2006-07-19 Support introtext on login ... 109 def __init__(self, session, argdict, message=None):
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 110 self.localize = session.localize
986213fe » friedelwolff 2006-07-19 Support introtext on login ... 111 if not message:
112 introtext = self.localize("Please enter your registration details")
113 else:
d4b5e43b » friedelwolff 2006-09-15 Allow users to change their... 114 introtext = forcemessage(message)
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 115 pagetitle = self.localize("Pootle Registration")
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 116 self.argdict = argdict
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 117 templatename = "register"
118 instancetitle = getattr(session.instance, "title", session.localize("Pootle Demo"))
119 sessionvars = {"status": session.status, "isopen": session.isopen, "issiteadmin": session.issiteadmin()}
120 templatevars = {"pagetitle": pagetitle, "introtext": introtext,
121 "username_title": self.localize("Username"),
122 "username_tooltip": self.localize("Your requested username"),
123 "username": self.argdict.get("username", ""),
124 "email_title": self.localize("Email Address"),
40c807c8 » friedelwolff 2006-09-15 Minor improvements to new t... 125 "email_tooltip": self.localize("You must supply a valid email address"),
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 126 "email": self.argdict.get("email", ""),
127 "fullname_title": self.localize("Full Name"),
128 "fullname_tooltip": self.localize("Your full name"),
129 "fullname": self.argdict.get("name", ""),
130 "password_title": self.localize("Password"),
131 "password_tooltip": self.localize("Your desired password"),
132 "password": self.argdict.get("password", ""),
d4da3f2f » friedelwolff 2006-09-04 [Contributed by Charl van N... 133 "passwordconfirm_title": self.localize("Confirm password"),
134 "passwordconfirm_tooltip": self.localize("Type your password again to ensure it is entered correctly"),
135 "passwordconfirm": self.argdict.get("passwordconfirm", ""),
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 136 "register_text": self.localize('Register Account'),
31976563 » friedelwolff 2006-08-11 Use instancetitle instead o... 137 "session": sessionvars, "instancetitle": instancetitle}
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 138 pagelayout.PootlePage.__init__(self, templatename, templatevars, session)
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 139
140 class ActivatePage(pagelayout.PootlePage):
141 """page for new registrations"""
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 142 def __init__(self, session, argdict, title=None, message=None):
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 143 self.localize = session.localize
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 144 if not message:
145 introtext = self.localize("Please enter your activation details")
146 else:
d4b5e43b » friedelwolff 2006-09-15 Allow users to change their... 147 introtext = forcemessage(message)
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 148 self.argdict = argdict
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 149 if title is None:
150 pagetitle = self.localize("Pootle Account Activation")
151 else:
152 pagetitle = title
153 templatename = "activate"
154 instancetitle = getattr(session.instance, "title", session.localize("Pootle Demo"))
155 sessionvars = {"status": session.status, "isopen": session.isopen, "issiteadmin": session.issiteadmin()}
156 templatevars = {"pagetitle": pagetitle, "introtext": introtext,
157 "username_title": self.localize("Username"),
158 "username_tooltip": self.localize("Your requested username"),
159 "username": self.argdict.get("username", ""),
160 "code_title": self.localize("Activation Code"),
161 "code_tooltip": self.localize("The activation code you received"),
162 "code": self.argdict.get("activationcode", ""),
163 "activate_text": self.localize('Activate Account'),
31976563 » friedelwolff 2006-08-11 Use instancetitle instead o... 164 "session": sessionvars, "instancetitle": instancetitle}
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 165 pagelayout.PootlePage.__init__(self, templatename, templatevars, session)
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 166
167 class UserOptions(pagelayout.PootlePage):
168 """page for user to change their options"""
d4b5e43b » friedelwolff 2006-09-15 Allow users to change their... 169 def __init__(self, potree, session, message=None):
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 170 self.potree = potree
171 self.session = session
172 self.localize = session.localize
ca4ee7c6 » friedelwolff 2007-05-16 Translate language names an... 173 self.tr_lang = session.tr_lang
d4b5e43b » friedelwolff 2006-09-15 Allow users to change their... 174 message = forcemessage(message)
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 175 pagetitle = self.localize("Options for: %s", session.username)
176 templatename = "options"
177 instancetitle = getattr(session.instance, "title", session.localize("Pootle Demo"))
0fc2f1aa » friedelwolff 2008-06-13 Enable translation while di... 178 enablealtsrc = getattr(session.instance, "enablealtsrc", False)
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 179 sessionvars = {"status": session.status, "isopen": session.isopen, "issiteadmin": session.issiteadmin()}
d4b5e43b » friedelwolff 2006-09-15 Allow users to change their... 180 templatevars = {"pagetitle": pagetitle, "introtext": message,
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 181 "detailstitle": self.localize("Personal Details"),
182 "option_heading": self.localize("Option"),
183 "value_heading": self.localize("Current value"),
184 "fullname_title": self.localize("Name"),
185 "fullname": self.session.prefs.name,
186 "email_title": self.localize("Email"),
187 "email": self.session.prefs.email,
3887270c » friedelwolff 2006-09-14 Enable functionality for us... 188 "password_title": self.localize("Password"),
40c807c8 » friedelwolff 2006-09-15 Minor improvements to new t... 189 "passwordconfirm_title": self.localize("Confirm password"),
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 190 "interface_title": self.localize("Translation Interface Configuration"),
191 "uilanguage_heading": self.localize("User Interface language"),
192 "projects_title": self.localize("My Projects"),
193 "projects": self.getprojectoptions(),
194 "languages_title": self.localize("My Languages"),
195 "languages": self.getlanguageoptions(),
196 "home_link": self.localize("Home page"),
197 "submit_button": self.localize("Save changes"),
0fc2f1aa » friedelwolff 2008-06-13 Enable translation while di... 198 "session": sessionvars,
199 "instancetitle": instancetitle,
200 "enablealtsrc": enablealtsrc}
201 if enablealtsrc == 'True':
202 templatevars["altsrclanguage_title"] = self.localize("Alternative Source Language")
203 templatevars["altsrclanguages"] = self.getaltsrcoptions()
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 204 otheroptions = self.getotheroptions()
205 templatevars.update(otheroptions)
206 pagelayout.PootlePage.__init__(self, templatename, templatevars, session)
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 207
208 def getprojectoptions(self):
99714754 » friedelwolff 2006-10-12 Revert 4019:4021 by Gasper ... 209 """gets the options box to change the user's projects"""
210 projectoptions = []
211 userprojects = self.session.getprojects()
212 for projectcode in self.potree.getprojectcodes():
213 projectname = self.potree.getprojectname(projectcode)
214 projectoptions.append({"code": projectcode, "name": projectname, "selected": projectcode in userprojects or None})
215 return projectoptions
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 216
217 def getlanguageoptions(self):
99714754 » friedelwolff 2006-10-12 Revert 4019:4021 by Gasper ... 218 """returns options for languages"""
219 userlanguages = self.session.getlanguages()
220 languageoptions = self.potree.getlanguages()
221 languages = []
222 for language, name in languageoptions:
ca4ee7c6 » friedelwolff 2007-05-16 Translate language names an... 223 languages.append({"code": language, "name": self.tr_lang(name), "selected": language in userlanguages or None})
1e0066f2 » friedelwolff 2007-07-17 Provide translated language... 224 # rewritten for compatibility with Python 2.3
225 # languages.sort(cmp=locale.strcoll, key=lambda dict: dict["name"])
226 languages.sort(lambda x,y: locale.strcoll(x["name"], y["name"]))
99714754 » friedelwolff 2006-10-12 Revert 4019:4021 by Gasper ... 227 return languages
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 228
0fc2f1aa » friedelwolff 2008-06-13 Enable translation while di... 229 def getaltsrcoptions(self):
230 """returns options for alternative source languages"""
231 useraltsrc = self.session.getaltsrclanguage()
232 languageoptions = self.potree.getlanguages()
233 altsrclanguages = []
234 for language, name in languageoptions:
235 altsrclanguages.append({"code": language, "name": self.tr_lang(name), "selected": language in useraltsrc and 'selected' or None})
236 # rewritten for compatibility with Python 2.3
237 # altsrclanguages.sort(cmp=locale.strcoll, key=lambda dict: dict["name"])
238 altsrclanguages.sort(lambda x,y: locale.strcoll(x["name"], y["name"]))
239 # l10n: 'None' is displayed as the first item in the alternative source languages list and disables the feature.
240 altsrclanguages.insert(0, {"code": '', "name": self.session.localize("None"), "selected": '' in useraltsrc and 'selected' or None})
241 return altsrclanguages
242
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 243 def getotheroptions(self):
99714754 » friedelwolff 2006-10-12 Revert 4019:4021 by Gasper ... 244 uilanguage = getattr(self.session.prefs, "uilanguage", "")
245 if not uilanguage:
246 userlanguages = self.session.getlanguages()
247 if userlanguages:
248 uilanguage = userlanguages[0]
249 languageoptions = [{"code": '', "name": ''}]
250 for code, name in self.potree.getlanguages():
9e611dc5 » friedelwolff 2007-01-07 Don't make 'templates' a po... 251 if code == "templates":
252 continue
ca4ee7c6 » friedelwolff 2007-05-16 Translate language names an... 253 languageoptions.append({"code": code, "name": self.tr_lang(name), "selected": uilanguage == code or None})
1e0066f2 » friedelwolff 2007-07-17 Provide translated language... 254 # rewritten for compatibility with Python 2.3
255 # languageoptions.sort(cmp=locale.strcoll, key=lambda dict: dict["name"])
256 languageoptions.sort(lambda x,y: locale.strcoll(x["name"], y["name"]))
c8b256cd » friedelwolff 2007-04-12 Remove option to set the wi... 257 options = {"inputheight": self.localize("Input Height (in lines)"),
99714754 » friedelwolff 2006-10-12 Revert 4019:4021 by Gasper ... 258 "viewrows": self.localize("Number of rows in view mode"),
259 "translaterows": self.localize("Number of rows in translate mode")}
260 optionlist = []
261 for option, description in options.items():
262 optionvalue = getattr(self.session.prefs, option, "")
263 optionlist.append({"code": option, "description": description, "value": optionvalue})
264 return {"uilanguage": uilanguage, "uilanguage_options": languageoptions, "other_options": optionlist}
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 265
266 class OptionalLoginAppServer(server.LoginAppServer):
267 """a server that enables login but doesn't require it except for specified pages"""
268 def handle(self, req, pathwords, argdict):
269 """handles the request and returns a page object in response"""
8d547b44 » friedelwolff 2007-05-16 Handle session initialisati... 270 session = None
197ce83e » friedelwolff 2006-08-16 Trap exceptions and display... 271 try:
272 argdict = self.processargs(argdict)
273 session = self.getsession(req, argdict)
274 if session.isopen:
275 session.pagecount += 1
276 session.remote_ip = self.getremoteip(req)
277 else:
278 self.initlanguage(req, session)
279 page = self.getpage(pathwords, session, argdict)
280 except Exception, e:
8d547b44 » friedelwolff 2007-05-16 Handle session initialisati... 281 # Because of the exception, 'session' might not be initialised. So let's
282 # play extra safe
283 if not session:
284 raise Exception("Could not initialise session.\nDetail:%s" % str(e))
285
197ce83e » friedelwolff 2006-08-16 Trap exceptions and display... 286 exceptionstr = self.errorhandler.exception_str()
287 errormessage = str(e).decode("utf-8")
288 traceback = self.errorhandler.traceback_str().decode('utf-8')
289 browsertraceback = ""
0b0d21a8 » friedelwolff 2006-10-04 Correctly display exception... 290 options = getattr(self, "options", None)
291 # with unit tests we might not have self.options, therefore this test
292 if options:
3927647f » friedelwolff 2007-01-08 Rewrite error handling slig... 293 if options.browsererrors == 'traceback':
0b0d21a8 » friedelwolff 2006-10-04 Correctly display exception... 294 browsertraceback = traceback
3927647f » friedelwolff 2007-01-08 Rewrite error handling slig... 295 if options.logerrors == 'traceback':
0b0d21a8 » friedelwolff 2006-10-04 Correctly display exception... 296 self.errorhandler.logerror(traceback)
3927647f » friedelwolff 2007-01-08 Rewrite error handling slig... 297 elif options.logerrors == 'exception':
0b0d21a8 » friedelwolff 2006-10-04 Correctly display exception... 298 self.errorhandler.logerror(exceptionstr)
3927647f » friedelwolff 2007-01-08 Rewrite error handling slig... 299 elif options.logerrors == 'message':
0b0d21a8 » friedelwolff 2006-10-04 Correctly display exception... 300 self.errorhandler.logerror(errormessage)
301 else:
197ce83e » friedelwolff 2006-08-16 Trap exceptions and display... 302 self.errorhandler.logerror(traceback)
303
304 refreshurl = req.headers_in.getheader('Referer') or "/"
305 templatename = "error"
306 templatevars = {
307 "pagetitle": session.localize("Error"),
308 "refresh": 30,
309 "refreshurl": refreshurl,
310 "message": errormessage,
db0f63f7 » friedelwolff 2006-09-21 Only set the UI language fr... 311 "traceback": browsertraceback,
312 "back": session.localize("Back"),
197ce83e » friedelwolff 2006-08-16 Trap exceptions and display... 313 }
314 pagelayout.completetemplatevars(templatevars, session)
315 page = server.Redirect(refreshurl, withtemplate=(templatename, templatevars))
316 return page
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 317
65879a92 » friedelwolff 2006-08-11 Pave the way to have the se... 318 def initlanguage(self, req, session):
319 """Initialises the session language from the request"""
320 # This version doesn't know which languages we have, so we have to override
321 # in PootleServer.
322 session.setlanguage("en")
323
69188f52 » davidfraser 2005-07-01 add support for unicode use... 324 def hasuser(self, users, username):
325 """returns whether the user exists in users"""
326 return users.__hasattr__(username)
327
328 def getusernode(self, users, username):
329 """gets the node for the given user"""
330 if not self.hasuser(users, username):
331 usernode = prefs.PrefNode(users, username)
332 users.__setattr__(username, usernode)
333 else:
334 usernode = users.__getattr__(username)
335 return usernode
336
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 337 def adduser(self, users, username, fullname, email, password):
338 """adds the user with the given details"""
69188f52 » davidfraser 2005-07-01 add support for unicode use... 339 usernode = self.getusernode(users, username)
340 usernode.name = fullname
341 usernode.email = email
88aa19f2 » andreaspauley 2007-01-16 General code improvements t... 342 usernode.passwdhash = web.session.md5hexdigest(password)
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 343
344 def makeactivationcode(self, users, username):
345 """makes a new activation code for the user and returns it"""
69188f52 » davidfraser 2005-07-01 add support for unicode use... 346 usernode = self.getusernode(users, username)
347 usernode.activated = 0
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 348 activationcode = self.generateactivationcode()
69188f52 » davidfraser 2005-07-01 add support for unicode use... 349 usernode.activationcode = activationcode
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 350 return activationcode
351
352 def activate(self, users, username):
353 """sets the user as activated"""
69188f52 » davidfraser 2005-07-01 add support for unicode use... 354 self.getusernode(users, username).activated = 1
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 355
356 def changeusers(self, session, argdict):
357 """handles multiple changes from the site admin"""
358 if not session.issiteadmin():
359 raise ValueError(session.localize("You need to be siteadmin to change users"))
360 users = session.loginchecker.users
361 for key, value in argdict.iteritems():
362 if key.startswith("userremove-"):
363 usercode = key.replace("userremove-", "", 1)
69188f52 » davidfraser 2005-07-01 add support for unicode use... 364 if self.hasuser(users, usercode):
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 365 raise NotImplementedError("Can't remove users")
366 elif key.startswith("username-"):
367 username = key.replace("username-", "", 1)
69188f52 » davidfraser 2005-07-01 add support for unicode use... 368 if self.hasuser(users, username):
369 usernode = self.getusernode(users, username)
24ac3aa0 » davidfraser 2005-10-21 corrected horrendous code t... 370 fullname = getattr(usernode, "name", None)
371 if fullname != value:
372 usernode.name = value
ce7cc2e8 » davidfraser 2005-10-24 fixed missing : syntax errors 373 elif key.startswith("useremail-"):
24ac3aa0 » davidfraser 2005-10-21 corrected horrendous code t... 374 username = key.replace("useremail-", "", 1)
375 if self.hasuser(users, username):
376 usernode = self.getusernode(users, username)
69188f52 » davidfraser 2005-07-01 add support for unicode use... 377 useremail = getattr(usernode, "email", None)
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 378 if useremail != value:
69188f52 » davidfraser 2005-07-01 add support for unicode use... 379 usernode.email = value
ce7cc2e8 » davidfraser 2005-10-24 fixed missing : syntax errors 380 elif key.startswith("userpassword-"):
24ac3aa0 » davidfraser 2005-10-21 corrected horrendous code t... 381 username = key.replace("userpassword-", "", 1)
382 if self.hasuser(users, username):
383 usernode = self.getusernode(users, username)
384 if value and value.strip():
88aa19f2 » andreaspauley 2007-01-16 General code improvements t... 385 usernode.passwdhash = web.session.md5hexdigest(value.strip())
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 386 elif key.startswith("useractivated-"):
387 username = key.replace("useractivated-", "", 1)
69188f52 » davidfraser 2005-07-01 add support for unicode use... 388 self.activate(users, username)
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 389 elif key == "newusername":
390 username = value.lower()
391 if not username:
392 continue
393 if not (username[:1].isalpha() and username.replace("_","").isalnum()):
394 raise ValueError("Login must be alphanumeric and start with an alphabetic character (got %r)" % username)
b6cdd52e » friedelwolff 2006-04-05 Don't allow "nobody" or "de... 395 if username in ["nobody", "default"]:
396 raise ValueError('"%s" is a reserved username.' % username)
69188f52 » davidfraser 2005-07-01 add support for unicode use... 397 if self.hasuser(users, username):
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 398 raise ValueError("Already have user with the login: %s" % username)
399 userpassword = argdict.get("newuserpassword", None)
a380c12e » friedelwolff 2006-08-11 Use session.localize() inst... 400 if userpassword is None or userpassword == session.localize("(add password here)"):
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 401 raise ValueError("You must specify a password")
b28e9ad6 » friedelwolff 2006-05-15 [Forward port] Fix adding u... 402 userfullname = argdict.get("newuserfullname", None)
a380c12e » friedelwolff 2006-08-11 Use session.localize() inst... 403 if userfullname == session.localize("(add full name here)"):
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 404 raise ValueError("Please set the users full name or leave it blank")
405 useremail = argdict.get("newuseremail", None)
a380c12e » friedelwolff 2006-08-11 Use session.localize() inst... 406 if useremail == session.localize("(add email here)"):
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 407 raise ValueError("Please set the users email address or leave it blank")
408 useractivate = "newuseractivate" in argdict
409 self.adduser(users, username, userfullname, useremail, userpassword)
410 if useractivate:
411 self.activate(users, username)
412 else:
413 activationcode = self.makeactivationcode(users, username)
414 print "user activation code for %s is %s" % (username, activationcode)
415 session.saveprefs()
416
417 def handleregistration(self, session, argdict):
418 """handles the actual registration"""
a380c12e » friedelwolff 2006-08-11 Use session.localize() inst... 419 #TODO: Fix layout, punctuation, spacing and correlation of messages
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 420 supportaddress = getattr(self.instance.registration, 'supportaddress', "")
421 username = argdict.get("username", "")
422 if not username or not username.isalnum() or not username[0].isalpha():
40c807c8 » friedelwolff 2006-09-15 Minor improvements to new t... 423 raise RegistrationError(session.localize("Username must be alphanumeric, and must start with an alphabetic character."))
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 424 fullname = argdict.get("name", "")
425 email = argdict.get("email", "")
426 password = argdict.get("password", "")
d4da3f2f » friedelwolff 2006-09-04 [Contributed by Charl van N... 427 passwordconfirm = argdict.get("passwordconfirm", "")
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 428 if " " in email or not (email and "@" in email and "." in email):
a380c12e » friedelwolff 2006-08-11 Use session.localize() inst... 429 raise RegistrationError(session.localize("You must supply a valid email address"))
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 430 userexists = session.loginchecker.userexists(username)
431 users = session.loginchecker.users
432 if userexists:
69188f52 » davidfraser 2005-07-01 add support for unicode use... 433 usernode = self.getusernode(users, username)
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 434 # use the email address on file
435 email = getattr(usernode, "email", email)
436 password = ""
437 # TODO: we can't figure out the password as we only store the md5sum. have a password reset mechanism
a380c12e » friedelwolff 2006-08-11 Use session.localize() inst... 438 message = session.localize("You (or someone else) attempted to register an account with your username.\n")
439 message += session.localize("We don't store your actual password but only a hash of it.\n")
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 440 if supportaddress:
a380c12e » friedelwolff 2006-08-11 Use session.localize() inst... 441 message += session.localize("If you have a problem with registration, please contact %s.\n", supportaddress)
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 442 else:
a380c12e » friedelwolff 2006-08-11 Use session.localize() inst... 443 message += session.localize("If you have a problem with registration, please contact the site administrator.\n")
444 displaymessage = session.localize("That username already exists. An email will be sent to the registered email address.\n")
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 445 redirecturl = "login.html?username=%s" % username
a380c12e » friedelwolff 2006-08-11 Use session.localize() inst... 446 displaymessage += session.localize("Proceeding to <a href='%s'>login</a>\n", redirecturl)
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 447 else:
d4b5e43b » friedelwolff 2006-09-15 Allow users to change their... 448 validatepassword(session, password, passwordconfirm)
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 449 self.adduser(users, username, fullname, email, password)
450 activationcode = self.makeactivationcode(users, username)
451 activationlink = ""
a380c12e » friedelwolff 2006-08-11 Use session.localize() inst... 452 message = session.localize("A Pootle account has been created for you using this email address.\n")
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 453 if session.instance.baseurl.startswith("http://"):
a380c12e » friedelwolff 2006-08-11 Use session.localize() inst... 454 message += session.localize("To activate your account, follow this link:\n")
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 455 activationlink = session.instance.baseurl
456 if not activationlink.endswith("/"):
457 activationlink += "/"
458 activationlink += "activate.html?username=%s&activationcode=%s" % (username, activationcode)
459 message += " %s \n" % activationlink
a380c12e » friedelwolff 2006-08-11 Use session.localize() inst... 460 message += session.localize("Your activation code is:\n%s\n", activationcode)
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 461 if activationlink:
a380c12e » friedelwolff 2006-08-11 Use session.localize() inst... 462 message += session.localize("If you are unable to follow the link, please enter the above code at the activation page.\n")
463 message += session.localize("This message is sent to verify that the email address is in fact correct. If you did not want to register an account, you may simply ignore the message.\n")
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 464 redirecturl = "activate.html?username=%s" % username
a380c12e » friedelwolff 2006-08-11 Use session.localize() inst... 465 displaymessage = session.localize("Account created. You will be emailed login details and an activation code. Please enter your activation code on the <a href='%s'>activation page</a>.", redirecturl)
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 466 if activationlink:
cca184cc » friedelwolff 2006-08-12 Typo in code to add space f... 467 displaymessage += " " + session.localize("(Or simply click on the activation link in the email)")
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 468 session.saveprefs()
a380c12e » friedelwolff 2006-08-11 Use session.localize() inst... 469 message += session.localize("Your user name is: %s\n", username)
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 470 if password.strip():
a380c12e » friedelwolff 2006-08-11 Use session.localize() inst... 471 message += session.localize("Your password is: %s\n", password)
472 message += session.localize("Your registered email address is: %s\n", email)
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 473 smtpserver = self.instance.registration.smtpserver
474 fromaddress = self.instance.registration.fromaddress
b6b28c3d » andreaspauley 2007-04-19 Encode the Subject Header o... 475 subject = Header(session.localize("Pootle Registration"),
476 "utf-8").encode()
477 messagedict = {"from": fromaddress, "to": [email], "subject": subject, "body": message}
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 478 if supportaddress:
479 messagedict["reply-to"] = supportaddress
480 fullmessage = mailer.makemessage(messagedict)
69188f52 » davidfraser 2005-07-01 add support for unicode use... 481 if isinstance(fullmessage, unicode):
482 fullmessage = fullmessage.encode("utf-8")
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 483 errmsg = mailer.dosendmessage(fromemail=self.instance.registration.fromaddress, recipientemails=[email], message=fullmessage, smtpserver=smtpserver)
484 if errmsg:
485 raise RegistrationError("Error sending mail: %s" % errmsg)
486 return displaymessage, redirecturl
487
488 def registerpage(self, session, argdict):
489 """handle registration or return the Register page"""
490 if "username" in argdict:
491 try:
492 displaymessage, redirecturl = self.handleregistration(session, argdict)
493 except RegistrationError, message:
986213fe » friedelwolff 2006-07-19 Support introtext on login ... 494 return RegisterPage(session, argdict, message)
c1445f5b » friedelwolff 2006-05-15 templatevars is dictionary,... 495 redirectpage = pagelayout.PootlePage("Redirecting...", {}, session)
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 496 redirectpage.templatename = "redirect"
497 redirectpage.templatevars = {
beff060a » friedelwolff 2007-01-04 Indicate message bug in com... 498 # BUG: We won't redirect to registration page, we will go to
499 # activation or login
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 500 "pagetitle": session.localize("Redirecting to Registration Page..."),
501 "refresh": 10,
502 "refreshurl": redirecturl,
503 "message": displaymessage,
504 }
505 redirectpage.completevars()
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 506 return redirectpage
507 else:
508 return RegisterPage(session, argdict)
509
510 def activatepage(self, session, argdict):
511 """handle activation or return the Register page"""
512 if "username" in argdict and "activationcode" in argdict:
513 username = argdict["username"]
514 activationcode = argdict["activationcode"]
69188f52 » davidfraser 2005-07-01 add support for unicode use... 515 if self.hasuser(session.loginchecker.users, username):
516 usernode = self.getusernode(session.loginchecker.users, username)
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 517 correctcode = getattr(usernode, "activationcode", "")
518 if correctcode and correctcode.strip().lower() == activationcode.strip().lower():
519 setattr(usernode, "activated", 1)
520 session.saveprefs()
c1445f5b » friedelwolff 2006-05-15 templatevars is dictionary,... 521 redirectpage = pagelayout.PootlePage("Redirecting to login...", {}, session)
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 522 redirectpage.templatename = "redirect"
523 redirectpage.templatevars = {
524 "pagetitle": session.localize("Redirecting to login Page..."),
525 "refresh": 10,
526 "refreshurl": "login.html?username=%s" % username,
527 "message": session.localize("Your account has been activated! Redirecting to login..."),
528 }
529 redirectpage.completevars()
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 530 return redirectpage
a8137361 » friedelwolff 2006-08-04 Two minor improvements to E... 531 failedmessage = session.localize("The activation information was not valid.")
b00bca80 » davidfraser 2006-04-26 [forwardport from Pootle-ki... 532 return ActivatePage(session, argdict, title=session.localize("Activation Failed"), message=failedmessage)
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 533 else:
534 return ActivatePage(session, argdict)
535
88aa19f2 » andreaspauley 2007-01-16 General code improvements t... 536 class PootleSession(web.session.LoginSession):
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 537 """a session object that knows about Pootle"""
538 def __init__(self, sessioncache, server, sessionstring = None, loginchecker = None):
539 """sets up the session and remembers the users prefs"""
540 super(PootleSession, self).__init__(sessioncache, server, sessionstring, loginchecker)
541 self.getprefs()
542
543 def getprefs(self):
544 """gets the users prefs into self.prefs"""
545 if self.isopen:
69188f52 » davidfraser 2005-07-01 add support for unicode use... 546 self.prefs = self.loginchecker.users.__getattr__(self.username)
5de66380 » friedelwolff 2006-10-11 Properly deal with interfac... 547 if self.language_set:
548 self.setlanguage(self.language_set)
549 return
02a70584 » friedelwolff 2006-09-18 Handle language preference ... 550 uilanguage = getattr(self.prefs, "uilanguage", None)
5de66380 » friedelwolff 2006-10-11 Properly deal with interfac... 551 if uilanguage:
02a70584 » friedelwolff 2006-09-18 Handle language preference ... 552 self.setlanguage(uilanguage)
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 553 else:
554 self.prefs = None
555
556 def saveprefs(self):
557 """saves changed preferences back to disk"""
558 # TODO: this is a hack, fix it up nicely :-)
559 prefsfile = self.loginchecker.users.__root__.__dict__["_setvalue"].im_self
560 prefsfile.savefile()
561
562 def open(self):
563 """opens the session, along with the users prefs"""
564 super(PootleSession, self).open()
565 self.getprefs()
566 return self.isopen
567
568 def close(self, req):
569 """opens the session, along with the users prefs"""
570 super(PootleSession, self).close(req)
571 self.getprefs()
572
53814567 » davidfraser 2005-06-26 added ability to set a lang... 573 def setlanguage(self, language):
574 """sets the language for the session"""
575 self.language_set = language or ""
576 if language:
577 self.language = language
1b0dde27 » friedelwolff 2006-08-11 with setlanguage(None) only... 578 elif not getattr(self, "language", None):
53814567 » davidfraser 2005-06-26 added ability to set a lang... 579 if self.isopen:
580 self.language = getattr(self.prefs, "uilanguage", "") or self.server.defaultlanguage
581 else:
582 self.language = self.server.defaultlanguage
583 if self.isopen:
584 if not getattr(self.prefs, "uilanguage", "") and self.language_set:
585 self.setinterfaceoptions({"option-uilanguage": self.language_set})
586 self.translation = self.server.gettranslation(self.language)
ca4ee7c6 » friedelwolff 2007-05-16 Translate language names an... 587 self.tr_lang = langdata.tr_lang(self.language)
588 try:
589 locale.setlocale(locale.LC_ALL, str(self.language))
590 except locale.Error:
591 # The system might not have the locale installed
592 pass
8a3b96ca » friedelwolff 2006-12-21 Recheck the session status ... 593 self.checkstatus(None, None)
d5a68e88 » friedelwolff 2007-08-02 Instantiate the language mo... 594 if self.language:
595 self.lang = factory.getlanguage(self.language)
53814567 » davidfraser 2005-06-26 added ability to set a lang... 596
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 597 def validate(self):
598 """checks if this session is valid (which means the user must be activated)"""
599 if not super(PootleSession, self).validate():
600 return False
69188f52 » davidfraser 2005-07-01 add support for unicode use... 601 if self.loginchecker.users.__hasattr__(self.username):
602 usernode = self.loginchecker.users.__getattr__(self.username)
603 if getattr(usernode, "activated", 0):
604 return self.isvalid
605 self.isvalid = False
606 self.status = "username has not yet been activated"
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 607 return self.isvalid
608
609 def setoptions(self, argdict):
610 """sets the user options"""
611 userprojects = argdict.get("projects", [])
612 if isinstance(userprojects, (str, unicode)):
613 userprojects = [userprojects]
614 setattr(self.prefs, "projects", ",".join(userprojects))
615 userlanguages = argdict.get("languages", [])
616 if isinstance(userlanguages, (str, unicode)):
617 userlanguages = [userlanguages]
618 setattr(self.prefs, "languages", ",".join(userlanguages))
619 self.saveprefs()
620
621 def setpersonaloptions(self, argdict):
622 """sets the users personal details"""
623 name = argdict.get("option-name", "")
624 email = argdict.get("option-email", "")
d4b5e43b » friedelwolff 2006-09-15 Allow users to change their... 625 password = argdict.get("option-password", "")
626 passwordconfirm = argdict.get("option-passwordconfirm", "")
627
628 if password or passwordconfirm:
629 validatepassword(self, password, passwordconfirm)
630 setattr(self.prefs, "name", name)
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 631 setattr(self.prefs, "email", email)
d4b5e43b » friedelwolff 2006-09-15 Allow users to change their... 632 if password:
88aa19f2 » andreaspauley 2007-01-16 General code improvements t... 633 passwdhash = web.session.md5hexdigest(argdict.get("option-password", ""))
3887270c » friedelwolff 2006-09-14 Enable functionality for us... 634 setattr(self.prefs, "passwdhash", passwdhash)
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 635 self.saveprefs()
636
0b867088 » dwaynebailey 2005-05-03 Users can now set the desir... 637 def setinterfaceoptions(self, argdict):
638 """sets the users interface details"""
53814567 » davidfraser 2005-06-26 added ability to set a lang... 639 value = argdict.get("option-uilanguage", "")
640 if value:
641 self.prefs.uilanguage = value
02a70584 » friedelwolff 2006-09-18 Handle language preference ... 642 self.setlanguage(value)
0b867088 » dwaynebailey 2005-05-03 Users can now set the desir... 643 def setinterfacevalue(name, errormessage):
644 value = argdict.get("option-%s" % name, "")
645 if value != "":
646 if not value.isdigit():
647 raise ValueError(errormessage)
648 setattr(self.prefs, name, value)
649 setinterfacevalue("inputheight", self.localize("Input height must be numeric"))
650 setinterfacevalue("inputwidth", self.localize("Input width must be numeric"))
651 setinterfacevalue("viewrows", self.localize("The number of rows displayed in view mode must be numeric"))
652 setinterfacevalue("translaterows", self.localize("The number of rows displayed in translate mode must be numeric"))
0fc2f1aa » friedelwolff 2008-06-13 Enable translation while di... 653 useraltsrclanguage = argdict.get("altsrclanguage", "")
654 if isinstance(useraltsrclanguage, (str, unicode)):
655 setattr(self.prefs, "altsrclanguage", useraltsrclanguage)
0b867088 » dwaynebailey 2005-05-03 Users can now set the desir... 656 self.saveprefs()
657
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 658 def getprojects(self):
659 """gets the user's projects"""
660 userprojects = getattr(self.prefs, "projects", "")
661 return [projectcode.strip() for projectcode in userprojects.split(',') if projectcode.strip()]
662
663 def getlanguages(self):
664 """gets the user's languages"""
665 userlanguages = getattr(self.prefs, "languages", "")
666 return [languagecode.strip() for languagecode in userlanguages.split(',') if languagecode.strip()]
667
0fc2f1aa » friedelwolff 2008-06-13 Enable translation while di... 668 def getaltsrclanguage(self):
669 """gets the user's alternative source language"""
670 useraltsrclanguage = getattr(self.prefs, "altsrclanguage", "")
671 return useraltsrclanguage.strip()
672
ca3d8109 » davidfraser 2005-04-20 moved from translate/pootle... 673 def getrights(self):
674 """gets the user's rights"""
675 return getattr(self.prefs, "rights", None)
676
677 def issiteadmin(self):
678 """returns whether the user can administer the site"""
679 return getattr(self.getrights(), "siteadmin", False)
680