Esempio n. 1
0
def user(db):
    """测试普通用户记录
    """
    user = User(name='test_user', email='*****@*****.**', is_admin=False)
    user.password = PASSWORD
    user.save()
    return user
Esempio n. 2
0
    def test_create_user_success(self, client, admin):
        """测试创建用户成功
        """
        # 当前数据库只有 admin 账户
        assert User.query.count() == 1

        # 用于创建用户的数据
        data = {
            'name': 'test_user',
            'email': '*****@*****.**',
            'password': '******'
        }

        # 通过 '/users/' 接口创建用户
        resp = client.post(url_for(self.endpoint),
                           data=json.dumps(data),
                           headers=self.token_header(admin))

        # 创建成功, 返回状态码 201
        assert resp.status_code == 201
        assert resp.json == {'ok': True}

        # 成功写入数据库
        assert User.query.count() == 2
        user = User.query.filter_by(name=data['name']).first()
        assert user is not None
        assert user.email == data['email']

        # 创建的用户可以进行登录
        assert User.authenticate(data['name'], data['password']) == user
        assert User.authenticate(data['email'], data['password']) == user
Esempio n. 3
0
def admin(db):
    """测试管理员用户记录
    """
    user = User(name='admin', email='*****@*****.**', is_admin=True)
    user.password = PASSWORD
    user.save()
    return user
Esempio n. 4
0
 def wrapper(*args, **kwargs):
     # 补全代码
     print(request.method)
     if self.admin:
         if request.method == 'POST':
             data = request.form
         else:
             data = request.args
         token = request.headers.get('Authorization',
                                     '')[4:] or data.get('token', '')
         User.verify_token(token=token, verify_exp=self.verify_exp)
     return func(*args, **kwargs)
Esempio n. 5
0
    def post(self):
        """登录认证用户

        用户可以使用昵称或者邮箱进行登录,登录成功后返回用于后续认证的 token
        """

        # FIXME 没有处理 data 为 None 的情况
        data = request.get_json()
        if data is None:
            raise AuthenticationError(403, 'user name or password required')

        name = data.get('name')
        password = data.get('password')

        if not name or not password:
            raise AuthenticationError(403, 'user name or password required')

        # FIXME 只有管理员用户允许登录管理后台
        user = User.authenticate(name, password)
        if not user.is_admin:
            raise AuthenticationError(403, 'user name or password required')

        user.login_at = datetime.utcnow()
        user.save()
        return {'ok': True, 'token': user.generate_token()}
Esempio n. 6
0
    def post(self):
        """登录认证用户

        用户可以使用昵称或者邮箱进行登录,登录成功后返回用于后续认证的 token
        """

        # FIXME 没有处理 data 为 None 的情况
        data = request.get_json()
        if data is None:
            raise AuthenticationError(403, 'user name or password required')

        name = data.get('name')
        password = data.get('password')

        if not name or not password:
            raise AuthenticationError(403, 'user name or password required')

        # FIXME 只有管理员用户允许登录管理后台
        user = User.authenticate(name, password)
        if not user.is_admin:
            raise AuthenticationError(403, 'administrator required')

        user.login_at = datetime.utcnow()
        user.save()
        return {'ok': True, 'token': user.generate_token()}
Esempio n. 7
0
 def test_verify_token(self, user):
     """测试 User.verify_token 类方法
     """
     # 成功验证 token
     token = user.generate_token()
     # 验证 token 成功后会返回 User 对象
     u = User.verify_token(token)
     assert user == u
Esempio n. 8
0
    def test_authenticate(self, user):
        """测试 User.authenticate 类方法
        """
        assert User.authenticate(user.name, PASSWORD)
        assert user.authenticate(user.email, PASSWORD)

        wrong_password = PASSWORD + '0'

        try:
            User.authenticate(user.name, wrong_password)
        except AuthenticationError as e:
            assert e.code == 403
            assert e.message == 'authentication failed'

        try:
            User.authenticate(user.email, wrong_password)
        except AuthenticationError as e:
            assert e.code == 403
            assert e.message == 'authentication failed'
Esempio n. 9
0
 def wrapper(*args, **kwargs):
     # 补全代码
     jwt_token = request.headers.get('Authorization')
     if jwt_token is not None:
         jwt_token = jwt_token.split(" ")[-1]
     else:
         jwt_token = request.form.get('token')
         if jwt_token is None:
             jwt_token = request.args.get('token')
             if jwt_token is None:
                 raise RestError(403, 'token not exist')
     g.instance = User.verify_token(jwt_token)
     return func(*args, **kwargs)
Esempio n. 10
0
def init_db():
    """初始化数据库
    """
    db.create_all()
    print("sqlite3 database file is %s" %
          app.config['SQLALCHEMY_DATABASE_URI'])

    # create administrator
    name, password = User.create_administrator()

    # 如果 password 为空,代表已经存在 admin 账户
    if password != '':
        print("create admin user %s with password %s" % (name, password))
Esempio n. 11
0
    def handle(self, message):
        """ 执行相应的命令
        """
        # 判断命令是否匹配
        if not self.check_match(message):
            return

        # 判断用户是否已经绑定
        user = User.wx_id_user(message.source)
        if user is not None:
            return create_reply('你已绑定到 %s 用户' % user.name, message)

        # 返回绑定用户链接
        url = url_for('apps.wx_bind', wx_id=message.source, _external=True)
        return create_reply('请打开链接 %s 完成用户绑定' % url, message)
Esempio n. 12
0
    def post(self, wx_id):
        """绑定用户
        """
        data = request.get_json()
        if data is None or 'name' not in data or 'password' not in data:
            return {'ok': False, 'message': '无效用户数据'}, 400

        user = User.authenticate(data['name'], data['password'])

        if user.wx_id is not None:
            return {'ok': False, 'message': '已绑定到其他微信账户'}, 400

        user.wx_id = wx_id
        user.save()
        return {'ok': True, 'message': '绑定成功'}
Esempio n. 13
0
    def test_login_success(self, client, admin):
        """登录成功
        """

        data = {'name': admin.name, 'password': PASSWORD}

        resp = client.post(url_for(self.endpoint),
                           data=json.dumps(data),
                           headers={'Content-Type': 'application/json; utf-8'})

        assert resp.status_code == 200
        assert resp.json['ok'] == True

        # 获取到的 token 成功验证
        u = User.verify_token(resp.json['token'])

        assert u == admin
Esempio n. 14
0
def create_app(config=None):
    """ 创建并初始化 Flask app

    Args:
        config(dict): 配置字典

    Returns:
        app (object): Flask App 实例
    """

    app = Flask('rmon')

    # 根据环境变量加载开发环境或生产环境配置
    env = os.environ.get('RMON_ENV')

    if env in ('pro', 'prod', 'product'):
        app.config.from_object(ProductConfig)
    else:
        app.config.from_object(DevConfig)

    # 从环境变量 RMON_SETTINGS 指定的文件中加载配置
    app.config.from_envvar('RMON_SETTINGS', silent=True)

    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

    # 从 config 参数更新配置
    if config is not None:
        app.config.update(config)

    # 注册 Blueprint
    app.register_blueprint(api)
    # 初始化数据库
    db.init_app(app)

    # 初始化微信消息处理器
    wx_dispatcher.init_app(app)

    # 如果是开发环境则创建所有数据库表
    if app.debug and not app.testing:
        with app.app_context():
            db.create_all()
            name, password = User.create_administrator()
            app.logger.debug('create administrator name/password %s/%s', name,
                             password)
    return app
Esempio n. 15
0
    def handle(self, message):
        # 判断命令是否匹配
        if not self.check_match(message):
            return

        # 检查微信用户是否已经绑定到 rmon 用户
        user = User.wx_id_user(message.source)
        if not user:
            return create_reply('未绑定用户', message)
        parts = message.content.strip().split(' ')
        if len(parts) == 1:
            return create_reply('请输入子命令', message)
        if parts[1].lower() == 'ls':
            return create_reply(self.list_servers(), message)
        elif parts[1].lower() == 'del':
            return create_reply(self.delete_server(*parts[2:]), message)
        else:
            return create_reply('命令暂未实现', message)
Esempio n. 16
0
    def test_generate_token(self, user, app):
        """测试 User.generate_token 方法
        """

        now = timegm(datetime.utcnow().utctimetuple())
        token = user.generate_token()

        payload = jwt.decode(token, verify=False)

        assert payload['uid'] == user.id
        assert payload['is_admin'] == user.is_admin
        assert 'refresh_exp' in payload
        assert 'exp' in payload

        # 生成的 token 有效期为一天
        assert payload['exp'] - now == 24 * 3600
        # token 过期后十分钟内,还可以使用老 token 进行刷新 token
        assert payload['refresh_exp'] - now == 24 * 3600 + 10 * 60
        u = User.verify_token(token)
        assert u == user
Esempio n. 17
0
def create_app(config):
    app = Flask("rmon")
    app.config.from_object(configs.get(config, "development"))
    # 从环境变量 RMON_SETTINGS 指定的文件中加载配置
    app.config.from_envvar('RMON_SETTINGS', silent=True)
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
    get_config_from_file(app)
    register_extensions(app)
    register_blueprints(app)

    # 如果是开发环境则创建所有数据库表
    if app.debug and not app.testing:
        with app.app_context():
            db.create_all()
            name, password = User.create_administrator()
            app.logger.debug('create administrator name/password %s/%s', name,
                             password)

    return app
    return app
Esempio n. 18
0
    def test_verify_token_failed(self, user, app):
        """测试 User.verify_token 验证 token 时失败
        """

        algorithm = 'HS512'

        # token 验证失败
        invalid_token = user.generate_token() + '0'

        try:
            User.verify_token(invalid_token)
        except InvalidTokenError as e:
            assert e.code == 403
            assert 'Signature' in e.message

        # token 指定的用户不存在
        exp = datetime.utcnow() + timedelta(days=1)
        # token 过期后十分钟内,还可以使用老 token 进行刷新 token
        refresh_exp = timegm((exp + timedelta(seconds=60 * 10)).utctimetuple())

        # 用户步存在
        user_not_exist = 100
        payload = {
            'uid': user_not_exist,
            'is_admin': False,
            'exp': exp,
            'refresh_exp': refresh_exp
        }

        # 用户不存在
        try:
            User.verify_token(
                jwt.encode(payload, app.secret_key, algorithm=algorithm))
        except InvalidTokenError as e:
            assert e.code == 403
            assert e.message == 'user not exist'

        payload = {'exp': exp}
        try:
            User.verify_token(
                jwt.encode(payload, app.secret_key, algorithm=algorithm))
        except InvalidTokenError as e:
            assert e.code == 403
            assert e.message == 'invalid token'

        # token 刷新时间无效
        refresh_exp = datetime.utcnow() - timedelta(days=1)
Esempio n. 19
0
        def wrapper(*args, **kwargs):

            pack = request.headers.get('Authorization', None)
            if pack is None:
                raise AuthenticationError(401, 'token not found')
            parts = pack.split()
            # Authorization 头部值必须为 'jwt <token_value>' 这种形式
            if parts[0].lower() != 'jwt':
                raise AuthenticationError(401, 'invalid token header')
            elif len(parts) == 1:
                raise AuthenticationError(401, 'token missing')
            elif len(parts) > 2:
                raise AuthenticationError(401, 'invalid token')
            token = parts[1]
            user = User.verify_token(token, verify_exp=self.verify_exp)

            # 如果需要验证是否是管理员
            if self.admin and not user.is_admin:
                raise AuthenticationError(403, 'no permission')

            # 将当前用户存入到 g 对象中
            g.user = user
            return func(*args, **kwargs)