Пример #1
0
def test_response_header_in_minimal_mode(client, faker, broken_db):
    test_user = User(username=faker.safe_email().split('@')[0])
    test_token = test_user.generate_token(settings.SECRET_KEY)

    r = client.get('/whoami', headers={'Authorization': test_token})
    assert_response_ok(r)
    assert r.headers['X-Minimal-Mode'] == '1'
    assert r.headers['X-Minimal-Mode-Reason'] == 'auth'
Пример #2
0
 def factory(names):
     for name in names:
         if isinstance(name, list):
             name, email = name
         else:
             email = '*****@*****.**' % name
         User.create_normal(
             name, faker.password(), email=email,
             is_active=True)
Пример #3
0
def test_minimal_mode_incompatible(client, faker, broken_db):
    test_user = User(username=faker.safe_email().split('@')[0])
    test_token = test_user.generate_token(settings.SECRET_KEY)

    r = client.get('/incompatible', headers={'Authorization': test_token})
    assert r.status_code == 501
    assert r.json['status'] == 'NotImplemented'
    assert r.json['message'] == ('Current API is not suitable for working '
                                 'in minimal mode')
    assert r.json['data'] is None
Пример #4
0
def test_get_team_application_token_with_malformed_user(
        client, db, test_team, test_application, admin_user, admin_token,
        faker):
    """The username and email prefix are not inconsistent."""
    User.create_normal('foobar',
                       faker.uuid4()[:8], '*****@*****.**', True)
    r = client.post('/api/team/%s/application/%s/token' %
                    (test_team.team_name, test_application.application_name),
                    data={'owner_email': '*****@*****.**'},
                    headers={'Authorization': admin_token})
    assert_response_ok(r)
Пример #5
0
def test_authenticated_user_in_minimal_mode(client, faker, mocker, broken_db):
    test_user = User(username=faker.safe_email().split('@')[0])
    test_token = test_user.generate_token(settings.SECRET_KEY)

    mocker.patch.object(settings, 'ADMIN_EMERGENCY_USER_LIST', ['admin'])

    r = client.get('/whoami', headers={'Authorization': test_token})
    assert_response_ok(r)
    data = r.json['data']
    assert data['username'] == test_user.username
    assert data['is_application'] is False
    assert data['is_admin'] is False
Пример #6
0
 def ensure(self):
     user = (User.get_by_name(self.name) or User.get_by_email(self.email))
     if user is None:
         password = gen_salt(30)
         user = User.create_normal(self.name,
                                   password,
                                   self.email,
                                   is_active=True)
         deliver_email(EmailTemplate.SIGNUP, user.email, {
             'username': user.username,
             'password': password,
         })
     return user
Пример #7
0
def test_get_team_application_token_by_admin_with_unknown_owner_email(
        client, db, test_team, test_application, admin_user, admin_token,
        owner_email, mocker):
    r = client.post('/api/team/%s/application/%s/token' %
                    (test_team.team_name, test_application.application_name),
                    data={'owner_email': owner_email},
                    headers={'Authorization': admin_token})

    assert_response_ok(r)
    user = User.get_by_token(settings.SECRET_KEY, r.json['data']['token'])
    assert user and user.username == test_application.application_name
    owner = owner_email.split('@', 1)[0]
    assert User.get_by_name(owner)
Пример #8
0
def test_create_normal(db):
    user = User.create_normal('water', 'foobar', '*****@*****.**')
    assert user.username == 'water'
    assert user.check_password('foobar')
    assert not user.check_password('foobaz')
    assert not user.is_active
    assert user.is_admin is False
    assert user.is_application is False

    with raises(NameOccupiedError):
        User.create_normal('water', 'foobaz', '*****@*****.**')
    assert db.query(
        User.email).filter_by(username='******').scalar() == '*****@*****.**'
Пример #9
0
def test_doctor_in_minimal_mode(app, client, mocker, faker, broken_db):
    metrics = app.extensions['huskar_api.db.tester'].metrics
    on_sys_exc = mocker.patch.object(metrics,
                                     'on_api_called_sys_exc',
                                     autospec=True)
    on_ok = mocker.patch.object(metrics, 'on_api_called_ok', autospec=True)

    test_user = User(username=faker.safe_email().split('@')[0])
    test_token = test_user.generate_token(settings.SECRET_KEY)

    client.get('/whoami', headers={'Authorization': test_token})

    assert not on_ok.called
    assert on_sys_exc.called
Пример #10
0
def test_authenticated_application_in_minimal_mode(client, zk, faker, mocker,
                                                   broken_db, data_type):
    test_user = User(username=faker.uuid4()[:8])
    test_token = test_user.generate_token(settings.SECRET_KEY)

    zk_path = '/huskar/%s/%s' % (data_type, test_user.username)
    zk.ensure_path(zk_path)
    sleep(0.1)

    r = client.get('/whoami', headers={'Authorization': test_token})
    assert_response_ok(r)
    data = r.json['data']
    assert data['username'] == test_user.username
    assert data['is_application'] is True
    assert data['is_admin'] is False
Пример #11
0
def _publish_new_action(user_id, remote_addr, action):
    if remote_addr == settings.LOCAL_REMOTE_ADDR:
        return

    user = User.get(user_id)
    user_type = NORMAL_USER
    username = None
    if user:
        username = user.username
        if (user.is_application
                or username in settings.APPLICATION_USE_USER_TOKEN_USER_LIST):
            user_type = APPLICATION_USER
    is_subscriable = any(item[0] == TYPE_APPLICATION
                         for item in action.action_indices)

    severity = SEVERITY_DANGEROUS
    action_name = action_types[action.action_type]
    if action_name in settings.DANGEROUS_ACTION_NAMES_EXCLUDE_LIST:
        severity = SEVERITY_NORMAL

    insensitive_data = remove_sensitive_data(action.action_data)
    try:
        new_action_detected.send(AuditLog,
                                 action_type=action.action_type,
                                 username=username,
                                 user_type=user_type,
                                 action_data=insensitive_data,
                                 is_subscriable=is_subscriable,
                                 severity=severity)
    except Exception:
        logger.exception('Unexpected error of publish webhook event')
        capture_exception(data=None)
Пример #12
0
def huskar_audit_log(action_type, **extra):
    if not switch.is_switched_on(SWITCH_ENABLE_AUDIT_LOG):
        yield
        return
    action = action_creator.make_action(action_type, **extra)
    yield
    try:
        if switch.is_switched_on(SWITCH_ENABLE_MINIMAL_MODE, False):
            action_name = action_types[action_type]
            fallback_audit_logger.info('arch.huskar_api %s %r', action_name,
                                       action.action_data)
        else:
            user = User.get_by_name('arch.huskar_api')
            user_id = user.id if user else 0
            AuditLog.create(user_id, settings.LOCAL_REMOTE_ADDR, action)
    except AuditLogTooLongError:
        logger.info('Audit log is too long. %s arch.huskar_api',
                    action_types[action_type])
        return
    except AuditLogLostError:
        action_name = action_types[action_type]
        fallback_audit_logger.info('arch.huskar %s %r', action_name,
                                   action.action_data)
    except Exception:
        logger.exception('Unexpected error of audit log')
Пример #13
0
def test_get_multi_by_index(faker, action):
    assert AuditLog.get_multi_by_index(AuditLog.TYPE_SITE, 0)[:] == []
    assert AuditLog.get_multi_by_index(AuditLog.TYPE_TEAM, 0)[:] == []
    user = User.create_normal(faker.uuid4(), '-', faker.email())
    log = AuditLog.create(user.id, faker.ipv4(), action)
    assert AuditLog.get_multi_by_index(AuditLog.TYPE_SITE, 0)[:] == [log]
    assert AuditLog.get_multi_by_index(AuditLog.TYPE_TEAM, 0)[:] == []
Пример #14
0
def test_ensure_ensure_owners_send_mail_failed(mocker):
    deliver_email = mocker.patch('huskar_api.extras.auth.deliver_email')
    deliver_email.side_effect = EmailDeliveryError()

    prefix = 'test_ensure_ensure_owners_send_mail_failed'
    application_name = '{}_app'.format(prefix)
    owner = Owner(
            '{}_user'.format(prefix),
            '{}[email protected]'.format(prefix),
            'owner',
        )
    department = Department(
            '1', '{}_team'.format(prefix), '2', '{}_team'.format(prefix))
    appinfo = AppInfo(
        department=department,
        application_name=application_name,
        owners=[owner])

    assert department.team_name == '{}-{}'.format(
        department.parent_id, department.child_id)
    assert department.team_desc == '{}-{}'.format(
        department.parent_name, department.child_name)

    assert len(list(ensure_owners(appinfo))) == 0

    assert User.get_by_name('{}_user'.format(prefix)) is not None
    deliver_email.assert_called_once()

    mocker.patch.object(owner, 'ensure',
                        mocker.MagicMock(side_effect=NameOccupiedError))
    assert len(list(ensure_owners(appinfo))) == 0
Пример #15
0
def test_create_application(db, zk, test_team, faker):
    application_name = faker.uuid4()[:8]
    stat = zk.exists('/huskar/service/%s' % application_name)
    assert stat is None

    application = Application.create(application_name, test_team.id)
    assert zk.exists('/huskar/service/%s' % application_name)

    assert application.id > 0
    assert application.application_name == application_name
    assert application.domain_name == application_name
    assert application.team_id == test_team.id
    assert application.team.team_name == test_team.team_name

    user = User.get_by_name(application_name)
    assert user is not None
    assert user.is_application
    assert not user.is_admin
    assert application.check_auth(Authority.WRITE, user.id)
    assert application.check_auth(Authority.READ, user.id)

    with raises(NameOccupiedError):
        Application.create(application_name, test_team.id)  # name conflicts

    application = Application.create('baz', test_team.id)
    assert application.application_name == 'baz'
Пример #16
0
def test_add_application_auth_to_invalid_user(
        client, faker, add_user, admin_token, last_audit_log,
        test_application):
    add_user(['foo'])
    user = User.get_by_name('foo')
    user.archive()
    application_name = test_application.application_name

    unknow_user = faker.uuid4()[:6]
    r = client.post(
        '/api/auth/application/%s' % application_name,
        data={'username': unknow_user, 'authority': 'read'},
        headers={'Authorization': admin_token})
    assert r.status_code == 400
    assert r.json['status'] == 'BadRequest'
    assert r.json['message'] == 'user %s does not exist' % unknow_user

    r = client.post(
        '/api/auth/application/%s' % application_name,
        data={'username': '******', 'authority': 'read'},
        headers={'Authorization': admin_token})
    assert r.status_code == 400
    assert r.json['status'] == 'BadRequest'
    assert r.json['message'] == 'user foo does not exist'

    assert last_audit_log() is None
Пример #17
0
    def post(self):
        """Obtains an user token by checking username and password.

        :form username: Required. The username of user.
        :form password: Required. The password of user.
        :form expiration: Optional. The life time in seconds of the token.
                          ``0`` or omitted will make token be expired in 30
                          days. Default is ``0``.
        :<header Content-Type: :mimetype:`application/x-www-form-urlencoded`
        :status 400: The username or password is incorrect.
        :status 200: You could find token from the response body:
                     ``{"status": "SUCCESS", "data": {"token": "..",
                     "expires_in": 1}}``
        """
        username = request.form['username'].strip()
        password = request.form['password'].strip()
        expires_in = request.form.get('expiration', type=int, default=0)
        if expires_in > 0:
            expires_in = min(expires_in, settings.ADMIN_MAX_EXPIRATION)
        else:
            expires_in = settings.ADMIN_MAX_EXPIRATION

        user = User.get_by_name(username)
        if user is None or user.is_application:
            raise UserNotExistedError('user not found')
        if not user.check_password(password):
            raise LoginError("username or password not correct")

        g.auth = SessionAuth.from_user(user)
        with audit_log(audit_log.types.OBTAIN_USER_TOKEN, user=user):
            token = user.generate_token(settings.SECRET_KEY, expires_in)
            return api_response({'token': token, 'expires_in': expires_in})
Пример #18
0
def test_change_password(db, user_foo, input_password, hashed_password):
    user_foo.change_password(input_password)
    assert db.query(User.password).filter_by(
        username=user_foo.username).scalar() == hashed_password

    db.close()  # clear identity map
    assert User.get(user_foo.id).password == hashed_password
Пример #19
0
def test_dismiss_admin(db, user_foo, present_is_admin):
    user_foo.huskar_admin = present_is_admin
    db.commit()

    user_foo.dismiss_admin()
    assert user_foo.is_admin is False
    assert User.get(user_foo.id, force=True).is_admin is False
Пример #20
0
def test_get_application_token_by_admin(client, db, test_application,
                                        admin_token):
    r = client.post('/api/application/%s/token' %
                    test_application.application_name,
                    headers={'Authorization': admin_token})
    assert_response_ok(r)
    user = User.get_by_token(settings.SECRET_KEY, r.json['data']['token'])
    assert user and user.username == test_application.application_name
Пример #21
0
def test_get_application_token_with_malformed_application(
        client, faker, capsys, db, test_team, admin_token):
    _application = Application.create(faker.uuid4()[:8], test_team.id)
    _user = User.get_by_name(_application.application_name)
    with DBSession() as session:
        session.delete(_user)
        session.commit()
    _user = User.create_normal(_application.application_name,
                               '-',
                               is_active=True)

    r = client.post('/api/application/%s/token' %
                    _application.application_name,
                    headers={'Authorization': admin_token})
    assert r.status_code == 400
    assert r.json['status'] == 'BadRequest'
    assert r.json['message'] == ('malformed application: %s' %
                                 _application.application_name)
    assert r.json['data'] is None
Пример #22
0
def test_initdb_with_admin_present(mocker, admin_user):
    prompt_pass = mocker.patch.object(huskar_api.cli, 'prompt_pass')

    with pytest.raises(SystemExit):
        huskar_api.cli.initadmin()

    prompt_pass.assert_not_called()

    user = User.get_by_name('admin')
    assert user is admin_user
Пример #23
0
def test_get_application_token_with_orphan_application(client, faker, db,
                                                       test_team, admin_token):
    _application = Application.create(faker.uuid4()[:8], test_team.id)
    _user = User.get_by_name(_application.application_name)
    _user.archive()

    user = User.get_by_name(_application.application_name)
    assert db.query(User).filter_by(username=_application.application_name,
                                    is_active=True).count() == 0

    r = client.post('/api/application/%s/token' %
                    _application.application_name,
                    headers={'Authorization': admin_token})
    assert_response_ok(r)
    user = User.get_by_token(settings.SECRET_KEY, r.json['data']['token'])
    assert user and user.username == _application.application_name

    assert User.get_by_name(_application.application_name) is not None
    assert db.query(User).filter_by(
        username=_application.application_name).count() == 1
Пример #24
0
def test_get_application_token_by_writer(client, db, method, test_application,
                                         test_user, test_token):
    test_application.ensure_auth(Authority.WRITE, test_user.id)

    r = client.open('/api/application/%s/token' %
                    test_application.application_name,
                    method=method,
                    headers={'Authorization': test_token})
    assert_response_ok(r)
    user = User.get_by_token(settings.SECRET_KEY, r.json['data']['token'])
    assert user and user.username == test_application.application_name
Пример #25
0
    def post(self):
        """Creates a new user with your site admin authority.

        We will send you an email of random password if don't specify password
        explicitly.

        :form username: The username of new user.
        :form password: The optional password of new user.
        :form email: The email of new user.
        :<header Authorization: Huskar Token (See :ref:`token`)
        :status 400: The username is used or the format is invalid.
        :status 200: The new user is created successfully.
        """
        g.auth.require_admin('only admin can add users')

        username = request.form['username'].strip()
        password = request.form.get('password', gen_salt(30))
        is_generated_password = '******' not in request.form
        email = request.form['email'].strip()
        validate_fields(user_schema, {'username': username, 'email': email})

        user = User.get_by_name(username)
        if user:
            abort(400, u'{0} is used username'.format(username))

        try:
            user = User.create_normal(username,
                                      password,
                                      email,
                                      is_active=True)
        except NameOccupiedError:
            abort(400, u'User %s has been archived' % username)
        audit_log.emit(audit_log.types.CREATE_USER, user=user)

        if is_generated_password:
            deliver_email(EmailTemplate.SIGNUP, user.email, {
                'username': user.username,
                'password': password,
            })

        return api_response()
Пример #26
0
def test_get_user_token(client, mocker, admin_user):
    g.auth = None
    r = client.post('/api/auth/token',
                    data={
                        'username': admin_user.username,
                        'password': '******'
                    })
    assert_response_ok(r)
    assert r.json['data']['expires_in'] == settings.ADMIN_MAX_EXPIRATION
    user = User.get_by_token(settings.SECRET_KEY, r.json['data']['token'])
    assert user and user.username == admin_user.username
    assert g.auth and g.auth.id == admin_user.id
Пример #27
0
def test_get_all_normal(db, user_foo):
    assert User.get_all_normal() == [user_foo]

    user_bar = User.create_application('base.bar')
    user_baz = User.create_normal('baz', '-', '*****@*****.**', is_active=True)
    user_too = User.create_normal('too', '-', '*****@*****.**', is_active=False)

    assert User.get_all_normal() == [user_foo, user_baz]
    assert user_bar not in User.get_all_normal()
    assert user_too not in User.get_all_normal()
Пример #28
0
def reset_password(username, token, new_password):
    key = _PASSWORD_RESET_KEY.format(username=username)
    expected_token = _redis_client.get(key)
    if expected_token and safe_str_cmp(token.hex, expected_token):
        _redis_client.delete(key)
        user = User.get_by_name(username)
        if user is None or user.is_application:
            abort(404, u'user {0} not found'.format(username))
        user.change_password(new_password)
    else:
        abort(403, u'token is expired')
    return user
Пример #29
0
def test_recreate_archived_user(client, admin_token, add_test_user):
    user_data = {'username': '******', 'password': '******', 'email': '*****@*****.**'}
    headers = {'Authorization': admin_token}

    add_test_user(user_data)
    user = User.get_by_name('foo')
    user.archive()

    r = client.post('/api/user', data=user_data, headers=headers)

    assert r.status_code == 400
    assert r.json['message']
Пример #30
0
    def get(self, username=None):
        """Gets the entity data of an user or a list of users.

        :param username: If specified then respond an user instead a list of
                         users.
        :<header Authorization: Huskar Token (See :ref:`token`)
        :status 404: The username is specified but there is nothing found.
        :status 200: An user or a list of users.
        """
        if username:
            user = self._get_user_or_404(username)
            return api_response(user_schema.dump(user).data)
        else:
            user_list = User.get_all_normal()
            return api_response(user_schema.dump(user_list, many=True).data)