Beispiel #1
0
def _check_quota(req, up_type, info):
    """Check the user's quota. 'up_type' is a string such as 'upload'
    or 'copy', depending on how the file is being added. Only '-file'
    files are counted towards quota.

       (user_dir_size, status) = _check_quota(req, up_type, info)

    Returns an (int, str) tuple with the user's space usage and
    an empty string if underquota, the number -1 and a "you are
    over quota" page (as a string) if overquota. Note that the quota
    doesn't impede a user from going over it, it just disallows
    adding files after it has been exceeded. Worst case scenario
    uses up approximately 'quota + max upload size'.
    """
    import aux
    import logging
    user_dir_size = aux._get_dir_size(info)
    logging.debug('Space usage: %s/%s (%s)' % \
                      (user_dir_size, info['quota'], info['login_name']))
    if user_dir_size >= info['quota']:
        info['user_dir_size'] = user_dir_size
        info['details'] = aux._fill_str(info['quota_limit_blurb'], info)
        info['class'] = 'fail'
        info['status_button_1'] = aux._go_back_button(req, info['token'])
        info['status_button_2'] = ''
        logging.info('File %s forbidden due to quota limits (%s)' % \
                         (up_type, info['login_name']))
        info['title'] = up_type.capitalize()
        return (-1, aux._fill_page(info['status_page_'], info))
    else:
        return (user_dir_size, '')
Beispiel #2
0
def _update(req, info):
    import logging
    import re
    import time
    import manage_users
    import manage_kbasix
    import aux
    if '*' in info['allowed_internal_logins'] or \
            info['login_name'] in info['allowed_internal_logins']:
        allow_internal = True
    else:
        allow_internal = False
    profile = {}
    account = {}
    account['first_name'] = req.form['first_name'].value
    account['last_name'] = req.form['last_name'].value
    profile['user_email'] = req.form['user_email'].value
    err = 0
    info['details'] = ''
    if not re.match(info['valid_email_'], profile['user_email'], re.I):
        err += 1
        info['details'] += 'Please input a valid email address.<br>'
    if 'user_password' in req.form:
        info['user_password'] = req.form['user_password'].value
    else:
        info['user_password'] = ''
    info['user_ldap_password'] = req.form['user_ldap_password'].value
    info['user_ldap_name'] = req.form['user_ldap_name'].value
    was_external = manage_users._info(info['login_name'])['auth_method']
    if 'use_ldap' in req.form and info['user_ldap_password']:
        if not info['user_ldap_name']:
            err += 1
            info['details'] += 'Please fill out all the LDAP credentials.<br>'
        else:
                from register import _check_ldap
                info['ldap_server'] = req.form['ldap_server'].value
                if info['ldap_server']:
                    (err, info['details']) = _check_ldap(info, err)
                else:
                    err += 1
                    info['details'] += 'Please specify the LDAP server.<br>'
                if not err:
                    account['password'] = '******'
                    account['auth_method'] = 'ldap'
                    account['auth_server'] = info['ldap_server']
                    account['user_auth_name'] = info['user_ldap_name']
                    if not was_external:
                        info['details'] += 'Authentication is no longer internal.<br>'
    elif info['user_password'] and allow_internal:
        from register import _check_password
        info['user_password_check'] = req.form['user_password_check'].value
        (err, info['details']) = _check_password(info, err)
        if not err:
            account['auth_method'] = ''
            account['auth_server'] = account['user_auth_name'] = ''
            account['password'] = info['user_password']
            if was_external:
                info['details'] += 'Authentication is now internal.<br>'
    else:
        info['details'] += 'Note: no authentication changes made.<br>'
    if not err:
        try:
            manage_kbasix._account_mod(info['login_name'], 'profile', profile)
            manage_users._mod(info['login_name'], account)
        except Exception as reason:
            raise UpdateError(reason)
    if err:
        info['class'] = 'fail'
        info['status_button_1'] = aux._go_back_button(req, info['token'])
        info['status_button_2'] = ''
        logging.debug('Failed profile update because "%s" (%s)' % \
                          (info['details'].replace('<br>',' '), info['login_name']))
    else:
        info['class'] = 'success'
        info['details'] += aux._fill_str(info['successful_update_blurb'], info)
        if info['access'] == 'profile.py':
            info['status_button_1'] = """
          <form action="../login.py/process?start" method="post">
            <input type="submit" value="Login" />
          </form><br>
""" % info
        else:
            info['status_button_1'] = ''
        info['status_button_2'] = ''
        logging.debug('Successful profile update (%s)' % info['login_name'])
    info['title'] = 'User Profile'
    return aux._fill_page(info['status_page_'], info)
Beispiel #3
0
def _register(req, info):
    """Perform the registration process.

       _register(req, info)

    Returns the registration status page.
    """
    import logging
    import re
    import time
    import manage_users
    import manage_kbasix
    import aux
    # User names will be unique, case-insensitive and case-aware.
    info['user_name'] = req.form['user_name'].value
    info['login_name'] = info['user_name'].lower()
    logging.info('Registering new account for "%s"' % info['login_name'])
    if '*' in info['allowed_internal_logins'] or \
            info['login_name'] in info['allowed_internal_logins']:
        allow_internal = True
    else:
        allow_internal = False
    info['user_email'] = req.form['user_email'].value
    err = 0
    info['details'] = ''
    # KBasix is not yet tested on different locales, so we enforce
    # ASCII here.
    try:
        info['login_name'].encode('ascii')
        info['user_email'].encode('ascii')
    except:
        err += 1
        info['details'] += 'Your user name and email address must be \
ASCII.<br>'
    if info['login_name'] in info['reserved_login_names']:
        err += 1
        # This might be a lie, but the user need not know that.
        info['details'] += 'That user name is already taken.<br>'
    if info['login_name'] in info['blacklisted_login_names']:
        err += 1
        info['details'] += 'That user name is not permitted.<br>'
    # Keep in mind that, regardless of %(login_name_max_length)s, problems
    # may arise if the file paths are too long (this is an issue with
    # with the fact that the user name is present as part of the "world" 
    # URN). Note that there is a 100 character hard limit, regardless
    # of 'login_name_max_length'.
    if len(info['login_name']) > info['login_name_max_length']:
        err += 1
        info['details'] += 'That user name is too long.<br>'
    if not info['login_name'].isalnum():
        err += 1
        info['details'] += 'Your user name can only contain letters and/or \
numbers.<br>'
    # To avoid UID look-alike names we can set 'alpha_start_login_name'
    if info['alpha_start_login_name'] and len(info['login_name']) > 0 and \
            not info['login_name'][0].isalpha():
        err += 1
        info['details'] += 'The user name must begin with a letter.<br>'
    if len(info['user_email']) > info['email_max_length']:
        err += 1
        info['details'] += 'That email address is too long.<br>'
    if not re.match(info['valid_email_'], info['user_email'], re.I):
        err += 1
        info['details'] += 'Please input a valid email address.<br>'
    if 'use_ldap' in req.form:
        info['user_password'] = '******'
        info['auth_method'] = 'ldap'
        info['ldap_server'] = req.form['ldap_server'].value
        if info['ldap_server']:
            info['user_ldap_name'] = req.form['user_ldap_name'].value
            info['user_ldap_password'] = \
                req.form['user_ldap_password'].value
            (err, info['details']) = _check_ldap(info, err)
        else:
            err += 1
            info['details'] += 'Please specify the LDAP server.<br>'
    elif allow_internal:
        info['user_password'] = req.form['user_password'].value
        info['user_password_check'] = req.form['user_password_check'].value
        info['auth_method'] = ''
        info['ldap_server'] = info['user_ldap_name'] = ''
        (err, info['details']) = _check_password(info, err)
    else:
        err += 1
        info['details'] += 'Unavailable authentication scheme.<br>'
    if not err:
        deadline = time.time() + info['account_confirmation_timeout']
        try:
            (OK, dt) = manage_users._user_add(login_name = \
                                                  info['login_name'], \
                                                  password = \
                                                  info['user_password'], \
                                                  auth_method = \
                                                  info['auth_method'], \
                                                  user_auth_name = \
                                                  info['user_ldap_name'], \
                                                  auth_server = \
                                                  info['ldap_server'], \
                                                  expires = deadline)
            if OK:
                now = time.time()
                profile = {'registered': now, \
                               'login_name': info['login_name'], \
                               'user_name': info['user_name'], \
                               'user_email': info['user_email'], \
                               'quota': info['default_quota'], \
                               'last_login': now}
                manage_kbasix._account_add(info['login_name'], profile)
        except Exception as reason:
            raise RegisterError(reason)
        if not OK:
            err += 1
            info['details'] += dt
        else:
            try:
                _confirmation_email(req, info)
            except:
                err += 1
                info['details'] += 'Unable to send confirmation email.<br>'
    if err:
        info['class'] = 'fail'
        info['status_button_1'] = aux._go_back_button(req, info['token'])
        info['status_button_2'] = ''
        logging.info('Failed account registration for "%s" because "%s"' % \
                         (info['login_name'], \
                              info['details'].replace('<br>',' ')))
    else:
        info['class'] = 'success'
        info['details'] += \
            aux._fill_str(info['successful_registration_blurb'], info)
        info['status_button_1'] = ''
        info['status_button_2'] = ''
        logging.info('Successful account registration for "%s"' % \
                         info['login_name'])
    info['title'] = 'Registration'
    return aux._fill_page(info['status_page_'], info)
Beispiel #4
0
def _confirm_bulk_delete(req, info):
    """Query for a multiple file deletion confirmation.

       _confirm_bulk_delete(req, info)

    Returns a status page.
    """
    import logging
    import aux
    logging.debug('Bulk file deletion requested (%s)' % info['login_name'])
    info['title'] = 'Confirm the deletion of selected files'
    files = info['file_tags'] = ''
    n = 0
    if 'bulk' not in req.form or not req.form['bulk']:
        info['details'] = 'No files selected'
        info['class'] = 'warning'
        info['status_button_1'] = aux._go_back_button(req, info['token'])
        info['status_button_2'] = ''
        return aux._fill_page(info['status_page_'], info)
    for file_tag in req.form['bulk']:
        # When only one file is selected.
        if not isinstance(req.form['bulk'], list):
            file_tag = req.form['bulk'].value
        _check_file_tag(file_tag, info['login_name'])
        file_info = _get_file_info(file_tag, info)
        # We're not checking permissions on each file (see the
        # comment in '_confirm_delete'). It'd be a hassle to
        # mess up a carefully selected list of files to announce
        # some of them cannot be deleted, even if the final outcome is
        # the same i.e. getting rid of the file(s). In the end the file(s)
        # will not show up once the file managers refreshes, either
        # because they have been deleted or access to them denied.
        if file_info:
            info['file_tags'] += ' ' + file_tag
            files += file_info['file_name'] + '<br>'
            n += 1
        if not isinstance(req.form['bulk'], list): break
    if n == 0:
        # This could happen is one file is selected via checkbox having
        # been unshared from underneath the user.
        logging.warn('No deletable files found (%s)' % info['login_name'])
        info['class'] = 'warning'
        info['details'] = 'No files which you can delete were found.'
        info['status_button_1'] = """
          <form action="../file_manager.py/process?start" method="post">
            <input type="hidden" name="token" value="%(token)s" />
            <input type="submit" value="Back" />
          </form>
""" % info
        info['status_button_2'] = ''
        return aux._fill_page(info['status_page_'], info)
    elif n == 1:
        q = 'file'
    else:
        q = '%s files' % n
    info['details'] = 'Really delete the following %s?<br>%s' % (q, files)
    info['status_button_1'] = """
          <form action="../file_manager.py/process?action=delete"
            method="post">
            <input type="hidden" name="token" value="%(token)s" />
            <input type="hidden" name="file_tags" value="%(file_tags)s" />
            <input type="submit" value="Delete" />
          </form><br>
""" % info
    info['status_button_2'] = """
          <form action="../file_manager.py/process?start" method="post">
            <input type="hidden" name="token" value="%(token)s" />
            <input type="submit" value="Cancel" />
          </form>
""" % info
    info['class'] = 'information'
    return aux._fill_page(info['status_page_'], info)
Beispiel #5
0
def _register(req, info):
    """Perform the registration process.

       _register(req, info)

    Returns the registration status page.
    """
    import logging
    import re
    import time
    import manage_users
    import manage_kbasix
    import aux
    # User names will be unique, case-insensitive and case-aware.
    info['user_name'] = req.form['user_name'].value
    info['login_name'] = info['user_name'].lower()
    logging.info('Registering new account for "%s"' % info['login_name'])
    if '*' in info['allowed_internal_logins'] or \
            info['login_name'] in info['allowed_internal_logins']:
        allow_internal = True
    else:
        allow_internal = False
    info['user_email'] = req.form['user_email'].value
    err = 0
    info['details'] = ''
    # KBasix is not yet tested on different locales, so we enforce
    # ASCII here.
    try:
        info['login_name'].encode('ascii')
        info['user_email'].encode('ascii')
    except:
        err += 1
        info['details'] += 'Your user name and email address must be \
ASCII.<br>'

    if info['login_name'] in info['reserved_login_names']:
        err += 1
        # This might be a lie, but the user need not know that.
        info['details'] += 'That user name is already taken.<br>'
    if info['login_name'] in info['blacklisted_login_names']:
        err += 1
        info['details'] += 'That user name is not permitted.<br>'
    # Keep in mind that, regardless of %(login_name_max_length)s, problems
    # may arise if the file paths are too long (this is an issue with
    # with the fact that the user name is present as part of the "world"
    # URN). Note that there is a 100 character hard limit, regardless
    # of 'login_name_max_length'.
    if len(info['login_name']) > info['login_name_max_length']:
        err += 1
        info['details'] += 'That user name is too long.<br>'
    if not info['login_name'].isalnum():
        err += 1
        info['details'] += 'Your user name can only contain letters and/or \
numbers.<br>'

    # To avoid UID look-alike names we can set 'alpha_start_login_name'
    if info['alpha_start_login_name'] and len(info['login_name']) > 0 and \
            not info['login_name'][0].isalpha():
        err += 1
        info['details'] += 'The user name must begin with a letter.<br>'
    if len(info['user_email']) > info['email_max_length']:
        err += 1
        info['details'] += 'That email address is too long.<br>'
    if not re.match(info['valid_email_'], info['user_email'], re.I):
        err += 1
        info['details'] += 'Please input a valid email address.<br>'
    if 'use_ldap' in req.form:
        info['user_password'] = '******'
        info['auth_method'] = 'ldap'
        info['ldap_server'] = req.form['ldap_server'].value
        if info['ldap_server']:
            info['user_ldap_name'] = req.form['user_ldap_name'].value
            info['user_ldap_password'] = \
                req.form['user_ldap_password'].value
            (err, info['details']) = _check_ldap(info, err)
        else:
            err += 1
            info['details'] += 'Please specify the LDAP server.<br>'
    elif allow_internal:
        info['user_password'] = req.form['user_password'].value
        info['user_password_check'] = req.form['user_password_check'].value
        info['auth_method'] = ''
        info['ldap_server'] = info['user_ldap_name'] = ''
        (err, info['details']) = _check_password(info, err)
    else:
        err += 1
        info['details'] += 'Unavailable authentication scheme.<br>'
    if not err:
        deadline = time.time() + info['account_confirmation_timeout']
        try:
            (OK, dt) = manage_users._user_add(login_name = \
                                                  info['login_name'], \
                                                  password = \
                                                  info['user_password'], \
                                                  auth_method = \
                                                  info['auth_method'], \
                                                  user_auth_name = \
                                                  info['user_ldap_name'], \
                                                  auth_server = \
                                                  info['ldap_server'], \
                                                  expires = deadline)
            if OK:
                now = time.time()
                profile = {'registered': now, \
                               'login_name': info['login_name'], \
                               'user_name': info['user_name'], \
                               'user_email': info['user_email'], \
                               'quota': info['default_quota'], \
                               'last_login': now}
                manage_kbasix._account_add(info['login_name'], profile)
        except Exception as reason:
            raise RegisterError(reason)
        if not OK:
            err += 1
            info['details'] += dt
        else:
            try:
                _confirmation_email(req, info)
            except:
                err += 1
                info['details'] += 'Unable to send confirmation email.<br>'
    if err:
        info['class'] = 'fail'
        info['status_button_1'] = aux._go_back_button(req, info['token'])
        info['status_button_2'] = ''
        logging.info('Failed account registration for "%s" because "%s"' % \
                         (info['login_name'], \
                              info['details'].replace('<br>',' ')))
    else:
        info['class'] = 'success'
        info['details'] += \
            aux._fill_str(info['successful_registration_blurb'], info)
        info['status_button_1'] = ''
        info['status_button_2'] = ''
        logging.info('Successful account registration for "%s"' % \
                         info['login_name'])
    info['title'] = 'Registration'
    return aux._fill_page(info['status_page_'], info)
Beispiel #6
0
def _confirm_bulk_delete(req, info):
    """Query for a multiple file deletion confirmation.

       _confirm_bulk_delete(req, info)

    Returns a status page.
    """
    import logging
    import aux
    logging.debug('Bulk file deletion requested (%s)' % info['login_name'])
    info['title'] = 'Confirm the deletion of selected files'
    files = info['file_tags'] = ''
    n = 0
    if 'bulk' not in req.form or not req.form['bulk']:
        info['details'] = 'No files selected'
        info['class'] = 'warning'
        info['status_button_1'] = aux._go_back_button(req, info['token'])
        info['status_button_2'] = ''
        return aux._fill_page(info['status_page_'], info)
    for file_tag in req.form['bulk']:
        # When only one file is selected.
        if not isinstance(req.form['bulk'], list):
            file_tag = req.form['bulk'].value
        _check_file_tag(file_tag, info['login_name'])
        file_info = _get_file_info(file_tag, info)
        # We're not checking permissions on each file (see the
        # comment in '_confirm_delete'). It'd be a hassle to
        # mess up a carefully selected list of files to announce
        # some of them cannot be deleted, even if the final outcome is
        # the same i.e. getting rid of the file(s). In the end the file(s)
        # will not show up once the file managers refreshes, either
        # because they have been deleted or access to them denied.
        if file_info:
            info['file_tags'] += ' ' + file_tag
            files += file_info['file_name'] + '<br>'
            n += 1
        if not isinstance(req.form['bulk'], list): break
    if n == 0:
        # This could happen is one file is selected via checkbox having
        # been unshared from underneath the user.
        logging.warn('No deletable files found (%s)' % info['login_name'])
        info['class'] = 'warning'
        info['details'] = 'No files which you can delete were found.'
        info['status_button_1'] = """
          <form action="../file_manager.py/process?start" method="post">
            <input type="hidden" name="token" value="%(token)s" />
            <input type="submit" value="Back" />
          </form>
""" % info
        info['status_button_2'] = ''
        return aux._fill_page(info['status_page_'], info)
    elif n == 1:
        q = 'file'
    else:
        q = '%s files' % n
    info['details'] = 'Really delete the following %s?<br>%s' % (q, files)
    info['status_button_1'] = """
          <form action="../file_manager.py/process?action=delete"
            method="post">
            <input type="hidden" name="token" value="%(token)s" />
            <input type="hidden" name="file_tags" value="%(file_tags)s" />
            <input type="submit" value="Delete" />
          </form><br>
""" % info
    info['status_button_2'] = """
          <form action="../file_manager.py/process?start" method="post">
            <input type="hidden" name="token" value="%(token)s" />
            <input type="submit" value="Cancel" />
          </form>
""" % info
    info['class'] = 'information'
    return aux._fill_page(info['status_page_'], info)
Beispiel #7
0
def _login(req, info):
    """Try to login the user, or send an email token if the password is
    forgotten.

       _login(req, info)

    Returns a status page.
    """
    if 'forgot_password' in req.form:
        try:
            return _send_token(req, info)
        except Exception as reason:
            raise SendTokenError(reason)
    import logging
    from mod_python import apache
    import manage_users
    import manage_kbasix
    import time
    import aux
    from mod_python import util
    logging.debug('Starting login process for "%s"' % info['login_name'])
    if '*' in info['allowed_internal_logins'] or \
            info['login_name'] in info['allowed_internal_logins']:
        allow_internal = True
    else:
        allow_internal = False
    password = req.form['user_password'].value
    # Note that '_authenticate' only returns the uid if 'is_usr' is
    # True, otherwise it'll return a keyword specifying the authentication
    # failure point.
    try:
        (is_usr, status) = manage_users._authenticate(info['login_name'], \
                                                          password)
        logging.info('Authentication for "%s" was "%s" with \
status/uid: %s' % (info['login_name'], is_usr, status))
    except Exception as reason:
        raise LoginError(reason)
    blocked = False
    # We don't just show the reasons for authentication failures, but
    # instead use codes defined in 'defs.py' (the log is explicit in this
    # respect).
    if is_usr:
        uid = status
        locked = manage_users._info(info['login_name'])['locked']
        if locked:
            blocked = True
            msg = info['reason_not_active_']
    else:
        blocked = True
        msg = info['reason_auth_fail_']
    if not blocked:
        auth_method = manage_users._info(info['login_name'])['auth_method']
        # An empty 'auth_method' means the auth is internal.
        if not auth_method and not allow_internal:
            blocked = True
            msg = info['reason_not_allowed_']
        elif info['login_name'] in info['banned_logins']:
            blocked = True
            msg = info['reason_banned_']
    if not blocked:
        try:
            info['token'] = manage_kbasix._create_token(req, uid)
            info['user_name'] = \
                manage_kbasix._account_info(info['login_name'], \
                                                'profile')['user_name']
            info['access'] = 'all'
            info['class'] = 'information'
            info['main_header'] = aux._make_header(info)
            info['title'] = aux._fill_str(info['welcome_title'], info)
            info['details'] = aux._fill_str(info['welcome_blurb'], info)
            info['status_button_1'] = """
<form action="../%(referrer)s/process?start" method="post">
<input type="hidden" name="token" value="%(token)s">
<input type="submit" value="Continue" />
</form>
""" % info
            info['status_button_2'] = ''
            manage_kbasix._account_mod(info['login_name'], \
                                           'profile', {'last_login': \
                                                           time.time()})
            logging.info('Successful login from %s (%s)' % \
                             (req.get_remote_host(apache.REMOTE_NOLOOKUP), \
                                  info['login_name']))
            return aux._fill_page(info['status_page_'], info)
        except Exception as reason:
            raise LoginError(reason)
    else:
        info['class'] = 'fail'
        info['title'] = 'Login'
        info['details'] = aux._fill_str(msg, info)
        info['status_button_1'] = aux._go_back_button(req, token = '')
        info['status_button_2'] = ''
        logging.info('Failed login for "%s" because "%s"' % \
                         (info['login_name'], info['details']))
        return aux._fill_page(info['status_page_'], info)
Beispiel #8
0
def _update(req, info):
    import logging
    import re
    import time
    import manage_users
    import manage_kbasix
    import aux
    if '*' in info['allowed_internal_logins'] or \
            info['login_name'] in info['allowed_internal_logins']:
        allow_internal = True
    else:
        allow_internal = False
    profile = {}
    account = {}
    account['first_name'] = req.form['first_name'].value
    account['last_name'] = req.form['last_name'].value
    profile['user_email'] = req.form['user_email'].value
    err = 0
    info['details'] = ''
    if not re.match(info['valid_email_'], profile['user_email'], re.I):
        err += 1
        info['details'] += 'Please input a valid email address.<br>'
    if 'user_password' in req.form:
        info['user_password'] = req.form['user_password'].value
    else:
        info['user_password'] = ''
    info['user_ldap_password'] = req.form['user_ldap_password'].value
    info['user_ldap_name'] = req.form['user_ldap_name'].value
    was_external = manage_users._info(info['login_name'])['auth_method']
    if 'use_ldap' in req.form and info['user_ldap_password']:
        if not info['user_ldap_name']:
            err += 1
            info['details'] += 'Please fill out all the LDAP credentials.<br>'
        else:
            from register import _check_ldap
            info['ldap_server'] = req.form['ldap_server'].value
            if info['ldap_server']:
                (err, info['details']) = _check_ldap(info, err)
            else:
                err += 1
                info['details'] += 'Please specify the LDAP server.<br>'
            if not err:
                account['password'] = '******'
                account['auth_method'] = 'ldap'
                account['auth_server'] = info['ldap_server']
                account['user_auth_name'] = info['user_ldap_name']
                if not was_external:
                    info[
                        'details'] += 'Authentication is no longer internal.<br>'
    elif info['user_password'] and allow_internal:
        from register import _check_password
        info['user_password_check'] = req.form['user_password_check'].value
        (err, info['details']) = _check_password(info, err)
        if not err:
            account['auth_method'] = ''
            account['auth_server'] = account['user_auth_name'] = ''
            account['password'] = info['user_password']
            if was_external:
                info['details'] += 'Authentication is now internal.<br>'
    else:
        info['details'] += 'Note: no authentication changes made.<br>'
    if not err:
        try:
            manage_kbasix._account_mod(info['login_name'], 'profile', profile)
            manage_users._mod(info['login_name'], account)
        except Exception as reason:
            raise UpdateError(reason)
    if err:
        info['class'] = 'fail'
        info['status_button_1'] = aux._go_back_button(req, info['token'])
        info['status_button_2'] = ''
        logging.debug('Failed profile update because "%s" (%s)' % \
                          (info['details'].replace('<br>',' '), info['login_name']))
    else:
        info['class'] = 'success'
        info['details'] += aux._fill_str(info['successful_update_blurb'], info)
        if info['access'] == 'profile.py':
            info['status_button_1'] = """
          <form action="../login.py/process?start" method="post">
            <input type="submit" value="Login" />
          </form><br>
""" % info
        else:
            info['status_button_1'] = ''
        info['status_button_2'] = ''
        logging.debug('Successful profile update (%s)' % info['login_name'])
    info['title'] = 'User Profile'
    return aux._fill_page(info['status_page_'], info)