示例#1
0
 def new(cls, password: str, sid_orig: str) -> None:
     db = get_mongodb()
     db[cls.collection_name].insert({
         "sid_orig": sid_orig,
         "time": datetime.datetime.now(),
         "password": password
     })
示例#2
0
    def new_register_request(cls,
                             sid_orig: str,
                             verification_method: str,
                             status: str,
                             password: str = None) -> str:
        """
        add a new register request

        :param sid_orig: original sid
        :param verification_method: password or email
        :param status: status of the request
        :param password: if register by password, save everyclass password (not jw password) here
        :return: the `request_id`
        """
        if verification_method not in ("email", "password"):
            raise ValueError(
                "verification_method must be one of email, password")
        db = get_mongodb()
        doc = {
            "request_id": uuid.uuid4(),
            "create_time": datetime.datetime.now(),
            "sid_orig": sid_orig,
            "verification_method": verification_method,
            "status": status
        }
        if password:
            doc.update({"password": generate_password_hash(password)})
        db[cls.collection_name].insert(doc)
        return str(doc["request_id"])
示例#3
0
 def exist(cls, sid_orig: str) -> bool:
     """check if a student has registered"""
     db = get_mongodb()
     result = db.user.find_one({'sid_orig': sid_orig})
     if result:
         return True
     return False
示例#4
0
 def create_index(cls) -> None:
     db = get_mongodb()
     db.get_collection(cls.collection_name).create_index(
         [("course_id", 1), ("teach_type", 1), ("teacher_id_str", 1)],
         unique=True)
     db.get_collection(cls.collection_name).create_index([("cotc_id", 1)],
                                                         unique=True)
示例#5
0
 def get_visitors(cls, sid_orig: str) -> List[Dict]:
     """获得访客列表"""
     db = get_mongodb()
     result = db[cls.collection_name].find({
         "host": sid_orig
     }).sort("last_time", -1).limit(50)
     visitor_list = []
     for people in result:
         stu_cache = RedisCacheDAO.get_student(people["visitor"])
         if stu_cache:
             visitor_list.append({
                 "name": stu_cache.name,
                 "sid": stu_cache.sid,
                 "visit_time": people["last_time"]
             })
         else:
             # query api-server
             with elasticapm.capture_span('rpc_search'):
                 rpc_result = HttpRpc.call(
                     method="GET",
                     url='{}/v1/search/{}'.format(
                         current_app.config['API_SERVER_BASE_URL'],
                         people["visitor"]),
                     retry=True)
             visitor_list.append({
                 "name": rpc_result["student"][0]["name"],
                 "sid": rpc_result["student"][0]["sid"],
                 "visit_time": people["last_time"]
             })
             RedisCacheDAO.set_student(
                 Student(sid_orig=people["visitor"],
                         name=rpc_result["student"][0]["name"],
                         sid=rpc_result["student"][0]["sid"]))
     return visitor_list
示例#6
0
 def get_level(cls, sid_orig: str) -> int:
     """获得学生的隐私级别。0为公开,1为实名互访,2为自己可见。默认为配置文件中定义的 DEFAULT_PRIVACY_LEVEL"""
     db = get_mongodb()
     doc = mongo_with_retry(db[cls.collection_name].find_one,
                            {"sid_orig": sid_orig},
                            num_retries=1)
     return doc["level"] if doc else get_config().DEFAULT_PRIVACY_LEVEL
示例#7
0
 def get_my_review(cls, cotc_id: int, student_id: str) -> Dict:
     db = get_mongodb()
     doc = db.get_collection(cls.collection_name).find_one({
         "cotc_id":
         cotc_id,
         "student_id":
         student_id
     })
     return doc
示例#8
0
 def add_user(cls, sid_orig: str, password: str) -> None:
     """add a user"""
     db = get_mongodb()
     if db[cls.collection_name].find_one({"sid_orig": sid_orig}):
         raise ValueError("sid_orig repeated")
     db.user.insert({
         "sid_orig": sid_orig,
         "create_time": datetime.datetime.now(),
         "password": generate_password_hash(password)
     })
示例#9
0
 def migrate(cls) -> None:
     """migrate data from mongodb"""
     mongo = get_mongodb()
     with pg_conn_context() as pg_conn, pg_conn.cursor() as cursor:
         results = mongo.get_collection("privacy_settings").find()
         for each in results:
             insert_query = "INSERT INTO privacy_settings (student_id, level, create_time) VALUES (%s,%s,%s)"
             cursor.execute(
                 insert_query,
                 (each['sid_orig'], each['level'], each['create_time']))
         pg_conn.commit()
     print("Migration finished.")
示例#10
0
 def migrate(cls) -> None:
     """migrate data from mongodb"""
     mongo = get_mongodb()
     with pg_conn_context() as pg_conn, pg_conn.cursor() as cursor:
         results = mongo.get_collection("visitor_track").find()
         for each in results:
             insert_query = "INSERT INTO visit_tracks (host_id, visitor_id, last_visit_time) VALUES (%s,%s,%s)"
             cursor.execute(
                 insert_query,
                 (each['host'], each['visitor'], each['last_time']))
         pg_conn.commit()
     print("Migration finished.")
示例#11
0
    def migrate(cls):
        """migrate data from mongodb"""
        mongo = get_mongodb()

        with pg_conn_context() as pg_conn, pg_conn.cursor() as cursor:
            results = mongo.get_collection("simple_passwords").find()
            for each in results:
                insert_query = "INSERT INTO simple_passwords (student_id, time, password) VALUES (%s,%s,%s)"
                cursor.execute(
                    insert_query,
                    (each['sid_orig'], each['time'], each['password']))
            pg_conn.commit()
        print("Migration finished.")
示例#12
0
    def get_review(cls, cotc_id: int) -> Dict:
        """
        获得一个教学班集合的评价
        {
            "avg_rate": 4.3,
            "count"   : 1,
            "reviews": [
                {
                    "review"  : "老师讲得好",
                    "rate"    : 5,
                    "stu_name": "16级软件工程专业学生"
                },
            ]
        }

        :param cotc_id: 教学班集合 ID
        :return:
        """
        db = get_mongodb()
        result = db.get_collection(cls.collection_name).aggregate([{
            "$match": {
                "cotc_id": int(cotc_id)
            }
        }, {
            "$project": {
                "_id": 0,
                "student_id": 0,
                "cotc_id": 0
            }
        }, {
            "$group": {
                "_id": None,
                "avg_rate": {
                    "$avg": "$rate"
                },
                "reviews": {
                    "$push": "$$ROOT"
                },
                "count": {
                    "$sum": 1
                }
            }
        }])
        result = list(result)

        if result:
            result = result[0]
        else:
            result = {"avg_rate": 0, "reviews": [], "count": 0}
        return result
示例#13
0
    def get_id_by_card(cls, card: CardResult) -> int:
        """
        从 api-server 返回的 CardResult 获得对应的“教学班集合” ID,如果不存在则新建
        """
        teachers = [{
            "name": x.name,
            "teacher_id": x.teacher_id
        } for x in card.teachers]
        teacher_name_str = '、'.join([x.name for x in card.teachers])

        card_name = card.name

        teach_type = 1
        if '辅修' in card.name:
            teach_type = 2
        elif '重修' in card.name:
            teach_type = 3
            # 教务会有“线性代数-新校区重修班-重修”这样的名字。对于重修班来说,在同一个老师不同校区对授课内容没有影响,所以这里标准化,
            # 在名字中去掉校区。
            name_splitted = [x for x in card_name.split("-") if x != '']
            card_name = ""
            for item in name_splitted:
                if '重修' not in item:
                    card_name = card_name + item
                else:
                    card_name = card_name + "-重修"
                    break

        db = get_mongodb()
        doc = db.get_collection(cls.collection_name).find_one_and_update(
            {
                'course_id': card.course_id,
                'teach_type': teach_type,
                'teacher_id_str': teacher_list_to_tid_str(card.teachers)
            }, {
                "$setOnInsert": {
                    "cotc_id": Redis.new_cotc_id(),
                    'name': card_name,
                    'teachers': teachers,
                    'teacher_name_str': teacher_name_str
                }
            },
            upsert=True,
            new=True)
        # you must set "new=True" in upsert case
        # https://stackoverflow.com/questions/32811510/mongoose-findoneandupdate-doesnt-return-updated-document

        return doc['cotc_id']
示例#14
0
    def insert_calendar_token(cls, resource_type: str, semester: str,
                              identifier: str) -> str:
        """生成日历令牌,写入数据库并返回字符串类型的令牌"""
        token = uuid.uuid4()

        db = get_mongodb()
        doc = {
            'type': resource_type,
            "create_time": datetime.datetime.now(),
            "identifier": identifier,
            'semester': semester,
            'token': token
        }

        db[cls.collection_name].insert(doc)
        return str(token)
示例#15
0
 def edit_my_review(cls, cotc_id: int, student_id: str, rate: int,
                    review: str, name: str) -> None:
     db = get_mongodb()
     db.get_collection(cls.collection_name).update_one(
         filter={
             "cotc_id": cotc_id,
             "student_id": student_id
         },
         update={
             "$set": {
                 "rate": rate,
                 "review": review,
                 "student_name": name
             }
         },
         upsert=True)
示例#16
0
    def migrate(cls) -> None:
        """migrate data from mongodb"""
        mongo = get_mongodb()
        with pg_conn_context() as pg_conn, pg_conn.cursor() as cursor:
            results = mongo.get_collection("calendar_token").find()
            for each in results:
                insert_query = """
                INSERT INTO calendar_tokens (type, identifier, semester, token, create_time, last_used_time)
                    VALUES (%s,%s,%s,%s,%s,%s)
                """

                cursor.execute(
                    insert_query,
                    (each['type'], each['identifier'], each['semester'],
                     each['token'], each['create_time'],
                     each['last_used'] if 'last_used' in each else None))
            pg_conn.commit()
        print("Migration finished.")
示例#17
0
    def update_track(cls, host: str, visitor: Student) -> None:
        """
        Update time of visit. If this is first time visit, add a new document.

        @:param host: original sid of host
        @:param visitor_sid_orig: original sid of visitor
        @:return None
        """
        db = get_mongodb()
        criteria = {
            "host": host,
            "visitor": visitor.sid_orig,
            "visitor_type": "student"
        }
        new_val = {"$set": {"last_time": datetime.datetime.now()}}
        db[cls.collection_name].update(criteria, new_val, True)  # upsert

        RedisCacheDAO.set_student(student=visitor)
示例#18
0
 def set_level(cls, sid_orig: str, new_level: int) -> None:
     """Set privacy level for a student"""
     db = get_mongodb()
     criteria = {"sid_orig": sid_orig}
     doc = db[cls.collection_name].find_one(criteria)
     if doc:
         db[cls.collection_name].update_one(criteria,
                                            {"$set": {
                                                "level": new_level
                                            }})
     else:
         db[cls.collection_name].insert({
             "create_time":
             datetime.datetime.now(),
             "sid_orig":
             sid_orig,
             "level":
             new_level
         })
示例#19
0
    def migrate(cls):
        """migrate data from mongodb"""
        mongo = get_mongodb()

        with pg_conn_context() as pg_conn, pg_conn.cursor() as cursor:
            results = mongo.get_collection("verification_requests").find()
            for each in results:
                insert_query = """
                INSERT INTO identity_verify_requests (request_id, identifier, method, status, create_time, extra)
                    VALUES (%s,%s,%s,%s,%s,%s)
                """

                cursor.execute(insert_query,
                               (each['request_id'], each['sid_orig'],
                                each['verification_method'], each['status'],
                                each['create_time'], {
                                    'password': each['password']
                                } if 'password' in each else None))
            pg_conn.commit()
        print("Migration finished.")
示例#20
0
    def find_calendar_token(cls,
                            tid=None,
                            sid=None,
                            semester=None,
                            token=None):
        """通过 token 或者 sid/tid + 学期获得 token 文档"""
        db = get_mongodb()
        if token:
            return db[cls.collection_name].find_one(
                {'token': uuid.UUID(token)})
        elif tid and semester:
            new = db[cls.collection_name].find_one({
                'identifier': tid,
                'semester': semester
            })
            if new:
                return new
            else:
                legacy = db[cls.collection_name].find_one({
                    'tid': tid,
                    'semester': semester
                })
                return legacy

        elif sid and semester:
            new = db[cls.collection_name].find_one({
                'identifier': sid,
                'semester': semester
            })
            if new:
                return new
            else:
                legacy = db[cls.collection_name].find_one({
                    'tid': sid,
                    'semester': semester
                })
                return legacy
        else:
            raise ValueError(
                "tid/sid together with semester or token must be given to search a token document"
            )
示例#21
0
 def create_index(cls) -> None:
     db = get_mongodb()
     db.get_collection(cls.collection_name).create_index([("cotc_id", 1)],
                                                         unique=True)
示例#22
0
    def upgrade(cls, key):
        """字段升级"""
        def fill_16(text):
            """
            自动填充至十六位或十六的倍数
            :param text: 需要被填充的字符串
            :return: 已经被空白符填充的字符串
            """
            text += '\0' * (16 - (len(text) % 16))
            return str.encode(text)

        def aes_decrypt(aes_key, aes_text):
            """
            使用密钥解密文本信息,将会自动填充空白字符
            :param aes_key: 解密密钥
            :param aes_text: 需要解密的文本
            :return: 经过解密的数据
            """
            # 初始化解码器
            cipher = AES.new(fill_16(aes_key), AES.MODE_ECB)
            # 优先逆向解密十六进制为bytes
            decrypt = a2b_base64(aes_text.replace('-', '/').encode())
            # 使用aes解密密文
            decrypt_text = str(cipher.decrypt(decrypt),
                               encoding='utf-8').replace('\0', '')
            # 返回执行结果
            return decrypt_text.strip()

        def identifier_decrypt(key, data):
            print("key:{} data:{}".format(key, data))
            data = aes_decrypt(key, data)
            # 通过正则校验确定数据的正确性
            group = re.match(r'^(student|teacher|klass|room);([\s\S]+)$', data)
            if group is None:
                raise ValueError('解密后的数据无法被合理解读,解密后数据:%s' % data)
            else:
                return group.group(1), group.group(2)

        db = get_mongodb()
        teacher_docs = db[cls.collection_name].find({"tid": {"$exists": True}})
        for each in teacher_docs:
            print(each)
            db[cls.collection_name].update_one(
                each, {
                    "$set": {
                        "identifier": identifier_decrypt(key, each["tid"])[1],
                        "type": "teacher"
                    },
                    "$unset": {
                        "tid": 1
                    }
                })
        student_docs = db[cls.collection_name].find({"sid": {"$exists": True}})
        for each in student_docs:
            print(each)
            db[cls.collection_name].update_one(
                each, {
                    "$set": {
                        "identifier": identifier_decrypt(key, each["sid"])[1],
                        "type": "student"
                    },
                    "$unset": {
                        "sid": 1
                    }
                })
示例#23
0
 def reset_tokens(cls, sid: str) -> None:
     """删除学生所有的 token"""
     db = get_mongodb()
     db[cls.collection_name].remove({"sid": sid})
示例#24
0
 def create_index(cls) -> None:
     db = get_mongodb()
     db[cls.collection_name].create_index("token", unique=True)
     db[cls.collection_name].create_index([("tid", 1), ("semester", 1)])
     db[cls.collection_name].create_index([("sid", 1), ("semester", 1)])
示例#25
0
 def get_doc(cls, cotc_id: int) -> Optional[Dict]:
     """获得 cotc_id 对应的文档,可能为 None """
     db = get_mongodb()
     return db.get_collection(cls.collection_name).find_one(
         {'cotc_id': cotc_id})
示例#26
0
 def check_password(cls, sid_orig: str, password: str) -> bool:
     """verify a user's password. Return True if password is correct, otherwise return False."""
     db = get_mongodb()
     doc = db.user.find_one({'sid_orig': sid_orig})
     return check_password_hash(doc['password'], password)
示例#27
0
 def get_request_by_id(cls, req_id: str) -> Optional[Dict]:
     db = get_mongodb()
     return db[cls.collection_name].find_one(
         {'request_id': uuid.UUID(req_id)})
示例#28
0
 def set_request_status(cls, request_id: str, status: str) -> None:
     """mark a verification request's status as email token passed"""
     db = get_mongodb()
     query = {"request_id": uuid.UUID(request_id)}
     new_values = {"$set": {"status": status}}
     db[cls.collection_name].update_one(query, new_values)
示例#29
0
 def create_index(cls) -> None:
     db = get_mongodb()
     db[cls.collection_name].create_index([("sid_orig", 1)], unique=True)
示例#30
0
 def create_index(cls) -> None:
     db = get_mongodb()
     db[cls.collection_name].create_index([("host", 1), ("last_time", 1)],
                                          unique=True)