[gen] Bugfix while managing languages, ui improvements.
|
@ -261,8 +261,8 @@ class ZopeInstaller:
|
||||||
# may still be in the way for migration purposes.
|
# may still be in the way for migration purposes.
|
||||||
users = ('admin',) # We suppose there is at least a user.
|
users = ('admin',) # We suppose there is at least a user.
|
||||||
if not users:
|
if not users:
|
||||||
appyTool.create('users', login='admin', firstName='admin',
|
appyTool.create('users', login='admin', password1='admin',
|
||||||
name='admin', password1='admin', password2='admin',
|
password2='admin',
|
||||||
email='admin@appyframework.org', roles=['Manager'])
|
email='admin@appyframework.org', roles=['Manager'])
|
||||||
appyTool.log('Admin user "admin" created.')
|
appyTool.log('Admin user "admin" created.')
|
||||||
|
|
||||||
|
|
|
@ -121,6 +121,13 @@ class ToolMixin(BaseMixin):
|
||||||
p_code.'''
|
p_code.'''
|
||||||
return languages.get(code)[2]
|
return languages.get(code)[2]
|
||||||
|
|
||||||
|
def changeLanguage(self):
|
||||||
|
'''Sets the language cookie with the new desired language code that is
|
||||||
|
in request["language"].'''
|
||||||
|
rq = self.REQUEST
|
||||||
|
rq.RESPONSE.setCookie('_ZopeLg', rq['language'], path='/')
|
||||||
|
return self.goto(rq['HTTP_REFERER'])
|
||||||
|
|
||||||
def getGlobalCssJs(self):
|
def getGlobalCssJs(self):
|
||||||
'''Returns the list of CSS and JS files to include in the main template.
|
'''Returns the list of CSS and JS files to include in the main template.
|
||||||
The method ensures that appy.css and appy.js come first.'''
|
The method ensures that appy.css and appy.js come first.'''
|
||||||
|
@ -231,6 +238,12 @@ class ToolMixin(BaseMixin):
|
||||||
res = appyObj.showPortlet()
|
res = appyObj.showPortlet()
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
res = True
|
res = True
|
||||||
|
else:
|
||||||
|
appyObj = self.appy()
|
||||||
|
try:
|
||||||
|
res = appyObj.showPortletAt(context)
|
||||||
|
except AttributeError:
|
||||||
|
res = True
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def getObject(self, uid, appy=False, brain=False):
|
def getObject(self, uid, appy=False, brain=False):
|
||||||
|
@ -979,7 +992,7 @@ class ToolMixin(BaseMixin):
|
||||||
elem is the one-line user info as shown on every page; second line is
|
elem is the one-line user info as shown on every page; second line is
|
||||||
the URL to edit user info.'''
|
the URL to edit user info.'''
|
||||||
appyUser = self.appy().appyUser
|
appyUser = self.appy().appyUser
|
||||||
res = [appyUser.title, appyUser.login]
|
res = [appyUser.title]
|
||||||
rolesToShow = [r for r in appyUser.roles \
|
rolesToShow = [r for r in appyUser.roles \
|
||||||
if r not in ('Authenticated', 'Member')]
|
if r not in ('Authenticated', 'Member')]
|
||||||
if rolesToShow:
|
if rolesToShow:
|
||||||
|
|
|
@ -1345,10 +1345,16 @@ class BaseMixin:
|
||||||
def getUserLanguage(self):
|
def getUserLanguage(self):
|
||||||
'''Gets the language (code) of the current user.'''
|
'''Gets the language (code) of the current user.'''
|
||||||
if not hasattr(self, 'REQUEST'): return 'en'
|
if not hasattr(self, 'REQUEST'): return 'en'
|
||||||
# Try first the "LANGUAGE" key from the request
|
# Try the value which comes from the cookie. Indeed, if such a cookie is
|
||||||
|
# present, it means that the user has explicitly chosen this language
|
||||||
|
# via the language selector.
|
||||||
|
rq = self.REQUEST
|
||||||
|
if '_ZopeLg' in rq.cookies: return rq.cookies['_ZopeLg']
|
||||||
|
# Try the LANGUAGE key from the request: it corresponds to the language
|
||||||
|
# as configured in the user's browser.
|
||||||
res = self.REQUEST.get('LANGUAGE', None)
|
res = self.REQUEST.get('LANGUAGE', None)
|
||||||
if res: return res
|
if res: return res
|
||||||
# Try then the HTTP_ACCEPT_LANGUAGE key from the request, which stores
|
# Try the HTTP_ACCEPT_LANGUAGE key from the request, which stores
|
||||||
# language preferences as defined in the user's browser. Several
|
# language preferences as defined in the user's browser. Several
|
||||||
# languages can be listed, from most to less wanted.
|
# languages can be listed, from most to less wanted.
|
||||||
res = self.REQUEST.get('HTTP_ACCEPT_LANGUAGE', None)
|
res = self.REQUEST.get('HTTP_ACCEPT_LANGUAGE', None)
|
||||||
|
|
|
@ -93,7 +93,7 @@ class ModelClass:
|
||||||
elif callable(value):
|
elif callable(value):
|
||||||
className = wrapperName
|
className = wrapperName
|
||||||
if (appyType.type == 'Ref') and appyType.isBack:
|
if (appyType.type == 'Ref') and appyType.isBack:
|
||||||
className = appyType.back.klass.__name__
|
className = value.im_class.__name__
|
||||||
value = '%s.%s' % (className, value.__name__)
|
value = '%s.%s' % (className, value.__name__)
|
||||||
typeArgs += '%s=%s,' % (name, value)
|
typeArgs += '%s=%s,' % (name, value)
|
||||||
return '%s(%s)' % (appyType.__class__.__name__, typeArgs)
|
return '%s(%s)' % (appyType.__class__.__name__, typeArgs)
|
||||||
|
@ -143,10 +143,13 @@ class User(ModelClass):
|
||||||
'password2', 'email', 'roles']
|
'password2', 'email', 'roles']
|
||||||
# All methods defined below are fake. Real versions are in the wrapper.
|
# All methods defined below are fake. Real versions are in the wrapper.
|
||||||
title = gen.String(show=False, indexed=True)
|
title = gen.String(show=False, indexed=True)
|
||||||
gm = {'group': 'main', 'multiplicity': (1,1), 'width': 25}
|
gm = {'group': 'main', 'width': 25}
|
||||||
def showName(self): pass
|
def showName(self): pass
|
||||||
name = gen.String(show=showName, **gm)
|
name = gen.String(show=showName, **gm)
|
||||||
firstName = gen.String(show=showName, **gm)
|
firstName = gen.String(show=showName, **gm)
|
||||||
|
def showEmail(self): pass
|
||||||
|
email = gen.String(show=showEmail)
|
||||||
|
gm['multiplicity'] = (1,1)
|
||||||
def showLogin(self): pass
|
def showLogin(self): pass
|
||||||
def validateLogin(self): pass
|
def validateLogin(self): pass
|
||||||
login = gen.String(show=showLogin, validator=validateLogin,
|
login = gen.String(show=showLogin, validator=validateLogin,
|
||||||
|
@ -156,8 +159,6 @@ class User(ModelClass):
|
||||||
password1 = gen.String(format=gen.String.PASSWORD, show=showPassword,
|
password1 = gen.String(format=gen.String.PASSWORD, show=showPassword,
|
||||||
validator=validatePassword, **gm)
|
validator=validatePassword, **gm)
|
||||||
password2 = gen.String(format=gen.String.PASSWORD, show=showPassword, **gm)
|
password2 = gen.String(format=gen.String.PASSWORD, show=showPassword, **gm)
|
||||||
def showEmail(self): pass
|
|
||||||
email = gen.String(show=showEmail, group='main', width=25)
|
|
||||||
gm['multiplicity'] = (0, None)
|
gm['multiplicity'] = (0, None)
|
||||||
def showRoles(self): pass
|
def showRoles(self): pass
|
||||||
roles = gen.String(show=showRoles, indexed=True,
|
roles = gen.String(show=showRoles, indexed=True,
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
body { font: 75% Helvetica,Arial,sans-serif; background-color: #EAEAEA;
|
body { font: 75% Helvetica,Arial,sans-serif; background-color: #EAEAEA;
|
||||||
margin-top: 18px}
|
margin-top: 18px}
|
||||||
pre { font: 100% Helvetica,Arial,sans-serif; margin: 0}
|
pre { font: 100% Helvetica,Arial,sans-serif; margin: 0}
|
||||||
h1 { font-size: 14pt; margin:0;}
|
h1 { font-size: 14pt; margin-bottom:4px;}
|
||||||
h2 { font-size: 13pt; margin:0; font-style: italic; font-weight: normal;
|
h2 { font-size: 13pt; margin-bottom:4px; font-style: italic;
|
||||||
background-color: #d7dee4}
|
font-weight: normal; background-color: #d7dee4}
|
||||||
h3 { font-size: 12pt; margin:0; font-weight: bold;}
|
h3 { font-size: 12pt; margin-bottom:4px; font-weight: bold;}
|
||||||
h4 { font-size: 11pt; margin:0;}
|
h4 { font-size: 11pt; margin-bottom:4px;}
|
||||||
h5 { font-size: 10pt; margin:0; font-style: italic; font-weight: normal;
|
h5 { font-size: 10pt; margin:0; font-style: italic; font-weight: normal;
|
||||||
background-color: #d7dee4}
|
background-color: #d7dee4}
|
||||||
h6 { font-size: 9pt; margin:0; font-weight: bold;}
|
h6 { font-size: 9pt; margin:0; font-weight: bold;}
|
||||||
a { text-decoration: none; color: #503737;}
|
a { text-decoration: none; color: #436976;}
|
||||||
a:visited { color: #503737;}
|
a:visited { color: #436976;}
|
||||||
table { font-size: 100%; border-spacing: 0px; border-collapse:collapse;}
|
table { font-size: 100%; border-spacing: 0px; border-collapse:collapse;}
|
||||||
form { margin: 0; padding: 0;}
|
form { margin: 0; padding: 0;}
|
||||||
p { margin: 0;}
|
p { margin: 0;}
|
||||||
|
@ -40,7 +40,7 @@ ul { line-height: 1.2em; margin: 0 0 0.2em 0.6em; padding: 0;
|
||||||
list-style: none outside none;}
|
list-style: none outside none;}
|
||||||
ul li { margin: 0; background-image: url("ui/li.gif"); padding-left: 10px;
|
ul li { margin: 0; background-image: url("ui/li.gif"); padding-left: 10px;
|
||||||
background-repeat: no-repeat; background-position: 0 4px;}
|
background-repeat: no-repeat; background-position: 0 4px;}
|
||||||
img {border: 0}
|
img { border: 0; vertical-align: middle}
|
||||||
|
|
||||||
/* Styles that apply when viewing content of XHTML fields, that mimic styles
|
/* Styles that apply when viewing content of XHTML fields, that mimic styles
|
||||||
that ckeditor uses for displaying XHTML content in the edit view. */
|
that ckeditor uses for displaying XHTML content in the edit view. */
|
||||||
|
@ -51,9 +51,10 @@ img {border: 0}
|
||||||
.main { width: 900px; background-color: white; box-shadow: 3px 3px 3px #A9A9A9;
|
.main { width: 900px; background-color: white; box-shadow: 3px 3px 3px #A9A9A9;
|
||||||
border-style: solid; border-width: 1px; border-color: grey}
|
border-style: solid; border-width: 1px; border-color: grey}
|
||||||
.top { height: 75px; margin-left: 3em; vertical-align: top;}
|
.top { height: 75px; margin-left: 3em; vertical-align: top;}
|
||||||
.lang { margin-right: 3px; }
|
.lang { margin-right: 6px; }
|
||||||
.userStrip { background-color: #d7dee4; height: 35px;
|
.userStrip { background-color: #6282B3; height: 35px;
|
||||||
border-top: 1px solid #5F7983; border-bottom: 1px solid #5F7983; }
|
border-top: 3px solid #034984; border-bottom: 2px solid #034984; }
|
||||||
|
.userStripText { font-size: 110%; padding: 0 0.3em 0 0.3em; color: white }
|
||||||
.login { margin-top: 2px; margin-bottom: 2px; color: black;}
|
.login { margin-top: 2px; margin-bottom: 2px; color: black;}
|
||||||
.buttons { margin-left: 4px;}
|
.buttons { margin-left: 4px;}
|
||||||
.fakeButton { border: 1px solid #D7DEE4; background-color: #fde8e0;
|
.fakeButton { border: 1px solid #D7DEE4; background-color: #fde8e0;
|
||||||
|
@ -117,3 +118,6 @@ img {border: 0}
|
||||||
.topSpace { margin-top: 15px;}
|
.topSpace { margin-top: 15px;}
|
||||||
.discreet { color: grey}
|
.discreet { color: grey}
|
||||||
.pageLink { padding-left: 6px; font-style: italic}
|
.pageLink { padding-left: 6px; font-style: italic}
|
||||||
|
.footer { font-size: 95% }
|
||||||
|
.footer td { background-color: #CBCBC9; border-top: 1px solid grey;
|
||||||
|
padding: 0.4em 1em 0.5em }
|
||||||
|
|
Before Width: | Height: | Size: 239 B After Width: | Height: | Size: 239 B |
BIN
gen/ui/edit.gif
Before Width: | Height: | Size: 475 B After Width: | Height: | Size: 476 B |
4
gen/ui/footer.pt
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<table metal:define-macro="footer"
|
||||||
|
cellpadding="0" cellspacing="0" width="100%" class="footer">
|
||||||
|
<tr><td align="right">Made with <a href="http://appyframework.org" target="_blank">Appy</a></td></tr>
|
||||||
|
</table>
|
|
@ -289,7 +289,7 @@
|
||||||
</tal:edit>
|
</tal:edit>
|
||||||
|
|
||||||
<tal:refresh condition="contextObj/isDebug">
|
<tal:refresh condition="contextObj/isDebug">
|
||||||
<img title="Refresh" style="cursor:pointer"
|
<img title="Refresh" style="cursor:pointer; vertical-align:top"
|
||||||
tal:attributes="onClick python: 'href: window.location=\'%s\'' % contextObj.getUrl(mode=layoutType, page=page, refresh='yes');
|
tal:attributes="onClick python: 'href: window.location=\'%s\'' % contextObj.getUrl(mode=layoutType, page=page, refresh='yes');
|
||||||
src string: $appUrl/ui/refresh.png"/>
|
src string: $appUrl/ui/refresh.png"/>
|
||||||
</tal:refresh>
|
</tal:refresh>
|
||||||
|
|
BIN
gen/ui/plus.png
Before Width: | Height: | Size: 246 B After Width: | Height: | Size: 251 B |
Before Width: | Height: | Size: 189 B After Width: | Height: | Size: 191 B |
|
@ -39,12 +39,12 @@
|
||||||
<td align="right" tal:condition="tool/showLanguageSelector">
|
<td align="right" tal:condition="tool/showLanguageSelector">
|
||||||
<tal:lgs define="languages tool/getLanguages;
|
<tal:lgs define="languages tool/getLanguages;
|
||||||
defaultLanguage python: languages[0];
|
defaultLanguage python: languages[0];
|
||||||
asLinks python: len(languages) <= 5">
|
asLinks python: len(languages) <= 8">
|
||||||
<table tal:condition="asLinks">
|
<table tal:condition="asLinks">
|
||||||
<tr>
|
<tr>
|
||||||
<td tal:repeat="lang languages">
|
<td tal:repeat="lang languages">
|
||||||
<a class="lang"
|
<a class="lang"
|
||||||
tal:attributes="href python: req.get('ACTUAL_URL')+'/switchLanguage?set_language=%s' % lang;
|
tal:attributes="href string: $appUrl/config/changeLanguage?language=$lang;
|
||||||
title python: tool.getLanguageName(lang)"
|
title python: tool.getLanguageName(lang)"
|
||||||
tal:content="python: lang"></a>
|
tal:content="python: lang"></a>
|
||||||
</td>
|
</td>
|
||||||
|
@ -94,7 +94,7 @@
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tal:comment replace="nothing">The user data strip</tal:comment>
|
<tal:comment replace="nothing">The user strip</tal:comment>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<table class="userStrip" width="100%">
|
<table class="userStrip" width="100%">
|
||||||
|
@ -103,7 +103,7 @@
|
||||||
<tal:comment replace="nothing">The user login form for anonymous users</tal:comment>
|
<tal:comment replace="nothing">The user login form for anonymous users</tal:comment>
|
||||||
<table align="center" tal:condition="python: isAnon and ('/temp_folder/' not in req['ACTUAL_URL'])"
|
<table align="center" tal:condition="python: isAnon and ('/temp_folder/' not in req['ACTUAL_URL'])"
|
||||||
class="login">
|
class="login">
|
||||||
<tr><td>
|
<tr><td class="userStripText">
|
||||||
<form name="loginform" method="post"
|
<form name="loginform" method="post"
|
||||||
tal:attributes="action python: tool.absolute_url() + '/performLogin'">
|
tal:attributes="action python: tool.absolute_url() + '/performLogin'">
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@
|
||||||
<img tal:attributes="src string: $appUrl/ui/logout.gif"/>
|
<img tal:attributes="src string: $appUrl/ui/logout.gif"/>
|
||||||
</a>
|
</a>
|
||||||
</td>
|
</td>
|
||||||
<td align="right" tal:define="userInfo tool/getUserLine">
|
<td align="right" class="userStripText" tal:define="userInfo tool/getUserLine">
|
||||||
<span tal:content="python: userInfo[0]"></span>
|
<span tal:content="python: userInfo[0]"></span>
|
||||||
<a tal:attributes="href python: userInfo[1]">
|
<a tal:attributes="href python: userInfo[1]">
|
||||||
<img tal:attributes="src string: $appUrl/ui/edit.gif"/>
|
<img tal:attributes="src string: $appUrl/ui/edit.gif"/>
|
||||||
|
@ -168,6 +168,9 @@
|
||||||
</table>
|
</table>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr><tal:comment replace="nothing">Footer</tal:comment>
|
||||||
|
<td><metal:call use-macro="app/ui/footer/macros/footer"/></td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -156,17 +156,16 @@
|
||||||
</tr></table>
|
</tr></table>
|
||||||
</tal:atMostOneReference>
|
</tal:atMostOneReference>
|
||||||
|
|
||||||
<tal:comment replace="nothing">Display a fieldset in all other cases.</tal:comment>
|
<tal:comment replace="nothing">Display a table in all other cases.</tal:comment>
|
||||||
<tal:anyNumberOfReferences condition="not: atMostOneRef">
|
<tal:anyNumberOfReferences condition="not: atMostOneRef">
|
||||||
<fieldset tal:attributes="class python:test(innerRef, 'innerAppyFieldset', '')">
|
<div tal:condition="python: not innerRef or showPlusIcon">
|
||||||
<legend tal:condition="python: not innerRef or showPlusIcon">
|
|
||||||
(<span tal:replace="totalNumber"/>)
|
(<span tal:replace="totalNumber"/>)
|
||||||
<metal:plusIcon use-macro="app/ui/widgets/ref/macros/plusIcon"/>
|
<metal:plusIcon use-macro="app/ui/widgets/ref/macros/plusIcon"/>
|
||||||
<tal:comment replace="nothing">The search icon if field is queryable</tal:comment>
|
<tal:comment replace="nothing">The search icon if field is queryable</tal:comment>
|
||||||
<a tal:condition="python: objs and appyType['queryable']"
|
<a tal:condition="python: objs and appyType['queryable']"
|
||||||
tal:attributes="href python: '%s/ui/search?className=%s&ref=%s:%s' % (tool.absolute_url(), linkedPortalType, contextObj.UID(), appyType['name'])">
|
tal:attributes="href python: '%s/ui/search?className=%s&ref=%s:%s' % (tool.absolute_url(), linkedPortalType, contextObj.UID(), appyType['name'])">
|
||||||
<img src="search.gif" tal:attributes="title python: _('search_objects')"/></a>
|
<img src="search.gif" tal:attributes="title python: _('search_objects')"/></a>
|
||||||
</legend>
|
</div>
|
||||||
|
|
||||||
<tal:comment replace="nothing">Appy (top) navigation</tal:comment>
|
<tal:comment replace="nothing">Appy (top) navigation</tal:comment>
|
||||||
<metal:nav use-macro="here/ui/navigate/macros/appyNavigate"/>
|
<metal:nav use-macro="here/ui/navigate/macros/appyNavigate"/>
|
||||||
|
@ -223,9 +222,6 @@
|
||||||
|
|
||||||
<tal:comment replace="nothing">Appy (bottom) navigation</tal:comment>
|
<tal:comment replace="nothing">Appy (bottom) navigation</tal:comment>
|
||||||
<metal:nav use-macro="context/ui/navigate/macros/appyNavigate"/>
|
<metal:nav use-macro="context/ui/navigate/macros/appyNavigate"/>
|
||||||
|
|
||||||
</fieldset>
|
|
||||||
<tal:comment replace="nothing">A carriage return needed in some cases.</tal:comment>
|
|
||||||
</tal:anyNumberOfReferences>
|
</tal:anyNumberOfReferences>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,27 @@ class UserWrapper(AbstractWrapper):
|
||||||
# wants to edit information about himself.
|
# wants to edit information about himself.
|
||||||
if self.user.has_role('Owner', self): return 'edit'
|
if self.user.has_role('Owner', self): return 'edit'
|
||||||
|
|
||||||
|
def setPassword(self, newPassword=None):
|
||||||
|
'''Sets a p_newPassword for self. If p_newPassword is not given, we
|
||||||
|
generate one. This method returns the generated password (or simply
|
||||||
|
p_newPassword if no generation occurred).'''
|
||||||
|
if newPassword:
|
||||||
|
msgPart = 'changed'
|
||||||
|
else:
|
||||||
|
newPassword = self.getField('password1').generatePassword()
|
||||||
|
msgPart = 'generated'
|
||||||
|
login = self.login
|
||||||
|
zopeUser = self.o.acl_users.getUserById(login)
|
||||||
|
tool = self.tool.o
|
||||||
|
zopeUser.__ = tool._encryptPassword(newPassword)
|
||||||
|
if self.user.getId() == login:
|
||||||
|
# The user for which we change the password is the currently logged
|
||||||
|
# user. So update the authentication cookie, too.
|
||||||
|
tool._updateCookie(login, newPassword)
|
||||||
|
self.log('Password %s by "%s" for "%s".' % \
|
||||||
|
(msgPart, self.user.getId(), login))
|
||||||
|
return newPassword
|
||||||
|
|
||||||
def getGrantableRoles(self):
|
def getGrantableRoles(self):
|
||||||
'''Returns the list of roles that the admin can grant to a user.'''
|
'''Returns the list of roles that the admin can grant to a user.'''
|
||||||
res = []
|
res = []
|
||||||
|
@ -70,7 +91,7 @@ class UserWrapper(AbstractWrapper):
|
||||||
return self._callCustom('validate', new, errors)
|
return self._callCustom('validate', new, errors)
|
||||||
|
|
||||||
def onEdit(self, created):
|
def onEdit(self, created):
|
||||||
self.title = self.firstName + ' ' + self.name
|
self.title = self.login
|
||||||
aclUsers = self.o.acl_users
|
aclUsers = self.o.acl_users
|
||||||
login = self.login
|
login = self.login
|
||||||
if created:
|
if created:
|
||||||
|
@ -89,11 +110,7 @@ class UserWrapper(AbstractWrapper):
|
||||||
zopeUser.roles = self.roles
|
zopeUser.roles = self.roles
|
||||||
# Update the password if the user has entered new ones.
|
# Update the password if the user has entered new ones.
|
||||||
rq = self.request
|
rq = self.request
|
||||||
if rq.has_key('password1'):
|
if rq.has_key('password1'): self.setPassword(rq['password1'])
|
||||||
tool = self.tool.o
|
|
||||||
zopeUser.__ = tool._encryptPassword(rq['password1'])
|
|
||||||
# Update the cookie value
|
|
||||||
tool._updateCookie(login, rq['password1'])
|
|
||||||
self.password1 = self.password2 = ''
|
self.password1 = self.password2 = ''
|
||||||
# "self" must be owned by its Zope user.
|
# "self" must be owned by its Zope user.
|
||||||
if 'Owner' not in self.o.get_local_roles_for_userid(login):
|
if 'Owner' not in self.o.get_local_roles_for_userid(login):
|
||||||
|
|