Example #1
0
def setUserStatus(userNameOrEmail, user_id):
    """After the user's login has authenticated, record some values
    in the session.
    
    user _str_: userNameOrEmail 
    user_id _int_: user record id
    user_name _str_: full name of user
    user_has_password _bool_: True if the user has a password
    
    also sets the globals:
    
    g.user = session["user]
    g.user_has_password = session["user_has_password"]
    
    """

    user = User(g.db)
    rec = user.get(user_id)
    if rec:
        user.update_last_access(rec.id)
        session["user"] = userNameOrEmail.strip()
        session['user_id'] = rec.id
        session["user_name"] = ""
        if rec.first_name:
            session['user_name'] = rec.first_name + " "
        if rec.last_name:
            session["user_name"] = session["user_name"] + rec.last_name
        session["user_name"] = session['user_name'].strip()
        g.user = session["user"]
        g.user_has_password = session['user_has_password'] = (
            rec.password != None and rec.password != '')
    else:
        flash("Unable to locate user")
Example #2
0
def display(path=""):
    setExits()
    g.title = "{} Record List".format(g.title)
    user = User(g.db)
    user_rank = user.max_role_rank(g.user)
    user_list = UserView(User, g.db)
    return user_list.dispatch_request(include_inactive=True,
                                      user_rank=user_rank)
Example #3
0
def validForm(rec):
    # Validate the form
    goodForm = True
    user = User(g.db)

    if request.form['email'].strip() == '':
        goodForm = False
        flash('Email may not be blank')

    if request.form['email'].strip() != '' and not looksLikeEmailAddress(
            request.form['email'].strip()):
        goodForm = False
        flash("That doesn't look like a valid email address")

    if request.form['email'].strip() != '':
        # always test lower case version of email
        found = user.get(request.form['email'].strip().lower(),
                         include_inactive=True)
        if found:
            if request.form['id'] == 'None' or found.id != int(
                    request.form['id']):
                goodForm = False
                flash('That email address is already in use')

    # user name must be unique if supplied
    if 'new_username' in request.form:
        if request.form['new_username'].strip() != '':
            found = user.get(request.form['new_username'].strip(),
                             include_inactive=True)
            if found:
                if request.form['id'] == 'None' or found.id != int(
                        request.form['id']):
                    goodForm = False
                    flash('That User Name is already in use')

        if request.form["new_username"].strip() != '' and request.form[
                "new_password"].strip() == '' and rec.password == '':
            goodForm = False
            flash('There must be a password if there is a User Name')

    if request.form["new_password"].strip() == '' and request.form[
            "confirm_password"].strip() != '' and rec.password != '':
        goodForm = False
        flash("You can't enter a blank password.")

    #passwords must match if present
    if request.form['confirm_password'].strip(
    ) != request.form['new_password'].strip():
        goodForm = False
        flash('Passwords don\'t match.')

    return goodForm
Example #4
0
def recover_password():
    """Send reset password and send user an email if they forget their password"""

    setExits()
    g.title = "Reset Password"
    rec = None
    temp_pass = None
    email_not_found = False

    if not request.form:
        pass
    else:
        #find the user with that email
        rec = User(g.db).select_one(where='lower(email) = lower("{}")'.format(
            request.form['email'].strip().lower()))
        if rec == None:
            flash(
                "That email address could not be found in the list of users.")
        else:
            # generate a new password that is unique to the system
            temp_pass = get_access_token()
            # save the temporary password
            rec.access_token = temp_pass
            rec.access_token_expires = time() + (3600 * 48)  # 2 days to reset
            User(g.db).save(rec)
            g.db.commit()

            # send an email with instructions
            from shotglass2.takeabeltof.mailer import send_message
            full_name = rec.first_name + " " + rec.last_name
            context = {
                'temp_pass': temp_pass,
                'rec': rec,
                'full_name': full_name
            }
            to_address_list = [
                (full_name, rec.email),
            ]
            result, msg = send_message(
                to_address_list,
                context=context,
                html_template='email/confirm_reset.html',
                text_template='email/confirm_reset.txt',
                subject='Confirm Password Reset')

    # Return a page telling user what we did
    return render_template('recover_password.html',
                           temp_pass=temp_pass,
                           rec=rec)
Example #5
0
def nogood_test_list_page(client):
    """Right now this fails missurably, but when it was 'working' it was operating on the live database instead
    of the temporary one like the docs implied it would."""
    with app.app.app_context():
        with client as c:
            from flask import session, g
            from shotglass2.users.models import User, Role
            import app
            print(app.app.config['DATABASE_PATH'])
            app.get_db(app.app.config['DATABASE_PATH'])
            # access without login
            result = c.get('/user/delete/3/', follow_redirects=True)
            assert result.status_code == 200
            assert b'Sorry. You do not have access to that page' in result.data

            rec = User(app.g.db).get('John')
            print(rec)

            # Login as user role
            result = c.post('/login/',
                            data={
                                'userNameOrEmail': 'John',
                                'password': '******'
                            },
                            follow_redirects=True)
            assert result.status == '200 OK'
            assert b'Invalid User Name or Password' not in result.data
            assert session['user'] == 'John'

            #attempt to delete a record
            result = c.get('/role/delete/3/', follow_redirects=True)
            assert result.status_code == 200
            assert b'Sorry. You do not have access to that page' in result.data
Example #6
0
def get_user_role_names(rec):
    user_roles = []
    roles = User(g.db).get_roles(rec.id)
    if roles:
        for x in roles:
            user_roles.append(x.name)

    return user_roles
Example #7
0
def test_user_creation():
    from shotglass2.users.models import User
    #create some user records
    user = User(db)
    
    rec = user.new()
    assert rec != None
    rec.first_name = 'Another'
    rec.last_name = 'User'
    rec.username = '******' # Spaces should be trimmed
    rec.email = '*****@*****.**'
    new_id = user.save(rec)
    assert new_id != None
    assert new_id > 0
    assert rec.active == 1 #test the default value
    assert rec.username == 'anotheruser'
    
    db.rollback()
Example #8
0
    def has_access(self, user_name, table=None):
        """Test to see if the user represented by user name has access to ANY admin items
        If a table class is specified, only check to see if user has access to that table
        
        If 'table' is a string, look for permissions by the display_name.
        Useful when testing the permissions from a template where the table object is not available.
        """
        from shotglass2.users.models import User

        if len(self.permissions) == 0:
            return False

        user = User(self.db)
        rec = user.get(user_name)
        if not rec or not user:
            return False

        user_roles = user.get_roles(rec.id)
        if not user_roles:
            return False

        temp_list = self.permissions
        if table:
            dict_item = 'table'
            try:
                if type(table) is str:
                    # Look up the table by display name
                    dict_item = 'display_name'

                temp_list = [x for x in temp_list if x[dict_item] == table]
            except:
                return False

        for role in user_roles:
            for list_item in temp_list:
                if role.name.lower() in list_item['roles']:
                    return True
                if list_item['minimum_rank_required'] <= role.rank:
                    return True

        return False
Example #9
0
def activate():
    """Allow administrator to activate a new user"""

    activate = request.args.get('activate', None)
    if activate:
        user = User(g.db)
        rec = user.select_one(
            where='access_token = "{}"'.format(activate.strip()))
        if rec:
            rec.active = 1
            rec.access_token = None
            rec.access_token_expires = None
            user.save(rec)
            g.db.commit()

            # inform user that their account is now active
            full_name = '{} {}'.format(rec.first_name, rec.last_name).strip()
            to = [(full_name, rec.email)]
            context = {
                'rec': rec,
            }
            subject = 'Account Activated'
            html_template = 'email/activation_complete.html'
            text_template = 'email/activation_complete.txt'
            send_message(to,
                         context=context,
                         subject=subject,
                         html_template=html_template,
                         text_template=text_template)

        else:
            flash("User not found with access_token: {}".format(activate))
            return redirect('/')

    else:
        flash("Activation code not in request args")
        return redirect('/')

    flash("New User Activation Successful")
    return edit(rec.id)
Example #10
0
def test_user_update():
    from shotglass2.users.models import User
    
    user = User(db)
    rec = user.get('doris')
    assert rec != None
    
    rec.email = '*****@*****.**'
    user.save(rec)
    rec = user.get('doris')
    assert rec.email == '*****@*****.**'
    
    db.rollback()
    
    #test the update() method of _Table
    rec = user.get('doris')
    d = {'id':233,'address':'1234 Some Street',}
    user.update(rec,d,True) #save to db
    rec = user.get('doris')
    assert rec.address == '1234 Some Street'
    assert rec.id != 233
        
    db.rollback()
Example #11
0
def get_access_token(token_length=24):
    """Return an access token that does not exist in the user table"""
    from shotglass2.users.models import User

    temp_rec = 'temp'
    while temp_rec != None:
        access_token = ""
        for x in range(token_length):
            access_token += random.choice(
                'abcdefghijklmnopqrstuvwxyz12344567890')
        #test that access_token is unique. break when rec == None
        temp_rec = User(
            g.db).select_one(where='access_token = "{}"'.format(access_token))

    return access_token
Example #12
0
def test_create_test_data():
    # Populate the test database
    from shotglass2.users.models import User
    try:
        f = open(abs_path('test_data_create.sql'), 'r')
        sql = f.read()
        f.close()
        cur = db.cursor()
        cur.executescript(sql)

        rec = User(db).get('doris')
        rec.password = getPasswordHash('password')
        User(db).save(rec)
        rec = User(db).get('John')
        rec.password = getPasswordHash('password')
        User(db).save(rec)
        db.commit()

        assert True == True

    except:
        assert True == False
Example #13
0
def test_user_delete():
    from shotglass2.users.models import User, Role
    
    user = User(db)
    record_deleted = user.delete(2)
    assert record_deleted == True
    record_deleted = user.delete('John')
    assert record_deleted == True
    record_deleted = user.delete('John') # can't delete it twice
    assert record_deleted == False
    record_deleted = user.delete('none') # test that we can delete an inactive record
    assert record_deleted == True
    record_deleted = Role(db).delete(1)
    assert record_deleted == True
    db.rollback()
Example #14
0
def authenticate_user(username, password, **kwargs):
    """
    Check username and password in db and return:
        0 = Authentication Failed
        1 = Authentication Succeeded
        2 = Need a password for this user
        -1 = User Inactive
        
    Optional kwargs:
        include_inactive = True
        login_on_success = True
    """

    include_inactive = kwargs.get('include_inactive', True)
    login_on_success = kwargs.get('login_on_success', True)

    result = 0

    #import pdb; pdb.set_trace()

    rec = User(g.db).get(username, include_inactive=include_inactive)

    if rec:
        if not rec.password:
            #User has no password, just login
            result = 1
        elif not password:
            #need a password for this user
            result = 2
        elif matchPasswordToHash(password, rec.password):
            result = 1
        if rec.active != 1:
            result = -1
        if result == 1 and rec.active == 1 and login_on_success:
            # use rec.username if there is one
            if rec.username:
                username = rec.username
            setUserStatus(username, rec.id)

    return result
Example #15
0
def login():
    setExits()
    g.user = g.get('user', None)
    next = request.args.get('next', request.form.get('next', ''))
    get_pass = request.form.get('get_pass', False)

    if g.user is not None:
        #flash("Already Logged in...")
        return redirect('/')

    if 'reset' in request.args:
        #Try to find the user record that requested a reset
        rec = User(g.db).select_one(where='access_token = "{}"'.format(
            request.args.get('reset', '')).strip())
        if rec and rec.access_token_expires > time():
            userNameOrEmail = rec.username
            if not userNameOrEmail:
                userNameOrEmail = rec.email
            setUserStatus(userNameOrEmail, rec.id)
            return redirect(url_for('user.edit'))
        else:
            flash("That reset request has expired")
            return redirect('/')

    if not request.form:
        if 'loginTries' not in session:
            session['loginTries'] = 0

    if request.form:
        if 'loginTries' not in session:
            #Testing that user agent is keeping cookies.
            #If not, there is no point in going on... Also, could be a bot.
            return render_template('no-cookies.html')

        result = authenticate_user(request.form["userNameOrEmail"],
                                   request.form.get('password'))
        if result == 2:
            # need to get password from user
            get_pass = True
        elif result != 0:
            session['loginTries'] = 0
            if result == -1:
                flash("Your account is inactive")
                return render_template('inactive.html')
            #import pdb;pdb.set_trace()
            if next:
                return redirect(next)
            return redirect('/')  #logged in...
        else:
            flash("Invalid User Name or Password")

    if 'loginTries' not in session:
        session['loginTries'] = 0

    #remember howmany times the user has tried to log in
    session['loginTries'] = session['loginTries'] + 1
    #slow down login attempts
    if session['loginTries'] > 5:
        sleep(session['loginTries'] / .8)

    return render_template('login.html',
                           form=request.form,
                           next=next,
                           get_pass=get_pass)
Example #16
0
def register():
    """Allow people to sign up thier own accounts on the web site"""
    setExits()
    site_config = get_site_config()

    g.title = "Account Registration"
    g.editURL = url_for('.register')
    g.listURL = '/'  # incase user cancels
    user = User(g.db)
    rec = user.new()

    is_admin = False
    user_roles = None
    roles = None
    no_delete = True
    success = True
    help = render_markdown_for("new_account_help.md", mod)
    next = request.form.get('next', request.args.get('next', ''))

    # import pdb;pdb.set_trace()

    if 'confirm' in request.args:
        #Try to find the user record that requested registration
        rec = user.select_one(where='access_token = "{}"'.format(
            request.args.get('confirm', '')).strip())
        if rec and rec.access_token_expires > time():
            if site_config.get('ACTIVATE_USER_ON_CONFIRMATION', False):
                rec.active = 1
                user.save(rec, commit=True)
                # log the user in
                setUserStatus(rec.email, rec.id)

            if rec.active == 1:
                success = "active"
            else:
                success = "waiting"

            #inform the admins
            inform_admin_of_registration(rec)

            return render_template('registration_success.html',
                                   success=success,
                                   next=next)
        else:
            flash("That registration request has expired")
            return redirect('/')

    if request.form:
        #update the record
        user.update(rec, request.form)

        if validForm(rec):
            rec.active = 0  # Self registered accounts are inactive by default
            set_password_from_form(rec)
            set_username_from_form(rec)
            rec.access_token = get_access_token()
            rec.access_token_expires = time() + (3600 * 48)
            if site_config.get('AUTOMATICALLY_ACTIVATE_NEW_USERS', False):
                rec.active = 1
                success = "active"

            try:
                user.save(rec)

                # give user default roles
                for role in site_config.get('DEFAULT_USER_ROLES', ['user']):
                    User(g.db).add_role(rec.id, role)

                g.db.commit()
                # log the user in
                setUserStatus(rec.email, rec.id)

                #inform the admins
                inform_admin_of_registration(rec)

                #Send confirmation email to user if not already active
                full_name = '{} {}'.format(rec.first_name,
                                           rec.last_name).strip()
                to = [(full_name, rec.email)]
                context = {'rec': rec, 'confirmation_code': rec.access_token}
                subject = 'Please confirm your account registration at {}'.format(
                    site_config['SITE_NAME'])
                html_template = 'email/registration_confirm.html'
                text_template = 'email/registration_confirm.txt'
                if rec.active == 1:
                    subject = 'Your account is now active at {}'.format(
                        site_config['SITE_NAME'])
                    html_template = 'email/activation_complete.html'
                    text_template = 'email/activation_complete.txt'

                send_message(to,
                             context=context,
                             subject=subject,
                             html_template=html_template,
                             text_template=text_template)

            except Exception as e:
                g.db.rollback()
                mes = "An error occured while new user was attempting to register"
                printException(mes, "error", e)
                # Send email to the administrator
                to = [(site_config['MAIL_DEFAULT_SENDER'],
                       site_config['MAIL_DEFAULT_ADDR'])]
                context = {'mes': mes, 'rec': rec, 'e': str(e)}
                body = "Signup Error\n{{context.mes}}\n{{context.e}}\nrec:\n{{context.rec}}"
                send_message(to, context=context, body=body, subject=mes)
                success = False

            return render_template(
                'registration_success.html',
                success=success,
                next=next,
            )

    return render_template(
        'user_edit.html',
        rec=rec,
        no_delete=no_delete,
        is_admin=is_admin,
        next=next,
    )
Example #17
0
def edit(rec_handle=None):
    setExits()
    g.title = "Edit {} Record".format(g.title)
    #import pdb;pdb.set_trace()
    site_config = get_site_config()

    user = User(g.db)
    rec = None
    request_rec_id = cleanRecordID(
        request.form.get('id', request.args.get('id', -1)))
    is_admin = g.admin.has_access(g.user, User)
    no_delete = not is_admin
    new_password = ''
    confirm_password = ''
    user_roles = ['user']  # default

    #limit roles to roles <= current users rank
    curr_user_max_rank = user.max_role_rank(g.user)
    roles = Role(g.db).select(where="rank <= {}".format(curr_user_max_rank))

    include_inactive = True
    next = request.form.get('next', request.args.get('next', ''))

    if not is_admin:
        g.listURL = g.homeURL  # Non admins can't see the list
        include_inactive = False

    if rec_handle != None:
        pass  #rec_handle has to come from admin() at this point
    elif rec_handle == None and g.user != None and request_rec_id == -1:
        rec_handle = g.user
    else:
        rec_handle = request_rec_id
        if rec_handle < 0:
            flash("That is not a valid User ID")
            return redirect(g.listURL)

    if not request.form:
        """ if no form object, send the form page """
        if rec_handle != g.user and not is_admin:
            flash("You do not have access to that area")
            return redirect(g.homeURL)
        elif curr_user_max_rank < user.max_role_rank(rec_handle):
            flash(
                "You don't have sufficiant privelages to edit that user record."
            )
            return redirect(g.homeURL)
        elif rec_handle == 0:
            rec = user.new()
        else:
            rec = user.get(rec_handle, include_inactive=include_inactive)
            if not rec:
                flash("Unable to locate user record")
                return redirect('/')

            user_roles = get_user_role_names(rec)

    else:
        #have the request form
        # import pdb;pdb.set_trace()
        is_new_user = False
        if rec_handle and request.form['id'] != 'None':
            rec = user.get(rec_handle, include_inactive=include_inactive)
            user_roles = get_user_role_names(rec)
        else:
            # its a new unsaved record
            is_new_user = True
            rec = user.new()
            user.update(rec, request.form)

        if validForm(rec):

            #Are we editing the current user's record?
            editingCurrentUser = ''
            if (g.user == rec.username):
                if 'new_username' in request.form:
                    editingCurrentUser = request.form['new_username'].strip()
                else:
                    editingCurrentUser = g.user
            else:
                if (g.user == rec.email):
                    editingCurrentUser = request.form['email'].strip()

            #update the record
            user.update(rec, request.form)

            # ensure these are ints
            if 'may_send_email' in rec._fields:
                rec.may_send_email = cleanRecordID(rec.may_send_email)
            if 'may_send_text' in rec._fields:
                rec.may_send_text = cleanRecordID(rec.may_send_text)

            set_username_from_form(rec)
            set_password_from_form(rec)

            try:
                user.save(rec)

                # update the user roles
                if 'roles_select' in request.form:
                    # import pdb;pdb.set_trace()
                    #delete all the users current roles
                    user.clear_roles(rec.id)
                    for role_name in request.form.getlist('roles_select'):
                        #find the role by name
                        role = Role(g.db).select_one(
                            where='name = "{}"'.format(role_name))
                        if role:
                            user.add_role(rec.id, role.id)

                # if the username or email address are the same as g.user
                # update g.user if it changes
                if (editingCurrentUser != ''):
                    setUserStatus(editingCurrentUser, rec.id)

                g.db.commit()

            except Exception as e:
                g.db.rollback()
                flash(
                    printException(
                        'Error attempting to save ' + g.title + ' record.',
                        "error", e))
                return redirect(g.listURL)

            if is_new_user:
                rec.access_token = get_access_token()
                rec.access_token_expires = time() + (3600 * 48)

                #inform the admins
                inform_admin_of_registration(rec)

                # send an email to welcome the new user
                full_name = '{} {}'.format(rec.first_name,
                                           rec.last_name).strip()

                context = {
                    'rec': rec,
                    'full_name': full_name,
                }
                to_address_list = [(full_name, rec.email)]
                sent, msg = send_message(
                    to_address_list,
                    subject="Welcome to {{ site_config.SITE_NAME}}",
                    context=context,
                    html_template='email/welcome.html',
                    text_template='email/welcome.txt',
                )
                if not sent:
                    flash('The welcome message could not be sent. Error: {}'.
                          format(msg))

            return redirect(g.listURL)

        else:
            # form did not validate, give user the option to keep their old password if there was one
            #need to restore the username
            user.update(rec, request.form)
            if 'new_username' in request.form:
                rec.username = request.form[
                    'new_username']  #preserve user input
            # preserve the selected roles
            #import pdb;pdb.set_trace()
            if 'roles_select' in request.form:
                user_roles = request.form.getlist('roles_select')
            #and password
            new_password = request.form.get('new_password', '')
            confirm_password = request.form.get('confirm_password', '')

    # display form
    return render_template(
        'user_edit.html',
        rec=rec,
        no_delete=no_delete,
        is_admin=is_admin,
        next=next,
        user_roles=user_roles,
        roles=roles,
        new_password=new_password,
        confirm_password=confirm_password,
    )
Example #18
0
def edit(rec_id=None):
    setExits()
    g.title = "Edit {} Record".format(g.title)

    role = PRIMARY_TABLE(g.db)
    rec = None
    super_user = User(g.db).user_has_role(session['user_id'], 'Super')
    no_delete = False

    rec_id = cleanRecordID(request.form.get('id', rec_id))

    if rec_id < 0:
        flash("That is not a valid ID")
        return redirect(g.listURL)

    if not request.form:
        """ if no form object, send the form page """
        if rec_id == 0:
            rec = role.new()
        else:
            rec = role.get(rec_id)
            if not rec:
                flash("Unable to locate that record")
                return redirect(g.listURL)
    else:
        #have the request form
        if rec_id and request.form['id'] != 'None':
            rec = role.get(rec_id)
        else:
            # its a new unsaved record
            # import pdb;pdb.set_trace()
            rec = role.new()
            role.update(rec, request.form)

        if validForm(rec):
            #update the record
            # import pdb;pdb.set_trace()
            # set default for locked
            rec.locked = 0
            role.update(rec, request.form)
            if request.form.get('locked'):
                rec.locked = 1

            try:
                role.save(rec)
                g.db.commit()
            except Exception as e:
                g.db.rollback()
                flash(
                    printException(
                        'Error attempting to save ' + g.title + ' record.',
                        "error", e))

            return redirect(g.listURL)

        else:
            # form did not validate
            pass

    if rec and rec.locked and not super_user:
        no_delete = True

    # display form
    return render_template('role_edit.html',
                           rec=rec,
                           super_user=super_user,
                           no_delete=no_delete)
Example #19
0
def test_user_get():
    import shotglass2.users.views.password as login
    from shotglass2.users.models import User
    
    #do some tests...
    user = User(db)
    rec = user.get(1)
    assert rec.username == 'admin'
    rec = user.get('admin')
    assert rec.username == 'admin'
    
    admin_roles = user.get_roles(rec.id)
    assert admin_roles != None
    assert len(admin_roles)>0
    assert admin_roles[0].name == "super"
    
    assert user.max_role_rank(1) == 1000;
    assert user.max_role_rank('admin') == 1000;
    
    # test that user admin is in admins
    assert user.is_admin('admin')
    assert user.is_admin(rec.id)
    
    #user John is not administrator
    rec = user.get('John')
    assert user.is_admin(rec.id) == False
        
    recs = user.select()
    assert len(recs) == 3
    # select inactive users too...
    recs = user.select(include_inactive=True)
    assert len(recs) == 4
    #ensure that inactive users are not returned with get
    rec = user.get('none')
    assert rec == None
    #and now we can...
    rec = user.get('none',include_inactive=True)
    assert rec.username == 'none'
    
    # user 'none' has no roles
    assert user.get_roles(rec.id) == None
    
    #add some roles for none
    user.add_role(rec.id,'user')
    assert user.get_roles(rec.id) != None
    
    #ensure that username is case sensitive
    rec = user.get('doris')
    assert rec.username == 'doris'
    rec = user.get('Doris')
    assert rec == None
    #get by email and NOT case sensitive
    rec = user.get('*****@*****.**')
    assert rec.last_name == "Goodman"
    rec = user.get('*****@*****.**')
    assert rec.last_name == "Goodman"
    #and that spaces are stripped
    rec = user.get(' [email protected] ')
    assert rec.last_name == "Goodman"
    #test a total miss
    assert user.get('something that doesnt exist') == None
    assert user.get(234343) == None