chore: add domain logic
This commit is contained in:
+6
-6
@@ -20,12 +20,12 @@
|
||||
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
||||
"test:e2e": "jest --config ./test/jest-e2e.json",
|
||||
"prepare": "husky || true",
|
||||
"orm:create": "mikro-orm migration:create --config=database/mikro-orm.config.ts",
|
||||
"orm:up": "mikro-orm migration:up --config=database/mikro-orm.config.ts",
|
||||
"orm:down": "mikro-orm migration:down --config=database/mikro-orm.config.ts",
|
||||
"orm:generate": "mikro-orm migration:create --blank --config=database/mikro-orm.config.ts",
|
||||
"orm:update": "mikro-orm schema:update --run --config=database/mikro-orm.config.ts",
|
||||
"orm:drop": "mikro-orm schema:drop --run --config=database/mikro-orm.config.ts",
|
||||
"orm:create": "mikro-orm migration:create --config=database/mikro-orm.config.ts",
|
||||
"orm:up": "mikro-orm migration:up --config=database/mikro-orm.config.ts",
|
||||
"orm:down": "mikro-orm migration:down --config=database/mikro-orm.config.ts",
|
||||
"orm:generate": "mikro-orm migration:create --blank --config=database/mikro-orm.config.ts",
|
||||
"orm:update": "mikro-orm schema:update --run --config=database/mikro-orm.config.ts",
|
||||
"orm:drop": "mikro-orm schema:drop --run --drop-migrations-table --drop-db --config=database/mikro-orm.config.ts",
|
||||
"orm:seed": "mikro-orm seeder:create --config=database/mikro-orm.config.ts",
|
||||
"seed:run": "mikro-orm seeder:run --config=database/mikro-orm.config.ts"
|
||||
},
|
||||
|
||||
@@ -612,4 +612,36 @@ export const enum BusinessMessage {
|
||||
BUSINESS_SETTINGS_UPDATED = "تنظیمات کسب و کار با موفقیت به روز رسانی شد",
|
||||
NAME_REQUIRED = "نام کسب و کار مورد نیاز است",
|
||||
NAME_STRING = "نام کسب و کار باید یک رشته باشد",
|
||||
DOMAIN_CONNECTED = "دامنه با موفقیت متصل شد",
|
||||
DOMAIN_NOT_CONNECTED = "دامنه به سرور ما متصل نشد",
|
||||
DOMAIN_NOT_FOUND = "دامنه یافت نشد",
|
||||
DOMAIN_VERIFICATION_TOKEN_REQUIRED = "توکن تایید دامنه مورد نیاز است",
|
||||
|
||||
// Domain Connection Instructions in Farsi
|
||||
DOMAIN_CONNECTION_TITLE = "دامنه خود را به سرورهای ما متصل کنید",
|
||||
DOMAIN_CONNECTION_DESCRIPTION = "یکی از این گزینهها را برای اتصال دامنه خود انتخاب کنید:",
|
||||
DOMAIN_CONNECTION_OPTION_A_TITLE = "گزینه A: استفاده از رکورد A (IP مستقیم)",
|
||||
DOMAIN_CONNECTION_OPTION_A_STEP1 = "۱. یک رکورد A در تنظیمات DNS خود اضافه کنید",
|
||||
DOMAIN_CONNECTION_OPTION_A_STEP2 = "۲. میزبان را روی @ یا زیردامنه خود (مثلاً www) تنظیم کنید - رکورد A",
|
||||
DOMAIN_CONNECTION_OPTION_A_STEP3 = "۳. مقدار را به IP سرور ما تنظیم کنید: ",
|
||||
DOMAIN_CONNECTION_OPTION_A_STEP4 = "۴. TTL را روی ۳۶۰۰ (۱ ساعت) یا کمترین مقدار موجود تنظیم کنید - رکورد A",
|
||||
DOMAIN_CONNECTION_OPTION_B_TITLE = "گزینه B: استفاده از رکورد CNAME (توصیه شده)",
|
||||
DOMAIN_CONNECTION_OPTION_B_STEP1 = "۱. یک رکورد CNAME در تنظیمات DNS خود اضافه کنید",
|
||||
DOMAIN_CONNECTION_OPTION_B_STEP2 = "۲. میزبان را روی @ یا زیردامنه خود (مثلاً www) تنظیم کنید - رکورد CNAME",
|
||||
DOMAIN_CONNECTION_OPTION_B_STEP3 = "۳. مقدار را تنظیم کنید به: ",
|
||||
DOMAIN_CONNECTION_OPTION_B_STEP4 = "۴. TTL را روی ۳۶۰۰ (۱ ساعت) یا کمترین مقدار موجود تنظیم کنید - رکورد CNAME",
|
||||
DOMAIN_CONNECTION_OPTION_B_NOTE = "توجه: برخی از ارائهدهندگان DNS اجازه CNAME برای دامنههای اصلی (@) را نمیدهند",
|
||||
DOMAIN_CONNECTION_TROUBLESHOOTING_1 = "- مطمئن شوید که رکوردها را به دامنه صحیح اضافه کردهاید",
|
||||
DOMAIN_CONNECTION_TROUBLESHOOTING_2 = "- برخی از ارائهدهندگان DNS برای دامنههای اصلی به نماد @ نیاز دارند",
|
||||
DOMAIN_CONNECTION_TROUBLESHOOTING_3 = "- بررسی کنید که مقادیر را دقیقاً همانطور که نشان داده شده کپی کردهاید",
|
||||
DOMAIN_CONNECTION_TROUBLESHOOTING_4 = "- تغییرات DNS میتواند برای انتشار زمان ببرد (معمولاً ۱۵ دقیقه تا ۴۸ ساعت)",
|
||||
|
||||
// Domain Setup Instructions in Farsi
|
||||
DOMAIN_SETUP_VERIFICATION_TITLE = "مرحله ۱: تایید مالکیت دامنه",
|
||||
DOMAIN_SETUP_VERIFICATION_DESC = "این رکورد TXT را اضافه کنید تا ثابت کنید مالک دامنه هستید:",
|
||||
DOMAIN_SETUP_PROPAGATION_NOTE = "تغییرات DNS میتواند ۱۵ دقیقه تا ۴۸ ساعت در سراسر جهان منتشر شود",
|
||||
DOMAIN_SETUP_TROUBLESHOOTING_1 = "- اطمینان حاصل کنید که رکوردها را به دامنه صحیح اضافه کردهاید",
|
||||
DOMAIN_SETUP_TROUBLESHOOTING_2 = "- بعضی از ارائهدهندگان DNS برای دامنههای اصلی به نماد @ نیاز دارند",
|
||||
DOMAIN_SETUP_TROUBLESHOOTING_3 = "- اطمینان حاصل کنید که مقادیر را دقیقاً همانطور که نشان داده شده کپی کردهاید",
|
||||
DOMAIN_SETUP_TROUBLESHOOTING_4 = "- حداقل ۱۵ دقیقه قبل از بررسی وضعیت تأیید صبر کنید",
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Body, Controller, Get, Param, Patch, Post, UseInterceptors } from "@nestjs/common";
|
||||
import { ApiHeader, ApiOperation } from "@nestjs/swagger";
|
||||
import { ApiHeader, ApiOperation, ApiTags } from "@nestjs/swagger";
|
||||
|
||||
import { UpdateBusinessDomainDto } from "./DTO/business-domain.dto";
|
||||
import { BusinessSlugParamDto } from "./DTO/business-slug-param.dto";
|
||||
@@ -13,6 +13,7 @@ import { BusinessInterceptor } from "../../core/interceptors/business.intercepto
|
||||
|
||||
@Controller("business")
|
||||
@ApiHeader({ name: "x-business-id", description: "Business ID" })
|
||||
@ApiTags("Business")
|
||||
@UseInterceptors(BusinessInterceptor)
|
||||
export class BusinessesController {
|
||||
constructor(
|
||||
@@ -22,86 +23,43 @@ export class BusinessesController {
|
||||
|
||||
@Get("slug/:slug")
|
||||
@ApiOperation({ summary: "Get business by slug" })
|
||||
async getBusinessBySlug(@Param() params: BusinessSlugParamDto) {
|
||||
getBusinessBySlug(@Param() params: BusinessSlugParamDto) {
|
||||
return this.businessesService.getBusinessBySlug(params.slug);
|
||||
}
|
||||
|
||||
@Patch("settings")
|
||||
@ApiOperation({ summary: "Update business settings" })
|
||||
@AuthGuards()
|
||||
async updateBusinessSettings(@BusinessDec("id") businessId: string, @Body() settingsDto: UpdateBusinessSettingsDto) {
|
||||
updateBusinessSettings(@BusinessDec("id") businessId: string, @Body() settingsDto: UpdateBusinessSettingsDto) {
|
||||
return this.businessesService.updateBusinessSettings(businessId, settingsDto);
|
||||
}
|
||||
|
||||
@Get("settings")
|
||||
@ApiOperation({ summary: "Get business settings" })
|
||||
@AuthGuards()
|
||||
async getBusinessSettings(@BusinessDec("id") businessId: string) {
|
||||
getBusinessSettings(@BusinessDec("id") businessId: string) {
|
||||
return this.businessesService.getBusinessSettings(businessId);
|
||||
}
|
||||
|
||||
// Domain management endpoints - simplified flow
|
||||
@Post("domain")
|
||||
@ApiOperation({ summary: "Update business domain" })
|
||||
@ApiOperation({ summary: "Set/update business domain and get verification instructions" })
|
||||
@AuthGuards()
|
||||
async updateBusinessDomain(@BusinessDec() business: Business, @Body() domainDto: UpdateBusinessDomainDto) {
|
||||
return this.domainVerificationService.updateBusinessDomain(business.id, domainDto);
|
||||
}
|
||||
|
||||
@Get("domain/status")
|
||||
@ApiOperation({ summary: "Get business domain status" })
|
||||
@AuthGuards()
|
||||
async getDomainStatus(@BusinessDec() business: Business) {
|
||||
return this.domainVerificationService.getDomainVerificationStatus(business.id);
|
||||
setDomain(@BusinessDec() business: Business, @Body() domainDto: UpdateBusinessDomainDto) {
|
||||
return this.domainVerificationService.setDomain(business.id, domainDto);
|
||||
}
|
||||
|
||||
@Post("domain/verify")
|
||||
@ApiOperation({ summary: "Initiate domain verification" })
|
||||
@ApiOperation({ summary: "Verify domain ownership and connection" })
|
||||
@AuthGuards()
|
||||
async verifyDomain(@BusinessDec() business: Business) {
|
||||
return this.domainVerificationService.initiateVerification(business.id);
|
||||
}
|
||||
|
||||
@Post("domain/verify/check")
|
||||
@ApiOperation({ summary: "Check domain verification status" })
|
||||
@AuthGuards()
|
||||
async checkVerification(@BusinessDec() business: Business) {
|
||||
verifyDomain(@BusinessDec() business: Business) {
|
||||
return this.domainVerificationService.verifyDomain(business.id);
|
||||
}
|
||||
|
||||
// DNS-specific domain verification endpoints
|
||||
@Post("domain/set-domain")
|
||||
@ApiOperation({ summary: "Set domain and get verification instructions" })
|
||||
@Get("domain/status")
|
||||
@ApiOperation({ summary: "Get current domain status" })
|
||||
@AuthGuards()
|
||||
async setDomainAndGetInstructions(@BusinessDec() business: Business, @Body() domainDto: UpdateBusinessDomainDto) {
|
||||
return this.domainVerificationService.setDomainAndGetVerificationInstructions(business.id, domainDto.domain);
|
||||
}
|
||||
|
||||
@Get("domain/check-dns")
|
||||
@ApiOperation({ summary: "Check DNS verification" })
|
||||
@AuthGuards()
|
||||
async checkDnsVerification(@BusinessDec() business: Business) {
|
||||
return this.domainVerificationService.verifyDnsTxtRecord(business.id);
|
||||
}
|
||||
|
||||
// Admin domain management endpoints
|
||||
@Post("admin/:businessId/domain/verify")
|
||||
@ApiOperation({ summary: "Admin initiate domain verification" })
|
||||
@AuthGuards()
|
||||
async adminVerifyDomain(@Param("businessId") businessId: string) {
|
||||
return this.domainVerificationService.initiateVerification(businessId);
|
||||
}
|
||||
|
||||
@Post("admin/:businessId/domain/verify/check")
|
||||
@ApiOperation({ summary: "Admin check domain verification status" })
|
||||
@AuthGuards()
|
||||
async adminCheckVerification(@Param("businessId") businessId: string) {
|
||||
return this.domainVerificationService.verifyDomain(businessId);
|
||||
}
|
||||
|
||||
@Post("admin/:businessId/domain/check-dns")
|
||||
@ApiOperation({ summary: "Admin check DNS verification" })
|
||||
@AuthGuards()
|
||||
async adminCheckDnsVerification(@Param("businessId") businessId: string) {
|
||||
return this.domainVerificationService.verifyDnsTxtRecord(businessId);
|
||||
getDomainStatus(@BusinessDec() business: Business) {
|
||||
return this.domainVerificationService.getDomainStatus(business.id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ export class DomainVerificationService {
|
||||
private readonly resolveA = promisify(dns.resolve4);
|
||||
private readonly resolveCname = promisify(dns.resolveCname);
|
||||
|
||||
private readonly serverIP = "IP_OF_YOUR_SERVER";
|
||||
private readonly serverIP = "194.5.192.20";
|
||||
private readonly serverDomain = "app.dzone.danakcorp.com";
|
||||
|
||||
constructor(
|
||||
@@ -26,21 +26,27 @@ export class DomainVerificationService {
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Update business domain
|
||||
* Set Domain - Core method for setting/updating the domain and returning instructions
|
||||
*
|
||||
* This is the main entry point for users to set their domain
|
||||
*/
|
||||
async updateBusinessDomain(businessId: string, domainDto: UpdateBusinessDomainDto) {
|
||||
async setDomain(businessId: string, domainDto: UpdateBusinessDomainDto) {
|
||||
const business = await this.businessesService.getBusinessById(businessId);
|
||||
|
||||
// If domain hasn't changed and is already verified, just return success
|
||||
if (business.domain === domainDto.domain && business.isDomainVerified) {
|
||||
return {
|
||||
message: BusinessMessage.DOMAIN_ALREADY_VERIFIED,
|
||||
domain: business.domain,
|
||||
isVerified: business.isDomainVerified,
|
||||
verifiedAt: business.domainVerifiedAt,
|
||||
};
|
||||
}
|
||||
|
||||
// Generate verification token
|
||||
const verificationToken = this.generateVerificationToken();
|
||||
|
||||
// Update domain info
|
||||
business.domain = domainDto.domain;
|
||||
business.isDomainVerified = false;
|
||||
business.domainVerificationToken = verificationToken;
|
||||
@@ -48,133 +54,33 @@ export class DomainVerificationService {
|
||||
|
||||
await this.em.flush();
|
||||
|
||||
// Return setup instructions
|
||||
return {
|
||||
message: BusinessMessage.DOMAIN_UPDATED,
|
||||
message: BusinessMessage.DOMAIN_VERIFICATION_INITIATED,
|
||||
domain: business.domain,
|
||||
isVerified: business.isDomainVerified,
|
||||
isVerified: false,
|
||||
dnsInstructions: this.getDomainSetupInstructions(business.domain, verificationToken),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate domain verification with specific method
|
||||
* Verify Domain - Check domain ownership and connection status
|
||||
*
|
||||
* This method checks if the domain is properly configured with TXT record and
|
||||
* if it points to our servers
|
||||
*/
|
||||
async initiateVerification(businessId: string) {
|
||||
const business = await this.businessesService.getBusinessById(businessId);
|
||||
|
||||
if (!business.domain) throw new BadRequestException(BusinessMessage.DOMAIN_INVALID);
|
||||
|
||||
if (business.isDomainVerified) {
|
||||
return {
|
||||
message: BusinessMessage.DOMAIN_ALREADY_VERIFIED,
|
||||
domain: business.domain,
|
||||
isVerified: true,
|
||||
verifiedAt: business.domainVerifiedAt,
|
||||
};
|
||||
}
|
||||
|
||||
if (!business.domainVerificationToken) {
|
||||
business.domainVerificationToken = this.generateVerificationToken();
|
||||
await this.em.flush();
|
||||
}
|
||||
|
||||
await this.em.flush();
|
||||
|
||||
return {
|
||||
message: BusinessMessage.DOMAIN_VERIFICATION_INITIATED,
|
||||
domain: business.domain,
|
||||
instructions: this.getDomainSetupInstructions(business.domain, business.domainVerificationToken),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Set domain and get verification and connection instructions
|
||||
*/
|
||||
async setDomainAndGetVerificationInstructions(businessId: string, domain: string) {
|
||||
const business = await this.businessesService.getBusinessById(businessId);
|
||||
|
||||
// Domain hasn't changed, check if it's already verified
|
||||
if (business.domain === domain && business.isDomainVerified) {
|
||||
return {
|
||||
message: BusinessMessage.DOMAIN_ALREADY_VERIFIED,
|
||||
domain: business.domain,
|
||||
isVerified: business.isDomainVerified,
|
||||
dnsInstructions: business.domainVerificationToken
|
||||
? this.getDomainSetupInstructions(domain, business.domainVerificationToken)
|
||||
: this.getDomainSetupInstructions(domain, ""),
|
||||
};
|
||||
}
|
||||
|
||||
// Generate verification token
|
||||
const verificationToken = this.generateVerificationToken();
|
||||
|
||||
// Update the domain and verification data
|
||||
business.domain = domain;
|
||||
business.isDomainVerified = false;
|
||||
business.domainVerificationToken = verificationToken;
|
||||
business.domainVerifiedAt = undefined;
|
||||
|
||||
await this.em.flush();
|
||||
|
||||
// Return DNS verification and setup instructions
|
||||
return {
|
||||
message: BusinessMessage.DOMAIN_VERIFICATION_INITIATED,
|
||||
domain: business.domain,
|
||||
isVerified: false,
|
||||
dnsInstructions: this.getDomainSetupInstructions(domain, verificationToken),
|
||||
};
|
||||
}
|
||||
|
||||
//************************************** */
|
||||
async verifyDomain(businessId: string) {
|
||||
const business = await this.businessesService.getBusinessById(businessId);
|
||||
|
||||
if (!business.domain || !business.domainVerificationToken) throw new BadRequestException(BusinessMessage.DOMAIN_VERIFICATION_METHOD_INVALID);
|
||||
|
||||
if (business.isDomainVerified) {
|
||||
// Validate required fields
|
||||
if (!business.domain) {
|
||||
return {
|
||||
message: BusinessMessage.DOMAIN_ALREADY_VERIFIED,
|
||||
domain: business.domain,
|
||||
isVerified: true,
|
||||
verifiedAt: business.domainVerifiedAt,
|
||||
hasDomain: false,
|
||||
message: BusinessMessage.DOMAIN_NOT_FOUND,
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
let isVerified = false;
|
||||
|
||||
isVerified = await this.checkDnsTxtRecord(business.domain, business.domainVerificationToken);
|
||||
|
||||
if (isVerified) {
|
||||
business.isDomainVerified = true;
|
||||
business.domainVerifiedAt = dayjs().toDate();
|
||||
await this.em.flush();
|
||||
|
||||
return {
|
||||
message: BusinessMessage.DOMAIN_VERIFICATION_SUCCESS,
|
||||
domain: business.domain,
|
||||
isVerified: true,
|
||||
verifiedAt: business.domainVerifiedAt,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
message: BusinessMessage.DOMAIN_VERIFICATION_FAILED,
|
||||
domain: business.domain,
|
||||
isVerified: false,
|
||||
instructions: this.getDomainSetupInstructions(business.domain, business.domainVerificationToken),
|
||||
};
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
this.logger.error(`Domain verification failed: ${error instanceof Error ? error.message : String(error)}`);
|
||||
throw new BadRequestException(BusinessMessage.DOMAIN_VERIFICATION_FAILED);
|
||||
}
|
||||
}
|
||||
|
||||
//************************************** */
|
||||
async verifyDnsTxtRecord(businessId: string) {
|
||||
const business = await this.businessesService.getBusinessById(businessId);
|
||||
|
||||
if (!business.domain || !business.domainVerificationToken) throw new BadRequestException(BusinessMessage.DOMAIN_INVALID);
|
||||
if (!business.domainVerificationToken) throw new BadRequestException(BusinessMessage.DOMAIN_VERIFICATION_TOKEN_REQUIRED);
|
||||
|
||||
if (business.isDomainVerified) {
|
||||
const domainPointsToServer = await this.checkDomainPointsToServer(business.domain);
|
||||
@@ -185,23 +91,20 @@ export class DomainVerificationService {
|
||||
isVerified: true,
|
||||
verifiedAt: business.domainVerifiedAt,
|
||||
domainPointsToServer,
|
||||
serverConnectionStatus: domainPointsToServer
|
||||
? "Your domain is properly set up and pointing to our servers"
|
||||
: "Your domain is verified, but not properly pointing to our servers",
|
||||
setupInstructions: !domainPointsToServer ? this.getDomainConnectionInstructions(business.domain) : null,
|
||||
connectionStatus: domainPointsToServer ? BusinessMessage.DOMAIN_CONNECTED : BusinessMessage.DOMAIN_NOT_CONNECTED,
|
||||
connectionInstructions: !domainPointsToServer ? this.getDomainConnectionInstructions(business.domain) : null,
|
||||
};
|
||||
}
|
||||
|
||||
try {
|
||||
// First check domain ownership verification via TXT record
|
||||
// Check domain ownership verification via TXT record
|
||||
const isVerified = await this.checkDnsTxtRecord(business.domain, business.domainVerificationToken);
|
||||
|
||||
// Then check if domain points to our server (A or CNAME record)
|
||||
// Check domain points to our server
|
||||
const domainPointsToServer = await this.checkDomainPointsToServer(business.domain);
|
||||
|
||||
// If TXT verification passes, mark the domain as verified regardless of A/CNAME
|
||||
// Update verification status if verified
|
||||
if (isVerified) {
|
||||
// Update domain verification status
|
||||
business.isDomainVerified = true;
|
||||
business.domainVerifiedAt = dayjs().toDate();
|
||||
await this.em.flush();
|
||||
@@ -212,21 +115,18 @@ export class DomainVerificationService {
|
||||
isVerified: true,
|
||||
verifiedAt: business.domainVerifiedAt,
|
||||
domainPointsToServer,
|
||||
serverConnectionStatus: domainPointsToServer
|
||||
? "Your domain is properly set up and pointing to our servers"
|
||||
: "Your domain is verified, but not properly pointing to our servers",
|
||||
connectionStatus: domainPointsToServer ? BusinessMessage.DOMAIN_CONNECTED : BusinessMessage.DOMAIN_NOT_CONNECTED,
|
||||
connectionInstructions: !domainPointsToServer ? this.getDomainConnectionInstructions(business.domain) : null,
|
||||
};
|
||||
} else {
|
||||
// Verification failed
|
||||
return {
|
||||
message: BusinessMessage.DOMAIN_VERIFICATION_FAILED,
|
||||
domain: business.domain,
|
||||
isVerified: false,
|
||||
domainPointsToServer,
|
||||
serverConnectionStatus: domainPointsToServer
|
||||
? "Your domain is pointing to our servers, but ownership verification failed"
|
||||
: "Both ownership verification and server connection failed",
|
||||
setupInstructions: this.getDomainSetupInstructions(business.domain, business.domainVerificationToken || ""),
|
||||
connectionStatus: domainPointsToServer ? BusinessMessage.DOMAIN_CONNECTED : BusinessMessage.DOMAIN_NOT_CONNECTED,
|
||||
setupInstructions: this.getDomainSetupInstructions(business.domain, business.domainVerificationToken),
|
||||
};
|
||||
}
|
||||
} catch (error: unknown) {
|
||||
@@ -237,38 +137,11 @@ export class DomainVerificationService {
|
||||
domain: business.domain,
|
||||
isVerified: false,
|
||||
error: error instanceof Error ? error.message : String(error),
|
||||
setupInstructions: this.getDomainSetupInstructions(business.domain, business.domainVerificationToken || ""),
|
||||
setupInstructions: this.getDomainSetupInstructions(business.domain, business.domainVerificationToken),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
//************************************** */
|
||||
async getDomainVerificationStatus(businessId: string) {
|
||||
const business = await this.businessesService.getBusinessById(businessId);
|
||||
|
||||
if (!business.domain) {
|
||||
return {
|
||||
hasDomain: false,
|
||||
};
|
||||
}
|
||||
|
||||
// Check if domain points to our server (A or CNAME record)
|
||||
const domainPointsToServer = await this.checkDomainPointsToServer(business.domain);
|
||||
|
||||
return {
|
||||
hasDomain: true,
|
||||
domain: business.domain,
|
||||
isVerified: business.isDomainVerified,
|
||||
verifiedAt: business.domainVerifiedAt,
|
||||
domainPointsToServer,
|
||||
verificationStatus: business.isDomainVerified ? "Verified" : "Not Verified",
|
||||
connectionStatus: domainPointsToServer ? "Connected" : "Not Connected",
|
||||
fullSetupComplete: business.isDomainVerified && domainPointsToServer,
|
||||
connectionInstructions: !domainPointsToServer ? this.getDomainConnectionInstructions(business.domain) : null,
|
||||
setupInstructions: !business.isDomainVerified ? this.getDomainSetupInstructions(business.domain, business.domainVerificationToken || "") : null,
|
||||
};
|
||||
}
|
||||
|
||||
//*********************************** */
|
||||
async getDomainStatus(businessId: string) {
|
||||
const business = await this.businessesService.getBusinessById(businessId);
|
||||
@@ -276,7 +149,7 @@ export class DomainVerificationService {
|
||||
if (!business.domain) {
|
||||
return {
|
||||
hasDomain: false,
|
||||
message: "No domain set for this business",
|
||||
message: BusinessMessage.DOMAIN_NOT_FOUND,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -288,8 +161,8 @@ export class DomainVerificationService {
|
||||
isVerified: business.isDomainVerified,
|
||||
verifiedAt: business.domainVerifiedAt,
|
||||
domainPointsToServer,
|
||||
verificationStatus: business.isDomainVerified ? "Verified" : "Not Verified",
|
||||
connectionStatus: domainPointsToServer ? "Connected" : "Not Connected",
|
||||
verificationStatus: business.isDomainVerified ? BusinessMessage.DOMAIN_VERIFICATION_SUCCESS : BusinessMessage.DOMAIN_VERIFICATION_FAILED,
|
||||
connectionStatus: domainPointsToServer ? BusinessMessage.DOMAIN_CONNECTED : BusinessMessage.DOMAIN_NOT_CONNECTED,
|
||||
fullSetupComplete: business.isDomainVerified && domainPointsToServer,
|
||||
setupInstructions:
|
||||
!business.isDomainVerified || !domainPointsToServer
|
||||
@@ -298,60 +171,54 @@ export class DomainVerificationService {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random verification token
|
||||
*/
|
||||
//*********************************** */
|
||||
//private methods
|
||||
|
||||
private generateVerificationToken(): string {
|
||||
return `dzone-verify-${crypto.randomBytes(16).toString("hex")}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get domain connection instructions
|
||||
*/
|
||||
// Get domain connection instructions
|
||||
private getDomainConnectionInstructions(_domain: string) {
|
||||
// The domain parameter is used for contextual purposes in some implementations
|
||||
// but not directly in this template
|
||||
return {
|
||||
title: "Point your domain to our servers",
|
||||
description: "Choose ONE of these options to connect your domain:",
|
||||
title: BusinessMessage.DOMAIN_CONNECTION_TITLE,
|
||||
description: BusinessMessage.DOMAIN_CONNECTION_DESCRIPTION,
|
||||
options: [
|
||||
{
|
||||
title: "Option A: Using A Record (Direct IP)",
|
||||
title: BusinessMessage.DOMAIN_CONNECTION_OPTION_A_TITLE,
|
||||
steps: [
|
||||
"1. Add an A record in your DNS settings",
|
||||
"2. Set the host to @ or your subdomain (e.g., www)",
|
||||
"3. Set the value to our server IP: " + this.serverIP,
|
||||
"4. Set TTL to 3600 (1 hour) or the lowest available",
|
||||
BusinessMessage.DOMAIN_CONNECTION_OPTION_A_STEP1,
|
||||
BusinessMessage.DOMAIN_CONNECTION_OPTION_A_STEP2,
|
||||
BusinessMessage.DOMAIN_CONNECTION_OPTION_A_STEP3 + this.serverIP,
|
||||
BusinessMessage.DOMAIN_CONNECTION_OPTION_A_STEP4,
|
||||
],
|
||||
},
|
||||
{
|
||||
title: "Option B: Using CNAME Record (Recommended)",
|
||||
title: BusinessMessage.DOMAIN_CONNECTION_OPTION_B_TITLE,
|
||||
steps: [
|
||||
"1. Add a CNAME record in your DNS settings",
|
||||
"2. Set the host to @ or your subdomain (e.g., www)",
|
||||
"3. Set the value to: " + this.serverDomain,
|
||||
"4. Set TTL to 3600 (1 hour) or the lowest available",
|
||||
"Note: Some DNS providers don't allow CNAME for root domains (@)",
|
||||
BusinessMessage.DOMAIN_CONNECTION_OPTION_B_STEP1,
|
||||
BusinessMessage.DOMAIN_CONNECTION_OPTION_B_STEP2,
|
||||
BusinessMessage.DOMAIN_CONNECTION_OPTION_B_STEP3 + this.serverDomain,
|
||||
BusinessMessage.DOMAIN_CONNECTION_OPTION_B_STEP4,
|
||||
BusinessMessage.DOMAIN_CONNECTION_OPTION_B_NOTE,
|
||||
],
|
||||
},
|
||||
],
|
||||
troubleshooting: [
|
||||
"- Make sure you've added the records to the correct domain",
|
||||
"- Some DNS providers require the @ symbol for root domains",
|
||||
"- Check that you've copied the values exactly as shown",
|
||||
"- DNS changes can take time to propagate (typically 15 minutes to 48 hours)",
|
||||
BusinessMessage.DOMAIN_CONNECTION_TROUBLESHOOTING_1,
|
||||
BusinessMessage.DOMAIN_CONNECTION_TROUBLESHOOTING_2,
|
||||
BusinessMessage.DOMAIN_CONNECTION_TROUBLESHOOTING_3,
|
||||
BusinessMessage.DOMAIN_CONNECTION_TROUBLESHOOTING_4,
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get comprehensive domain setup instructions
|
||||
*/
|
||||
// Get comprehensive domain setup instructions
|
||||
private getDomainSetupInstructions(domain: string, token: string) {
|
||||
return {
|
||||
verificationInstructions: {
|
||||
title: "Step 1: Verify domain ownership",
|
||||
description: "Add this TXT record to prove you own the domain:",
|
||||
title: BusinessMessage.DOMAIN_SETUP_VERIFICATION_TITLE,
|
||||
description: BusinessMessage.DOMAIN_SETUP_VERIFICATION_DESC,
|
||||
host: "@", // Root domain
|
||||
type: "TXT", // Record type
|
||||
value: token, // Token value
|
||||
@@ -360,20 +227,18 @@ export class DomainVerificationService {
|
||||
connectionInstructions: this.getDomainConnectionInstructions(domain),
|
||||
general: {
|
||||
verificationEndpoint: `/business/domain/verify/check-dns`,
|
||||
propagationNote: "DNS changes can take 15 minutes to 48 hours to propagate worldwide",
|
||||
propagationNote: BusinessMessage.DOMAIN_SETUP_PROPAGATION_NOTE,
|
||||
troubleshooting: [
|
||||
"- Make sure you've added the records to the correct domain",
|
||||
"- Some DNS providers require the @ symbol for root domains",
|
||||
"- Check that you've copied the values exactly as shown",
|
||||
"- Wait at least 15 minutes before checking verification status",
|
||||
BusinessMessage.DOMAIN_SETUP_TROUBLESHOOTING_1,
|
||||
BusinessMessage.DOMAIN_SETUP_TROUBLESHOOTING_2,
|
||||
BusinessMessage.DOMAIN_SETUP_TROUBLESHOOTING_3,
|
||||
BusinessMessage.DOMAIN_SETUP_TROUBLESHOOTING_4,
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify domain using DNS TXT record
|
||||
*/
|
||||
// Verify domain using DNS TXT record
|
||||
private async checkDnsTxtRecord(domain: string, token: string): Promise<boolean> {
|
||||
try {
|
||||
this.logger.log(`Checking TXT records for domain: ${domain}`);
|
||||
@@ -392,9 +257,7 @@ export class DomainVerificationService {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if domain points to our server via A or CNAME record
|
||||
*/
|
||||
// Check if domain points to our server via A or CNAME record
|
||||
private async checkDomainPointsToServer(domain: string): Promise<boolean> {
|
||||
try {
|
||||
// Try CNAME first
|
||||
|
||||
Reference in New Issue
Block a user