Esempio n. 1
0
def create_user():
    form = UserForm()
    if not form.validate_on_submit():
        return render_template('admin/form/user.html',
                               title='Create user',
                               form=form,
                               User=User,
                               password_length={
                                   'min': TRACKER_PASSWORD_LENGTH_MIN,
                                   'max': TRACKER_PASSWORD_LENGTH_MAX
                               })

    password = random_string(
    ) if not form.password.data else form.password.data
    salt = random_string()

    user = db.create(User,
                     name=form.username.data,
                     email=form.email.data,
                     salt=salt,
                     password=hash_password(password, salt),
                     role=UserRole.fromstring(form.role.data),
                     active=form.active.data)
    db.session.commit()

    flash('Created user {} with password {}'.format(user.name, password))
    return redirect('/user')
Esempio n. 2
0
def edit_user(username):
    own_user = username == current_user.name
    if not current_user.role.is_administrator and not own_user:
        forbidden()

    user = User.query.filter_by(name=username).first()
    if not user:
        return not_found()

    form = UserForm(edit=True)
    if not form.is_submitted():
        form.username.data = user.name
        form.email.data = user.email
        form.role.data = user.role.name
        form.active.data = user.active
    if not form.validate_on_submit():
        return render_template('admin/form/user.html',
                               title='Edit {}'.format(username),
                               form=form,
                               User=User,
                               random_password=True,
                               password_length={
                                   'min': TRACKER_PASSWORD_LENGTH_MIN,
                                   'max': TRACKER_PASSWORD_LENGTH_MAX
                               })

    active_admins = User.query.filter_by(active=True,
                                         role=UserRole.administrator).count()
    if user.id == current_user.id and 1 == active_admins and not form.active.data:
        return forbidden()

    user.name = form.username.data
    user.email = form.email.data
    user.role = UserRole.fromstring(form.role.data)
    if form.random_password.data:
        form.password.data = random_string()
    if form.password.data and 0 != len(form.password.data):
        user.salt = random_string()
        user.password = hash_password(form.password.data, user.salt)
    user.active = form.active.data
    user_invalidate(user)
    db.session.commit()

    flash_password = ''
    if form.random_password.data:
        flash_password = '******'.format(form.password.data)
    flash('Edited user {}{}'.format(user.name, flash_password))
    return redirect('/user')
Esempio n. 3
0
def user(username, email, password, role, active):
    """Create a new application user."""

    from tracker import db
    from tracker.user import hash_password
    from tracker.user import random_string

    user_by_name = db.get(User, name=username)
    if user_by_name:
        echo('Error: username already exists', err=True)
        exit(1)

    user_by_email = db.get(User, email=email)
    if user_by_email:
        echo('Error: e-mail already exists', err=True)
        exit(1)

    user = User()
    user.name = username
    user.email = email
    user.salt = random_string()
    user.password = hash_password(password, user.salt)
    user.role = UserRole.fromstring(role)
    user.active = active

    db.session.add(user)
    db.session.commit()
def test_password_repeat_mismatches(db, client):
    new_password = random_string()
    resp = client.post(url_for('tracker.edit_own_user_profile'), follow_redirects=True,
                       data=dict(password=new_password, password_repeat=new_password[::-1],
                                 password_current=DEFAULT_USERNAME))
    assert resp.status_code == 200
    assert ERROR_PASSWORD_REPEAT_MISMATCHES in resp.data.decode()
def test_current_password_incorrect(db, client):
    new_password = random_string()
    resp = client.post(url_for('tracker.edit_own_user_profile'), follow_redirects=True,
                       data=dict(password=new_password, password_repeat=new_password,
                                 password_current=new_password))
    assert resp.status_code == 200
    assert ERROR_PASSWORD_INCORRECT in resp.data.decode()
Esempio n. 6
0
def test_edit_user(db, client):
    new_password = random_string()
    new_email = '{}foo'.format(EMAIL)
    new_role = UserRole.security_team
    resp = client.post(url_for('tracker.edit_user', username=USERNAME),
                       follow_redirects=True,
                       data=dict(username=USERNAME,
                                 email=new_email,
                                 password=new_password,
                                 role=new_role.name,
                                 active=True))
    assert resp.status_code == 200

    resp = client.post(url_for('tracker.logout'), follow_redirects=True)
    assert_not_logged_in(resp)

    resp = client.post(url_for('tracker.login'),
                       follow_redirects=True,
                       data={
                           'username': USERNAME,
                           'password': new_password
                       })
    assert_logged_in(resp)
    assert USERNAME == current_user.name
    assert new_email == current_user.email
    assert new_role == current_user.role
Esempio n. 7
0
def validate_password(ctx, param, password):
    from tracker.user import random_string
    if not password or 'generated' == password:
        password = random_string()
        print('Generated password: {}'.format(password))
    if len(password) > TRACKER_PASSWORD_LENGTH_MAX or len(password) < TRACKER_PASSWORD_LENGTH_MIN:
        raise BadParameter('Error: password must be between {} and {} characters.'
                           .format(TRACKER_PASSWORD_LENGTH_MIN, TRACKER_PASSWORD_LENGTH_MAX))
    return password
Esempio n. 8
0
        def wrapper(db, *args, **kwargs):
            user = User()
            user.active = active
            user.name = username
            user.password = password if password else username
            user.role = role
            user.email = email if email else '{}@cyber.cyber'.format(username)
            user.salt = salt if salt else random_string()
            user.password = hash_password(user.password, user.salt)

            db.session.add(user)
            db.session.commit()
            func(db=db, *args, **kwargs)
Esempio n. 9
0
def edit_own_user_profile():
    form = UserPasswordForm()
    if not form.validate_on_submit():
        return render_template('form/profile.html',
                               title='Edit profile',
                               form=form,
                               password_length={'min': TRACKER_PASSWORD_LENGTH_MIN,
                                                'max': TRACKER_PASSWORD_LENGTH_MAX})

    user = current_user
    user.salt = random_string()
    user.password = hash_password(form.password.data, user.salt)
    db.session.commit()

    flash('Profile saved')
    return redirect('/')
Esempio n. 10
0
def sso_auth():
    try:
        token = oauth.idp.authorize_access_token()
        parsed_token = oauth.idp.parse_id_token(token)
    except AuthlibBaseError as e:
        return bad_request(f'{e.description}')

    idp_user_sub = parsed_token.get('sub')
    if not idp_user_sub:
        return bad_request(LOGIN_ERROR_MISSING_USER_SUB_FROM_TOKEN)

    idp_email_verified = parsed_token.get('email_verified')
    if not idp_email_verified:
        return forbidden(LOGIN_ERROR_EMAIL_ADDRESS_NOT_VERIFIED)

    idp_email = parsed_token.get('email')
    if not idp_email:
        return bad_request(LOGIN_ERROR_MISSING_EMAIL_FROM_TOKEN)

    idp_username = parsed_token.get('preferred_username')
    if not idp_username:
        return bad_request(LOGIN_ERROR_MISSING_USERNAME_FROM_TOKEN)

    idp_groups = parsed_token.get('groups')
    if idp_groups is None:
        return bad_request(LOGIN_ERROR_MISSING_GROUPS_FROM_TOKEN)

    user_role = get_user_role_from_idp_groups(idp_groups)
    if not user_role:
        return forbidden(LOGIN_ERROR_PERMISSION_DENIED)

    # get local user from current authenticated idp id
    user = db.get(User, idp_id=idp_user_sub)

    if not user:
        # get local user from idp email address
        user = db.get(User, email=idp_email)
        if user:
            # prevent impersonation by checking whether this email is associated with an idp id
            if user.idp_id:
                return forbidden(
                    LOGIN_ERROR_EMAIL_ASSOCIATED_WITH_DIFFERENT_SUB)
            # email is already associated with a different username
            if user.name != idp_username:
                return forbidden(
                    LOGIN_ERROR_EMAIL_ASSOCIATED_WITH_DIFFERENT_USERNAME)
        # prevent integrity error for mismatching mail between db and keycloak
        check_user = db.get(User, name=idp_username)
        if check_user and check_user.email != idp_email:
            return forbidden(
                LOGIN_ERROR_USERNAME_ASSOCIATE_WITH_DIFFERENT_EMAIL)

    if user:
        user.role = user_role
        user.email = idp_email
    else:
        salt = random_string()
        user = db.create(User,
                         name=idp_username,
                         email=idp_email,
                         salt=salt,
                         password=hash_password(
                             random_string(TRACKER_PASSWORD_LENGTH_MAX), salt),
                         role=user_role,
                         active=True,
                         idp_id=idp_user_sub)
        db.session.add(user)

    db.session.commit()
    user = user_assign_new_token(user)
    user.is_authenticated = True
    login_user(user)

    return redirect(url_for('tracker.index'))
Esempio n. 11
0
from werkzeug.exceptions import Unauthorized

from tracker.form.admin import ERROR_EMAIL_EXISTS
from tracker.form.admin import ERROR_USERNAME_EXISTS
from tracker.form.login import ERROR_ACCOUNT_DISABLED
from tracker.model.enum import UserRole
from tracker.user import random_string

from .conftest import DEFAULT_USERNAME
from .conftest import assert_logged_in
from .conftest import assert_not_logged_in
from .conftest import create_user
from .conftest import logged_in

USERNAME = '******'
PASSWORD = random_string()
EMAIL = '{}@cyber.cyber'.format(USERNAME)


@create_user(username=USERNAME, password=PASSWORD, role=UserRole.administrator)
@logged_in
def test_delete_user(db, client):
    resp = client.post(url_for('tracker.delete_user', username=USERNAME),
                       follow_redirects=True,
                       data=dict(confirm='confirm'))
    assert resp.status_code == 200

    resp = client.post(url_for('tracker.logout'), follow_redirects=True)
    assert_not_logged_in(resp)

    resp = client.post(url_for('tracker.login'),
Esempio n. 12
0
from wtforms import StringField
from wtforms import SubmitField
from wtforms.validators import DataRequired
from wtforms.validators import Length

from config import TRACKER_PASSWORD_LENGTH_MAX
from config import TRACKER_PASSWORD_LENGTH_MIN
from tracker.model.user import User
from tracker.user import hash_password
from tracker.user import random_string

from .base import BaseForm

ERROR_INVALID_USERNAME_PASSWORD = '******'
ERROR_ACCOUNT_DISABLED = 'Account is disabled.'
dummy_password = hash_password(random_string(), random_string())


class LoginForm(BaseForm):
    username = StringField(
        u'Username', validators=[DataRequired(),
                                 Length(max=User.NAME_LENGTH)])
    password = PasswordField(u'Password',
                             validators=[
                                 DataRequired(),
                                 Length(min=TRACKER_PASSWORD_LENGTH_MIN,
                                        max=TRACKER_PASSWORD_LENGTH_MAX)
                             ])
    login = SubmitField(u'login')

    def validate(self):