Erster Eindruck von Ruby/Roda und Frust bei der Authentifizierung
Wednesday, 23. January 2019
Das ist noch keine Gesamtbewertung von Roda, einem an Sinatra angelehnten Framework zum Bauen von Webanwendungen. Sowas braucht mehr Zeit, aber ich will schonmal anfangen zu dokumentieren. Kommend von Sinatra wollte ich für ein neues Softwareprojekt eine ähnliche Serverkomponente nutzen, aber auch etwas neues lernen. Daher Roda, und weil für die spätere Bewertung diese Ersteindrücke oft schon vergessen sind, starte ich mit dem Aufschreiben diesmal ziemlich direkt.
Roda hat mir erst sehr gut gefallen. Es ist ganz klar an Sinatra orientiert, sodass ich schnell starten konnte. Um GET /home.html
zu bedienen ist nur wenig und vertraut aussehender Code nötig:
require "roda" class App < Roda route do |r| r.on "/home.html" do r.get do "Hi" end end end end
Das ist ein bisschen expliziter als gewohnt, mit dem expliziten Iterieren über route
. Das passt, weniger unsichtbare Magie zu haben soll einer der Vorteile sein.
Ich habe schnell verstanden, dass viele der Grundfunktionen in Roda nicht direkt enthalten sind, sie aber per mitgeliefertem Plugin aktiviert werden können. Das meint wirklich Grundfunktionen. Selbst das Ausliefern von Dateien im Verzeichnis public/ oder die Templateunterstützung ist nicht direkt an. Da aber alles nötige direkt anschaltbar ist wirkt das positiv. Als ein hilfreiches Werkzeug, dessen hilfreiche Funktionen man bei Bedarf aktiviert und bewusst entdeckt, anstatt nach ein paar Monaten der Nutzung über eine alternative integrierte Lösung zu stolpern. Das vermeidet das Gefühl, als spiele man mit einer mächtigen Maschine mit unbekannten Grundkonzepten.
Wo steckt also der erwähnt Frust?
Die fehlende Auth-Story
Meine Anwendung ist die letzten Tage fleißig gewachsen. Der Serverpart ist noch minimal, ich habe viel ins Frontend gepackt und dafür vue.js eingesetzt, aber dazu vielleicht später mehr. Jetzt wäre der Zeitpunkt, Daten auf dem Server zu speichern. Das bedeutet auch: Eine Nutzerverwaltung einzuführen und diese Nutzer zu authentifizieren. Sie müssen sich registrieren und einloggen können.
Nun war das auch bei Sinatra damals etwas verwirrend. Da war aber das Problem nur, die vorhandenen simplen Beispiele auszuweiten, zu verstehen wie man Nutzer und Passwörter in der Datenbank ablegt und später abgleicht. Wobei ich dann über browserid stolperte, dessen Nachfolger Portier ich heute bevorzugt nutze, was das Problem komplett umgeht.
Bei Roda dagegen stehe ich derzeit vor einer Wand vor Unverständnis. Gegen die Wand habe ich gestern ein paar Stunden mit dem Kopf geschlagen, langsam wackelt sie, ein bisschen Licht scheint durch und ich habe eine vage Ahnung, was meine Optionen sind. Dafür tut mein Kopf weh.
Insgesamt stolperte ich über fünf Möglichkeiten:
- Es gibt rodauth. Das ist ein großes, allumfassendes Authentifizerungssytem, das auch ohne Roda nutzbar wäre. Aber ich finde keine klare Dokumentation. Die Github-Projektseite listet dagegen all die Datenbanksysteme, die ich nutzen könnte (wovon ich keines nehmen will, denn keines ist sqlite) und all die Nutzer und Tabellen, die ich manuell anlegen soll. Vermittelt nicht den Eindruck, als ob das die gesuchte simple Lösung sei.
- Dann gibt es roda-auth. Schreibt direkt:
Also höchstens als Nachschlagequelle geeignet.This is a first stab at integrating Roda and Warden. It is by no means ready for real use.
- Das nächste gem roda-http-auth macht einen Fehler, der gleich wiederkehren wird: Es erklärt nicht was es macht. Das kann irgendwie authentifizieren, mit verschiedenen Methoden – aber es erklärt nicht wie genau. Bedeutet HTTP-Auth, dass der Browser dieses unmögliche eingebaute Login-Fenster öffnen soll? Was können die angeblich unterstützten anderen Schemata? Ist da irgendwas dabei, was tatsächlich direkt nutzbar ist? Ich weiß es nicht, die Seite erklärt es nicht und man findet auch sonst nichts.
- Es gibt ein Beispiel im Wiki: Example: Adding authentication. Das benutzt warden und sequel_secure_password. Ich wollte es erst verwerfen, weil ich sequel nicht einsetzen wollte. Las dann doch nach und stellte fest, dass sequel_secure_password wieder nicht erklärt wie es funktioniert. Irgendwie wird da eine per Magie herbeigezauberte User-Tabelle benutzt, um Passwörter zu authentifizieren. Damit kann ich nichts anfangen.
- Ich gelang zur Erkenntnis: Dir fehlen da Grundlagen, die in dieser Community voraussetzt werden. Wahrscheinlich, wie warden die Auth-Geschichte erschlagen kann. Also schaute ich dort nach, ging durch das gut lesbare Wiki – das wieder genau dann aufhört, wenn die Authentifizierung beginnt. Da sollen dann irgendwelche Strategien reingepackt werden, deren Funktionsweise nicht erklärt wird. Ich fand dann nur Beispiele, die sich durch ihren Hashtyp unterscheiden – und veraltet sind. Wtf.
Tatsächlich fand ich noch eine weitere Art Option: warden-browserid. Ich könnte wahrscheinlich dieses Gem nehmen und in ein Portier-Gem umwandeln, wie ich es für Sinatra auch gemacht habe. Der Vorteil wäre, dass ein solches Modul für eine Rack-Middleware Portier für alle Ruby/Rack-Frameworks einfacher nutzbar machen würde – für mich und andere. Der Nachteil ist, dass ich mich immer noch mit warden und dessen Integration in Roda auseinandersetzen müsste, Zeit verlöre; Das alles könnte ich mir sparen wenn ich statt Roda einfach wieder zu Sinatra wechsle. Da hadere ich noch mit mir.
Roda wirkt nett und als ob es viele Anwendungsfelder abdeckt. Es gibt auch Dokumentation. Aber sie reicht nicht aus. Leider finden sich zu wenige Anleitungen online um diesen Nachteil auszugleichen. Ich vermute, dass es sogar schlicht zu wenige Leute gibt, die Authentifizierung mit Roda umgesetzt haben und außerhalb der rodauth-Lösung des Hauptentwicklers gar nötige Softwarelösungen fehlen. Vielleicht ist auch alles schon da und es fehlen nur die kompletten Erklärungen, wie man sie in seiner Anwendung nutzen kann. So oder so, ich zweifel sehr, ob Roda für mein gerade anlaufendes Projekt die richtige Lösung ist. Man soll nicht zuviele Technologien auf einmal wechseln und wenn Roda doch in der Praxis ganz neue Probleme aufwirft, dann reicht diesmal vue.js im Frontend einzusetzen vielleicht als Neuheit.
PS: Ich stolpere gerade über diese Erklärung, die zwar auch Sequel voraussetzt, aber verständlich ist. Das könnte ich entweder mit Sequel übernehmen oder ohne nachbauen. Schwere Geburt.