Von der Idee zum Prototyp mit Google Firebase und Angular (Teil 2)

In diesem zweiteiligen Artikel stelle ich ein Arbeitsbeispiel vor, das für die Liquid Democracy-Bewegung entstanden ist: In Vorbereitung der Bildungsinitiative Great American Debate soll ein Formular als Web-App entstehen, das Studenten und Freiwillige nutzen können, um für ein Event zum Thema Klimawandel eine Datenbank mit allen im Internet verfügbaren Informationen zu befüllen.

Im ersten Teil des Beitrags habe ich gezeigt, wie wir unsere Web-App grundsätzlich aufsetzen und dafür Google Firebase und Angular nutzen. Nun wollen wir das Formular mit unserem Team und den Testern teilen.

Hosting via Firebase

Dafür greifen wir wieder auf einen Service von Firebase zurück, denn auch das Hosting einer Angular-App kann dort erfolgen. Hierzu bauen wir unsere App für den Produktivbetrieb:

ng build --prod

Nun müssen wir das Firebase-Hosting einrichten:

firebase init

Anschließend stellt uns das System einige Fragen. Diese können wir weitgehend im Standard belassen, wir wählen jedoch auf Nachfrage aus, dass es sich bei unserer App um eine sogenannte Single Page-Anwendung handelt.

Der init-Prozess legt uns jetzt eine Config in den Ordner. Dann laden wir unsere App hoch:

firebase deploy

Damit ist sie unter der von der CLI ausgegebenen Adresse zu erreichen. Das genügt uns aber nicht, denn wir brauchen eine eigene Domain. Hierfür gehen wir in der Firebase-Konsole auf „Hosting“ und fügen eine neue Domain hinzu:

Der nachfolgende Vorgang erfordert die Verifizierung der Domain auf dem DNS-Server. Wenn das abgeschlossen ist, ist unsere App erreichbar. Unseren aktuellen Live-Stand findet man z.B. unter https://statements.canonicaldebate.com. Firebase kümmert sich hier übrigens auch um ein SSL-Zertifikat, sehr praktisch.

Login-Funktionalität und Berechtigungen

Doch da unser Formular nun live ist, haben wir ein weiteres Problem: Jeder kann schreiben! Folglich muss ein Login her. Auch hier leistet uns die Firebase-Anleitung gute Dienste.

Wir brauchen eine einfache Login-Komponente, die uns das An- und Abmelden ermöglicht. In unserem Fall reicht ein Standard-Google-Login, es sind aber eine Vielzahl an Login-Providern möglich.

Unter Umständen müssen wir auch den Google-Provider erst aktivieren:

Wir fügen also einen Login-Button in den Header ein, der durch Firebase den Google-Auth-Flow startet und uns anmeldet:

Der Code dazu findet sich wie erwähnt in der Anleitung oder in unserem GitHub-Repo. Wir können dem Nutzer auch noch ein paar Zusatzinfos sowie einen Logout bieten:

Nun ist dieser Login ganz automatisch bei jeder Firebase-Verbindung enthalten und der User so bei Firebase identifiziert. Das können wir in der Auth-Sektion der Firebase-Konsole sehen:

Anschließend wollen wir der Datenbank mitteilen, dass sie nur angemeldete Nutzer schreiben lassen soll. Dafür bietet Firestore ein sehr praktisches System: Wir können in einer eigenen Design Language unsere Datenbankregeln definieren.

Die folgende Regel begrenzt das Schreiben auf angemeldete Nutzer, Lesen bleibt aber öffentlich:

Fertig? Nicht ganz, denn natürlich möchten wir nicht, dass jeder beliebige Nutzer, der einen Google-Account hat, schreiben darf, sondern nur ausgewählte Mitglieder unseres Teams. Also ist ein kleines Update nötig.

Wir benötigen dazu Rollen, in unserem Fall „Editor“ und „Admin“. Ein Editor kann neue Objekte anlegen und bestehende bearbeiten. Ein Admin darf auch löschen. Für diese Rollen erstellen wir neue Collections in der Datenbank selbst:

Die ID des Editor-Objekts ist jeweils die User-ID aus der Auth-Sektion.

Danach legen wir eine neue Regel an, die den Nutzer auf seine Rolle prüft:

Auch das klappt. Sobald die Regel aktiv ist, kann nur noch ein angemeldeter Nutzer, der zur Editor-Gruppe gehört, schreiben. Prima!

Doch wer genau hinschaut, erkennt ein Problem: Ein Editor kann sich selbst zum Admin machen, was wir natürlich nicht wollen. Folglich müssen wir die Regel noch weiter einschränken:

Leider sind Berechtigungen immer positiv; wir können also nicht verbieten, dass jemand ein Dokument verändert, sondern es nur erlauben. Daher sieht man hier mehrere konkrete Regeln pro Typ. Das könnten wir mit einer anderen Datenstruktur umgehen. Doch uns soll das vorerst genügen, denn wir haben unser Ziel erreicht: Ein Nutzer muss sich nun anmelden und Editor sein, um schreiben zu können.

Für uns steht jetzt nur noch ein Feature aus: eine Option zum Hochladen von Dateien in ein Statement. Dazu nutzen wir den Google Cloud Storage, der direkt mit Firebase funktioniert und uns einen einfachen Datei-Upload ermöglicht.

Bei den letzten Tests sind wir allerdings noch auf eine weitere Limitierung gestoßen: Die Daten in Angular sind live, immerhin ist Firestore ja eine Echtzeit-Datenbank. Wenn also jemand ein Objekt verändert und speichert, werden die Änderungen sofort bei allen anderen Nutzern sichtbar. Dies kann aber auch bedeuten, dass bestehende Felder, die ein User gerade editiert und noch nicht gespeichert hat, überschrieben werden.

Unsere erste Lösung dafür ist ein einfacher Edit-lock-Mechanismus: Wenn jemand ein Objekt editiert, kann er es durch einen Klick sperren. Andere Nutzer können es dann vorerst nicht bearbeiten und müssen das Lock überschreiben. Da eigentlich immer nur ein Nutzer ein Objekt bearbeiten soll, ist das im Moment die einfachste Lösung.

Wie es weitergeht

Die Umsetzung ist bereits im Gange und ich werde den Artikel auch noch aktualisieren, wenn wir fertig sind. An dieser Stelle soll es das erstmal gewesen sein. Für uns heißt es jetzt, die Lösung zu testen und mit ihr zu arbeiten. Die ersten Studenten und Freiwilligen sind bereits angemeldet und werden eingearbeitet. Wie sich die Anwendung verhält, wenn dann ein paar hundert bis tausend Objekte angelegt sind, müssen wir beobachten, doch wir sind zuversichtlich.

Der aktuelle Code ist wie gesagt noch kein Augenschmaus, darum sitzen wir aktuell an einem größeren Refactoring, bevor wir das Locking, den Datei-Upload und ein paar andere kleinere Features angehen.

Wir sind aber soweit zufrieden. Auch wenn es eine gewisse Umstellung erfordert hat und ich mich zudem etwas einarbeiten musste, bin ich von Firebase als Option zum schnellen Umsetzen von Prototypen oder gar von produktiven Apps überzeugt.

Ich habe den aktuellen Stand in ca. drei Tagen gebaut, wobei wahrscheinlich ein bis zwei Tage meiner Einarbeitung bzw. meiner mangelnden Erfahrung mit JavaScript und Firebase geschuldet waren. Alles in allem ist das ein akzeptabler Zeitraum; ich kann nicht versprechen, mit meinen üblichen Technologien schneller zu sein.

Abschließend ist vielleicht noch ein kleiner Kostenüberblick ganz interessant. Im aktuellen Zustand können wir noch ohne Weiteres den kostenfreien Firebase-Tarif nutzen. Sobald das Formular aber produktiv genutzt wird, benötigen wir automatische Backups und vermutlich auch mehr Speicher.

Die Preisliste findet man hier: https://firebase.google.com/pricing. Wir werden auf den Blaze-Tarif (pay as you go) zurückgreifen. Eine grobe Schätzung ergibt für uns ca. 14 USD pro Monat. Das ist nun wirklich kein Vermögen.

Der Großteil des beschriebenen Projekts ist am Wochenende in meiner Freizeit entstanden, doch einige Arbeiten und auch das Erstellen dieses Artikels sind Teil meiner Slacktime gewesen. Ich habe in dieser Zeit viel über eine neue Technologie gelernt und bin begeistert davon, dass es dieses Konzept bei uns gibt.

Falls auch du Interesse an unserer Art zu arbeiten hast: Wir haben diverse offenen Stellen zu besetzen!

Wenn unsere Kunden eigene Projekte mit modernen Google-Lösungen umsetzen wollen – sei es als Prototyp oder als vollwertige Anwendung –, haben wir daran immer Interesse. Dann auch mit vollwertigen Frontend-Entwicklern. 😉

Ihr Partner für Google Cloud

Interessieren Sie sich für moderne Zusammenarbeit und Lösungen mit Google-Technologien? Melden Sie sich bei uns, wenn Sie Fragen haben oder mehr wissen wollen. Wir sind offizieller Google Cloud Partner: Gerne beraten wir Sie unverbindlich zur Einführung, Lizenzierung und produktiven Nutzung von G Suite sowie zur Planung und Umsetzung von Anwendungen in der Google AppEngine oder anderen Umgebungen.

Weiterführende Infos

Serverless Apps mit Firebase Cloud Functions
Java-Anwendungen in der Google App Engine mit CloudSQL
Google Apps Scripts, Clasp und Data Studio
Legacy-Projekte in der Cloud – Erfahrungen mit Kubernetes


Mehr über die Creative-Commons-Lizenz erfahren