Website-Analyse: AVV als Seite, www/Apex-Domains, Abo-Check unabhängig vom Schalter, Dev-Hinweis
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7ead59ff73
commit
714687fe3b
10 files changed
+267
-20
No files matched your search
+8
-9
@@ -169,15 +169,14 @@ const server = app.listen(config.port, '0.0.0.0', () => {
|
||||
.catch((err) => console.warn('[funktionen] Freischalten fehlgeschlagen:', err.message))
|
||||
setInterval(activateFeatures, 5 * 60 * 1000).unref()
|
||||
|
||||
// Website-Analyse: aktive Analysen ohne laufendes Wartungs-Abo beenden (taeglich, 2 Minuten nach Start beginnend)
|
||||
if (config.analyse.enabled) {
|
||||
const analyseAboCheck = () =>
|
||||
runAboCheck({ now: new Date() })
|
||||
.then((r) => r.deactivated.length && console.log(`[analyse] ${r.deactivated.length} Analyse(n) ohne Abo beendet`))
|
||||
.catch((err) => console.warn('[analyse] Abo-Prüfung fehlgeschlagen:', err.message))
|
||||
setTimeout(analyseAboCheck, 2 * 60 * 1000).unref()
|
||||
setInterval(analyseAboCheck, 24 * 60 * 60 * 1000).unref()
|
||||
}
|
||||
// Website-Analyse: aktive Analysen ohne laufendes Wartungs-Abo beenden (taeglich, 2 Minuten nach Start beginnend).
|
||||
// Laeuft unabhaengig vom Schalter ANALYSE_ENABLED: er liest nur Analyse-Dokumente und ist ohne solche wirkungslos.
|
||||
const analyseAboCheck = () =>
|
||||
runAboCheck({ now: new Date() })
|
||||
.then((r) => r.deactivated.length && console.log(`[analyse] ${r.deactivated.length} Analyse(n) ohne Abo beendet`))
|
||||
.catch((err) => console.warn('[analyse] Abo-Prüfung fehlgeschlagen:', err.message))
|
||||
setTimeout(analyseAboCheck, 2 * 60 * 1000).unref()
|
||||
setInterval(analyseAboCheck, 24 * 60 * 60 * 1000).unref()
|
||||
|
||||
// Neue Gitea-Repos erkennen, Zuordnungs-Mail senden, Erinnerungen/Wiederholungen (alle 10 Minuten)
|
||||
const repoAssign = () =>
|
||||
|
||||
@@ -18,7 +18,8 @@ import {
|
||||
ELIGIBILITY_MESSAGES,
|
||||
activateAnalyse,
|
||||
analyseDeps,
|
||||
analyseDomains,
|
||||
analyseHosts,
|
||||
isDevPreview,
|
||||
analyseEligibility,
|
||||
deactivateAnalyse,
|
||||
} from '../services/analyse.js'
|
||||
@@ -41,8 +42,14 @@ const ANALYSE_ERROR = 'Die Website-Analyse konnte gerade nicht geändert werden.
|
||||
async function analyseView(customerId, projectId) {
|
||||
if (!config.analyse.enabled) return { comingSoon: true }
|
||||
const [doc, eligibility] = await Promise.all([getFeatureDoc(customerId, projectId, 'analyse'), analyseEligibility(customerId, projectId)])
|
||||
let devMode = false
|
||||
if (doc?.state === 'active') {
|
||||
const project = eligibility.project || (await getDocument(config.collections.websiteProjects, projectId).catch(() => null))
|
||||
devMode = isDevPreview(project)
|
||||
}
|
||||
return {
|
||||
state: doc?.state || 'off',
|
||||
devMode,
|
||||
accentColor: doc?.accentColor || '#111111',
|
||||
eligible: eligibility.ok,
|
||||
reason: eligibility.reason || null,
|
||||
@@ -233,7 +240,7 @@ router.post('/analyse/heatmap-link', analyseGuard, async (req, res) => {
|
||||
if (!doc?.siteKey || doc.state !== 'active') {
|
||||
return res.status(409).json({ error: 'Die Website-Analyse ist für dieses Projekt nicht aktiv.' })
|
||||
}
|
||||
const domains = analyseDomains(project)
|
||||
const domains = analyseHosts(project)
|
||||
if (!domains.length) return res.status(409).json({ error: 'Keine gültige Domain' })
|
||||
const host = project.liveDomain ? domains[domains.length - 1] : domains[0]
|
||||
const token = analyseDeps.client.heatToken({ siteKey: doc.siteKey, path, vp })
|
||||
|
||||
@@ -58,8 +58,8 @@ export async function analyseEligibility(customerId, projectId) {
|
||||
|
||||
const HOSTNAME_RE = /^(?=.{4,253}$)(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z][a-z0-9-]{0,61}[a-z0-9]$/
|
||||
|
||||
/** `<subdomain>.project.webklar.com` plus Live-Domain (klein, ohne Schema/Pfad), ohne Doppelte; ungueltige Hosts werden uebersprungen. */
|
||||
export function analyseDomains(project) {
|
||||
/** Gespeicherte Hosts: `<subdomain>.project.webklar.com` plus Live-Domain (klein, ohne Schema/Pfad), ohne Doppelte; ungueltige werden uebersprungen. */
|
||||
export function analyseHosts(project) {
|
||||
const domains = []
|
||||
if (project.subdomain) domains.push(`${String(project.subdomain).trim().toLowerCase()}.project.webklar.com`)
|
||||
const live = String(project.liveDomain || '')
|
||||
@@ -71,6 +71,17 @@ export function analyseDomains(project) {
|
||||
return [...new Set(domains)].filter((d) => HOSTNAME_RE.test(d))
|
||||
}
|
||||
|
||||
/** Erlaubte Origin-Domains des Messdienstes: gespeicherte Hosts plus www-/Apex-Gegenstueck der Live-Domain (Besucher kommen mit und ohne www), max. 5. */
|
||||
export function analyseDomains(project) {
|
||||
const hosts = analyseHosts(project)
|
||||
const live = project.liveDomain ? hosts[hosts.length - 1] : ''
|
||||
const extra = live && hosts.length > 1 ? (live.startsWith('www.') ? live.slice(4) : `www.${live}`) : ''
|
||||
return [...new Set([...hosts, extra].filter(Boolean))].filter((d) => HOSTNAME_RE.test(d)).slice(0, 5)
|
||||
}
|
||||
|
||||
/** Dev-Server-Projekte (previewDetected 'dev…') bekommen kein Messskript: der Runner injiziert nur in veroeffentlichte Ordner. */
|
||||
export const isDevPreview = (project) => String(project?.previewDetected || '').startsWith('dev')
|
||||
|
||||
async function customerOf(customerId) {
|
||||
try {
|
||||
return await getDocument(config.collections.customers, customerId)
|
||||
@@ -111,7 +122,7 @@ async function mailSafe(customerId, template, project) {
|
||||
|
||||
function privacyTicket(customerId, project, siteKey) {
|
||||
const name = project.projectName || project.subdomain || ''
|
||||
const domains = analyseDomains(project)
|
||||
const domains = analyseHosts(project)
|
||||
return analyseDeps.ticket({
|
||||
customerId,
|
||||
project,
|
||||
|
||||
Reference in new issue
Block a user