Пример #1
0
    def create_or_update(
            self, username, password, email, firstname='', lastname='',
            active=True, admin=False, extern_type=None, extern_name=None,
            cur_user=None, plugin=None, force_password_change=False,
            allow_to_create_user=True, create_repo_group=False,
            updating_user_id=None, language=None, strict_creation_check=True):
        """
        Creates a new instance if not found, or updates current one

        :param username:
        :param password:
        :param email:
        :param firstname:
        :param lastname:
        :param active:
        :param admin:
        :param extern_type:
        :param extern_name:
        :param cur_user:
        :param plugin: optional plugin this method was called from
        :param force_password_change: toggles new or existing user flag
            for password change
        :param allow_to_create_user: Defines if the method can actually create
            new users
        :param create_repo_group: Defines if the method should also
            create an repo group with user name, and owner
        :param updating_user_id: if we set it up this is the user we want to
            update this allows to editing username.
        :param language: language of user from interface.

        :returns: new User object with injected `is_new_user` attribute.
        """
        if not cur_user:
            cur_user = getattr(get_current_rhodecode_user(), 'username', None)

        from rhodecode.lib.auth import (
            get_crypt_password, check_password, generate_auth_token)
        from rhodecode.lib.hooks_base import (
            log_create_user, check_allowed_create_user)

        def _password_change(new_user, password):
            # empty password
            if not new_user.password:
                return False

            # password check is only needed for RhodeCode internal auth calls
            # in case it's a plugin we don't care
            if not plugin:

                # first check if we gave crypted password back, and if it matches
                # it's not password change
                if new_user.password == password:
                    return False

                password_match = check_password(password, new_user.password)
                if not password_match:
                    return True

            return False

        user_data = {
            'username': username,
            'password': password,
            'email': email,
            'firstname': firstname,
            'lastname': lastname,
            'active': active,
            'admin': admin
        }

        if updating_user_id:
            log.debug('Checking for existing account in RhodeCode '
                      'database with user_id `%s` ' % (updating_user_id,))
            user = User.get(updating_user_id)
        else:
            log.debug('Checking for existing account in RhodeCode '
                      'database with username `%s` ' % (username,))
            user = User.get_by_username(username, case_insensitive=True)

        if user is None:
            # we check internal flag if this method is actually allowed to
            # create new user
            if not allow_to_create_user:
                msg = ('Method wants to create new user, but it is not '
                       'allowed to do so')
                log.warning(msg)
                raise NotAllowedToCreateUserError(msg)

            log.debug('Creating new user %s', username)

            # only if we create user that is active
            new_active_user = active
            if new_active_user and strict_creation_check:
                # raises UserCreationError if it's not allowed for any reason to
                # create new active user, this also executes pre-create hooks
                check_allowed_create_user(user_data, cur_user, strict_check=True)
            self.send_event(UserPreCreate(user_data))
            new_user = User()
            edit = False
        else:
            log.debug('updating user %s', username)
            self.send_event(UserPreUpdate(user, user_data))
            new_user = user
            edit = True

            # we're not allowed to edit default user
            if user.username == User.DEFAULT_USER:
                raise DefaultUserException(
                    _("You can't edit this user (`%(username)s`) since it's "
                      "crucial for entire application") % {'username': user.username})

        # inject special attribute that will tell us if User is new or old
        new_user.is_new_user = not edit
        # for users that didn's specify auth type, we use RhodeCode built in
        from rhodecode.authentication.plugins import auth_rhodecode
        extern_name = extern_name or auth_rhodecode.RhodeCodeAuthPlugin.name
        extern_type = extern_type or auth_rhodecode.RhodeCodeAuthPlugin.name

        try:
            new_user.username = username
            new_user.admin = admin
            new_user.email = email
            new_user.active = active
            new_user.extern_name = safe_unicode(extern_name)
            new_user.extern_type = safe_unicode(extern_type)
            new_user.name = firstname
            new_user.lastname = lastname

            if not edit:
                new_user.api_key = generate_auth_token(username)

            # set password only if creating an user or password is changed
            if not edit or _password_change(new_user, password):
                reason = 'new password' if edit else 'new user'
                log.debug('Updating password reason=>%s', reason)
                new_user.password = get_crypt_password(password) if password else None

            if force_password_change:
                new_user.update_userdata(force_password_change=True)
            if language:
                new_user.update_userdata(language=language)

            self.sa.add(new_user)

            if not edit and create_repo_group:
                # create new group same as username, and make this user an owner
                desc = RepoGroupModel.PERSONAL_GROUP_DESC % {'username': username}
                RepoGroupModel().create(group_name=username,
                                        group_description=desc,
                                        owner=username, commit_early=False)
            if not edit:
                # add the RSS token
                AuthTokenModel().create(username,
                                        description='Generated feed token',
                                        role=AuthTokenModel.cls.ROLE_FEED)
                log_create_user(created_by=cur_user, **new_user.get_dict())
            return new_user
        except (DatabaseError,):
            log.error(traceback.format_exc())
            raise