settings: fix #3944 add password reset permission

This commit is contained in:
lisaq 2016-10-25 17:37:14 +02:00
parent e10c482cd2
commit 607fd8931d
12 changed files with 129 additions and 36 deletions

View file

@ -51,7 +51,7 @@ PYRAMID_SETTINGS = {}
EXTENSIONS = {}
__version__ = ('.'.join((str(each) for each in VERSION[:3])))
__dbversion__ = 60 # defines current db version for migrations
__dbversion__ = 61 # defines current db version for migrations
__platform__ = platform.system()
__license__ = 'AGPLv3, and Commercial License'
__author__ = 'RhodeCode GmbH'

View file

@ -81,6 +81,7 @@ def get_user(request, apiuser, userid=Optional(OAttr('apiuser'))):
"usergroup.read",
"hg.repogroup.create.false",
"hg.create.none",
"hg.password_reset.enabled",
"hg.extern_activate.manual",
"hg.create.write_on_repogroup.false",
"hg.usergroup.create.false",

View file

@ -92,6 +92,7 @@ class PermissionsController(BaseController):
self.__load_data()
_form = ApplicationPermissionsForm(
[x[0] for x in c.register_choices],
[x[0] for x in c.password_reset_choices],
[x[0] for x in c.extern_activate_choices])()
try:

View file

@ -0,0 +1,42 @@
import logging
import datetime
from sqlalchemy import *
from sqlalchemy.exc import DatabaseError
from sqlalchemy.orm import relation, backref, class_mapper, joinedload
from sqlalchemy.orm.session import Session
from sqlalchemy.ext.declarative import declarative_base
from rhodecode.lib.dbmigrate.migrate import *
from rhodecode.lib.dbmigrate.migrate.changeset import *
from rhodecode.lib.utils2 import str2bool
from rhodecode.model.meta import Base
from rhodecode.model import meta
from rhodecode.lib.dbmigrate.versions import _reset_base, notify
log = logging.getLogger(__name__)
def upgrade(migrate_engine):
"""
Upgrade operations go here.
Don't create your own engine; bind migrate_engine to your metadata
"""
_reset_base(migrate_engine)
from rhodecode.lib.dbmigrate.schema import db_4_5_0_0
fixups(db_4_5_0_0, meta.Session)
def downgrade(migrate_engine):
meta = MetaData()
meta.bind = migrate_engine
def fixups(models, _SESSION):
# ** create default permissions ** #
from rhodecode.model.permission import PermissionModel
PermissionModel(_SESSION()).create_permissions()
res = PermissionModel(_SESSION()).create_default_user_permissions(
models.User.DEFAULT_USER)
_SESSION().commit()

View file

@ -2314,6 +2314,10 @@ class Permission(Base, BaseModel):
('hg.register.manual_activate', _('User Registration with manual account activation')),
('hg.register.auto_activate', _('User Registration with automatic account activation')),
('hg.password_reset.enabled', _('Password reset enabled')),
('hg.password_reset.hidden', _('Password reset hidden')),
('hg.password_reset.disabled', _('Password reset disabled')),
('hg.extern_activate.manual', _('Manual activation of external account')),
('hg.extern_activate.auto', _('Automatic activation of external account')),
@ -2332,6 +2336,7 @@ class Permission(Base, BaseModel):
'hg.create.write_on_repogroup.true',
'hg.fork.repository',
'hg.register.manual_activate',
'hg.password_reset.enabled',
'hg.extern_activate.auto',
'hg.inherit_default_perms.true',
]

View file

@ -427,7 +427,8 @@ def LabsSettingsForm():
return _LabSettingsForm
def ApplicationPermissionsForm(register_choices, extern_activate_choices):
def ApplicationPermissionsForm(
register_choices, password_reset_choices, extern_activate_choices):
class _DefaultPermissionsForm(formencode.Schema):
allow_extra_fields = True
filter_extra_fields = True
@ -435,6 +436,7 @@ def ApplicationPermissionsForm(register_choices, extern_activate_choices):
anonymous = v.StringBoolean(if_missing=False)
default_register = v.OneOf(register_choices)
default_register_message = v.UnicodeString()
default_password_reset = v.OneOf(password_reset_choices)
default_extern_activate = v.OneOf(extern_activate_choices)
return _DefaultPermissionsForm

View file

@ -51,8 +51,8 @@ class PermissionModel(BaseModel):
'default_user_group_create': None,
'default_fork_create': None,
'default_inherit_default_permissions': None,
'default_register': None,
'default_password_reset': None,
'default_extern_activate': None,
# object permissions below
@ -85,6 +85,11 @@ class PermissionModel(BaseModel):
('hg.register.manual_activate', translator('Allowed with manual account activation')),
('hg.register.auto_activate', translator('Allowed with automatic account activation')),]
c_obj.password_reset_choices = [
('hg.password_reset.enabled', translator('Allow password recovery')),
('hg.password_reset.hidden', translator('Hide password recovery link')),
('hg.password_reset.disabled', translator('Disable password recovery')),]
c_obj.extern_activate_choices = [
('hg.extern_activate.manual', translator('Manual activation of external account')),
('hg.extern_activate.auto', translator('Automatic activation of external account')),]
@ -149,6 +154,9 @@ class PermissionModel(BaseModel):
if perm.permission.permission_name.startswith('hg.register.'):
defaults['default_register' + suffix] = perm.permission.permission_name
if perm.permission.permission_name.startswith('hg.password_reset.'):
defaults['default_password_reset' + suffix] = perm.permission.permission_name
if perm.permission.permission_name.startswith('hg.extern_activate.'):
defaults['default_extern_activate' + suffix] = perm.permission.permission_name
@ -182,6 +190,7 @@ class PermissionModel(BaseModel):
# application perms
'default_register': 'hg.register.',
'default_password_reset': 'hg.password_reset.',
'default_extern_activate': 'hg.extern_activate.',
# object permissions below
@ -383,6 +392,7 @@ class PermissionModel(BaseModel):
'default_user_group_perm',
'default_register',
'default_password_reset',
'default_extern_activate'])
self.sa.commit()
except (DatabaseError,):
@ -404,6 +414,7 @@ class PermissionModel(BaseModel):
'default_user_group_perm',
'default_register',
'default_password_reset',
'default_extern_activate'])
self.sa.commit()
except (DatabaseError,):
@ -429,6 +440,7 @@ class PermissionModel(BaseModel):
'default_inherit_default_permissions',
'default_register',
'default_password_reset',
'default_extern_activate'])
# overwrite default repo permissions

View file

@ -188,6 +188,10 @@
line-height: 1.5em;
}
}
p.help-block {
margin-left: 0;
}
}
.user-menu.submenu {

View file

@ -28,6 +28,15 @@
</div>
</div>
<div class="field">
<div class="label label-select">
<label for="default_password_reset">${_('Password Reset')}:</label>
</div>
<div class="select">
${h.select('default_password_reset','',c.password_reset_choices)}
</div>
</div>
<div class="field">
<div class="label label-textarea">
<label for="default_register_message">${_('Registration Page Message')}:</label>
@ -66,6 +75,7 @@
};
$("#default_register").select2(select2Options);
$("#default_password_reset").select2(select2Options);
$("#default_extern_activate").select2(select2Options);
});
</script>

View file

@ -308,7 +308,9 @@
<div class="field">
<div class="label">
<label for="password">${_('Password')}:</label>
<span class="forgot_password">${h.link_to(_('(Forgot password?)'),h.route_path('reset_password'))}</span>
%if h.HasPermissionAny('hg.password_reset.enabled')():
<span class="forgot_password">${h.link_to(_('(Forgot password?)'),h.route_path('reset_password'))}</span>
%endif
</div>
<div class="input">
${h.password('password',class_='focus',tabindex=2)}

View file

@ -56,9 +56,17 @@
${h.checkbox('remember', value=True, checked=defaults.get('remember'))}
<label class="checkbox" for="remember">${_('Remember me')}</label>
<p class="links">
${h.link_to(_('Forgot your password?'), h.route_path('reset_password'))}
</p>
%if h.HasPermissionAny('hg.password_reset.enable')():
<p class="links">
${h.link_to(_('Forgot your password?'), h.route_path('reset_password'))}
</p>
%elif h.HasPermissionAny('hg.password_reset.hidden')():
<p class="help-block">
${_('Contact an administrator if you have forgotten your password.')}
</p>
%endif
${h.submit('sign_in', _('Sign In'), class_="btn sign-in")}

View file

@ -28,39 +28,45 @@
<img class="sign-in-image" src="${h.asset('images/sign-in.png')}" alt="RhodeCode"/>
</div>
<div id="register" class="right-column">
<!-- login -->
<div class="sign-in-title">
<h1>${_('Reset your Password')}</h1>
<h4>${h.link_to(_("Go to the login page to sign in."), request.route_path('login'))}</h4>
%if h.HasPermissionAny('hg.password_reset.disabled')():
<div class="right-column">
<p>${_('Password reset has been disabled.')}</p>
</div>
<div class="inner form">
${h.form(request.route_path('reset_password'), needs_csrf_token=False)}
<label for="email">${_('Email Address')}:</label>
${h.text('email', defaults.get('email'))}
%if 'email' in errors:
<span class="error-message">${errors.get('email')}</span>
<br />
%endif
%if captcha_active:
<div class="login-captcha"
<label for="email">${_('Captcha')}:</label>
${h.hidden('recaptcha_field')}
<div id="recaptcha"></div>
%if 'recaptcha_field' in errors:
<span class="error-message">${errors.get('recaptcha_field')}</span>
%else:
<div id="register" class="right-column">
<!-- login -->
<div class="sign-in-title">
<h1>${_('Reset your Password')}</h1>
<h4>${h.link_to(_("Go to the login page to sign in."), request.route_path('login'))}</h4>
</div>
<div class="inner form">
${h.form(request.route_path('reset_password'), needs_csrf_token=False)}
<label for="email">${_('Email Address')}:</label>
${h.text('email', defaults.get('email'))}
%if 'email' in errors:
<span class="error-message">${errors.get('email')}</span>
<br />
%endif
</div>
%endif
${h.submit('send', _('Send password reset email'), class_="btn sign-in")}
<div class="activation_msg">${_('Password reset link will be sent to matching email address')}</div>
${h.end_form()}
%if captcha_active:
<div class="login-captcha"
<label for="email">${_('Captcha')}:</label>
${h.hidden('recaptcha_field')}
<div id="recaptcha"></div>
%if 'recaptcha_field' in errors:
<span class="error-message">${errors.get('recaptcha_field')}</span>
<br />
%endif
</div>
%endif
${h.submit('send', _('Send password reset email'), class_="btn sign-in")}
<div class="activation_msg">${_('Password reset link will be sent to matching email address')}</div>
${h.end_form()}
</div>
</div>
</div>
%endif
</div>
</div>