Generate random platform subdomains for apps without custom domains.

Assign unpredictable subdomains on create when no custom domain is set, and update deploy UI CNAME hints to reference the app Platform Domain after creation.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
keyhan
2026-05-26 19:55:44 +03:30
parent d7594df9a0
commit 20c4184cde
2 changed files with 35 additions and 17 deletions
@@ -30,6 +30,33 @@ export class ApplicationsService {
private configService: ConfigService,
) {}
private toDnsLabel(value: string): string {
return (value || '')
.toLowerCase()
.replace(/[^a-z0-9-]/g, '-')
.replace(/-+/g, '-')
.replace(/^-|-$/g, '')
.slice(0, 63);
}
private async generateRandomSubdomain(baseLabel: string): Promise<string> {
const base = this.toDnsLabel(baseLabel) || 'app';
const suffixLenBytes = 5; // 10 hex chars
const suffixLen = suffixLenBytes * 2;
for (let attempt = 0; attempt < 10; attempt++) {
const suffix = crypto.randomBytes(suffixLenBytes).toString('hex'); // [0-9a-f]
const maxBaseLen = 63 - 1 - suffixLen; // base + '-' + suffix
const truncatedBase = base.slice(0, Math.max(1, maxBaseLen)).replace(/-+$/g, '');
const candidate = `${truncatedBase}-${suffix}`;
const exists = await this.appsRepository.findOne({ where: { subdomain: candidate } });
if (!exists) return candidate;
}
throw new BadRequestException('Failed to generate a unique subdomain. Please try again.');
}
async create(userId: string, dto: CreateApplicationDto, userRole?: string): Promise<Application> {
dto = normalizeCreateApplicationDto(dto);
const productType = dto.productType ?? ProductType.APPLICATION;
@@ -83,7 +110,10 @@ export class ApplicationsService {
? 80
: 3000;
const subdomain = `${dto.name}-${userId.split('-')[0]}`;
const baseLabel = dto.name;
const subdomain = customDomain
? `${this.toDnsLabel(baseLabel)}-${this.toDnsLabel(userId.split('-')[0])}`
: await this.generateRandomSubdomain(baseLabel);
const platformDomain = this.configService.get('platform.domain') || 'apps.cloudhost.ir';
const app = this.appsRepository.create({