Login Block

Anwendungen für Webseiten. Künstliche Intelligenz verwenden.
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 9127
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Login Block

Beitrag von Tommy Herrmann »

Ich frage jetzt mal Tante Chat ...
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 9127
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Login Block

Beitrag von Tommy Herrmann »

ChatGPT hat es in 7 Sekunden erkannt - warte ...

Bei mir habe ich es schon online
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 9127
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Login Block

Beitrag von Tommy Herrmann »

Hier der neue Code für den HTML-Block der Passwort-Änderung. Das Passwort wird am Auge erst sichtbar, wenn es tatsächlich neu eingetragen wurde.

Code: Alles auswählen

<section data-bs-version="5.1" class="vn-changepass" group="Content" plugins="vn-login" data-endpoint="assets/vn-login/login.php" data-login-url="{{loginUrl}}" style="
            --vl-bg:       {{bgColor}};
            --vl-card:     {{cardColor}};
            --vl-accent:   {{accentColor}};
            --vl-text:     {{textColor}};
            --vl-sub:      {{subtextColor}};
            --vl-input-bg: {{inputBgColor}};
            --vl-border:   {{borderColor}};
            --vl-pt:       {{paddingTop}}rem;
            --vl-pb:       {{paddingBottom}}rem;
            --vl-radius:   {{cardRadius}}px;
        ">
    <mbr-parameters>
        <header>URLs</header>
        <input type="text" title="Login-Seite (URL)" name="loginUrl" value="Login-Members.html">
        <header>Size</header>
        <input type="checkbox" title="Full Width" name="fullWidth">
        <input type="range" inline title="Top" name="paddingTop" min="0" max="12" step="1" value="4">
        <input type="range" inline title="Bottom" name="paddingBottom" min="0" max="12" step="1" value="2">

        <header>Farben</header>
        <input type="color" title="Hintergrund" value="#000000" name="bgColor" selected>
        <input type="color" title="Karte" value="#1a1a1a" name="cardColor" selected>
        <input type="color" title="Akzent" value="#1d9e75" name="accentColor" selected>
        <input type="color" title="Text" value="#ffffff" name="textColor" selected>
        <input type="color" title="Subtext" value="#888888" name="subtextColor" selected>
        <input type="color" title="Input Hintergrund" value="#111111" name="inputBgColor" selected>
        <input type="color" title="Rahmen" value="#2a2a2a" name="borderColor" selected>

        <header>Design</header>
        <input type="range" inline title="Eckenrundung (px)" name="cardRadius" min="0" max="24" step="2" value="16">
    </mbr-parameters>

    <div mbr-class="{'container': !fullWidth, 'container-fluid': fullWidth}">
        <div class="vl-wrap">

            <div class="vl-header">
                <div class="vl-logo">🔑</div>
                <h2 class="vl-title mbr-fonts-style" mbr-text data-app-selector=".vl-title" mbr-theme-style="display-2">Passwort ändern</h2>
                <p class="vl-subtitle mbr-fonts-style" mbr-text data-app-selector=".vl-subtitle" mbr-theme-style="display-7">Gib dein aktuelles und neues Passwort ein.</p>
            </div>

            <div class="vl-form" autocomplete="off">
                <!--
                    Verstecktes Username-Feld nur für interne Anzeige/Zuordnung.
                    Wichtig: kein autocomplete="username", damit Browser hier nicht automatisch Passwortdaten koppelt.
                -->
                <input type="text" id="vcp-username" name="vcp-user-display" autocomplete="off" style="position:absolute;left:-9999px;top:-9999px;width:1px;height:1px;opacity:0;" tabindex="-1" readonly>

                <div class="vcp-user-info" id="vcp-user-info" style="display:none;">
                    <span class="vcp-user-label">Eingeloggt als:</span>
                    <span class="vcp-user-name" id="vcp-user-name">–</span>
                </div>

                <div class="vl-field">
                    <label class="vl-label" for="vcp-old">Aktuelles Passwort</label>
                    <div class="vl-pw-wrap">
                        <input type="password" id="vcp-old" class="vl-input" placeholder="••••••••" autocomplete="off" readonly>
                        <button type="button" class="vl-pw-toggle" onclick="vcpToggle('vcp-old')">👁</button>
                    </div>
                </div>

                <div class="vl-field">
                    <label class="vl-label" for="vcp-new">Neues Passwort</label>
                    <div class="vl-pw-wrap">
                        <input type="password" id="vcp-new" class="vl-input" placeholder="min. 6 Zeichen" autocomplete="new-password">
                        <button type="button" class="vl-pw-toggle" onclick="vcpToggle('vcp-new')">👁</button>
                    </div>
                </div>

                <div class="vl-field">
                    <label class="vl-label" for="vcp-new2">Neues Passwort bestätigen</label>
                    <input type="password" id="vcp-new2" class="vl-input" placeholder="Passwort wiederholen" autocomplete="new-password">
                </div>

                <div class="vl-error" id="vcp-error" style="display:none"></div>
                <div class="vcp-success" id="vcp-success" style="display:none"></div>

                <button type="button" class="vl-btn" id="vcp-btn" onclick="vcpSave()">
                    <span id="vcp-btn-text">Passwort speichern</span>
                </button>
            </div>

        </div>
    </div>

    <script>
    (function () {
        var sec = document.querySelector('section.vn-changepass');
        if (!sec) return;

        var endpoint = (sec.dataset.endpoint || 'assets/vn-login/login.php').trim();

        /*
         * Merker: Beim aktuellen Passwort darf das Auge nur dann anzeigen,
         * wenn der Benutzer wirklich selbst etwas eingetippt hat.
         * Browser-Autofill soll nicht sichtbar gemacht werden.
         */
        var oldPasswordTouched = false;

        function clearOldPasswordField() {
            var old = document.getElementById('vcp-old');
            if (!old) return;

            old.value = '';
            old.type = 'password';
            oldPasswordTouched = false;
        }

        window.vcpToggle = function(id) {
            var el = document.getElementById(id);
            if (!el) return;

            /*
             * Sonderregel für "Aktuelles Passwort":
             * Wenn der Browser heimlich etwas eingefüllt hat, aber der Benutzer
             * noch nicht selbst getippt hat, wird nichts sichtbar gemacht.
             */
            if (id === 'vcp-old' && !oldPasswordTouched) {
                el.type = 'password';
                el.value = '';
                return;
            }

            if (!el.value) {
                el.type = 'password';
                return;
            }

            el.type = el.type === 'password' ? 'text' : 'password';
        };

        function showError(msg) {
            var e = document.getElementById('vcp-error');
            var s = document.getElementById('vcp-success');

            if (s) s.style.display = 'none';
            if (e) {
                e.textContent = msg;
                e.style.display = 'block';
            }
        }

        function showSuccess(msg) {
            var e = document.getElementById('vcp-error');
            var s = document.getElementById('vcp-success');

            if (e) e.style.display = 'none';

            if (s) {
                s.textContent = msg;
                s.style.display = 'block';
            }

            ['vcp-old', 'vcp-new', 'vcp-new2'].forEach(function(id) {
                var el = document.getElementById(id);
                if (el) {
                    el.value = '';
                    el.type = 'password';
                }
            });

            oldPasswordTouched = false;
        }

        function setLoading(on) {
            var btn = document.getElementById('vcp-btn');
            var txt = document.getElementById('vcp-btn-text');

            if (btn) btn.disabled = on;
            if (txt) txt.textContent = on ? '⟳ Bitte warten…' : 'Passwort speichern';
        }

        /*
         * Aktuelles Passwortfeld zunächst readonly halten.
         * Das reduziert Browser-Autofill deutlich.
         * Beim echten Fokus durch den Benutzer wird readonly entfernt.
         */
        var oldPwInput = document.getElementById('vcp-old');

        if (oldPwInput) {
            oldPwInput.value = '';
            oldPwInput.type = 'password';
            oldPwInput.setAttribute('readonly', 'readonly');

            oldPwInput.addEventListener('focus', function() {
                oldPwInput.removeAttribute('readonly');

                /*
                 * Falls der Browser genau beim Fokus doch etwas einfüllt,
                 * wird das Feld sofort wieder geleert.
                 */
                if (!oldPasswordTouched) {
                    window.setTimeout(function() {
                        if (!oldPasswordTouched) {
                            oldPwInput.value = '';
                            oldPwInput.type = 'password';
                        }
                    }, 50);
                }
            });

            oldPwInput.addEventListener('input', function() {
                oldPasswordTouched = true;
            });

            oldPwInput.addEventListener('blur', function() {
                if (!oldPwInput.value) {
                    oldPasswordTouched = false;
                    oldPwInput.type = 'password';
                    oldPwInput.setAttribute('readonly', 'readonly');
                }
            });
        }

        /*
         * Browser-Autofill nach dem Laden mehrfach neutralisieren.
         * Manche Browser füllen erst verzögert ein.
         */
        clearOldPasswordField();
        window.setTimeout(clearOldPasswordField, 100);
        window.setTimeout(clearOldPasswordField, 500);
        window.setTimeout(clearOldPasswordField, 1200);

        // Login-Status prüfen und Benutzer anzeigen
        fetch(endpoint + '?action=check')
            .then(function(r) {
                return r.json();
            })
            .then(function(d) {
                var uInput = document.getElementById('vcp-username');
                var uInfo  = document.getElementById('vcp-user-info');
                var uName  = document.getElementById('vcp-user-name');

                if (d.user) {
                    if (uInput) uInput.value = d.user;
                    if (uName)  uName.textContent = d.user;
                    if (uInfo)  uInfo.style.display = 'flex';
                }

                /*
                 * Nach dem Setzen des Usernamens nochmals leeren,
                 * weil manche Browser dann erst Autofill auslösen.
                 */
                clearOldPasswordField();
                window.setTimeout(clearOldPasswordField, 100);
                window.setTimeout(clearOldPasswordField, 500);

                // Nicht eingeloggt → weiterleiten
                if (!d.loggedIn) {
                    var loginUrl = (sec && sec.dataset.loginUrl) ? sec.dataset.loginUrl : 'login.html';
                    if (loginUrl.indexOf('{{') === -1) {
                        window.location.href = loginUrl;
                    }
                }
            })
            .catch(function() {
                clearOldPasswordField();
            });

        window.vcpSave = function() {
            var oldEl = document.getElementById('vcp-old');
            var newEl = document.getElementById('vcp-new');
            var new2El = document.getElementById('vcp-new2');

            var old = oldEl ? (oldEl.value || '') : '';
            var nw  = newEl ? (newEl.value || '') : '';
            var nw2 = new2El ? (new2El.value || '') : '';

            if (!old || !nw || !nw2) {
                showError('Bitte alle Felder ausfüllen.');
                return;
            }

            if (nw.length < 6) {
                showError('Neues Passwort mind. 6 Zeichen.');
                return;
            }

            if (nw !== nw2) {
                showError('Passwörter stimmen nicht überein.');
                return;
            }

            setLoading(true);

            var fd = new FormData();
            fd.append('action', 'changepass');
            fd.append('oldpassword', old);
            fd.append('newpassword', nw);

            fetch(endpoint, {
                method: 'POST',
                body: fd
            })
            .then(function(r) {
                return r.json();
            })
            .then(function(d) {
                setLoading(false);

                if (d.success) {
                    showSuccess('✓ ' + (d.message || 'Passwort erfolgreich geändert!'));
                } else {
                    showError(d.message || 'Fehler beim Ändern.');
                }
            })
            .catch(function() {
                setLoading(false);
                showError('Verbindungsfehler.');
            });
        };

        ['vcp-old', 'vcp-new', 'vcp-new2'].forEach(function(id) {
            var el = document.getElementById(id);

            if (el) {
                el.addEventListener('keypress', function(e) {
                    if (e.key === 'Enter') {
                        vcpSave();
                    }
                });
            }
        });
    })();
    </script>
</section>

Der wichtigste Unterschied ist diese Änderung.

Es war so:

Code: Alles auswählen

<input type="password" id="vcp-old" class="vl-input" placeholder="••••••••" autocomplete="current-password">
Jetzt ist es im Code oben so (ersetze aber bitte den gesamten HTML-Code mit dem oben:

Code: Alles auswählen

<input type="password" id="vcp-old" class="vl-input" placeholder="••••••••" autocomplete="off" readonly>
Volker
Moderator
Moderator
Beiträge: 3114
Registriert: Sa 12. Dez 2020, 22:35

Re: Login Block

Beitrag von Volker »

Du bist ein Schatz :kiss:

Bau ich ein
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 9127
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Login Block

Beitrag von Tommy Herrmann »

Dann schiebe das bitte nochmals alles neu in den Download-Ordner, damit ich das morgen erneut einbauen und nochmals angucken kann, ob dann hier auch alles passt.
Volker
Moderator
Moderator
Beiträge: 3114
Registriert: Sa 12. Dez 2020, 22:35

Re: Login Block

Beitrag von Volker »

Tommy jetzt werd ich nicht mehr,

hab das claude gegeben also deinen code soll die mir schnell einbauen. hier ihre Antwort:
Das ist Tommys verbesserte Version mit dem super Autofill-Schutz! Ich ersetze das komplette Template:
Jetzt DU :angst: :confused:
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 9127
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Login Block

Beitrag von Tommy Herrmann »

Ich habe da nur das autocomplete geändert (ausgeschaltet) - teste es auf meiner Seite - das geht so bestens.

Das ist doch nur ein neuer HTML-Code vom Block, den Du schell tauschen kannst. Passe auf, dass die KI jetzt nicht wieder andere Stellen zerschießt!


Sorry - mir fällt da noch eine Kleinigkeit auf, die man vielleicht präziser in der Anleitung beschreiben sollte, siehe auch meine Änderungen im Code:


Anleitung zum VN-Login hat geschrieben:
PHP-Session-Schutz eintragen

Seiteneigenschaften → „Vor <DOCTYPE>" → diesen Code einfügen. Bitte weder vor noch nach dem Code Leerzeichen lassen, da dies den Browser in den "Quirks-Modus" schalten kann und es dann keinen validen DOCTYPE gibt:

Code: Alles auswählen

<?php
session_start();
if (empty($_SESSION['vn_login_user'])) {
    header('Location: login.html'); // ← Pfad und Name deiner Login-Seite!
    exit;
}
?>
Volker
Moderator
Moderator
Beiträge: 3114
Registriert: Sa 12. Dez 2020, 22:35

Re: Login Block

Beitrag von Volker »

Ist nun im Download Tommy

https://www.niederastroth.de/00login/vn ... itung.html

Anleitung auch ergänzt ;)
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 9127
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Login Block

Beitrag von Tommy Herrmann »

Computer ist aus.

Ich mache das morgen am späten Vormittag. Falls Dir noch was einfällt, nur zu :D
Volker
Moderator
Moderator
Beiträge: 3114
Registriert: Sa 12. Dez 2020, 22:35

Re: Login Block

Beitrag von Volker »

Tommys verbesserte Version ist drin! Die wichtigsten Verbesserungen:

readonly Trick – Feld startet readonly, wird erst beim echten Fokus des Users editierbar
clearOldPasswordField() – wird 4x aufgerufen (0ms, 100ms, 500ms, 1200ms) damit auch verzögertes Browser-Autofill erwischt wird
Auge-Button – zeigt nur wenn der User wirklich selbst getippt hat (oldPasswordTouched)
autocomplete="off" statt current-password am alten Passwort-Feld
Nach dem check()-Call nochmals leeren falls Browser dann erst befüllt

Danke Tommy für den schlauen Code! 😊
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 9127
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Login Block

Beitrag von Tommy Herrmann »

:D
Ich werde noch als "Ki-Flüsterer" in die Geschichte eingehen :smoking:
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 9127
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Login Block

Beitrag von Tommy Herrmann »

Moin,

also alles jetzt prima - eine schöne und sichere Anwendung um beliebig viele Seiten eines Projektes zu schützen. Die integrierte Benutzerverwaltung macht diese Anwendung modern und praktisch :tu:


Das Häkchen nach der Passwort-Änderung ist immer noch doppelt, das doppelte Häkchen entsteht hier:

Code: Alles auswählen

showSuccess('✓ ' + (d.message || 'Passwort erfolgreich geändert!'));
Die login.php liefert bereits diese Meldung zurück! Das muss also im JavaScript der Block-HTML raus. Hier nochmals die gesamte korrigierte und getestete HTML. Das solltest Du vielleicht noch ändern, ohne das ich das dann erneut teste, bei mir ist es bereits korrigiert eingebaut.

Meine Beispielseite:

↗️ https://www.mobirise-tutorials.com/VN-B ... mbers.html


Am besten den Code unten zur Korrektur einbauen.

Code: Alles auswählen

<section data-bs-version="5.1" class="vn-changepass" group="Content" plugins="vn-login" data-endpoint="assets/vn-login/login.php" data-login-url="{{loginUrl}}" style="
            --vl-bg:       {{bgColor}};
            --vl-card:     {{cardColor}};
            --vl-accent:   {{accentColor}};
            --vl-text:     {{textColor}};
            --vl-sub:      {{subtextColor}};
            --vl-input-bg: {{inputBgColor}};
            --vl-border:   {{borderColor}};
            --vl-pt:       {{paddingTop}}rem;
            --vl-pb:       {{paddingBottom}}rem;
            --vl-radius:   {{cardRadius}}px;
        ">
    <mbr-parameters>
        <header>URLs</header>
        <input type="text" title="Login-Seite (URL)" name="loginUrl" value="Login-Members.html">
        <header>Size</header>
        <input type="checkbox" title="Full Width" name="fullWidth">
        <input type="range" inline title="Top" name="paddingTop" min="0" max="12" step="1" value="4">
        <input type="range" inline title="Bottom" name="paddingBottom" min="0" max="12" step="1" value="4">
        <header>Farben</header>
        <input type="color" title="Hintergrund" value="#000000" name="bgColor" selected>
        <input type="color" title="Karte" value="#1a1a1a" name="cardColor" selected>
        <input type="color" title="Akzent" value="#1d9e75" name="accentColor" selected>
        <input type="color" title="Text" value="#ffffff" name="textColor" selected>
        <input type="color" title="Subtext" value="#888888" name="subtextColor" selected>
        <input type="color" title="Input Hintergrund" value="#111111" name="inputBgColor" selected>
        <input type="color" title="Rahmen" value="#2a2a2a" name="borderColor" selected>
        <header>Design</header>
        <input type="range" inline title="Eckenrundung (px)" name="cardRadius" min="0" max="24" step="2" value="16">
    </mbr-parameters>

    <div mbr-class="{'container': !fullWidth, 'container-fluid': fullWidth}">
        <div class="vl-wrap">

            <div class="vl-header">
                <div class="vl-logo">🔑</div>
                <h2 class="vl-title mbr-fonts-style" mbr-text data-app-selector=".vl-title" mbr-theme-style="display-2">Passwort ändern</h2>
                <p class="vl-subtitle mbr-fonts-style" mbr-text data-app-selector=".vl-subtitle" mbr-theme-style="display-7">Gib dein aktuelles und neues Passwort ein.</p>
            </div>

            <div class="vl-form" autocomplete="off">
                <input type="text" id="vcp-username" name="vcp-user-display" autocomplete="off" style="position:absolute;left:-9999px;top:-9999px;width:1px;height:1px;opacity:0;" tabindex="-1" readonly>

                <div class="vcp-user-info" id="vcp-user-info" style="display:none;">
                    <span class="vcp-user-label">Eingeloggt als:</span>
                    <span class="vcp-user-name" id="vcp-user-name">–</span>
                </div>

                <div class="vl-field">
                    <label class="vl-label" for="vcp-old">Aktuelles Passwort</label>
                    <div class="vl-pw-wrap">
                        <input type="password" id="vcp-old" class="vl-input" placeholder="••••••••" autocomplete="off" readonly>
                        <button type="button" class="vl-pw-toggle" onclick="vcpToggle('vcp-old')">👁</button>
                    </div>
                </div>

                <div class="vl-field">
                    <label class="vl-label" for="vcp-new">Neues Passwort</label>
                    <div class="vl-pw-wrap">
                        <input type="password" id="vcp-new" class="vl-input" placeholder="min. 6 Zeichen" autocomplete="new-password">
                        <button type="button" class="vl-pw-toggle" onclick="vcpToggle('vcp-new')">👁</button>
                    </div>
                </div>

                <div class="vl-field">
                    <label class="vl-label" for="vcp-new2">Neues Passwort bestätigen</label>
                    <input type="password" id="vcp-new2" class="vl-input" placeholder="Passwort wiederholen" autocomplete="new-password">
                </div>

                <div class="vl-error" id="vcp-error" style="display:none"></div>
                <div class="vcp-success" id="vcp-success" style="display:none"></div>

                <button type="button" class="vl-btn" id="vcp-btn" onclick="vcpSave()">
                    <span id="vcp-btn-text">Passwort speichern</span>
                </button>
            </div>

        </div>
    </div>

    <script>
    (function () {
        var sec = document.querySelector('section.vn-changepass');
        if (!sec) return;

        var endpoint = (sec.dataset.endpoint || 'assets/vn-login/login.php').trim();

        var oldPasswordTouched = false;

        function clearOldPasswordField() {
            var old = document.getElementById('vcp-old');
            if (!old) return;
            old.value = '';
            old.type = 'password';
            oldPasswordTouched = false;
        }

        window.vcpToggle = function(id) {
            var el = document.getElementById(id);
            if (!el) return;
            if (id === 'vcp-old' && !oldPasswordTouched) {
                el.type = 'password';
                el.value = '';
                return;
            }
            if (!el.value) { el.type = 'password'; return; }
            el.type = el.type === 'password' ? 'text' : 'password';
        };

        function showError(msg) {
            var e = document.getElementById('vcp-error');
            var s = document.getElementById('vcp-success');
            if (s) s.style.display = 'none';
            if (e) { e.textContent = msg; e.style.display = 'block'; }
        }

        function showSuccess(msg) {
            var e = document.getElementById('vcp-error');
            var s = document.getElementById('vcp-success');
            if (e) e.style.display = 'none';
            if (s) { s.textContent = msg; s.style.display = 'block'; }
            ['vcp-old','vcp-new','vcp-new2'].forEach(function(id) {
                var el = document.getElementById(id);
                if (el) { el.value = ''; el.type = 'password'; }
            });
            oldPasswordTouched = false;
        }

        function setLoading(on) {
            var btn = document.getElementById('vcp-btn');
            var txt = document.getElementById('vcp-btn-text');
            if (btn) btn.disabled = on;
            if (txt) txt.textContent = on ? '⟳ Bitte warten…' : 'Passwort speichern';
        }

        var oldPwInput = document.getElementById('vcp-old');
        if (oldPwInput) {
            oldPwInput.value = '';
            oldPwInput.type = 'password';
            oldPwInput.setAttribute('readonly', 'readonly');

            oldPwInput.addEventListener('focus', function() {
                oldPwInput.removeAttribute('readonly');
                if (!oldPasswordTouched) {
                    window.setTimeout(function() {
                        if (!oldPasswordTouched) {
                            oldPwInput.value = '';
                            oldPwInput.type = 'password';
                        }
                    }, 50);
                }
            });
            oldPwInput.addEventListener('input', function() { oldPasswordTouched = true; });
            oldPwInput.addEventListener('blur', function() {
                if (!oldPwInput.value) {
                    oldPasswordTouched = false;
                    oldPwInput.type = 'password';
                    oldPwInput.setAttribute('readonly', 'readonly');
                }
            });
        }

        clearOldPasswordField();
        window.setTimeout(clearOldPasswordField, 100);
        window.setTimeout(clearOldPasswordField, 500);
        window.setTimeout(clearOldPasswordField, 1200);

        fetch(endpoint + '?action=check')
            .then(function(r) { return r.json(); })
            .then(function(d) {
                var uInput = document.getElementById('vcp-username');
                var uInfo  = document.getElementById('vcp-user-info');
                var uName  = document.getElementById('vcp-user-name');
                if (d.user) {
                    if (uInput) uInput.value = d.user;
                    if (uName)  uName.textContent = d.user;
                    if (uInfo)  uInfo.style.display = 'flex';
                }
                clearOldPasswordField();
                window.setTimeout(clearOldPasswordField, 100);
                window.setTimeout(clearOldPasswordField, 500);
                if (!d.loggedIn) {
                    var loginUrl = (sec && sec.dataset.loginUrl) ? sec.dataset.loginUrl : 'login.html';
                    if (loginUrl.indexOf('{{') === -1) window.location.href = loginUrl;
                }
            })
            .catch(function() { clearOldPasswordField(); });

        window.vcpSave = function() {
            var oldEl  = document.getElementById('vcp-old');
            var newEl  = document.getElementById('vcp-new');
            var new2El = document.getElementById('vcp-new2');
            var old  = oldEl  ? (oldEl.value  || '') : '';
            var nw   = newEl  ? (newEl.value  || '') : '';
            var nw2  = new2El ? (new2El.value || '') : '';
            if (!old || !nw || !nw2) { showError('Bitte alle Felder ausfüllen.'); return; }
            if (nw.length < 6)       { showError('Neues Passwort mind. 6 Zeichen.'); return; }
            if (nw !== nw2)          { showError('Passwörter stimmen nicht überein.'); return; }
            setLoading(true);
            var fd = new FormData();
            fd.append('action', 'changepass');
            fd.append('oldpassword', old);
            fd.append('newpassword', nw);
            fetch(endpoint, { method: 'POST', body: fd })
                .then(function(r) { return r.json(); })
                .then(function(d) {
                    setLoading(false);
                    if (d.success) showSuccess(d.message || '✓ Passwort erfolgreich geändert!');
                    else showError(d.message || 'Fehler beim Ändern.');
                })
                .catch(function() { setLoading(false); showError('Verbindungsfehler.'); });
        };

        ['vcp-old','vcp-new','vcp-new2'].forEach(function(id) {
            var el = document.getElementById(id);
            if (el) el.addEventListener('keypress', function(e) { if (e.key === 'Enter') vcpSave(); });
        });
    })();
    </script>
</section>

Bitte löscht vor dem Import eines Updates dieser oder einer anderen PHP-Anwendung von Volker Niederastroth (VN) alle Komponenten innerhalb der Software, einschließlich der Blöcke, sowie auf dem Rechner das zugehörige Erweiterungsverzeichnis und auf dem Server das Verzeichnis /assets/vn-login/, damit eine fehlerfreie Neuinstallation möglich ist.

Bitte veröffentlicht in diesem Fall einmalig alles und deaktiviert dazu die Option „Nur Änderungen veröffentlichen“.
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 9127
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Login Block

Beitrag von Tommy Herrmann »

Moin,

wozu hast Du da eigentlich noch das E-Mail Feld in der JSON vom "VN Login"?

Code: Alles auswählen

    "Tester": {
        "password": "$2y$12$m23iNa77jupzuyK\/.xAZMeW0s712VkO3X\/g\/13XJO1SFgWi4Yn0LS",
        "email": "",
        "status": "active",
        "created": "2026-07-06 05:49:47"
    }
Ich habe bei mir jetzt die Änderung zwar noch stehen aber unterbunden. Ich kann diese nur durch ein "true" wieder aktivieren. Nur falls Du das auch brauchen kannst.
Volker
Moderator
Moderator
Beiträge: 3114
Registriert: Sa 12. Dez 2020, 22:35

Re: Login Block

Beitrag von Volker »

Es war ursprünglich als Vorbereitung für ein „Passwort vergessen" Feature gedach ist halt noch drin ;)
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 9127
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Login Block

Beitrag von Tommy Herrmann »

Moin Volker,

willst Du die Passwort-Änderung nicht auf Deiner Demo-Seite auch lieber sperren?

Schließlich kann bei Dir jeder das Benutzerpasswort ändern, ohne dass Du es bemerkst. Dann kann kein interessierter Besucher mehr nachsehen — vielleicht wochen- oder monatelang, bis Du es zufällig entdeckst. Wahrscheinlich würdest Du es aber nie merken :crying:

Wahrscheinlich würde es dir dann auch niemand mitteilen, sondern denken: „Das funktioniert nicht.“

Zum scharf schalten einfach den Demo-Mode in Zeile 95 auf "false" setzen:

Code: Alles auswählen

var DEMO_MODE = true;
Hier das gesamte angepassste Script zur Passwort-Änderung mit oder ohne Demo-Mode:

Code: Alles auswählen

<section data-bs-version="5.1" class="vn-changepass" group="Content" plugins="vn-login" data-endpoint="assets/vn-login/login.php" data-login-url="{{loginUrl}}" style="
            --vl-bg:       {{bgColor}};
            --vl-card:     {{cardColor}};
            --vl-accent:   {{accentColor}};
            --vl-text:     {{textColor}};
            --vl-sub:      {{subtextColor}};
            --vl-input-bg: {{inputBgColor}};
            --vl-border:   {{borderColor}};
            --vl-pt:       {{paddingTop}}rem;
            --vl-pb:       {{paddingBottom}}rem;
            --vl-radius:   {{cardRadius}}px;
        ">
    <mbr-parameters>
        <header>URLs</header>
        <input type="text" title="Login-Seite (URL)" name="loginUrl" value="Login-Members.html">
        <header>Size</header>
        <input type="checkbox" title="Full Width" name="fullWidth">
        <input type="range" inline title="Top" name="paddingTop" min="0" max="12" step="1" value="4">
        <input type="range" inline title="Bottom" name="paddingBottom" min="0" max="12" step="1" value="4">
        <header>Farben</header>
        <input type="color" title="Hintergrund" value="#000000" name="bgColor" selected>
        <input type="color" title="Karte" value="#232323" name="cardColor" selected>
        <input type="color" title="Akzent" value="#e43f3f" name="accentColor" selected>
        <input type="color" title="Text" value="#ffffff" name="textColor" selected>
        <input type="color" title="Subtext" value="#888888" name="subtextColor" selected>
        <input type="color" title="Input Hintergrund" value="#2b2a2a" name="inputBgColor" selected>
        <input type="color" title="Rahmen" value="#2a2a2a" name="borderColor" selected>
        <header>Design</header>
        <input type="range" inline title="Eckenrundung (px)" name="cardRadius" min="0" max="24" step="2" value="16">
    </mbr-parameters>

    <div mbr-class="{'container': !fullWidth, 'container-fluid': fullWidth}">
        <div class="vl-wrap">

            <div class="vl-header">
                <div class="vl-logo">🔑</div>
                <h2 class="vl-title mbr-fonts-style" mbr-text data-app-selector=".vl-title" mbr-theme-style="display-2">Passwort ändern</h2>
                <p class="vl-subtitle mbr-fonts-style" mbr-text data-app-selector=".vl-subtitle" mbr-theme-style="display-7">Gib dein aktuelles und neues Passwort ein.</p>
            </div>

            <div class="vl-form" autocomplete="off">
                <input type="text" id="vcp-username" name="vcp-user-display" autocomplete="off" style="position:absolute;left:-9999px;top:-9999px;width:1px;height:1px;opacity:0;" tabindex="-1" readonly>

                <div class="vcp-user-info" id="vcp-user-info" style="display:none;">
                    <span class="vcp-user-label">Eingeloggt als:</span>
                    <span class="vcp-user-name" id="vcp-user-name">–</span>
                </div>

                <div class="vl-field">
                    <label class="vl-label" for="vcp-old">Aktuelles Passwort</label>
                    <div class="vl-pw-wrap">
                        <input type="password" id="vcp-old" class="vl-input" placeholder="••••••••" autocomplete="off" readonly>
                        <button type="button" class="vl-pw-toggle" onclick="vcpToggle('vcp-old')">👁</button>
                    </div>
                </div>

                <div class="vl-field">
                    <label class="vl-label" for="vcp-new">Neues Passwort</label>
                    <div class="vl-pw-wrap">
                        <input type="password" id="vcp-new" class="vl-input" placeholder="min. 6 Zeichen" autocomplete="new-password">
                        <button type="button" class="vl-pw-toggle" onclick="vcpToggle('vcp-new')">👁</button>
                    </div>
                </div>

                <div class="vl-field">
                    <label class="vl-label" for="vcp-new2">Neues Passwort bestätigen</label>
                    <input type="password" id="vcp-new2" class="vl-input" placeholder="Passwort wiederholen" autocomplete="new-password">
                </div>

                <!-- Demo-Hinweis: wird nur bei DEMO_MODE = true per JavaScript sichtbar geschaltet -->
                <div class="vl-error" id="vcp-error" style="display:none;color:#ff3333;font-weight:bold;"></div>

                <div class="vcp-success" id="vcp-success" style="display:none"></div>

                <button type="button" class="vl-btn" id="vcp-btn" onclick="vcpSave()">
                    <span id="vcp-btn-text">Passwort speichern</span>
                </button>
            </div>

        </div>
    </div>

    <script>
    (function () {
        var sec = document.querySelector('section.vn-changepass');
        if (!sec) return;

        var endpoint = (sec.dataset.endpoint || 'assets/vn-login/login.php').trim();

        /*
         * DEMO-MODUS:
         * true  = Passwortänderung ist gesperrt
         * false = ursprüngliche Passwortänderung wieder aktiv
         */
        var DEMO_MODE = true;

        var oldPasswordTouched = false;

        function clearOldPasswordField() {
            var old = document.getElementById('vcp-old');
            if (!old) return;
            old.value = '';
            old.type = 'password';
            oldPasswordTouched = false;
        }

        window.vcpToggle = function(id) {
            var el = document.getElementById(id);
            if (!el) return;
            if (id === 'vcp-old' && !oldPasswordTouched) {
                el.type = 'password';
                el.value = '';
                return;
            }
            if (!el.value) { el.type = 'password'; return; }
            el.type = el.type === 'password' ? 'text' : 'password';
        };

        function showError(msg) {
            var e = document.getElementById('vcp-error');
            var s = document.getElementById('vcp-success');
            if (s) s.style.display = 'none';
            if (e) {
                e.textContent = msg;
                e.style.display = 'block';
                e.style.color = '#ff3333';
                e.style.fontWeight = 'bold';
            }
        }

        function hideError() {
            var e = document.getElementById('vcp-error');
            if (e) {
                e.textContent = '';
                e.style.display = 'none';
            }
        }

        function showSuccess(msg) {
            var e = document.getElementById('vcp-error');
            var s = document.getElementById('vcp-success');
            if (e) e.style.display = 'none';
            if (s) { s.textContent = msg; s.style.display = 'block'; }
            ['vcp-old','vcp-new','vcp-new2'].forEach(function(id) {
                var el = document.getElementById(id);
                if (el) { el.value = ''; el.type = 'password'; }
            });
            oldPasswordTouched = false;
        }

        function setLoading(on) {
            var btn = document.getElementById('vcp-btn');
            var txt = document.getElementById('vcp-btn-text');
            if (btn) btn.disabled = on;
            if (txt) txt.textContent = on ? '⟳ Bitte warten…' : 'Passwort speichern';
        }

        /*
         * Demo-Hinweis nur dann sofort anzeigen,
         * wenn der Demo-Modus tatsächlich aktiv ist.
         */
        if (DEMO_MODE) {
            showError('Änderung in Demo nicht möglich');
        } else {
            hideError();
        }

        var oldPwInput = document.getElementById('vcp-old');
        if (oldPwInput) {
            oldPwInput.value = '';
            oldPwInput.type = 'password';
            oldPwInput.setAttribute('readonly', 'readonly');

            oldPwInput.addEventListener('focus', function() {
                oldPwInput.removeAttribute('readonly');
                if (!oldPasswordTouched) {
                    window.setTimeout(function() {
                        if (!oldPasswordTouched) {
                            oldPwInput.value = '';
                            oldPwInput.type = 'password';
                        }
                    }, 50);
                }
            });
            oldPwInput.addEventListener('input', function() { oldPasswordTouched = true; });
            oldPwInput.addEventListener('blur', function() {
                if (!oldPwInput.value) {
                    oldPasswordTouched = false;
                    oldPwInput.type = 'password';
                    oldPwInput.setAttribute('readonly', 'readonly');
                }
            });
        }

        clearOldPasswordField();
        window.setTimeout(clearOldPasswordField, 100);
        window.setTimeout(clearOldPasswordField, 500);
        window.setTimeout(clearOldPasswordField, 1200);

        fetch(endpoint + '?action=check')
            .then(function(r) { return r.json(); })
            .then(function(d) {
                var uInput = document.getElementById('vcp-username');
                var uInfo  = document.getElementById('vcp-user-info');
                var uName  = document.getElementById('vcp-user-name');
                if (d.user) {
                    if (uInput) uInput.value = d.user;
                    if (uName)  uName.textContent = d.user;
                    if (uInfo)  uInfo.style.display = 'flex';
                }
                clearOldPasswordField();
                window.setTimeout(clearOldPasswordField, 100);
                window.setTimeout(clearOldPasswordField, 500);
                if (!d.loggedIn) {
                    var loginUrl = (sec && sec.dataset.loginUrl) ? sec.dataset.loginUrl : 'login.html';
                    if (loginUrl.indexOf('{{') === -1) window.location.href = loginUrl;
                }
            })
            .catch(function() { clearOldPasswordField(); });

        window.vcpSave = function() {

            /*
             * DEMO-SPERRE:
             * In dieser Demo wird keine Anfrage an login.php?action=changepass gesendet.
             * Dadurch kann der öffentliche Tester-Account nicht verändert werden.
             */
            if (DEMO_MODE) {
                showError('Änderung in Demo nicht möglich');
                return;
            }

            /*
             * URSPRÜNGLICHE VERSION:
             * Zum Scharfschalten oben DEMO_MODE auf false setzen.
             */

            var oldEl  = document.getElementById('vcp-old');
            var newEl  = document.getElementById('vcp-new');
            var new2El = document.getElementById('vcp-new2');
            var old  = oldEl  ? (oldEl.value  || '') : '';
            var nw   = newEl  ? (newEl.value  || '') : '';
            var nw2  = new2El ? (new2El.value || '') : '';
            if (!old || !nw || !nw2) { showError('Bitte alle Felder ausfüllen.'); return; }
            if (nw.length < 6)       { showError('Neues Passwort mind. 6 Zeichen.'); return; }
            if (nw !== nw2)          { showError('Passwörter stimmen nicht überein.'); return; }
            setLoading(true);
            var fd = new FormData();
            fd.append('action', 'changepass');
            fd.append('oldpassword', old);
            fd.append('newpassword', nw);
            fetch(endpoint, { method: 'POST', body: fd })
                .then(function(r) { return r.json(); })
                .then(function(d) {
                    setLoading(false);
                    if (d.success) showSuccess(d.message || '✓ Passwort erfolgreich geändert!');
                    else showError(d.message || 'Fehler beim Ändern.');
                })
                .catch(function() { setLoading(false); showError('Verbindungsfehler.'); });
        };

        ['vcp-old','vcp-new','vcp-new2'].forEach(function(id) {
            var el = document.getElementById(id);
            if (el) el.addEventListener('keypress', function(e) { if (e.key === 'Enter') vcpSave(); });
        });
    })();
    </script>
</section>
Volker
Moderator
Moderator
Beiträge: 3114
Registriert: Sa 12. Dez 2020, 22:35

Re: Login Block

Beitrag von Volker »

Moin Tommy,

Demo Mode ist eine nette Idee :)

Aber ich gucke da schon täglich rein, solange das da online ist :)

Ich überarbeite gerade meine Seite, die wird kleiner und übersichtlicher - da fliegen ganz viele Seiten raus jetzt.

Also ich lass das mal so stehen, wenn einer meint mein Login würde nicht funktionieren dann soll er das von mir aus denken ;) Will eh keiner haben wegen der Kosten :D Ich hab es gebaut - klappt - fertig :D

Baue gerade noch andere nette Dinge - ob ich die veröffentliche weiß ich noch gar nicht.
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 9127
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Login Block

Beitrag von Tommy Herrmann »

Na ja - bei mir habe ich das jetzt so eingebaut (denn ich vergesse das spätestens wenn ich mich mit etwas Neuem beschäftige) und auch die CSS für das "Auge" und die Platzhaltertexte geändert. Die sind an meinem Laptop nämlich nicht zu sehen - ich weiß Deiner ist anders kalibriert.

Die Anwendung würde sicherlich von vielen Menschen genutzt werden – vorausgesetzt, man findet sie bei dir und du würdest etwas Werbung dafür machen. Allein das Forum reicht kaum aus; es hilft zwar, darf aber nicht die einzige Werbemaßnahme sein.

Ein weiteres Problem ist, dass du die Suchmaschinenoptimierung vernachlässigst: Es fehlen viele Einträge und es gibt kaum Texte, sodass die Website bei Google nur schwer auffindbar sein wird.

Na zumindest kommt meine alte Seite, die ganz ähnlich aufgebaut ist und auch einen Link zu der neuen Seite hat bei Google ganz oben beim Suchbegriff:

"Mobirise Mitglieder Bereich"
Volker
Moderator
Moderator
Beiträge: 3114
Registriert: Sa 12. Dez 2020, 22:35

Re: Login Block

Beitrag von Volker »

Tommy :D

Ich will nix bewerben oder verkaufen.

Das sind doch alles Erweiterungen speziell hier für Foren Mitglieder - die im Hersteller Forum verpassen ja jetzt meine neuen Blöcke :D

Mir ist das doch wuppe ob Google die findet oder sonst wer. Ich bau die, weil ich es kann :D

Hab jetzt meinen Live Chat in einen Block gepackt - cool. Admin panel einfach per Link aufrufen. Wird nicht veröffentlicht. Ich wollte das hin bekommen - hab ich.

Jetzt bau ich ( nur für Frank) die Galerie noch um, das Effekte für die Bilder und HG Farbe einstellbar ist.
Benutzeravatar
Tommy Herrmann
Site Admin
Site Admin
Beiträge: 9127
Registriert: So 6. Dez 2020, 07:37
Wohnort: Berlin
Kontaktdaten:

Re: Login Block

Beitrag von Tommy Herrmann »

Also ich interessiere mich sehr für deine Blöcke, obwohl ich wahrscheinlich der Einzige bin, der sie wirklich nicht braucht, da ich das nur als Hobby betreibe :D

Glaub bloß nicht, dass hier niemand aus dem anderen Forum mitliest — alle schauen zu, besonders diejenigen, die über mich schimpfen.

Immerhin habe ich über zwei Millionen eindeutige Besucher im Jahr; auch wenn die meisten davon Bots sind, bleiben trotzdem viele echte Besucher übrig, darunter zahlreiche aus dem Herstellerforum. Rate mal, warum unser Forum bei fast allen Google-Suchen noch vor dem Herstellerforum gelistet wird.

Da können dann auch schon mal nur in einem Monat (wie im Mai) über 500.000 Besucher dabei sein und die wollen alle Deine Anwendungen :)


Besucher.jpg



Auch ganz interessant wo die Besucher herkommen - nur dieser laufende Monat - jedenfalls nicht vom Herstellerforum - das finde ich auch in den vielen anderen Statistiken fast nicht - weil die da behaupten ich würde da nur User abgreifen - zumal ich eigentlich fast nie einen Link zu meinem Forum dort poste - lächerlich ist das:


Laufende Monat.jpg



Hier kann man auch gut sehen wie wichtig die Handys sind - die Betriebssysteme der letzten 4 Wochen:


Betriebssysteme der letzten 4 Wochen.jpg



Ich benutze das Hersteller-Forum als Marketing-Werkzeug :eek: wie zum Beispiel dieses nette Mitglied hier schreibt:

https://forums.mobirise.com/discussion/ ... ent_126169

Dabei habe ich nur Volker verteidigt, der dort in Deutsch geschrieben hatte und bemerkt, dass man in meinem Forum in jeder Sprache schreiben darf.

1. Juli 2026 Strettonbull an Tommy Herrmann


Also, this isn't about your forum, it's about this one. I'm not interested in your forum at all and it's obvious you are using this forum as a marketing tool to promote your own forum.

>>> auf Deutsch:

Außerdem geht es hier nicht um dein Forum, sondern um dieses hier. Dein Forum interessiert mich überhaupt nicht, und es ist offensichtlich, dass du dieses Forum als Marketinginstrument nutzt, um für dein eigenes Forum zu werben.
Volker
Moderator
Moderator
Beiträge: 3114
Registriert: Sa 12. Dez 2020, 22:35

Re: Login Block

Beitrag von Volker »

Tommy !!!!

Du sollt dich doch nicht aufregen :D

Alles total gechillt :huepf:
Antworten

Wer ist online?

Mitglieder in diesem Forum: Amazon [Bot] und 5 Gäste