40 lines
2.9 KiB
JavaScript
40 lines
2.9 KiB
JavaScript
/**
|
|
* hal/ui/public/reauth.mjs — 운영자 콘솔 재인증 흐름의 순수 계약(0.2.1, 개발 지시 `Ariweb-Suitle_Dev-Order_v0.2.1.md`).
|
|
*
|
|
* 브라우저(ops.js)와 Node 테스트가 같은 파일을 쓴다. DOM·fetch 를 직접 만지지 않고, 호출자가 넘긴 함수만 부른다.
|
|
*
|
|
* 왜 따로 두나
|
|
* - 0.2.0 까지는 재인증이 10분을 넘기면 모든 일반 화면 위에 "고위험 작업(…)은 최근 10분 안의 재인증이 필요합니다" 전역 배너가 늘 떠 있었다.
|
|
* 단순 조회·화면 이동·로그인 10분 뒤에도 보여 운영자가 경고에 무뎌진다. 0.2.1 은 이 안내를 backend 가 실제로 고위험 요청을
|
|
* `reauth_required` 로 거부한 **바로 그 때 여는 재인증 창 안**으로만 옮긴다. 수동 재인증(계정 화면 단추)에는 붙이지 않는다.
|
|
* - 보안 경계는 그대로다: 거부·재인증 판단은 전부 서버(hal/app.mjs requireRecent·CSRF·3단계 확인)가 하고, 여기는 "거부됐을 때 어떻게 묻고 몇 번 다시 보내는가"만 정한다.
|
|
*/
|
|
|
|
/** 서버가 고위험 요청을 거부할 때 쓰는 오류 코드(hal/app.mjs requireRecent 와 같은 값) */
|
|
export const REAUTH_REQUIRED = 'reauth_required';
|
|
/** 거부 시점 재인증 창에만 보이는 고위험 안내(옛 전역 배너 문구 그대로 — 위치만 옮겼다) */
|
|
export const HIGH_RISK_NOTICE = '고위험 작업(서버 삭제·되돌리기·인증 키 변경·복구)은 최근 10분 안의 재인증이 필요합니다';
|
|
|
|
/**
|
|
* 재인증 창의 문구. required=true(서버 거부 직후)일 때만 고위험 안내(note)를 붙이고, 수동 재인증(required 없음)은 안내 없이 비밀번호만 묻는다.
|
|
* @returns {{ title: string, okLabel: string, note: string }}
|
|
*/
|
|
export function reauthPrompt({ required = false } = {}) {
|
|
return { title: '재인증(최근 10분)', okLabel: '재인증', note: required ? HIGH_RISK_NOTICE : '' };
|
|
}
|
|
|
|
/**
|
|
* 요청을 보내고, 서버가 `reauth_required` 로 거부하면 재인증을 묻고(required=true) 성공했을 때만 **딱 한 번** 다시 보낸다.
|
|
* - 재인증 창을 취소하거나 재인증이 실패하면 원 요청을 다시 보내지 않고 원래 오류를 그대로 올린다(고위험 작업이 몰래 실행되지 않음).
|
|
* - 재시도도 거부되면 다시 묻지 않고 오류를 올린다(무한 반복 금지).
|
|
* - `reauth_required` 가 아닌 오류(권한 없음·검증 실패·네트워크)는 재인증을 묻지 않는다.
|
|
* @param {() => Promise<any>} run 실제 요청(같은 method·path·body 로 다시 부를 수 있어야 한다)
|
|
* @param {(opts: { required: true }) => Promise<boolean>} reauth 재인증 창을 열어 성공 여부를 돌려주는 함수
|
|
*/
|
|
export async function callWithReauth(run, reauth) {
|
|
try { return await run(); } catch (e) {
|
|
if (e && e.code === REAUTH_REQUIRED && await reauth({ required: true })) return run();
|
|
throw e;
|
|
}
|
|
}
|