From 531fc8e7411649a39c955be7de4ec29d1b754d22 Mon Sep 17 00:00:00 2001 From: Taarly Date: Wed, 17 Dec 2025 10:33:06 +0100 Subject: [PATCH] test if the csv also gets correctly tested now --- public/views/createuser.php | 184 +++++++++++++++++++++++++++++++++++- 1 file changed, 181 insertions(+), 3 deletions(-) diff --git a/public/views/createuser.php b/public/views/createuser.php index 17ff793..b870686 100644 --- a/public/views/createuser.php +++ b/public/views/createuser.php @@ -166,6 +166,14 @@ declare(strict_types=1); + + +
@@ -278,14 +286,184 @@ declare(strict_types=1); }); } - // Optional: Intercept submit to ensure csvcontent is present when no file is uploaded. + // CSV utilities and validation for passwords in preview + function parseCsvText(text, delimiter) { + const lines = text.split(/\r?\n/).map(l => l.trim()).filter(l => l !== ''); + if (lines.length === 0) return { headers: [], rows: [] }; + const headers = lines[0].split(delimiter).map(h => h.trim().replace(/^"|"$/g, '')); + const rows = lines.slice(1).map(l => l.split(delimiter).map(c => c.trim().replace(/^"|"$/g, ''))); + return { headers, rows }; + } + + function validatePasswordJS(password, sam) { + const errors = []; + if (!password || password.length < 7) { + errors.push('Passwort muss mindestens 7 Zeichen lang sein.'); + } + let categories = 0; + if (/[A-Z]/.test(password)) categories++; + if (/[a-z]/.test(password)) categories++; + if (/\d/.test(password)) categories++; + if (/[^A-Za-z0-9]/.test(password)) categories++; + if (categories < 3) { + errors.push('Passwort muss Zeichen aus mindestens 3 von 4 Kategorien enthalten.'); + } + if (sam) { + const pwLower = password.toLowerCase(); + const samLower = sam.toLowerCase(); + if (pwLower.includes(samLower)) { + errors.push('Passwort darf den Benutzernamen nicht enthalten.'); + } else { + const minLen = 4; + if (samLower.length >= minLen) { + outer: for (let len = minLen; len <= samLower.length; len++) { + for (let s = 0; s <= samLower.length - len; s++) { + const sub = samLower.substr(s, len); + if (pwLower.includes(sub)) { errors.push('Passwort darf keine größeren Teile des Benutzernamens enthalten.'); break outer; } + } + } + } + } + } + return errors; + } + + function renderCsvPreview(text, delimiter) { + const parsed = parseCsvText(text, delimiter); + const headers = parsed.headers; + const rows = parsed.rows; + const previewArea = document.getElementById('csvPreviewArea'); + const previewInfo = document.getElementById('csvPreviewInfo'); + const table = document.getElementById('csvPreviewTable'); + table.innerHTML = ''; + if (headers.length === 0) { + previewArea.style.display = 'none'; + return { invalidCount: 0 }; + } + + // build header + const thead = document.createElement('thead'); + const trh = document.createElement('tr'); + headers.forEach(h => { const th = document.createElement('th'); th.textContent = h; trh.appendChild(th); }); + thead.appendChild(trh); + table.appendChild(thead); + + // find indexes + const pwdIdx = headers.findIndex(h => /pass(word)?/i.test(h)); + const samIdx = headers.findIndex(h => /(sam(accountname)?)|samaccountname/i.test(h)); + + const tbody = document.createElement('tbody'); + let invalidCount = 0; + rows.forEach((rowArr, rowIndex) => { + const tr = document.createElement('tr'); + rowArr.forEach((cell, colIndex) => { + const td = document.createElement('td'); + const input = document.createElement('input'); + input.type = 'text'; + input.value = cell; + input.className = 'form-control form-control-sm'; + input.addEventListener('input', function () { + // re-validate this row when edited + const currentPwd = (pwdIdx >= 0) ? tr.querySelectorAll('input')[pwdIdx].value : ''; + const currentSam = (samIdx >= 0) ? tr.querySelectorAll('input')[samIdx].value : ''; + const errs = validatePasswordJS(currentPwd, currentSam); + if (errs.length > 0) { + tr.classList.add('table-danger'); + } else { + tr.classList.remove('table-danger'); + } + }); + td.appendChild(input); + tr.appendChild(td); + }); + + // validate password for this row if applicable + if (pwdIdx >= 0) { + const pwd = rowArr[pwdIdx] || ''; + const sam = (samIdx >= 0) ? (rowArr[samIdx] || '') : ''; + const errs = validatePasswordJS(pwd, sam); + if (errs.length > 0) { + tr.classList.add('table-danger'); + invalidCount++; + } + } + + tbody.appendChild(tr); + }); + table.appendChild(tbody); + previewArea.style.display = 'block'; + previewInfo.textContent = (invalidCount > 0) + ? `${invalidCount} Zeile(n) haben ungültige Passwörter. Bitte korrigieren Sie diese in der Tabelle bevor Sie die CSV verarbeiten.` + : 'CSV-Vorschau geladen. Alle Passwörter entsprechen den Anforderungen.'; + return { invalidCount }; + } + + if (loadBtn) { + loadBtn.addEventListener('click', function () { + const file = fileInput.files && fileInput.files[0]; + const delim = document.getElementById('csvdelimiter').value || ','; + if (file) { + const reader = new FileReader(); + reader.onload = function (e) { + preview.value = e.target.result || ''; + renderCsvPreview(preview.value, delim); + }; + reader.readAsText(file, 'utf-8'); + return; + } + if (preview.value.trim() === '') { + alert('Bitte wählen Sie zuerst eine CSV-Datei aus oder fügen Sie CSV-Text direkt in das Feld ein.'); + return; + } + renderCsvPreview(preview.value, delim); + }); + } + + if (clearBtn) { + clearBtn.addEventListener('click', function () { + preview.value = ''; + fileInput.value = ''; + document.getElementById('csvPreviewArea').style.display = 'none'; + }); + } + + if (fileInput) { + fileInput.addEventListener('change', function () { + // auto-load content into preview textarea (but do not auto-validate until user clicks 'In Vorschau laden') + const file = fileInput.files && fileInput.files[0]; + if (file) { + const reader = new FileReader(); + reader.onload = function (e) { + preview.value = e.target.result || ''; + }; + reader.readAsText(file, 'utf-8'); + } + }); + } + + // Intercept submit: require preview validation or loaded file to have been checked form.addEventListener('submit', function (e) { - // If no file was sent, ensure csvcontent isn't empty. + const delim = document.getElementById('csvdelimiter').value || ','; const file = fileInput.files && fileInput.files[0]; - if (!file && preview.value.trim() === '') { + // If no preview is present, require user to load preview first to ensure validation + if (preview.value.trim() === '') { + if (file) { + e.preventDefault(); + alert('Bitte klicken Sie auf "In Vorschau laden" bevor Sie die CSV verarbeiten, damit Passwörter validiert werden.'); + return false; + } e.preventDefault(); alert('Die CSV-Vorschau ist leer. Bitte wählen Sie eine Datei oder fügen Sie CSV-Inhalt ein.'); + return false; } + + const res = renderCsvPreview(preview.value, delim); + if (res.invalidCount > 0) { + e.preventDefault(); + alert('Import abgebrochen: Es gibt ungültige Passwörter in der CSV-Vorschau. Bitte korrigieren Sie diese zuerst.'); + return false; + } + return true; }); })();