修复打手短信验证码发送
This commit is contained in:
@@ -2,3 +2,4 @@ export * from './types.js'
|
||||
export * from './shared.js'
|
||||
export * from './worker-repo.js'
|
||||
export * from './work-order-repo.js'
|
||||
export * from './sms-code-repo.js'
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
import { query } from '../../db/client.js'
|
||||
|
||||
export type WorkerSmsCodeRow = {
|
||||
id: number
|
||||
phone: string
|
||||
purpose: string
|
||||
code_hash: string
|
||||
expires_at: string
|
||||
consumed_at: string | null
|
||||
created_at: string
|
||||
}
|
||||
|
||||
export async function createWorkerSmsCode(input: {
|
||||
phone: string
|
||||
purpose: string
|
||||
codeHash: string
|
||||
expiresAt: string
|
||||
now: string
|
||||
}): Promise<WorkerSmsCodeRow | null> {
|
||||
const result = await query<WorkerSmsCodeRow>(
|
||||
`
|
||||
INSERT INTO worker_sms_codes (phone, purpose, code_hash, expires_at, consumed_at, created_at)
|
||||
VALUES ($1, $2, $3, $4, NULL, $5)
|
||||
RETURNING *
|
||||
`,
|
||||
[input.phone, input.purpose, input.codeHash, input.expiresAt, input.now],
|
||||
)
|
||||
return result.rows[0] || null
|
||||
}
|
||||
|
||||
export async function getLatestWorkerSmsCode(
|
||||
phone: string,
|
||||
purpose: string,
|
||||
): Promise<WorkerSmsCodeRow | null> {
|
||||
const result = await query<WorkerSmsCodeRow>(
|
||||
`
|
||||
SELECT *
|
||||
FROM worker_sms_codes
|
||||
WHERE phone = $1 AND purpose = $2
|
||||
ORDER BY id DESC
|
||||
LIMIT 1
|
||||
`,
|
||||
[phone, purpose],
|
||||
)
|
||||
return result.rows[0] || null
|
||||
}
|
||||
|
||||
export async function consumeWorkerSmsCode(
|
||||
codeId: number,
|
||||
now: string,
|
||||
): Promise<WorkerSmsCodeRow | null> {
|
||||
const result = await query<WorkerSmsCodeRow>(
|
||||
`
|
||||
UPDATE worker_sms_codes
|
||||
SET consumed_at = $1
|
||||
WHERE id = $2 AND consumed_at IS NULL
|
||||
RETURNING *
|
||||
`,
|
||||
[now, codeId],
|
||||
)
|
||||
return result.rows[0] || null
|
||||
}
|
||||
|
||||
export async function countWorkerSmsCodesOnDay(
|
||||
phone: string,
|
||||
dayStartIso: string,
|
||||
dayEndIso: string,
|
||||
): Promise<number> {
|
||||
const result = await query<{ total: number }>(
|
||||
`
|
||||
SELECT COUNT(*)::int AS total
|
||||
FROM worker_sms_codes
|
||||
WHERE phone = $1
|
||||
AND created_at >= $2
|
||||
AND created_at < $3
|
||||
`,
|
||||
[phone, dayStartIso, dayEndIso],
|
||||
)
|
||||
return Number(result.rows[0]?.total || 0)
|
||||
}
|
||||
@@ -118,6 +118,14 @@ export async function getWorkerUserByUsername(username: string): Promise<WorkerU
|
||||
return result.rows[0] || null
|
||||
}
|
||||
|
||||
export async function getWorkerUserByPhone(phone: string): Promise<WorkerUserRow | null> {
|
||||
const result = await query<WorkerUserRow>(
|
||||
`${WORKER_USER_SELECT} WHERE wu.phone = $1 LIMIT 1`,
|
||||
[String(phone || '').trim()],
|
||||
)
|
||||
return result.rows[0] || null
|
||||
}
|
||||
|
||||
export async function getWorkerUserByInviteCode(
|
||||
inviteCode: string,
|
||||
): Promise<WorkerUserRow | null> {
|
||||
|
||||
Reference in New Issue
Block a user