async def get_disable_deletion_protection_code( request: Request, app_id: str, user: User = Depends(get_current_active_user)): """ Initiate disabling deletion protection for the app. This will send an email. :param request: the request from the server :param app_id: the unique id of the app. :param user: the owner of the app. :return: """ vm = SingleAppVM(request) await vm.get_app(app_id) code = deletion_protection.generate_dp_code(user, vm.app.app_id) try: await io_email.send( to=user.email, subject="Deletion Protection Code", text=f"Enter this code to disable deletion protection " f"for {vm.app.name}: {code}. This code will expire in " f"{config.OTP_LIFETIME} minutes.", from_name="Purple Authentication", reply_to=config.WEBMASTER_EMAIL, ) except io_email.EmailError: raise HTTPException(status_code=500, detail="Failed to send email") return templates.TemplateResponse( "dashboard/app_deletion_protection_confirm.html", vm.to_dict())
async def enable_deletion_protection( request: Request, app_id: str, user: User = Depends(get_current_active_user)): vm = SingleAppVM(request) await vm.check_for_user() vm.app = await clientapp_crud.enable_deletion_protection(app_id, user) res = templates.TemplateResponse( "dashboard/deletion_protection_display.html", vm.to_dict()) res.headers["HX-Trigger-After-Settle"] = ujson.dumps( {"flashAppSection": "deletion_protection"}) return res
async def update_app( request: Request, app_id: str, app_name: str = Form(...), redirect_url: str = Form(...), failure_redirect_url: str = Form(...), refresh_enabled: bool = Form(...), refresh_token_expire_hours: int = Form(24), low_quota_threshold: int = Form(10), user: User = Depends(get_current_active_user), ): """ Update an app. :param request: the request from the server :param app_id: the unique id for the app to updated :param app_name: the new name for the app :param redirect_url: updated redirect url (see create_app) :param failure_redirect_url: updated failure redirect url (see create_app) :param refresh_enabled: whether to enable refresh on the app :param refresh_token_expire_hours: how long refresh tokens are valid for. :param low_quota_threshold: how many authentications should be left before the app owner is notified that they are running out :param user: the owner of the app. This route requires authentication. :return: HTML to replace the app in the list and an event to display the app """ updated_app = await clientapp_crud.update_client_app( app_id, user, app_name, redirect_url, refresh_enabled, refresh_token_expire_hours, failure_redirect_url, low_quota_threshold, ) vm = SingleAppVM(request, updated_app) res = templates.TemplateResponse( "dashboard/single_app.html", vm.to_dict(), ) res.headers["HX-Trigger"] = htmx.make_event_header(res.headers, {"closeModal": {}}) res.headers["HX-Trigger"] = htmx.make_show_notification_header( res.headers, "App Updated", f"Your app {updated_app.name} has been updated!", "success", ) res.headers["HX-Trigger-After-Settle"] = ujson.dumps( {"showApp": updated_app.app_id}) return res
async def create_app( request: Request, app_name: str = Form(...), redirect_url: str = Form(...), failure_redirect_url: str = Form(...), refresh: bool = Form(False), refresh_token_expire_hours: int = Form(24), user: User = Depends(get_current_active_user), ): """ Create a new app to authenticate against. :param request: request from the server :param app_name: The name of the app :param redirect_url: The url to redirect to after a successful magic link authentication. :param failure_redirect_url: The url to redirect to after a failed magic link authentication attempt. :param refresh: Whether to enable refresh on the app :param refresh_token_expire_hours: How long refresh tokens are valid for. :param user: The user creating the app. This route requires authentication. :return: HTML for the app in the list and events to display the full app. """ new_app = await clientapp_crud.create_client_app( app_name=app_name, owner=user.email, redirect_url=redirect_url, refresh=refresh, refresh_token_expire_hours=refresh_token_expire_hours, failure_redirect_url=failure_redirect_url, ) vm = SingleAppVM(request, new_app) res = templates.TemplateResponse( "dashboard/single_app.html", vm.to_dict(), headers={"HX-Trigger": '{"closeModal": "{}"}'}, status_code=201, ) res.headers["HX-Trigger"] = htmx.make_show_notification_header( res.headers, "App Created", f"Your app {new_app.name} has been created!", "success", ) res.headers["HX-Trigger"] = htmx.make_event_header(res.headers, {"appCreated": "{}"}) res.headers["HX-Trigger-After-Settle"] = ujson.dumps( {"showApp": new_app.app_id}) return res
async def get_app_display(request: Request, app_id: str, _user: User = Depends(get_current_active_user)): """ Get the HTML for the app display. :param request: the request from the server :param app_id: the unique id for the app :param _user: the user who owns the app. This route requires authentication. :return: HTML for the app display modal with an event to open the modal. """ vm = SingleAppVM(request) await vm.get_app(app_id) return templates.TemplateResponse( "dashboard/app_display.html", vm.to_dict(), headers={"HX-Trigger-After-Settle": "openModal"}, )
async def rotate_app_keys_form(request: Request, app_id: str, _user: User = Depends(get_current_active_user)): """ Get the form to rotate app encryption keys. :param request: request from the server :param app_id: the unique id of the app to rotate keys for :param _user: the user who owns the app. this route requires authentication :return: HTML of the appropriate form """ vm = SingleAppVM(request) await vm.get_app(app_id) return templates.TemplateResponse( "dashboard/app_change_keys.html", vm.to_dict(), )
async def delete_app_form(request: Request, app_id: str, _user: User = Depends(get_current_active_user)): """ Get HTML to either confirm deletion of the app or begin disabling deletion protection. :param request: the request from the server :param app_id: the unique id for the app to delete :param _user: the user who owns the app, this route requires authentication :return: HTML for the appropriate form """ vm = SingleAppVM(request) await vm.get_app(app_id) if vm.app.deletion_protection: return templates.TemplateResponse( "dashboard/app_deletion_protection_warning.html", vm.to_dict()) return templates.TemplateResponse( "dashboard/app_delete.html", vm.to_dict(), headers={"HX-Trigger-After-Settle": "openModal"}, )