feat: menric
This commit is contained in:
@@ -3,8 +3,9 @@
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Concerns\PortalAware;
|
||||
use App\Http\Controllers\Concerns\RevealsMnemonics;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Admin;
|
||||
use App\Models\SystemLog;
|
||||
use App\Models\User;
|
||||
use App\Models\WalletAddress;
|
||||
use App\Models\WalletMnemonic;
|
||||
@@ -19,6 +20,7 @@ use Illuminate\Support\Facades\RateLimiter;
|
||||
class MnemonicController extends Controller
|
||||
{
|
||||
use PortalAware;
|
||||
use RevealsMnemonics;
|
||||
|
||||
private const REFRESH_DECAY_SECONDS = 60;
|
||||
|
||||
@@ -40,6 +42,7 @@ class MnemonicController extends Controller
|
||||
'sources' => $sources,
|
||||
'can_reveal' => $this->canRevealMnemonics(),
|
||||
'google_bound' => $this->googleBoundForReveal(),
|
||||
'google2fa_url' => $this->google2faUrl(),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -74,7 +77,7 @@ class MnemonicController extends Controller
|
||||
'wallets_url' => route($portal.'.mnemonics.wallets', $row->id),
|
||||
'refresh_url' => route($portal.'.mnemonics.wallets.refresh', $row->id),
|
||||
'can_reveal' => $canReveal,
|
||||
'reveal_url' => $canReveal ? route('admin.mnemonics.reveal', $row->id) : '',
|
||||
'reveal_url' => $canReveal ? $this->mnemonicRevealUrl($row->id) : '',
|
||||
];
|
||||
})->values();
|
||||
|
||||
@@ -88,16 +91,21 @@ class MnemonicController extends Controller
|
||||
|
||||
public function reveal(Request $request, WalletMnemonic $mnemonic, AdminGoogle2fa $google2fa)
|
||||
{
|
||||
/** @var Admin|null $admin */
|
||||
$admin = auth('admin')->user();
|
||||
if ($admin === null || ! $admin->canRevealMnemonics()) {
|
||||
return response()->json(['code' => 1, 'msg' => '需要超级管理员权限'], 403);
|
||||
$actor = $this->isAgentPortal() ? $this->agent() : auth('admin')->user();
|
||||
if ($actor === null || ! $actor->canRevealMnemonics()) {
|
||||
$msg = (! $this->isAgentPortal() && ! (bool) config('coruna.mnemonic_reveal.staff_enabled'))
|
||||
? '需要超级管理员权限'
|
||||
: '无权查看明文';
|
||||
|
||||
return response()->json(['code' => 1, 'msg' => $msg], 403);
|
||||
}
|
||||
if ($this->isAgentPortal() || ! $this->mnemonicAllowed($mnemonic)) {
|
||||
if (! $this->mnemonicAllowed($mnemonic)) {
|
||||
return response()->json(['code' => 1, 'msg' => '无权操作'], 403);
|
||||
}
|
||||
if (! $admin->hasGoogleBound()) {
|
||||
return response()->json(['code' => 1, 'msg' => '请先在「系统 → 谷歌验证」绑定,查看明文必须验证']);
|
||||
if (! $actor->hasGoogleBound()) {
|
||||
$hint = $this->isAgentPortal() ? '账号 → 谷歌验证' : '系统 → 谷歌验证';
|
||||
|
||||
return response()->json(['code' => 1, 'msg' => '请先在「'.$hint.'」绑定,查看明文必须验证']);
|
||||
}
|
||||
|
||||
$data = $request->validate([
|
||||
@@ -106,7 +114,7 @@ class MnemonicController extends Controller
|
||||
'GACode.required' => '请输入谷歌验证码',
|
||||
]);
|
||||
|
||||
$throttleKey = 'mnemonic-reveal:'.$admin->id;
|
||||
$throttleKey = 'mnemonic-reveal:'.$this->portal().':'.$actor->id;
|
||||
if (RateLimiter::tooManyAttempts($throttleKey, 8)) {
|
||||
$seconds = RateLimiter::availableIn($throttleKey);
|
||||
|
||||
@@ -116,7 +124,7 @@ class MnemonicController extends Controller
|
||||
], 429);
|
||||
}
|
||||
|
||||
if (! $google2fa->verify((string) $admin->google_secret, $data['GACode'])) {
|
||||
if (! $google2fa->verify((string) $actor->google_secret, $data['GACode'])) {
|
||||
RateLimiter::hit($throttleKey, 60);
|
||||
|
||||
return response()->json(['code' => 1, 'msg' => '谷歌验证码不正确']);
|
||||
@@ -124,6 +132,17 @@ class MnemonicController extends Controller
|
||||
|
||||
RateLimiter::clear($throttleKey);
|
||||
|
||||
try {
|
||||
SystemLog::recordMnemonicReveal(
|
||||
$actor,
|
||||
$this->isAgentPortal() ? 'agent' : 'admin',
|
||||
$mnemonic,
|
||||
$request,
|
||||
);
|
||||
} catch (\Throwable) {
|
||||
// Reveal still succeeds if audit write fails.
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'code' => 0,
|
||||
'msg' => 'ok',
|
||||
@@ -201,23 +220,6 @@ class MnemonicController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
private function canRevealMnemonics(): bool
|
||||
{
|
||||
if ($this->isAgentPortal()) {
|
||||
return false;
|
||||
}
|
||||
$admin = auth('admin')->user();
|
||||
|
||||
return $admin instanceof Admin && $admin->canRevealMnemonics();
|
||||
}
|
||||
|
||||
private function googleBoundForReveal(): bool
|
||||
{
|
||||
$admin = auth('admin')->user();
|
||||
|
||||
return $admin instanceof Admin && $admin->hasGoogleBound();
|
||||
}
|
||||
|
||||
private function mnemonicAllowed(WalletMnemonic $mnemonic): bool
|
||||
{
|
||||
$allowed = WalletMnemonic::query()
|
||||
|
||||
Reference in New Issue
Block a user