Example #1
0
def register_by_password_status_refresh(
        request_id: str) -> Tuple[bool, str, Optional[str]]:
    """通过教务密码注册-刷新状态,返回是否成功、auth message及学号/教工号(如果成功)"""
    req = VerificationRequest.find_by_id(uuid.UUID(request_id))
    if not req:
        raise IdentityVerifyRequestNotFoundError
    if req.method != "password":
        logger.warn(
            "Non-password verification request is trying get status from password interface"
        )
        raise IdentityVerifyMethodNotExpectedError
    if req.method == VerificationRequest.STATUS_PWD_SUCCESS:
        raise RequestIDUsed(
            "Request ID is used and password is set. It cannot be reused.")

    # fetch status from everyclass-auth
    with tracer.trace('get_result'):
        rpc_result = Auth.get_result(str(request_id))

    if rpc_result.success:  # 密码验证通过,设置请求状态并新增用户
        verification_req = VerificationRequest.find_by_id(
            uuid.UUID(request_id))
        verification_req.set_status_success()

        add_user(identifier=verification_req.identifier,
                 password=verification_req.extra["password"],
                 password_encrypted=True)

        return True, "SUCCESS", verification_req.identifier
    else:
        # 如果不是成功状态则返回auth服务返回的message
        return False, rpc_result.message, None
Example #2
0
def register_by_password_status():
    if not request.args.get("request", None) or not isinstance(request.args["request"], str):
        return "Invalid request"
    req = IdentityVerificationDAO.get_request_by_id(request.args.get("request"))
    if not req:
        return "Invalid request"
    if req["verification_method"] != "password":
        logger.warn("Non-password verification request is trying get status from password interface")
        return "Invalid request"
    # fetch status from everyclass-auth
    with elasticapm.capture_span('rpc_get_auth_state'):
        rpc_result = HttpRpc.call_with_error_page('{}/get_result'.format(app.config['AUTH_BASE_URL']),
                                                  data={'request_id': str(request.args.get("request"))},
                                                  retry=True)
        if isinstance(rpc_result, str):
            return rpc_result
        api_response = rpc_result

    if api_response['success']:
        IdentityVerificationDAO.set_request_status(str(request.args.get("request")), ID_STATUS_PWD_SUCCESS)
        return jsonify({"message": "SUCCESS"})
    elif api_response["message"] in ("PASSWORD_WRONG", "INTERNAL_ERROR"):
        return jsonify({"message": api_response["message"]})
    else:
        return jsonify({"message": "next-time"})
Example #3
0
def register_by_password_status():
    """AJAX 刷新教务验证状态"""
    if not request.args.get("request", None) or not isinstance(
            request.args["request"], str):
        return "Invalid request"
    req = IdentityVerification.get_request_by_id(request.args.get("request"))
    if not req:
        return "Invalid request"
    if req["verification_method"] != "password":
        logger.warn(
            "Non-password verification request is trying get status from password interface"
        )
        return "Invalid request"

    # fetch status from everyclass-auth
    with tracer.trace('get_result'):
        try:
            rpc_result = Auth.get_result(str(request.args.get("request")))
        except Exception as e:
            return handle_exception_with_error_page(e)
        logger.info(f"RPC result: {rpc_result}")

    if rpc_result.success:  # 密码验证通过,设置请求状态并新增用户
        IdentityVerification.set_request_status(
            str(request.args.get("request")), ID_STATUS_PWD_SUCCESS)

        verification_req = IdentityVerification.get_request_by_id(
            str(request.args.get("request")))

        # 从 api-server 查询学生基本信息
        try:
            student = Entity.get_student(verification_req["sid_orig"])
        except Exception as e:
            return handle_exception_with_error_page(e)

        # 添加用户
        try:
            User.add_user(sid_orig=verification_req["sid_orig"],
                          password=verification_req["password"],
                          password_encrypted=True)
        except ValueError:
            pass  # 已经注册成功,但不知为何进入了中间状态,没有执行下面的删除 session 的代码,并且用户刷新页面

        # write login state to session
        flash(MSG_REGISTER_SUCCESS)
        if SESSION_PWD_VER_REQ_ID in session:
            del session[SESSION_PWD_VER_REQ_ID]
        session[SESSION_CURRENT_USER] = StudentSession(
            sid_orig=student.student_id,
            sid=student.student_id_encoded,
            name=student.name)

        return jsonify({"message": "SUCCESS"})
    elif rpc_result.message in ("PASSWORD_WRONG", "INTERNAL_ERROR",
                                "INVALID_REQUEST_ID"):
        return jsonify({"message": rpc_result.message})
    else:
        return jsonify({"message": "NEXT_TIME"})
Example #4
0
def js_set_preference():
    """AJAX更新偏好设置"""
    if request.form.get("privacyLevel", None):
        # update privacy level
        privacy_level = int(request.form["privacyLevel"])
        if privacy_level not in (0, 1, 2):
            logger.warn("Received malformed set preference request. privacyLevel value not valid.")
            return jsonify({"acknowledged": False,
                            "message"     : "Invalid value"})

        PrivacySettingsDAO.set_level(session[SESSION_CURRENT_USER].sid_orig, privacy_level)
    return jsonify({"acknowledged": True})
Example #5
0
def ensure_slots(cls, dct: Dict):
    """移除 dataclass 中不存在的key,预防 dataclass 的 __init__ 中 unexpected argument 的发生。"""
    _names = [x.name for x in fields(cls)]
    _del = []
    for key in dct:
        if key not in _names:
            _del.append(key)
    for key in _del:
        del dct[key]  # delete unexpected keys
        logger.warn(
            "Unexpected field `{}` is removed when converting dict to dataclass `{}`"
            .format(key, cls.__name__))
    return dct
Example #6
0
def get_username_from_jwt(token: str) -> Optional[str]:
    """从JWT token中解析出用户名,如果解析失败,返回None"""
    from everyclass.server import logger

    if not token:
        logger.warn(f"empty token received, type: {type(token)}")

    try:
        payload = decode_jwt_payload(token)
    except jwt.exceptions.PyJWTError as e:
        logger.warn(
            "JWT token decode failed, maybe it was tampered with client side",
            extra={
                "token": token,
                "error": repr(e)
            })
        return None

    if 'username' not in payload:
        logger.warn("aud not in payload. the token is weird.")
        return None
    return payload["username"]