From 577249978270d6bbb4135466789296a6d5d60882 Mon Sep 17 00:00:00 2001 From: Christopher Carroll Smith Date: Mon, 2 Dec 2024 21:26:14 +0000 Subject: [PATCH 1/3] Used Jinja2 templates to generate the reset email --- templates/emails/base_email.html | 31 +++++++++++++++++++++++++++++++ templates/emails/reset_email.html | 19 +++++++++++++++++++ utils/auth.py | 28 +++++++++++++++++++++------- 3 files changed, 71 insertions(+), 7 deletions(-) create mode 100644 templates/emails/base_email.html create mode 100644 templates/emails/reset_email.html diff --git a/templates/emails/base_email.html b/templates/emails/base_email.html new file mode 100644 index 0000000..2fc0570 --- /dev/null +++ b/templates/emails/base_email.html @@ -0,0 +1,31 @@ +{% from 'components/logo.html' import render_logo %} + + + + + + + {% block email_title %}{% endblock %} + + +
+ +
+ {{ render_logo(width=40, height=40) }} + FastAPI-Jinja2-Postgres Webapp +
+ +
+ + {% block email_content %}{% endblock %} + +
+ +

+ This is an automated message, please do not reply directly to this email. + {% block email_footer %} + {% endblock %} +

+
+ + \ No newline at end of file diff --git a/templates/emails/reset_email.html b/templates/emails/reset_email.html new file mode 100644 index 0000000..e919368 --- /dev/null +++ b/templates/emails/reset_email.html @@ -0,0 +1,19 @@ +{% extends "emails/base_email.html" %} + +{% block email_title %}Password Reset{% endblock %} + +{% block email_content %} +

Password Reset Request

+

Hello,

+

We received a request to reset your password. If you didn't make this request, you can safely ignore this email.

+

+ Reset Your Password +

+

Or copy and paste this link into your browser:

+

{{ reset_url }}

+

This link will expire in 24 hours.

+{% endblock %} + +{% block email_footer %} + If you didn't request this password reset, please ignore this email or contact support if you have concerns. +{% endblock %} \ No newline at end of file diff --git a/utils/auth.py b/utils/auth.py index e7de8c5..01fc8f4 100644 --- a/utils/auth.py +++ b/utils/auth.py @@ -12,17 +12,24 @@ from bcrypt import gensalt, hashpw, checkpw from datetime import UTC, datetime, timedelta from typing import Optional +from jinja2.environment import Template +from fastapi.templating import Jinja2Templates from fastapi import Depends, Cookie, HTTPException, status from utils.db import get_session from utils.models import User, Role, PasswordResetToken load_dotenv() -logger = logging.getLogger("uvicorn.error") +resend.api_key = os.environ["RESEND_API_KEY"] + +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) +logger.addHandler(logging.StreamHandler()) # --- Constants --- +templates = Jinja2Templates(directory="templates") SECRET_KEY = os.getenv("SECRET_KEY") ALGORITHM = "HS256" ACCESS_TOKEN_EXPIRE_MINUTES = 30 @@ -294,9 +301,9 @@ def generate_password_reset_url(email: str, token: str) -> str: return f"{base_url}/auth/reset_password?email={email}&token={token}" -def send_reset_email(email: str, session: Session): +def send_reset_email(email: str, session: Session) -> None: # Check for an existing unexpired token - user = session.exec(select(User).where( + user: Optional[User] = session.exec(select(User).where( User.email == email )).first() if user: @@ -314,17 +321,24 @@ def send_reset_email(email: str, session: Session): return # Generate a new token - token = str(uuid.uuid4()) - reset_token = PasswordResetToken(user_id=user.id, token=token) + token: str = str(uuid.uuid4()) + reset_token: PasswordResetToken = PasswordResetToken( + user_id=user.id, token=token) session.add(reset_token) try: - reset_url = generate_password_reset_url(email, token) + reset_url: str = generate_password_reset_url(email, token) + + # Render the email template + template: Template = templates.get_template( + "emails/reset_email.html") + html_content: str = template.render({"reset_url": reset_url}) + params: resend.Emails.SendParams = { "from": "noreply@promptlytechnologies.com", "to": [email], "subject": "Password Reset Request", - "html": f"

Click here to reset your password.

", + "html": html_content, } sent_email: resend.Email = resend.Emails.send(params) From 010170c33dadfc40af8954889ee5e9fb95bc1634 Mon Sep 17 00:00:00 2001 From: Christopher Carroll Smith Date: Mon, 2 Dec 2024 21:31:14 +0000 Subject: [PATCH 2/3] Add a dummy resend key to Github workflow so tests will pass --- .github/workflows/test.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index af360f1..918cd90 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -54,6 +54,7 @@ jobs: echo "DB_NAME=test_db" >> $GITHUB_ENV echo "SECRET_KEY=$(openssl rand -base64 32)" >> $GITHUB_ENV echo "BASE_URL=http://localhost:8000" >> $GITHUB_ENV + echo "RESEND_API_KEY=resend_api_key" >> $GITHUB_ENV - name: Verify environment variables run: | @@ -63,7 +64,8 @@ jobs: [ -n "$DB_HOST" ] && \ [ -n "$DB_PORT" ] && \ [ -n "$DB_NAME" ] && \ - [ -n "$SECRET_KEY" ] + [ -n "$SECRET_KEY" ] && \ + [ -n "$RESEND_API_KEY" ] - name: Run type checking with mypy run: poetry run mypy . From e763843d700fef91cbcc9321da4e70e85e0e6702 Mon Sep 17 00:00:00 2001 From: Christopher Carroll Smith Date: Mon, 2 Dec 2024 22:10:20 +0000 Subject: [PATCH 3/3] Corrected URL encoding in the email template and updated unit tests and documentation --- docs/customization.qmd | 10 ++++++++++ docs/static/documentation.txt | 10 ++++++++++ docs/static/reset_email.png | Bin 0 -> 56750 bytes tests/test_authentication.py | 6 ++++-- 4 files changed, 24 insertions(+), 2 deletions(-) create mode 100644 docs/static/reset_email.png diff --git a/docs/customization.qmd b/docs/customization.qmd index 1f9a439..9cebc65 100644 --- a/docs/customization.qmd +++ b/docs/customization.qmd @@ -138,6 +138,16 @@ Best practices dictate implementing thorough client-side validation via JavaScri Server-side validation remains essential as a security measure against malicious requests that bypass client-side validation, but it should rarely be encountered during normal user interaction. See `templates/authentication/register.html` for a client-side form validation example involving both JavaScript and HTML regex `pattern` matching. +#### Email templating + +Password reset and other transactional emails are also handled through Jinja2 templates, located in the `templates/emails` directory. The email templates follow the same inheritance pattern as web templates, with `base_email.html` providing the common layout and styling. + +Here's how the default password reset email template looks: + +![Default Password Reset Email Template](static/reset_email.png) + +The email templates use inline CSS styles to ensure consistent rendering across email clients. Like web templates, they can receive context variables from the Python code (such as `reset_url` in the password reset template). + ### Writing type annotated code Pydantic is used for data validation and serialization. It ensures that the data received in requests meets the expected format and constraints. Pydantic models are used to define the structure of request and response data, making it easy to validate and parse JSON payloads. diff --git a/docs/static/documentation.txt b/docs/static/documentation.txt index 34ef6a5..2669ef8 100644 --- a/docs/static/documentation.txt +++ b/docs/static/documentation.txt @@ -790,6 +790,16 @@ Best practices dictate implementing thorough client-side validation via JavaScri Server-side validation remains essential as a security measure against malicious requests that bypass client-side validation, but it should rarely be encountered during normal user interaction. See `templates/authentication/register.html` for a client-side form validation example involving both JavaScript and HTML regex `pattern` matching. +#### Email templating + +Password reset and other transactional emails are also handled through Jinja2 templates, located in the `templates/emails` directory. The email templates follow the same inheritance pattern as web templates, with `base_email.html` providing the common layout and styling. + +Here's how the default password reset email template looks: + +![Default Password Reset Email Template](static/reset_email.png) + +The email templates use inline CSS styles to ensure consistent rendering across email clients. Like web templates, they can receive context variables from the Python code (such as `reset_url` in the password reset template). + ### Writing type annotated code Pydantic is used for data validation and serialization. It ensures that the data received in requests meets the expected format and constraints. Pydantic models are used to define the structure of request and response data, making it easy to validate and parse JSON payloads. diff --git a/docs/static/reset_email.png b/docs/static/reset_email.png new file mode 100644 index 0000000000000000000000000000000000000000..b93623bc4f5956ab847f3b14e2e0d78e0b5f257b GIT binary patch literal 56750 zcmeFZbx@p7*ESe}1qcvA2o3>4a7b_)2n0`XncxtD!{9bJB)BF>kl^lag9djUd~kQ0 z8JutOd!Bl~-FdW0`8C#Cl2 z(PJd)HTVPz^^13JsV(Xa%}GsG@=@6c)h_A_hPi~I#G^-*(RjDUn5geK_Hx=zj~)?p z{(YhK+7*0#^a%DrUP?m4-QeI3&HcrUH`lGNzM7Cjb=i5yKJQ>|?V4VAjP+bu?wH&! z`XreEz1Ke#=rNOCN-WF8gnykW@d(JUi|y!hrvsX}bN~6iZRzeH)LHOtSu=0^|$YyL%t^m%}3?BdJ18W?OD%qp6K1 za(*FyFOX+j?!$8;)HQA!)dBeXA@;-D1}1vc<@f{(DfRav=vYbnTey#oY?1hH5h08~ z&%Y(;gN^K!|CZQz_Vg(9ZxO056M#%tBcn%l&8JxRyXp5h;x}`nC!-IyqYcix&+p-e z575h7H=k{{w=R1cw;i;%XkrgnqwC|cwB07rfS{qFPwP&9Th59uk|$a$_G>LI#pi0f z<@ULrOy8^QzxqSk>R0XqFaF%*%!2Oyx8${4Q*KAg%)Yd`Ixzv2U`B6_jHM-um9=$j zVq$*pvw!-#%z<+>nl2vQ)FgZ`S1lV&uE)EY*>*K-7vXvmOh`Lz@+m$(zM#Ck?I=Sm8TU-UX4Wqu;U%D_#;D_Qw)X>**eMPm z=x@zFA&|R$`Qw|b^X+w6@#|O`bgw=2bndd1#Kgq?cLFk=o)CxbdtlpjJPrEoDec3% zC@P^pkJA5ErP>a{MjBoX0O`wS&CSgzVFqF+?dag4Ncf1zF&WHc-mX~_cw*>z$afd@ z&tH*)c8IMsDLp-n%FB{zMO+W^FcD!o2|9T?b<(-=xsm@Ak_XMkdqUYp4DUA$_uRHf zJW0MX&EqK*6&kqE_}-p|uw5?SEFovZ3I3VK9(qQ|`3Tj~ky>r#L$B{`Zwk0u z>?KrcJNkYnI%r{~7{sldE;j6Q@>e1Ih(L1HRB%65PjSTF)|@W&EE_96qD)YeLR04- zg-w062|Q{s;4&LcD_u^4>9=04gNULGD{8?VayyvKT#h^zzsrC4hElsdw>;0|7Se|^u7|AUNIUo*G&{i41@1Fn zV|h&-!88w=uaR$K_-iIjcR3e9^NEH&+JtDRiZs7#~xv2YA+YtPJ1Z9 zeHt1XIl*f;%MUlc`BXbgNd=}>9nV6>+A^2!?ocBPT|P${r7+E&RIlW+x|iM z;X)bQ=S6W?3Vv?OtwBNSeW7~C=}7%o>LDNj7Q7>0M0NTu-77Y>kA#tjZFlt#dBOCB zWh@-XMJGbArzeAfRcg0bseZGEtS8C|T&QgPyIUYsw;s;LAF62{AGJOB0C?*(i?zC& zGZD2j1|LwSacTgM7k4{a3`wNOFR+}dsRR{ho-2I=lp--r9v zB~X@PLhxtpDX4Gp$03oU2J{D%AsRpZ$MeEKAh5mo+`m0^zMOV->hjg^g<-T{; z0N$&)Nh?F_zkSJCP#g&Ggy(!79v?o9Kjku@I;lD);`77e9 zQC|Z>G$!S=sSiKXmyc&Y#Qq=d(%$9Fpj_FG+s{M=6JOspAJWGE8VV*d8i4pk!|meY zvYXk@_J5wa^rWOvF0WO*YwDA;L9YGGt^!WxnNnSWOvJVMXc}K@ij6=5g14xq_}|jh z&n-#!G+pnBM0vKEV?R7n&h|sseK!;Jjw`28KyXbBuju&@&uoP;y4d|`^uDr*x^fn* z#*)~;eHC+^rPhkZ_om*rSe#n-Em>EM<>ZA3*`WHlLhVXgF7uLD#xi5}lZ9)_nEYi} znItx=YJ>Fh%nEDoNH)#Jr+3RyyIyPwoK}*OLfZ<#H?6@cF@^zW<(nP9^Lk}ZK|?ab z#(Z(1^MSSnzd#X6rRy$zKJ&NI%ud5}H5}FPz6-*U*9T1=s)_pOCjEGInZA>eY(lGU z!l!F>T2w;R@0o3)K0=t#3FYsB>};}27lM?pRO>{kl;;7UPlH2}KC3_7&)Aae8P)16 zCdlUmU{ao~PehOp6r>RGX`pCtK2zwD>@UU&X+Um1_eDGLP3s$$&;Mi0- zgOWn2HJY=Se#k8&+``-Gbp;TM3wuRm_FJ+vo~qN^jNT>pz{J2O&2!%q6hFqcRbc(z zzQF!Dv~oqm3$l?_Y0H=6q3Iw0AdyP(WOr3i?4(1)u{h4F8*kYIK-Ifq`Ec?*AVAbw z8}-PIn_xpKXlu{etK2WN-7N^Byzd|2@n6#*dKi5;e^{9+R0lt`9|a&$c8^C0xOjGd zxBNhzubj>gUcYL4KtAlT7F>mIYieFlQ&acY7tNI~ znsZo7b^ik99OSKLdL+rs9D{1dj0qJU@~~H}<@GX!VG(Pl9F9${od7^chA^7=fdumC z>~v<(C--m_m)D15kc@gT*UfXxvjDF(9NZQ6X^Mu-+cXV$R4)7ZtX$(v8QTC!l3BMW z|3Z|T#Lb}P+fP~Km+dl63}+aJxwn8TXR^_5?PexqEO7qTeKeg+YHT@h1Rc;hC=JG` zqh9oDhFsjpx3?9OX+i?YyfR(}BQ*P#-e=Duk$+?^>^R@b^uAb6{Czr*;#PfdgAG-& zLV6oCGG+BM=K_!7=jU|*7!2-O!}`zRvc4Cx?l*_^zA|- z>%K-aW%@l8B(wSX`6k;VzkA%C;~$X3zhSEY9$2=u0lD;J+6~&| zV~$mVJ#r`XznLfQ7Mt3+t^OkU#x(Gon88=ZU{e!+_R5Njf^>%p!ta+y4S0U7$UVt6 zHoa_jF%~!9ZqWZBFb#=s`Qsd+WK;F{CaHF3cG(Y?B^xw{Jqb%<{ygm$1?10YH&t3& zIHLlKy$vo8W^-~KvIVtA#H zdFud8_=Dozg0U+jYxS^%VY*#}C{26606as4P)Hz4O<9UJG)J^yba1c}73^JzWaQ>z z9v&WE!!CXH>wWN0k=kW9mydsItC-i#!ZLqZ2}+A@(<2kFO^x=aOD}_cFR|Bgy)-pR zjvCep?ha22YYKR^HFPwSS-Q)v#uiE!Y(;NlHXOu;tdD(aTD{N%%2_yHlz6_x)JoaU z1_;J}HT|}B-nvM@Q!^T{easp|RBU_G!szZ=d;fh?hp=g>L7vW52a9!|HMl$k+q0#? z13!?NkNY&n#ao82I&{Iu@)6V0+h{iO>MfJ|lBXtQy~^#RcD{taJ6HhXGbYu&pcG}P zjYlkmNAW>HSYBs8)2EJ&FjkJ6&!c=2e~BD76B}MnB%WMMDpM+&jiig)HEY=4PpK=D z1FxXN_5CWADwdT6D95a}hmUa0(C?k0dt=MYv|ts+r>2ixiBIV(22 z8)z_wYl+P&aOmbr}1O4Ghbku37O?Q;=0(4H@+X zBZi^Ox-sHsuv^Kv(lS}=<()0`y)-nwVYz5={esHY`gcpEwShakNAIxnUl_NZcFGCU za7{2xQ@WUxvUl<&&2vkuABMRsalnYleRQr;TXLXJKXKiRw^ly?ekEL9?G!7%h0wG; zg4dYXB#!MW@s^iLoi^(M3<1Y$+!}U=UG1iTLYNU5P#@HA96NB)qRyo0R7u47i8_12 zxPd?9y&>BkJ%XCYa3ASTM3pZ`khV`A@78!8rrKCX{`)whHB`5@S8MW@ZB@63BJ=ce z_|kn)$E#+~Jr&CZfpb!gtRuhW*{x2~*AULLJjAMF?TgZFQ{fNLa( z-o@k5Z-^+-Aa`E8%dU{Pl1zb@D24Y^HPeFUY5EQWDvu|s&W&Jud*ak0O@wgI;Wr}c zXEDf(TW^(niZ=T14u2?bM0~EI3LjOw@T6H3VKdj-$|3}KjsXyG4+p91YW+g47YV&@ zf>89LN0p&1C|KNIlw5RM+WMk$PA)jEGP3lfXMt07!7x5Mt&}@`$E0`sa=5dk%8FWK z2;L`KrWB|h^<0;bz6lPJvo9~vYvf*IZM4GE)6?_%_}HuVQ?1R-q=n|Z28A8d>iwIz zVUDf|MUEXI5~*3AoPpZ-N%C4r57+(pFOs7&9YQ{ zw^e2%y#g*TGW5bcY}v}NRt*)qQrKz9&{HbUOQUVhO7X~X8rLKSkDM_{fXl3V1ShrDiyl7NqJ%Bp>RZEFgwYq{W-+ zGzR$Xg1G$K_tfmD6=rG_p5;w4-_$)!VYa&lIut;Z24>Wzj*mh=C%h{y2{#|ti?fAy z8zfqz)%fU(8It~;`o8Ei7;5V2C#qwd+JwlwCP~+45+$;2TZ~6+sz1V5gnj{fsYot* zuA^+y>z#GX%;?yzW%jM)bC7xZkhwem^=zdQ z^>WH8t&?UMg(*xgy249c-E{p#a9={|XAeH!5s6FnegG!kg~$qO4NLTQotTrdqeocF z{#Q4`6@Dr#*lv2U6={7`$&ad2pNOrmLK8u{WkYlgg6Au2^)Vew*b+%aRO>sh>2%bW z4HrUVgm)KHf(H~u#xq;l%A@pY;+F0B9VomYIGVb$P36vsN8EXq+GPuM3hql8Z8I(W zu8EGB>(4XDK5!1Do2P7*J$^Af*-6}3=}P4fNE!R`8wS;Em!C3G_~TPaY7KRj6n0E- zzu*`9Ru@UqSH;SfzbW<5G7Dre!OL=S;nP{>QHJh1v5r?1cP<85EiC{F`szS31exdM zZb~I{ak#gw<-U~?FVD_FT8FGpj}u6ZI6O2UdljTE%HSYK|EJM1KiTq!Ou)hl%dns7 zHTIo_wsu%vePn+SJ_1U4^KGD|=4NnpZYk)4){^|n?|dX=tb@XxAPPfF$a?rLr-Stz z3C!xgG!Sr&p9d8XxOG%F;P{xF=g@s%B|;p64rcOmAHO?_{DW>0KOn)Zk2pTGx*NLC z)Z(BSi9R_MX4mGLEI4HAjZI~w9CKv`>tivt7t27?cHTRxoHZ((_4eT~{9Zs%aZk%q z2T}mH==3oci=LLo-ztG0M&7&DfplH2pN>c+c36w03W5l>Hnx5(e7XmA2Dvq#NcaAx zyV8@y^sCi~lE6lvae?t4-D}(| zfVn)1{I0bs6tLuenArQwqWD8KL5?1t)=KDUa=#uI+#0$|!z*sPpXH=LVD+%LR0e(q zNU@v0dbK`g*IFcdfYm^nsq*-C1N`EnFOl3@0iWt^^$j%RiJY$e5BV&nH+$?4 zF`{+`!ae6W8Gd{4zN8^Z(Pdk ziGCU`vc+-U%N;W|~ENDODZPeN47lDXum@3|xMfI#a^nGWeq*BoE2^YTPYwHnd{>f)p3Gw4F8LtL|ta z+aFD>P1cqt_}1qa(4KvsiWWhHE0D`2y`P&<=R#ANM-U_x+M-6+p}wyQNL}{RA1pD< zpl_@KSX4AI;n!xnT&Bfj9EgBV3FT*9)0Kr|)ikR#fjHu1pGR{0v=p--pFX zOY4(Mv?y$0B;GLUYL^q|39R83%gC=|y6=T8YzsWb z4ov*&y{Lxfoav>Q${P~laUNX%5PyP#*aC~G@O|~)Uds;`2~^fjyT*G7+jo_0bjQ@X zim<}teIS+7fgx`aDQOnjSbzB(*3Qt+udo$;RDi!NMB$40uls=KD(7nFHEwQ&1*XNk ziv#TjfUY8k!OLoL!x^S`q|o)xLpKqgSlqL z=}NIhNYQ0bGeesZ3C9#Le!cH@K5Ugz*fUC3B1;!R4Y+h=DB?%Hdgf3a&SG7EBr{mBg0O-mCKDe0E4O9bxt#T9e36HmeKn+|e^C_=i+>k{kIq91}XN^+*T@9Rxu z-A4O{Ax9CbE0YgiBzw_V^v5^vzIIH)!jC=#k5!2#rH)N7s?4;#B4{?{|IUrM>Zwk8 zsZA)o>F|c8iuK&i-L~y>kbTb{`lMC19nRHCtxoXB&s#D!5t^U3W1afk55MwWWPXhh z9ljkPejBY2D{!9&XvXFE0c`PZIfy_}zEHRH{d-^$bFE4_}o zE=vwhPP{|Yw9>Xp`k5K&okdtV@F`2Eb7d2S)wJvgjYTv;O$)-Hc)|8uV8_cM#e#Ai zD4t{NZ^NKH_^`!s;!kH>8o?Li^>^r-?vm*_*_$sC@v&n~^d%_r(o`t3pMPzwBR`b% zj7Da=DWeb2(y)0!sO9_s9buXiVow-eQ28M(M3QHK**3M{WP8Uydsrj+@D?g{Zk1Ms z5t3CLHRXcH78rD}*)FHPoG{pRD$D44XYBG1#QZ|#jadY6`(wI4c4@#>nMT@$(b9~} z^%x=5MFzV#Y2!KT>fC%-+N7#L9n)^aa*@=~`>kKpZn+GDdz0QzIf2b*zF7D57b|z5 zPx0$Aa(o>jSGWw`O$O7oJWqBE*QTJyOr>n~dvC^EO#4QMrSBaHlMxq2uPh*FPJb5r zDmgomH;m9^E0OY)CnR5^TW6Sq)K)c>NS{~=D0l_n>+$T=}j3)hH z`vY9)i8M|BTy^CUo%^dE#a>r6&Jr~;QGqjS79vGX0lo&H1|c5`sETqQi#L6^zmri< zUcQ4ZODicwjn~Lv?oS6+Ont;JcG%;APc|oOdCPhWBNnroP&RkG22uSaaGln-#m<;hTMBE;pQN~MEkw_qiS^- z5eE#h#P|GNNPC*Xi}|uy;1S5bw~3B>z#i!7U{HC)quS#mS?aMYH>4|GV?V3If}_xL z2%r8Aku4L6_|=GOyTBG>tUIz|Dh@{QbyR;Ih21Xmu(@Bk6Rf4DWui$6@Z zro}Er_wf2)PJ1ugTM$6$E#e$z7|?l2!ud%#yGQWon>JB6eR)CaX4}Kv@p@M%anGc= ziK;+H(R%~F>dN_1-NOs0Abd{zZc===kl|m?>qXbQ+1_jjH@m^)x9Od-r;~d2;-CG( z_#!{Y7x#8&fK_G@RoA;(Z(*+sKUQPSLO`SDx+w?ffi!PlioX+~%r%t5MU;dI^ zB-6YNi`vYe)!5>jD%i3RbJ%(RgAv6Or>_wGL-Ip6otM zMmAM0m+f55?o;1D{eGFh)a5Cg<&0cpa9ZwzI%KD47Cwt|RxE;$YL3RmY{F?0*3Y*z zWkv&ZoJ!$uAF%_az|VsBXR?@6z7)cur0Xkqr(3HS1C=>T>h&R9a5H zxlMmK_l;Q5tBnN;v=@Qcpu?3#uv==kMdRkF3W|I&^~nNDsN0kqRCKDDYWpy@?5V!v zm!l;V#tVx#y?`QD)0Z|k668d#YdpDQ)SGZ4x!`N?yJDHgN3EX;zlGZ6*m=Inx4{hi z!k=By^0MT8s0;BTzULR)fIMJ^?Uei?VjgIm*2Rh6jx-o^9~)k=`;tE+cAqEK#lk7B zQyP|B{3H@aZSgq|q8iC5T8FDO1XuUJJL86pHljQdb-B&^4tElT*m@S3)_H@<$9)>V z5JLM$7ig)KYsv1MX;N*PJ8f?b&N1NOvTtym{T8fU&{)7rH9AhwcCWpk$3$sgk#)82 zo@yDflm9Z-Z{ZJEexcSzHNyVB`}+5e;JnC0?p`g8JJVG5K;Iqas=5!(=h60NE>~x_ z1lJ^w>S5bwqThMWsM|nxhObBhR9`Qb3Uzx@fYjFbW-3#~guJ|lZc|W}b_4)zk;qDI@s3K~>0+bT$- z4YBy~>qSS)Z`=`0N)H$GgZ=V0PV8bohqpJ;50`}Nxj`szl!Qu8?)UjEy~#OyPq@9Y zPyCsk_9A0&51~vj&H#LjJytls%Y}mHe45?a_elM(v^)n0;mhAG#=~L3S(7bPVfeFmjO~6{8%EyOPI4QM&FL)kT~D z_T25e9TjQ7Nj|QkmhV*~<=Cm3sg%e?KQn;K_p-=#MvN^c%r+z2Meq@2t0m8d^yD7* zI!$7(14s*~cfJ*^H%^_M|Hp!17jM09aB1}s=*10}3GteYQdwCUhRB%E*-kW>PMejJEA-Pm2>cQ;BkB;az*(s60jWxuLywZ8mJMdyW~Z?aL? zLR#4@UR4xHs=;pCbnLJZeY!vMeuk|R7K0^wn8I){s!hhY$mi(O#}xuAjw+G8Ic>;& zhF-3{TTzZpq{#o1vmt+cDo~ES)c`i*RMYWjeny+HGn8MGVBQCVE9l)UjOsx?e7niM z3;bl9LEE8Bug7A^Xn(=Lg$)?9GF)oe$X)6ZAivQwuRHwm**8M|$dTSbz^v!{be;T- zS0YMw5(1jnQ?X@4%Lg5yv){4((XCGx?Yr%3#w3)x(0yH7RJdJ_U;XTEQO@`S=6~-C zm~MUn368e+W!NiO0kr6~W~2XcCdE?5j_}mOnonMhO!7UuTVm+cm)R11z8$tDVjhHE zWBj9)1aF7}czN>1CJd^ifA{6=)4F}PNfviolO(pYaZNcggKgygW zwb5l_(gg&|VG95i8GD5A;aY0JG%kEiu#MsPW`5#K0%s$#h9CpFXD!|&GH8L=62*3T zw&(MV=gV{@Po;a3%Q{G8uOuHK!*kYZ5bz-JEl^@8CPUEm?(?Rl{?J)w8k(xxd*7Ir z$Kk=zce~;I8qW<78W( z=gscZ-Sp|OQ4{@zAn^ll79{FYjo|Vei-!`M;A%Xv?36mB*Ur3pa8;wJ#lg=Nwyl0H zYDUc_UoUu0clY;#In$+P(;)^yKN`Mh#_Qcsb?(YF>)29_e4qI}Q;$co1Xs^AmL~<^ zQF`%@akqw*GHeT6foKCSwetrSR(o`G-)EdT$dijg=Et3Cun!@k%(}18eu}X)C6>xH z{BSZUObfa&YQRg|bg=*k8-c{3(4|$aDUP)8Dh`8hYnV#3?x%lTiwor`&bAteb`IZ7 zdk)R)_Mhl}qQITD`w&ZTg5?@#Y^?cn{I0n6p&*}VfifzFd3Rfyn&(7tLWuN~2xM3F_`yp8R7bND^A*Ookce5Y@rHCRt0lb5DlG5-=n ztod=RusZ>DnZ)XvObt@oRNlLdT2V9iWar3!l2p^kXQ*8mP2Eh6Q63*-#djgqa4S$1 zrXBSoDpk+vE?|3@;m3aETxVOI^hYj4hL(UPE_LaL)jy~l&!*IwI)Vo`;n*X-bU07&q5U}y^oZcZhbm9vK}p!} z3>tk&gb{#{C=aL^=`Z!LiqdikLx+!J3z2<>mU%#czQeX^w1p zjBjAgUR32)1;vk_lO6mTp9&aq-!`XwR5gLAPy||4JwG3)v;ECILnWC4HE$qeVKT|* zxOX;~GM#C+_)PrU(3oqFbSA^8#877Hr(l~1E&8C-4 zB};E*?l!n$|9C)_?*pY+9y^K&r(Bm#9x)zTQA8emVj9Tn{{!!;8Yl?u;9w$l0 z;0?BwLthi2T&3+p#2?3o+#j2f)xzZA^_iQy&8o^3)I$7QnO+Xh4o?Tb&5kJh$1Pu6 zexv8azXC;HP=UPqSo?y^Z1EYS;N=1VBGc0eXOYmH@WJ^IKrt62U^33%3|8671lQU} zUqoe>(G(p$3!k?6AZsUk&^n-5&J3|uwQoE0JpSGNa6Buwj3|?4?8ih5bTTqmKc3R{ zHnEk|>(hN;C9o}*9uM4QVCrY#%n|?mZT>L$WDg-f{k5CXznd+%!d8)}>Zq2KhLqbZ zp3L${WYO=(u25fEuDIv=ljiH7gIH`1SWnK`#EBKxJbzJI=G6NA@VLxen>aS(zH8PE zJc`V}WleHqp5Wq$2NL75aIRwOcIDIE!|&Wikw23W446fFd3;@J^W@A5RhqvevGBNi zMv>UpYMCF@Yt;iQ)yzvtev3u>OSR*o+#0|4g#(k^%F!5|A?rEIOAN7d+T7WQ){?bK z>tpL-j8`Q!gFZ637y99JAc(zf4Fda-PSRINs~fp4kH%`Md(k=`ph;-HLRVaV?-rH8 zGy)*BOd^>@6miOGiILqjmh`q7IG0dU&&vK-Phs7M035x-TWFphguW3+(IXtcy(?S% ziT*Up+Lm)~O0jkv2-?lIjWEO@=5yQ>+XK?kH*uT}0Af48etmlYu`Ot4Z+q4qUOdjN zH5p;e6bx~tdSJTnhR{9Cr&gjanDEgdcV@XvPFQQ zxHs-Q^FnSh$OJwsDJAt9MZ`t1mH-8YdJ%vAa8J=fXS~eI-p_p|yv~$o+TYcmjj_hM z3_Nzpw1la>AbmOD%F#2y7in=QP;Wcmi6U1F*CC{&c==HT-}>VBkIYNM8`Sms`pTsT zqrw)}SJikW;j>k+1OGzQs&J9U!XUBTr%Id%#cKos5D6dt($+SfH9P)asJ{XKEBM3z zyOICoRR4!eLPUbT(X?{5T|>(+{vlKn!EjNu$A1W|JJVmPss0iG|8L0I|IyI@8;1A) zZsfl)L;nrIHlTup)fXpOoDeMiYuGQnU3p}l4RGL3~lGTOPa*TT7_-;oBOInH~5PUT#4eKV7@GmQtZQR z_>;es`sCNcj*=&!GD+BJg^zNaaAqr5!}j!xN}F2_;p3e-oyb4EVXD;-Y|^s5Q-N_= z`gEqu4kv&`5v$Zu7Ddg4fzdrNk$0D37C(~C`3~-M;*+ubJXd9B#cB2~%4hxk5{K!@ z!8x6CczLP_Af1Vpi$5MbHcvZo92&BdeT0RLOez4(M&IA}0S)a0gzMrM7@GV+4S2u3 zn~$W{L-or_fXl1D3x*YECUpXKu2=nN^19xpqtqWHP`@$YoytE8QdYVtRKAy=+ZHxP<5vdot#5Y?~q(0KjNX7t%H6fnC4t(1x{O8#D%P~@T96tFd zfK+xKkq=w%sTpG5AQcN`YWsmR^Wsi|SC>L54Ue8zG#rJ>O}_mACp+6#&e}lp%;5!@hWvo{*|w-=#P7c?ukL9rl!KKix@n#p?o00Hft%e$jfU6`)1Hc6 z)Z)+9aa-q@zc5J}c0a{7xO7=6+T7HfUYnEFw)aqn>5jN>D&SU`v9kjRZ8z0#&v~94uOINEEn=xm^^FGq7nQ>;W} zm*~C79>_aNzF>HY;NMttp-Rfp^T&3z@w1LrS6*K`uI7A~EB-UNC^Y5r_x*SGeJ&xK z*5jsB(zDace&dCT^jvQ$U z^iqX4OrmI}PO6PuTG1lL?gFIrzVZMa@EsA8vgwKAGk*cdSd}Hq8R>K<7;M|Z zs?{nS)z+^oh^##Hby;KE8i-m4!5hQQhmQl=#yS&3;LA?}pHLNa{K14;h%zs9;0ngu zKe;z((N71-zA8E(f1}4w|NSOeg}?l18Vo>mRRGSxX`Tzsy_LQ90taUA8x#+mxt_m4+#92OwtOBBnV-K$ z$H?4aiZ9HyS8qb`&DR<~IUBTvcT_An+<{@o4`KG-+tbo6(&x5R5qL43VYS>xg<^xn zWCzEeP%_y7@#7^fuf4$T-zZ4Q*Z*Ppv8v;$#FPe08;z>HC_7eI2~xnRLO?Sv3Ne~E z4nQ)KmH-=hu8uIwrr)&~buNa9873tMfSIVhVG~2cPb@e^lE)t7w;I&**#VgW+6WF~ z+ym{XDvl+Ga}MWbB2zZq?6ZUGfgnb&W`bPnuS=%^I<_Y*T2t(0DO3_mio@p8k5}8Y z1DcL1aZ@lJtoM5xlYa}(KwxDLvnY?qJCEA;10^Z+{{Uy!U3%_P!gWb(d#LzBQxc(bLCsl9oUMt;0Q;<&^8Zc2w|a!~VXD z!#_V|%z4VS&PRkBzwAJB)}z60Bk#`=fz2;c5B1gdx;Gb}Tkdm4Wnwv=$d2Kqx6tnW z<+PLqA4c6gBRWeL^Cw2E7%8EdE$0R=gQTE{KGqM{sq?YUG{-$7d>(T3oAG;f6(D8$ z(U)?v9X(O8qWepJqAhyMQNqsBU2k^#bgPMB-d6Ks7e~u}S)QgB?(rcx_!*X}{8iN^ z&5q})4GmZv-l`JnU?JACYzo;_JL%tm<-D&MUq51lgD00mo_kI*vrxhjMhD=*pfi8c z(YsoWfs2JzQPHw(BJWA70z4NH83mc8H%?8qco$C;`MN77Vn6>({rpB=jLq)2E3Y$l zeF9G)BYS4(xD_2t!@_0lpttP`xi?X#p@=wy;7fxeTs_7V^{ zZj+eo=8*xT@)I*RhyW#`YT+Ml-2PNoJrP1S##EzH+2&0{Z|Kw~VmLdd!aRE7I|_IRU*+|IDb#TG##vpQa;VkoCaSSZBSW;_)_ zMtP-e{djL$owJXYG*d#aQMM2ob%gcevwwYRn)&G9MCZVxW&~(o$zwH=Bt~w`cjBcW zDtSyqLI+*!{UrV5aM`jRlf0@6bHU!ox?4{8SV4A#n;hw-Dpm2eqS#@vc%*Csi}$5@ z#75F)AdNFsMDvTJMl;enjzRyq9C5|78Vvj!My{+j&+1&$Oaz4Ht8{MX4B|^yIWuO8 z&TFz!KWo7|%-IvQuh(}X25}Wb&UdCC>XueX$4yg0J+EAO2;sb2ipAW7x-l=s#sWqP zX5G{pB(9!5&DzF}HKm%Ptgv&!;T}qQb=W$7-Vj^n3CUggtLHBUH!PjR8HsDTO2V3- zbD=d0SH=VRjJEv^4%j1`af^ofYV>!b5tahn7a5u5G~dIE#+}=P{SNmmxAyoi6d1EI zi>QQFN6@P)nuEM|E~4Jc=6svu1K&geSdnJBrY2q@3H* zuQ+Ch_l)83&kT*nCH7(=X`G(!ae>V?EfMFkV^?)T76X66>^A78Z9~h1l#RPPuOsP6 zLPpk2WJ5jPC4VMc+6^8xU`bN@rumWKd|>5AhUvJwfcz4(rTz9y)}}okYZgdJ3#jA? zIULtS!=(w2Rg(9OZFx+NvZ1C4mpfC2Z^W{PNTUYTINEH{LD8*`nAYEv2YLi;B|t@# zDWg5t^B@IaSVEkX0aWWN4N0y*c1f<${}kAhqsc0jMo(Zw`>P=9y*J%x?u7MOJ}%@5 zM-|vDs(C{)5>xSa9p_>-phB6sRGW=Nt!xmG35zp|h*{o<#)HrPS%-k`_-D>chPa#i~O*5mNspiC-N#rZHccSPpVzM z^0?2_I%vKid|^~)g-fh1?080xuJ)kI1Xp2C`gJMLc<_f&;H!Naz&z*m01H@!$&~&Y_y&IFyf6P$B2}b(aL^?&lIO<*c z#hi~}e{+umk+wTNEtthL5x(8FC#i%e;ITk2Ci+0Tv5(6jEICqf$IB^)G;wx9rNW0& zVGRRfoMe}{Ct)VR=?K;2!ReA2J}!G~d9NiA-yM@@Txl&NVOO&0LHEZWRPa_!I^I+2^W zzDsiOog(RZuOj*LT^G)5c~Cj(#!_K+d5+cY?x|Q3vo7R|%W*eN^jw|q>?;Zmpdm+|Iy^1$BNk>#Ak(j?l*z=~*Zte7=W@MMg3_#q!~*$q18}?g7gQ;zjbvXM zIyzeJwm5H!30r~*R#ADy&zh-)3l_bv(9}k^BsUVYvfnioH%c|0RjkH;n61lul4NrG z#ZHeed~!3@dIYN(Y(!~A8Zl1T+G<5vKG-=VBuykyKh9|OfD_>i+LbY=qeP{CWRs`# z&i{Dgs_Gk=Wf@JoU<}G*J|XWTE6#gMUf{`PmXM9&2fmR0I{4}q!loKOrr1fG7*^$= z+t7XGHK`9N!UkphtGii>Y5d4{7)W3TG1NK;9HORVjAD35%!ZeAf z@4}9}x0(ifD%|5&$;t%@Lz`AX(qhY-e_&fNFaP8U)`xwQG+F-eqr&Lz-W;(>W7J_n zfC*|>TrBK0!BKWo7_rcP)3{p=x`@C`))xsHZW!mcW!h@her8Lg8GX4k35Dw~{nNrL zTixfH5`y!@bNIQx9WZ%DoBQ2-xvrNq^sj6`e8(NK1xLw_(h*l53OvWs9iKA$=n3MF z5Oc}fFseJmsq+VjICQ<_Y24nB!dg#Hp>wM9$j4?{L--K~j8c+UZHRJLB2FwPkHbIp zdYZ2xQhd)!8yb^zkeWs}O*{NEbk4RupbHY^!WYs@4A0)TFG=r8z1HV{jZc)0zcO@a zk9KRe?F7c+rZ2Ne?|47t@pNq?r9Yuoa2Lmre4R9bvKm%)^Vi|Oe&b+I+Y=vBZH?tv zm7S9P&ED+QJ9XzB*Smf%T`vAWvKsw>!G0e(!dyD0nU{j!JL`BMs=Q2ALX%E0q~nRT zv|K(+u9GOfFX>5Ei}`OBOlG!JBjWT=h2Lh;%dGV+K;cBIsXrAyX(T2Is9k5t@NVo2 zB&d+`+ahK3PvgA8e}Nu(wk3Z3nY7PI37VTG(tPcF7zKZn-@l!=RjuK9j(7N-BLY!3 zepAJ2%|!$4Jk3#--mp`Wz*wFM?EG_bpWzf?*sfLqQ**FEfg54QY663eJbPiw_oatq zV}R(V1{aww!_RqToYBcyoGWmz!i!bwTSx$V4sh9hmBvPF{}Z{(ckT|44n+_$2tghg z{<%;iT}^qvthOd~G9t)zr~XLZa^=N)H}?wm)Z^3D;xD2)rrXK%O7`92WZhhS@!YiBkuEoDmDZz~H7>(leJO$^I=`qbmw zV70uBj4vKvSv4mkk^y4hBDxh?FY2?l_7%w*3OkDMq$y>QZZyITIEqB3jQE&?tPDQh zDpzK4gvD-@zwN$XeJ{{k_%_`shQX;zDaL2Y;Iv!RSCa;kgsN8^4tkHr;JLa)#kHeL-5F9Rau0ETKJBL<v`19`m^}?8$-FqY_^??CihKmPzvJGJ% zg`u!QU0WD_W7GJ4qZYe<>Q}#Hg8*A>*|ZI-ZP+gk|3DuT2VmCW7_07kalfs#T#L{q z=N+BJfTdal_809xC&vYnn;+MM_&X!8^=-rU2p^hD_UW~OchfesFu#UU2=TBX3C7&{ zvA+)0JdlXIB$DOIk>m*R%D3fC=IcBCvn#(lZQQ^UkakEix_n$EYJ-`3;bU?u8WvW{ zj=OkfZv!{as8m>z};o_}tOM+|fHsGcq4DO7IU@ zdnRBwyxZZwW_Fqz$_^94On%aR8!3{US^&eU*yiV>v2=OFQ70(0%6o5$6&Imxn!vrq z8L6dHC{>Nco!U0L<@c?iaZfc4EF=z7F;ddV&KF2M&YH^~LtJO*xs(!JvKMu~1+`S7 z*12{D8=Y$;s7+k9{w>d;V#_OkZpA}MX4yEumipjO@1K2f8ziH{*Jjg|!A1}pZyYOW zEYj{D{f$L8uJBc(``S+RzEjEwPzo&v)IttOGI%#iMf`q$CWCuLQw zCMf7GTuascZV(`(Y^5ZhW!wEu!W;@5^5wZ!@GV-5^Wrb?IQZf16ybf<>Uf|h?jt{V zJ7`P5LTIR#+IBJ=b;?dluh%F|M92iWraIEUxGLE4^1+DGbUuDHFpY-)p zc&l4amlUv-mRbhJSwL_S$c#>A^-J<|6fiV`Tu1j zQdWUCD0FvZq-O#k0ib`$wf8mofU%U!x~KsK;#p2{H&dGW%(-xz{{`~1qB&7Hs{g^= zTL#6^h3le8uwWq}Avh$#AwY1qV8PurxCD0(5Foe?gA*9s-C+p9-EGj|Hpt*Jz#YEt z+R#)8?D41ng(VBEh9jkaE4kYcEWUJcbBGCCN21XF z{?7XBvjg{^T3#D}>0qMi?0;=r2J$eWC~&0Iz2=p{@tEjMixj7QiR4OBqLqQ(&wQU} z-X+~=mmek9_upoSzF<6r>1jpfkHKHgPCfcjyyELYx^G}K5Rz&Qnu2Y{^9xDct6xV$ z5JbMl1pJ1};fs^c-h3<){c~^6`L@N(pUcW$S}FafN195l-;)%b$OgY?ZSxTaBOdNe zxiv8Og~00U)IZKMeBH?78gO7M*A!8YGGW*YWzx*gyjbP>RaAmctakn-7#mG)$n5rA zi$DEu?;u1b`57(`$%N)4o*XvPfd{BM)_x$5?4k=mqKDHpaO8 z!dlc7jlk9)2=K1h*hJA>>-!~!Z1gcS{BKN@KOT~7ToXfxQ@2x|b5ODaAEr9HZx{Z# z&S`nHV(IW-s8`#o6+1#FWs%-?`#&cB-gnXHs|LJ2&AHhb{b}^{(Qo2sh8;fYm3Q#ziU?>;< z3V152h7P&)|AiqGrl-=F_a^#I^fm}x-SWWt^=T*LH#L~R@{fEuK`V+Zqxbth=Khf% zc6OGn+^2Lr^ke@uxWHA2Su-^IXe)kfj~5~Ahkm3dc=GMrXC*82h}rtJ&H}-rQ0@U` z*nxk?GrZqnnx_6ECxfjK%t);Ic5_Gi@fL9|Jgyv0q_v-CYUC3Y?T74q6^eMgkh|O* z))h;uvPjf2cR4%w5aS$)L_GRfybShnDu59cRFq5oHtS?W^TGUg`@@Z|nWZJDLn-#>%g>e?4X0l28ij3j=+Rn2!OLSK5WSw60l)Nwa)ykSXIh6F-Y{Y=? zCv59&BJt}Z_vwX2>1|~9s+h+j@@^vPGE{EDdoZlPeEaT6bL9TGn@WKHLhNNUpnr^O zC-YGhQZDqo$BO;O?|0q}nxKyX8P=e}p%Lk=UiWK|KOoXd`bvyY&}K2^>H|)$WoB9f zNoE6H;sEf30aDl8b8>h}ccoT5TKLzid7FQL$zz4ci=an)j;8$Nisx%_JZm$(;VM^6 zh0M3GpKhsu*nCofS48KziYpLEM6bh?m7+iixqT2sA$%0B;`KGDmBh7p{SQ|!rxT<) zhUZ9jdPFvqHn%$D6h$Vih0?&bFU0z^d`m`jvMraaNBC zym!KQx-z_Fxx78P%3K{{Ds}<}Z8Y8;lOt+y$rgty= zFk!wAfBEf(0wKS)T~wujeMe)8-Eyr;8x><8vd`ZURVi#GFiNd1+&2XNguvKWE}j$e zh?kC8kRi{(H>m)w%#}G4+QON5N|vH0DujxCa4JGR#Aw|Nk(dHYdF`ODh3K^Vpx?`@kPkKz>w}{My@pDKsTm4CfQC!OnT*P zHFb@C(d7o!P2ObEwYRR<2+ZkknQ3mJK<_J&>2RByj{%Vp#`RT6bIbtxD8&c!yXIuq z4r+#w-$HSKOu7dQM~lv6%=ef}tF_NOc%0Aj>>pwXg^_gqlVqFp9Vx@hFYO{#O6->A zR4psnfoE>fR!i!UZ47kgmh?%{iMtAoVuyYO=+XtrIbS0&wqlF1LZgJ|A_ma_R)-zm ziEG5U?5#zQOgjhsDBiFDgQMEth0%Zr2cJ5w%B)rErpC&rV_%yshA1sOb5567sBl|tw zgL`)8{APF{u$muP;Z=uuy)8KMJ+EyHW|P;T_ufh6-;(h?$P?!6rTk@Au6*OdG}5VY zOXU5a5%Gi}2Q9;|H>2pxebH*BPyP@{WzCGHmaIf`&(JLN(<>Q}34-4kF zaZ~e-x!%ZctK_-6dAt%teyv^TjSgq3(!dAcVXpzNyKZc)J}l>;Y8bZuL9ilS6Ls^Q zep3q?U0g60yra5;NG=;ZdI@$A4lCI~Nx5^SBGDxL^-h4}@8@nSVZp0BjLKbKTkWh6 zrn~Z!k5O1_|IUeUc_2%lO?cm$-&6-4URS^%j%Bcel;L;cldQO7^FcOU%AX0$*=#Te zhKBTg zOqjIJBO4kQ^4S?6!QCh<3KN;zjFSVZB0c@^_H{vZhh)3Pg6C?%`1%zeB{v}6Bz$SW z!7muwsu{w_G38`??vvh)$#0c^9_D+rh0!N0H`aufy~dIxJgv zSR@fzZ%X%?PJ;A`m#zTQR zV#to^1x6O<%@W+ z>mDGdM4FO34dSU9OGMJLSns|&Ax-$==(?EV6m)TRKaq1GbbB|RpQF`rzdH_c$tESa zpM|q$vko?i_&DtzhIwbK4~|zmjB@Sp{F3eg0b#olcQvR2?QPOPoOYsdP#u%dLD=@7 z$6Kf%s1FDC?%HAIY+Kg5GKH#+V^zm0Dqz&ILuBE4D`g57&5%qtck=YGI;YfoIvjWV z?CO5WH{c?SF_wb7#G8*j-(p3GzwR>ZHeF_GC^d&%slU!;4v)N+ZtqX6IO~0??mb9c zt|LG!HtOh`-pu$CYjoL06`sVK+ZlD=+EI7Me!#^A=yHqw!bp z7JYzg(W%OT35$zgR9z;KF6)$V%h%0Bvj#}DLmEuzE#OKz>t=F%>E<9T1|b_8QJryZ zqF`HInH0a(m9iY2-`4zv0Jd~>DWZ{rV>c%>j{c6~^E ztUbRky52X_foe-e$rdu#X9~DcvA!u*1eMFv)W*`ZFyp5y4yL4mh46%vYKmf5_b-YL zZJipm*tcAw5L1wE>Z#S2LJ&4~>)BHg6YwN_v7FHZG&uVcd(|jm{8o1-f`-}hf+*2# zIEoj#CrG4Y=)8kkN*17V_Q?dkD_E7i1EOgW9z1crzwG-14=F27(sDt7#>m38?@yYw zb`EAJ?MQCVmb7<>7SJCIM#LxC+H^I&IAMDc0e$268Y>U#F^R93QuQ-l>K$&#v)|Y# z3M9l@>d9{T?G(u{*CAMU zFCD)J-VgXKsOWn~aFfiC>YMsA$*{R`aXD=D4A1D|)XV3|+_&MZVrjFnP$xY*uv^bA z4#Hs|d+A%PJ57+m(TNOmb&;&i#4EcK1A1*;^v2=#gRpARflyc>57JvWgJ0GhybR|!^T}5H4Vl?7nB#YP4f8qA(d=tXH#l^aa_rpXn z49<9B)`1XOq~VfxQLn2*;J+F0zHL#OulR&R!X+usAgWT~#qhq^m(LH!U?+c8=aw4l zP$n%QFhWF2&)An(&ONuWk}&I=P#3#o1MJV))uIOMu8I8%m(gu}{Nc)k7<(lZCpQGu235t^1Fv)kL zPF)OfYK$aT`~Lbh8w~2uYN``_*|#gJaVp0!aG0-Di2{!fjB$u9NT#rI;JE9-^9DT5 zpLf+bBoU--4X!S{&tHumbR&p|_r4*NP1YKudtV237ZP#Veh+^oloCf|o!YEAn2H>F zAeFbYl0T(f9U_{?fYw5Ume}@zz-^5hF{e*&WXPg+)oE!UhI6y#Cq4TmCV&6)X7}LE zE`s#>E3kTGFj)#fY`fYDpjBwDO?3I(nDKfO=XUdNzu{Jy>2?aOtD+-l)7C2B}&k+AhPJR>Y04-6*>2)g>sObDxZA zb#Q=tCy+?1t}+YB9v^&*lLs`0$Wd(06DFu2Ba6sSh zxt}yd*}6x^^zRKX-<~IeX@Afc&--wvDl!4jIm(rlyYi6A6_s2{F0!!7Nzv?fibCI< z0uF~bQ8#Ofy-r?STe0zYh@td1MR}yT+|NJrSONqK^2LX&^5$R<%1{}P4EXn7Yh$*R z3dc{LV-LtZWvRDo7KyYNeG{gACt^gurwnxz1=4uta=e{{XDMd0 zX(Y~ATeKpm8-nXu_;f%4OA15s&IX4GOZK&3)eo&VPjt1m)9qgIH0G8XoeA`YZ+N4c zXDf%5YC{y!%<+iDR*6wJp9oNRxZVIWaN0`mSHk5`CJvT@U++|s(9Lrkr-@Y1HjEC8 zaPaBSGiV_7g|EYHh0opPUThJ5ZK!rYy?82&&0%7`FdR0#F{Xqf#h3Q7k#s7TQO0zr zOB|$Fr`h>8c$N2hfx0S|M)w{+lf^a}i^lilZrYd97ZUl4Eb=T_w&%0oS#oOsZ~x*a z{W31@S*gvh8M8rWtUovkqo~xQ?6~pgm-!R(mLz#mz*wEo>_B-xMWP&-AI@t5I{80! zN(W*?Z~O$#dgN*d)Otc%L4Wzw(1l5t1>D>296v>k`v@p?-||Zyd~a}2D4Rf@cu6bIvj@g7Gl-)TS*=kzg|kr!6-auCEK~(WDOLes!`_i z{XVd#Yn<33j_k>Vj@>SHeU<#Yp8^y3Z1%`e92$F53Nc3fN_bIUkx~8TgKZD3kHl7N zYzJYi#yw*;9gNiQXB^lXnyKn2i&q!Lmt1bD&&O$YIa6sXlS-cYnG6!vzq@096Xo(D zJPBQEdVoIl$hchYyn$1GEKYm|m8N-l(wS$i^B%V-1@LqZ+7Q=%SqO*CYEsQCiD{-#Yg_Mcrt6O8$?$R)XPCU^cJ`Zr_v(XwmBK1M z0uwCQEV{~{oL|m(xm#kLeJoH~VfHb_hdvzcVn5^7D!0q%7EZRhk!#A(1?Q3+K{3{~ zej|{Si1opQC&~?T41C2ybla7cuy_YIHNp5ZKE{WNE`EvSDm(W~TFK@}N5A$v`NNF3 znBob-Zsvp(iGWt}Y_dL6_p6l9I;W{piWH6DuD&xQZ%X$vho6&tS8T0fAw`64#gHf= zKs6re3WNma#)$iFU-3{Y{`@4>5hH1!?(0TpLufW|Pkpcq3F_sNQ%Olj3av1gc5T;g zc&%sKTGGbf*|Q5f~JwX_O)@e@%w@|bUr zBnL5Yr38v)90FTnkbZ=J1R6-~L9Uy|;*I+oT%)!|Jt=f!o=d9NNf{T*)jPIr35Qyj zS0c7=tmghE6TwKlxQ5y2Vi{VyulI&l-Q-{Jx5&is=e&4G%GB>z+M5)@Gm>VW1-oGi zVmxykf&DsCMxxzGH&^bUts6kf9fQyWDorhUf&XILt>ATfKT6g6r0y9IUe}*``#-1+ z=?C}t)6iW}2ct*nd9bC-izPKAF}PCVZh~kp{b%eRm}d>^2cvYhhQVyh-~_&@L6}i` znXLJTgA9aV;#ubgeS)(wSNsXZ5qq+RNp|LFZRuRPrSo6e0h#soTIWO3qkS%b5zA7! z$C%kwwZxFo=P4a~vH@(4eiJ*P;jMucFaWOo`MxR%MWt|Oo%c|Svl=}ygeKEN7;Wj4h zAF#99AysxR%Cmkg8k;J1XWTUc*!VdL#FX`O%(i#;;5(V(V0-3q zBv#Be6y6nZOOT<0N8ojx^E2DIpjpE`8lg|N?#dD20#j*Np1n|J7iJc#L7cV|ER%xS zkT2>ycIebp7N>CZ%Q)FwiYU&Xj^|1RJEKyH>C^78oMK+eW=&u|lA0&X zfw!e}+?~TLX@kQObulH6zl3a?S2*`BxhL?@Y3S`TaQxNZBN^jt3NX6=q0~hQ(it;u z#3-@lik;Z{ntPBjEJ*j^btKS2CTS+bw9r?oin!UKDgNSDyeS(+9G#+E%k(O%1Xm^e zVpr7v1ks!#=5_XrElmN}WUa2{b8_&<4I3qPxOOh&L#lHcQtiig*0B@(&}2ig*CnoF z@uGNTBnt73BfyWjf2v*V=X8?N9kzXjodvg8+l;+@Gbwq$oUuDgyebch&i)EceY@0= z>?~{Rslfx^S9Yv*iAH`oGh@Jh{_eeNQz$EaETGa}UQI!*K+71kzeP74(_+v-_Jvll z$vVi&NbM)0OR84CnCaw^h^T|Ic=?4!Qh{y4<>gr4hU^flc=I82zsq)Qgkk_dmb3|B z(YH(+Ax3ey9pRL$^8PT?9W|C}Dv!B2gqknh1RTk___^6xOn7RN-Ihr}+(i1wHJR=R zT2b^gXIfMui*TwfK^!d-% zP&}Qq@VYKbJ%gP)mlmn8Q)zW7U+9KcxUj?OWd35A-DZ3+8<>Sb_u`CQ&O72Ya_#By zKz_FBgl;vl?j6+d(7cMa@xkiiloA$UG`Q2G;d=7f^h$xfwtUFb!@De=+;1z|W%?1|@20o(_aM>>n&`X&)Cr}1or6nReY zUzVEg_yWj3tox?^B7M1Z;C}V{DNg?_fmt8p{q1&;hgsV0>#z^?d!bzWFpDH16}!6Z z1HPq*7MgskL!hAk_;(vOG}F&ZMc2u<42m`&xkt4w>f}CpMzlG-2HuA+te^kv$8+wK z*^8=pf3bL^C0{G6@f|>iHsvZxnm+g$}SJ!eTiG^NGSDB*#Byf2pM=U=3B|`;w#W*(Q9a6vhD-t zaxSWx%Wg|PzYz}5bpNRFsj_h7D?8*pIn9AhJk1ns4a*-fQJ*A-C(jC0L?gx5#;jFA+WVXsv_HH1ymyT)V zZda5;utZR%qEs~-D+fxFq{)@D%&5jhqpZ2*ZI_iN`ah~sO|fTqA%%ITbj^z|v*_}2 zR>OK3wy^e#zZkj1K4M~E%AP$Pp10V(^*AaPUr3-$g;{Nj8%c?H9)!x8H`fLM8%e9p znpp^21$%EvlmcbH*Jp>kkWOX>WnZovz4_a`;_~_LZ~^JlL*U@ou?gfRi(Rc}5g2Uc zCv`luUvOTp`nJ^Y_jH&>M@-#RjJ51ro4IsCy0k4aV|2}d9?WWmHC~>W;ry|E7=R#l z*KhkE!5&lC_Cc`bEVU_i?M7QnX4Y`d!!B5H+$#^~`l9w z!4~hkcW<5mRhm z|F_*{@O4cpI#)RhQnyvJ9&sF!Lo4jEuL+g4Q5-(=FVEKKftV{)Lx6|AP*pF21Ml+_>g9x?-|1ll7^^$Yul5p~F!x!Il zojpHSr2F&nd1CaodsO-=CSdFo#yabM?KHIOKUwbDD^vh6a1goTW?=T9G-QwA!VZId zyBT+}dH6J$t_?nsO5M{IaUPDdYrTZig&Bqm&&KTU7|NYwynL9?6czUObl(M7mYL7P zQz@BOoc~?|C^we;i+7rHwqg(1&B(z4EX|c0QSmTqGm$GQ^@m*>-)Wdd0-s0^{su2l zz9Vf)YAeu1I};iv2ql!}rTq1=p22%9*~-ik;KqdNTy+_2BiJEM{D zD0*56Ue-S?bq%zHD<|p>R%!Cqe>aa>{e0^PW>c%)!#vLpg`ue~>LkI^w%ufA=Er z40`%@`Qt|qiBV2^_~q}!elIiEfVi7r=W zC`4|TZ#p~+rlwNmPberOBp7XFq7D5?23^;!vtwp!6`-8TY;uM^=Wq2R8ZPS`-I+;r zq7!NOe>o-pIl1J2pZD`$f~nyLFQK-dx7zfPfHaklCe32-ZLmZJ5^}y-nG_oEwZ`%G zUm$Jw?w0PZ|Ag>K8}~8I^<1M94H;* zba+dl?s|4Y@Sp+`Ng z4|=rsr(DMW$A>=lUct*7m1Yx^pA87czf0mH{4^TsP8O^gW5|!q6s~Mvyjhkxc+!K2x2e`jn z?5b1gZU9z%<#Qa~kj-t7v#9`L!(P`#;Ee-i-1<{aX4Tb7@$N;^qtiYep!Q8chsQ7b zP5%g9bC-{pfTv6jG1AOqvW4>aP+KXt;?a#I6ZPYW2~?TOXe6{uPoe0*?Yz@7e=Jr1 zPtg_1*f~;O=GuQ{6ND>1i=D~+Du-g@@^n=g@2&6*CQ}_Id5PHipp#7XKLi^ zs&(cr$hwkw0!EE?IKX5E3kS9I0OmE zp)l3KErmH=i4u|kStViCLa8SX20#D0mGk<{eJi`R1+d5joZ_t2$+u1hk4D;*6!(|L zk0qNEuR0N?!OAi@W;`k9wX7>3a1P}T#RAB`5M?_SO%WE+RQF#N#=tbwu?dP|6A7#f z_bv>=?XjT=Q+(GBgP>!i1lH(xR1afjJ^gPsPubF{D?;zI=U>Sdv?B&7f5bN~%KJ>T z6OPxmtt zZCd0jE34`YS^Z5Sbd} z;&zpGH0EQhFKI}nMY&;@*67d!DxGY}Wq^U5P)2oo^6x$iQmGC2UfIuy_Rh<$kODr# zJVFuMf>rV#4jx>B7kTuMeu%DP@DOitvy9G()ir>J=ACG-- zhmM0{N6B?pU3$oJGH*sdn<89B28o3*x}BaruzH5jaQv<3eb=-LsgdzCDOglZ${!n9=%9R zse8QOCgGj{9>$Vt8fvhoZ<_a227)Feg|KSpgTfn}j=}8e7m_l^+3mcp+$PHvIOOnx z!SoPu0rc~t>|=6W{L?!*aky5In}LAqrqKm`Fa_%k*LK?ejS%CFSqs1Gp$-?AMw}J> zoc<5Nz!WQ~b-?-9VlWafUV(bKnf5uu_bB8u^})J7L9th0MJl-pQU z)#kQU*#Sc6L}h=X>PTi^Qs}) zWYZywi4LW-Z-|TLXCgZc@tg}%vhjRA^)-1%m-Y&f^2l~1hy838PQZ1;Hsck%2dHmN zT8ji-%KhcgT30q=UDUKlJDx%cUmRI)J%F(-Y_k_%UPKiObFTCf9NL5(lPIfegh%~! zbICEbPA!vsX&|ER^-_+X;vu4ieKk0X=No3bCys%G+>4LMEkkjpFv4L z=!j(e0h#${b7Mu!tg6)we%N~#_|gOF_84bx3UshL3chs=I5}ZSs5YbXrZM;j+@Znd z!y8()1-T=2wI7_TrqQl;P;mE#(|F!`kvw16^FWMmXw<7NA` z!7P>=cS^V%gLyW(jF1(V=PG=!<3rMy?{A>x(oPjNgitZqQ&#lPY>N$~=&xR&tqCj! zR|qK-8R><0nJfGxOn{)RXs8V=K75{)>7YFI=0OGgU2EP$d+7j+F6^ACgflsDP=8|!8Ev+LQj}4{Lk4K{X>@@097wkvgo znQjfLH;I5SKzW6IBUV2yW}u~v^w|j(s3qaf&AB$O134^0_Ks#Jyl5)7g$eG_Uqz+s zY(#=tOl8DZZc%pUwF5KY`p>grIWDcJL;219hRVUSDm-5y3S~HEvLU<$65b{)Z$FPE zvu}oZz#yTF#2!z5vYuW zD#F~F#zegUql4d=pDH$uNXZISxnfoy%A7P7>zioYh4-}nkhz?t4~0bi)jbp(kG$Vl zwt_&#dOq?@vUpF_)%Zshd@iO(88~$?cs3S@oU4LX0@INlJm&Z9%T`|gG!_A}{}{+n z5*K4bX-e1@iNK_tMKPBZ7rzwU7@9k<*VPPobJHZ=2uJo#$~PTXbA93Ucx!oXT!M-> z{p%Chu}LeFQw!bst@^L8N~AV3Gbb>y4Mv-Oh?ack9fo*L(xN|>e zm)5&>U{|$faX)^$!qsd$8RXvgUJxw0V$}NGxQ$lm1A+NFCx2IR&2WaU+Vr9LJ@5fb8djrmv=6^>WpG)(5=O%k#0;gwe=a!|s^*vHYq$;FVf0171SOZ%E z)oHxSXo+uozurLVOVOUfvGkE_;?}bCsG$M!LV+O$zJAuEIq#&ISFH%rsYcJIv;bhe^2to*KEos?G;KPo{}ZFI)kM8GK0Z~1NAO>>>hp_M7Go$d_w{&^ za~#`IeK~Ba#g>bBVVFs!Oxu1JMf$4|6`=jz8EU7G6w9n(v)#7k|=2x?_4s7|CT)sc|Z>Xw+!S1v;t9tV8f z4iUu?q}S-zX!#pOj=`)Vsi~*7I*+ZgDo-(#5|9s9`1?XDVg0$yRzFd(uVRPk%zc2+ zpqcvq3}jEgC&b&Q4pdz7hHKeW-&;|1u?=^g){BH+pUO)&cJ@z#CMIoZc9F!v4X2q< z`_rur^eyXtz0yHBB7*}gm4=Cr*hhM$)sAigpVin^^mtl!a;?-v%I&9djUOsBb-;nu z4i$<&)cH%a(jks}3H&b0t{pQ&mtTzZqZ6v}0lDmPDe{6UC9(yC7ej8k<~kP|A@siY zA8RZ~1k@1eVWyLK)@pd10+rJL5UZ)`?Vtu;R-P9xNeC7GENGFg>u7})@O%$T=FElX zV=Z(2A|+V06SMP2XCb%yyv&cseT4b0y#}ql655r>sOdEp%fZmPxchmQ`+++v%)fV21zr(@+cVq(-m&#%4eOm`yXS0}hZ(63- z@1BS~xjx6E5koRtIQWv;Mn_>6b3}BaluW3eeIov|GOr^_kHgu-Pj z9d^Y;vPccXWI@!nugM|3cb1MG?r0=Nc9HvC91V3|GxKrBQrd$Fmdmtcsg5q7SHwex zT{+DAzcmb9mS?$gVUw0B)mtwO4Fvqd@)#IUFr8T;=1E6U%D~jwP{LPD9%#BPt<|>0 z-g$FR5GcjSNKRxe)3yqzTV8pm(Bl4o{e%1x%&-v*gOlN6@v&UHU8BmZxBu|}6&+zd zLpe?%$d&>1q11v_C0*53t}qW}h^>G$mjnT=SoNp4%?F?8^6iZWxObS|mAo!99wkZ$GTLSlOI*1xy^q(;j7ge4{?|k97=N z)#IMn`OSZ11#|z`LxcZIO@#j}dHDbDgLIRNf5s~uez?V~y0TmAd!Rfy5EDxHNgJY6 z@YDz~)|rTh5^x&kO^uvYe4k~5;Q{cM^bb!@_KAgpe$v*5aD2b4d`kI{@<=F0uF{jx zuX@Unc69bUjGZFtIjcxpuL(P5b33Sp8X5YfL?dPWYRMfCSv~dvNT)Aks_ustA*TnV zxWqX$3GHfsTjziJ{g5DR_p;~l^Zms0WB(1Y&i`?7mmb9%Zp|P?yd~oR4NSzcCDN(W|uN}3Y7X@LRO+m;^cs=uMje_`)4@Z!~f#2ycUG%qs=$hSH zEyj7j-k~eXiIx1NFxt(`6E;scMGQ2hy09;6#X;VjSNXF?q)TCe`S{aPU}rFMfKvL@ z8?&JyvbJ*HRy9V3VD=M+wd1T$eUjH1QQ2Q#P(T4dKHlQCOOfxXDwSiLPsWNOB9mIs zVxJIi=RMA$qz^IQT)>s2&x-$%565%}!uCqQPZh27fl#?@c?mJOV2b z60vOxzVN0M?rd~T(tom{=`}LE#LH3p7(d0B4?J5t=NY-|=`DS6Ewi^<+8>LEkGh&K zfS@8uEH)#W4L-mGX*bGz(6G$Bxt8r=cJhILI)`c~z9hc$%;6i2V>&JzTE(O8e=ypn z56(L{eh@ezm9doY&UZF$)a&ihYp~f6qRz&Hm+&1`f7YS2z2kmnw{Qy!kHZSDw#(aG zNT(}LM%;#M##iIq-9~?eap}1Ku&zPa=*jq3%xmiL+cwl;hjx@hxJc)i8G;H=&QZe}yWcD= z>w$LTcyg+p`Iu&$dodCyZ78GUniY0;c1!4TZRwqLS=Uo@{?iKpr@&-?Fw|nazn8O6 zUV@>Y*tsOVn$NyZ>;9XK&N9SqnCwM)k9Oh&FvJ`;Y8~~#b2d-S2HT8YF{cJ7f$xo< z9YPBFh^T(opsugRBU*OEiRo@EH?QDlftwG{WZ<>|R*HpWaF=3vnYDX|8h@J>;Mm|v z-^kvr*-ElR0X)1!aG>d#&gCcKhK7Zmhf)ePaLPgCFx6O!D*^ z4$K)au=51ZHRcBsli$PiPB0g^ZSJTk;nS5Y>_XJ5WwN44NH13kn6E2zKDk`x;8g#t>-#w!nuWF5jmb&6C~tv~CNAO}&lH3#e^N zLc@;}t`WVL?Y?qIhyma)=`C){t=+Kc7-7B@q1wAvOTE%^mtCTtLZn9-#nIj57G^#t zX!94h!MEuMpofw3ELRuV!RWRXMr|OdqcRl5r&Bb3sthW>?|B-&2+Q3Q-;~dauL{K5 z-rc@iy%Wd0W|e!1AeISBgDUBnEybD%J&2!m?n^TK-n%Tu`q5w2L3h88H+;@O%xIt+ znkR;KAd=XoMNsjqc(XiiFtMc?u2k+ibonrRmG_MEIU*}5=XjoxX0R{+@G$P&SF&=I zLse?gVy|Wv*H;sHMQxHOWp<8Jjs7Xac{|dj(#{2&-cJZ`tob`>3*~b>k>q##1TMN; zl@#245Ax4?9ZH!RxaIEf^9EL>DL$?0u~VP;O5icMt)fA%18C+EIXC_vVDht(($pu3 z#C`~lGakKrfBL7nsNbbp-6SWKk!gO)?b~hNVrtrGo^E_4j#YXlM{PvAf7Y{!a!XL% zFhVJpRpNuj@l^ znqz+V2grxqj4wSWa^4WT294P_r3mD^=M~LH11^-RrAuAmt1I>SP;KW1;}a1x?C(80 z2Hv92mK!FE<_bqd_czW`_YHO+_~*sH*iC7p+!w&NOl$RY)W-E_5wh&Cj8B;8TKBQ4kn_K2hY;fNP}!FXpiO6_G!EW>7`#{VOK% zW3H`X;jP}WOaoE8W2bV~c**kgVHIrKF&1}J!Y!Na?=S~*sYNWoTDN_Mz%prv=J=|o zYGCy4C3n?V;VH?;7cBkLMh8cSV=OhUkofPX=9mfo$F=xBA3QMMT(~CVkpB!Yd{#n( zFCo=N{gWrCUul==!mpFE#DY^b@KcZt=Ji`Ml-3#Cw1#x@#IzkZWvz^I(PO#^l~aZJ zpofB%EqT?liccC-fEJ>5_(yuwQQ43~F3dwMxfMT+hOeQUdZLV|j1NZ?4=h#UjE+E& zq=-aRB*(kWsL~!$o`^L=cp>p&V((t8;ncC!$4^9b4Va*)(~$6fRqg1n2rEIU5qkay z>zJ�Jw*carNTE6nLE%+B_8aU~@0@5%Bbab2+6F9cML< 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 EA2ZpaU;qFB literal 0 HcmV?d00001 diff --git a/tests/test_authentication.py b/tests/test_authentication.py index 58bcc04..3f76c79 100644 --- a/tests/test_authentication.py +++ b/tests/test_authentication.py @@ -6,6 +6,7 @@ from unittest.mock import patch import resend from urllib.parse import urlparse, parse_qs +from html import unescape from main import app from utils.models import User, PasswordResetToken @@ -321,12 +322,13 @@ def test_password_reset_email_url(unauth_client: TestClient, session: Session, t mock_resend_send.assert_called_once() call_args = mock_resend_send.call_args[0][0] html_content = call_args["html"] + print(html_content) # Extract URL from HTML import re - url_match = re.search(r'href=[\'"]([^\'"]*)[\'"]', html_content) + url_match = re.search(r']*href=[\'"]([^\'"]*)[\'"]', html_content) assert url_match is not None - reset_url = url_match.group(1) + reset_url = unescape(url_match.group(1)) # Parse and verify the URL parsed = urlparse(reset_url)