# HG changeset patch # User Marcin Kuzminski # Date 1372687822 -7200 # Node ID 3b136af34329d70d828ca02ac7ee126a93e4678c # Parent 2c82dd8ba31812ca48280ee28d993744a93bf774 Added pre-create user hook. It allows to control user creation using rcext hooks. diff -r 2c82dd8ba318 -r 3b136af34329 rhodecode/config/rcextensions/__init__.py --- a/rhodecode/config/rcextensions/__init__.py Mon Jul 01 15:39:01 2013 +0200 +++ b/rhodecode/config/rcextensions/__init__.py Mon Jul 01 16:10:22 2013 +0200 @@ -53,6 +53,29 @@ #============================================================================== +# PRE CREATE USER HOOK +#============================================================================== +# this function will be executed before each user is created +def _pre_cruserhook(*args, **kwargs): + """ + Pre create user HOOK, it returns a tuple of bool, reason. + If bool is False the user creation will be stopped and reason + will be displayed to the user. + kwargs available: + :param username: + :param password: + :param email: + :param firstname: + :param lastname: + :param active: + :param admin: + :param created_by: + """ + reason = 'allowed' + return True, reason +PRE_CREATE_USER_HOOK = _pre_cruserhook + +#============================================================================== # POST CREATE USER HOOK #============================================================================== # this function will be executed after each user is created diff -r 2c82dd8ba318 -r 3b136af34329 rhodecode/controllers/admin/users.py --- a/rhodecode/controllers/admin/users.py Mon Jul 01 15:39:01 2013 +0200 +++ b/rhodecode/controllers/admin/users.py Mon Jul 01 16:10:22 2013 +0200 @@ -35,7 +35,7 @@ import rhodecode from rhodecode.lib.exceptions import DefaultUserException, \ - UserOwnsReposException + UserOwnsReposException, UserCreationError from rhodecode.lib import helpers as h from rhodecode.lib.auth import LoginRequired, HasPermissionAllDecorator, \ AuthUser @@ -137,6 +137,8 @@ errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8") + except UserCreationError, e: + h.flash(e, 'error') except Exception: log.error(traceback.format_exc()) h.flash(_('Error occurred during creation of user %s') \ diff -r 2c82dd8ba318 -r 3b136af34329 rhodecode/controllers/login.py --- a/rhodecode/controllers/login.py Mon Jul 01 15:39:01 2013 +0200 +++ b/rhodecode/controllers/login.py Mon Jul 01 16:10:22 2013 +0200 @@ -37,6 +37,7 @@ import rhodecode.lib.helpers as h from rhodecode.lib.auth import AuthUser, HasPermissionAnyDecorator from rhodecode.lib.base import BaseController, render +from rhodecode.lib.exceptions import UserCreationError from rhodecode.model.db import User from rhodecode.model.forms import LoginForm, RegisterForm, PasswordResetForm from rhodecode.model.user import UserModel @@ -120,6 +121,12 @@ errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8") + except UserCreationError, e: + # container auth or other auth functions that create users on + # the fly can throw this exception signaling that there's issue + # with user creation, explanation should be provided in + # Exception itself + h.flash(e, 'error') return render('/login.html') @@ -147,6 +154,12 @@ errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8") + except UserCreationError, e: + # container auth or other auth functions that create users on + # the fly can throw this exception signaling that there's issue + # with user creation, explanation should be provided in + # Exception itself + h.flash(e, 'error') return render('/register.html') diff -r 2c82dd8ba318 -r 3b136af34329 rhodecode/lib/base.py --- a/rhodecode/lib/base.py Mon Jul 01 15:39:01 2013 +0200 +++ b/rhodecode/lib/base.py Mon Jul 01 16:10:22 2013 +0200 @@ -22,6 +22,7 @@ from rhodecode.lib.auth import AuthUser, get_container_username, authfunc,\ HasPermissionAnyMiddleware, CookieStoreWrapper from rhodecode.lib.utils import get_repo_slug +from rhodecode.lib.exceptions import UserCreationError from rhodecode.model import meta from rhodecode.model.db import Repository, RhodeCodeUi, User, RhodeCodeSetting @@ -300,7 +301,17 @@ cookie_store = CookieStoreWrapper(session.get('rhodecode_user')) user_id = cookie_store.get('user_id', None) username = get_container_username(environ, config) - auth_user = AuthUser(user_id, api_key, username, self.ip_addr) + try: + auth_user = AuthUser(user_id, api_key, username, self.ip_addr) + except UserCreationError, e: + from rhodecode.lib import helpers as h + h.flash(e, 'error') + # container auth or other auth functions that create users on + # the fly can throw this exception signaling that there's issue + # with user creation, explanation should be provided in + # Exception itself + auth_user = AuthUser(ip_addr=self.ip_addr) + request.user = auth_user self.rhodecode_user = c.rhodecode_user = auth_user if not self.rhodecode_user.is_authenticated and \ diff -r 2c82dd8ba318 -r 3b136af34329 rhodecode/lib/exceptions.py --- a/rhodecode/lib/exceptions.py Mon Jul 01 15:39:01 2013 +0200 +++ b/rhodecode/lib/exceptions.py Mon Jul 01 16:10:22 2013 +0200 @@ -90,3 +90,11 @@ class IMCCommitError(Exception): pass + + +class UserCreationError(Exception): + pass + + +class RepositoryCreationError(Exception): + pass diff -r 2c82dd8ba318 -r 3b136af34329 rhodecode/lib/hooks.py --- a/rhodecode/lib/hooks.py Mon Jul 01 15:39:01 2013 +0200 +++ b/rhodecode/lib/hooks.py Mon Jul 01 16:10:22 2013 +0200 @@ -34,7 +34,7 @@ from rhodecode.lib.utils import action_logger from rhodecode.lib.vcs.backends.base import EmptyChangeset from rhodecode.lib.compat import json -from rhodecode.lib.exceptions import HTTPLockedRC +from rhodecode.lib.exceptions import HTTPLockedRC, UserCreationError from rhodecode.lib.utils2 import safe_str, _extract_extras from rhodecode.model.db import Repository, User @@ -252,6 +252,15 @@ return 0 +def check_allowed_create_user(user_dict, created_by, **kwargs): + from rhodecode import EXTENSIONS + callback = getattr(EXTENSIONS, 'PRE_CREATE_USER_HOOK', None) + if isfunction(callback): + allowed, reason = callback(created_by=created_by, **user_dict) + if not allowed: + raise UserCreationError(reason) + + def log_create_user(user_dict, created_by, **kwargs): """ Post create user Hook. This is a dummy function for admins to re-use diff -r 2c82dd8ba318 -r 3b136af34329 rhodecode/model/user.py --- a/rhodecode/model/user.py Mon Jul 01 15:39:01 2013 +0200 +++ b/rhodecode/model/user.py Mon Jul 01 16:10:22 2013 +0200 @@ -36,9 +36,9 @@ from rhodecode.lib.utils2 import safe_unicode, generate_api_key, get_current_rhodecode_user from rhodecode.lib.caching_query import FromCache from rhodecode.model import BaseModel -from rhodecode.model.db import User, UserRepoToPerm, Repository, Permission, \ +from rhodecode.model.db import User, Repository, Permission, \ UserToPerm, UserGroupRepoToPerm, UserGroupToPerm, UserGroupMember, \ - Notification, RepoGroup, UserRepoGroupToPerm, UserGroupRepoGroupToPerm, \ + Notification, RepoGroup, UserGroupRepoGroupToPerm, \ UserEmailMap, UserIpMap, UserGroupUserGroupToPerm, UserGroup from rhodecode.lib.exceptions import DefaultUserException, \ UserOwnsReposException @@ -83,6 +83,17 @@ def create(self, form_data, cur_user=None): if not cur_user: cur_user = getattr(get_current_rhodecode_user(), 'username', None) + + from rhodecode.lib.hooks import log_create_user, check_allowed_create_user + _fd = form_data + form_data = { + 'username': _fd['username'], 'password': _fd['password'], + 'email': _fd['email'], 'firstname': _fd['firstname'], 'lastname': _fd['lastname'], + 'active': _fd['active'], 'admin': False + } + # raises UserCreationError if it's not allowed + check_allowed_create_user(form_data, cur_user) + from rhodecode.lib.auth import get_crypt_password try: new_user = User() @@ -96,7 +107,6 @@ new_user.api_key = generate_api_key(form_data['username']) self.sa.add(new_user) - from rhodecode.lib.hooks import log_create_user log_create_user(new_user.get_dict(), cur_user) return new_user except Exception: @@ -124,6 +134,14 @@ cur_user = getattr(get_current_rhodecode_user(), 'username', None) from rhodecode.lib.auth import get_crypt_password + from rhodecode.lib.hooks import log_create_user, check_allowed_create_user + form_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(form_data, cur_user) log.debug('Checking for %s account in RhodeCode database' % username) user = User.get_by_username(username, case_insensitive=True) @@ -151,7 +169,6 @@ self.sa.add(new_user) if not edit: - from rhodecode.lib.hooks import log_create_user log_create_user(new_user.get_dict(), cur_user) return new_user except (DatabaseError,): @@ -169,23 +186,33 @@ if not cur_user: cur_user = getattr(get_current_rhodecode_user(), 'username', None) if self.get_by_username(username, case_insensitive=True) is None: - # autogenerate email for container account without one generate_email = lambda usr: '%s@container_auth.account' % usr + firstname = attrs['name'] + lastname = attrs['lastname'] + active = attrs.get('active', True) + email = attrs['email'] or generate_email(username) + + from rhodecode.lib.hooks import log_create_user, check_allowed_create_user + form_data = { + 'username': username, 'password': None, + 'email': email, 'firstname': firstname, 'lastname': lastname, + 'active': attrs.get('active', True), 'admin': False + } + # raises UserCreationError if it's not allowed + check_allowed_create_user(form_data, cur_user) try: new_user = User() new_user.username = username new_user.password = None new_user.api_key = generate_api_key(username) - new_user.email = attrs['email'] - new_user.active = attrs.get('active', True) - new_user.name = attrs['name'] or generate_email(username) - new_user.lastname = attrs['lastname'] + new_user.email = email + new_user.active = active + new_user.name = firstname + new_user.lastname = lastname self.sa.add(new_user) - - from rhodecode.lib.hooks import log_create_user log_create_user(new_user.get_dict(), cur_user) return new_user except (DatabaseError,): @@ -212,26 +239,37 @@ from rhodecode.lib.auth import get_crypt_password log.debug('Checking for such ldap account in RhodeCode database') if self.get_by_username(username, case_insensitive=True) is None: + # autogenerate email for container account without one + generate_email = lambda usr: '%s@ldap.account' % usr + password = get_crypt_password(password) + firstname = attrs['name'] + lastname = attrs['lastname'] + active = attrs.get('active', True) + email = attrs['email'] or generate_email(username) - # autogenerate email for ldap account without one - generate_email = lambda usr: '%s@ldap.account' % usr + from rhodecode.lib.hooks import log_create_user, check_allowed_create_user + form_data = { + 'username': username, 'password': password, + 'email': email, 'firstname': firstname, 'lastname': lastname, + 'active': attrs.get('active', True), 'admin': False + } + # raises UserCreationError if it's not allowed + check_allowed_create_user(form_data, cur_user) try: new_user = User() username = username.lower() # add ldap account always lowercase new_user.username = username - new_user.password = get_crypt_password(password) + new_user.password = password new_user.api_key = generate_api_key(username) - new_user.email = attrs['email'] or generate_email(username) - new_user.active = attrs.get('active', True) + new_user.email = email + new_user.active = active new_user.ldap_dn = safe_unicode(user_dn) - new_user.name = attrs['name'] - new_user.lastname = attrs['lastname'] - + new_user.name = firstname + new_user.lastname = lastname self.sa.add(new_user) - from rhodecode.lib.hooks import log_create_user log_create_user(new_user.get_dict(), cur_user) return new_user except (DatabaseError,): diff -r 2c82dd8ba318 -r 3b136af34329 rhodecode/templates/register.html --- a/rhodecode/templates/register.html Mon Jul 01 15:39:01 2013 +0200 +++ b/rhodecode/templates/register.html Mon Jul 01 16:10:22 2013 +0200 @@ -6,7 +6,16 @@
- +
+ <% messages = h.flash.pop_messages() %> + % if messages: +
    + % for message in messages: +
  • ${message}
  • + % endfor +
+ % endif +
${_('Sign Up to')} ${c.rhodecode_name}