##// END OF EJS Templates
i18n: updated translation for Russian...
i18n: updated translation for Russian Currently translated at 100.0% (1087 of 1087 strings)

File last commit:

r8075:e3537310 default
r8091:b6839376 default
Show More
user.py
514 lines | 18.8 KiB | text/x-python | PythonLexer
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 # -*- coding: utf-8 -*-
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
kallithea.model.user
~~~~~~~~~~~~~~~~~~~~
Bradley M. Kuhn
General renaming to Kallithea
r4212 users model for Kallithea
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Bradley M. Kuhn
RhodeCode GmbH is not the sole author of this work
r4211 This file was forked by the Kallithea project in July 2014.
Original author and date, and relevant copyright and licensing information is below:
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 :created_on: Apr 9, 2010
:author: marcink
Bradley M. Kuhn
RhodeCode GmbH is not the sole author of this work
r4211 :copyright: (c) 2013 RhodeCode GmbH, and others.
Bradley M. Kuhn
Correct licensing information in individual files....
r4208 :license: GPLv3, see LICENSE.md for more details.
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 """
Andrew Shadura
auth: secure password reset implementation...
r5457 import hashlib
Søren Løvborg
auth: use HMAC-SHA1 to calculate password reset token...
r5458 import hmac
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 import logging
Andrew Shadura
auth: secure password reset implementation...
r5457 import time
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 import traceback
Andrew Shadura
auth: secure password reset implementation...
r5457
Mads Kiilerich
scripts: initial run of import cleanup using isort
r7718 from sqlalchemy.exc import DatabaseError
Mads Kiilerich
tg: minimize future diff by some mocking and replacing some pylons imports with tg...
r6508 from tg import config
from tg.i18n import ugettext as _
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
from kallithea.lib.caching_query import FromCache
Mads Kiilerich
scripts: initial run of import cleanup using isort
r7718 from kallithea.lib.exceptions import DefaultUserException, UserOwnsReposException
Mads Kiilerich
py3: remove safe_unicode in places where it no longer is needed because all strings (except bytes) already *are* unicode strings...
r8075 from kallithea.lib.utils2 import generate_api_key, get_current_authuser
Mads Kiilerich
scripts: initial run of import cleanup using isort
r7718 from kallithea.model.db import Permission, User, UserEmailMap, UserIpMap, UserToPerm
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 from kallithea.model.meta import Session
log = logging.getLogger(__name__)
Søren Løvborg
model: remove BaseModel class...
r6483 class UserModel(object):
Andrew Shadura
auth: secure password reset implementation...
r5457 password_reset_token_lifetime = 86400 # 24 hours
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 def get(self, user_id, cache=False):
Søren Løvborg
model: remove BaseModel class...
r6483 user = User.query()
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 if cache:
user = user.options(FromCache("sql_cache_short",
"get_user_%s" % user_id))
return user.get(user_id)
def get_user(self, user):
Søren Løvborg
model: inline BaseModel._get_user calls
r6423 return User.guess_instance(user)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
def create(self, form_data, cur_user=None):
if not cur_user:
Bradley M. Kuhn
Rename rhodecode_user to authuser - it is an AuthUser instance
r4197 cur_user = getattr(get_current_authuser(), 'username', None)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Ronny Pfannschmidt
user model: cleanup
r5032 from kallithea.lib.hooks import log_create_user, \
check_allowed_create_user
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 _fd = form_data
user_data = {
Ronny Pfannschmidt
user model: cleanup
r5032 'username': _fd['username'],
'password': _fd['password'],
'email': _fd['email'],
'firstname': _fd['firstname'],
'lastname': _fd['lastname'],
'active': _fd['active'],
'admin': False
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 }
# raises UserCreationError if it's not allowed
check_allowed_create_user(user_data, cur_user)
from kallithea.lib.auth import get_crypt_password
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733 new_user = User()
for k, v in form_data.items():
if k == 'password':
v = get_crypt_password(v)
if k == 'firstname':
k = 'name'
setattr(new_user, k, v)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Mads Kiilerich
utils: make API key generator more random...
r5217 new_user.api_key = generate_api_key()
Søren Løvborg
db: clean up SQLAlchemy session flushes...
r6279 Session().add(new_user)
Session().flush() # make database assign new_user.user_id
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733
log_create_user(new_user.get_dict(), cur_user)
return new_user
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Mads Kiilerich
constants: use correct unicode encoding - avoid extra conversions
r5610 def create_or_update(self, username, password, email, firstname=u'',
lastname=u'', active=True, admin=False,
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 extern_type=None, extern_name=None, cur_user=None):
"""
Creates a new instance if not found, or updates current one
:param username:
:param password:
:param email:
:param active:
:param firstname:
:param lastname:
:param active:
:param admin:
:param extern_name:
:param extern_type:
:param cur_user:
"""
if not cur_user:
Bradley M. Kuhn
Rename rhodecode_user to authuser - it is an AuthUser instance
r4197 cur_user = getattr(get_current_authuser(), 'username', None)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
from kallithea.lib.auth import get_crypt_password, check_password
Ronny Pfannschmidt
user model: cleanup
r5032 from kallithea.lib.hooks import log_create_user, \
check_allowed_create_user
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 user_data = {
'username': username, 'password': password,
'email': email, 'firstname': firstname, 'lastname': lastname,
'active': active, 'admin': admin
}
# raises UserCreationError if it's not allowed
check_allowed_create_user(user_data, cur_user)
Mads Kiilerich
cleanup: pass log strings unformatted - avoid unnecessary % formatting when not logging
r5375 log.debug('Checking for %s account in Kallithea database', username)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 user = User.get_by_username(username, case_insensitive=True)
if user is None:
Mads Kiilerich
cleanup: pass log strings unformatted - avoid unnecessary % formatting when not logging
r5375 log.debug('creating new user %s', username)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 new_user = User()
edit = False
else:
Mads Kiilerich
cleanup: pass log strings unformatted - avoid unnecessary % formatting when not logging
r5375 log.debug('updating user %s', username)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 new_user = user
edit = True
try:
new_user.username = username
new_user.admin = admin
new_user.email = email
new_user.active = active
Mads Kiilerich
py3: remove safe_unicode in places where it no longer is needed because all strings (except bytes) already *are* unicode strings...
r8075 new_user.extern_name = extern_name
new_user.extern_type = extern_type
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 new_user.name = firstname
new_user.lastname = lastname
if not edit:
Mads Kiilerich
utils: make API key generator more random...
r5217 new_user.api_key = generate_api_key()
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
# set password only if creating an user or password is changed
Ronny Pfannschmidt
user model: cleanup
r5032 password_change = new_user.password and \
not check_password(password, new_user.password)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 if not edit or password_change:
reason = 'new password' if edit else 'new user'
Mads Kiilerich
cleanup: pass log strings unformatted - avoid unnecessary % formatting when not logging
r5375 log.debug('Updating password reason=>%s', reason)
Ronny Pfannschmidt
user model: cleanup
r5032 new_user.password = get_crypt_password(password) \
Mads Kiilerich
user: when updating a user, never set the password to None - the field is not nullable...
r6166 if password else ''
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Søren Løvborg
db: clean up SQLAlchemy session flushes...
r6279 if user is None:
Session().add(new_user)
Session().flush() # make database assign new_user.user_id
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
if not edit:
log_create_user(new_user.get_dict(), cur_user)
Søren Løvborg
db: clean up SQLAlchemy session flushes...
r6279
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 return new_user
except (DatabaseError,):
log.error(traceback.format_exc())
raise
def create_registration(self, form_data):
from kallithea.model.notification import NotificationModel
Mads Kiilerich
urls: introduce canonical_url config setting...
r4445 import kallithea.lib.helpers as h
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733 form_data['admin'] = False
Mads Kiilerich
auth: cleanup of EXTERN_TYPE_INTERNAL...
r6168 form_data['extern_type'] = User.DEFAULT_AUTH_TYPE
form_data['extern_name'] = ''
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733 new_user = self.create(form_data)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733 # notification to admins
subject = _('New user registration')
Ronny Pfannschmidt
user model: cleanup
r5032 body = (
Mads Kiilerich
constants: use correct unicode encoding - avoid extra conversions
r5610 u'New user registration\n'
Ronny Pfannschmidt
user model: cleanup
r5032 '---------------------\n'
'- Username: {user.username}\n'
'- Full Name: {user.full_name}\n'
'- Email: {user.email}\n'
).format(user=new_user)
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733 edit_url = h.canonical_url('edit_user', id=new_user.user_id)
Ronny Pfannschmidt
user model: cleanup
r5032 email_kwargs = {
'registered_user_url': edit_url,
Mads Kiilerich
mails: restructure notification mail content...
r6098 'new_username': new_user.username,
'new_email': new_user.email,
'new_full_name': new_user.full_name}
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733 NotificationModel().create(created_by=new_user, subject=subject,
body=body, recipients=None,
Thomas De Schampheleire
model: move notification types from Notification to NotificationModel...
r7368 type_=NotificationModel.TYPE_REGISTRATION,
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733 email_kwargs=email_kwargs)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Jiří Suchan
cleanup: stop using mutable default params
r5555 def update(self, user_id, form_data, skip_attrs=None):
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 from kallithea.lib.auth import get_crypt_password
Jiří Suchan
cleanup: stop using mutable default params
r5555 skip_attrs = skip_attrs or []
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733 user = self.get(user_id, cache=False)
Søren Løvborg
cleanup: refer less to User.DEFAULT_USER...
r6476 if user.is_default_user:
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733 raise DefaultUserException(
Søren Løvborg
spelling: fix inappropriate use of title case...
r5424 _("You can't edit this user since it's "
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733 "crucial for entire application"))
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733 for k, v in form_data.items():
if k in skip_attrs:
continue
if k == 'new_password' and v:
user.password = get_crypt_password(v)
else:
# old legacy thing orm models store firstname as name,
# need proper refactor to username
if k == 'firstname':
k = 'name'
setattr(user, k, v)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
def update_user(self, user, **kwargs):
from kallithea.lib.auth import get_crypt_password
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733
Søren Løvborg
model: inline BaseModel._get_user calls
r6423 user = User.guess_instance(user)
Søren Løvborg
cleanup: refer less to User.DEFAULT_USER...
r6476 if user.is_default_user:
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733 raise DefaultUserException(
Søren Løvborg
spelling: fix inappropriate use of title case...
r5424 _("You can't edit this user since it's"
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733 " crucial for entire application")
)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733 for k, v in kwargs.items():
if k == 'password' and v:
v = get_crypt_password(v)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733 setattr(user, k, v)
return user
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
def delete(self, user, cur_user=None):
Mads Kiilerich
cleanup: check for None object identity in cases where that is what the 'contract' says...
r5306 if cur_user is None:
Bradley M. Kuhn
Rename rhodecode_user to authuser - it is an AuthUser instance
r4197 cur_user = getattr(get_current_authuser(), 'username', None)
Søren Løvborg
model: inline BaseModel._get_user calls
r6423 user = User.guess_instance(user)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Søren Løvborg
cleanup: refer less to User.DEFAULT_USER...
r6476 if user.is_default_user:
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733 raise DefaultUserException(
Mads Kiilerich
validators: cleanup of message wording...
r5296 _("You can't remove this user since it is"
" crucial for the entire application"))
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733 if user.repositories:
repos = [x.repo_name for x in user.repositories]
raise UserOwnsReposException(
Mads Kiilerich
i18n: use plain strings on the english lookup side of translations...
r5295 _('User "%s" still owns %s repositories and cannot be '
Mads Kiilerich
user: prevent deletion of users that are owners of a repo group...
r4745 'removed. Switch owners or remove those repositories: %s')
Ronny Pfannschmidt
user model: cleanup
r5032 % (user.username, len(repos), ', '.join(repos)))
Mads Kiilerich
user: prevent deletion of users that are owners of a repo group...
r4745 if user.repo_groups:
repogroups = [x.group_name for x in user.repo_groups]
Ronny Pfannschmidt
user model: cleanup
r5032 raise UserOwnsReposException(_(
'User "%s" still owns %s repository groups and cannot be '
'removed. Switch owners or remove those repository groups: %s')
% (user.username, len(repogroups), ', '.join(repogroups)))
Mads Kiilerich
user: prevent deletion of users that are owners of a user group...
r4746 if user.user_groups:
usergroups = [x.users_group_name for x in user.user_groups]
raise UserOwnsReposException(
Ronny Pfannschmidt
user model: cleanup
r5032 _('User "%s" still owns %s user groups and cannot be '
Mads Kiilerich
user: prevent deletion of users that are owners of a user group...
r4746 'removed. Switch owners or remove those user groups: %s')
Ronny Pfannschmidt
user model: cleanup
r5032 % (user.username, len(usergroups), ', '.join(usergroups)))
Søren Løvborg
model: remove BaseModel class...
r6483 Session().delete(user)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733 from kallithea.lib.hooks import log_delete_user
log_delete_user(user.get_dict(), cur_user)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Mads Kiilerich
auth: only local passwords can be reset...
r5582 def can_change_password(self, user):
from kallithea.lib import auth_modules
managed_fields = auth_modules.get_managed_fields(user)
return 'password' not in managed_fields
Andrew Shadura
auth: secure password reset implementation...
r5457 def get_reset_password_token(self, user, timestamp, session_id):
"""
Søren Løvborg
auth: use HMAC-SHA1 to calculate password reset token...
r5458 The token is a 40-digit hexstring, calculated as a HMAC-SHA1.
Andrew Shadura
auth: secure password reset implementation...
r5457
Søren Løvborg
auth: use HMAC-SHA1 to calculate password reset token...
r5458 In a traditional HMAC scenario, an attacker is unable to know or
influence the secret key, but can know or influence the message
and token. This scenario is slightly different (in particular
since the message sender is also the message recipient), but
sufficiently similar to use an HMAC. Benefits compared to a plain
SHA1 hash includes resistance against a length extension attack.
The HMAC key consists of the following values (known only to the
server and authorized users):
* per-application secret (the `app_instance_uuid` setting), without
which an attacker cannot counterfeit tokens
* hashed user password, invalidating the token upon password change
Andrew Shadura
auth: secure password reset implementation...
r5457
Søren Løvborg
auth: use HMAC-SHA1 to calculate password reset token...
r5458 The HMAC message consists of the following values (potentially known
to an attacker):
* session ID (the anti-CSRF token), requiring an attacker to have
access to the browser session in which the token was created
* numeric user ID, limiting the token to a specific user (yet allowing
users to be renamed)
* user email address
* time of token issue (a Unix timestamp, to enable token expiration)
The key and message values are separated by NUL characters, which are
guaranteed not to occur in any of the values.
Andrew Shadura
auth: secure password reset implementation...
r5457 """
Søren Løvborg
auth: use HMAC-SHA1 to calculate password reset token...
r5458 app_secret = config.get('app_instance_uuid')
return hmac.HMAC(
key=u'\0'.join([app_secret, user.password]).encode('utf-8'),
msg=u'\0'.join([session_id, str(user.user_id), user.email, str(timestamp)]).encode('utf-8'),
digestmod=hashlib.sha1,
).hexdigest()
Andrew Shadura
auth: secure password reset implementation...
r5457
def send_reset_password_email(self, data):
"""
Sends email with a password reset token and link to the password
reset confirmation page with all information (including the token)
pre-filled. Also returns URL of that page, only without the token,
allowing users to copy-paste or manually enter the token from the
email.
"""
Mads Kiilerich
celeryd: annotate tasks so they can be run directly without run_task...
r6133 from kallithea.lib.celerylib import tasks
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 from kallithea.model.notification import EmailNotificationModel
Mads Kiilerich
urls: introduce canonical_url config setting...
r4445 import kallithea.lib.helpers as h
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 user_email = data['email']
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733 user = User.get_by_email(user_email)
Andrew Shadura
auth: secure password reset implementation...
r5457 timestamp = int(time.time())
Mads Kiilerich
cleanup: check for None object identity in cases where that is what the 'contract' says...
r5306 if user is not None:
Mads Kiilerich
auth: only local passwords can be reset...
r5582 if self.can_change_password(user):
log.debug('password reset user %s found', user)
token = self.get_reset_password_token(user,
timestamp,
Mads Kiilerich
helpers: rename internal names of authentication_token to clarify that secure_form is about session CSRF secrets - not authentication
r7709 h.session_csrf_secret_token())
Mads Kiilerich
auth: only local passwords can be reset...
r5582 # URL must be fully qualified; but since the token is locked to
# the current browser session, we must provide a URL with the
# current scheme and hostname, rather than the canonical_url.
link = h.url('reset_password_confirmation', qualified=True,
email=user_email,
timestamp=timestamp,
token=token)
else:
log.debug('password reset user %s found but was managed', user)
token = link = None
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733 reg_type = EmailNotificationModel.TYPE_PASSWORD_RESET
Ronny Pfannschmidt
user model: cleanup
r5032 body = EmailNotificationModel().get_email_tmpl(
reg_type, 'txt',
user=user.short_contact,
Andrew Shadura
auth: secure password reset implementation...
r5457 reset_token=token,
Ronny Pfannschmidt
user model: cleanup
r5032 reset_url=link)
html_body = EmailNotificationModel().get_email_tmpl(
reg_type, 'html',
user=user.short_contact,
Andrew Shadura
auth: secure password reset implementation...
r5457 reset_token=token,
Ronny Pfannschmidt
user model: cleanup
r5032 reset_url=link)
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733 log.debug('sending email')
Mads Kiilerich
celeryd: annotate tasks so they can be run directly without run_task...
r6133 tasks.send_email([user_email], _("Password reset link"), body, html_body)
Mads Kiilerich
cleanup: pass log strings unformatted - avoid unnecessary % formatting when not logging
r5375 log.info('send new password mail to %s', user_email)
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733 else:
Mads Kiilerich
cleanup: pass log strings unformatted - avoid unnecessary % formatting when not logging
r5375 log.debug("password reset email %s not found", user_email)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Andrew Shadura
auth: secure password reset implementation...
r5457 return h.url('reset_password_confirmation',
email=user_email,
timestamp=timestamp)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Andrew Shadura
auth: secure password reset implementation...
r5457 def verify_reset_password_token(self, email, timestamp, token):
import kallithea.lib.helpers as h
user = User.get_by_email(email)
if user is None:
log.debug("user with email %s not found", email)
return False
token_age = int(time.time()) - int(timestamp)
if token_age < 0:
log.debug('timestamp is from the future')
return False
if token_age > UserModel.password_reset_token_lifetime:
log.debug('password reset token expired')
return False
expected_token = self.get_reset_password_token(user,
timestamp,
Mads Kiilerich
helpers: rename internal names of authentication_token to clarify that secure_form is about session CSRF secrets - not authentication
r7709 h.session_csrf_secret_token())
Andrew Shadura
auth: secure password reset implementation...
r5457 log.debug('computed password reset token: %s', expected_token)
log.debug('received password reset token: %s', token)
return expected_token == token
def reset_password(self, user_email, new_passwd):
Mads Kiilerich
celeryd: annotate tasks so they can be run directly without run_task...
r6133 from kallithea.lib.celerylib import tasks
Andrew Shadura
auth: secure password reset implementation...
r5457 from kallithea.lib import auth
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733 user = User.get_by_email(user_email)
Mads Kiilerich
cleanup: check for None object identity in cases where that is what the 'contract' says...
r5306 if user is not None:
Mads Kiilerich
auth: only local passwords can be reset...
r5582 if not self.can_change_password(user):
raise Exception('trying to change password for external user')
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733 user.password = auth.get_crypt_password(new_passwd)
Session().commit()
Mads Kiilerich
cleanup: pass log strings unformatted - avoid unnecessary % formatting when not logging
r5375 log.info('change password for %s', user_email)
Mads Kiilerich
cleanup: avoid some 'except Exception' catching - catch specific exceptions or log it and show what happened...
r4733 if new_passwd is None:
Andrew Shadura
auth: secure password reset implementation...
r5457 raise Exception('unable to set new password')
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Mads Kiilerich
celeryd: annotate tasks so they can be run directly without run_task...
r6133 tasks.send_email([user_email],
Andrew Shadura
auth: secure password reset implementation...
r5457 _('Password reset notification'),
_('The password to your account %s has been changed using password reset form.') % (user.username,))
log.info('send password reset mail to %s', user_email)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
return True
def has_perm(self, user, perm):
Søren Løvborg
model: inline calls to BaseModel._get_perm
r6425 perm = Permission.guess_instance(perm)
Søren Løvborg
model: inline BaseModel._get_user calls
r6423 user = User.guess_instance(user)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Mads Kiilerich
cleanup: consistent space before line continuation backslash
r5585 return UserToPerm.query().filter(UserToPerm.user == user) \
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 .filter(UserToPerm.permission == perm).scalar() is not None
def grant_perm(self, user, perm):
"""
Grant user global permissions
:param user:
:param perm:
"""
Søren Løvborg
model: inline BaseModel._get_user calls
r6423 user = User.guess_instance(user)
Søren Løvborg
model: inline calls to BaseModel._get_perm
r6425 perm = Permission.guess_instance(perm)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 # if this permission is already granted skip it
Mads Kiilerich
cleanup: consistent space before line continuation backslash
r5585 _perm = UserToPerm.query() \
.filter(UserToPerm.user == user) \
.filter(UserToPerm.permission == perm) \
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 .scalar()
if _perm:
return
new = UserToPerm()
new.user = user
new.permission = perm
Søren Løvborg
model: remove BaseModel class...
r6483 Session().add(new)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 return new
def revoke_perm(self, user, perm):
"""
Revoke users global permissions
:param user:
:param perm:
"""
Søren Løvborg
model: inline BaseModel._get_user calls
r6423 user = User.guess_instance(user)
Søren Løvborg
model: inline calls to BaseModel._get_perm
r6425 perm = Permission.guess_instance(perm)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
Ronny Pfannschmidt
user model: saner user permission revoking
r5033 UserToPerm.query().filter(
UserToPerm.user == user,
UserToPerm.permission == perm,
).delete()
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
def add_extra_email(self, user, email):
"""
Adds email address to UserEmailMap
:param user:
:param email:
"""
from kallithea.model import forms
form = forms.UserExtraEmailForm()()
data = form.to_python(dict(email=email))
Søren Løvborg
model: inline BaseModel._get_user calls
r6423 user = User.guess_instance(user)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
obj = UserEmailMap()
obj.user = user
obj.email = data['email']
Søren Løvborg
model: remove BaseModel class...
r6483 Session().add(obj)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 return obj
def delete_extra_email(self, user, email_id):
"""
Removes email address from UserEmailMap
:param user:
:param email_id:
"""
Søren Løvborg
model: inline BaseModel._get_user calls
r6423 user = User.guess_instance(user)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 obj = UserEmailMap.query().get(email_id)
Mads Kiilerich
cleanup: check for None object identity in cases where that is what the 'contract' says...
r5306 if obj is not None:
Søren Løvborg
model: remove BaseModel class...
r6483 Session().delete(obj)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
def add_extra_ip(self, user, ip):
"""
Mads Kiilerich
spelling: more consistent casing of 'IP'
r5125 Adds IP address to UserIpMap
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
:param user:
:param ip:
"""
from kallithea.model import forms
form = forms.UserExtraIpForm()()
data = form.to_python(dict(ip=ip))
Søren Løvborg
model: inline BaseModel._get_user calls
r6423 user = User.guess_instance(user)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
obj = UserIpMap()
obj.user = user
obj.ip_addr = data['ip']
Søren Løvborg
model: remove BaseModel class...
r6483 Session().add(obj)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 return obj
def delete_extra_ip(self, user, ip_id):
"""
Mads Kiilerich
spelling: more consistent casing of 'IP'
r5125 Removes IP address from UserIpMap
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187
:param user:
:param ip_id:
"""
Søren Løvborg
model: inline BaseModel._get_user calls
r6423 user = User.guess_instance(user)
Bradley M. Kuhn
Second step in two-part process to rename directories....
r4187 obj = UserIpMap.query().get(ip_id)
if obj:
Søren Løvborg
model: remove BaseModel class...
r6483 Session().delete(obj)