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

225 lines
19 KiB
Plaintext
Raw Normal View History

2026-05-18 22:25:43 +12:00
+
2026-05-19 23:36:58 +12:00
t= jD(ã
ó°a0t$Rt^RIHt^RIt^RIt^RIt^RIt^RIH t ^RI
2026-05-18 22:25:43 +12:00
t
]P!R4t
2026-05-19 23:36:58 +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# ] 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-05-19 23:36:58 +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©)Úformatsdb.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,
email text not null,
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Ã
C"
ÃC"
ÃC'Ã%DÃ'D Ã-C0Ã.
D Ã9D Ã; DÚ
request_idÚ actor_emailÚipÚstatusÚdetailcó4V^8„dQhRRRRRRRRRRRR R
R /#) rÚ
event_typerr4ú
str | Noner5r6r7r8z dict | Nonerr+r )r
s"r r r tsY÷GñGàðGððGðð Gð
ð Gð
ð
Gð
ðGð
ñGr
c ƒóê"\4GRjxL
pVfR#\4GRjxL
\P!T;'g/4pVP 4;_uu_4GRjxL
pVP RWW#WG4GRjxL
RRR4GRjxL
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¥
insert into events (request_id, event_type, actor_email, ip, status, detail)
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_eventr@téð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ð ð
FððFððFð
ñFr
cƒóÔ"\4GRjxL
pVfR#\4GRjxL
VP4;_uu_4GRjxL
pVPRWPWW4\P
!V44GRjxL
RRR4GRjxL
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')
rBrCrDrEr6r4r?r1r2r(s
$$$$$$$ r Úrecord_submissionrHéðFÜ“Z×ˆØ Š<Ù ÜÓ×ÐØ—<<—>—>”> —,ð %°E¼t¿zºzÈ'Ó?Ró ÷
ð
÷"—> ñ Ù
÷"—>—>“>ûô ôFÜÐ9¸4×EûðFüsÄC(
B9BB9šC(œ
B9©Bª B9Á
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 /#)
rrIÚintrJú
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-05-19 23:36:58 +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) rIrJr:r5r1ÚclausesÚparamsÚwhereÚsqlr2ÚrowsÚrs $$$$ r Ú list_eventsrn­séô× €DØ ‚|؈ Ü
Ó
×ÐØ€GØ€FØÒØ
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-05-19 23:36:58 +12:00
JrBrCc
2026-05-18 22:25:43 +12:00
ó,V^8„dQhRRRRRRRRRR /#)
rrIrLrJrMrBr;rCrrNr )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
RRR4GRjxL
2026-05-19 23:36:58 +12:00
X
2026-05-18 22:25:43 +12:00
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)NrPzkind = $z email = $rQrRrrSz_select id, created_at, request_id, kind, email, full_name, phone, ip, payload from submissions rTrUrVrWrXr4rBrCÚfullNamerDrEr6r?r[) rIrJrBrCr1rhrirjrkr2rlrms $$$$ r Úlist_submissionsrrÚséô× €DØ ‚|؈ Ü
Ó
2026-05-19 23:36:58 +12:00
×ÐØ€GØ€FØÒØ
2026-05-18 22:25:43 +12:00
 ؘ¤ F£ ˜}Ð Ø
2026-05-19 23:36:58 +12:00
ؘ¤# f£+ Ð Ø
2026-05-18 22:25:43 +12:00
e—k‘k“mט¤3 v£; -Ð1ß29ˆX˜Ÿ  
-¸r€EØ
2026-05-19 23:36:58 +12:00
‡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œŸ
š