feat: HTTPS-TLS-Sync nach Deploy, Projekte ohne Subdomain, portalPassword-Feld
- previewDeploy.syncPreviewTls(): schreibt Traefik-Router (Host-Regeln) fuer alle Preview-Subdomains nach preview-hosts.yml, damit Let's Encrypt Zertifikate ausstellt. Laeuft nach jedem Deploy und beim Serverstart (ersetzt das nie aufgerufene bash-Script sync-preview-tls.sh). - createProjectFromTemplate: Subdomain optional. Ohne Subdomain wird nur das Gitea-Repo angelegt (projectType 'repo', Status 'created'), kein Deploy. - customerAdmin: Portal-Passwort liegt jetzt im Feld customers.portalPassword statt als __portalPassword__-Prefix in den Notizen; Legacy-Notizen werden beim naechsten Update bereinigt. CRM-Stufe (lead/customer) wird beim Setzen des Portal-Passworts nicht mehr auf 'active' ueberschrieben. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -14,20 +14,16 @@ import {
|
||||
Query,
|
||||
} from './appwriteAdmin.js'
|
||||
|
||||
const PORTAL_PASSWORD_PREFIX = '__portalPassword__:'
|
||||
|
||||
function readPortalPassword(customer) {
|
||||
if (customer?.portalPassword) return customer.portalPassword
|
||||
// Fallback: Altbestand, bei dem das Passwort noch in den Notizen lag
|
||||
const notes = customer?.notes || ''
|
||||
const match = notes.match(/^__portalPassword__:([^\n]+)/)
|
||||
return match ? match[1] : ''
|
||||
}
|
||||
|
||||
function notesWithPortalPassword(existingNotes, password) {
|
||||
const stripped = (existingNotes || '').replace(/^__portalPassword__:[^\n]*\n?/, '').trim()
|
||||
if (!password) return stripped || ''
|
||||
const line = `${PORTAL_PASSWORD_PREFIX}${password}`
|
||||
return stripped ? `${line}\n${stripped}` : line
|
||||
function notesWithoutPortalPassword(notes) {
|
||||
return (notes || '').replace(/^__portalPassword__:[^\n]*\n?/, '').trim()
|
||||
}
|
||||
|
||||
function sanitizeCustomer(customer, { portalPassword } = {}) {
|
||||
@@ -115,7 +111,7 @@ export async function createCustomerWithPortalAccess(payload) {
|
||||
location: location.trim(),
|
||||
email: email.trim(),
|
||||
phone: phone.trim(),
|
||||
notes: notesWithPortalPassword('', password),
|
||||
portalPassword: password,
|
||||
portalAccessEnabled: true,
|
||||
appwriteUserId: appwriteUser.$id,
|
||||
customerStatus: 'active',
|
||||
@@ -206,6 +202,9 @@ export async function updateCustomerWithPortalAccess(customerId, payload) {
|
||||
const now = new Date().toISOString()
|
||||
const nextPortalPassword =
|
||||
normalizedPassword || readPortalPassword(customer) || undefined
|
||||
// Legacy-Prefix aus den Notizen entfernen, Passwort liegt jetzt im eigenen Feld
|
||||
const cleanedNotes = notesWithoutPortalPassword(customer.notes)
|
||||
const notesChanged = cleanedNotes !== (customer.notes || '')
|
||||
|
||||
const updated = await updateDocument(config.collections.customers, customerId, {
|
||||
...(code !== undefined ? { code: String(code).trim() } : {}),
|
||||
@@ -213,10 +212,16 @@ export async function updateCustomerWithPortalAccess(customerId, payload) {
|
||||
...(location !== undefined ? { location: String(location).trim() } : {}),
|
||||
email: nextEmail,
|
||||
...(phone !== undefined ? { phone: String(phone).trim() } : {}),
|
||||
...(nextPortalPassword
|
||||
? { notes: notesWithPortalPassword(customer.notes, nextPortalPassword) }
|
||||
...(nextPortalPassword ? { portalPassword: nextPortalPassword } : {}),
|
||||
...(notesChanged ? { notes: cleanedNotes } : {}),
|
||||
// CRM-Stufe (lead/customer/lost) nicht ueberschreiben - nur setzen, wenn leer
|
||||
...(appwriteUserId
|
||||
? {
|
||||
appwriteUserId,
|
||||
portalAccessEnabled: true,
|
||||
...(customer.customerStatus ? {} : { customerStatus: 'active' }),
|
||||
}
|
||||
: {}),
|
||||
...(appwriteUserId ? { appwriteUserId, portalAccessEnabled: true, customerStatus: 'active' } : {}),
|
||||
updatedAt: now,
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user