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')
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')
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()
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
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
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)
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('/')
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'))
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'),
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):