def pre_insert_bills(bills): ''' Before insert bill: 1. Make sure now user is at least writer of the bill book of this bill. 2. Set now user as the creater of this bill. 3. Check related categorys, create if not existing. ''' user = get_data('user', 409) for num, bill in enumerate(bills): relation = operator.get('billbook_user_relation', { 'user': user['_id'], 'billbook': bill['billbook'] }) if not relation: billbook = operator.get('billbooks', {'_id': bill['billbook']}) if billbook['status'] > 0: abort(400) elif relation['status'] > 2: abort(400) bills[num]['creater'] = user['_id'] bills[num]['creater_name'] = user['nickname'] if get_transfer_billbook(user['_id']) != bill['billbook']: _check_bill_cats(bill)
def check_billbook_readable(billbook, user, relation=None): billbook = operator.get('billbooks', {'_id': billbook}) status = billbook.get('status') if status <= 1: return True elif relation is not None: return billbook['_id'] in relation else: relation = operator.get('billbook_user_relation', { 'user': user, 'billbook': billbook['_id'] }) return relation is not None return False
def remove(): jwt_status, jwt_result = check_jwt(request) if not jwt_status: return jwt_result _, _, _, payload = jwt_result # get user username = payload.get('username') user = operator.get('users', {'username': username}) if not user: return jsonify({ 'message': '用户不存在' }), 401 # get user info user_info = operator.get('user_infos', {'_id': user['info']}) if user_info: # remove bill books # TODO # if there are other owners, remove user from owner list # if user not owners, remove user from corrensponding list relations = get_user_billbook_relation( operator.id2str(user_info['_id']), True ) print(user['_id'], user['info'], relations, list(relations.keys())) operator.delete_many('billbooks', { '_id': {'$in': list(relations.keys())}, }) operator.delete_many('billbook_user_relation', { 'user': user_info['_id'] }) # TODO # remove the avator if it was saved # remove user info operator.delete('user_infos', {'_id': user_info['_id']}) # remove account operator.delete_many('accounts', {'user': user_info['_id']}) operator.delete('users', {'_id': user['_id']}) return jsonify({ 'message': '删除用户成功' }), 200
def login(): data = request.get_json() username = data.get('username') password = data.get('password') remember = data.get('remember', False) # get user user = operator.get('users', {'username': username}) if not user: return jsonify({ 'message': '用户不存在' }), 401 # check password if not bcrypt_checker(password, user['password']): return jsonify({ 'message': '密码错误' }), 401 # get user info user_info = operator.get('user_infos', {'_id': user['info']}) if not user_info: return jsonify({ 'message': '用户信息加载失败' }), 404 # generate jwt status, new, message, jwt, payload = jwt_run(payload={ 'user': user_info['id'], 'username': username, 'remember': remember }) if not status: return jsonify({ 'message': message }), 400 return jsonify({ 'jwt': jwt if new else '', 'message': message, 'id': user_info['id'], 'username': username, 'nickname': user_info['nickname'], 'avatar': user_info['avatar'] }), 200
def pre_insert_bill_categorys(cats): ''' Before insert category: 1. If the same category exists, stop ''' for num, cat in enumerate(cats): billbook = cat.get('billbook') text = cat.get('text') if operator.get('bill_categorys', {'billbook': billbook, 'text': text}): abort(400)
def instance_auth(self, bill, method): user = get_data('user') if not user: return False creater = bill.get('creater') relation = operator.get('billbook_user_relation', { 'user': user['_id'], 'billbook': bill['billbook'] }) billbook = operator.get('billbooks', {'_id': bill['billbook']}) relation_status = relation['status'] if relation else 4 billbook_status = billbook['status'] # set_data('relation', relation) if method in ['PATCH', 'DELETE']: return billbook_status == 0 or relation_status <= 1 or (user['_id'] is creater and relation_status <= 2) elif method == 'GET': return billbook_status <= 1 or relation_status is not None return False
def _check_bill_cats(bill): billbook = bill.get('billbook') text = bill.get('cat_0') label = bill.get('cat_1', '') cat = operator.get('bill_categorys', {'billbook': billbook, 'text': text}) if cat and label: if cat.get('labels', []): operator.patch('bill_categorys', { '$push': {'labels': label}}, {'_id': cat['_id']}) else: operator.patch('bill_categorys', { '$set': {'labels': [label]}}, {'_id': cat['_id']})
def get_user_billbook_relation(user, with_transfer=False): relations = operator.get_many('billbook_user_relation', {'user': user}) relation_dict = {} for relation in relations: if not with_transfer: billbook = operator.get('billbooks', {'_id': relation['billbook']}) if billbook['name'] == '***transfer***': continue relation_dict[relation['billbook']] = relation['status'] # relations = { # relation['billbook']:relations['status'] # for relation in relations # } return relation_dict
def instance_auth(self, cat, method): user = get_data('user') if not user: return False relation = operator.get('billbook_user_relation', { 'user': user['_id'], 'billbook': cat['billbook'] }) if method in ['DELETE', 'PATCH']: return relation['status'] <= 1 elif method == 'GET': return relation is not None return False
def pre_update_bill_categorys(updates, cat): ''' Before update category: 1. Remove immutable fields 'billbook' 2. If text is going to be change, check whether the same category exsits. If not, change the all related bills and categorys. ''' del_immutable_field(updates, ['billbook']) billbook = cat.get('billbook') text = updates.get('text', None) if text: if operator.get('bill_categorys', {'text': text, 'billbook': billbook}): abort(400)
def pre_insert_relation(relations): ''' Before insert relation: 1. Only owners or managers can add new user. 2. Managers can only add writers or readers ''' user = get_data('user', 409) for num, relation in enumerate(relations): user_relation = operator.get('billbook_user_relation', { 'user': user['_id'], 'billbook': relation['billbook'] }) if not user_relation or user_relation['status'] > 1: abort(409) if relation['status'] <= 1 and user_relation['status'] == 1: abort(409)
def instance_auth(self, relation, method): user = get_data('user') if not user: return False user_relation = operator.get('billbook_user_relation', { 'user': user['_id'], 'billbook': relation['billbook'] }) set_data('relation', user_relation) if method in ['DELETE', 'PATCH']: return user_relation and user_relation['status'] <= 1 elif method == 'GET': return True return False
def check_auth(self, token, allowed_roles, resource, method): status, new, msg, jwt, payload = jwt_run(jwt=token) if not status: return False user_id = payload['user'] user = operator.get('user_infos', {'_id': user_id}) if not user: return False set_data('user', user) args = request.view_args if args: resource_instance = self.get_resource_instance(resource, args['_id']) return self.instance_auth(resource_instance, method) else: return self.resource_auth(method)
def forget(): data = request.get_json() username = data.get('username') password = data.get('password') # get user user = operator.get('users', {'username': username}) if not user: return jsonify({ 'message': '用户不存在' }), 401 # save new password hashed = bcrypt_generator(password) operator.patch('users', {'$set': {'password': hashed}}, { '_id': user['_id']}) return jsonify({ 'message': '修改密码成功' }), 200
def login_jwt(): jwt_status, jwt_result = check_jwt(request) if not jwt_status: return jwt_result new, message, jwt, payload = jwt_result user_id = payload.get('user') username = payload.get('username') user_info = operator.get('user_infos', {'_id': user_id}) if not user_info: return jsonify({ 'message': 'JWT无效, 请重新登录' }), 401 return jsonify({ 'jwt': jwt if new else '', 'message': message, 'id': user_info['id'], 'username': username, 'nickname': user_info['nickname'], 'avatar': user_info['avatar'] }), 200
def instance_auth(self, billbook, method): user = get_data('user') if not user: return False relation = operator.get('billbook_user_relation', { 'user': user['_id'], 'billbook': billbook['_id'] }) if relation: set_data('relation', relation) relation_status = relation['status'] else: relation_status = 4 billbook_status = billbook['status'] if method == 'DELETE': return relation_status <= 0 elif method == 'PATCH': return relation_status <= 1 elif method == 'GET': return billbook_status <= 1 or relation_status <= 3 return False
def get_resource_instance(self, resource, resource_id): return operator.get(resource, {'_id': resource_id})
def register(): data = request.get_json() username = data.get('username') password = data.get('password') remember = data.get('remember', False) nickname = data.get('nickname') # check user user = operator.get('users', {'username': username}) if user: return jsonify({ 'message': '用户已存在' }), 409 # create user_info user_info = operator.post('user_infos', {'nickname': nickname}) if not user_info: return jsonify({ 'message': '用户信息创建失败' }), 407 # create user with hashed password hashed = bcrypt_generator(password) user = operator.post('users', { 'username': username, 'password': hashed, 'info': user_info['_id'] }) if not user: operator.delete('user_infos', {'_id': user_info['_id']}) return jsonify({ 'message': '注册失败' }), 407 # create default account account = operator.post('accounts', { 'name': '默认账户', 'amount': 0.0, 'default': True, 'user': user_info['_id'] }) if not account: operator.delete('user_infos', {'_id': user_info['_id']}) operator.delete('users', {'_id': user['_id']}) return jsonify({ 'message': '用户账户创建失败' }), 407 # creater transfer billbook transfer_billbook = operator.post('billbooks', { 'name': '***transfer***', 'status': 2, 'default': False }) operator.post('billbook_user_relation', { 'user': user_info['_id'], 'billbook': transfer_billbook['_id'], 'status': 0 }) # generate jwt return jsonify({ 'message': '注册成功' }), 200
def get_transfer_billbook(user): relations = operator.get_many('billbook_user_relation', {'user': user}) for relation in relations: billbook = operator.get('billbooks', {'_id': relation['billbook']}) if billbook['name'] == '***transfer***': return billbook['_id']