141 lines
6.7 KiB
PHP
141 lines
6.7 KiB
PHP
@extends('admin.layouts.app')
|
|
|
|
@section('title', '보안 설정 (2차 인증)')
|
|
|
|
@section('content')
|
|
<div class="a-panel">
|
|
<div style="display:flex; justify-content:space-between; align-items:flex-start; gap:12px; flex-wrap:wrap;">
|
|
<div>
|
|
<div style="font-weight:900; font-size:16px;">2차 인증 (Google OTP)</div>
|
|
<div class="a-muted" style="font-size:12px; margin-top:4px;">
|
|
SMS 또는 Google OTP(TOTP)로 2차 인증을 진행합니다.
|
|
</div>
|
|
</div>
|
|
|
|
<a class="a-btn a-btn--ghost a-btn--sm" href="{{ route('admin.me') }}" style="width:auto;">뒤로가기</a>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="height:12px;"></div>
|
|
|
|
{{-- 이용 안내 --}}
|
|
<div class="a-panel">
|
|
<div style="font-weight:900; margin-bottom:6px;">이용 안내</div>
|
|
<div class="a-muted" style="font-size:13px; line-height:1.55;">
|
|
1) Google Authenticator / Microsoft Authenticator 등 앱 설치<br>
|
|
2) 등록 시작 → QR 스캔(또는 시크릿 수동 입력)<br>
|
|
3) 앱에 표시되는 6자리 코드를 입력해 등록 완료<br>
|
|
4) 필요 시 재등록(새 시크릿 발급) 또는 삭제 가능
|
|
</div>
|
|
</div>
|
|
|
|
<div style="height:12px;"></div>
|
|
|
|
{{-- 상태/모드 --}}
|
|
<div class="a-panel">
|
|
<div style="display:flex; justify-content:space-between; gap:12px; flex-wrap:wrap; align-items:center;">
|
|
<div>
|
|
<div style="font-weight:900;">현재 상태</div>
|
|
<div style="margin-top:6px;">
|
|
@if($isRegistered)
|
|
<span class="a-pill a-pill--ok">Google OTP 등록됨</span>
|
|
<span class="a-muted" style="font-size:12px; margin-left:6px;">({{ $admin->totp_verified_at }})</span>
|
|
@elseif($isPending)
|
|
<span class="a-pill a-pill--warn">등록 진행 중</span>
|
|
@else
|
|
<span class="a-pill a-pill--muted">미등록</span>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
|
|
<form method="POST" action="{{ route('admin.totp.mode') }}" style="display:flex; gap:8px; align-items:center; flex-wrap:wrap;">
|
|
@csrf
|
|
<label class="a-muted" style="font-size:13px;">2차 인증방법</label>
|
|
<select class="a-input a-input--sm" name="totp_enabled" style="width:180px;">
|
|
<option value="0" {{ (int)($admin->totp_enabled ?? 0) === 0 ? 'selected' : '' }}>SMS 인증</option>
|
|
<option value="1"
|
|
{{ (int)($admin->totp_enabled ?? 0) === 1 ? 'selected' : '' }}
|
|
{{ !$isRegistered ? 'disabled' : '' }}
|
|
>Google OTP 인증</option>
|
|
</select>
|
|
<button class="a-btn a-btn--primary a-btn--sm" type="submit" style="width:auto;">저장</button>
|
|
|
|
@if(!$isRegistered)
|
|
<div class="a-muted" style="font-size:12px; width:100%;">
|
|
※ Google OTP 미등록 상태에서는 OTP 인증으로 전환할 수 없습니다.
|
|
</div>
|
|
@endif
|
|
</form>
|
|
</div>
|
|
</div>
|
|
|
|
<div style="height:12px;"></div>
|
|
|
|
{{-- 등록/확인 UI --}}
|
|
@if($isPending)
|
|
<div class="a-panel">
|
|
<div style="font-weight:900; margin-bottom:10px;">등록 진행</div>
|
|
|
|
<div class="a-grid2">
|
|
<div class="a-card" style="padding:14px;">
|
|
<div class="a-muted" style="font-size:12px; margin-bottom:8px;">QR 코드 스캔</div>
|
|
<div style="background:#fff; border-radius:14px; padding:12px; display:inline-block;">
|
|
{!! $qrSvg !!}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="a-card" style="padding:14px;">
|
|
<div class="a-muted" style="font-size:12px; margin-bottom:6px;">시크릿(수동 입력용)</div>
|
|
<div class="a-mono" style="font-weight:900; font-size:16px; letter-spacing:.08em;">
|
|
{{ $secret }}
|
|
</div>
|
|
|
|
<div style="height:10px;"></div>
|
|
|
|
<form method="POST" action="{{ route('admin.totp.confirm') }}">
|
|
@csrf
|
|
<label class="a-label">앱에 표시된 6자리 인증코드</label>
|
|
<input class="a-input a-otp-input" name="code" inputmode="numeric" autocomplete="one-time-code" placeholder="123456">
|
|
@error('code') <div class="a-error">{{ $message }}</div> @enderror
|
|
|
|
<button class="a-btn a-btn--primary" type="submit" style="margin-top:12px;">
|
|
등록 완료
|
|
</button>
|
|
</form>
|
|
|
|
<form method="POST" action="{{ route('admin.totp.disable') }}" style="margin-top:10px;"
|
|
data-confirm="등록을 취소하고 OTP 정보를 삭제할까요?">
|
|
@csrf
|
|
<button class="a-btn a-btn--danger" type="submit">등록 취소(삭제)</button>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@else
|
|
{{-- 미등록 / 등록됨 --}}
|
|
<div class="a-panel">
|
|
<div style="display:flex; gap:8px; flex-wrap:wrap;">
|
|
@if(!$isRegistered)
|
|
<form method="POST" action="{{ route('admin.totp.start') }}"
|
|
data-confirm="Google OTP 등록을 시작할까요?\nQR 스캔 후 6자리 코드를 입력해야 완료됩니다.">
|
|
@csrf
|
|
<button class="a-btn a-btn--primary" type="submit" style="width:auto;">등록 시작</button>
|
|
</form>
|
|
@else
|
|
<form method="POST" action="{{ route('admin.totp.reset') }}"
|
|
data-confirm="Google OTP를 재등록할까요?\n새 시크릿이 발급되며 기존 등록은 무효화됩니다.">
|
|
@csrf
|
|
<button class="a-btn a-btn--primary" type="submit" style="width:auto;">재등록(수정)</button>
|
|
</form>
|
|
|
|
<form method="POST" action="{{ route('admin.totp.disable') }}"
|
|
data-confirm="Google OTP를 삭제할까요?\n삭제 후에는 SMS 인증을 사용합니다.">
|
|
@csrf
|
|
<button class="a-btn a-btn--danger" type="submit" style="width:auto;">삭제</button>
|
|
</form>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
@endif
|
|
@endsection
|