async def decorator(*args: Any, **kwargs: Any) -> Callable: request = __get_request(args) jwt_token = request.cookies.get("jwt_token", "") if not jwt_token: return RedirectResponse(request.url_for("home")) try: jwt_decode(jwt_token) except InvalidTokenError: try: UsersSessions.get(jwt_token=jwt_token).delete_instance() except UsersSessions.DoesNotExist: pass response = RedirectResponse(request.url_for("home")) response.delete_cookie("jwt_token") return response try: UsersSessions.get(jwt_token=jwt_token) except UsersSessions.DoesNotExist: response = RedirectResponse(request.url) response.delete_cookie("jwt_token") return response return await func(*args, **kwargs)
async def post( self, request: Request) -> Union[_TemplateResponse, RedirectResponse]: data = await request.form() current_password = data.get("password", "") new_password = data.get("new_password", "") confirm_password = data.get("confirm_password", "") errors = [] if not current_password: errors.append("The field password is mandatory.") if not new_password: errors.append("The field new password is mandatory.") if not confirm_password: errors.append("The field confirm password is mandatory.") if errors: return self.__response(request, {"errors": errors}) jwt = request.cookies.get("jwt_token", "") jwt_decoded = jwt_decode(jwt) username = jwt_decoded.get("username") user = Users.get(username=username) hashed_password = user.password if verify_password( current_password, hashed_password) and current_password == new_password: errors.append("The new password is equal to the current one.") else: errors.append("The current password is wrong.") if new_password != confirm_password: errors.append("New password and confirm password are not equal.") psw_req_errors = password_requirements(new_password) for i in psw_req_errors: errors.append(i) new_hashed_password = hash_password(new_password) if new_hashed_password is None: errors.append( "Unable to change password. Please contact an administrator.") if errors: return self.__response(request, {"errors": errors}) setattr(user, "password", new_hashed_password) user.save() return self.__response(request, {"success": "Password changed."})
async def dispatch(self, request: Request, call_next: RequestResponseEndpoint) -> Response: jwt_token = request.cookies.get("jwt_token", "") request.state.is_admin = False if jwt_token: try: jwt_decoded = jwt_decode(jwt_token) request.state.is_admin = jwt_decoded.get("is_admin", False) except Exception: pass return await call_next(request)
async def get(self, request: Request) -> _TemplateResponse: token = request.cookies.get("jwt_token", "") token_decoded = jwt_decode(token) username = token_decoded.get("username") user = Users.get(username=username) is_twofa = user.is_twofa context = {"is_twofa": is_twofa} secret = user.twofa_secret or otp_random_base32() totp = TOTP(secret).provisioning_uri(username, SITE_NAME) if not is_twofa: context.update({"qrcode": totp, "secret": secret}) return self.__response(request, context)
async def post(self, request: Request) -> _TemplateResponse: data = await request.form() password = data.get("password", "") code = data.get("code", "") token = request.cookies.get("jwt_token", "") token_decoded = jwt_decode(token) username = token_decoded.get("username") user = Users.get(username=username) is_twofa = user.is_twofa secret = data.get("secret", user.twofa_secret) context = {"is_twofa": is_twofa} errors = [] if not secret: errors.append("Invalid request. Please try again.") context.update({"errors": errors}) return self.__response(request, context, 400) if not password: errors.append("The password field is mandatory.") if not code: errors.append("The code field is mandatory.") if not verify_password(password, user.password): errors.append("The password is not valid.") totp = TOTP(secret).provisioning_uri(username, SITE_NAME) if not is_twofa: context.update({"qrcode": totp, "secret": secret}) if errors: context.update({"errors": errors}) return self.__response(request, context, 401) if is_twofa: user.is_twofa = False user.twofa_secret = "" new_secret = otp_random_base32() new_totp = TOTP(new_secret).provisioning_uri(username, SITE_NAME) context.update({"qrcode": new_totp, "secret": new_secret}) else: user.is_twofa = True user.twofa_secret = secret del context["qrcode"] del context["secret"] user.save() context.update({ "success": f"2Factor {'enabled' if user.is_twofa else 'disabled'}", "is_twofa": user.is_twofa }) return self.__response(request, context)