Changeset - 3b136af34329
[Not reviewed]
default
0 8 0
Marcin Kuzminski - 12 years ago 2013-07-01 16:10:22
marcin@python-works.com
Added pre-create user hook.
It allows to control user creation using rcext hooks.
8 files changed with 137 insertions and 24 deletions:
0 comments (0 inline, 0 general)
rhodecode/config/rcextensions/__init__.py
Show inline comments
 
@@ -53,6 +53,29 @@ CREATE_REPO_HOOK = _crrepohook
 

	
 

	
 
#==============================================================================
 
# 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
rhodecode/controllers/admin/users.py
Show inline comments
 
@@ -35,7 +35,7 @@ from pylons.i18n.translation import _
 

	
 
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 @@ class UsersController(BaseController):
 
                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') \
rhodecode/controllers/login.py
Show inline comments
 
@@ -37,6 +37,7 @@ from pylons import request, response, se
 
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 @@ class LoginController(BaseController):
 
                    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 @@ class LoginController(BaseController):
 
                    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')
 

	
rhodecode/lib/base.py
Show inline comments
 
@@ -22,6 +22,7 @@ from rhodecode.lib.utils2 import str2boo
 
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 @@ class BaseController(WSGIController):
 
            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 \
rhodecode/lib/exceptions.py
Show inline comments
 
@@ -90,3 +90,11 @@ class HTTPLockedRC(HTTPClientError):
 

	
 
class IMCCommitError(Exception):
 
    pass
 

	
 

	
 
class UserCreationError(Exception):
 
    pass
 

	
 

	
 
class RepositoryCreationError(Exception):
 
    pass
rhodecode/lib/hooks.py
Show inline comments
 
@@ -34,7 +34,7 @@ from rhodecode.lib import helpers as h
 
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 @@ def log_create_repository(repository_dic
 
    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
rhodecode/model/user.py
Show inline comments
 
@@ -36,9 +36,9 @@ from sqlalchemy.orm import joinedload
 
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 @@ class UserModel(BaseModel):
 
    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 @@ class UserModel(BaseModel):
 
            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 @@ class UserModel(BaseModel):
 
            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 @@ class UserModel(BaseModel):
 
            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 @@ class UserModel(BaseModel):
 
        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 @@ class UserModel(BaseModel):
 
        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,):
rhodecode/templates/register.html
Show inline comments
 
@@ -6,7 +6,16 @@
 
</%def>
 

	
 
<div id="register">
 

	
 
<div class="flash_msg">
 
    <% messages = h.flash.pop_messages() %>
 
    % if messages:
 
    <ul id="flash-messages">
 
        % for message in messages:
 
        <li class="${message.category}_msg">${message}</li>
 
        % endfor
 
    </ul>
 
    % endif
 
</div>
 
    <div class="title top-left-rounded-corner top-right-rounded-corner">
 
        <h5>${_('Sign Up to')} ${c.rhodecode_name}</h5>
 
    </div>
0 comments (0 inline, 0 general)