Files
gw-svelte/mail-api/__pycache__/db.cpython-314.pyc
T

251 lines
22 KiB
Plaintext
Raw Normal View History

2026-05-18 22:25:43 +12:00
+
2026-06-17 21:51:29 +12:00
ƒjT/ã
ó¼a0t$Rt^RIHt^RIt^RIt^RIt^RIt^RIH t ^RI
2026-05-18 22:25:43 +12:00
t
]P!R4t
2026-06-17 21:51:29 +12:00
RsR]R&]P !4t]P !4tRsRR ltR
R ltR R
2026-05-18 22:25:43 +12:00
ltRRltRRRRRRRRRR/RRlltRRltR^dRRRRRR/RRlltR^dRRRRRR/R R!lltR"R#ltR$R%ltR&R'ltR(R)ltR# ] dRt
L²i;i)*aØPostgres-backed key/value persistence for mail-api admin state.
The mail-api historically stored client_profiles / allowed_emails / drafts
as JSON files on a Docker volume. This module lets the same data live in
the shared Goodwalk postgres database so the admin dashboard at
admin.goodwalk.co.nz reads from a real database instead of a per-container
2026-06-17 21:51:29 +12:00
JSON file. JSON files remain as a development/local fallback and as the
2026-05-18 22:25:43 +12:00
seed source for the initial postgres migration.
)Ú annotationsN)ÚAnyz mail-api.dbrÚ_poolFcóV^8„dQhRR/#)éÚreturnÚstr©)Úformats"Ú1C:\Users\mattc\gw-svelte\gw-svelte\mail-api\db.pyÚ __annotate__r !s÷>cór\PPRR4;'gRP4#)Ú DATABASE_URLÚ)ÚosÚenvironÚgetÚstripr r
r Ú database_urlr!s(Ü J‰JN‰N˜>¨2Ó .× 4°"× =r
cóV^8„dQhRR/#©rrÚboolr )r
s"r r r %s÷88r
cóH\\44;'d \RJ#)N)rrÚasyncpgr r
r Ú
is_enabledr%sÜ  Ó × 7¤G°4Ð$7Ð7r
cóV^8„dQhRR/#)rrrr )r
s"r r r )s÷ñ˜ñr
c ƒó"\4'gR#\e\#\;_uu_4GRjxL
\fA\P!\ 4^^^
R7GRjxL
2026-05-19 23:36:58 +12:00
s\ PR4RRR4GRjxL
2026-05-18 22:25:43 +12:00
\#LbL1 \d3p\ PRT4Rp?RRR4GRjxL
R#Rp?ii;iLN +GRjxL
'gi\#;i5i)zFReturn a lazily-initialised asyncpg pool, or None when DB is disabled.N)ÚdsnÚmin_sizeÚmax_sizeÚcommand_timeoutz,Postgres pool ready for admin_kv persistencez9Postgres pool init failed (%s); falling back to JSON only)
rrÚ
_pool_lockrÚ create_poolrÚloggerÚinfoÚ ExceptionÚwarning)Úexcs r Úget_poolr))éô <Š<ÙÜ Ò܈ ßzŽzÜ Š=ð
Ü$ØØØ$&ô ÷ô  Ð €Lññøôô
ÜÐZÐ\_Ô÷zŠzûð
ú÷zz‰zô €Lüs3C?µBC?¹ CÁ%BÁ(BÁ)BÂ C?Â
2026-05-19 23:36:58 +12:00
CÂ C?ÂBÂ CÂ'CÂ=CÃ C?Ã CÃ
2026-05-18 22:25:43 +12:00
C?ÃCÃCÃC?ÃC< Ã$C'Ã%
C< Ã0C< Ã2
C?cóV^8„dQhRR/#)rrÚNoner )r
s"r r r @s÷1ñ1˜1r
c
2026-05-19 23:36:58 +12:00
ƒó "\'dR#\4GRjxL
pVfR#\;_uu_4GRjxL
\'dRRR4GRjxL
R#VP4;_uu_4GRjxL
pVP R4GRjxL
RRR4GRjxL
RsRRR4GRjxL
R#LhLGL0L" +GRjxL
'giL9;iL. +GRjxL
'giR#;i5i)NaC
create table if not exists admin_kv (
key text primary key,
value jsonb not null,
updated_at timestamptz not null default now()
);
create table if not exists events (
id bigserial primary key,
created_at timestamptz not null default now(),
request_id text,
event_type text not null,
actor_email text,
ip text,
status text,
detail jsonb
);
create index if not exists events_created_at_idx on events (created_at desc);
create index if not exists events_event_type_idx on events (event_type);
create index if not exists events_actor_email_idx on events (actor_email);
2026-05-18 22:25:43 +12:00
create table if not exists submissions (
2026-05-19 23:36:58 +12:00
id bigserial primary key,
created_at timestamptz not null default now(),
request_id text,
kind text not null,
2026-06-17 21:51:29 +12:00
email text not null,
2026-05-19 23:36:58 +12:00
full_name text,
phone text,
ip text,
payload jsonb not null
);
create index if not exists submissions_created_at_idx on submissions (created_at desc);
create index if not exists submissions_email_idx on submissions (email);
create index if not exists submissions_kind_idx on submissions (kind);
T)Ú_schema_ensuredr)Ú _schema_lockÚacquireÚexecute)ÚpoolÚconns r Ú_ensure_schemar3@éçƒÙÜ× €DØ ‚|Ùß|Ž|ß ‹?Ø ÷|‰|ð—<<—>—>”> —,#ó%÷%
ð%
÷"—>ðNˆ÷U|‰|ñ óñ%
÷"—>—>>ú÷|||üsØDžB=ŸD»B?¼D¿C'Á
DÁCÁDÁC'Á;C Á<C'Á?C ÂC ÂC Â C'Â$CÂ%C'Â+ DÂ6C%Â7DÂ?DÃDÃC'ÃC ÃC'Ã C"
ÃCÃ
2026-06-17 21:51:29 +12:00
C"
2026-05-19 23:36:58 +12:00
ÃC"
2026-06-17 21:51:29 +12:00
ÃC'Ã%DÃ'D Ã-C0Ã.
2026-05-19 23:36:58 +12:00
D Ã9D Ã; DÚ
request_idÚ actor_emailÚipÚstatusÚdetailcó4V^8„dQhRRRRRRRRRRRR R
R /#) rÚ
event_typerr4ú
str | Noner5r6r7r8ú dict | Nonerr+r )r
s"r r r tsY÷GñGàðGððGðð Gð
ð Gð
ð
Gð
ðGð
ñGr
c ƒóê"\4GRjxL
pVfR#\4GRjxL
2026-06-17 21:51:29 +12:00
\P!T;'g/4pVP 4;_uu_4GRjxL
pVP RWW#WG4GRjxL
RRR4GRjxL
2026-05-19 23:36:58 +12:00
R#LLuL6LL +GRjxL
'giR#;i \ d"p \PRY 4Rp ? R#Rp ? ii;i5i)zˆAppend a single business event to the events table. Best-effort:
failures are logged and swallowed so they never block request handling.Nz¥
2026-06-17 21:51:29 +12:00
insert into events (request_id, event_type, actor_email, ip, status, detail)
2026-05-19 23:36:58 +12:00
values ($1, $2, $3, $4, $5, $6::jsonb)
zrecord_event(%s) failed: %s) r)r3ÚjsonÚdumpsr/r0r&r$r')
r:r4r5r6r7r8r1Úpayloadr2r(s
$$$$$$ r Ú record_eventrAtéðGÜ“Z×ˆØ Š<Ù ÜÓ×ÐÜ—*’*˜VŸ\˜\ *ˆØ—<<—>—>”> —,𨠸ó ÷
ð
÷"—>  ñ á
÷"—>—>“>ûô ôGÜÐ4°j×FûðGüsÊC3
CBCšC3œ
C©BªCÁ#CÁ*B!Á+CÁ.B'ÂB#ÂB'Â CÂB%ÂCÂC3ÂCÂCÂ!CÂ#B'Â%CÂ'C Â-B0Â.
C Â9C Â;CÂ?C3ÃCÃ C0ÃC+Ã%C3Ã+C0Ã0C3có8V^8„dQhRRRRRRRRRRRRR R
R R /#)
rÚkindrÚemailÚ full_namer;Úphoner6r4r@Údictrr+r )r
s"r r r sd÷FñFà
ðFð ðFðð Fð
ð Fð ð
2026-06-17 21:51:29 +12:00
FððFððFð
2026-05-19 23:36:58 +12:00
ñFr
cƒóÔ"\4GRjxL
pVfR#\4GRjxL
VP4;_uu_4GRjxL
2026-06-17 21:51:29 +12:00
pVPRWPWW4\P
2026-05-19 23:36:58 +12:00
!V44GRjxL
2026-06-17 21:51:29 +12:00
RRR4GRjxL
2026-05-19 23:36:58 +12:00
R#L€LjLKLL +GRjxL
'giR#;i \ d"p \PRY 4Rp ? R#Rp ? ii;i5i)zDPersist a contact-form submission (booking / onboarding / contract).Nz­
insert into submissions (request_id, kind, email, full_name, phone, ip, payload)
values ($1, $2, $3, $4, $5, $6, $7::jsonb)
z record_submission(%s) failed: %s) r)r3r/r0r>r?r&r$r')
rCrDrErFr6r4r@r1r2r(s
$$$$$$$ r Úrecord_submissionrIéðFÜ“Z×ˆØ Š<Ù ÜÓ×ÐØ—<<—>—>”> —,ð %°E¼t¿zºzÈ'Ó?Ró ÷
ð
÷"—> ñ Ù
÷"—>—>“>ûô ôFÜÐ9¸4×EûðFüsÄC(
B9BB9šC(œ
2026-06-17 21:51:29 +12:00
B9©Bª B9Á
2026-05-19 23:36:58 +12:00
BÁ B9Á-BÁ;BÁ<BÂ B9Â BÂ B9ÂC(ÂB9ÂB9ÂB9ÂBÂB9ÂB6 Â"B%Â#
B6 Â.B6 Â0B9Â4C(Â6B9Â9 C%ÃC ÃC(Ã C%Ã%C(ÚlimitÚ before_idr:c
ó,V^8„dQhRRRRRRRRRR /#)
rrJÚintrKú
int | Noner:r;r5rú
list[dict]r )r
s"r r r ­s<÷*ñ*à ð*ðð*ðð *ð
ð *ð ñ
*r
cƒó"\4GRjxL
pVf.#\4GRjxL
2026-05-18 22:25:43 +12:00
.p.pVe/VPV4VPR\V4 24V'd/VPV4VPR\V4 24V'dKVPVP 4P 44VPR\V4 24V'dRRP
2026-05-19 23:36:58 +12:00
V4,MRpVP\^\RV444RV R \V4 2pVP4;_uu_4GRjxL
2026-05-18 22:25:43 +12:00
p V P!V.VO5!GRjxL
p
RRR4GRjxL
X
U u.up R
V R
,R V R ,'dV R ,P4MRR
V R,RV R,RV R,RV R,RV R,R\V R,\\\34'd\ P"!V R,4MV R,;'g//N up #ELHEL3+GRjxL
'giLí;iuup i5i)id < $zevent_type = $zactor_email = $úwhere ú and réôz[select id, created_at, request_id, event_type, actor_email, ip, status, detail from events ú order by id desc limit $ÚidÚ createdAtÚ
2026-06-17 21:51:29 +12:00
created_atÚ requestIdr4Ú eventTyper:Ú
2026-05-18 22:25:43 +12:00
actorEmailr5r6r7r8©r)r3ÚappendÚlenrÚlowerÚjoinÚmaxÚminr/ÚfetchÚ isoformatÚ
isinstancerÚbytesÚ bytearrayr>Úloads) rJrKr:r5r1ÚclausesÚparamsÚwhereÚsqlr2ÚrowsÚrs $$$$ r Ú list_eventsro­séô× €DØ ‚|؈ Ü
Ó
×ÐØ€GØ€FØÒØ
2026-06-17 21:51:29 +12:00
2026-05-19 23:36:58 +12:00
 ؘ¤ F£ ˜}ÐØ
2026-05-18 22:25:43 +12:00
˜¬¨F«  }ÐØ
k×)ט¬¨V«¨
Ð7ß29ˆX˜Ÿ  WÓ
-¸r€EØ
‡MM”#˜S %›Ó Ø6´s¸6³{°mð Eðð|‰|~~Œ~ Ø—ZZ Ð- fÓ÷ó ñˆAð
!D•'Ø ¸¸,¿¼˜˜<×4ÈTØ ˜˜<Ø ˜˜<Ø ˜!˜ !D•'Ø a˜•kØ ´*¸Q¸x½[Ì3ÔPUÔW`ÐJa×2bÒ2b”t—zz ! H¥+Ô.ÐhiÐjrÕhs×zÐxzó
ññ ð ò/ òñ$Ù~~Š~üò ùs­JIJ¨I©AJÁ+5JÂ!AJÃ3A,JÅIÅ JÅ#I$Å;I Å<I$Æ JÆ I"Æ JÆJÆ2BJÉ
JÉJÉJÉJÉ I$É"JÉ$I= É*I-É+
I= É6I= É8
2026-06-17 21:51:29 +12:00
JrCrDc
2026-05-18 22:25:43 +12:00
ó,V^8„dQhRRRRRRRRRR /#)
rrJrMrKrNrCr;rDrrOr )r
s"r r r Ús<÷+ñ+à ð+ðð+ð ð +ð
ð +ð ñ
+r
cƒó""\4GRjxL
pVf.#\4GRjxL
.p.pVe/VPV4VPR\V4 24V'd/VPV4VPR\V4 24V'dKVPVP 4P 44VPR\V4 24V'dRRP
V4,MRpVP\^\RV444RV R \V4 2pVP4;_uu_4GRjxL
p V P!V.VO5!GRjxL
p
2026-06-17 21:51:29 +12:00
RRR4GRjxL
X
U u.up R
V R
,R V R ,'dV R ,P4MRR
V R,RV R,RV R,RV R,RV R,RV R,R\V R,\\\34'd\ P"!V R,4MV R,;'g// N up #ELQEL<EL+GRjxL
'giL÷;iuup i5i)NrQzkind = $z email = $rRrSrrTz_select id, created_at, request_id, kind, email, full_name, phone, ip, payload from submissions rUrVrWrXrYr4rCrDÚfullNamerErFr6r@r\) rJrKrCrDr1rirjrkrlr2rmrns $$$$ r Úlist_submissionsrsÚséô× €DØ ‚|؈ Ü
Ó
×ÐØ€GØ€FØÒØ
 ؘ¤ F£ ˜}Ð Ø
ؘ¤# f£+ Ð Ø
e—k‘k“mט¤3 v£; -Ð1ß29ˆX˜Ÿ  
-¸r€EØ
‡MM”#˜S %›Ó Ø!˜7Ð";¼CÀ»K¸ Jðð|‰|~~Œ~ Ø—ZZ Ð- fÓ÷ó
ñˆ
!D•'Ø ¸¸,¿¼˜˜<×4ÈTØ ˜˜<Ø Af•IØ Qw•ZØ ˜˜+Ø Qw•ZØ !D•'Ø ´J¸½|ÌcÔSXÔZcÐMd×4eÒ4eœŸ
š
 1 Y¥<Ô0ÐklÐmvÕkw×~Ð|~ó
ññ
ð
ò/ òò$Ù~~Š~üò
ùs­JI!J¨I$©AJÁ+5JÂ!AJÃ3A,JÅI'Å JÅ#I.Å;I*Å<I.Æ JÆ I,Æ JÆJ
Æ2B#J
2026-05-18 22:25:43 +12:00
ÉJ
ÉJÉ$JÉ'JÉ*I.É,JÉ.J É4I7É5
J ÊJ Ê
Jcó V^8„dQhRRRR/#)rÚkeyrrz
Any | Noner )r
s"r r r s÷ñ˜jñr
2026-06-17 21:51:29 +12:00
cƒóÆ"\4GRjxL
2026-05-18 22:25:43 +12:00
pVfR#\4GRjxL
VP4;_uu_4GRjxL
pVPRV4GRjxL
2026-06-17 21:51:29 +12:00
pV'gRRR4GRjxL
R#VR,p\ V\
2026-05-18 22:25:43 +12:00
\ 34'dTuuRRR4GRjxL
#\ V\\34'dVPR4p\P!V4uuRRR4GRjxL
2026-05-19 23:36:58 +12:00
#ELLfL \dRRR4GRjxL
R#i;i +GRjxL
'giR#;i5i)Nz)select value from admin_kv where key = $1Úvalueúutf-8)
2026-06-17 21:51:29 +12:00
r)r3r/ÚfetchrowrerGÚlistrfrgÚdecoder>rhr&)rur1r2ÚrowÚraws& r Úget_kvr~éÜ× €DØ ‚|ÙÜ
Ó