Add page-view analytics, product counters, SSL expiry, and business renewal.

Auto-count storefront page views with 6-month event retention and lifetime counters, track product visit/cart/sale stats, persist SSL cert expiry with daily probes, and support owner titles plus annual contract renewal.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-08-26 10:13:06 +03:30
co-authored by Cursor
parent 6cd0b009ef
commit 92601ae729
39 changed files with 1013 additions and 198 deletions
+69 -21
View File
@@ -12,7 +12,11 @@ import { Prisma } from '@prisma/client';
import { ArvanDnsService } from '../arvan-dns/arvan-dns.service';
import { AuthUser } from '../auth/auth.types';
import { PermissionsService } from '../auth/permissions.service';
import { probeTlsHost } from '../common/tls-probe';
import {
earliestTlsExpiry,
probeTlsHost,
probeTlsHostDetailed,
} from '../common/tls-probe';
import { PrismaService } from '../prisma/prisma.service';
import { WebsiteDeployAgentService } from '../website-deploy/website-deploy-agent.service';
import { DisableDomainDto } from './dto/disable-domain.dto';
@@ -26,6 +30,7 @@ type DomainRow = {
businessId: bigint;
businessName: string;
sslEnabled: boolean;
sslExpiresAt: Date | null;
isActive: boolean;
expiresAt: Date | null;
createdAt: Date;
@@ -71,6 +76,7 @@ export class DomainAdminService {
d.business_id AS "businessId",
b.name AS "businessName",
d.ssl_enabled AS "sslEnabled",
d.ssl_expires_at AS "sslExpiresAt",
d.is_active AS "isActive",
d.expires_at AS "expiresAt",
d.created_at AS "createdAt",
@@ -90,7 +96,19 @@ export class DomainAdminService {
`),
]);
return { items: rows, total: totalRow[0]?.total ?? 0, page, pageSize };
const now = Date.now();
const items = rows.map((row) => {
const certStillValid =
!row.sslExpiresAt || row.sslExpiresAt.getTime() > now;
return {
...row,
// List badge: issued/probed OK and cert not past notAfter.
sslEnabled: row.sslEnabled && certStillValid,
sslExpiresAt: row.sslExpiresAt,
};
});
return { items, total: totalRow[0]?.total ?? 0, page, pageSize };
}
async syncSsl(actor: AuthUser) {
@@ -185,26 +203,28 @@ export class DomainAdminService {
const targets: Array<{ id: bigint; host: string; deploySlug: string | null }> = [];
for (const domain of candidates) {
const apexOk = await probeTlsHost(domain.host);
const apexProbe = await probeTlsHostDetailed(domain.host);
const wwwHost = domain.host.startsWith('www.')
? domain.host
: `www.${domain.host}`;
const wwwOk = await probeTlsHost(wwwHost);
const ok = apexOk && wwwOk;
const wwwProbe = await probeTlsHostDetailed(wwwHost);
const ok = apexProbe.ok && wwwProbe.ok;
if (ok) {
if (!domain.sslEnabled) {
await this.prisma.domain.update({
where: { id: domain.id },
data: { sslEnabled: true },
});
}
const sslExpiresAt = earliestTlsExpiry(apexProbe, wwwProbe);
await this.prisma.domain.update({
where: { id: domain.id },
data: {
sslEnabled: true,
...(sslExpiresAt ? { sslExpiresAt } : {}),
},
});
continue;
}
if (domain.sslEnabled) {
await this.prisma.domain.update({
where: { id: domain.id },
data: { sslEnabled: false },
data: { sslEnabled: false, sslExpiresAt: null },
});
}
targets.push(domain);
@@ -228,14 +248,21 @@ export class DomainAdminService {
host: domain.host,
slug: domain.deploySlug,
});
const ok = await probeTlsHost(domain.host);
const apexProbe = await probeTlsHostDetailed(domain.host);
const wwwHost = domain.host.startsWith('www.')
? domain.host
: `www.${domain.host}`;
const wwwOk = ok && (await probeTlsHost(wwwHost));
const wwwProbe = await probeTlsHostDetailed(wwwHost);
const wwwOk = apexProbe.ok && wwwProbe.ok;
const sslExpiresAt = wwwOk
? earliestTlsExpiry(apexProbe, wwwProbe)
: null;
await this.prisma.domain.update({
where: { id: domain.id },
data: { sslEnabled: wwwOk },
data: {
sslEnabled: wwwOk,
sslExpiresAt,
},
});
if (wwwOk) {
issued.push(domain.host);
@@ -297,10 +324,12 @@ export class DomainAdminService {
customer: { host: customerHost, status: 'ok' },
};
let apexOk = await probeTlsHost(apex);
let wwwOk = await probeTlsHost(wwwHost);
let apexProbe = await probeTlsHostDetailed(apex);
let wwwProbe = await probeTlsHostDetailed(wwwHost);
let businessOk = await probeTlsHost(businessHost);
let customerOk = await probeTlsHost(customerHost);
let apexOk = apexProbe.ok;
let wwwOk = wwwProbe.ok;
const storefrontNeedsIssue = !apexOk || !wwwOk;
@@ -325,8 +354,10 @@ export class DomainAdminService {
} else {
try {
await this.websiteDeployAgent.issueSsl({ host: apex, slug });
apexOk = await probeTlsHost(apex);
wwwOk = await probeTlsHost(wwwHost);
apexProbe = await probeTlsHostDetailed(apex);
wwwProbe = await probeTlsHostDetailed(wwwHost);
apexOk = apexProbe.ok;
wwwOk = wwwProbe.ok;
hosts.apex = apexOk
? {
host: apex,
@@ -416,9 +447,22 @@ export class DomainAdminService {
}
const storefrontOk = apexOk && wwwOk;
// Re-probe apex/www once more when already-ok so we persist current cert expiry.
if (storefrontOk && (!apexProbe.expiresAt || !wwwProbe.expiresAt)) {
apexProbe = await probeTlsHostDetailed(apex);
wwwProbe = await probeTlsHostDetailed(wwwHost);
apexOk = apexProbe.ok;
wwwOk = wwwProbe.ok;
}
const sslExpiresAt =
apexOk && wwwOk ? earliestTlsExpiry(apexProbe, wwwProbe) : null;
const updated = await this.prisma.domain.update({
where: { id: domainId },
data: { sslEnabled: storefrontOk },
data: {
sslEnabled: storefrontOk && apexOk && wwwOk,
sslExpiresAt: storefrontOk && apexOk && wwwOk ? sslExpiresAt : null,
},
});
const parts = [hosts.apex, hosts.www, hosts.business, hosts.customer];
@@ -434,6 +478,7 @@ export class DomainAdminService {
status: failed.length === 0 ? ('ok' as const) : ('partial' as const),
host: apex,
sslEnabled: updated.sslEnabled,
sslExpiresAt: updated.sslExpiresAt?.toISOString() ?? null,
hosts,
issued: issued.map((p) => p.host),
failed: failed.map((p) => ({ host: p.host, error: p.detail || 'failed' })),
@@ -579,7 +624,10 @@ export class DomainAdminService {
return this.prisma.domain.update({
where: { id: domainId },
data: { sslEnabled: dto.sslEnabled },
data: {
sslEnabled: dto.sslEnabled,
...(dto.sslEnabled ? {} : { sslExpiresAt: null }),
},
});
}