mirror of
https://github.com/freedbygrace/DynamoDNS.git
synced 2026-07-26 11:38:13 +00:00
Enhance DNS record display with automatic IP address updates. The API now retrieves and displays the current public IP address for A and AAAA records with auto-IP enabled.
Replit-Commit-Author: Agent Replit-Commit-Session-Id: 9111ef36-26c8-4085-84ca-a35dc1fec1b5 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/7083d608-d6d3-4a6a-9a27-6286c5109627/eac6d55d-5ae1-43e4-8a86-77381999f6ba.jpg
This commit is contained in:
+60
-1
@@ -5,6 +5,7 @@ import { db } from "./db";
|
||||
import { setupAuth, requireRole } from "./auth";
|
||||
import { z } from "zod";
|
||||
import { eq } from "drizzle-orm";
|
||||
import { getCurrentIpAddress, getCurrentIpv6Address } from "./utils/ip-utils";
|
||||
import {
|
||||
insertDomainSchema,
|
||||
insertDnsRecordSchema,
|
||||
@@ -169,7 +170,40 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
||||
console.log(`API endpoint: Fetching DNS records for domain: ${domainId}`);
|
||||
const records = await storage.getDnsRecordsByDomain(domainId);
|
||||
console.log(`API endpoint: Retrieved ${records.length} DNS records from storage`);
|
||||
res.json(records);
|
||||
|
||||
// Process records to show current IP for auto IP records
|
||||
const processedRecords = await Promise.all(records.map(async (record) => {
|
||||
// For A records with auto IP enabled, fetch the current IP
|
||||
if (record.isAutoIP && (record.type === 'A' || record.type === 'AAAA')) {
|
||||
try {
|
||||
// Get the appropriate IP address based on record type
|
||||
let currentIp = null;
|
||||
if (record.type === 'A') {
|
||||
currentIp = await getCurrentIpAddress();
|
||||
} else if (record.type === 'AAAA') {
|
||||
currentIp = await getCurrentIpv6Address();
|
||||
}
|
||||
|
||||
if (currentIp) {
|
||||
console.log(`Found current IP for auto record ${record.id}: ${currentIp}`);
|
||||
// Create a new object to avoid modifying the original record
|
||||
return {
|
||||
...record,
|
||||
// Store the actual IP in the response for display purposes
|
||||
currentIp: currentIp,
|
||||
// Keep content as is - the UI will show currentIp if isAutoIP is true
|
||||
};
|
||||
}
|
||||
} catch (ipError) {
|
||||
console.error(`Error getting current IP for record ${record.id}:`, ipError);
|
||||
}
|
||||
}
|
||||
|
||||
// Return the record unmodified if it's not auto IP or if there was an error
|
||||
return record;
|
||||
}));
|
||||
|
||||
res.json(processedRecords);
|
||||
} catch (error) {
|
||||
console.error("Error fetching DNS records:", error);
|
||||
res.status(500).json({
|
||||
@@ -188,6 +222,31 @@ export async function registerRoutes(app: Express): Promise<Server> {
|
||||
return res.status(404).json({ message: "DNS record not found" });
|
||||
}
|
||||
|
||||
// For A/AAAA records with auto IP enabled, fetch the current IP address
|
||||
if (record.isAutoIP && (record.type === 'A' || record.type === 'AAAA')) {
|
||||
try {
|
||||
// Get the appropriate IP address based on record type
|
||||
let currentIp = null;
|
||||
if (record.type === 'A') {
|
||||
currentIp = await getCurrentIpAddress();
|
||||
} else if (record.type === 'AAAA') {
|
||||
currentIp = await getCurrentIpv6Address();
|
||||
}
|
||||
|
||||
if (currentIp) {
|
||||
console.log(`Found current IP for auto record ${record.id}: ${currentIp}`);
|
||||
// Create a new object to avoid modifying the original record
|
||||
return res.json({
|
||||
...record,
|
||||
// Store the actual IP in the response for display purposes
|
||||
currentIp: currentIp
|
||||
});
|
||||
}
|
||||
} catch (ipError) {
|
||||
console.error(`Error getting current IP for record ${record.id}:`, ipError);
|
||||
}
|
||||
}
|
||||
|
||||
res.json(record);
|
||||
} catch (error) {
|
||||
console.error("Error fetching DNS record:", error);
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
import fetch from 'node-fetch';
|
||||
|
||||
/**
|
||||
* Gets the current public IP address of the server
|
||||
* Uses multiple services for redundancy
|
||||
*/
|
||||
export async function getCurrentIpAddress(): Promise<string | null> {
|
||||
const ipServices = [
|
||||
'https://api.ipify.org',
|
||||
'https://ifconfig.me/ip',
|
||||
'https://icanhazip.com',
|
||||
'https://ipecho.net/plain'
|
||||
];
|
||||
|
||||
// Try each service in sequence until we get a valid response
|
||||
for (const service of ipServices) {
|
||||
try {
|
||||
console.log(`Attempting to get IP address from ${service}`);
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
||||
|
||||
const response = await fetch(service, { signal: controller.signal });
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
if (response.ok) {
|
||||
const ip = (await response.text()).trim();
|
||||
console.log(`Got IP address: ${ip} from ${service}`);
|
||||
|
||||
// Basic validation - IP should be a string with numbers and dots
|
||||
if (ip && /^[0-9.]+$/.test(ip)) {
|
||||
return ip;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Error getting IP from ${service}:`, error);
|
||||
// Continue to the next service
|
||||
}
|
||||
}
|
||||
|
||||
console.error('Failed to get IP address from any service');
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current IPv6 address (if available)
|
||||
*/
|
||||
export async function getCurrentIpv6Address(): Promise<string | null> {
|
||||
try {
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
||||
|
||||
const response = await fetch('https://ipv6.icanhazip.com', { signal: controller.signal });
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
if (response.ok) {
|
||||
const ip = (await response.text()).trim();
|
||||
console.log(`Got IPv6 address: ${ip}`);
|
||||
|
||||
// Basic validation for IPv6 format
|
||||
if (ip && ip.includes(':')) {
|
||||
return ip;
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error getting IPv6 address:', error);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user