fix(alerts): защитить тест правила общим замком Telegram
This commit is contained in:
1 parent
9c1d14635a
commit
dc5594ca7c
9 files changed
+110
-61
No files matched your search
@@ -0,0 +1,34 @@
|
||||
"use client"
|
||||
import {useEffect,useRef,useState,useSyncExternalStore} from "react"
|
||||
import {testTelegramSchema,type TestTelegramBody} from "@mmapp/contracts/alerts"
|
||||
import {can} from "@/lib/auth"
|
||||
import {telegramPending,subscribeTelegramPending,setTelegramPending} from "@/lib/alerts-telegram-checkpoint"
|
||||
import {ApiClientError} from "@/shared/api/http-client"
|
||||
import {testAlertsTelegram} from "@/shared/api/alerts"
|
||||
|
||||
export function useAlertsTelegramPreview(base:string,live:boolean,available:boolean,onBegin:()=>boolean,onEnd:()=>void){
|
||||
const source=JSON.stringify([live,base])
|
||||
const unknown=useSyncExternalStore(subscribeTelegramPending,()=>telegramPending(source),()=>false)
|
||||
const [busy,setBusy]=useState(false),[error,setError]=useState<string|null>(null),[outcome,setOutcome]=useState<string|null>(null)
|
||||
const active=useRef(true),lock=useRef(false),controller=useRef<AbortController|null>(null)
|
||||
useEffect(()=>{active.current=true;return()=>{active.current=false;controller.current?.abort()}},[source])
|
||||
const enabled=live&&available&&can("mm:alerts:write")
|
||||
async function test(payload:TestTelegramBody){
|
||||
if(!enabled||lock.current||telegramPending(source)||!active.current||!can("mm:alerts:write"))return false
|
||||
const parsed=testTelegramSchema.strict().safeParse(payload)
|
||||
if(!parsed.success){setError("Проверьте параметры тестового сообщения");return false}
|
||||
if(!onBegin())return false
|
||||
lock.current=true;controller.current=new AbortController();setBusy(true);setError(null);setOutcome(null);setTelegramPending(source,true)
|
||||
const current=()=>active.current&&can("mm:alerts:write")
|
||||
try{
|
||||
await testAlertsTelegram(base,parsed.data,{signal:controller.current.signal});if(!current())return false
|
||||
setTelegramPending(source,false);setOutcome("Telegram API подтвердил приём тестового правила. Проверьте его в чате.");return true
|
||||
}catch(e){
|
||||
if(e instanceof ApiClientError&&[400,401,403,409,422].includes(e.status)&¤t())setTelegramPending(source,false)
|
||||
if(current())setError(e instanceof Error?e.message:"Результат отправки не получен");return false
|
||||
}finally{lock.current=false;controller.current=null;if(active.current){setBusy(false);onEnd()}}
|
||||
}
|
||||
function review(){if(!enabled||busy)return;setTelegramPending(source,false)}
|
||||
function clear(){setError(null);setOutcome(null)}
|
||||
return {test,busy,error,outcome,unknown,enabled,review,clear}
|
||||
}
|
||||
Reference in new issue
Block a user