Sport. Oder: Die Sucht beginnt wieder.

Wer mich kennt weiß, dass ich den Sport dringend nötig habe. Phasenweise gebe ich dabei dann mal Vollgas, schufte mich ein halbes oder auch ein Dreivierteljahr ab, aber falle dann wieder in ein Loch, das zumindest ein Drittel der errungenen Erfolge zunichte macht. Nun ja, wie das eben so ist.

Zuletzt bin ich auf die Suche nach einem neuen Weg für mich gegangen. Das reine Studio-Workout langweilt mich mittlerweile, was natürlich wieder ein gefundener Grund dafür war, nicht mehr hin zu gehen. Aber letzten Endes macht es mir leider auch wirklich mehr Spaß, wenn ich nicht in einer Butze mit zig anderen Menschen eingesperrt bin. Lieber habe ich ganz ungezwungen Freunde um mich. Oder einfach nur die Natur. Oder eben die gefühlte Freiheit, nicht immer an den selben Ort fahren zu müssen, um den Sport zu machen.

Die erste Idee war, es mit dem Fahrrad zu probieren. Bin ein paar Mal geradelt und fand es super, hab mir natürlich dabei gleich ausgemalt, es zu einem Hobby auszubauen, in das auch Geld gesteckt wird. Ein paar erste Käufe wurden dann auch getätigt. Dabei gibt es aber ein großes Aber: Irgendwie geht die Lust verloren, wenn man sich bei einem Hobby denkt, dass man es eher nicht alleine, sondern primär zu zweit oder zu mehreren machen möchte. Und das verhagelt einem natürlich dann auch einfach der Job der potentiellen Mitstreiter. Langer Rede kurzer Sinn: Das kommt bei mir irgendwie nicht so aus dem Knick, die Lust hält sich nach den ersten terminlichen Rückschlägen arg in Grenzen, auch wenn das Interesse in der Theorie riesig ist. Aber vielleicht hat das ja auch sein gutes, immerhin war ich schon drauf und dran, 1.000+ Euro für ein neues Gefährt einzuplanen. Geld mal nicht auszugeben, ist ja nun auch nicht das schlechteste. Außerdem muss ich zugeben, dass mich das Laufen eigentlich noch mehr reizt, nur fehlt dazu eben die Kondition.

Aus der Gruppendynamik mit den engsten Freunden kristallisierte sich dann das eine oder andere Ziel heraus. Allem voran: Wir wollen Klimmzüge schaffen, die auch nach Klimmzügen aussehen! Ich möchte laufen, ohne mich dabei wie ein Krüppel zu fühlen! Die dringend nötige Gewichtsabnahme verkommt dabei gedanklich fast zum Beiwerk, aber vielleicht ist ja ein konkretes Ziel, das nicht unbedingt nur mit der Waage zu tun hat, auch ein viel bessere Ansporn!

Sei es drum. Diese Ziele, gepaart mit dem Ehrgeiz, das alles alleine auf die Beine zu stellen (also mich wohl), haben nun etwas in mir ausgelöst, das hoffentlich ein wenig länger anhält ;-) Die ersten Schritte weg vom Studio sind dabei auch schon getätigt. Erstes Equipment ist da, das einem die Arbeit etwas erleichtert, bzw. angenehmer gestaltet. Und so langsam muss ich sagen, komme ich wieder in Fahrt. Mal schauen, ob ich die Fortschritte vielleicht auch hier mal dokumentiere. Weiß nur noch nicht, in welcher Form. Vorsichtshalber haben wir zwar schon einmal ein kleines Video des ersten Scheiterns an den Klimmzügen aufgenommen, aber wer weiß, ob ich mich traue, das auch zu zeigen. Schauen wir mal, gell?

Der heutige Workout tat aber schonmal sehr gut und funktionierte gar im Wohnzimmer, ohne sich wie Gymnastik in den 80ern anzufühlen. Und so wie das Wetter aussieht, könnte mich der Sportplatz nachher eventuell auch noch einmal zu Gesicht bekommen. Die Motivation passt – danke, lieber Sommer!

Gleich mal nach der Kündigungsfrist des Studios schauen …

TYPO3 7.x: Branding des Backend-Logins vereinfacht

Im 7er-Zweig von TYPO3 CMS wurde das Branding des Backend-Logins stark vereinfacht.

Anstatt über PHP-Aufrufe, wie es bisher auch schon möglich war, könnt Ihr die nötigen Variablen nun auch direkt im Backend setzen. Dazu müsst Ihr lediglich in den Extension Manager gehen und dort die Konfiguration der Core-Extension backend aufrufen. Hier könnt Ihr dann den Pfad zu einem Logo, eine Highlightfarbe (insbesondere für den Login-Button wichtig) sowie den Pfad zu einem Bild festlegen, das als Fullscreen-Hintergrundbild im Login genutzt wird.

Gespeichert werden diese Daten, wie im Extension Manager üblich, als Konfigurationsvariable in der Datei LocalConfiguration.php. Für mich ist das sehr wichtig, da ich alle meine Projekte über Git versioniere und diese Anpassung darin sauber mit einfließen kann.

TYPO3: Dateien vor nicht eingeloggten Nutzern schützen

Besuchern einer Website einen geschützten Login-Bereich bereitzustellen, ist mit TYPO3 CMS sehr schön und recht einfach lösbar. Was aber in der Natur der Sache liegt ist dabei, dass Datei-Downloads dadurch nicht geschützt werden, da sie ohne PHP-seitige Prüfung der Zugriffsrechte direkt vom Webserver geholt werden. Ein Link, der direkt die Datei aufruft, kann von TYPO3 CMS leider nicht abgefangen werden.

Um das Problem zu lösen, gibt es mehrere Ansätze. Der korrekte Weg ist, die Dateien nicht direkt zu verlinken, sondern stattdessen über PHP-Code, der vorher die Zugriffsrechte prüft, zu „dispatchen“. Eine Extension, die sich genau das auf die Fahne geschrieben hat, ist fal_securedownload. Sie klinkt sich in die FAL-Storages ein und führt vor der Auslieferung die Zugriffsrechteprüfung durch.

Nicht immer jedoch ist es möglich, diese Extension einzusetzen, zum Beispiel, weil die schiere schon bestehende Datenmenge eine Migration schwierig macht. Oder es ist den Aufwand nicht wert, weil die Daten nur rudimentär geschützt werden müssen, aber nicht wirklich kritisch sind.

Eine Notlösung, die leider recht einfach hackbar ist, aber zumindest vor unerlaubtem Zugriff nicht technik-affiner Menschen schützt und bei vielleicht nicht ganz so kritischen Dateien anwendbar ist: Ihr könnt einem Apache2-Webserver auch über die .htaccess-Datei sagen, dass bei Fehlen bspw. eines bestimmten Cookies die angeforderte Ressource nicht ausgeliefert, sondern der Benutzer umgelenkt wird. In folgendem Beispiel nutze ich das, um nur eingeloggten Frontend-Benutzern Dateien auch auszuliefern:

RewriteEngine On
RewriteCond %{HTTP_COOKIE} !^.*fe_typo_user.*$ [NC]
RewriteRule ^ http://www.domain.de [R,L]

Um es noch ein wenig sicherer zu machen, könntet Ihr den Cookie umbenennen. Im Install-Tool im Bereich FE bzw. Frostend findet Ihr zu dem Zweck eine Option, die die Variable für den Cookie-Namen ändert. Das könnte dann zum Beispiel so aussehen:

// /typo3conf/LocalConfiguration.php
$GLOBALS['TYPO3_CONF_VARS']['FE']['cookieName'] = 'diesenCookieNamenKennstDuNicht';

In der .htaccess-Datei ist der Name dann natürlich entsprechend zu ersetzen.

Aber Achtung: Dies sollte keine Lösung sein, auf der man sich bei kritischen Daten ausruht!

Ich bin gespannt, ob jemand Vorschläge hat, wie man dies sicherer lösen kann, ohne den „großen“ Weg über eine Extension zu gehen. Hat da jemand Ideen?

TYPO3: Umgebungskontexte per .htaccess

Wer kennt es nicht? Wenn man eine Website implementiert, benötigt man oft Einstellungen für unterschiedliche Umgebungen. Meist sind das die Entwicklungsversion auf Eurem Rechner, eventuell eine Staging-Version auf einem internen oder externen Server und die Produktiv-Version, in der die Website schlussendlich läuft.

Je nachdem wie Ihr arbeitet, zum Beispiel über ein SCM wie Git, oder über direktes Veröffentlichen via PHP, benötigt Ihr für jede dieser Versionen unterschiedliche Einstellungen. Mindestens sind das in der Regel die Zugangsdaten zur Datenbank, aber auch weitere Konfigurationsvariablen für z.B. ImageMagick sind von Server zu Server unterschiedlich.

Wie also löst man das Umschalten der jeweiligen mit möglichst wenig Aufwand, also ohne, dass man aufpassen muss, dass man auch die richtigen Daten in der jeweiligen Umgebung hat?

Seit Längerem schon liefert TYPO3 CMS die Grundlage dafür mit, verschiedene Setups anhand von Umgebungsvariablen des Webservers auszuliefern.

Hier zeige ich Euch kurz beispielhaft, wofür man es nutzen kann.

Der wichtigste Punkt ist schon auskommentiert als Vorlage in der Datei .htaccess Eurer Installation zu finden:

# Rules to set ApplicationContext based on hostname
#RewriteCond %{HTTP_HOST} ^dev\.example\.com$
#RewriteRule .? - [E=TYPO3_CONTEXT:Development]
#RewriteCond %{HTTP_HOST} ^staging\.example\.com$
#RewriteRule .? - [E=TYPO3_CONTEXT:Production/Staging]
#RewriteCond %{HTTP_HOST} ^www\.example\.com$
#RewriteRule .? - [E=TYPO3_CONTEXT:Production]

Hier müsst Ihr im Prinzip nur Eure Hosts eintragen und es wieder einkommentieren. Ich halte es zum Beispiel so, dass ich auf meinem lokalen Rechner die Entwicklungsversion und auf einem externen Server je eine Staging- und eine Produktionsumgebung betreibe. Die Staging-Version ist für den Demo-Rollout für den Kunden und/oder die Redakteure, und sobald alles abgesegnet ist, geht es in die Produktivumgebung. Das könnt Ihr aber beliebig Euren Anforderungen anpassen. Hier ein Beispiel dessen, wie ich es handhabe:

# Rules to set ApplicationContext based on hostname
RewriteCond %{HTTP_HOST} ^dev\.kundenwebsite\.de$
RewriteRule .? - [E=TYPO3_CONTEXT:Development]
RewriteCond %{HTTP_HOST} ^staging\.kundenwebsite\.de$
RewriteRule .? - [E=TYPO3_CONTEXT:Production/Staging]
RewriteCond %{HTTP_HOST} ^www\.kundenwebsite\.de$
RewriteRule .? - [E=TYPO3_CONTEXT:Production]

Ihr könnt es aber natürlich auch vereinfachen, solltet Ihr nur die Entwicklungs- und die Live-Version haben:

# Rules to set ApplicationContext based on hostname
RewriteCond %{HTTP_HOST} ^dev\.kundenwebsite\.de$
RewriteRule .? - [E=TYPO3_CONTEXT:Development]
RewriteCond %{HTTP_HOST} ^www\.kundenwebsite\.de$
RewriteRule .? - [E=TYPO3_CONTEXT:Production]

Die hiermit gesetzte Umgebungsvariable ist dann für Euch PHP- und damit TYPO3-seitig einfach auswertbar. Ihr könnt also Bedingungen daran knüpfen, sowohl im PHP als auch im TypoScript, welche Umgebung Ihr gerade vor Euch habt.

Regelmäßig nutze ich dies insbesondere für unterschiedliche Einstellungen in der Datei LocalConfiguration.php. Hier werden wie oben angesprochen Zugangsdaten zur Datenbank, aber auch Einstellungen für z.B. ImageMagick abgelegt.

Aber bevor wir fortfahren, stellt sich ein Problem: Die LocalConfiguration.php wird vom Install-Tool von TYPO3 selbst verwaltet. Wenn man also doch noch einmal ins Install-Tool muss, werden die Daten mitunter wieder weggeschmissen und neu überschrieben, ein Context-Switch in dieser Datei ist damit also recht schwierig.

Abhilfe schafft hier, dass TYPO3 CMS für genau solche Fälle anbietet, parallel zu dieser Datei eine Datei namens AdditionalConfiguration.php anzulegen. Diese wird nach Abarbeitung der LocalConfiguration.php automatisch inkludiert und von TYPO3 nicht angefasst, was uns ermöglicht, hier genau die Konfigurationsdetails abzulegen, die sich von Umgebung zu Umgebung unterscheiden.

Da es sich um PHP handelt, könnt Ihr hier also eine einfache if-Abfrage platzieren, die je nach Umgebungsvariable aus der .htaccess-Datei andere Variablen setzt. Dazu fragt Ihr einfach die Variable $_SERVER["TYPO3_CONTEXT"] ab und erhaltet den String zurück, den Ihr in der .htaccess-Datei hierfür gesetzt habt. Hier müsst Ihr aber etwas aufpassen, da je nach Konfiguration des Webservers diese Variable auch mal nur als $_SERVER["REDIRECT_TYPO3_CONTEXT"] verfügbar ist. In meinem gleich folgenden Beispiel berücksichtige ich das. Es beinhaltet wie oben angesprochen zwei Setups mit Variablen für den Datenbankzugriff sowie ImageMagick. Außerdem setze ich nur für die Entwicklungsversion ein paar Einstellungen, die mir beim Debugging helfen:

// /typo3conf/AdditionalConfiguration.php
$context = !empty($_SERVER["TYPO3_CONTEXT"]) ? $_SERVER["TYPO3_CONTEXT"] : $_SERVER["REDIRECT_TYPO3_CONTEXT"];

if ( $context == "Development") {
    \TYPO3\CMS\Core\Configuration\ConfigurationManager::setLocalConfigurationValueByPath('DB/database', "kundenwebsite_local");
    \TYPO3\CMS\Core\Configuration\ConfigurationManager::setLocalConfigurationValueByPath('DB/host', "127.0.0.1");
    \TYPO3\CMS\Core\Configuration\ConfigurationManager::setLocalConfigurationValueByPath('DB/port', 3306);
    \TYPO3\CMS\Core\Configuration\ConfigurationManager::setLocalConfigurationValueByPath('DB/username', "root");
    \TYPO3\CMS\Core\Configuration\ConfigurationManager::setLocalConfigurationValueByPath('DB/password', "root");
    \TYPO3\CMS\Core\Configuration\ConfigurationManager::setLocalConfigurationValueByPath('SYS/displayErrors', "1");
    \TYPO3\CMS\Core\Configuration\ConfigurationManager::setLocalConfigurationValueByPath('SYS/systemLogLevel', 0);
    \TYPO3\CMS\Core\Configuration\ConfigurationManager::setLocalConfigurationValueByPath('GFX/im_path', '/opt/ImageMagick/bin/');
    \TYPO3\CMS\Core\Configuration\ConfigurationManager::setLocalConfigurationValueByPath('GFX/im_path_lzw', '/opt/ImageMagick/bin/');
}

if ( $context == "Production/Staging") {
    \TYPO3\CMS\Core\Configuration\ConfigurationManager::setLocalConfigurationValueByPath('DB/database', "db1");
    \TYPO3\CMS\Core\Configuration\ConfigurationManager::setLocalConfigurationValueByPath('DB/host', "127.0.0.1");
    \TYPO3\CMS\Core\Configuration\ConfigurationManager::setLocalConfigurationValueByPath('DB/port', 3307);
    \TYPO3\CMS\Core\Configuration\ConfigurationManager::setLocalConfigurationValueByPath('DB/username', "username_db1");
    \TYPO3\CMS\Core\Configuration\ConfigurationManager::setLocalConfigurationValueByPath('DB/password', "daspasswort");
    \TYPO3\CMS\Core\Configuration\ConfigurationManager::setLocalConfigurationValueByPath('SYS/displayErrors', "1");
    \TYPO3\CMS\Core\Configuration\ConfigurationManager::setLocalConfigurationValueByPath('SYS/systemLogLevel', 2);
    \TYPO3\CMS\Core\Configuration\ConfigurationManager::setLocalConfigurationValueByPath('GFX/im_path', '/usr/bin/');
    \TYPO3\CMS\Core\Configuration\ConfigurationManager::setLocalConfigurationValueByPath('GFX/im_path_lzw', '/usr/bin/');
}

Ein kleiner Wermutstropfen an der Stelle: TYPO3 CMS arbeitet derzeit so, dass es diese Einstellungen in die lokale LocalConfiguration.php übernimmt. Das ist aber kein Problem, da es nach einem Austausch der Dateien einfach wieder gemacht wird. Man muss lediglich damit leben, dass beim ersten Reload nach Austausch der Dateien die Daten noch nicht stimmen, wodurch ein Fehler geworfen wird. Bei diesem Aufruf aber übernimmt TYPO3 CMS die richtigen Daten, so dass es ab dem zweiten Aufruf dann läuft. Ein Reload zu viel, anstatt jede Datei immer wieder manuell zu synchronisieren.

Wir können also auf diese Art und Weise alle drei Dateien nur ein Mal anfassen und dennoch auf allen Umgebungen lauffähig behalten:

  • .htaccess
  • typo3conf/LocalConfiguration.php
  • typo3conf/AdditionalConfiguration.php

Darüber hinaus gibt es, wie oben angesprochen, auch die Möglichkeit, die Variable via TypoScript auszulesen, um auch hier if-Abfragen zu platzieren. Dies ist insbesondere dann von Vorteil, wenn man das TypoScript über TypoScript-Includes auf Dateiebene versioniert. Ein Beispiel in TypoScript:

[applicationContext = Development,Production/Staging]
config.admPanel = 1

[applicationContext = Production]
config.admPanel = 0

[global]

Zusammenfassung

Über das Setzen und Auswerten einer Umgebungsvariable des Webservers kann man sich das Leben beim Synchronhalten mehrerer Server sehr stark erleichtern und TYPO3 CMS bringt die dafür notwendigen Vorkehrungen mit.

Getestet und laufen habe ich das mit mehreren Installationen auf Apache2-Webservern, die jeweils TYPO3 CMS in Version 6.2 bis 7.6 fahren. Von 6.2 LTS bis 7.6 LTS gibt es hier auch keinerlei mir bekannte Unterschiede.

Rails: Aktivitäten-Logging leicht gemacht mit public_activity

Dieses schöne Stück Software habe ich gestern in unsere Agentur-Software eingebaut: public_activity. Leichter kann einem das Loggen von Aktivitäten wirklich nicht gemacht werden. Vom Namen lässt man sich dabei am Besten nicht irritieren.

Meine Quick-and-dirty-Lösung für eine _default.html.slim sieht ungefähr so aus:

= t("public_activity.key.#{activity.key}", default: "%{model} #%{id} %{key}.", \
    model: t("activerecord.models.#{activity.trackable_type.underscore}"), \
    id: activity.trackable.id, \
    key: "public_activity.key.#{activity.key.split('.')[1]}" \
  ).html_safe