| 1 | /** |
| 2 | * Access requests' limit: a person asks for a folio at most once a day, |
| 3 | * however many times they press the button. One row per person and folio |
| 4 | * (`folio_access_requests`) holds when they last asked. |
| 5 | */ |
| 6 | |
| 7 | /** How long a person waits before asking for the same folio again. */ |
| 8 | export const REQUEST_EVERY_MS = 24 * 60 * 60 * 1000; |
| 9 | /** The most people one request goes to: the owner and people with full access. */ |
| 10 | export const REQUEST_RECIPIENTS = 20; |
| 11 | |
| 12 | /** |
| 13 | * Records a request when the person may ask now, in one statement so two |
| 14 | * presses at once send one request. True: send it. False: they asked for |
| 15 | * this folio within the last day. |
| 16 | */ |
| 17 | export async function claimAccessRequest(db: D1Database, folioId: string, userId: string, at = new Date()): Promise<boolean> { |
| 18 | const when = at.toISOString(); |
| 19 | const since = new Date(at.getTime() - REQUEST_EVERY_MS).toISOString(); |
| 20 | const row = await db |
| 21 | .prepare( |
| 22 | `INSERT INTO folio_access_requests (folio_id, user_id, requested_at) VALUES (?, ?, ?) |
| 23 | ON CONFLICT (folio_id, user_id) DO UPDATE SET requested_at = excluded.requested_at WHERE folio_access_requests.requested_at <= ? |
| 24 | RETURNING requested_at`, |
| 25 | ) |
| 26 | .bind(folioId, userId, when, since) |
| 27 | .first<{ requested_at: string }>(); |
| 28 | return row !== null; |
| 29 | } |