Changeset - 4ae17f819ee8
[Not reviewed]
beta
0 9 0
Marcin Kuzminski - 14 years ago 2012-01-27 03:46:00
marcin@python-works.com
#344 optional firstname lastname on user creation
- on display fallback to username if both empty
9 files changed with 102 insertions and 66 deletions:
0 comments (0 inline, 0 general)
docs/api/api.rst
Show inline comments
 
@@ -158,9 +158,9 @@ INPUT::
 
    args :    {
 
                "username" :  "<username>",
 
                "password" :  "<password>",
 
                "firstname" : "<firstname>",
 
                "lastname" :  "<lastname>",
 
                "email" :     "<useremail>"
 
                "email" :     "<useremail>",
 
                "firstname" : "<firstname> = None",
 
                "lastname" :  "<lastname> = None",
 
                "active" :    "<bool> = True",
 
                "admin" :     "<bool> = False",
 
                "ldap_dn" :   "<ldap_dn> = None"
docs/changelog.rst
Show inline comments
 
@@ -35,6 +35,7 @@ news
 
  based on user defined regular expression
 
- added linking of changesets in commit messages  
 
- new compact changelog with expandable commit messages
 
- firstname and lastname are optional in user creation
 
    
 
fixes
 
-----
rhodecode/controllers/api/api.py
Show inline comments
 
@@ -131,17 +131,17 @@ class ApiController(JSONRPCController):
 
        return result
 

	
 
    @HasPermissionAllDecorator('hg.admin')
 
    def create_user(self, apiuser, username, password, firstname,
 
                    lastname, email, active=True, admin=False, ldap_dn=None):
 
    def create_user(self, apiuser, username, password, email, firstname=None,
 
                    lastname=None, active=True, admin=False, ldap_dn=None):
 
        """
 
        Create new user or updates current one
 

	
 
        :param apiuser:
 
        :param username:
 
        :param password:
 
        :param email:
 
        :param name:
 
        :param lastname:
 
        :param email:
 
        :param active:
 
        :param admin:
 
        :param ldap_dn:
rhodecode/lib/auth.py
Show inline comments
 
@@ -129,6 +129,7 @@ def get_crypt_password(password):
 
def check_password(password, hashed):
 
    return RhodeCodeCrypto.hash_check(password, hashed)
 

	
 

	
 
def generate_api_key(str_, salt=None):
 
    """
 
    Generates API KEY from given string
 
@@ -237,6 +238,7 @@ def authenticate(username, password):
 
                pass
 
    return False
 

	
 

	
 
def login_container_auth(username):
 
    user = User.get_by_username(username)
 
    if user is None:
 
@@ -260,6 +262,7 @@ def login_container_auth(username):
 
              user.username)
 
    return user
 

	
 

	
 
def get_container_username(environ, config):
 
    username = None
 

	
 
@@ -278,6 +281,7 @@ def get_container_username(environ, conf
 

	
 
    return username
 

	
 

	
 
class  AuthUser(object):
 
    """
 
    A simple object that handles all attributes of user in RhodeCode
 
@@ -302,6 +306,7 @@ class  AuthUser(object):
 
        self.permissions = {}
 
        self._api_key = api_key
 
        self.propagate_data()
 
        self._instance = None
 

	
 
    def propagate_data(self):
 
        user_model = UserModel()
 
@@ -350,10 +355,6 @@ class  AuthUser(object):
 
    def is_admin(self):
 
        return self.admin
 

	
 
    @property
 
    def full_contact(self):
 
        return '%s %s <%s>' % (self.name, self.lastname, self.email)
 

	
 
    def __repr__(self):
 
        return "<AuthUser('id:%s:%s|%s')>" % (self.user_id, self.username,
 
                                              self.is_authenticated)
 
@@ -374,6 +375,7 @@ class  AuthUser(object):
 
        api_key = cookie_store.get('api_key')
 
        return AuthUser(user_id, api_key, username)
 

	
 

	
 
def set_available_permissions(config):
 
    """
 
    This function will propagate pylons globals with all available defined
 
@@ -388,7 +390,7 @@ def set_available_permissions(config):
 
    try:
 
        sa = meta.Session
 
        all_perms = sa.query(Permission).all()
 
    except:
 
    except Exception:
 
        pass
 
    finally:
 
        meta.Session.remove()
rhodecode/model/db.py
Show inline comments
 
@@ -299,6 +299,11 @@ class User(Base, BaseModel):
 
        return '%s %s' % (self.name, self.lastname)
 

	
 
    @property
 
    def full_name_or_username(self):
 
        return ('%s %s' % (self.name, self.lastname)
 
                if (self.name and self.lastname) else self.username)
 

	
 
    @property
 
    def full_contact(self):
 
        return '%s %s <%s>' % (self.name, self.lastname, self.email)
 

	
 
@@ -354,8 +359,13 @@ class User(Base, BaseModel):
 
        log.debug('updated user %s lastlogin', self.username)
 

	
 
    def __json__(self):
 
        return dict(email=self.email,
 
                    full_name=self.full_name)
 
        return dict(
 
            email=self.email,
 
            full_name=self.full_name,
 
            full_name_or_username=self.full_name_or_username,
 
            short_contact=self.short_contact,
 
            full_contact=self.full_contact
 
        )
 

	
 

	
 
class UserLog(Base, BaseModel):
rhodecode/model/forms.py
Show inline comments
 
@@ -56,8 +56,12 @@ class ValidAuthToken(formencode.validato
 
    def validate_python(self, value, state):
 

	
 
        if value != authentication_token():
 
            raise formencode.Invalid(self.message('invalid_token', state,
 
                                            search_number=value), value, state)
 
            raise formencode.Invalid(
 
                self.message('invalid_token',
 
                             state, search_number=value),
 
                value,
 
                state
 
            )
 

	
 

	
 
def ValidUsername(edit, old_data):
 
@@ -77,11 +81,13 @@ def ValidUsername(edit, old_data):
 
                                               'exists') , value, state)
 

	
 
            if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
 
                raise formencode.Invalid(_('Username may only contain '
 
                                           'alphanumeric characters '
 
                                           'underscores, periods or dashes '
 
                                           'and must begin with alphanumeric '
 
                                           'character'), value, state)
 
                raise formencode.Invalid(
 
                    _('Username may only contain alphanumeric characters '
 
                      'underscores, periods or dashes and must begin with '
 
                      'alphanumeric character'), 
 
                    value, 
 
                    state
 
                )
 

	
 
    return _ValidUsername
 

	
 
@@ -107,11 +113,13 @@ def ValidUsersGroup(edit, old_data):
 
                                             state)
 

	
 
            if re.match(r'^[a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+$', value) is None:
 
                raise formencode.Invalid(_('RepoGroup name may only contain '
 
                                           'alphanumeric characters '
 
                                           'underscores, periods or dashes '
 
                                           'and must begin with alphanumeric '
 
                                           'character'), value, state)
 
                raise formencode.Invalid(
 
                    _('RepoGroup name may only contain  alphanumeric characters '
 
                      'underscores, periods or dashes and must begin with '
 
                      'alphanumeric character'), 
 
                    value, 
 
                    state
 
                )
 

	
 
    return _ValidUsersGroup
 

	
 
@@ -177,7 +185,8 @@ class ValidPassword(formencode.validator
 

	
 
    def to_python(self, value, state):
 

	
 
        if value:
 
        if not value:
 
            return
 

	
 
            if value.get('password'):
 
                try:
 
@@ -191,7 +200,9 @@ class ValidPassword(formencode.validator
 
                    value['password_confirmation'] = \
 
                        get_crypt_password(value['password_confirmation'])
 
                except UnicodeEncodeError:
 
                    e_dict = {'password_confirmation':_('Invalid characters in password')}
 
                e_dict = {
 
                    'password_confirmation': _('Invalid characters in password')
 
                }
 
                    raise formencode.Invalid('', value, state, error_dict=e_dict)
 

	
 
            if value.get('new_password'):
 
@@ -238,15 +249,19 @@ class ValidAuth(formencode.validators.Fa
 
        else:
 
            if user and user.active is False:
 
                log.warning('user %s is disabled', username)
 
                raise formencode.Invalid(self.message('disabled_account',
 
                raise formencode.Invalid(
 
                    self.message('disabled_account',
 
                                         state=State_obj),
 
                                         value, state,
 
                                         error_dict=self.e_dict_disable)
 
                    error_dict=self.e_dict_disable
 
                )
 
            else:
 
                log.warning('user %s not authenticated', username)
 
                raise formencode.Invalid(self.message('invalid_password',
 
                raise formencode.Invalid(
 
                    self.message('invalid_password',
 
                                         state=State_obj), value, state,
 
                                         error_dict=self.e_dict)
 
                    error_dict=self.e_dict
 
                )
 

	
 

	
 
class ValidRepoUser(formencode.validators.FancyValidator):
 
@@ -272,7 +287,6 @@ def ValidRepoName(edit, old_data):
 
                e_dict = {'repo_name': _('This repository name is disallowed')}
 
                raise formencode.Invalid('', value, state, error_dict=e_dict)
 

	
 

	
 
            if value.get('repo_group'):
 
                gr = RepoGroup.get(value.get('repo_group'))
 
                group_path = gr.full_path
 
@@ -285,7 +299,6 @@ def ValidRepoName(edit, old_data):
 
                group_path = ''
 
                repo_name_full = repo_name
 

	
 

	
 
            value['repo_name_full'] = repo_name_full
 
            rename = old_data.get('repo_name') != repo_name_full
 
            create = not edit
 
@@ -293,15 +306,17 @@ def ValidRepoName(edit, old_data):
 

	
 
                if group_path != '':
 
                    if Repository.get_by_repo_name(repo_name_full):
 
                        e_dict = {'repo_name':_('This repository already '
 
                                                'exists in a group "%s"') %
 
                                  gr.group_name}
 
                        e_dict = {
 
                            'repo_name': _('This repository already exists in '
 
                                           'a group "%s"') % gr.group_name
 
                        }
 
                        raise formencode.Invalid('', value, state,
 
                                                 error_dict=e_dict)
 
                elif RepoGroup.get_by_group_name(repo_name_full):
 
                        e_dict = {'repo_name':_('There is a group with this'
 
                                                ' name already "%s"') %
 
                                  repo_name_full}
 
                        e_dict = {
 
                            'repo_name': _('There is a group with this name '
 
                                           'already "%s"') % repo_name_full
 
                        }
 
                        raise formencode.Invalid('', value, state,
 
                                                 error_dict=e_dict)
 

	
 
@@ -341,14 +356,14 @@ def ValidCloneUri():
 
            elif value.startswith('https'):
 
                try:
 
                    httpsrepository(make_ui('db'), value).capabilities
 
                except Exception, e:
 
                except Exception:
 
                    log.error(traceback.format_exc())
 
                    raise formencode.Invalid(_('invalid clone url'), value,
 
                                             state)
 
            elif value.startswith('http'):
 
                try:
 
                    httprepository(make_ui('db'), value).capabilities
 
                except Exception, e:
 
                except Exception:
 
                    log.error(traceback.format_exc())
 
                    raise formencode.Invalid(_('invalid clone url'), value,
 
                                             state)
 
@@ -394,7 +409,8 @@ class ValidPerms(formencode.validators.F
 
            elif k.startswith('u_perm_') or k.startswith('g_perm_'):
 
                member = k[7:]
 
                t = {'u':'user',
 
                     'g':'users_group'}[k[0]]
 
                     'g': 'users_group'
 
                }[k[0]]
 
                if member == 'default':
 
                    if value['private']:
 
                        #set none for default when updating to private repo
 
@@ -419,8 +435,9 @@ class ValidPerms(formencode.validators.F
 
            except Exception:
 
                msg = self.message('perm_new_member_name',
 
                                     state=State_obj)
 
                raise formencode.Invalid(msg, value, state,
 
                                         error_dict={'perm_new_member_name':msg})
 
                raise formencode.Invalid(
 
                    msg, value, state, error_dict={'perm_new_member_name': msg}
 
                )
 
        return value
 

	
 

	
 
@@ -428,9 +445,8 @@ class ValidSettings(formencode.validator
 

	
 
    def to_python(self, value, state):
 
        # settings  form can't edit user
 
        if value.has_key('user'):
 
        if 'user' in value:
 
            del['value']['user']
 

	
 
        return value
 

	
 

	
 
@@ -452,8 +468,8 @@ def UniqSystemEmail(old_data):
 
                user = User.get_by_email(value, case_insensitive=True)
 
                if user:
 
                    raise formencode.Invalid(
 
                                    _("This e-mail address is already taken"),
 
                                    value, state)
 
                        _("This e-mail address is already taken"), value, state
 
                    )
 
            return value
 

	
 
    return _UniqSystemEmail
 
@@ -464,8 +480,9 @@ class ValidSystemEmail(formencode.valida
 
        value = value.lower()
 
        user = User.get_by_email(value, case_insensitive=True)
 
        if  user is None:
 
            raise formencode.Invalid(_("This e-mail address doesn't exist.") ,
 
                                     value, state)
 
            raise formencode.Invalid(
 
                _("This e-mail address doesn't exist."), value, state
 
            )
 

	
 
        return value
 

	
 
@@ -486,14 +503,15 @@ class AttrLoginValidator(formencode.vali
 
    def to_python(self, value, state):
 

	
 
        if not value or not isinstance(value, (str, unicode)):
 
            raise formencode.Invalid(_("The LDAP Login attribute of the CN "
 
                                       "must be specified - this is the name "
 
                                       "of the attribute that is equivalent "
 
                                       "to 'username'"),
 
                                     value, state)
 
            raise formencode.Invalid(
 
                _("The LDAP Login attribute of the CN must be specified - "
 
                  "this is the name of the attribute that is equivalent "
 
                  "to 'username'"), value, state
 
            )
 

	
 
        return value
 

	
 

	
 
#==============================================================================
 
# FORMS
 
#==============================================================================
 
@@ -531,15 +549,17 @@ def UserForm(edit=False, old_data={}):
 
                       ValidUsername(edit, old_data))
 
        if edit:
 
            new_password = All(UnicodeString(strip=True, min=6, not_empty=False))
 
            password_confirmation = All(UnicodeString(strip=True, min=6, not_empty=False))
 
            password_confirmation = All(UnicodeString(strip=True, min=6,
 
                                                      not_empty=False))
 
            admin = StringBoolean(if_missing=False)
 
        else:
 
            password = All(UnicodeString(strip=True, min=6, not_empty=True))
 
            password_confirmation = All(UnicodeString(strip=True, min=6, not_empty=False))
 
            password_confirmation = All(UnicodeString(strip=True, min=6,
 
                                                      not_empty=False))
 

	
 
        active = StringBoolean(if_missing=False)
 
        name = UnicodeString(strip=True, min=1, not_empty=True)
 
        lastname = UnicodeString(strip=True, min=1, not_empty=True)
 
        name = UnicodeString(strip=True, min=1, not_empty=False)
 
        lastname = UnicodeString(strip=True, min=1, not_empty=False)
 
        email = All(Email(not_empty=True), UniqSystemEmail(old_data))
 

	
 
        chained_validators = [ValidPasswordsMatch, ValidPassword]
 
@@ -592,14 +612,15 @@ def RegisterForm(edit=False, old_data={}
 
        password = All(UnicodeString(strip=True, min=6, not_empty=True))
 
        password_confirmation = All(UnicodeString(strip=True, min=6, not_empty=True))
 
        active = StringBoolean(if_missing=False)
 
        name = UnicodeString(strip=True, min=1, not_empty=True)
 
        lastname = UnicodeString(strip=True, min=1, not_empty=True)
 
        name = UnicodeString(strip=True, min=1, not_empty=False)
 
        lastname = UnicodeString(strip=True, min=1, not_empty=False)
 
        email = All(Email(not_empty=True), UniqSystemEmail(old_data))
 

	
 
        chained_validators = [ValidPasswordsMatch, ValidPassword]
 

	
 
    return _RegisterForm
 

	
 

	
 
def PasswordResetForm():
 
    class _PasswordResetForm(formencode.Schema):
 
        allow_extra_fields = True
 
@@ -607,6 +628,7 @@ def PasswordResetForm():
 
        email = All(ValidSystemEmail(), Email(not_empty=True))
 
    return _PasswordResetForm
 

	
 

	
 
def RepoForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
 
             repo_groups=[]):
 
    class _RepoForm(formencode.Schema):
 
@@ -630,6 +652,7 @@ def RepoForm(edit=False, old_data={}, su
 
        chained_validators = [ValidRepoName(edit, old_data), ValidPerms]
 
    return _RepoForm
 

	
 

	
 
def RepoForkForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
 
                 repo_groups=[]):
 
    class _RepoForkForm(formencode.Schema):
 
@@ -648,6 +671,7 @@ def RepoForkForm(edit=False, old_data={}
 

	
 
    return _RepoForkForm
 

	
 

	
 
def RepoSettingsForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(),
 
                     repo_groups=[]):
 
    class _RepoForm(formencode.Schema):
 
@@ -674,6 +698,7 @@ def ApplicationSettingsForm():
 

	
 
    return _ApplicationSettingsForm
 

	
 

	
 
def ApplicationUiSettingsForm():
 
    class _ApplicationUiSettingsForm(formencode.Schema):
 
        allow_extra_fields = True
 
@@ -687,6 +712,7 @@ def ApplicationUiSettingsForm():
 

	
 
    return _ApplicationUiSettingsForm
 

	
 

	
 
def DefaultPermissionsForm(perms_choices, register_choices, create_choices):
 
    class _DefaultPermissionsForm(formencode.Schema):
 
        allow_extra_fields = True
rhodecode/model/user.py
Show inline comments
 
@@ -92,7 +92,6 @@ class UserModel(BaseModel):
 
            log.error(traceback.format_exc())
 
            raise
 

	
 

	
 
    def create_or_update(self, username, password, email, name, lastname,
 
                         active=True, admin=False, ldap_dn=None):
 
        """
 
@@ -136,7 +135,6 @@ class UserModel(BaseModel):
 
            log.error(traceback.format_exc())
 
            raise
 

	
 

	
 
    def create_for_container_auth(self, username, attrs):
 
        """
 
        Creates the given user if it's not already in the database
 
@@ -493,7 +491,6 @@ class UserModel(BaseModel):
 
        new.permission = perm
 
        self.sa.add(new)
 

	
 

	
 
    def revoke_perm(self, user, perm):
 
        if not isinstance(perm, Permission):
 
            raise Exception('perm needs to be an instance of Permission class '
rhodecode/templates/admin/users/user_add.html
Show inline comments
 
@@ -86,7 +86,7 @@
 
                    <label for="active">${_('Active')}:</label>
 
                </div>
 
                <div class="checkboxes">
 
                    ${h.checkbox('active',value=True)}
 
                    ${h.checkbox('active',value=True,checked='checked')}
 
                </div>
 
             </div>
 

	
rhodecode/templates/base/base.html
Show inline comments
 
@@ -112,7 +112,7 @@
 
            ${h.end_form()}
 
        %else:
 
            <div class="links_left">
 
                <div class="full_name">${c.rhodecode_user.full_name}</div>
 
                <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
 
                <div class="email">${c.rhodecode_user.email}</div>
 
                <div class="big_gravatar"><img alt="gravatar" src="${h.gravatar_url(c.rhodecode_user.email,48)}" /></div>
 
            </div>
0 comments (0 inline, 0 general)