예제 #1
0
def signup():

    if not current_app.config['SIGNUP_ENABLED']:
        raise ApiError('user signup is disabled', 403)

    try:
        user = User.parse(request.json)
    except Exception as e:
        raise ApiError(str(e), 400)

    # set sign-up defaults
    user.roles = ['user']
    user.email_verified = False

    # check allowed domain
    if not_authorized('ALLOWED_EMAIL_DOMAINS', groups=[user.domain]):
        raise ApiError('unauthorized domain', 403)

    if User.find_by_email(email=user.email):
        raise ApiError('username already exists', 409)

    try:
        user = user.create()
    except Exception as e:
        ApiError(str(e), 500)

    # if email verification is enforced, deny login and send email
    if current_app.config['EMAIL_VERIFICATION'] and not user.email_verified:
        user.send_confirmation()
        raise ApiError('email not verified', 403)

    # check user is active & update last login
    if user.status != 'active':
        raise ApiError('user not active', 403)
    user.update_last_login()

    # assign customers
    customers = get_customers(user.email, groups=[user.domain])

    auth_audit_trail.send(current_app._get_current_object(),
                          event='basic-auth-signup',
                          message='user signup using BasicAuth',
                          user=user.email,
                          customers=customers,
                          scopes=Permission.lookup(user.email,
                                                   groups=user.roles),
                          resource_id=user.id,
                          type='user',
                          request=request)

    # generate token
    token = create_token(user_id=user.id,
                         name=user.name,
                         login=user.email,
                         provider='basic',
                         customers=customers,
                         roles=user.roles,
                         email=user.email,
                         email_verified=user.email_verified)
    return jsonify(token=token.tokenize)
예제 #2
0
파일: users.py 프로젝트: guardian/alerta
def update_user(user_id):
    if not request.json:
        raise ApiError('nothing to change', 400)

    user = User.find_by_id(user_id)

    if not user:
        raise ApiError('not found', 404)

    if request.json.get('email'):
        user_by_email = User.find_by_email(request.json['email'])
        if user_by_email and user_by_email.id != user.id:
            raise ApiError('user with that email already exists', 409)

    if request.json.get('roles'):
        want_scopes = Permission.lookup(login='', roles=request.json['roles'])
        for want_scope in want_scopes:
            if not Permission.is_in_scope(want_scope, have_scopes=g.scopes):
                raise ApiError("Requested scope '{}' not in existing scopes: {}".format(
                    want_scope, ','.join(g.scopes)), 403)

    admin_audit_trail.send(current_app._get_current_object(), event='user-updated', message='', user=g.login,
                           customers=g.customers, scopes=g.scopes, resource_id=user.id, type='user', request=request)

    if user.update(**request.json):
        return jsonify(status='ok')
    else:
        raise ApiError('failed to update user', 500)
예제 #3
0
def create_user():
    try:
        user = User.parse(request.json)
    except Exception as e:
        raise ApiError(str(e), 400)

    # check allowed domain
    if not_authorized('ALLOWED_EMAIL_DOMAINS', groups=[user.domain]):
        raise ApiError('unauthorized domain', 403)

    if User.find_by_email(email=user.email):
        raise ApiError('username already exists', 409)

    try:
        user = user.create()
    except Exception as e:
        ApiError(str(e), 500)

    # if email verification is enforced, send confirmation email
    if current_app.config['EMAIL_VERIFICATION'] and not user.email_verified:
        user.send_confirmation()

    admin_audit_trail.send(current_app._get_current_object(), event='user-created', message='', user=g.user,
                           customers=g.customers, scopes=g.scopes, resource_id=user.id, type='user', request=request)

    if user:
        return jsonify(status='ok', id=user.id, user=user.serialize), 201
    else:
        raise ApiError('create user failed', 500)
예제 #4
0
def search_users():
    query = qb.from_params(request.args)
    users = User.find_all(query)

    # add admins defined in server config
    if 'admin' in request.args.getlist('roles'):
        for admin in set(current_app.config['ADMIN_USERS']):
            user = User.find_by_email(admin)
            if user:
                users.append(user)

    # remove admins whose default role is 'user'
    if 'admin' not in request.args.getlist('roles'):
        users = [u for u in users if 'admin' not in u.roles]

    if users:
        return jsonify(status='ok',
                       users=[user.serialize for user in users],
                       domains=current_app.config['ALLOWED_EMAIL_DOMAINS'],
                       total=len(users))
    else:
        return jsonify(status='ok',
                       message='not found',
                       users=[],
                       domains=current_app.config['ALLOWED_EMAIL_DOMAINS'],
                       total=0)
예제 #5
0
파일: users.py 프로젝트: guardian/alerta
def update_me():
    if not request.json:
        raise ApiError('nothing to change', 400)

    if 'roles' in request.json:
        raise ApiError('not allowed to update roles', 400)
    if 'email_verified' in request.json:
        raise ApiError('not allowed to set email verified', 400)

    user = User.find_by_id(g.user_id)

    if not user:
        raise ApiError('not found', 404)

    if 'email' in request.json:
        user_by_email = User.find_by_email(email=request.json['email'])
        if user_by_email and user_by_email.id != user.id:
            raise ApiError('user with that email already exists', 409)

    write_audit_trail.send(current_app._get_current_object(), event='user-me-updated', message='', user=g.login,
                           customers=g.customers, scopes=g.scopes, resource_id=user.id, type='user', request=request)

    if user.update(**request.json):
        return jsonify(status='ok')
    else:
        raise ApiError('failed to update user', 500)
예제 #6
0
파일: basic.py 프로젝트: guardian/alerta
def signup():

    if not current_app.config['SIGNUP_ENABLED']:
        raise ApiError('user signup is disabled', 403)

    try:
        user = User.parse(request.json)
    except Exception as e:
        raise ApiError(str(e), 400)

    # set sign-up defaults
    user.roles = ['user']
    user.email_verified = False

    # check allowed domain
    if not_authorized('ALLOWED_EMAIL_DOMAINS', groups=[user.domain]):
        raise ApiError('unauthorized domain', 403)

    if User.find_by_username(username=user.email):
        raise ApiError('user with that email already exists', 409)

    try:
        user = user.create()
    except Exception as e:
        ApiError(str(e), 500)

    # if email verification is enforced, deny login and send email
    if current_app.config['EMAIL_VERIFICATION'] and not user.email_verified:
        user.send_confirmation()
        raise ApiError('email not verified', 403)

    # check user is active & update last login
    if user.status != 'active':
        raise ApiError('User {} not active'.format(user.login), 403)
    user.update_last_login()

    groups = [g.name for g in user.get_groups()]
    scopes = Permission.lookup(login=user.login, roles=user.roles + groups)
    customers = get_customers(login=user.login, groups=[user.domain] + groups)

    auth_audit_trail.send(current_app._get_current_object(), event='basic-auth-signup', message='user signup using BasicAuth',
                          user=user.login, customers=customers, scopes=scopes,
                          resource_id=user.id, type='user', request=request)

    # generate token
    token = create_token(user_id=user.id, name=user.name, login=user.login, provider='basic',
                         customers=customers, scopes=scopes, roles=user.roles, groups=groups,
                         email=user.email, email_verified=user.email_verified)
    return jsonify(token=token.tokenize)
예제 #7
0
 def create_user(name, login):
     email = login if '@' in login else None
     user = User(name=name or login,
                 login=login,
                 password=generate_password_hash(password),
                 roles=current_app.config['ADMIN_ROLES'],
                 text=text,
                 email=email,
                 email_verified=bool(email))
     try:
         user = user.create()
     except Exception as e:
         click.echo(f'ERROR: {e}')
     else:
         return user
예제 #8
0
def create_user():
    if current_app.config['AUTH_PROVIDER'] != 'basic':
        raise ApiError(
            'must use {} login flow to create new user'.format(
                current_app.config['AUTH_PROVIDER']), 400)

    try:
        user = User.parse(request.json)
    except Exception as e:
        raise ApiError(str(e), 400)

    # check allowed domain
    if not_authorized('ALLOWED_EMAIL_DOMAINS', groups=[user.domain]):
        raise ApiError('unauthorized domain', 403)

    if User.find_by_username(username=user.email):
        raise ApiError('user with that email already exists', 409)

    want_scopes = Permission.lookup(login=user.email, roles=user.roles)
    for want_scope in want_scopes:
        if not Permission.is_in_scope(want_scope, have_scopes=g.scopes):
            raise ApiError(
                "Requested scope '{}' not in existing scopes: {}".format(
                    want_scope, ','.join(g.scopes)), 403)

    try:
        user = user.create()
    except Exception as e:
        ApiError(str(e), 500)

    # if email verification is enforced, send confirmation email
    if current_app.config['EMAIL_VERIFICATION'] and not user.email_verified:
        user.send_confirmation()

    admin_audit_trail.send(current_app._get_current_object(),
                           event='user-created',
                           message='',
                           user=g.login,
                           customers=g.customers,
                           scopes=g.scopes,
                           resource_id=user.id,
                           type='user',
                           request=request)

    if user:
        return jsonify(status='ok', id=user.id, user=user.serialize), 201
    else:
        raise ApiError('create user failed', 500)
예제 #9
0
파일: commands.py 프로젝트: 3IWOH/alerta
 def create_user(admin):
     user = User(
         name=admin,
         email=admin,
         password=generate_password_hash(password),
         roles=None,
         text='Admin user created by alertad script',
         email_verified=True
     )
     try:
         db.get_db()  # init db on global app context
         user = user.create()
     except Exception as e:
         click.echo('ERROR: {}'.format(e))
     else:
         click.echo('{} {}'.format(user.id, user.name))
예제 #10
0
파일: users.py 프로젝트: 3IWOH/alerta
def update_user(user_id):
    if not request.json:
        raise ApiError("nothing to change", 400)

    user = User.find_by_id(user_id)

    if not user:
        raise ApiError("not found", 404)

    if 'email' in request.json and User.find_by_email(request.json['email']):
        raise ApiError("user with email already exists", 409)

    if user.update(**request.json):
        return jsonify(status="ok")
    else:
        raise ApiError("failed to update user", 500)
예제 #11
0
파일: users.py 프로젝트: guardian/alerta
def get_me_attributes():
    user = User.find_by_id(g.user_id)

    if user:
        return jsonify(status='ok', total=1, attributes=user.attributes)
    else:
        raise ApiError('not found', 404)
예제 #12
0
파일: users.py 프로젝트: guardian/alerta
def get_user(user_id):
    user = User.find_by_id(user_id)

    if user:
        return jsonify(status='ok', total=1, user=user.serialize)
    else:
        raise ApiError('not found', 404)
예제 #13
0
 def create_user(admin):
     email = admin if '@' in admin else None
     user = User(name='Admin user',
                 login=admin,
                 password=generate_password_hash(password),
                 roles=['admin'],
                 text='Created by alertad script',
                 email=email,
                 email_verified=bool(email))
     try:
         db.get_db()  # init db on global app context
         user = user.create()
     except Exception as e:
         click.echo('ERROR: {}'.format(e))
     else:
         click.echo('{} {}'.format(user.id, user.name))
예제 #14
0
def login():
    # lookup user from username/email
    try:
        username = request.json.get('username', None) or request.json['email']
        password = request.json['password']
    except KeyError:
        raise ApiError("must supply 'username' and 'password'", 401)

    user = User.check_credentials(username, password)
    if not user:
        raise ApiError('Invalid username or password', 401)

    # if email verification is enforced, deny login and send email
    if current_app.config['EMAIL_VERIFICATION'] and not user.email_verified:
        user.send_confirmation()
        raise ApiError('email not verified', 401)

    # check allowed domain
    if not_authorized('ALLOWED_EMAIL_DOMAINS', groups=[user.domain]):
        raise ApiError('unauthorized domain', 403)

    # assign customers
    customers = get_customers(user.email, groups=[user.domain])

    # generate token
    token = create_token(user.id,
                         user.name,
                         user.email,
                         provider='basic',
                         customers=customers,
                         roles=user.roles,
                         email=user.email,
                         email_verified=user.email_verified)
    return jsonify(token=token.tokenize)
예제 #15
0
def update_me_attributes():
    if not request.json.get('attributes', None):
        raise ApiError("must supply 'attributes' as json data", 400)

    user = User.find_by_id(g.user_id)

    if not user:
        raise ApiError('not found', 404)

    resp = user.update_attributes(request.json['attributes'])

    write_audit_trail.send(current_app._get_current_object(),
                           event='user-me-attributes-updated',
                           message='',
                           user=g.login,
                           customers=g.customers,
                           scopes=g.scopes,
                           resource_id=user.id,
                           type='user',
                           request=request)

    if resp:
        return jsonify(status='ok')
    else:
        raise ApiError('failed to update attributes', 500)
예제 #16
0
파일: users.py 프로젝트: kaggis/alerta
def update_user(user_id):
    if not request.json:
        raise ApiError("nothing to change", 400)

    user = User.get(user_id)

    if not user:
        raise ApiError("not found", 404)

    if 'email' in request.json and User.get_by_email(request.json['email']):
        raise ApiError("user with email already exists", 409)

    if user.update(**request.json):
        return jsonify(status="ok")
    else:
        raise ApiError("failed to update user", 500)
예제 #17
0
def signup():
    try:
        user = User.parse(request.json)
    except Exception as e:
        raise ApiError(str(e), 400)

    # set sign-up defaults
    user.roles = ['user']
    user.email_verified = False

    # check allowed domain
    if is_authorized('ALLOWED_EMAIL_DOMAINS', groups=[user.domain]):
        raise ApiError("unauthorized domain", 403)

    if User.find_by_email(email=user.email):
        raise ApiError("username already exists", 409)

    try:
        user = user.create()
    except Exception as e:
        ApiError(str(e), 500)

    # if email verification is enforced, deny login and send email
    if current_app.config['EMAIL_VERIFICATION'] and not user.email_verified:
        hash = str(uuid4())
        send_confirmation(user, hash)
        user.set_email_hash(hash)
        raise ApiError('email not verified', 401)

    # check user is active
    if user.status != 'active':
        raise ApiError('user not active', 403)

    # assign customers & update last login time
    customers = get_customers(user.email, groups=[user.domain])
    user.update_last_login()

    # generate token
    token = create_token(user.id,
                         user.name,
                         user.email,
                         provider='basic',
                         customers=customers,
                         roles=user.roles,
                         email=user.email,
                         email_verified=user.email_verified)
    return jsonify(token=token.tokenize)
예제 #18
0
def verify_email(hash):

    user = User.verify_hash(hash)
    if user and not user.email_verified:
        user.set_email_verified()
        return render_template('auth/verify_success.html', email=user.email)
    else:
        return render_template('auth/verify_failed.html')
예제 #19
0
파일: basic.py 프로젝트: 3IWOH/alerta
def verify_email(hash):

    user = User.verify_hash(hash)
    if user and not user.email_verified:
        user.set_email_verified()
        return render_template('auth/verify_success.html', email=user.email)
    else:
        return render_template('auth/verify_failed.html')
예제 #20
0
파일: commands.py 프로젝트: guardian/alerta
 def create_user(admin):
     email = admin if '@' in admin else None
     user = User(
         name='Admin user',
         login=admin,
         password=generate_password_hash(password),
         roles=['admin'],
         text='Created by alertad script',
         email=email,
         email_verified=bool(email)
     )
     try:
         db.get_db()  # init db on global app context
         user = user.create()
     except Exception as e:
         click.echo('ERROR: {}'.format(e))
     else:
         click.echo('{} {}'.format(user.id, user.name))
예제 #21
0
def delete_user(user_id):
    user = User.find_by_id(user_id)

    if not user:
        raise ApiError("not found", 404)

    if user.delete():
        return jsonify(status="ok")
    else:
        raise ApiError("failed to delete user", 500)
예제 #22
0
파일: users.py 프로젝트: justenb/alerta
def delete_user(user_id):
    user = User.find_by_id(user_id)

    if not user:
        raise ApiError('not found', 404)

    if user.delete():
        return jsonify(status='ok')
    else:
        raise ApiError('failed to delete user', 500)
예제 #23
0
파일: users.py 프로젝트: 3IWOH/alerta
def delete_user(user_id):
    user = User.find_by_id(user_id)

    if not user:
        raise ApiError("not found", 404)

    if user.delete():
        return jsonify(status="ok")
    else:
        raise ApiError("failed to delete user", 500)
예제 #24
0
def verify_email(hash):

    user = User.verify_hash(hash, salt='confirm')
    if user:
        if user.email_verified:
            raise ApiError('email already verified', 400)
        user.set_email_verified()
        return jsonify(status='ok',
                       message='email address {} confirmed'.format(user.email))
    else:
        raise ApiError('invalid confirmation hash', 400)
예제 #25
0
파일: commands.py 프로젝트: guardian/alerta
def users():
    """List admin users."""
    for admin in current_app.config['ADMIN_USERS']:
        try:
            db.get_db()  # init db on global app context
            user = User.find_by_username(admin)
        except Exception as e:
            click.echo('ERROR: {}'.format(e))
        else:
            if user:
                click.echo('{} {}'.format(user.id, user.name))
예제 #26
0
def login():
    # Retrieve required fields from client request
    try:
        email = request.json.get('username', None) or request.json['email']
        password = request.json['password']
    except KeyError:
        raise ApiError("must supply 'username' and 'password'", 401)

    username = email.split("@")[0]
    domain = email.split("@")[1]

    # Validate LDAP domain
    if domain not in current_app.config["LDAP_DOMAINS"]:
        raise ApiError("unauthorized domain", 403)

    userdn = current_app.config["LDAP_DOMAINS"][domain] % username

    # Attempt LDAP AUTH
    try:
        trace_level = 2 if current_app.debug else 0
        ldap_connection = ldap.initialize(current_app.config['LDAP_URL'],
                                          trace_level=trace_level)
        ldap_connection.simple_bind_s(userdn, password)
    except ldap.INVALID_CREDENTIALS:
        raise ApiError("invalid username or password", 401)
    except Exception as e:
        raise ApiError(str(e), 500)

    # Create user if not yet there
    user = User.find_by_email(email=email)
    if not user:
        user = User(username,
                    email,
                    "", ["user"],
                    "LDAP user",
                    email_verified=True)
        user.create()

    # Check user is active
    if user.status != 'active':
        raise ApiError('user not active', 403)

    # Assign customers & update last login time
    customers = get_customers(user.email, groups=[user.domain])
    user.update_last_login()

    # Generate token
    token = create_token(user.id,
                         user.name,
                         user.email,
                         provider='basic_ldap',
                         customers=customers,
                         roles=user.roles,
                         email=user.email,
                         email_verified=user.email_verified)
    return jsonify(token=token.tokenize)
예제 #27
0
파일: users.py 프로젝트: 3IWOH/alerta
def update_user_attributes(user_id):
    if not request.json.get('attributes', None):
        raise ApiError("must supply 'attributes' as json data", 400)

    user = User.find_by_id(user_id)

    if not user:
        raise ApiError("not found", 404)

    if user.update_attributes(request.json['attributes']):
        return jsonify(status="ok")
    else:
        raise ApiError("failed to update attributes", 500)
예제 #28
0
파일: users.py 프로젝트: guardian/alerta
def delete_user(user_id):
    user = User.find_by_id(user_id)

    if not user:
        raise ApiError('not found', 404)

    admin_audit_trail.send(current_app._get_current_object(), event='user-deleted', message='', user=g.login,
                           customers=g.customers, scopes=g.scopes, resource_id=user.id, type='user', request=request)

    if user.delete():
        return jsonify(status='ok')
    else:
        raise ApiError('failed to delete user', 500)
예제 #29
0
파일: users.py 프로젝트: guardian/alerta
def create_user():
    if current_app.config['AUTH_PROVIDER'] != 'basic':
        raise ApiError(
            'must use {} login flow to create new user'.format(current_app.config['AUTH_PROVIDER']), 400)

    try:
        user = User.parse(request.json)
    except Exception as e:
        raise ApiError(str(e), 400)

    # check allowed domain
    if not_authorized('ALLOWED_EMAIL_DOMAINS', groups=[user.domain]):
        raise ApiError('unauthorized domain', 403)

    if User.find_by_username(username=user.email):
        raise ApiError('user with that email already exists', 409)

    want_scopes = Permission.lookup(login=user.email, roles=user.roles)
    for want_scope in want_scopes:
        if not Permission.is_in_scope(want_scope, have_scopes=g.scopes):
            raise ApiError("Requested scope '{}' not in existing scopes: {}".format(
                want_scope, ','.join(g.scopes)), 403)

    try:
        user = user.create()
    except Exception as e:
        ApiError(str(e), 500)

    # if email verification is enforced, send confirmation email
    if current_app.config['EMAIL_VERIFICATION'] and not user.email_verified:
        user.send_confirmation()

    admin_audit_trail.send(current_app._get_current_object(), event='user-created', message='', user=g.login,
                           customers=g.customers, scopes=g.scopes, resource_id=user.id, type='user', request=request)

    if user:
        return jsonify(status='ok', id=user.id, user=user.serialize), 201
    else:
        raise ApiError('create user failed', 500)
예제 #30
0
파일: basic.py 프로젝트: 3IWOH/alerta
def signup():
    try:
        user = User.parse(request.json)
    except Exception as e:
        raise ApiError(str(e), 400)

    # check allowed domain
    if is_authorized('ALLOWED_EMAIL_DOMAINS', groups=[user.domain]):
        raise ApiError("unauthorized domain", 403)

    if User.find_by_email(email=user.email):
        raise ApiError("username already exists", 409)

    try:
        user = user.create()
    except Exception as e:
        ApiError(str(e), 500)

    # if email verification is enforced, deny login and send email
    if current_app.config['EMAIL_VERIFICATION'] and not user.email_verified:
        hash = str(uuid4())
        send_confirmation(user, hash)
        user.set_email_hash(hash)
        raise ApiError('email not verified', 401)

    # check user is active
    if user.status != 'active':
        raise ApiError('user not active', 403)

    # assign customer & update last login time
    customer = get_customer(user.email, groups=[user.domain])
    user.update_last_login()

    # generate token
    token = create_token(user.id, user.name, user.email, provider='basic', customer=customer,
                         roles=user.roles, email=user.email, email_verified=user.email_verified)
    return jsonify(token=token.tokenize)
예제 #31
0
파일: basic.py 프로젝트: guardian/alerta
def verify_email(hash):

    user = User.verify_hash(hash, salt='confirm')
    if user:
        if user.email_verified:
            raise ApiError('email already verified', 400)
        user.set_email_verified()

        auth_audit_trail.send(current_app._get_current_object(), event='basic-auth-verify-email',
                              message='user confirm email address', user=user.email, customers=[], scopes=[],
                              resource_id=user.id, type='user', request=request)

        return jsonify(status='ok', message='email address {} confirmed'.format(user.email))
    else:
        raise ApiError('invalid confirmation hash', 400)
예제 #32
0
파일: users.py 프로젝트: guardian/alerta
def update_me_attributes():
    if not request.json.get('attributes', None):
        raise ApiError("must supply 'attributes' as json data", 400)

    user = User.find_by_id(g.user_id)

    if not user:
        raise ApiError('not found', 404)

    write_audit_trail.send(current_app._get_current_object(), event='user-me-attributes-updated', message='', user=g.login,
                           customers=g.customers, scopes=g.scopes, resource_id=user.id, type='user', request=request)

    if user.update_attributes(request.json['attributes']):
        return jsonify(status='ok')
    else:
        raise ApiError('failed to update attributes', 500)
예제 #33
0
파일: basic.py 프로젝트: guardian/alerta
def reset(hash):
    try:
        password = request.json['password']
    except KeyError:
        raise ApiError("must supply 'password'", 400)

    user = User.verify_hash(hash, salt='reset')
    if user:
        if not user.is_active:
            raise ApiError('user not active', 403)
        user.reset_password(password)

        auth_audit_trail.send(current_app._get_current_object(), event='basic-auth-password-reset',
                              message='user password reset successful', user=user.email, customers=[], scopes=[],
                              resource_id=user.id, type='user', request=request)

        return jsonify(status='ok', message='password reset successful')
    else:
        raise ApiError('invalid password reset hash', 400)
예제 #34
0
파일: users.py 프로젝트: guardian/alerta
def list_users():
    query = qb.from_params(request.args)
    users = User.find_all(query)

    if users:
        return jsonify(
            status='ok',
            users=[user.serialize for user in users],
            domains=current_app.config['ALLOWED_EMAIL_DOMAINS'],
            total=len(users)
        )
    else:
        return jsonify(
            status='ok',
            message='not found',
            users=[],
            domains=current_app.config['ALLOWED_EMAIL_DOMAINS'],
            total=0
        )
예제 #35
0
파일: basic.py 프로젝트: guardian/alerta
def forgot():
    try:
        email = request.json['email']
    except KeyError:
        raise ApiError("must supply 'email'", 400)

    user = User.find_by_email(email)
    if user:
        if not user.is_active:
            raise ApiError('user not active', 403)
        user.send_password_reset()

        auth_audit_trail.send(current_app._get_current_object(), event='basic-auth-password-forgot',
                              message='user requested password reset', user=user.email, customers=[], scopes=[],
                              resource_id=user.id, type='user', request=request)

        return jsonify(status='ok', message='password reset sent')
    else:
        raise ApiError('invalid email address', 400)
예제 #36
0
파일: users.py 프로젝트: guardian/alerta
def get_user_groups(user_id):
    user = User.find_by_id(user_id)
    if not user:
        raise ApiError('not found', 404)

    user_groups = user.get_groups()

    if user_groups:
        return jsonify(
            status='ok',
            groups=[group.serialize for group in user_groups],
            total=len(user_groups)
        )
    else:
        return jsonify(
            status='ok',
            message='not found',
            groups=[],
            total=0
        )
예제 #37
0
파일: basic.py 프로젝트: guardian/alerta
def login():
    # lookup user from username/email
    try:
        username = request.json.get('username', None) or request.json['email']
        password = request.json['password']
    except KeyError:
        raise ApiError("must supply 'username' and 'password'", 401)

    user = User.check_credentials(username, password)
    if not user:
        raise ApiError('Invalid username or password', 401)

    # if email verification is enforced, deny login and send email
    if current_app.config['EMAIL_VERIFICATION'] and not user.email_verified:
        user.send_confirmation()
        raise ApiError('email not verified', 403)

    # check allowed domain
    if not_authorized('ALLOWED_EMAIL_DOMAINS', groups=[user.domain]):
        raise ApiError('unauthorized domain', 403)

    # check user is active & update last login
    if user.status != 'active':
        raise ApiError('User {} not active'.format(user.login), 403)
    user.update_last_login()

    groups = [g.name for g in user.get_groups()]
    scopes = Permission.lookup(login=user.login, roles=user.roles + groups)
    customers = get_customers(login=user.login, groups=[user.domain] + groups)

    auth_audit_trail.send(current_app._get_current_object(), event='basic-auth-login', message='user login via BasicAuth',
                          user=user.login, customers=customers, scopes=scopes, resource_id=user.id, type='user',
                          request=request)

    # generate token
    token = create_token(user_id=user.id, name=user.name, login=user.login, provider='basic',
                         customers=customers, scopes=scopes, roles=user.roles, groups=groups,
                         email=user.email, email_verified=user.email_verified)
    return jsonify(token=token.tokenize)
예제 #38
0
파일: basic.py 프로젝트: 3IWOH/alerta
def login():
    # lookup user from username/email
    try:
        username = request.json.get('username', None) or request.json['email']
        password = request.json['password']
    except KeyError:
        raise ApiError("must supply 'username' and 'password'", 401)

    user = User.find_by_email(email=username)
    if not user:
        raise ApiError("invalid username or password", 401)

    if not user.verify_password(password):
        raise ApiError("invalid username or password", 401)

    # if email verification is enforced, deny login and send email
    if current_app.config['EMAIL_VERIFICATION'] and not user.email_verified:
        hash = str(uuid4())
        send_confirmation(user, hash)
        user.set_email_hash(hash)
        raise ApiError('email not verified', 401)

    # check user is active
    if user.status != 'active':
        raise ApiError('user not active', 403)

    # check allowed domain
    if is_authorized('ALLOWED_EMAIL_DOMAINS', groups=[user.domain]):
        raise ApiError("unauthorized domain", 403)

    # assign customer & update last login time
    customer = get_customer(user.email, groups=[user.domain])
    user.update_last_login()

    # generate token
    token = create_token(user.id, user.name, user.email, provider='basic', customer=customer,
                         roles=user.roles, email=user.email, email_verified=user.email_verified)
    return jsonify(token=token.tokenize)
예제 #39
0
def login():
    # Retrieve required fields from client request
    try:
        email = request.json.get('username', None) or request.json['email']
        password = request.json['password']
    except KeyError:
        raise ApiError("must supply 'username' and 'password'", 401)

    username, domain = email.split('@')

    # Validate LDAP domain
    if domain not in current_app.config['LDAP_DOMAINS']:
        raise ApiError('unauthorized domain', 403)

    userdn = current_app.config['LDAP_DOMAINS'][domain] % username

    # Attempt LDAP AUTH
    try:
        trace_level = 2 if current_app.debug else 0
        ldap_connection = ldap.initialize(current_app.config['LDAP_URL'], trace_level=trace_level)
        ldap_connection.simple_bind_s(userdn, password)
    except ldap.INVALID_CREDENTIALS:
        raise ApiError('invalid username or password', 401)
    except Exception as e:
        raise ApiError(str(e), 500)

    # Create user if not yet there
    user = User.find_by_username(username=email)
    if not user:
        user = User(name=username, login=email, password='', email=email,
                    roles=[], text='LDAP user', email_verified=True)
        try:
            user = user.create()
        except Exception as e:
            ApiError(str(e), 500)

    # Assign customers & update last login time
    groups = list()
    try:
        groups_filters = current_app.config.get('LDAP_DOMAINS_GROUP', {})
        base_dns = current_app.config.get('LDAP_DOMAINS_BASEDN', {})
        if domain in groups_filters and domain in base_dns:
            resultID = ldap_connection.search(
                base_dns[domain],
                ldap.SCOPE_SUBTREE,
                groups_filters[domain].format(username=username, email=email, userdn=userdn),
                ['cn']
            )
            resultTypes, results = ldap_connection.result(resultID)
            for _dn, attributes in results:
                groups.append(attributes['cn'][0].decode('utf-8'))
    except ldap.LDAPError as e:
        raise ApiError(str(e), 500)

    # Check user is active
    if user.status != 'active':
        raise ApiError('User {} not active'.format(email), 403)
    user.update_last_login()

    scopes = Permission.lookup(login=user.email, roles=user.roles)
    customers = get_customers(login=user.email, groups=[user.domain] + groups)

    auth_audit_trail.send(current_app._get_current_object(), event='basic-ldap-login', message='user login via LDAP',
                          user=user.email, customers=customers, scopes=scopes, resource_id=user.id, type='user',
                          request=request)

    # Generate token
    token = create_token(user_id=user.id, name=user.name, login=user.email, provider='ldap', customers=customers,
                         scopes=scopes, roles=user.roles, email=user.email, email_verified=user.email_verified)
    return jsonify(token=token.tokenize)
예제 #40
0
        def wrapped(*args, **kwargs):

            # API Key (Authorization: Key <key>)
            if 'Authorization' in request.headers:
                auth_header = request.headers['Authorization']
                m = re.match(r'Key (\S+)', auth_header)
                key = m.group(1) if m else None
            # API Key (X-API-Key: <key>)
            elif 'X-API-Key' in request.headers:
                key = request.headers['X-API-Key']
            # API Key (/foo?api-key=<key>)
            else:
                key = request.args.get('api-key', None)

            if key:
                key_info = ApiKey.verify_key(key)
                if not key_info:
                    raise ApiError("API key parameter '%s' is invalid" % key, 401)
                g.user_id = None
                g.login = key_info.user
                g.customers = [key_info.customer] if key_info.customer else []
                g.scopes = key_info.scopes  # type: List[Scope]

                if not Permission.is_in_scope(scope, have_scopes=g.scopes):
                    raise ApiError('Missing required scope: %s' % scope.value, 403)
                else:
                    return f(*args, **kwargs)

            # Bearer Token
            auth_header = request.headers.get('Authorization', '')
            m = re.match(r'Bearer (\S+)', auth_header)
            token = m.group(1) if m else None

            if token:
                try:
                    jwt = Jwt.parse(token)
                except DecodeError:
                    raise ApiError('Token is invalid', 401)
                except ExpiredSignature:
                    raise ApiError('Token has expired', 401)
                except InvalidAudience:
                    raise ApiError('Invalid audience', 401)
                g.user_id = jwt.subject
                g.login = jwt.preferred_username
                g.customers = jwt.customers
                g.scopes = jwt.scopes  # type: List[Scope]

                if not Permission.is_in_scope(scope, have_scopes=g.scopes):
                    raise ApiError('Missing required scope: %s' % scope.value, 403)
                else:
                    return f(*args, **kwargs)

            # Basic Auth
            auth_header = request.headers.get('Authorization', '')
            m = re.match(r'Basic (\S+)', auth_header)
            credentials = m.group(1) if m else None

            if credentials:
                try:
                    username, password = base64.b64decode(credentials).decode('utf-8').split(':')
                except Exception as e:
                    raise BasicAuthError('Invalid credentials', 400, errors=[str(e)])

                user = User.check_credentials(username, password)
                if not user:
                    raise BasicAuthError('Authorization required', 401)

                if current_app.config['EMAIL_VERIFICATION'] and not user.email_verified:
                    raise BasicAuthError('email not verified', 401)

                if not_authorized('ALLOWED_EMAIL_DOMAINS', groups=[user.domain]):
                    raise BasicAuthError('Unauthorized domain', 403)

                g.user_id = user.id
                g.login = user.email
                g.customers = get_customers(user.email, groups=[user.domain])
                g.scopes = Permission.lookup(user.email, roles=user.roles)  # type: List[Scope]

                if not Permission.is_in_scope(scope, have_scopes=g.scopes):
                    raise BasicAuthError('Missing required scope: %s' % scope.value, 403)
                else:
                    return f(*args, **kwargs)

            if not current_app.config['AUTH_REQUIRED']:
                g.user_id = None
                g.login = None
                g.customers = []
                g.scopes = []  # type: List[Scope]
                return f(*args, **kwargs)

            # Google App Engine Cron Service
            if request.headers.get('X-Appengine-Cron', False) and request.headers.get('X-Forwarded-For', '') == '0.1.0.1':
                return f(*args, **kwargs)

            raise ApiError('Missing authorization API Key or Bearer Token', 401)
예제 #41
0
파일: oidc.py 프로젝트: guardian/alerta
def openid():

    oidc_configuration, jwt_key_set = get_oidc_configuration(current_app)
    token_endpoint = oidc_configuration['token_endpoint']
    userinfo_endpoint = oidc_configuration['userinfo_endpoint']

    data = {
        'grant_type': 'authorization_code',
        'code': request.json['code'],
        'redirect_uri': request.json['redirectUri'],
        'client_id': request.json['clientId'],
        'client_secret': current_app.config['OAUTH2_CLIENT_SECRET'],
    }
    r = requests.post(token_endpoint, data)
    token = r.json()

    try:
        if current_app.config['OIDC_VERIFY_TOKEN']:
            jwt_header = jwt.get_unverified_header(token['id_token'])
            public_key = jwt_key_set[jwt_header['kid']]

            id_token = jwt.decode(
                token['id_token'],
                key=public_key,
                algorithms=jwt_header['alg']
            )
        else:
            id_token = jwt.decode(
                token['id_token'],
                verify=False
            )
    except Exception:
        current_app.logger.warning('No ID token in OpenID Connect token response.')
        id_token = {}

    try:
        headers = {'Authorization': '{} {}'.format(token.get('token_type', 'Bearer'), token['access_token'])}
        r = requests.get(userinfo_endpoint, headers=headers)
        userinfo = r.json()
    except Exception:
        raise ApiError('No access token in OpenID Connect token response.')

    subject = userinfo['sub']
    name = userinfo.get('name') or id_token.get('name')
    nickname = userinfo.get('nickname')
    email = userinfo.get('email') or id_token.get('email')
    email_verified = userinfo.get('email_verified', id_token.get('email_verified', bool(email)))
    picture = userinfo.get('picture') or id_token.get('picture')

    role_claim = current_app.config['OIDC_ROLE_CLAIM']
    group_claim = current_app.config['OIDC_GROUP_CLAIM']
    custom_claims = {
        role_claim: userinfo.get(role_claim) or id_token.get(role_claim, []),
        group_claim: userinfo.get(group_claim) or id_token.get(group_claim, []),
    }

    login = userinfo.get('preferred_username', nickname or email)
    if not login:
        raise ApiError("Must support one of the following OpenID claims: 'preferred_username', 'nickname' or 'email'", 400)

    user = User.find_by_id(id=subject)
    if not user:
        user = User(id=subject, name=name, login=login, password='', email=email,
                    roles=[], text='', email_verified=email_verified)
        user.create()
    else:
        user.update(login=login, email=email)

    roles = custom_claims[role_claim] or user.roles
    groups = custom_claims[group_claim]

    if user.status != 'active':
        raise ApiError('User {} is not active'.format(login), 403)

    if not_authorized('ALLOWED_OIDC_ROLES', roles) and not_authorized('ALLOWED_EMAIL_DOMAINS', groups=[user.domain]):
        raise ApiError('User {} is not authorized'.format(login), 403)
    user.update_last_login()

    scopes = Permission.lookup(login, roles)
    customers = get_customers(login, groups=[user.domain] + groups)

    auth_audit_trail.send(current_app._get_current_object(), event='openid-login', message='user login via OpenID Connect',
                          user=login, customers=customers, scopes=scopes, resource_id=subject, type='user', request=request)

    token = create_token(user_id=subject, name=name, login=login, provider='openid', customers=customers,
                         scopes=scopes, email=email, email_verified=email_verified, picture=picture, **custom_claims)
    return jsonify(token=token.tokenize)