def read_root(request: Request): return RedirectResponse("/page/index.html")
async def custom_http_exception_handler(request, exc): return RedirectResponse("/")
def go_to_app(): return RedirectResponse("/app")
def subscribe(request: Request, email: str = Form("body")): return RedirectResponse(f"/confirmation/subscribe/{email}", status_code=status.HTTP_303_SEE_OTHER)
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)
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}¤t_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}.", )
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')
def redirect_to_docs(): return RedirectResponse('/ui')
async def cache_clear(): try: utils.clear_dir('cache') except: pass return RedirectResponse("/cache")
def read_root(): return RedirectResponse("/docs")
def index_redir(): return RedirectResponse(url="/home", status_code=301)
async def index(): response = RedirectResponse(url=DOCS_URL) logger.info(f"Redirecting to swagger docs; {DOCS_URL}") return response
def root(): return RedirectResponse('/docs')
async def everything(request: Request): return RedirectResponse( url=f"https://b.ppy.sh{request['path']}", status_code=status.HTTP_301_MOVED_PERMANENTLY, )
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)
async def logout(request: Request): response = RedirectResponse(url="http://localhost:8000/", status_code=303) response.delete_cookie(key="Authorization", domain="localhost") return response
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
def redirect(to: str): return RedirectResponse(url=to)
def logout(request: Request): response = RedirectResponse(request.url_for('homepage')) response.delete_cookie("Authorization") return response
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/")
async def main(): return RedirectResponse(url="/redoc/")
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)
def home(): return RedirectResponse(url=content_path+"/ui/index.html")
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
async def init(request: Request, authtoken: str = Header(None)): await check_and_init_db() return RedirectResponse("/builder/forms")
async def exception_handler(request: Request, exc: RedirectException) -> Response: return RedirectResponse(url=exc.url)
async def logout_page(response: Response): response.set_cookie("token", "INVALID") return RedirectResponse(f"{default_login_path}", headers=response.headers)
async def redirect_docs(): return RedirectResponse("/docs")
async def no_user_exception_handler(request: Request, exc: Exception): request.session["goto"] = SERIALIZER.dumps(request.url.path) return RedirectResponse(request.url_for('login'))