2 # -*- coding: utf-8 -*-
4 # Copyright 2004-2006 Zuza Software Foundation
6 # This file is part of translate.
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.
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.
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
22 from jToolkit
import web
23 from jToolkit
.web
import server
24 from jToolkit
import mailer
25 from jToolkit
import prefs
26 from Pootle
import pagelayout
27 from translate
.lang
import data
as langdata
28 from translate
.lang
import factory
29 from email
.Header
import Header
32 class RegistrationError(ValueError):
33 def __init__(self
, message
):
34 message
= message
.encode('utf-8')
35 ValueError.__init
__(self
, message
)
37 # This mimimum passwordlength is mandated by the interface when registering or
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."))
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')
54 class LoginPage(pagelayout
.PootlePage
):
55 """wraps the normal login page in a PootlePage layout"""
56 def __init__(self
, session
, languagenames
=None, message
=None):
57 self
.localize
= session
.localize
58 self
.tr_lang
= session
.tr_lang
59 self
.languagenames
= languagenames
60 pagetitle
= self
.localize("Login to Pootle")
61 templatename
= "login"
62 message
= forcemessage(message
)
63 instancetitle
= getattr(session
.instance
, "title", session
.localize("Pootle Demo"))
64 sessionvars
= {"status": session
.status
, "isopen": session
.isopen
, "issiteadmin": session
.issiteadmin()}
65 templatevars
= {"pagetitle": pagetitle
, "introtext": message
,
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'),
72 "session": sessionvars
, "instancetitle": instancetitle
}
73 pagelayout
.PootlePage
.__init
__(self
, templatename
, templatevars
, session
)
75 def getlanguageoptions(self
, session
):
76 """returns the language selector..."""
77 tr_default
= session
.localize("Default")
78 if tr_default
!= "Default":
79 tr_default
= u
"%s | \u202dDefault" % tr_default
80 languageoptions
= [('', tr_default
)]
81 if isinstance(self
.languagenames
, dict):
82 languageoptions
+= self
.languagenames
.items()
84 languageoptions
+= self
.languagenames
85 if session
.language
in ["en", session
.server
.defaultlanguage
]:
86 preferredlanguage
= ""
88 preferredlanguage
= session
.language
90 for key
, value
in languageoptions
:
91 if key
== 'templates':
93 tr_name
= session
.tr_lang(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"]))
107 class RegisterPage(pagelayout
.PootlePage
):
108 """page for new registrations"""
109 def __init__(self
, session
, argdict
, message
=None):
110 self
.localize
= session
.localize
112 introtext
= self
.localize("Please enter your registration details")
114 introtext
= forcemessage(message
)
115 pagetitle
= self
.localize("Pootle Registration")
116 self
.argdict
= argdict
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"),
125 "email_tooltip": self
.localize("You must supply a valid email address"),
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", ""),
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", ""),
136 "register_text": self
.localize('Register Account'),
137 "session": sessionvars
, "instancetitle": instancetitle
}
138 pagelayout
.PootlePage
.__init
__(self
, templatename
, templatevars
, session
)
140 class ActivatePage(pagelayout
.PootlePage
):
141 """page for new registrations"""
142 def __init__(self
, session
, argdict
, title
=None, message
=None):
143 self
.localize
= session
.localize
145 introtext
= self
.localize("Please enter your activation details")
147 introtext
= forcemessage(message
)
148 self
.argdict
= argdict
150 pagetitle
= self
.localize("Pootle Account Activation")
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'),
164 "session": sessionvars
, "instancetitle": instancetitle
}
165 pagelayout
.PootlePage
.__init
__(self
, templatename
, templatevars
, session
)
167 class UserOptions(pagelayout
.PootlePage
):
168 """page for user to change their options"""
169 def __init__(self
, potree
, session
, message
=None):
171 self
.session
= session
172 self
.localize
= session
.localize
173 self
.tr_lang
= session
.tr_lang
174 message
= forcemessage(message
)
175 pagetitle
= self
.localize("Options for: %s", session
.username
)
176 templatename
= "options"
177 instancetitle
= getattr(session
.instance
, "title", session
.localize("Pootle Demo"))
178 enablealtsrc
= getattr(session
.instance
, "enablealtsrc", False)
179 sessionvars
= {"status": session
.status
, "isopen": session
.isopen
, "issiteadmin": session
.issiteadmin()}
180 templatevars
= {"pagetitle": pagetitle
, "introtext": message
,
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
,
188 "password_title": self
.localize("Password"),
189 "passwordconfirm_title": self
.localize("Confirm password"),
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"),
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()
204 otheroptions
= self
.getotheroptions()
205 templatevars
.update(otheroptions
)
206 pagelayout
.PootlePage
.__init
__(self
, templatename
, templatevars
, session
)
208 def getprojectoptions(self
):
209 """gets the options box to change the user's projects"""
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
217 def getlanguageoptions(self
):
218 """returns options for languages"""
219 userlanguages
= self
.session
.getlanguages()
220 languageoptions
= self
.potree
.getlanguages()
222 for language
, name
in languageoptions
:
223 languages
.append({"code": language
, "name": self
.tr_lang(name
), "selected": language
in userlanguages
or None})
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"]))
229 def getaltsrcoptions(self
):
230 """returns options for alternative source languages"""
231 useraltsrc
= self
.session
.getaltsrclanguage()
232 languageoptions
= self
.potree
.getlanguages()
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
243 def getotheroptions(self
):
244 uilanguage
= getattr(self
.session
.prefs
, "uilanguage", "")
246 userlanguages
= self
.session
.getlanguages()
248 uilanguage
= userlanguages
[0]
249 languageoptions
= [{"code": '', "name": ''}]
250 for code
, name
in self
.potree
.getlanguages():
251 if code
== "templates":
253 languageoptions
.append({"code": code
, "name": self
.tr_lang(name
), "selected": uilanguage
== code
or None})
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"]))
257 options
= {"inputheight": self
.localize("Input Height (in lines)"),
258 "viewrows": self
.localize("Number of rows in view mode"),
259 "translaterows": self
.localize("Number of rows in translate mode")}
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
}
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"""
272 argdict
= self
.processargs(argdict
)
273 session
= self
.getsession(req
, argdict
)
275 session
.pagecount
+= 1
276 session
.remote_ip
= self
.getremoteip(req
)
278 self
.initlanguage(req
, session
)
279 page
= self
.getpage(pathwords
, session
, argdict
)
281 # Because of the exception, 'session' might not be initialised. So let's
284 raise Exception("Could not initialise session.\nDetail:%s" % str(e
))
286 exceptionstr
= self
.errorhandler
.exception_str()
287 errormessage
= str(e
).decode("utf-8")
288 traceback
= self
.errorhandler
.traceback_str().decode('utf-8')
289 browsertraceback
= ""
290 options
= getattr(self
, "options", None)
291 # with unit tests we might not have self.options, therefore this test
293 if options
.browsererrors
== 'traceback':
294 browsertraceback
= traceback
295 if options
.logerrors
== 'traceback':
296 self
.errorhandler
.logerror(traceback
)
297 elif options
.logerrors
== 'exception':
298 self
.errorhandler
.logerror(exceptionstr
)
299 elif options
.logerrors
== 'message':
300 self
.errorhandler
.logerror(errormessage
)
302 self
.errorhandler
.logerror(traceback
)
304 refreshurl
= req
.headers_in
.getheader('Referer') or "/"
305 templatename
= "error"
307 "pagetitle": session
.localize("Error"),
309 "refreshurl": refreshurl
,
310 "message": errormessage
,
311 "traceback": browsertraceback
,
312 "back": session
.localize("Back"),
314 pagelayout
.completetemplatevars(templatevars
, session
)
315 page
= server
.Redirect(refreshurl
, withtemplate
=(templatename
, templatevars
))
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
322 session
.setlanguage("en")
324 def hasuser(self
, users
, username
):
325 """returns whether the user exists in users"""
326 return users
.__hasattr
__(username
)
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
)
334 usernode
= users
.__getattr
__(username
)
337 def adduser(self
, users
, username
, fullname
, email
, password
):
338 """adds the user with the given details"""
339 usernode
= self
.getusernode(users
, username
)
340 usernode
.name
= fullname
341 usernode
.email
= email
342 usernode
.passwdhash
= web
.session
.md5hexdigest(password
)
344 def makeactivationcode(self
, users
, username
):
345 """makes a new activation code for the user and returns it"""
346 usernode
= self
.getusernode(users
, username
)
347 usernode
.activated
= 0
348 activationcode
= self
.generateactivationcode()
349 usernode
.activationcode
= activationcode
350 return activationcode
352 def activate(self
, users
, username
):
353 """sets the user as activated"""
354 self
.getusernode(users
, username
).activated
= 1
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)
364 if self
.hasuser(users
, usercode
):
365 raise NotImplementedError("Can't remove users")
366 elif key
.startswith("username-"):
367 username
= key
.replace("username-", "", 1)
368 if self
.hasuser(users
, username
):
369 usernode
= self
.getusernode(users
, username
)
370 fullname
= getattr(usernode
, "name", None)
371 if fullname
!= value
:
372 usernode
.name
= value
373 elif key
.startswith("useremail-"):
374 username
= key
.replace("useremail-", "", 1)
375 if self
.hasuser(users
, username
):
376 usernode
= self
.getusernode(users
, username
)
377 useremail
= getattr(usernode
, "email", None)
378 if useremail
!= value
:
379 usernode
.email
= value
380 elif key
.startswith("userpassword-"):
381 username
= key
.replace("userpassword-", "", 1)
382 if self
.hasuser(users
, username
):
383 usernode
= self
.getusernode(users
, username
)
384 if value
and value
.strip():
385 usernode
.passwdhash
= web
.session
.md5hexdigest(value
.strip())
386 elif key
.startswith("useractivated-"):
387 username
= key
.replace("useractivated-", "", 1)
388 self
.activate(users
, username
)
389 elif key
== "newusername":
390 username
= value
.lower()
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
)
395 if username
in ["nobody", "default"]:
396 raise ValueError('"%s" is a reserved username.' % username
)
397 if self
.hasuser(users
, username
):
398 raise ValueError("Already have user with the login: %s" % username
)
399 userpassword
= argdict
.get("newuserpassword", None)
400 if userpassword
is None or userpassword
== session
.localize("(add password here)"):
401 raise ValueError("You must specify a password")
402 userfullname
= argdict
.get("newuserfullname", None)
403 if userfullname
== session
.localize("(add full name here)"):
404 raise ValueError("Please set the users full name or leave it blank")
405 useremail
= argdict
.get("newuseremail", None)
406 if useremail
== session
.localize("(add email here)"):
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
)
411 self
.activate(users
, username
)
413 activationcode
= self
.makeactivationcode(users
, username
)
414 print "user activation code for %s is %s" % (username
, activationcode
)
417 def handleregistration(self
, session
, argdict
):
418 """handles the actual registration"""
419 #TODO: Fix layout, punctuation, spacing and correlation of messages
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():
423 raise RegistrationError(session
.localize("Username must be alphanumeric, and must start with an alphabetic character."))
424 fullname
= argdict
.get("name", "")
425 email
= argdict
.get("email", "")
426 password
= argdict
.get("password", "")
427 passwordconfirm
= argdict
.get("passwordconfirm", "")
428 if " " in email
or not (email
and "@" in email
and "." in email
):
429 raise RegistrationError(session
.localize("You must supply a valid email address"))
430 userexists
= session
.loginchecker
.userexists(username
)
431 users
= session
.loginchecker
.users
433 usernode
= self
.getusernode(users
, username
)
434 # use the email address on file
435 email
= getattr(usernode
, "email", email
)
437 # TODO: we can't figure out the password as we only store the md5sum. have a password reset mechanism
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")
441 message
+= session
.localize("If you have a problem with registration, please contact %s.\n", supportaddress
)
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")
445 redirecturl
= "login.html?username=%s" % username
446 displaymessage
+= session
.localize("Proceeding to <a href='%s'>login</a>\n", redirecturl
)
448 validatepassword(session
, password
, passwordconfirm
)
449 self
.adduser(users
, username
, fullname
, email
, password
)
450 activationcode
= self
.makeactivationcode(users
, username
)
452 message
= session
.localize("A Pootle account has been created for you using this email address.\n")
453 if session
.instance
.baseurl
.startswith("http://"):
454 message
+= session
.localize("To activate your account, follow this link:\n")
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
460 message
+= session
.localize("Your activation code is:\n%s\n", activationcode
)
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")
464 redirecturl
= "activate.html?username=%s" % username
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
)
467 displaymessage
+= " " + session
.localize("(Or simply click on the activation link in the email)")
469 message
+= session
.localize("Your user name is: %s\n", username
)
471 message
+= session
.localize("Your password is: %s\n", password
)
472 message
+= session
.localize("Your registered email address is: %s\n", email
)
473 smtpserver
= self
.instance
.registration
.smtpserver
474 fromaddress
= self
.instance
.registration
.fromaddress
475 subject
= Header(session
.localize("Pootle Registration"),
477 messagedict
= {"from": fromaddress
, "to": [email
], "subject": subject
, "body": message
}
479 messagedict
["reply-to"] = supportaddress
480 fullmessage
= mailer
.makemessage(messagedict
)
481 if isinstance(fullmessage
, unicode):
482 fullmessage
= fullmessage
.encode("utf-8")
483 errmsg
= mailer
.dosendmessage(fromemail
=self
.instance
.registration
.fromaddress
, recipientemails
=[email
], message
=fullmessage
, smtpserver
=smtpserver
)
485 raise RegistrationError("Error sending mail: %s" % errmsg
)
486 return displaymessage
, redirecturl
488 def registerpage(self
, session
, argdict
):
489 """handle registration or return the Register page"""
490 if "username" in argdict
:
492 displaymessage
, redirecturl
= self
.handleregistration(session
, argdict
)
493 except RegistrationError
, message
:
494 return RegisterPage(session
, argdict
, message
)
495 redirectpage
= pagelayout
.PootlePage("Redirecting...", {}, session
)
496 redirectpage
.templatename
= "redirect"
497 redirectpage
.templatevars
= {
498 # BUG: We won't redirect to registration page, we will go to
499 # activation or login
500 "pagetitle": session
.localize("Redirecting to Registration Page..."),
502 "refreshurl": redirecturl
,
503 "message": displaymessage
,
505 redirectpage
.completevars()
508 return RegisterPage(session
, argdict
)
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"]
515 if self
.hasuser(session
.loginchecker
.users
, username
):
516 usernode
= self
.getusernode(session
.loginchecker
.users
, username
)
517 correctcode
= getattr(usernode
, "activationcode", "")
518 if correctcode
and correctcode
.strip().lower() == activationcode
.strip().lower():
519 setattr(usernode
, "activated", 1)
521 redirectpage
= pagelayout
.PootlePage("Redirecting to login...", {}, session
)
522 redirectpage
.templatename
= "redirect"
523 redirectpage
.templatevars
= {
524 "pagetitle": session
.localize("Redirecting to login Page..."),
526 "refreshurl": "login.html?username=%s" % username
,
527 "message": session
.localize("Your account has been activated! Redirecting to login..."),
529 redirectpage
.completevars()
531 failedmessage
= session
.localize("The activation information was not valid.")
532 return ActivatePage(session
, argdict
, title
=session
.localize("Activation Failed"), message
=failedmessage
)
534 return ActivatePage(session
, argdict
)
536 class PootleSession(web
.session
.LoginSession
):
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
)
544 """gets the users prefs into self.prefs"""
546 self
.prefs
= self
.loginchecker
.users
.__getattr
__(self
.username
)
547 if self
.language_set
:
548 self
.setlanguage(self
.language_set
)
550 uilanguage
= getattr(self
.prefs
, "uilanguage", None)
552 self
.setlanguage(uilanguage
)
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
563 """opens the session, along with the users prefs"""
564 super(PootleSession
, self
).open()
568 def close(self
, req
):
569 """opens the session, along with the users prefs"""
570 super(PootleSession
, self
).close(req
)
573 def setlanguage(self
, language
):
574 """sets the language for the session"""
575 self
.language_set
= language
or ""
577 self
.language
= language
578 elif not getattr(self
, "language", None):
580 self
.language
= getattr(self
.prefs
, "uilanguage", "") or self
.server
.defaultlanguage
582 self
.language
= self
.server
.defaultlanguage
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
)
587 self
.tr_lang
= langdata
.tr_lang(self
.language
)
589 locale
.setlocale(locale
.LC_ALL
, str(self
.language
))
591 # The system might not have the locale installed
593 self
.checkstatus(None, None)
595 self
.lang
= factory
.getlanguage(self
.language
)
598 """checks if this session is valid (which means the user must be activated)"""
599 if not super(PootleSession
, self
).validate():
601 if self
.loginchecker
.users
.__hasattr
__(self
.username
):
602 usernode
= self
.loginchecker
.users
.__getattr
__(self
.username
)
603 if getattr(usernode
, "activated", 0):
606 self
.status
= "username has not yet been activated"
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
))
621 def setpersonaloptions(self
, argdict
):
622 """sets the users personal details"""
623 name
= argdict
.get("option-name", "")
624 email
= argdict
.get("option-email", "")
625 password
= argdict
.get("option-password", "")
626 passwordconfirm
= argdict
.get("option-passwordconfirm", "")
628 if password
or passwordconfirm
:
629 validatepassword(self
, password
, passwordconfirm
)
630 setattr(self
.prefs
, "name", name
)
631 setattr(self
.prefs
, "email", email
)
633 passwdhash
= web
.session
.md5hexdigest(argdict
.get("option-password", ""))
634 setattr(self
.prefs
, "passwdhash", passwdhash
)
637 def setinterfaceoptions(self
, argdict
):
638 """sets the users interface details"""
639 value
= argdict
.get("option-uilanguage", "")
641 self
.prefs
.uilanguage
= value
642 self
.setlanguage(value
)
643 def setinterfacevalue(name
, errormessage
):
644 value
= argdict
.get("option-%s" % name
, "")
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"))
653 useraltsrclanguage
= argdict
.get("altsrclanguage", "")
654 if isinstance(useraltsrclanguage
, (str, unicode)):
655 setattr(self
.prefs
, "altsrclanguage", useraltsrclanguage
)
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()]
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()]
668 def getaltsrclanguage(self
):
669 """gets the user's alternative source language"""
670 useraltsrclanguage
= getattr(self
.prefs
, "altsrclanguage", "")
671 return useraltsrclanguage
.strip()
674 """gets the user's rights"""
675 return getattr(self
.prefs
, "rights", None)
677 def issiteadmin(self
):
678 """returns whether the user can administer the site"""
679 return getattr(self
.getrights(), "siteadmin", False)