Пример #1
0
def read_root(request: Request):
    return RedirectResponse("/page/index.html")
Пример #2
0
async def custom_http_exception_handler(request, exc):
    return RedirectResponse("/")
Пример #3
0
def go_to_app():
    return RedirectResponse("/app")
Пример #4
0
def subscribe(request: Request, email: str = Form("body")):
    return RedirectResponse(f"/confirmation/subscribe/{email}",
                            status_code=status.HTTP_303_SEE_OTHER)
Пример #5
0
async def redirect_to_provider(return_url: Optional[str],
                               context: RequestContext) -> RedirectResponse:
    """Redirect the user to an external authentication provider.

    Handles the initial processing and redirect to an external provider,
    storing necessary state in the user's session cookie.

    Parameters
    ----------
    return_url : `str`, optional
        The return URL to which to send the user after authentication.
    context : `gafaelfawr.dependencies.config.RequestContext`
        The context of the incoming request.

    Returns
    -------
    response : `fastapi.RedirectResponse`
        A redirect to the authentication provider.

    Raises
    ------
    fastapi.HTTPException
        The authentication request is invalid.
    """
    if not return_url:
        raise InvalidReturnURLError("No return URL given", "rd")
    context.state.return_url = return_url

    # Reuse the existing state if one already exists in the session cookie.
    #
    # This is subtle and requires some explanation.  Most modern webapps
    # involve a lot of background JavaScript.  If the user has a tab open when
    # their session expires, those background JavaScript requests will start
    # turning into redirects to Gafaelfawr and thus to this code.  Since there
    # isn't a good way to see whether a request is a background JavaScript
    # request versus a browser loading a page, we will generate an
    # authentication redirect for each one.
    #
    # This means that if we generate new random state for each request, there
    # is a race condition.  The user may go to a page with an expired session
    # and get redirected to log in.  While they are logging in at the external
    # provider, another open tab may kick off one of these JavaScript
    # requests, which generates a new redirect and replaces the state stored
    # in their session cookie.  Then, when they return from authentication,
    # the state will have changed, and the authentication attempt will fail.
    #
    # Work around this by reusing the same random state until the user
    # completes an authentication.  This does not entirely close the window
    # for the race condition because it's possible that two requests will both
    # see sessions without state, both generate state, and then both set
    # cookies, and only one of them will win.  However, that race condition
    # window is much smaller and is unlikely to persist across authentication
    # requests.
    state = context.state.state
    if not state:
        state = base64.urlsafe_b64encode(os.urandom(16)).decode()
        context.state.state = state

    # Get the authentication provider URL send the user there.
    auth_provider = context.factory.create_provider()
    redirect_url = auth_provider.get_redirect_url(state)
    return RedirectResponse(redirect_url)
Пример #6
0
async def serve_page(
    request: Request,
    course_name: constr(max_length=512),  # type: ignore
    pagepath: constr(max_length=512),  # type: ignore
    RS_info: Optional[str] = Cookie(None),
    mode: Optional[str] = None,
):
    if mode and mode == "browsing":
        use_services = False
        user = None
    else:
        use_services = True
        user = request.state.user
        rslogger.debug(f"user = {user}, course name = {course_name}")
    # Make sure this course exists, and look up its base course.
    # Since these values are going to be read by javascript we
    # need to use lowercase true and false.
    if user:
        logged_in = "true"
        user_is_instructor = await is_instructor(request)
        serve_ad = False
    else:
        logged_in = "false"
        activity_info = {}
        user_is_instructor = False
        serve_ad = True

    course_row = await fetch_course(course_name)
    # check for some error conditions
    if not course_row:
        raise HTTPException(status_code=404,
                            detail=f"Course {course_name} not found")
    else:
        # The course requires a login but the user is not logged in
        if course_row.login_required and not user:
            rslogger.debug(
                f"User not logged in: {course_name} redirect to login")
            return RedirectResponse(url="/runestone/default/accessIssue")

        # The user is logged in, but their "current course" is not this one.
        # Send them to the courses page so they can properly switch courses.
        if user and user.course_name != course_name:
            user_course_row = await fetch_course(user.course_name)
            rslogger.debug(
                f"Course mismatch: course name: {user.course_name} does not match requested course: {course_name} redirecting"
            )
            if user_course_row.base_course == course_name:
                return RedirectResponse(
                    url=f"/ns/books/published/{user.course_name}/{pagepath}")
            return RedirectResponse(
                url=
                f"/runestone/default/courses?requested_course={course_name}&current_course={user.course_name}"
            )

    rslogger.debug(f"Base course = {course_row.base_course}")
    chapter = os.path.split(os.path.split(pagepath)[0])[1]
    subchapter = os.path.basename(os.path.splitext(pagepath)[0])
    if user:
        activity_info = await fetch_page_activity_counts(
            chapter, subchapter, course_row.base_course, course_name,
            user.username)

    # The template path comes from the base course's name.
    templates = Jinja2Templates(directory=safe_join(
        settings.book_path,
        course_row.base_course,
        "published",
        course_row.base_course,
    ))
    course_attrs = await fetch_all_course_attributes(course_row.id)
    rslogger.debug(f"HEY COURSE ATTRS: {course_attrs}")
    # TODO set custom delimiters for PreTeXt books (https://stackoverflow.com/questions/33775085/is-it-possible-to-change-the-default-double-curly-braces-delimiter-in-polymer)
    # Books built with lots of LaTeX math in them are troublesome as they tend to have many instances
    # of ``{{`` and ``}}`` which conflicts with the default Jinja2 start stop delimiters. Rather than
    # escaping all of the latex math the PreTeXt built books use different delimiters for the templates
    # templates.env is a reference to a Jinja2 Environment object
    # try - templates.env.block_start_string = "@@@+"
    # try - templates.env.block_end_string = "@@@-"

    if course_attrs.get("markup_system", "RST") == "PreTeXt":
        rslogger.debug(f"PRETEXT book found at path {pagepath}")
        templates.env.variable_start_string = "~._"
        templates.env.variable_end_string = "_.~"
        templates.env.comment_start_string = "@@#"
        templates.env.comment_end_string = "#@@"
        templates.env.globals.update({"URL": URL})

    # enable compare me can be set per course if its not set provide a default of true
    if "enable_compare_me" not in course_attrs:
        course_attrs["enable_compare_me"] = "true"

    reading_list = []
    if RS_info:
        values = json.loads(RS_info)
        if "readings" in values:
            reading_list = values["readings"]

    #   TODO: provide the template google_ga as well as ad servings stuff
    #   settings.google_ga
    await create_useinfo_entry(
        UseinfoValidation(
            event="page",
            act="view",
            div_id=pagepath,
            course_id=course_name,
            sid=user.username if user else "Anonymous",
            timestamp=datetime.utcnow(),
        ))
    subchapter_list = await fetch_subchaptoc(course_row.base_course, chapter)
    # TODO: restore the contributed questions list ``questions`` for books (only fopp) that
    # show the contributed questions list on an Exercises page.
    context = dict(
        request=request,
        course_name=course_name,
        base_course=course_row.base_course,
        user_id=user.username if user else "",
        # _`root_path`: The server is mounted in a different location depending on how it's run (directly from gunicorn/uvicorn or under the ``/ns`` prefix using nginx). Tell the JS what prefix to use for Ajax requests. See also `setting root_path <setting root_path>` and the `FastAPI docs <https://fastapi.tiangolo.com/advanced/behind-a-proxy/>`_. This is then used in the ``eBookConfig`` of :doc:`runestone/common/project_template/_templates/plugin_layouts/sphinx_bootstrap/layout.html`.
        new_server_prefix=request.scope.get("root_path"),
        user_email=user.email if user else "",
        downloads_enabled="true" if course_row.downloads_enabled else "false",
        allow_pairs="true" if course_row.allow_pairs else "false",
        activity_info=json.dumps(activity_info),
        settings=settings,
        is_logged_in=logged_in,
        subchapter_list=subchapter_list,
        serve_ad=serve_ad,
        is_instructor="true" if user_is_instructor else "false",
        use_services="true" if use_services else "false",
        readings=reading_list,
        **course_attrs,
    )
    # See `templates <https://fastapi.tiangolo.com/advanced/templates/>`_.
    try:
        return templates.TemplateResponse(pagepath, context)
    except TemplateNotFound:
        raise HTTPException(
            status_code=404,
            detail=
            f"Page {pagepath} not found in base course {course_row.base_course}.",
        )
Пример #7
0
async def redirect(short_url: str):
    url = await get_url(short_url)
    if url:
        return RedirectResponse(url, status_code=301)
    raise HTTPException(status_code=404, detail='Short URL not found')
Пример #8
0
 def redirect_to_docs():
     return RedirectResponse('/ui')
Пример #9
0
async def cache_clear():
    try:
        utils.clear_dir('cache')
    except:
        pass
    return RedirectResponse("/cache")
Пример #10
0
def read_root():
    return RedirectResponse("/docs")
Пример #11
0
def index_redir():
    return RedirectResponse(url="/home", status_code=301)
Пример #12
0
async def index():
    response = RedirectResponse(url=DOCS_URL)
    logger.info(f"Redirecting to swagger docs; {DOCS_URL}")

    return response
def root():
    return RedirectResponse('/docs')
Пример #14
0
async def everything(request: Request):
    return RedirectResponse(
        url=f"https://b.ppy.sh{request['path']}",
        status_code=status.HTTP_301_MOVED_PERMANENTLY,
    )
Пример #15
0
 async def logout_page_post(response: Response, ):
     response.set_cookie("token", "INVALID",
                         **auth_server.cookie_security)
     return RedirectResponse(f"{default_login_path}/re",
                             headers=response.headers)
Пример #16
0
async def logout(request: Request):
    response = RedirectResponse(url="http://localhost:8000/", status_code=303)
    response.delete_cookie(key="Authorization", domain="localhost")
    return response
Пример #17
0
async def logout(response_class: RedirectResponse):
    # Send the user to the login page after the logout.
    response = RedirectResponse("/auth/login")
    response.delete_cookie(auth_manager.cookie_name)
    return response
Пример #18
0
def redirect(to: str):
    return RedirectResponse(url=to)
Пример #19
0
def logout(request: Request):
    response = RedirectResponse(request.url_for('homepage'))
    response.delete_cookie("Authorization")
    return response
Пример #20
0
async def create_thptsc(request: Request,
                        id: int = Form(None),
                        mo_ta: Optional[str] = Form(None),
                        v1a: Optional[str] = Form(None),
                        v1b: Optional[str] = Form(None),
                        v1c: Optional[str] = Form(None),
                        v1d: Optional[str] = Form(None),
                        v1e: Optional[str] = Form(None),
                        v1f: Optional[str] = Form(None),
                        v1g: Optional[str] = Form(None),
                        v1h: Optional[str] = Form(None),
                        v1i: Optional[str] = Form(None),
                        v2a: Optional[str] = Form(None),
                        v2b: Optional[str] = Form(None),
                        v2c: Optional[str] = Form(None),
                        v2d: Optional[str] = Form(None),
                        v2e: Optional[str] = Form(None),
                        v3a: Optional[str] = Form(None),
                        v3b: Optional[str] = Form(None),
                        v3c: Optional[str] = Form(None),
                        v3d: Optional[str] = Form(None),
                        v3e: Optional[str] = Form(None),
                        v3f: Optional[str] = Form(None),
                        v3g: Optional[str] = Form(None),
                        v3h: Optional[str] = Form(None),
                        v3i: Optional[str] = Form(None),
                        v4a: Optional[str] = Form(None),
                        v4b: Optional[str] = Form(None),
                        v4c: Optional[str] = Form(None),
                        v5a: Optional[str] = Form(None),
                        v5b: Optional[str] = Form(None),
                        v5c: Optional[str] = Form(None),
                        v6a: Optional[str] = Form(None),
                        v6b: Optional[str] = Form(None),
                        v6c: Optional[str] = Form(None),
                        v6d: Optional[str] = Form(None),
                        v6e: Optional[str] = Form(None),
                        v6f: Optional[str] = Form(None),
                        v7: Optional[str] = Form(None),
                        v8a: Optional[str] = Form(None),
                        v8b: Optional[str] = Form(None),
                        v9a: Optional[str] = Form(None),
                        v9b: Optional[str] = Form(None),
                        v9c: Optional[str] = Form(None),
                        v10a: Optional[str] = Form(None),
                        v10b: Optional[str] = Form(None),
                        v10c: Optional[str] = Form(None),
                        v10d: Optional[str] = Form(None),
                        v10e: Optional[str] = Form(None),
                        v10f: Optional[str] = Form(None),
                        v11: Optional[str] = Form(None),
                        xu_ly: Optional[str] = Form(None),
                        v12a: Optional[str] = Form(None),
                        v12b: Optional[str] = Form(None),
                        v12c: Optional[str] = Form(None),
                        v12d: Optional[str] = Form(None),
                        v12e: Optional[str] = Form(None),
                        v12f: Optional[str] = Form(None),
                        v13a: Optional[str] = Form(None),
                        v13b: Optional[str] = Form(None),
                        v13c: Optional[str] = Form(None),
                        v13d: Optional[str] = Form(None),
                        v13e: Optional[str] = Form(None),
                        v13f: Optional[str] = Form(None),
                        v14a: Optional[str] = Form(None),
                        v14b: Optional[str] = Form(None),
                        v14c: Optional[str] = Form(None),
                        v14d: Optional[str] = Form(None),
                        v15a: Optional[str] = Form(None),
                        v15b: Optional[str] = Form(None),
                        v15c: Optional[str] = Form(None),
                        v15d: Optional[str] = Form(None),
                        v16a: Optional[str] = Form(None),
                        v16b: Optional[str] = Form(None),
                        v16c: Optional[str] = Form(None),
                        v17: Optional[str] = Form(None),
                        khac_phuc: Optional[str] = Form(None),
                        de_xuat: Optional[str] = Form(None),
                        danh_gia: Optional[str] = Form(None),
                        v18: Optional[str] = Form(None),
                        v19a: Optional[str] = Form(None),
                        v19b: Optional[str] = Form(None),
                        v20: Optional[str] = Form(None),
                        v21a: Optional[str] = Form(None),
                        v21b: Optional[str] = Form(None),
                        v21c: Optional[str] = Form(None),
                        v21d: Optional[str] = Form(None),
                        v21e: Optional[str] = Form(None),
                        v21f: Optional[str] = Form(None),
                        v21g: Optional[str] = Form(None),
                        chuc_danh: Optional[str] = Form(None),
                        ngay_gio: dt.datetime = Form(...),
                        username: str = Depends(authen)):
    data = {
        "id": id,
        "mo_ta": mo_ta,
        "v1a": 1 if v1a == 'true' else 0,
        "v1b": 1 if v1b == 'true' else 0,
        "v1c": 1 if v1c == 'true' else 0,
        "v1d": 1 if v1d == 'true' else 0,
        "v1e": 1 if v1e == 'true' else 0,
        "v1f": 1 if v1f == 'true' else 0,
        "v1g": 1 if v1g == 'true' else 0,
        "v1h": 1 if v1h == 'true' else 0,
        "v1i": 1 if v1i == 'true' else 0,
        "v2a": 1 if v2a == 'true' else 0,
        "v2b": 1 if v2b == 'true' else 0,
        "v2c": 1 if v2c == 'true' else 0,
        "v2d": 1 if v2d == 'true' else 0,
        "v2e": 1 if v2e == 'true' else 0,
        "v3a": 1 if v3a == 'true' else 0,
        "v3b": 1 if v3b == 'true' else 0,
        "v3c": 1 if v3c == 'true' else 0,
        "v3d": 1 if v3d == 'true' else 0,
        "v3e": 1 if v3e == 'true' else 0,
        "v3f": 1 if v3f == 'true' else 0,
        "v3g": 1 if v3g == 'true' else 0,
        "v3h": 1 if v3h == 'true' else 0,
        "v3i": 1 if v3i == 'true' else 0,
        "v4a": 1 if v4a == 'true' else 0,
        "v4b": 1 if v4b == 'true' else 0,
        "v4c": 1 if v4c == 'true' else 0,
        "v5a": 1 if v5a == 'true' else 0,
        "v5b": 1 if v5b == 'true' else 0,
        "v5c": 1 if v5c == 'true' else 0,
        "v6a": 1 if v6a == 'true' else 0,
        "v6b": 1 if v6b == 'true' else 0,
        "v6c": 1 if v6c == 'true' else 0,
        "v6d": 1 if v6d == 'true' else 0,
        "v6e": 1 if v6e == 'true' else 0,
        "v6f": 1 if v6f == 'true' else 0,
        "v7": 1 if v7 == 'true' else 0,
        "v8a": 1 if v8a == 'true' else 0,
        "v8b": 1 if v8b == 'true' else 0,
        "v9a": 1 if v9a == 'true' else 0,
        "v9b": 1 if v9b == 'true' else 0,
        "v9c": 1 if v9c == 'true' else 0,
        "v10a": 1 if v10a == 'true' else 0,
        "v10b": 1 if v10b == 'true' else 0,
        "v10c": 1 if v10c == 'true' else 0,
        "v10d": 1 if v10d == 'true' else 0,
        "v10e": 1 if v10e == 'true' else 0,
        "v10f": 1 if v10f == 'true' else 0,
        "v11": 1 if v11 == 'true' else 0,
        "xu_ly": xu_ly,
        "v12a": 1 if v12a == 'true' else 0,
        "v12b": 1 if v12b == 'true' else 0,
        "v12c": 1 if v12c == 'true' else 0,
        "v12d": 1 if v12d == 'true' else 0,
        "v12e": 1 if v12e == 'true' else 0,
        "v12f": 1 if v12f == 'true' else 0,
        "v13a": 1 if v13a == 'true' else 0,
        "v13b": 1 if v13b == 'true' else 0,
        "v13c": 1 if v13c == 'true' else 0,
        "v13d": 1 if v13d == 'true' else 0,
        "v13e": 1 if v13e == 'true' else 0,
        "v13f": 1 if v13f == 'true' else 0,
        "v14a": 1 if v14a == 'true' else 0,
        "v14b": 1 if v14b == 'true' else 0,
        "v14c": 1 if v14c == 'true' else 0,
        "v14d": 1 if v14d == 'true' else 0,
        "v15a": 1 if v15a == 'true' else 0,
        "v15b": 1 if v15b == 'true' else 0,
        "v15c": 1 if v15c == 'true' else 0,
        "v15d": 1 if v15d == 'true' else 0,
        "v16a": 1 if v16a == 'true' else 0,
        "v16b": 1 if v16b == 'true' else 0,
        "v16c": 1 if v16c == 'true' else 0,
        "v17": 1 if v17 == 'true' else 0,
        "khac_phuc": khac_phuc,
        "de_xuat": de_xuat,
        "danh_gia": danh_gia,
        "v18": v18,
        "v19a": v19a,
        "v19b": v19b,
        "v20": v20,
        "v21a": 1 if v21a == 'true' else 0,
        "v21b": 1 if v21b == 'true' else 0,
        "v21c": 1 if v21c == 'true' else 0,
        "v21d": 1 if v21d == 'true' else 0,
        "v21e": 1 if v21e == 'true' else 0,
        "v21f": 1 if v21f == 'true' else 0,
        "v21g": 1 if v21g == 'true' else 0,
        "ngay_gio": ngay_gio,
    }
    sql.create_thptsc(data)
    return RedirectResponse(request.url_for('homepage') + f'thptsc/{id}',
                            status_code=303)
 async def index():
     return RedirectResponse("/panel/")
Пример #22
0
async def main():
    return RedirectResponse(url="/redoc/")
Пример #23
0
async def handle_provider_return(code: str, state: Optional[str],
                                 context: RequestContext) -> Response:
    """Handle the return from an external authentication provider.

    Handles the target of the redirect back from an external authentication
    provider with new authentication state information.

    Parameters
    ----------
    code : `str`
        The authentication code from the provider.
    state : `str`, optional
        The opaque state used to verify that this user initiated the
        authentication.  This can be `None`, but that will always be an
        error.
    context : `gafaelfawr.dependencies.config.RequestContext`
        The context of the incoming request.

    Returns
    -------
    response : ``fastapi.Response``
        Either a redirect to the resource the user was trying to reach before
        authentication or an HTML page with an error message if the
        authentication failed.

    Raises
    ------
    fastapi.HTTPException
        The authentication request is invalid or retrieving authentication
        information from the provider failed.
    """
    if not state:
        return login_error(context, LoginError.STATE_MISSING)

    # Extract details from the reply, check state, and get the return URL.
    if state != context.state.state:
        return login_error(context, LoginError.STATE_INVALID)
    return_url = context.state.return_url
    if not return_url:
        return login_error(context, LoginError.RETURN_URL_MISSING)
    context.rebind_logger(return_url=return_url)

    # Retrieve the user identity and authorization information based on the
    # reply from the authentication provider.
    auth_provider = context.factory.create_provider()
    try:
        user_info = await auth_provider.create_user_info(
            code, state, context.state)
    except ProviderException as e:
        return login_error(context, LoginError.PROVIDER_FAILED, str(e))
    except HTTPError as e:
        return login_error(context, LoginError.PROVIDER_NETWORK, str(e))

    # Get the user's scopes.  If this returns None, the user isn't in any
    # recognized groups, which means that we should abort the login and
    # display an error message.
    scopes = get_scopes_from_groups(context.config, user_info.groups)
    if scopes is None:
        await auth_provider.logout(context.state)
        msg = f"{user_info.username} is not a member of any authorized groups"
        return login_error(context, LoginError.GROUPS_MISSING, details=msg)

    # Construct a token.
    admin_service = context.factory.create_admin_service()
    if await admin_service.is_admin(user_info.username):
        scopes = sorted(scopes + ["admin:token"])
    token_service = context.factory.create_token_service()
    try:
        token = await token_service.create_session_token(
            user_info, scopes=scopes, ip_address=context.request.client.host)
    except PermissionDeniedError as e:
        await auth_provider.logout(context.state)
        return login_error(context, LoginError.INVALID_USERNAME, str(e))
    context.state.token = token

    # Successful login, so clear the login state and send the user back to
    # what they were doing.
    context.state.state = None
    context.state.return_url = None
    context.logger.info(
        "Successfully authenticated user %s (%s)",
        user_info.username,
        user_info.uid,
        user=user_info.username,
        token=token.key,
        scope=" ".join(scopes),
    )
    return RedirectResponse(return_url)
Пример #24
0
def home():
    return RedirectResponse(url=content_path+"/ui/index.html")
Пример #25
0
def logout(session_token: str = Cookie(None)):
    check_token(session_token)
    app.tokens.remove(session_token)
    response = RedirectResponse(url='/', status_code=301)
    app.user = None
    return response
Пример #26
0
async def init(request: Request, authtoken: str = Header(None)):
    await check_and_init_db()
    return RedirectResponse("/builder/forms")
Пример #27
0
async def exception_handler(request: Request,
                            exc: RedirectException) -> Response:
    return RedirectResponse(url=exc.url)
Пример #28
0
 async def logout_page(response: Response):
     response.set_cookie("token", "INVALID")
     return RedirectResponse(f"{default_login_path}",
                             headers=response.headers)
Пример #29
0
async def redirect_docs():
    return RedirectResponse("/docs")
Пример #30
0
async def no_user_exception_handler(request: Request, exc: Exception):
    request.session["goto"] = SERIALIZER.dumps(request.url.path)
    return RedirectResponse(request.url_for('login'))