Contao-Camp 2024
Ergebnis 1 bis 30 von 30

Thema: Benutzer aus tl_member laden und manuell einloggen

  1. #1
    Contao-Nutzer Avatar von fl0
    Registriert seit
    13.11.2019.
    Ort
    OWL
    Beiträge
    17

    Frage Benutzer aus tl_member laden und manuell einloggen

    Hallo,

    bei einer unserer Webseiten soll es die Möglichkeit geben, dass sich Benutzer zusätzlich zu Contao auch über einen Single-Sign-On-Provider (SSO) anmelden können.
    Nachdem sich der Benutzer über den SSO authentifiziert hat, wird für diesen, falls noch nicht vorhanden, ein neuer Benutzer in der Tabelle tl_member angelegt.
    Der SSO liefert hierbei eine eindeutige nameId, welche für den Contao-Benutzer als Username genutzt wird.

    Über diesen Username würde ich nun gerne den FrontendUser laden und ihn dann anschließend einloggen, so wie ein Benutzer, der sich ganz normal über das Loginformular eingeloggt hat.

    Das MemberModel konnte ich auch schon erfolgreich über die nameId als Username/E-Mail laden, dazu habe ich folgende Zeile verwendet:

    PHP-Code:
    //nameID wird als Benutzername und E-Mail genutzt
    $memberModel MemberModel::findActiveByEmailAndUsername$nameID ); 
    Für den FrontendUser soll es wohl auch eine Methode geben, mit welcher man diesen über den Username laden können soll, allerdings gibt diese immer NULL zurück

    PHP-Code:
    $user FrontendUser::loadUserByUsername$nameID ); 
    Theoretisch könnte man den FrontendUser dann wie folgt einloggen, dies scheint aber nur für den normalen Loginweg vorgesehen zu sein:

    PHP-Code:
    $user->login(); 

    Hätte also jemand eine Idee, wie ich einen Benutzer per Skript aus der Datenbank laden und dann anschließend einloggen kann?


    Grüße fl0

  2. #2
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    33.899
    Partner-ID
    10107

    Standard

    Dazu implementierst du am besten einen Custom Authenticator für die contao_frontend Firewall. Beispiel: https://github.com/inspiredminds/contao-ip-login
    » sponsor me via GitHub or PayPal or Revolut

  3. #3
    Contao-Nutzer Avatar von fl0
    Registriert seit
    13.11.2019.
    Ort
    OWL
    Beiträge
    17

    Standard

    Danke schonmal für deine Antwort Spooky!

    Ich habe mich mal kurz eingelesen und jetzt kommt noch eine etwas grundlegendere Frage auf:

    Wie mache ich meine erstelle Custom Authenticator-Klasse erreichbar bzw. wie binde ich diese am besten ein, so dass sie in meinen anderen Skripten verfügbar ist und wo genau packt man diese hin?

    Einfach über ein require bzw. Inserttag? Oder kann man das auch etwas "sauberer" lösen?

    Grüße fl0

  4. #4
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    33.899
    Partner-ID
    10107

    Standard

    Ich glaube du hast dich noch nicht genug in die Thematik eingelesen - das "packst du nicht irgendwo hin". Du erweiterst damit die bestehende Firewall.
    » sponsor me via GitHub or PayPal or Revolut

  5. #5
    Contao-Nutzer Avatar von fl0
    Registriert seit
    13.11.2019.
    Ort
    OWL
    Beiträge
    17

    Standard

    Ja und um diese zu erweitern muss ich doch eine eigene Klasse anlegen, wie die ApiKeyAuthenticator Klasse im Beispiel?

    Aber wie sage ich Contao jetzt, dass es diese Klasse verwenden soll? Erstelle ich dafür ein eigenes Paket, wie das von dir genannte Beispiel contao-ip-login, dass dann über den Autoloader eingebunden wird?

    Ich bin mir da gerade leider nicht ganz im Klaren drüber...

  6. #6
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    33.899
    Partner-ID
    10107

    Standard

    Eine eigene Extension brauchst du dafür nicht, das geht auch alles mit Applikationsanpassungen. Die groben Schritte wären:

    1. Authenticator Service unter src/Security/YourCustomAuthenticator.php anlegen (FQCN: App\Security\YourCustomAuthenticator)
    2. Authenticator in der Firewall über ein Contao Manager Plugin registrieren, also src/ContaoManager/Plugin.php (FQCN: App\ContaoManager\Plugin)
    » sponsor me via GitHub or PayPal or Revolut

  7. #7
    Contao-Nutzer Avatar von fl0
    Registriert seit
    13.11.2019.
    Ort
    OWL
    Beiträge
    17

    Standard

    Danke, das hat mir auf jeden Fall schon mal weiter geholfen.

    Den ersten Schritt habe ich umgesetzt. Beim zweiten Schritt hapert es dann aber leider wieder.
    Muss ich jetzt die bereits bestehende Plugin.php unter "vendor/contao/core-bundle/src/ContaoManager/Plugin.php" bearbeiten und dort meine Klasse eintragen?

    PHP-Code:
    public function getBundles(ParserInterface $parser): array
        {
            return [
                
    BundleConfig::create(KnpMenuBundle::class),
                
    BundleConfig::create(KnpTimeBundle::class),
                
    BundleConfig::create(SchebTwoFactorBundle::class),
                
    BundleConfig::create(CmfRoutingBundle::class),
                
    BundleConfig::create(Terminal42ServiceAnnotationBundle::class),
                
    BundleConfig::create(ContaoCoreBundle::class)
                    ->
    setReplace(['core'])
                    ->
    setLoadAfter(
                        [
                            
    FrameworkBundle::class,
                            
    SecurityBundle::class,
                            
    TwigBundle::class,
                            
    MonologBundle::class,
                            
    SwiftmailerBundle::class,
                            
    DoctrineBundle::class,
                            
    KnpMenuBundle::class,
                            
    KnpTimeBundle::class,
                            
    LexikMaintenanceBundle::class,
                            
    NelmioCorsBundle::class,
                            
    NelmioSecurityBundle::class,
                            
    SchebTwoFactorBundle::class,
                            
    CmfRoutingBundle::class,
                        ]
                    ),
            ];
        } 
    Füge ich jetzt hier einfach meine Klasse mit einem zusätzlichen Eintrag von YourCustomAuthenticator::class hinzu?

    Ich habe hier eine Anleitung gefunden, bin mir aber nicht sicher ob das die Richtige ist:

    https://docs.contao.org/dev/framework/manager-plugin/

    Grüße fl0

  8. #8
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    33.899
    Partner-ID
    10107

    Standard

    Zitat Zitat von fl0 Beitrag anzeigen
    Danke, das hat mir auf jeden Fall schon mal weiter geholfen.

    Den ersten Schritt habe ich umgesetzt. Beim zweiten Schritt hapert es dann aber leider wieder.
    Muss ich jetzt die bereits bestehende Plugin.php unter "vendor/contao/core-bundle/src/ContaoManager/Plugin.php" bearbeiten und dort meine Klasse eintragen?
    Nein, niemals direkt etwas in Vendor ändern. Du machst eine Applikationsanpassung, mit einem eigenen Contao Manager Plugin unter dem Pfad, den ich gepostet habe.
    » sponsor me via GitHub or PayPal or Revolut

  9. #9
    Contao-Nutzer
    Registriert seit
    11.12.2021.
    Beiträge
    28

    Standard

    Hi,
    ich möchte mich hier mal anschließen.
    Ich möchte über ein externes Programm ein POST Request auf eine Route durchführen. Letztendlich möchte ich damit eine Datei hochladen. Dafür müsste ich ja quasi eingeloggt sein. Kann ich in dem POST Request irgendwie Login Credentials mitschicken, sodass der User authentifiziert wird? Oder wie geht man da vor?

    Vielen Dank!

  10. #10
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    33.899
    Partner-ID
    10107

    Standard

    Zitat Zitat von tnickel Beitrag anzeigen
    Hi,
    ich möchte mich hier mal anschließen.
    Ich möchte über ein externes Programm ein POST Request auf eine Route durchführen. Letztendlich möchte ich damit eine Datei hochladen. Dafür müsste ich ja quasi eingeloggt sein. Kann ich in dem POST Request irgendwie Login Credentials mitschicken, sodass der User authentifiziert wird? Oder wie geht man da vor?

    Vielen Dank!
    Grundsätzlich geht das. Dein POST Request muss folgende Daten enthalten, damit die Firewall von Contao greift:

    • username=…
    • password=…
    • FORM_SUBMIT=tl_login


    Hier gibt es allerdings noch einen Bug in Contao: https://github.com/contao/contao/pull/4968
    » sponsor me via GitHub or PayPal or Revolut

  11. #11
    Contao-Nutzer
    Registriert seit
    11.12.2021.
    Beiträge
    28

    Standard

    Danke für die Antwort!
    Wenn ich das über curl mache, bekomme ich als Antwort:

    HTML-Code:
    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="UTF-8" />
            <meta http-equiv="refresh" content="0;url='https://www.***.de/***'" />
    
            <title>Redirecting to https://www.***.de/***</title>
        </head>
        <body>
            Redirecting to <a href="https://www.***.de/***">https://www.***.de/***</a>.
        </body>
    </html>
    Ich komme also nicht wirklich in meinen Controller. Muss ich noch etwas berücksichtigen?

  12. #12
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    33.899
    Partner-ID
    10107

    Standard

    Dazu musst du genaue Informationen zu deinem Request (ohne Credentials natürlich) und dem Response (ohne obfuscation) geben (Domain kannst du obfuscaten).
    » sponsor me via GitHub or PayPal or Revolut

  13. #13
    Contao-Nutzer
    Registriert seit
    11.12.2021.
    Beiträge
    28

    Standard

    Hab es jetzt doch hinbekommen.

    Code:
    curl -X POST -H "Content-Type: application/json" -d "{ "FORM_SUBMIT": "tl_login", "username": "***", "password": "***" }" "https://www.***.de/***"
    Allerdings scheint der User nicht authentifiziert worden zu sein. Denn in meinem Controller liefert
    Code:
    $this->security->getUser()
    null zurück.
    Im Konstruktor habe ich Security injected:
    Code:
    public function __construct(Security $security)
    {
        $this->security = $security;
    }
    Geändert von tnickel (25.07.2022 um 20:50 Uhr)

  14. #14
    Contao-Nutzer
    Registriert seit
    11.12.2021.
    Beiträge
    28

    Standard

    Wenn ich es so mache:
    Code:
    curl -X POST -H "Content-Type: application/x-www-form-urlencoded" -d "FORM_SUBMIT=tl_login&username=***&password=***" "https://www.***.de/***"
    Oder so mache:
    Code:
    curl -X POST -F "FORM_SUBMIT=tl_login" -F "username=***" -F "password=***" "https://www.***.de/***"
    Dann bekomme ich ein 400 Bad Request.

  15. #15
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    33.899
    Partner-ID
    10107

    Standard

    Content-Type: application/json wird auf jeden Fall nicht gehen, es muss Content-Type: application/x-www-form-urlencoded sein. Nutze den Debug-Modus um im Response den Stack Trace für den 400er zu sehen.
    » sponsor me via GitHub or PayPal or Revolut

  16. #16
    Contao-Nutzer Avatar von fl0
    Registriert seit
    13.11.2019.
    Ort
    OWL
    Beiträge
    17

    Standard

    Zitat Zitat von Spooky Beitrag anzeigen
    Nein, niemals direkt etwas in Vendor ändern. Du machst eine Applikationsanpassung, mit einem eigenen Contao Manager Plugin unter dem Pfad, den ich gepostet habe.
    Ich hatte meine Datei auch in einem neuen Verzeichnis "SSOAuthenticator" unter "vendor/contao/core-bundle/src/Security/SSOAuthenticator/SSOAuthenticator.php" angelegt, die gehört da dann vermutlich auch nicht hin?

    Kannst du den Punkt mit dem eigenen Contao Manager Plugin evtl. etwas näher erläutern? Hier werde ich leider nicht wirklich schlau draus, was nun genau getan werden muss, um so ein Plugin anzulegen.

    Grüße fl0

  17. #17
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    33.899
    Partner-ID
    10107

    Standard

    Zitat Zitat von fl0 Beitrag anzeigen
    Ich hatte meine Datei auch in einem neuen Verzeichnis "SSOAuthenticator" unter "vendor/contao/core-bundle/src/Security/SSOAuthenticator/SSOAuthenticator.php" angelegt, die gehört da dann vermutlich auch nicht hin?
    Nein, auf jeden Fall nicht. Wenn du eine Applikationsanpassung macht, dann alles im src/ Ordner deiner Applikation (also src/ Ordner im Contao Installationsverzeichnis).


    Zitat Zitat von fl0 Beitrag anzeigen
    Kannst du den Punkt mit dem eigenen Contao Manager Plugin evtl. etwas näher erläutern? Hier werde ich leider nicht wirklich schlau draus, was nun genau getan werden muss, um so ein Plugin anzulegen.
    Die Plugin Datei legst du unter src/ContaoManager/Plugin.php an.
    » sponsor me via GitHub or PayPal or Revolut

  18. #18
    Contao-Nutzer Avatar von fl0
    Registriert seit
    13.11.2019.
    Ort
    OWL
    Beiträge
    17

    Standard

    Und wenn ich kein src-Verzeichnis in meinem Hauptverzeichnis habe, muss ich dies noch anlegen?

    So sieht die Contao-Installation bei mir aus:

    • app
    • assets
    • contao-manager
    • files
    • system
    • templates
    • var
    • vendor
    • web
    • composer.json
    • composer.lock

  19. #19
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    33.899
    Partner-ID
    10107

    Standard

    Zitat Zitat von fl0 Beitrag anzeigen
    Und wenn ich kein src-Verzeichnis in meinem Hauptverzeichnis habe, muss ich dies noch anlegen?
    Den gesamten Pfad (inkl. Datei) musst du selbst anlegen, ja.
    » sponsor me via GitHub or PayPal or Revolut

  20. #20
    Contao-Nutzer Avatar von fl0
    Registriert seit
    13.11.2019.
    Ort
    OWL
    Beiträge
    17

    Standard

    Ich versuche jetzt momentan ein bestehendes Plugin https://github.com/inspiredminds/contao-ip-login anzupassen, um die gewünschte Funktionalität zu erzielen.

    Hier wird der Benutzer automatisch in Contao eingeloggt, wenn die IP in der Liste unter app/config/config.yml eingetragen wurde und das Plugin greift dann von selbst.

    Dafür gibt es in der services.yml des Plugins eine Option mit dem Namen "autowire" welche den Wert "true" hat. Ich möchte allerdings an meiner Stelle einen manuellen Einstiegspunkt für den Login in einem meiner Skripte bestimmen, an welchem das Plugin aufgerufen und der Benutzer dann eingeloggt wird. Wenn ich allerdings den Wert der "autowire" Option ändere oder diese ganz wegnehme, bekomme ich einen Fehler.

    Mir ist nicht ganz klar, wo genau die "autowire" Option im Plugin greift und wo ich dieses noch abändern muss, damit ich die Option wegnehmen kann. Ich würde gerne in meinem eigenem Skript die Plugin-Klasse aufrufen um dann anschließend den Benutzer sauber einzuloggen.

    Grüße fl0

  21. #21
    Contao-Nutzer Avatar von fl0
    Registriert seit
    13.11.2019.
    Ort
    OWL
    Beiträge
    17

    Standard

    Ich glaube, ich habe das Problem doch schon selber gefunden, die "autoconfigure" Option muss mit gesetzt werden, damit es in Kombination mit "autowire" zu keinem Fehler kommt.

    Edit: Nein, das war es leider doch nicht. Ich bekomme immer noch den folgenden Fehler:

    Got error 'PHP message: PHP Fatal error: Uncaught Symfony\\Component\\DependencyInjection\\Exception \\RuntimeException: Invalid constructor argument 3 for service "InspiredMinds\\ContaoIpLoginBundle\\Security\\IpA uthenticator": argument 1 must be defined before. Check your service definition.

    Grüße fl0
    Geändert von fl0 (09.08.2022 um 10:42 Uhr)

  22. #22
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    33.899
    Partner-ID
    10107

    Standard

    autowire und autoconfigure hat nichts direkt mit diesem Feature zu tun bzw. nichts direkt mit der Firewall. Siehe

    » sponsor me via GitHub or PayPal or Revolut

  23. #23
    Contao-Nutzer Avatar von fl0
    Registriert seit
    13.11.2019.
    Ort
    OWL
    Beiträge
    17

    Standard

    Ich habe es mittlerweile hinbekommen, das Plugin so zu modifizieren, dass der Benutzer wie gewünscht eingeloggt wird.

    Nun würde ich gerne nach dem der Benutzer authentifiziert worden ist, eine Weiterleitung auf eine bestimmte Seite durchführen. Dazu scheint es auch eine geeignete Methode zu geben:

    PHP-Code:
    public function onAuthenticationSuccess(Request $requestTokenInterface $token$providerKey): ?Response
    {
        return 
    null;

    Hier kann man wohl ein Response-Objekt zurückgeben, um weiterzuleiten

    PHP-Code:
    public function onAuthenticationSuccess(Request $requestTokenInterface $token$providerKey): ?Response
    {
        return 
    RedirectResponse::create'weiterleitung.html' );

    Dies führt allerdings zu einer Fehlermeldung. Hat hier jemand eine Idee?

  24. #24
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    33.899
    Partner-ID
    10107

    Standard

    Zitat Zitat von fl0 Beitrag anzeigen
    Dies führt allerdings zu einer Fehlermeldung. Hat hier jemand eine Idee?
    Ich verstehe nicht, warum es so viele Leute im Forum gibt, die einfach nur "führt zu Fehlermeldung" posten und sonst nichts . Erwartest du dir, dass wir Glaskugeln haben und automatisch wissen, wie die genaue Fehlermeldung bei dir aussieht, wie der Stack Trace etc. lautet?

    Ist nicht böse gemeint, aber ich muss mich halt über den Gedankengang wundern.
    » sponsor me via GitHub or PayPal or Revolut

  25. #25
    Contao-Nutzer Avatar von fl0
    Registriert seit
    13.11.2019.
    Ort
    OWL
    Beiträge
    17

    Standard

    Ich habe erst überlegt ob ich die Fehlermeldung mitposte, mich dann aber dagegen entschieden, da die Urls an mehreren Stellen enthalten ist.
    Habe mir gedacht, du erkennst eventuell tatsächlich schon am Code das Problem

    Dann hier einmal die Fehlermeldung in zensiert:


    Code:
    [2022-08-11 10:03:35] request.CRITICAL: Uncaught PHP Exception RuntimeException: "Error when rendering "https://server.url.de/_fragment?_hash=Z2X8SQ97ldGVhqVn4MKUyLnOxnJZ5d4NQpGzw5Hd6TA%3D&_path=insertTag%3D%257B%257Bua%253A%253Aclass%257Cattr%257D%257D%26_scope%3Dfrontend%26_format%3Dhtml%26_locale%3Dde%26_controller%3DContao%255CCoreBundle%255CController%255CInsertTagsController%253A%253ArenderAction&clientCache=0&pageId=2769&request=response.html" (Status code is 302)." at /var/www/vhosts/server.url.de/httpdocs/vendor/symfony/http-kernel/HttpCache/AbstractSurrogate.php line 99 {"exception":"[object] (RuntimeException(code: 0): Error when rendering \"https://server.url.de/_fragment?_hash=Z2X8SQ97ldGVhqVn4MKUyLnOxnJZ5d4NQpGzw5Hd6TA%3D&_path=insertTag%3D%257B%257Bua%253A%253Aclass%257Cattr%257D%257D%26_scope%3Dfrontend%26_format%3Dhtml%26_locale%3Dde%26_controller%3DContao%255CCoreBundle%255CController%255CInsertTagsController%253A%253ArenderAction&clientCache=0&pageId=2769&request=response.html\" (Status code is 302). at /var/www/vhosts/server.url.de/httpdocs/vendor/symfony/http-kernel/HttpCache/AbstractSurrogate.php:99)"} []

  26. #26
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    33.899
    Partner-ID
    10107

    Standard

    In deinem Authenticator müsstest du vielleicht prüfen ob der Request ein Fragment Request ist und dann nicht weiter leiten.
    » sponsor me via GitHub or PayPal or Revolut

  27. #27
    Contao-Nutzer Avatar von fl0
    Registriert seit
    13.11.2019.
    Ort
    OWL
    Beiträge
    17

    Standard

    Ich habe um zu prüfen, ob es sich um ein Fragment Request handelt etwas gefunden und daraus folgendes gebaut:

    PHP-Code:
    public function onAuthenticationSuccess(Request $requestTokenInterface $token$providerKey): ?Response
        
    {
          
    $return null;

          if( 
    strpos$request->server->get'REQUEST_URI' ), "_fragment" ) === false )
          {
            
    $return RedirectResponse::create$this->getRedirectUrl() );
          }

          return 
    $return;
        } 
    Da strpos 1 zurückgibt, gehe ich davon aus, dass es sich um einen Fragment Request handelt. Aber wie kriege ich es nun an dieser Stelle hin, dass eine Weiterleitung durchgeführt wird?

    Grüße fl0

  28. #28
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    33.899
    Partner-ID
    10107

    Standard

    Jetzt müsste die Weiterleitung ja eigentlich funktionieren?
    » sponsor me via GitHub or PayPal or Revolut

  29. #29
    Contao-Nutzer Avatar von fl0
    Registriert seit
    13.11.2019.
    Ort
    OWL
    Beiträge
    17

    Standard

    Nein, es wird nicht in den if-Zweig gegangen, da die Bedingung nicht erfüllt ist (es handelt sich um ein Fragment Request).
    Und andersrum kommt es zu besagtem Fehler.

  30. #30
    Community-Moderator
    Wandelndes Contao-Lexikon
    Avatar von Spooky
    Registriert seit
    12.04.2012.
    Ort
    Scotland
    Beiträge
    33.899
    Partner-ID
    10107

    Standard

    Ja du willst ja auch keinen Redirect, wenn es ein Fragment Request ist. Zumindest war das mein Vorschlag (ob das dein Problem wirklich behebt weiß ich nicht).

    Aber ich denke insgesamt wird man da bei dir näher debuggen müssen.
    » sponsor me via GitHub or PayPal or Revolut

Aktive Benutzer

Aktive Benutzer

Aktive Benutzer in diesem Thema: 2 (Registrierte Benutzer: 0, Gäste: 2)

Lesezeichen

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •