Jelajahi Sumber

fix: show DNS current values for verification records

AI-Co-Authored-By: Codex
chendeben 1 bulan lalu
induk
melakukan
5789576e93

File diff ditekan karena terlalu besar
+ 0 - 0
public/assets/index-rR5xt_XM.js


+ 1 - 1
public/index.html

@@ -4,7 +4,7 @@
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <title>MailHub</title>
-    <script type="module" crossorigin src="/assets/index-DCOXBks-.js"></script>
+    <script type="module" crossorigin src="/assets/index-rR5xt_XM.js"></script>
     <link rel="modulepreload" crossorigin href="/assets/styles-BBgHuOwj.js">
     <link rel="stylesheet" crossorigin href="/assets/styles-CWLk_28-.css">
     <link rel="stylesheet" crossorigin href="/assets/index-Tu04tXLf.css">

+ 2 - 5
src/components/domain/DnsRecordCard.tsx

@@ -4,6 +4,7 @@ import { Alert, Button, Card, Space, Tooltip, Typography } from 'antd';
 import { useI18n } from '../../frontend/i18n/react';
 import type { DnsRecord } from '../../frontend/types';
 import { StatusTag } from '../common/StatusTag';
+import { getDnsCurrentValues } from '../../frontend/domain-model.js';
 
 interface DnsRecordCardProps {
   record: DnsRecord;
@@ -14,11 +15,7 @@ interface DnsRecordCardProps {
 
 export function DnsRecordCard({ record, loading, onCopy, onRecheck }: DnsRecordCardProps) {
   const { t } = useI18n();
-  const currentValues = Array.isArray(record.current)
-    ? record.current
-    : record.current
-      ? [record.current]
-      : [];
+  const currentValues: string[] = getDnsCurrentValues(record);
 
   return (
     <Card

+ 2 - 0
src/dns-guide.js

@@ -23,6 +23,7 @@ export async function buildDnsGuide(domain) {
       host: `_mailhub.${domain.domain}`,
       type: 'TXT',
       value: verificationValue,
+      current: live.verificationTxt,
       status: containsTxt(live.verificationTxt, verificationValue) ? 'ok' : 'missing'
     },
     {
@@ -31,6 +32,7 @@ export async function buildDnsGuide(domain) {
       host: `${domain.selector}._domainkey.${domain.domain}`,
       type: 'TXT',
       value: dkimValue,
+      current: live.dkimTxt,
       status: containsTxt(live.dkimTxt, dkimValue) ? 'ok' : 'missing'
     },
     {

+ 7 - 0
src/frontend/domain-model.js

@@ -15,6 +15,13 @@ export function getRecordStatusMeta(record = {}) {
   return STATUS_META[String(record.status || '').toLowerCase()] || STATUS_META.missing;
 }
 
+export function getDnsCurrentValues(record = {}) {
+  if (Array.isArray(record.current)) return record.current.filter((value) => value);
+  if (record.current) return [record.current];
+  const status = getRecordStatusMeta(record);
+  return status.key === 'success' && record.value ? [record.value] : [];
+}
+
 export function getRequiredDnsRecords(domain = {}) {
   const records = Array.isArray(domain.status?.records) ? domain.status.records : [];
   const byKey = new Map(records.map((record) => [record.key, record]));

+ 58 - 0
test/dns-guide.test.js

@@ -0,0 +1,58 @@
+import assert from 'node:assert/strict';
+import dns from 'node:dns';
+import { test } from 'node:test';
+
+test('includes live current values for verification and dkim records', async () => {
+  const originalResolver = dns.promises.Resolver;
+  const lookup = new Map([
+    ['example.com', ['v=spf1 ip4:192.0.2.10 a:mail.example.com ~all']],
+    ['_mailhub.example.com', ['mailhub-verification=verify-token']],
+    ['mh202607._domainkey.example.com', ['v=DKIM1; k=rsa; p=dkim-public']],
+    ['_dmarc.example.com', ['v=DMARC1; p=none; rua=mailto:dmarc@example.com; adkim=s; aspf=s; pct=100']]
+  ]);
+
+  dns.promises.Resolver = class FakeResolver {
+    setServers() {}
+
+    async resolveTxt(name) {
+      const value = lookup.get(name);
+      if (!value) {
+        const error = new Error('not found');
+        error.code = 'ENODATA';
+        throw error;
+      }
+      return value.map((record) => [record]);
+    }
+
+    async resolve4(name) {
+      return name === 'mail.example.com' ? ['192.0.2.10'] : [];
+    }
+
+    async reverse(ip) {
+      return ip === '192.0.2.10' ? ['mail.example.com'] : [];
+    }
+  };
+
+  try {
+    const { buildDnsGuide } = await import(`../src/dns-guide.js?test=${Date.now()}`);
+    const guide = await buildDnsGuide({
+      domain: 'example.com',
+      selector: 'mh202607',
+      verificationToken: 'verify-token',
+      dkimPublic: 'dkim-public',
+      senderHost: 'mail.example.com',
+      sendingIp: '192.0.2.10',
+      spfExtra: '',
+      dmarcPolicy: 'none',
+      dmarcRua: 'mailto:dmarc@example.com'
+    });
+
+    const verification = guide.records.find((record) => record.key === 'verification');
+    const dkim = guide.records.find((record) => record.key === 'dkim');
+
+    assert.deepEqual(verification.current, ['mailhub-verification=verify-token']);
+    assert.deepEqual(dkim.current, ['v=DKIM1; k=rsa; p=dkim-public']);
+  } finally {
+    dns.promises.Resolver = originalResolver;
+  }
+});

+ 8 - 0
test/frontend-domain-model.test.js

@@ -3,6 +3,7 @@ import { test } from 'node:test';
 import {
   buildDnsApplyFeedback,
   buildDomainHealth,
+  getDnsCurrentValues,
   getRecordStatusMeta,
   getRequiredDnsRecords
 } from '../src/frontend/domain-model.js';
@@ -93,6 +94,13 @@ test('builds warning feedback for partial DNS apply failures', () => {
   });
 });
 
+test('normalizes DNS current values with legacy successful record fallback only', () => {
+  assert.deepEqual(getDnsCurrentValues({ current: ['one', 'two'], value: 'target', status: 'ok' }), ['one', 'two']);
+  assert.deepEqual(getDnsCurrentValues({ current: 'one', value: 'target', status: 'ok' }), ['one']);
+  assert.deepEqual(getDnsCurrentValues({ value: 'target', status: 'ok' }), ['target']);
+  assert.deepEqual(getDnsCurrentValues({ value: 'target', status: 'missing' }), []);
+});
+
 function record(key, status) {
   return {
     key,

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini