class RegisterLink(Resource): """ EMail verification. Send verify code to user's EMail. """ name = 'register_link' code = {} @args(require=['email']) @email_verify def get(self, email): """ Send EMail to certain user. One user can only be send once per 30 min. :param email: GET params or JSON data. :return: Result. """ if not _email_to_sid(email).isdigit(): return jsonDict(False, '老师的邮箱注册暂未开放(防止对老师形成骚扰),请手动联系我们进行注册。') if (code_tuple := RegisterLink.code.get(email, None)) is not None: if datetime.now() < code_tuple[1] + timedelta(minutes=1): return jsonDict(False, '请1分钟后再试。') RegisterLink.code[email] = (vcode := str(uuid.uuid4()), datetime.now()) try: email_sender = EmailSender() # TODO Remove the following comment mark in production. email_sender.send_msg(f'您的SUSTechFlow注册链接是:https://sustechflow.top/signup?vcode={vcode}', email) return jsonDict(True, '发送成功') except: return jsonDict(False, 'Email发送失败')
def put(self, username, password, email, vcode): """ User registration. :param username: JSON data. :param password: JSON data. :param email: JSON data. :param vcode: Verify code JSON data. :return: Token and username. The token should be attached when request a *auth_required* API. """ if not Verification.verify(email, vcode): if not RegisterLink.verify(email, vcode): return jsonDict(False, '验证码错误') permanent_token = Key.hashpw(password) temp_token = session.sign_jwt_token(username) db = db_client[db_name] if db.User.count_documents({"username": username}) >= 1: return jsonDict(False, '用户已存在') if db.User.count_documents({"email": email}) >= 1: return jsonDict(False, '用户已存在') ins_res = db.User.insert_one({ "username": username, "email": email, "permanent_token": permanent_token, 'learnt_course': [] }) if not ins_res.acknowledged: return jsonDict(False, '无法与数据库通信') return jsonDict(True, '注册成功', temp_token=temp_token, username=username)
class Verification(Resource): """ EMail verification. Send verify code to user's EMail. """ name = 'verify' code = {} @args(require=['email']) @email_verify def get(self, email): """ Send EMail to certain user. One user can only be send once per 30 min. :param email: GET params or JSON data. :return: Result. """ if (code_tuple := Verification.code.get(email, None)) is not None: if datetime.now() < code_tuple[1] + timedelta(minutes=1): return jsonDict(False, '请1分钟后再试。') Verification.code[email] = (vcode := str(int(random.uniform(100000, 999999))), datetime.now()) try: email_sender = EmailSender() # TODO Remove the following comment mark in production. email_sender.send_msg(f'你的SUSTechFlow验证码是:{vcode}', email) return jsonDict(True, '发送成功') except: return jsonDict(False, 'Email发送失败')
def rate_verify(rate): required_field = ['likes', 'useful', 'easy'] if isinstance(rate, dict): for field in required_field: if rate.get(field) is None: return jsonDict(False, '评分数据不完整。') rate['ratings'] = 5 return jsonDict(True, '', rate=rate) else: return jsonDict(False, 'rate必须是字典类型。')
def get(self, username): """ Fetch a user's learnt course. :param username: Provided by *auth_required* :return: data: [cid] User's learnt course. """ db = db_client[db_name] user = db.User.find_one({'username': username}) if user is not None: return jsonDict(True, '', data=user['learnt_course']) else: return jsonDict(False, '用户不存在')
def auth_required_func(self, *args, **kwargs): self.parser = reqparse.RequestParser() self.parser.add_argument('Authorization', location='headers') temp_token = self.parser.parse_args()['Authorization'] if temp_token is None: return jsonDict(False, '认证失败') success, username = session.check_jwt_token(temp_token) if success: kwargs['username'] = username return func(self, *args, **kwargs) else: return jsonDict(False, '认证失败')
def get(self, email): """ Send EMail to certain user. One user can only be send once per 30 min. :param email: GET params or JSON data. :return: Result. """ if not _email_to_sid(email).isdigit(): return jsonDict(False, '老师的邮箱注册暂未开放(防止对老师形成骚扰),请手动联系我们进行注册。') if (code_tuple := Verification.code.get(email, None)) is not None: if datetime.now() < code_tuple[1] + timedelta(minutes=1): return jsonDict(False, '请1分钟后再试。')
def post(self, username, cids=None, cid=None): """ Add learnt course(s) for certain user. :param username: Provided by *auth_required* :param cids: Bulker write to add user's learnt course, JSON list :param cid: Insert one learnt course, JSON data. :return: """ db = db_client[db_name] if cids is not None: db.User.update({'username': username}, {'$addToSet': {'learnt_course': {'$each': cids}}}) if cid is not None: db.User.update({'username': username}, {'$addToSet': {'learnt_course': cid}}) if cid is None and cids is None: return jsonDict(False, '你至少需要提供一个参数,cid或者cids') return jsonDict(True, '添加成功', data=True)
def delete(self, username, cids=None, cid=None): """ Remove learnt course(s) for certain user. :param username: Provided by *auth_required* :param cids: Bulker remove user's learnt course, JSON list :param cid: Remove one learnt course, JSON data. :return: """ db = db_client[db_name] if cids is not None: db.User.update({'username': username}, {'$pull': {'learnt_course': {'$in': cids}}}) if cid is not None: db.User.update({'username': username}, {'$pull': {'learnt_course': cid}}) if cid is None and cids is None: return jsonDict(False, '你至少需要提供一个参数,cid或者cids') return jsonDict(True, '删除成功', data=False)
def get(self, username): """ Respond the username based on request Authentication. :param username: Provided by *auth_required*, see its document. :return: username. """ return jsonDict(True, msg='成功', username=username)
def get(self, **kwargs): """ Fetch plan info. :param kwargs: Any filter you want. :return: Just Try. """ db = db_client[db_name] return jsonDict(True, '', data=[c for c in db.Plan.find(kwargs)])
def get(self, **kwargs): """ Fetch course basic info and their rate. :param kwargs: Any filter you want. JSON data. :return: Just Try. """ db = db_client[db_name] return jsonDict(True, '', data=[c for c in db.Rate.find(kwargs)])
def get(self, **kwargs): db = db_client[db_name] comments = list(db.Comment.find(kwargs)) for c in comments: if c['anonymous']: c['commentBy'] = '佚名' comments = list(filter(lambda a: a['content'] != '', comments)) return jsonDict(True, '', data=comments)
class User(Resource): """ User registration and login. """ name = 'user' @auth_required def get(self, username): """ Respond the username based on request Authentication. :param username: Provided by *auth_required*, see its document. :return: username. """ return jsonDict(True, msg='成功', username=username) @args(require=['username', 'password']) def post(self, username, password): """ User login. :param username: Username, JSON data. :param password: Password, JSON data. :return: Token and username. The token should be attached when request a *auth_required* API. """ db = db_client[db_name] if (res := db.User.find_one({'username': username})) is None: res = db.User.find_one({'email': username}) if res is None: return jsonDict(False, '用户不存在') username = res['username'] permanent_token = res['permanent_token'] valid = Key.checkpw(password, permanent_token) if not valid: return jsonDict(False, '用户名或密码错误') else: new_temp_token = session.sign_jwt_token(username) db.User.find_one_and_update( {'username': username}, {'$set': { 'temp_token': new_temp_token }}) return jsonDict(True, '登录成功', temp_token=new_temp_token, username=username)
def get(self, email): """ Send EMail to certain user. One user can only be send once per 30 min. :param email: GET params or JSON data. :return: Result. """ if (code_tuple := Verification.code.get(email, None)) is not None: if datetime.now() < code_tuple[1] + timedelta(minutes=1): return jsonDict(False, '请1分钟后再试。')
def post(self, email, vcode): """ Verify whether a verify code is correct. :param email: User's email. JSON data. :param vcode: Verify code. JSON data. :return: """ if (code_tuple := RegisterLink.code.get(email, None)) is not None: if vcode == code_tuple[0] and datetime.now() < code_tuple[1] + timedelta(minutes=30): return jsonDict(True, '验证成功')
def get(self, **kwargs): db = db_client[db_name] comments = list(db.Comment.find(kwargs)) for c in comments: if c['anonymous']: c['commentBy'] = '佚名' c['username'] = '******' if not c['willing']: c['gpa'] = 'flag{奇迹和魔法都是存在的。}' comments = list(filter(lambda a: a['content'] != '', comments)) return jsonDict(True, '', data=comments)
def get(self, **kwargs): db = db_client[db_name] comments = list(db.Comment.find(kwargs)) data = { 'likes': [0 for _ in range(11)], 'useful': [0 for _ in range(11)], 'easy': [0 for _ in range(11)] } for c in comments: for k, v in c['rate'].items(): if k == 'ratings': continue data[k][int(v * 2)] += 1 return jsonDict(True, '', data=data)
def put(self, **kwargs): rate_tuple = rate_verify(kwargs['rate']) if rate_tuple['success']: kwargs['rate'] = rate_tuple['rate'] kwargs['helpful'] = 0 kwargs['year'] = datetime.now().year kwargs['month'] = datetime.now().month kwargs['day'] = datetime.now().day kwargs['commentBy'] = kwargs['username'] del kwargs['username'] db = db_client[db_name] db.Comment.find_one_and_replace({'cid': kwargs['cid'], 'commentBy': kwargs['commentBy']}, kwargs, upsert=True) return jsonDict(True, '评论成功!') else: return rate_tuple
def get(self): db = db_client[db_name] majors = db.Plan.distinct('major') majors = list(filter(lambda c: c is not None and '通识' not in c, majors)) return jsonDict(True, '', data=majors)
def get(self, **kwargs): db = db_client[db_name] return jsonDict(True, '', data=db.Comment.find_one(kwargs))
str(int(random.uniform(100000, 999999))), datetime.now()) try: email_sender = EmailSender() # TODO Remove the following comment mark in production. email_sender.send_msg(f'你的SUSTechFlow验证码是:{vcode}', email) return jsonDict(True, '发送成功') except: return jsonDict(False, 'Email发送失败') @args(require=['email', 'vcode']) @email_verify def post(self, email, vcode): """ Verify whether a verify code is correct. :param email: User's email. JSON data. :param vcode: Verify code. JSON data. :return: """ if (code_tuple := Verification.code.get(email, None)) is not None: if vcode == code_tuple[0] and datetime.now( ) < code_tuple[1] + timedelta(minutes=30): return jsonDict(True, '验证成功') return jsonDict(False, '验证码错误') @staticmethod def verify(email, vcode): if (code_tuple := Verification.code.get(email, None)) is not None: return code_tuple[0] == str(vcode) return False
username=username) @args(require=['username', 'password', 'new_password']) def patch(self, username, password, new_password): """ Change user's password. NOT USED AND TESTED YET. :param username: :param password: :param new_password: :return: """ db = db_client[db_name] if (res := db.User.find_one({'username': username})) is None: res = db.User.find_one({'email': username}) if res is None: return jsonDict(False, '用户不存在') username = res['username'] if res is None: return jsonDict(False, '用户不存在') permanent_token = res['permanent_token'] valid = Key.checkpw(password, permanent_token) if not valid: return jsonDict(False, '用户名或密码错误') else: new_permanent_token = Key.hashpw(new_password) db.User.find_one_and_update( {'username': username}, {'$set': { 'permanent_token': new_permanent_token }}) return jsonDict(True, '修改成功')
def get(self, **kwargs): db = db_client[db_name] course_info = db.Course.aggregate([ { '$match': kwargs }, { '$lookup': { 'from': 'Detail', 'localField': 'cid', 'foreignField': 'cid', 'as': 'detail' } }, { '$lookup': { 'from': 'Comment', 'let': { 'course_cid': '$cid' }, 'pipeline': [ { '$match': { '$expr': { '$eq': ['$cid', '$$course_cid'] } } }, { '$replaceRoot': { 'newRoot': '$rate' } }, ], 'as': "rate" } }, { '$project': { 'rate': { '$concatArrays': [[{ 'ratings': 0, 'likes': 0, 'useful': 0, 'easy': 0 }], '$rate'] }, 'cid': '$cid', 'name': '$name', 'faculty': '$faculty', 'detail': '$detail', 'taughtBy': '$taughtBy' } }, { '$lookup': { 'from': 'Plan', 'let': { 'course_cid': '$cid' }, 'pipeline': [{ '$match': { '$expr': { '$eq': ['$cid', '$$course_cid'] } } }, { '$group': { '_id': '$grade', 'grade': { '$first': '$grade' }, 'gradePlan': { '$addToSet': { 'optionalType': '$optionalType', 'faculty': '$faculty', 'major': '$major', 'category': '$category', } }, } }, { '$unwind': '$gradePlan' }], 'as': 'plan' } }, { '$unwind': '$detail' }, { '$group': { '_id': '$cid', 'cid': { '$first': '$cid' }, 'name': { '$first': '$name' }, 'taughtBy': { '$addToSet': '$taughtBy' }, 'detail': { '$first': '$detail' }, 'ratings': { '$first': { '$sum': '$rate.ratings' } }, 'likes': { '$first': { '$sum': '$rate.likes' } }, 'useful': { '$first': { '$sum': '$rate.useful' } }, 'easy': { '$first': { '$sum': '$rate.easy' } }, 'plan': { '$first': '$plan' } } }, ]) return jsonDict(True, '', data=[c for c in course_info][0])