def initial_data(self): self.team_owner = User.create(name='test_activity') self.team = Team.create(name='club_test_activity', owner_id=self.team_owner.id) self.user = self.creator = User.create(name='activity_creator') self.activity = Activity.create(team=self.team, creator=self.creator, price='10', vip_price='8', leader=self.creator, title='just a test', description='description', start_time='3000-01-01 00:00:01', end_time='3000-12-31 23:59:59') self.order = OrderService.new_order(10, self.team, self.user, TeamOrder.OrderType.ACTIVITY, TeamOrder.OrderPaymentMethod.WXPAY, self.activity.id, title="UserOrderTest" ) self.activity.add_member(self.user.id, users_count=1, price=10, free_times=0, total_fee=10, order_id=self.order.id, order_no=self.order.order_no, payment_method=TeamOrder.OrderPaymentMethod.WXPAY, payment_state=TeamOrder.OrderState.TRADE_BUYER_PAID, state=TeamMember.TeamMemberState.normal)
def login(self, user: User, expires_days: int = None): self.set_secure_cookie("club_session", tornado.escape.json_encode({ "id": user.id, }), expires_days=expires_days) User.update(last_login=datetime.now()).where( User.id == user.id).execute()
def patch(self, user_id): user = User.get_or_404(id=user_id) self.has_update_permission(user) form = self.validated_arguments if not form: raise ApiException(400, "填写需要修改的属性和值") User.update(**form).where(User.id == user_id).execute() self.set_status(204)
def test_refresh_token(self): self.auth_user = User.create(name='test3', mobile="13838003803", password=User.create_password("123456")) url = "api/2/auth/refresh_token" response = self.fetch(url) self.assertEqual(200, response.code, response.body.decode()) result = json.loads(response.body.decode()) self.assertIn("session", result, result) self.assertIn("current_user", result, result)
def initial_data(self): self.team_owner = User.create(name='test_activity') self.team = Team.create(name='club_test_activity', owner_id=self.team_owner.id) self.user = self.creator = User.create(name='activity_creator') self.activity = Activity.create(team=self.team, creator=self.creator, price='10', vip_price='8', leader=self.creator, title='just a test', description='description')
def post(self): form = MobileResetPasswordForm(self.arguments) if form.validate() and self.validate_verify_code(form): User.update(password=User.create_password( self.get_argument("password"))).where( User.mobile == self.get_argument("mobile")).execute() self.flash("重置密码成功,请使用新密码登录") self.redirect(self.reverse_url("club_auth_login")) self.render("password/mobile_reset_password.html", form=form)
def test_create(self): """ 测试创建用户 实际并不迫切需要此测试 """ user = User.create( name='test_user', mobile=13800138000 ) _user = User.get(User.mobile == 13800138000) self.assertEqual(user.id, _user.id)
def test_login(self): user = User.create(name='test2', mobile="13838003802", password=User.create_password("123456")) url = "api/2/auth/login" body = {"username": "******", "password": "******"} response = self.fetch(url, method="POST", body=json.dumps(body)) self.assertEqual(200, response.code, response.body.decode()) result = json.loads(response.body.decode()) self.assertIn("session", result, result) self.assertIn("current_user", result, result)
def post(self): username = self.validated_arguments['username'] verify_code = self.validated_arguments['verify_code'] new_password = self.validated_arguments['new_password'] if is_mobile(username): if not self.verify_mobile(username, verify_code): raise ApiException(400, "验证码错误,请重新输入") user = User.get_or_none(mobile=username) if not user: raise ApiException(400, "手机号还没有注册") User.update(password=User.create_password(new_password)).where( User.id == user.id).execute() elif username.find("@") > 0: user = User.get_or_none(email=username) if not user: raise ApiException(400, "邮箱还没有注册") User.update(password=User.create_password(new_password)).where( User.id == user.id).execute() else: raise ApiException(400, "用户名格式有误,请填写手机号或电子邮箱") self.write_success()
def initial_data(self): self.team_owner = User.create(name='test_activity') self.team = Team.create(name='club_test_activity', owner_id=self.team_owner.id) self.user = self.creator = User.create(name='activity_creator') self.activity = Activity.create(team=self.team, creator=self.creator, price='10', vip_price='8', leader=self.creator, title='just a test', description='description', need_nickname=True, join_end="3000-12-30 22:59:59", max_members=10, start_time='3000-01-01 00:00:01', end_time='3000-12-31 23:59:59') self.activity_2 = Activity.create(team=self.team, creator=self.creator, price='10', vip_price='8', leader=self.creator, title='just a test', description='description', need_nickname=True, join_end="3000-12-30 22:59:59", max_members=10, start_time='3000-01-01 00:00:01', end_time='3000-12-31 23:59:59') self.activity_member = ActivityMember.create( activity=self.activity, user=self.user, total_fee='0.01', nickname="leave activities", payment_method=TeamOrder.OrderPaymentMethod.WXPAY.value, payment_state=TeamOrder.OrderState.TRADE_BUYER_PAID, ) TeamMemberService.new_order(team=self.team, activity_id=self.activity.id, user=self.user, order_type=TeamOrder.OrderType.ACTIVITY, payment_method='wxpay', total_fee=self.activity.price, payment_fee=self.activity.price, title='TestLeave') TeamOrder.update(state=TeamOrder.OrderState.TRADE_BUYER_PAID)\ .where(TeamOrder.activity_id == self.activity.id, TeamOrder.user == self.user)\ .execute()
def initial_data(self): self.team_owner = User.create(name='test_activity') self.team = Team.create(name='club_test_activity', owner_id=self.team_owner.id) self.user = self.creator = User.create(name='activity_creator') self.activity = Activity.create(team=self.team, creator=self.creator, price='10', vip_price='8', leader=self.creator, title='just a test', description='description', start_time='3000-01-01 00:00:01', end_time='3000-12-31 23:59:59', max_members=10)
def initial_database(): """ 初始化数据库, 重建旧表 创建表 Returns: """ # TODO: 重复代码抽象 from yiyun.helpers import find_subclasses from yiyun.models import BaseModel, Sport, User, Team, Activity # drop old database and create new; test_settings = reject_settings() test_db = test_settings['db_name'] raw_sql = ("drop database {test_db};" "create database {test_db};" "use {test_db};") # create new tables BaseModel._meta.database.execute_sql(raw_sql.format(test_db=test_db)) models = find_subclasses(BaseModel) if not Sport.table_exists(): Sport.create_table() if not User.table_exists(): User.create_table() if not Team.table_exists(): Team.create_table() if not Activity.table_exists(): Activity.create_table() for model in models: if model._meta.db_table.startswith("__"): logging.debug(("table skip: " + model._meta.db_table)) elif model.table_exists(): logging.debug(('table exist: ' + model._meta.db_table)) else: model.create_table() logging.debug(('table created: ' + model._meta.db_table)) logging.debug('create all [ok]')
def post(self): username = self.validated_arguments['username'].lower() password = self.validated_arguments['password'] if len(username) == 0 or len(password) == 0: raise ApiException(400, "用户名和密码不能为空") fail_times_key = "yiyun:user:%s:login_fail_times" % username if intval(self.redis.get(fail_times_key)) >= 5: raise ApiException(403, "密码错误次数太多,请休息10分钟再试") if is_mobile(username): user = User.get_or_none(mobile=username) elif username.find('@') > 0: user = User.get_or_none(email=username) else: raise ApiException(400, "用户名格式不正确,请填写手机号或电子邮箱") if not password or not user \ or not User.check_password(user.password, password): fail_times = intval(self.redis.incr(fail_times_key)) if fail_times == 1: self.redis.expire(fail_times_key, 600) raise ApiException(403, "密码有误,如果没有设置密码请使用手机号找回密码") # 重试次数归零 self.redis.delete(fail_times_key) if not user.is_active(): raise ApiException(403, "你的账户不可用,无法登录") update = {"last_login": datetime.now()} if self.device_id > 0: update["last_device_id"] = self.device_id User.update(**update).where(User.id == user.id).execute() if user and self.device_id: Device.update(owner_id=user.id).where( Device.id == self.device_id).execute() self.write(self.create_session(user))
def test_create_team(self): body = { "name": "test create team", "description": "description", "notice": "club notice", "province": "四川", "city": "成都", "address": "天府三街", "contact_person": "contact person", "contact_phone": "contact phone", "lat": 123.0000001, "lng": 123.0000002, "open_type": 2, "state": 1, } self.auth_user = User.create(name="create team") response = self.fetch(self.MODEL_PATH, method="POST", body=json.dumps(body)) self.assertEqual(201, response.code, response.body.decode()) result = json.loads(response.body.decode()) self.assertEqual(0, result['state']) self.assertEqual(self.auth_user.id, result['owner_id'], "创建俱乐部时 owner 错误") body.pop('state') for k, v in body.items(): self.assertEqual(v, result[k], (k, v))
def __init__(self, *args, **kwargs): super(CreateActivityFrom, self).__init__(*args, **kwargs) obj = kwargs.get("obj", None) team = kwargs.get("team", None) if not isinstance(team, Team): raise AssertionError("must a team") if obj and obj.province: province = obj.province else: province = self.province.choices[0][0] if province: self.city.choices = ChinaCity.get_cities(province) leaders = team.get_members(role="leader") leaders.insert(0, User.get_or_none(id=team.owner_id)) if leaders: self.leader.choices = [(str(user.id), user.name or user.mobile) for user in leaders] groups = team.groups if groups: self.allow_groups.choices = [(str(group.id), group.name) for group in groups]
def get_members(self, limit=20, offset=0, role="", state=None): """ 获取俱乐部成员 """ q = User.select( User, TeamMember ).join( TeamMember, on=TeamMember.user ).where( TeamMember.team == self ) if role == "leader": q = q.where(TeamMember.role >= self.TeamRole.leader) elif role == "admin": q = q.where(TeamMember.role >= self.TeamRole.admin) if isinstance(state, int): q = q.where(TeamMember.state >= state) q = q.order_by( TeamMember.role.desc() ).offset(offset).limit(limit) users = [] for user in q: users.append(user) return users
def test_over_left_count_activity(self): payment = Activity.PaymentType.ONLINE_PAY.value activity = Activity.create(team=self.team, creator=self.creator, leader=self.creator, price='10', vip_price='10', payment_type=payment, title='no online pay', description='on need online pay', state=Activity.ActivityState.opening.value, join_end="3000-12-30 22:59:59", allow_agents=10, start_time='3000-01-01 00:00:01', end_time='3000-12-31 23:59:59', members_count=2, max_members=10) body = { "payment": "wxpay", "nickname": "Nick name", "users_count": 11, } url = self.JOIN_ACTIVITY.format(activity_id=activity.id) self.auth_user = User.create(name='closed activity') response = self.fetch(url, method="POST", body=json.dumps(body), params={'team_id': self.team.id}, headers={"Content-Type": "application/json"}) self.assertEqual(400, response.code, response.body) result = json.loads(response.body.decode()) error = result["error"] self.assertEqual("该活动只有 8 名额了", error, error)
def test_stoped_activity(self): """活动已报名截止""" payment = Activity.PaymentType.ONLINE_PAY.value activity = Activity.create( team=self.team, creator=self.creator, leader=self.creator, price='10', vip_price='10', start_time='2000-01-01 00:00:01', end_time='3000-12-31 23:59:59', join_end="3000-12-30 22:59:59", payment_type=payment, title='no online pay', description='on need online pay', state=Activity.ActivityState.opening.value, ) body = {"payment": "wxpay", "nickname": "Nick name"} url = self.JOIN_ACTIVITY.format(activity_id=activity.id) self.auth_user = User.create(name='closed activity') response = self.fetch(url, method="POST", body=json.dumps(body), params={'team_id': self.team.id}) self.assertEqual(400, response.code, response.body) result = json.loads(response.body.decode()) error = result["error"] self.assertEqual("活动已报名截止", error, error)
def post(self): email = self.validated_arguments['email'] if email.find("@") <= 0: raise ApiException(400, "电子邮箱格式有误") user = User.get_or_none(email=email) if not user: raise ApiException(404, "你还没有注册或用户名有误") verify_code = self.redis.get("yiyun:email:verify_code:%s" % email) if not verify_code: verify_code = random.randint(1000, 9999) # 验证码两小时内有效 self.redis.set("yiyun:email:verify_code:%s" % email, verify_code) self.redis.expire("yiyun:email:verify_code:%s" % email, 3600 * 24) # 发送验证邮件 tasks.user.send_forgot_email.delay(user.name or email, email, verify_code) self.write_success()
def get_current_user(self): access_token = self.get_access_token() logging.debug("get access token: {0}".format(access_token)) if access_token: if access_token.startswith("2.0@"): try: user, data = User.verify_auth_token(access_token) if user is None: self.logger.debug("非法会话: %s" % data) raise ApiException(1004, "非法会话,用户不存在", status_code=401) if not user.is_active(): raise ApiException(1005, "账号被禁止登录", status_code=401) return user except jwt.ExpiredSignatureError: raise ApiException(1002, "会话已过期,请重新登录", status_code=401) except jwt.InvalidTokenError: raise ApiException(1003, "非法会话,请重新登录", status_code=403) else: user_info = self.get_session(access_token) user_info['id'] = user_info['userId'] return storage(user_info) return None
def post(self): form = ChangePasswordForm(self.arguments) if form.validate() and self.validate_password(form): User.update( password=User.create_password(self.get_argument("newPassword")) ).where( User.id == self.current_user.id ).execute() self.flash("修改密码成功!", category='success') self.redirect(self.reverse_url("club_account_change_password")) return self.render("account/change_password.html", form=form)
def validate_email_existed(form): user = User.get_or_none(email=form.new_email.data) if user: form.new_email.errors.append('邮箱已存在') return False else: return True
def post(self): form = LoginForm(self.arguments) if form.validate(): user = self.have_user(form.username.data) if user and User.check_password(user.password, form.password.data): remember_me = self.get_argument("remember", "off") if remember_me == "on": expires_days = 30 else: expires_days = None self.login(user, expires_days) team = Team.get_or_none(owner_id=user.id) if team is None: return self.redirect(self.reverse_url("club_create")) elif team.state == 0: return self.redirect(self.reverse_url("club_wait_approve")) elif self.next_url: return self.redirect(self.next_url) else: return self.redirect(self.reverse_url("club_home")) messages = [('danger', '登录失败:账号或密码不正确')] self.render("login.html", form=form, messages=messages)
def post(self): form = LoginVerifyCodeForm(self.arguments) fail = False if form.validate() and self.validate_verify_code(form): user = User.get_or_none(mobile=self.get_argument("mobile")) if user: remember_me = self.get_argument("remember", "off") if remember_me == "on": expires_days = 30 else: expires_days = None self.login(user, expires_days) team = Team.get_or_none(owner_id=user.id) if team is None: self.redirect(self.reverse_url("club_create")) return if team.state == 0: self.redirect(self.reverse_url("club_wait_approve")) return if self.next_url: self.redirect(self.next_url) else: self.redirect(self.reverse_url("club_home")) return fail = True self.render("login-by-sms.html", form=form, fail=fail)
def test_online_pay_activity(self): url = self.JOIN_ACTIVITY.format(activity_id=self.activity.id) body = {"payment": "wxpay", "nickname": "Nick name"} self.auth_user = User.create(name='join activity') response = self.fetch(url, method='POST', body=json.dumps(body), params={'team_id': self.team.id}) self.assertEqual(200, response.code, response.body) order = TeamOrder.get_or_none(user=self.auth_user, activity_id=self.activity.id) self.assertIsNotNone(order, "加入活动时订单 `TeamOrder` 未创建") result = json.loads(response.body.decode()) expect = { "status": "ok", "state": ActivityMember.ActivityMemberState.wait_confirm.value, "payment_state": TeamOrder.OrderState.WAIT_BUYER_PAY.value, "order_no": order.order_no } self.assertDictEqual(expect, result, result) member = ActivityMember.get_or_none(activity=self.activity, user=self.auth_user) self.assertIsNotNone(member, "加入活动后 `ActivityMember` 未添加记录")
def get(self): """ 获取用户列表 """ keyword = self.get_argument("kw", "") sort = intval(self.get_argument("sort", 0)) query = User.select() if keyword: query = query.where((User.name.contains(keyword)) | (User.mobile == keyword)) if sort == 2: query = query.order_by(User.name.desc()) else: query = query.order_by(User.id.desc()) users = self.paginate_query(query) self.render( "user/list.html", users=users, )
def validate_password(self, form): password = self.get_argument("password") if not password or \ not User.check_password(self.current_user.password, password): form.password.errors = [ValidationError("旧密码不正确")] return False return True
def test_patch_team_permission_deny(self): url = self.OBJECT_PATH.format(team_id=self.team.id) body = {"name": "new name"} self.auth_user = User.create(name="permission deny for patch team") response = self.fetch(url, method="PATCH", body=json.dumps(body)) self.assertEqual(403, response.code, response.body.decode) updated = Team.get(id=self.team.id) self.assertNotEqual("new name", updated.name, "权限错误, 但是跟新成功了")
def sync_user_info(self, extra_fields): """ 同步报名信息到用户信息 """ update_user_attrs = {} if not self.current_user.name and extra_fields.get("nickname", None): update_user_attrs['name'] = extra_fields['nickname'] if self.current_user.gender not in ('f', 'm') and \ extra_fields.get("gender", None): update_user_attrs['gender'] = extra_fields['gender'] if update_user_attrs: User.update( **update_user_attrs ).where( User.id == self.current_user.id ).execute()
def test_reset_password(self): user = User.create(name='test4', mobile="13838003804", password=User.create_password("123456")) new_password = "******" url = "api/2/auth/reset_password" body = { "username": "******", "verify_code": "8888", "new_password": new_password } response = self.fetch(url, method="POST", body=json.dumps(body)) self.assertEqual(200, response.code, response.body.decode()) user = User.get(id=user.id) result = User.check_password(user.password, new_password) self.assertEqual(True, result, result)