def verify_email(self, username, code): r = Redis().r email = self.db["users"].find_one({"username": username})["email"]["address"] verify_data = r.hgetall(email) wrong_count = int(verify_data["wrong"]) MAX = 10 if wrong_count >= MAX: self.db["users"].update_one({"username": username}, {"$set": {"status": {"disable": True, "reason": "verify email crack"}}} ) return {"status": False, "status_code": HTTPStatus.FORBIDDEN, "message": "Account locked. Please stay away"} correct_code = verify_data["code"] if correct_code == code: r.expire(email, 0) r.expire(f"timeout-{email}", 0) self.db["users"].update_one({"username": username}, {"$set": {"email.verified": True}} ) return {"status": True, "status_code": HTTPStatus.CREATED, "message": "success"} else: r.hset(email, "wrong", wrong_count + 1) return {"status": False, "status_code": HTTPStatus.FORBIDDEN, "message": f"verification code is incorrect. You have {MAX - wrong_count} attempts remaining"}
def login_user(self, username: str, password: str, captcha: str, captcha_id: str, ip: str, browser: str) -> dict: # verify captcha in the first place. redis = Redis().r correct_captcha = redis.get(captcha_id) if correct_captcha is None: return { "status_code": HTTPStatus.BAD_REQUEST, "message": "验证码已过期", "status": False } elif correct_captcha.lower() == captcha.lower(): redis.expire(captcha_id, 0) else: return { "status_code": HTTPStatus.FORBIDDEN, "message": "验证码错误", "status": False } # check user account is locked. data = self.db["users"].find_one({"username": username}) or {} if data.get("status", {}).get("disable"): return { "status_code": HTTPStatus.FORBIDDEN, "status": False, "message": data.get("status", {}).get("reason") } returned_value = {"status_code": 0, "message": ""} if data: # try to login stored_password = data["password"] if pbkdf2_sha256.verify(password, stored_password): returned_value["status_code"] = HTTPStatus.OK else: returned_value["status_code"] = HTTPStatus.FORBIDDEN returned_value["message"] = "用户名或密码错误" else: # register hash_value = pbkdf2_sha256.hash(password) try: self.db["users"].insert_one( dict(username=username, password=hash_value, date=ts_date(), ip=ip, browser=browser)) returned_value["status_code"] = HTTPStatus.CREATED except Exception as e: returned_value[ "status_code"] = HTTPStatus.INTERNAL_SERVER_ERROR returned_value["message"] = str(e) returned_value["username"] = data.get("username") returned_value["group"] = data.get("group", ["user"]) return returned_value
def update_user_info(self, username: str, data: dict) -> dict: redis = Redis().r valid_fields = ["email"] valid_data = {} for field in valid_fields: if data.get(field): valid_data[field] = data[field] if valid_data.get("email") and not re.findall(r"\S@\S", valid_data.get("email")): return { "status_code": HTTPStatus.BAD_REQUEST, "status": False, "message": "email format error " } elif valid_data.get("email"): # rate limit user_email = valid_data.get("email") timeout_key = f"timeout-{user_email}" if redis.get(timeout_key): return { "status_code": HTTPStatus.TOO_MANY_REQUESTS, "status": False, "message": f"try again in {redis.ttl(timeout_key)}s" } verify_code = random.randint(10000, 99999) valid_data["email"] = {"verified": False, "address": user_email} # send email confirm subject = "[人人影视下载分享站] 请验证你的邮箱" body = f"{username} 您好,<br>请输入如下验证码完成你的邮箱认证。验证码有效期为24小时。<br>" \ f"如果您未有此请求,请忽略此邮件。<br><br>验证码: {verify_code}" redis.set(timeout_key, username, ex=1800) redis.hset(user_email, mapping={"code": verify_code, "wrong": 0}) redis.expire(user_email, 24 * 3600) send_mail(user_email, subject, body) self.db["users"].update_one({"username": username}, {"$set": valid_data}) return { "status_code": HTTPStatus.CREATED, "status": True, "message": "success" }