Handbuch für Administratoren
Dieses Handbuch richtet sich an Benutzer in der Rolle des Administrators, die camindo CMS einrichten und betreuen: die Struktur der Inhalte, Websites und Sprachen, Benutzer und Rechte, Medienverarbeitung und die Übertragung von Strukturen. Installation, Updates und Serverbetrieb (Kapitel 1 und 12) sind meist Sache des Systemadministrators.
Wer camindo CMS zum ersten Mal einrichtet, liest am besten zuerst Kapitel 2 – Das Konzept. Es erklärt die Ideen, auf denen das System aufbaut, und endet mit einem Leitfaden für die ersten Schritte.
Die tägliche Arbeit mit Inhalten – Suchen, Bearbeiten, Stapelverarbeitung, Export und Import – beschreibt das Handbuch für Anwender.
Inhalt
- camindo CMS installieren – Voraussetzungen, Installer, Webserver, Cronjobs, Zusatzkomponenten
- Das Konzept – Inhaltsbereiche statt Datenbanktabellen, bereichsübergreifende Abfragen, Verknüpfungen, mehrere Websites, Template-Sätze, Strukturen kopieren; Leitfaden für die ersten Schritte
- Instanzen und Sprachen – Websites, Domains, Startseite, Sprachversionen
- Struktur: Ordner und Inhaltsbereiche – Bereichstypen, Baupläne, Einstellungen, Bereiche kopieren und löschen
- Eingabefelder – Feldtypen, Darstellung, Eingabeprüfung, Mehrsprachigkeit, Verknüpfungen, Dateien, Volltext, Metafelder, Typ ändern
- Templates verwalten – Template-Bereiche, Zuweisung, Dateisystem, Listen-Templates
- Benutzer und Rechte – Benutzer, Benutzergruppen, Modul-, Instanz-, Sprach- und Bereichsrechte, Owner
- Medien – Prozessoren, Konverter, Thumbnail-Felder, Uploads
- Strukturen exportieren und importieren – Strukturbäume kopieren, Entwicklung übertragen, Template-Sätze weitergeben
- Weitere Module – Status, Snippets (Frontend- und Backend-Snippets), Zeitplaner, Werkzeuge, Logdateien, Audit-Log, Komponenten, Papierkorb, PDF, KI-Assistent
- Extensions – Editoren und Eingabehilfen für Felder
- Betrieb und Wartung – Cronjobs, Papierkorb, Sicherung, Updates, Kommandozeile, Konfiguration, Betriebshinweise
- Community-Funktionen – Registrierung, Anmeldung, Beiträge von Frontend-Usern, geschützte Dateien, Datenexport und Löschen
- Sicherheit, Datenschutz und Betrieb – für Entscheider – Sicherheitsüberblick, Backup und Wiederherstellung, Sicherheitsupdates, Meldeweg (security.txt), DSGVO, Audit-Log, Aufgaben des Betreibers
- Datenschutz – welche personenbezogenen Daten von Benutzern, Website-Usern und Besuchern wo und wie lange gespeichert werden, Kürzen der IP-Adressen, Lösch-Policies, Datenexport personenbezogener Daten, Checkliste
1 camindo CMS installieren
Diese Schnellstart-Anleitung fasst zusammen, was zur Inbetriebnahme von camindo CMS nötig ist. Wenn Sie camindo CMS produktiv einsetzen, lesen Sie bitte alle Kapitel, insbesondere das Kapitel Betrieb und Wartung.
Was Sie brauchen
Einen Server (oder Rechner) mit Shell-Zugang (SSH oder Terminal) und darauf:
| Was | Version | So prüfen Sie es |
|---|---|---|
| PHP | 8.3 oder neuer, mit den Erweiterungen mysqli, intl, gd, json, mbstring |
php -v und php -m |
| MySQL oder MariaDB | MySQL 8 / MariaDB 10.6 oder neuer | mysql --version |
| Apache | 2.4 mit mod_rewrite und AllowOverride All |
apachectl -M \| grep rewrite |
| Composer | 2.x | composer --version |
| Git | beliebig | git --version |
| optional: ImageMagick, ffmpeg, mysqldump | – | which magick ffmpeg mysqldump |
- ImageMagick – Bildversionen lassen sich auch mit der in PHP eingebauten GD-Bibliothek berechnen; ImageMagick unterstützt aber sehr viel mehr Formate (etwa HEIC, TIFF, PSD) und Einstellungen.
- ffmpeg wird für die Umwandlung von Videos und Audiodateien und für Standbilder aus Videos benötigt.
- mysqldump wird für Datenbanksicherungen benötigt – vor Updates und durch den Zeitplaner.
Die Schritte im Überblick
- Datenbank anlegen
- Dateien holen – der Installer startet automatisch
- Installer-Fragen beantworten
- Webserver einrichten und Dateirechte setzen
- Cronjobs einrichten
- Im Backend anmelden
Schritt 1 – Datenbank anlegen
Halten Sie die Zugangsdaten für eine leere Datenbank bereit. Beim Hoster legen Sie sie im Kundenmenü an; auf einem eigenen Server zum Beispiel so:
mysql -u root -p
CREATE DATABASE camindo CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
CREATE USER 'camindo'@'localhost' IDENTIFIED BY 'EIN-SICHERES-PASSWORT';
GRANT ALL PRIVILEGES ON camindo.* TO 'camindo'@'localhost';
FLUSH PRIVILEGES;
EXIT;
Unter MariaDB heißt die Sortierung utf8mb4_uca1400_ai_ci (ab 10.10), bei älteren
Versionen utf8mb4_unicode_ci. Die Installation passt die Tabellen selbst an den
Server an; einen Index für die Suche in Listenfeldern, den nur MySQL kennt, lässt sie unter
MariaDB weg.
camindo CMS braucht die Zeitzonentabellen des Datenbankservers. Die offiziellen
Docker-Images von MySQL und MariaDB bringen sie mit, Pakete der Linux-Distributionen oft
nicht. Fehlen sie, warnen Installation und php Core/cron/camindo.php status; laden Sie
sie dann einmalig als Datenbank-Administrator:
mariadb-tzinfo-to-sql /usr/share/zoneinfo | mariadb -u root -p mysql
Unter MySQL heißt das Programm mysql_tzinfo_to_sql, der Client mysql.
Schritt 2 – Dateien holen
Wechseln Sie in das Verzeichnis, in dem das CMS installiert werden soll (hier
/var/www), und lassen Sie Composer das Projekt anlegen:
cd /var/www
composer create-project camindo/project mysite
mysite ist der Name des neuen Projektverzeichnisses und frei wählbar.
Composer lädt das Grundgerüst (composer.json, public/, leere Verzeichnisse), den
Core nach Core/ und die Bibliotheken nach vendor/. Anschließend startet
automatisch der Installer. Falls er nicht startet oder Sie ihn abgebrochen haben:
cd /var/www/mysite
php Core/cron/camindo.php install
Schritt 3 – Der Installer
Der Installer prüft zuerst die Voraussetzungen und markiert jede Zeile mit [ok],
[--] (fehlt, ist aber optional) oder [!!] (fehlt – der Installer bricht ab):
requirements
[ok] PHP >= 8.3 (8.4.22)
[ok] PHP extension mysqli
[ok] PHP extension intl
[ok] writable: var
[--] magick: not found
...
Dann stellt er Fragen. In eckigen Klammern steht die Vorgabe – Enter übernimmt sie.
| Frage | Ihre Eingabe |
|---|---|
Database host [localhost] |
meist Enter; beim Hoster steht der Host in den Zugangsdaten |
Database port [3306] |
Enter |
Database name [camindo] |
Name Ihrer Datenbank |
Database user [camindo] |
Name Ihres Datenbank-Benutzers |
| Database password | das Passwort (wird nicht angezeigt). Danach prüft der Installer sofort die Verbindung; schlägt sie fehl, nennt er den Grund und fragt die Datenbank-Angaben erneut ab |
Time zone [Europe/Berlin] |
Ihre Zeitzone |
Locale [de_DE] |
Land/Sprache für Datums- und Zahlenformate |
Will the site be served over HTTPS? [y] |
Enter, wenn die Seite über https:// läuft. n nur für einen lokalen Test ohne SSL – siehe Lokal ohne HTTPS testen |
Admin name [admin] |
Ihr Anmeldename im Backend (Kleinbuchstaben, Ziffern, _, -) |
| Admin password | nach der Passwort-Richtlinie (standardmäßig mindestens 12 Zeichen mit Groß- und Kleinbuchstaben und einem Sonderzeichen), zweimal eingeben |
| Admin e-mail | Ihre E-Mail-Adresse (darf leer bleiben, wird aber für den Anmelde-Code benötigt) |
Backend language (ar_SA|bn_BD|de_DE|en_US|…) [en_US] |
de_DE für ein deutsches Backend. Zur Wahl stehen ar_SA, bn_BD, de_DE, en_US, es_ES, fr_FR, hi_IN, ja_JP, ko_KR, pt_BR, ur_PK, zh_CN; die Sprache lässt sich später in den persönlichen Einstellungen ändern |
Danach läuft alles automatisch: Schlüsseldatei, Konfiguration, Verzeichnisse,
Datenbanktabellen, Ihr Benutzerkonto (Superuser), Caches.
Am Ende steht:
finish
var/install.lock written
Der Installer läuft nur einmal. Ein erneuter Aufruf meldet „already installed“ und tut nichts.
Drei Dateien im Projektverzeichnis sind jetzt wichtig:
| Datei | Inhalt | Wenn sie verloren geht |
|---|---|---|
.camindo.php |
Konfiguration (Datenbank, Pfade, E-Mail) | neu anlegen mit install --step=config |
.camindo.key |
Schlüssel für verschlüsselte Felder und Passwörter | nicht ersetzbar – ohne ihn sind verschlüsselte Inhalte verloren. Bitte Kopie an einem sicheren Ort aufbewahren! |
.sqlpwd |
Passwort für mysqldump |
neu anlegen mit install --step=sqlpwd |
Alle drei Dateien erhalten die Rechte 0600, nur ihr Eigentümer kann sie lesen. Das passt,
wenn Kommandozeile und Webserver unter demselben Benutzer laufen – bei den meisten
Hosting-Angeboten mit eigenem PHP-Benutzer je Kunde ist das so. Führen Sie den Installer
dagegen als root aus (etwa in einem Docker-Container oder mit sudo), übergibt er die
Dateien an den Webserver-Benutzer: an den mit --web-user=NAME genannten (oder in
der Umgebungsvariablen CAMINDO_WEB_USER), sonst an den Eigentümer des
Projektverzeichnisses. Ist keiner von beiden bekannt, gehören die Dateien root, und der
Installer warnt – holen Sie die Übergabe dann mit
php Core/cron/camindo.php install --step=key --web-user=NAME nach.
Passwörter und Schlüssel aus diesen Dateien können alternativ auch in Umgebungsvariablen stehen, wenn Ihr Server das anbietet; mehr dazu siehe Zugangsdaten aus Umgebungsvariablen.
Schritt 4 – Webserver einrichten
Die Website liegt nicht direkt im Projektverzeichnis, sondern in dessen
Unterverzeichnis public/. Das ist Absicht: Alles, was der Browser nicht sehen
darf (Konfiguration, Schlüssel, Code), liegt eine Ebene höher.
Apache-VirtualHost (z. B. /etc/apache2/sites-available/mysite.conf):
<VirtualHost *:80>
ServerName example.com
DocumentRoot /var/www/mysite/public
<Directory /var/www/mysite/public>
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/mysite-error.log
CustomLog ${APACHE_LOG_DIR}/mysite-access.log combined
</VirtualHost>
sudo a2enmod rewrite
sudo a2ensite mysite
sudo systemctl reload apache2
Beim Hoster stellen Sie im Kundenmenü das Zielverzeichnis der Domain (oft „Document
Root“ oder „Webroot“) auf mysite/public. HTTPS richten Sie wie gewohnt ein (Let's
Encrypt, Zertifikat des Hosters) – camindo CMS braucht dafür nichts Besonderes.
Zur Sicherheit liegt im Projektverzeichnis selbst eine .htaccess mit Zugriffssperre:
Zeigt die Domain versehentlich auf das Projektverzeichnis statt auf public/, beantwortet
Apache jede Anfrage mit 403. Die Website unter public/ ist davon nicht betroffen, weil
deren eigene .htaccess die Sperre aufhebt. Löschen Sie die Datei nicht.
Lokal ohne HTTPS testen
camindo CMS ist ab Werk auf HTTPS eingestellt: Die Anmelde-Cookies für das Backend
und für Frontend-User werden nur über verschlüsselte Verbindungen gesendet
(cookie_secure). Über eine reine http://-Adresse verwirft der Browser diese
Cookies – die Anmeldung scheitert dann, und der Anmeldedialog weist darauf hin.
Wenn Sie camindo CMS nur auf Ihrem Rechner ausprobieren und kein Zertifikat einrichten wollen:
-
Beantworten Sie im Installer die Frage Will the site be served over HTTPS? mit
n(oder rufen Sie ihn mit--https=nauf). Der Installer schreibt dann in.camindo.php:'admin' => [ 'cookie_secure' => false, ], 'user' => [ 'cookie_secure' => false, ],Ist der Installer schon mit
ygelaufen, tragen Sie diese beiden Werte selbst in.camindo.phpein. -
Bevor die Installation erreichbar wird – auf einem Server, im Firmennetz, für Kollegen – richten Sie HTTPS ein und setzen beide Werte auf
true(oder löschen die beiden Zeilen, dann gilt die Vorgabetrue). Ohne diese Einstellung gehen Sitzungs-Cookies unverschlüsselt über das Netz und können mitgelesen werden.
Chrome und Firefox behandeln
http://localhost(auchhttp://mysite.localhost) wie eine sichere Verbindung. Wer lokal unter diesen Adressen testet, kommt deshalb meist auch mitcookie_secure = truezurecht – Safari und andere Adressen (http://mysite.test, IP-Adressen im Netz) nicht.
Dateirechte: Der Webserver (meist Benutzer www-data) muss in var/ und
public/media/ schreiben dürfen, sonst nirgends:
sudo chown -R www-data:www-data /var/www/mysite/var /var/www/mysite/public/media
Haben Sie den Installer als anderer Benutzer ausgeführt, gehören diesem auch die
Cache-Dateien unter var/cache/ – der Befehl oben korrigiert das.
Schritt 5 – Cronjobs
Öffnen Sie die Crontab des Webserver-Benutzers
sudo crontab -u www-data -e
und tragen Sie eine Zeile ein:
* * * * * /usr/bin/php /var/www/mysite/Core/cron/cron.php >/dev/null 2>&1
cron.php ist der einzige Cronjob. Er prüft jede Minute, was zu tun ist: Manches läuft
minütlich (Template-Änderungen übernehmen, Bilder und Videos umwandeln), alles andere
sind Aufgaben des Zeitplaners. Die Installation richtet
dort die Wartungsaufgaben ein – nachts zwischen 2 und 4 Uhr verteilt: Datenbank-
Backup, Papierkorb leeren, Lösch-Policies und Aufbewahrungsfristen anwenden, Logs und
Frontend-Cache aufräumen, Volltext aktualisieren, Audit-Log prüfen, nach Updates suchen;
temporäre Dateien stündlich. Zeiten und Fristen passen Sie im Zeitplaner an (siehe
Betrieb). Ohne den Cronjob findet keine Wartung statt.
Schritt 6 – Anmelden
- Backend:
https://example.com/backend/– mit dem Namen und Passwort aus Schritt 3 (lokal ohne SSL:http://…/backend/, siehe Lokal ohne HTTPS testen). - Frontend:
https://example.com/– meldet zunächst, dass noch keine Inhalte eingerichtet sind.
Wie es im Backend weitergeht, beschreibt das Kapitel Das Konzept mit einem Leitfaden für die ersten Schritte.
Zusatzkomponenten installieren
Zusatzmodule, Medien-Prozessoren und Extensions sind Composer-Pakete. Es sind immer zwei Schritte:
- Composer legt die Dateien ab,
- camindo CMS richtet die Datenbank ein:
cd /var/www/mysite
composer require camindo/module-pdf
php Core/cron/camindo.php component install Pdf --activate
Was installiert und aktiv ist, zeigt php Core/cron/camindo.php component list – oder
das Modul „Komponenten“ im Backend.
Wenn etwas schiefgeht
| Symptom | Ursache und Abhilfe |
|---|---|
| Browser zeigt „camindo is not installed yet“ | Der Installer ist nicht durchgelaufen → php Core/cron/camindo.php install |
requirements not met |
Fehlende PHP-Erweiterung oder fehlendes Schreibrecht → die [!!]-Zeile nennt es |
database connection failed |
Host, Name, Benutzer und Passwort prüfen → beim Hoster ist der Host oft nicht localhost |
| Backend lädt ohne Gestaltung (CSS/JS fehlt) | public/backend/assets fehlt oder ist veraltet → php Core/cron/camindo.php upgrade kopiert die Dateien neu |
| Fehler 500 im Frontend | .htaccess fehlt oder AllowOverride ist nicht All → ist mod_rewrite aktiv? |
| „503 – Wartung“ nach einem Update | → php Core/cron/camindo.php upgrade ausführen (Datenbank nachziehen) |
| Anmeldung scheitert ohne Fehlermeldung, im Anmeldedialog steht ein Hinweis zu HTTPS |
Sie rufen das Backend über http:// auf, cookie_secure ist aber true → siehe Lokal ohne HTTPS testen |
| Anmelde-Code kommt nicht an | → E-Mail-Postfach in .camindo.php einrichten (siehe Betrieb) |
| Fehler 500 im Frontend und im Backend, auf der Kommandozeile: CONFIGURATION ERROR:.camindo.key exists but is not readable |
Der Benutzer, unter dem Webserver bzw. Cronjob laufen, darf die Schlüsseldatei nicht lesen – meist, weil der Installer oder ein Schlüsselwechsel als root lief → php Core/cron/camindo.php status nennt die betroffenen Dateien; als root übergibt install --step=key --web-user=NAME sie an den Webserver-Benutzer (sonst chown; kann der Webserver die Datei auf Ihrem System nur über die Gruppe lesen, chmod 640). camindo CMS weicht in diesem Fall bewusst nicht auf die Umgebungsvariable CAMINDO_KEY aus. Dasselbe gilt für .camindo.key.retired |
| Fehler 500 im Frontend und im Backend, auf der Kommandozeile: CONFIGURATION ERROR:paths.key_file -file not found |
Die Schlüsseldatei .camindo.key fehlt. Holen Sie sie aus Ihrer Datensicherung zurück – nicht neu erzeugen: install --step=key schriebe einen neuen Schlüssel, verschlüsselte Inhalte und Passwörter wären dann unbrauchbar. Kommt der Schlüssel aus der Umgebungsvariablen CAMINDO_KEY, prüfen Sie, ob sie für Webserver und Cronjob gesetzt ist |
| Etwas anderes | → php Core/cron/camindo.php status zeigt den Zustand des Systems; var/log/ enthält die Details |
Einzelne Schritte des Installers lassen sich wiederholen, ohne die Datenbank
anzufassen: php Core/cron/camindo.php install --step=dirs (ebenso key, config,
sqlpwd, runtime).
Updates beschreibt das Kapitel Betrieb und Wartung.
2 Das Konzept
Dieses Kapitel erklärt die Ideen, auf denen camindo CMS aufbaut. Wer sie kennt, richtet eine Website schneller und sauberer ein – und nutzt Möglichkeiten, die andere Systeme nicht bieten.
Inhaltsbereiche statt Datenbanktabellen
In vielen Content-Management-Systemen und Webanwendungen braucht jede neue Art von Inhalt – Produkte, Termine, Filialen, Stellenanzeigen – eine eigene Datenbanktabelle, eigene Eingabemasken und eigenen Programmcode. Jede Änderung der Struktur ist ein Auftrag an einen Entwickler.
camindo CMS geht einen anderen Weg. Sie legen im Backend Inhaltsbereiche an und geben ihnen Eingabefelder – beliebig viele, in beliebiger Kombination, jederzeit erweiterbar, auch während die Website in Betrieb ist. An der Datenbank ändert sich dabei nichts, und es wird keine Zeile programmiert.
Jeder Inhaltsbereich bekommt dabei automatisch alles, was zur Pflege seiner Inhalte nötig ist:
- eine Eingabemaske mit Eingabeprüfung, Pflichtfeldern und Hilfetexten,
- eine Suchmaske mit Platzhaltern, Vergleichsoperatoren und Volltextsuche,
- eine sortierbare Datensatzliste,
- Stapelverarbeitung, CSV-, DOCX- und XML-Export und -Import,
- Mehrsprachigkeit je Feld, Arbeitskopien, Bearbeitungssperren und Papierkorb,
- Zugriffsrechte je Benutzergruppe,
- und den Zugriff aus den Templates mit Filtern, Sortierung und Blätterfunktion.
Die Felder sind dabei keine bloßen Textschnipsel: Jedes Feld hat einen Typ – Text, Ganzzahl, Währungsbetrag, Datum mit Zeitzone, Datei, Verknüpfung und viele mehr. Der Typ bestimmt, wie eine Eingabe geprüft, gespeichert, sortiert und durchsucht wird. Intern liegt jeder Typ in einer eigenen, indizierten Tabelle; Filtern und Sortieren bleiben dadurch auch bei großen Datenmengen schnell.
Beispiel – ein Veranstaltungskalender:
| Inhaltsbereich | Eingabefelder |
|---|---|
| Veranstaltungen | Titel, Beginn, Ende, Beschreibung, Bild, Eintritt (Währungsbetrag), Ort (Verknüpfung), Rubriken (Verknüpfung) |
| Orte | Name, Adresse, Anfahrt, Karte (Datei) |
| Rubriken | Bezeichnung, Farbe |
Drei Inhaltsbereiche, eine halbe Stunde Einrichtung – und die Redaktion kann arbeiten.
Ein Feldname, eine Bedeutung: über Bereiche hinweg filtern
Feldnamen gelten in camindo CMS systemweit: Ein Name ist immer an denselben Typ
gebunden. Legen Sie in den Bereichen „Meldungen“, „Veranstaltungen“ und „Blog“ jeweils
ein Feld datum vom Typ „Datum + Uhrzeit“ an, ist datum überall dasselbe Merkmal.
Das eröffnet eine besondere Möglichkeit: Templates können mehrere Inhaltsbereiche gemeinsam abfragen, filtern und sortieren, als wären sie eine Tabelle. Eine Zeitleiste aus Meldungen, Veranstaltungen und Blogbeiträgen ist ein einziger Befehl:
(CMS:SELECT zeitleiste_eintrag
filter[area]=meldungen,veranstaltungen,blog
filter[datum] >= 2026-01-01
sort=datum
order=desc
limit=20
)
Ebenso findet eine Suche nach filter[schlagwort]=… die passenden Datensätze in allen
Bereichen, die ein Feld schlagwort haben. Zusätzlich hat jeder Datensatz ein
Hauptfeld (meist Titel oder Name), über das Listen und Verknüpfungen ihn
bereichsübergreifend benennen können – ohne zu wissen, wie das Feld im einzelnen
Bereich heißt.
Empfehlung: Geben Sie Feldern mit derselben Bedeutung in allen Bereichen
denselben Namen (titel, datum, text, bild, slug) und Feldern mit
unterschiedlicher Bedeutung unterschiedliche Namen. Diese Namenskonvention zahlt sich
aus, sobald Templates Inhalte zusammenführen.
Reservierte Namens-Präfixe
Folgende Präfixe sind für einen Feldtyp reserviert. Die Verwendung kann helfen, Typenkonflikte zu vermeiden, erschwert aber das nachträgliche Ändern eines Feldtyps (Feld muss dann erst umbenannt werden):
| Präfix | Typ |
|---|---|
| bit_ | bit |
| chr_ | chars |
| chr_ | currency |
| chr_ | datetime |
| dec_ | decimal |
| enc_ | encrypted |
| fil_ | file |
| flt_ | float |
| ftx_ | fulltext |
| rid_ | id |
| ids_ | ids |
| int_ | integer |
| jsn_ | json |
| pwd_ | password |
| rel_ | pointer, relation, link |
| txt_ | text |
| tim_ | time |
| tsl_ | timestampl |
Verknüpfen statt mehrfach pflegen
Was an mehreren Stellen vorkommt, wird einmal als eigener Datensatz angelegt und verknüpft: der Autor mit seinem Foto, der Ort mit seiner Adresse. Eine zentrale Änderung genügt – alle Seiten, mit denen der Datensatz verknüpft ist, werden aktualisiert.
camindo CMS kennt dafür mehrere Arten von Verknüpfungen:
| Art | Beispiel |
|---|---|
| Verknüpfung, beidseitig (n:m) | Artikel ↔ Schlagwörter: der Artikel kennt seine Schlagwörter, das Schlagwort seine Artikel |
| Verknüpfung, beidseitig (n:1) | Artikel → Hauptrubrik: genau eine Rubrik je Artikel |
| Verweis, einseitig (n:m bzw. n:1) | „Verwandte Artikel“, auch aus mehreren Bereichen |
| Fest verknüpfte Inhalte (1:n) | Text-Bild-Blöcke einer Seite: gehören exklusiv zu ihrem Datensatz und werden mit ihm kopiert, verschoben und gelöscht |
| Eingebettete Inhalte | wie fest verknüpfte Inhalte, aber direkt in der Eingabemaske des Datensatzes bearbeitet – ein flexibler Seitenbaukasten |
Templates können Datensätze über ihre Verknüpfungen abfragen und nach Feldern verknüpfter Datensätze sortieren – etwa Artikel nach dem Namen ihres Autors.
Hierarchien
Bekommt ein Inhaltsbereich das Metafeld „Eltern-Datensatz“, werden seine Datensätze zu einem Baum: Seiten mit Unterseiten, Kategorien mit Unterkategorien. Templates können ganze Teilbäume oder einzelne Ebenen abfragen – die Grundlage für Navigationen und Brotkrumenpfade. Unabhängig davon ordnen Ordner die Inhaltsbereiche selbst im Backend übersichtlich an.
Mehrere Websites und Sprachen
Eine Installation kann beliebig viele Websites betreiben, jede als eigene Instanz mit Domains, Sprachen und Startseite. Jeder Inhaltsbereich gehört einer Instanz.
Instanzen können Lesezugriff auf andere Instanzen erhalten und dadurch gemeinsame Inhalte auf unterschiedlichen Websites nutzen, während andere Inhalte streng an eine Domain gebunden bleiben – hilfreich etwa für Projekte mit mehreren Subdomains oder Filialen eines Unternehmens.
Jede Instanz hat eine Hauptsprache und beliebig viele weitere Sprachen. Mehrsprachig wird nur, was übersetzt werden muss: Sie entscheiden über Mehrsprachigkeit je Feld. Fehlt eine Übersetzung, springt die Hauptsprache ein – Feld für Feld. Die Website ist so in jeder Sprache vollständig, während die Übersetzung noch läuft.
Templates: gekapselte Funktionalität
Templates geben die Inhalte aus. Sie bestehen aus der Gestaltung (HTML, CSS,
JavaScript) und aus CMS-Befehlen, die Inhalte einsetzen und Aufgaben übernehmen:
Datensätze abfragen und filtern, Blätterfunktionen generieren, Bildversionen erstellen,
Formulare auswerten und Datensätze daraus speichern, Besucher registrieren und anmelden,
Warenkörbe verwalten oder PDF-Dokumente erzeugen.
Beim Speichern übersetzt camindo CMS jedes Template in PHP. Zur Laufzeit gibt es keinen Interpretationsaufwand. CMS-Befehle und PHP lassen sich optimal kombinieren.
Ein Template kann andere Templates einbinden. So entstehen in sich geschlossene Bausteine mit einer klaren Aufgabe: eine Artikelliste mit Blätterfunktion, ein Formular, das Einsendungen als Datensätze speichert, ein Mitgliederbereich mit Registrierung, Anmeldung und Passwort-Reset.
Template-Sätze
Ein Template-Satz ist ein solcher Baustein im Großen: die Templates einer Funktion zusammen mit den Inhaltsbereichen, die sie brauchen – etwa ein News-Modul mit den Bereichen „Meldungen“ und „Rubriken“ und den Templates für Übersicht, Detailseite, Archiv und RSS-Feed.
Ein Template-Satz wird importiert und ist direkt betriebsbereit. Individuell anpassen können Sie alles.
Template-Sätze werden über den XML-Export generiert. Die Option „Templates für Import in Fremddatenbank optimieren“ sorgt dafür, dass Verknüpfungen zwischen Templates, Bereichen, Datensätzen beim Import in eine andere Installation angepasst werden (siehe Kapitel 9).
Strukturen kopieren und weitergeben
Weil Inhaltsbereiche Einstellungen sind und keine Programmierung, lassen sie sich kopieren und übertragen:
- Bereich kopieren – eine Kopie eines Inhaltsbereichs mit allen Eingabefeldern und Template-Zuweisungen, aber ohne Datensätze.
- Baupläne – vorbereitete Vorlagen für neue Bereiche (etwa „Artikel“, „Mitglieder“, „Kommentare“) legen Bereich und Felder in einem Schritt an.
- XML-Export und -Import – ganze Strukturbäume mit Ordnern, Inhaltsbereichen, Eingabefeldern, Templates und auf Wunsch allen Datensätzen und Dateien. Damit übertragen Sie eine Entwicklung von der Testumgebung auf die Live-Website, vervielfältigen eine bewährte Website-Struktur für eine neue Instanz, geben Template-Sätze weiter oder sichern einzelne Bereiche.
Details in Kapitel 9.
Sicherheit im Redaktionsalltag
- Arbeitskopien: Bearbeitet wird immer eine Kopie. Die Website sieht Änderungen erst nach dem Speichern, vollständig und auf einmal.
- Bearbeitungssperren verhindern, dass zwei Personen denselben Datensatz gleichzeitig ändern.
- Papierkorb: Gelöschtes lässt sich (i. d. R. bis 7 Tage nach Löschung) wiederherstellen. Später lassen sich Änderungen über das Audit-Log rekonstruieren.
- Rechte: Benutzer sehen nur die Module, Websites, Bereiche und Sprachen, die für ihre Benutzergruppe freigegeben sind. Schreib- und Löschrechte lassen sich bis hin auf einzelne Datensätze steuern.
- Verschlüsselte Felder: Passwortfelder lassen sich von niemandem einsehen, verschlüsselte Inhalte können nur im Backend oder, sofern freigegeben, in geschützten Website-Bereichen eingesehen werden.
- Anmeldung: Zwei-Faktor-Anmeldung und Verhinderung des Durchprobierens von Passwörtern schützen sowohl im Backend als auch auf der Website.
Leitfaden: die ersten Schritte
Nach der Installation richten Sie eine Website in dieser Reihenfolge ein:
- Sprachen prüfen und bei Bedarf anlegen – Modul „Sprachen“.
- Instanz anlegen: Name, Haupt-Domain, Hauptsprache und weitere Sprachen – Modul „Instanzen“.
- Inhaltsbereiche anlegen, am besten in Ordnern gruppiert, und ihre Eingabefelder definieren – Modul „Struktur“.
- Template-Bereich anlegen und die Templates schreiben oder einen Template-Satz importieren; den Inhaltsbereichen ihr Standard-Template zuweisen – siehe Kapitel 6.
- In der Instanz die Startseite festlegen (Start-Datensatz und Start-Template).
- Für Bildversionen und Vorschaubilder Medienkonverter einrichten und den Upload-Feldern Thumbnail-Felder hinzufügen – Kapitel 8.
- Benutzergruppen und Benutzer für die Redaktion anlegen – Kapitel 7.
- Betrieb absichern: Cronjobs, Datenbanksicherung, E-Mail-Versand.
3 Instanzen und Sprachen
Instanzen
Eine Instanz ist eine Website: ein Frontend mit eigenen Domains, Sprachen und Inhalten. Eine camindo-Installation kann beliebig viele Instanzen betreiben – etwa verschiedene Filialen einer Hauptstelle, mehrere Websites eines Konzerns. Inhalte und Templates gehören zu einer Instanz und sind dadurch an ihre Domains gebunden. Darüber hinaus können gemeinsame Bereiche definiert werden, mit Inhalten, die für mehrere Instanzen zugänglich sind und unter allen ihren Domains erscheinen dürfen.
Keine Mandantenfähigkeit
Die Abgrenzung von Inhalten hat Grenzen: camindo CMS bietet keine echte Mandantenfähigkeit.
Eine sichere Trennung von Mandanten (etwa konkurrierende Firmen-Websites) wird nur mittels
separater camindo-Installationen erreicht, mit eigener Datenbank und eigenem public/- und var/-Verzeichnis.
Die Standard-Instanz
Nach der Installation gibt es eine Standard-Instanz im Modul „Instanzen“. Sie fängt alle Aufrufe auf, deren Domain keiner anderen Instanz zugeordnet ist. Ihre Hauptsprache ist nach der Installation Englisch (en_US). Sie lässt sich ändern, aber nicht löschen. Wenn Sie nur eine Website mit camindo CMS verwalten, können Sie diese Instanz dafür verwenden. Wenn Sie mehrere Websites verwalten, legen Sie für jede Website eine eigene Instanz an.
Weil sie alle übrigen Domains auffängt, steht die Standard-Instanz in allen Listen und Auswahlen des Backends immer an letzter Stelle – unabhängig von ihrer Position.
Einstellungen einer Instanz
| Einstellung | Bedeutung |
|---|---|
| Label | Name der Instanz im Backend |
| Position nach... | Die Reihenfolge im Backend wird geändert durch die Auswahl der vorangehenden Instanz. Die Standard-Instanz steht immer am Ende und ist als Vorgänger nicht wählbar |
| Frontend-Sprachen | |
| Haupt-Sprache | Sprache, die bei fehlender Übersetzung einspringt; bei einer neuen Instanz ist en_US vorausgewählt |
| Weitere Sprachen | zusätzliche Sprachversionen; die Reihenfolge wird im Backend beibehalten und kann auch im Frontend verwendet werden |
| Frontend-Domains | |
| Haupt-Domain | die eigentliche Adresse der Website, ohne Protokoll, z. B. www.example.com |
| Frontend-Protokoll | https oder http |
| Kanonische Aufrufe | leitet jeden Aufruf, der nicht über die Haupt-Domain und die gültige Adresse eines Datensatzes kommt, dauerhaft (301) dorthin um – auch die Startseite: Bei mehreren Sprachen führt sie auf die Startseite der Sprache (/de_DE/, ohne Sprachkürzel in der Adresse nach der Browsersprache), bei einer Sprache auf /. Für Suchmaschinen empfohlen |
| Weitere Domains | Aufrufe über diese Domains landen ebenfalls in dieser Instanz, z. B. example.com ohne www. Mit dem Schalter „RegEx“ gilt ein Eintrag als regulärer Ausdruck, etwa um alle Subdomains abzufangen: *\.camindo\.de |
| Zugriff | |
| Lesbare andere Instanzen | Inhalte der ausgewählten Instanzen sind im Frontend dieser Instanz abrufbar – etwa ein gemeinsamer Produktkatalog für mehrere Websites |
| Startseite | |
| Start-Datensatz | Datensatz, dessen Inhalte auf der Startseite zur Verfügung stehen |
| Start-Template | Template, mit dem die Startseite ausgegeben wird |
| Script-Policy (CSP) | |
| Script-Policy | „Vorgabe“ (Einstellung security.frontend_csp, sonst aus), „Aus“, „Nur melden“ oder „Durchsetzen“. Details siehe unten |
| Weitere Script-Quellen | Adressen fremder Scripts, die laufen dürfen, je Zeile eine, z. B. https://www.googletagmanager.com oder *.example.com |
| Nachgeladene Scripts erlauben | Scripts, die ein erlaubtes Script nachlädt (Tag-Manager, Widgets), laufen ebenfalls |
| Formularziele beschränken / Weitere Formularziele | Formulare dürfen nur an die eigene Website und die genannten Adressen gehen (z. B. den Zahlungsanbieter) |
Die Startseite lässt sich erst nach dem ersten Speichern wählen – vorher hat die Instanz noch keine Inhalte.
Medien-Dateien einer Instanz werden nur über ihre eigenen Domains und die Domains der Instanzen ausgeliefert, die sie lesen dürfen. So lassen sich Bilder einer Website nicht über die Adresse einer anderen abrufen.
Script-Policy
Die Script-Policy (Content Security Policy) ist eine Schranke im Browser: Es laufen nur die Scripts von der eigenen Domain und aus den eingetragenen externen Quellen. Gelangt über einen Inhalt – einen Kommentar, einen importierten Text – Script-Code in eine Seite, führt der Browser ihn nicht aus.
Gehen Sie in zwei Schritten vor:
- „Nur melden“: zum Testen – alle Scripts werden ausgeführt, aber der Browser meldet,
was er blockieren würde. Die Meldungen stehen im Modul „Logdateien“ unter
csp. Rufen Sie die wichtigsten Seiten auf (Startseite, Produkt, Warenkorb, Kasse, Kundenkonto) und prüfen Sie das Protokoll. - „Durchsetzen“: für den produktiven Betrieb, wenn alle Meldungen beseitigt sind.
Meldet das Protokoll fremde Scripts, die Sie brauchen (Zahlungsanbieter, Karten, Statistik),
tragen Sie deren Adresse als Script-Quelle ein. Jedes Script im Template braucht die Nonce
der Seite (
<script(CMS:NONCE)>), Scripts direkt im HTML (onclick="…") baut der Template-Programmierer um. Der Template-Editor und das Widget „Template-Meldungen“ auf der Startseite weisen auf Scripts ohne Nonce hin.
Neue Instanzen stehen auf „Vorgabe“: Sie übernehmen die Einstellung
security.frontend_csp der Konfiguration, ohne diese gilt „aus“. Die Konfiguration ist
nur diese Vorgabe – eine Instanz, bei der Sie „Aus“, „Nur melden“ oder „Durchsetzen“
gewählt haben, behält ihren Modus. Für eine Staging-Umgebung bietet sich
security.frontend_csp = 'report' an, wenn die Instanzen dort auf „Vorgabe“ stehen.
Adressen im Frontend
Die Adresse eines Datensatzes besteht aus der Domain, bei mehrsprachigen Websites dem Sprachkürzel und dem Slug oder der Nummer des Datensatzes (record_id):
https://www.example.com/betriebsfeier-2026
https://www.example.com/en/summer-party-2026
https://www.example.com/1758
Fehlt das Sprachkürzel, wählt camindo CMS die Sprache nach der Spracheinstellung des
Browsers (Accept-Language). Ist diese nicht als Frontend-Sprache eingerichtet, wird
die Hauptsprache der Instanz angezeigt.
Die Adresse aus dem Sprachkürzel (ohne Slug oder record_id) führt auf die Startseite
(beispielsweise https://www.example.com/en). Gibt es unter einer Adresse keinen
Datensatz, antwortet die Website mit dem Status 404. Datensätze haben nur einen Slug,
wenn das Feld slug im Inhaltsbereich eingerichtet ist; siehe
Kapitel 5.
Jeder Inhaltsbereich kann einen zusätzlichen Slug-Prefix bereitstellen. Dieser
steht dann vor dem Slug seiner Datensätze (/en/events/summer-party-2026) und kann je
Sprache unterschiedlich lauten. Mehr dazu in Kapitel 4.
Instanz kopieren und löschen
„Kopieren“ öffnet eine Eingabemaske, in der die Angaben der zu kopierenden Instanz bereits eingetragen sind – ohne Domains, Startseite und Inhalte. Inhaltsbereiche, Templates und Datensätze werden nicht mitkopiert. Dies können Sie per XML-Export und -Import auf Wunsch nachholen.
Achtung: Beim Löschen einer Instanz werden alle ihre Inhaltsbereiche, Eingabefelder, Datensätze und Templates endgültig mitgelöscht. Instanzen haben keinen Papierkorb. Die Rückfrage nennt, wie viele Elemente betroffen sind.
Sprachen
Im Modul „Sprachen“ legen Sie die Sprachen an, die den Instanzen zur Verfügung stehen. Nach der Installation sind diese Sprachen bereits angelegt:
- العربية (ar_SA)
- বাংলা (bn_BD)
- 简体中文 (zh_CN)
- Deutsch (de_DE)
- English (en_US)
- Español (es_ES)
- Français (fr_FR)
- हिन्दी (hi_IN)
- 日本語 (ja_JP)
- 한국어 (ko_KR)
- Português (pt_BR)
- اردو (ur_PK)
Weitere Sprachen können nachinstalliert werden – siehe unten.
| Einstellung | Bedeutung |
|---|---|
| Sprach- oder Locale-Code | Kürzel der Sprachversion, erscheint in der Adresse, z. B. de, de_DE oder de_AT. Eine Variante wie de_AT passt auch zu Browsern, die nur de anfordern |
| Backend-Sprache | Sprache der Snippets (Textbausteine) dieser Sprachversion, z. B. de_DE – sie gilt auch für Meldungen der CMS-Befehle im Frontend. de_DE und de_AT als Frontend-Sprachen teilen sich so dieselben Textbausteine (siehe Backend-Snippets) |
| Label / Label (Landessprache) | Name der Sprache, einmal in der Sprache des Backends („German“), einmal in der eigenen Sprache („Deutsch“) – für Sprachumschalter |
| Zeitzone | Zeitzone, in der Datums- und Zeitangaben dieser Sprachversion auf der Website erscheinen. Leer: die Zeitzone der Konfiguration |
| Position nach... | Reihenfolge |
Sprachen einer Instanz ändern
- Neue Sprache hinzufügen: Mehrsprachige Inhalte der Instanz erhalten die neue Sprachversion. Bis zur Übersetzung springt die Hauptsprache ein.
- Sprache aus einer Instanz entfernen: Alle Inhalte der Instanz in dieser Sprache werden endgültig gelöscht: Texte, Zahlen, Datumsangaben, Volltexte, Datenschutz-Vorlagen und die Dateien mehrsprachiger Felder. Verknüpfungen und die Inhalte der übrigen Sprachen bleiben erhalten. Beim Speichern erscheint die Maske zunächst noch einmal mit einem Warnhinweis, der die wegfallenden Sprachen nennt – erst ein zweiter Klick auf „Speichern“ entfernt sie. Wechseln Sie gleichzeitig die Haupt-Sprache, zeigen nicht übersetzte Dateien danach die Datei der neuen Haupt-Sprache.
- Sprache löschen: Die Inhalte der Sprache werden in allen Instanzen gelöscht, wie beim Entfernen aus einer Instanz. Vor dem Löschen nennt camindo CMS die Instanzen, die die Sprache verwenden. Ist sie irgendwo Haupt-Sprache, lässt sie sich nicht löschen – wählen Sie dort zuerst eine andere Haupt-Sprache.
Wie Felder mehrsprachig werden, beschreibt Kapitel 5.
4 Struktur: Ordner und Inhaltsbereiche
Im Modul „Struktur“ legen Sie fest, welche Inhalte camindo CMS verwaltet: Sie richten Ordner und Inhaltsbereiche ein und definieren deren Eingabefelder. Das Konzept dahinter beschreibt Kapitel 2.
Die Bereichsliste
Das Modul zeigt alle Ordner und Bereiche in ihrer Baumstruktur, bei mehreren Instanzen gruppiert nach Instanz. „Neu“ legt einen Ordner oder Bereich an, „Suche“ filtert die Liste.
Ausgegraut erscheinen abhängige Bereiche – etwa die Text-Bild-Blöcke einer Seite. Diese Bereiche sind im Modul „Inhalte“ nicht direkt zugänglich. Ihre Datensätze werden direkt über die Eingabemaske des Datensatzes bearbeitet, zu dem sie gehören (siehe Kapitel 5).
Bereichstypen
Beim Anlegen wählen Sie zuerst, was der Bereich enthalten soll:
| Typ | Symbol | Inhalt |
|---|---|---|
| RECORD | Inhaltsbereich für Datensätze aller Art. Die Eingabefelder fügen Sie selbst hinzu | |
| PROFILE | Profile registrierter Frontend-User – siehe Kapitel 13 | |
| UGC | Beiträge, die angemeldete Frontend-User auf der Website anlegen – siehe Kapitel 13 | |
| TEMPLATE | Template-Bereich für Seitenlayouts (HTML), PHP-Code und CMS-Befehle – siehe Kapitel 6 | |
| FOLDER | Ordner, der mehrere Bereiche zusammenfasst |
Für RECORD-, PROFILE- und UGC-Bereiche bietet die Auswahl zusätzlich Baupläne an: fertige Vorlagen, die den Bereich mit passenden Eingabefeldern anlegen.
| Bauplan | Typ | Felder |
|---|---|---|
| Artikel | RECORD | Titel, Datum, Teaser, Text und Bild |
| Mitglieder | PROFILE | Name, E-Mail (Anmeldename) und Passwort |
| Kommentare | UGC | Name und Kommentartext |
Die Felder eines Bauplans sind ein Ausgangspunkt – Sie können sie danach beliebig ändern und ergänzen.
Eigene Baupläne
Eigene Baupläne legen Sie als XML-Dateien im Verzeichnis var/area_blueprints/
der Installation ab; die Auswahl beim Anlegen zeigt sie zusammen mit den
mitgelieferten an. Dafür brauchen Sie Zugriff auf das Dateisystem des Servers.
So entsteht ein Bauplan:
- Richten Sie einen Bereich mit den gewünschten Einstellungen und Eingabefeldern ein.
- Exportieren Sie nur diesen Bereich mit der Option „Struktur exportieren“, ohne Inhalte (siehe Kapitel 9).
- Entpacken Sie die Zip-Datei und speichern Sie die XML-Datei als
var/area_blueprints/{name}.xml, z. B.var/area_blueprints/termine.xml.
Regeln:
- Der Dateiname ohne
.xmlist der Name des Bauplans: Buchstaben, Ziffern, Unterstrich und Minus. Heißt eine Datei wie ein mitgelieferter Bauplan (article,member,comment) und hat sie denselben Typ, ersetzt sie diesen. - Unter welchem Typ der Bauplan erscheint (RECORD, PROFILE oder UGC), bestimmt der Bereich in der Datei. Andere Typen erscheinen nicht.
- In der Auswahl steht das Label des Bereichs als Überschrift und sein
Hinweis darunter. Beides darf ein Text oder ein Snippet-Verweis sein
(
#label_articles) – ein Verweis erscheint in der Sprache des Benutzers. Die Beschriftungen der Felder werden beim Anlegen in der Sprache des Benutzers übernommen. - Ausgewertet wird nur der erste Bereich der Datei, Datensätze darin werden ignoriert. Label und Hinweis des neuen Bereichs bleiben leer und werden in der Maske eingegeben; Name, Icon und Sortier-Richtung kommen aus der Datei.
- Felder vom Typ Verknüpfung, Verweis oder Fest verknüpfte Inhalte, deren Zielbereich der Bereich selbst ist – etwa „Verwandte Artikel“ in einem Artikel-Bereich –, zeigen im neuen Bereich auf den neuen Bereich. Ziele in anderen Bereichen (etwa ein Verweis auf einen Bilder-Bereich) lassen sich nicht auflösen: Das Feld wird ohne diesen Zielbereich angelegt; tragen Sie ihn nach dem Anlegen in den Einstellungen des Feldes nach.
Sichern Sie var/area_blueprints/ zusammen mit den übrigen Projektdaten
(siehe Kapitel 12).
Einstellungen eines Inhaltsbereichs
| Einstellung | Bedeutung |
|---|---|
| Name | interner Name für die Templates, z. B. artikel – Kleinbuchstaben, Ziffern und Unterstrich, beginnend mit einem Buchstaben. Templates sprechen Bereiche über diesen Namen an, nicht über ihre Nummer; ein Bereich lässt sich so neu anlegen oder umziehen, ohne Templates zu ändern |
| Icon | Symbol im Backend, auswählbar über eine Suche |
| Label | Name des Bereichs im Backend |
| Instanz | Website, zu der der Bereich gehört. Seine Datensätze gehören zur selben Instanz |
| Eltern-Ordner, Vorangehendes Element | Platz im Bereichsbaum |
| Hinweis | erscheint über der Datensatzliste – möglichst kurz halten. Ein Snippet-Verweis (#custom.schluessel) erscheint wie bei der Bezeichnung in der Sprache des Benutzers |
| Haupt-Feld | Feld, das den Datensatz in Listen und Verknüpfungen vertritt (meist Titel oder Name) – erst nach dem Anlegen der Felder wählbar |
| Standard-Sortierung, Sortier-Richtung | Reihenfolge der Datensätze in der Datensatzliste und Vorgabe für Templates |
| Mehrsprachige Eingabe | „Alle Sprachen auf einer Seite“ oder „Ein Reiter je Sprache“ – wie die Eingabemaske mehrsprachige Felder zeigt. Ein neuer Bereich startet mit „Ein Reiter je Sprache“ |
| Datensätze je Seite | Anzahl der Datensätze, die die Datensatzliste auf einer Seite zeigt; zwischen den Seiten wird geblättert. 0 zeigt alle Datensätze auf einer Seite. Vorgabe für neue Bereiche ist der Wert aus admin.skiplist_default (siehe Kapitel 12); ein leeres Feld verwendet ebenfalls diesen Wert |
| Slug-Prefix | optionaler erster Teil der Adresse aller Datensätze des Bereichs, je Sprache (siehe unten) |
| Lösch-Policy | Regel, nach der Datensätze und Audit-Logs dieses Bereichs behandelt werden; vgl. Kapitel 15. Die Policy gilt für jedes Löschen – im Backend, über die API und mit CMS:USER_DELETE im Frontend. Vorgewählt ist die Standard-Policy zum Bereichstyp („Datensatz löschen“, „Profil löschen“, „User-Generated-Content löschen“) |
| Abhängiger Bereich | Die Datensätze gehören exklusiv je einem Datensatz eines anderen Bereichs (siehe Fest verknüpfte Inhalte). Der Bereich erscheint dann nicht in der Bereichsliste des Moduls „Inhalte“ |
| Standard-Template | Template, mit dem jeder Datensatz des Bereichs im Frontend ausgegeben wird, solange im Datensatz kein anderes gewählt ist |
| Wählbare Templates | Templates, die Redakteure im Datensatz alternativ wählen dürfen (Metafeld „Gestaltungsvorlage“) |
| URL-Override-Templates | Templates, die über die Adresse eines Datensatzes anstelle des zugewiesenen aufgerufen werden dürfen – etwa die Druckversion eines Inhalts oder die Ausgabe in einem anderen Format (/meldungen,xml_rss) |
| Übersichts-Template | Template, das aufgerufen wird, wenn die Adresse nur aus dem Slug-Prefix besteht (/de/termine) – eine Übersicht des Bereichs ohne Datensatz, etwa die Liste aller Termine. Ohne Übersichts-Template ergibt diese Adresse „Seite nicht gefunden“. Mit Übersichts-Template und Slug-Prefix erhält der Bereich die Schaltfläche „Vorschau“ (siehe Übersichts-Templates) |
| Listen-Template (Backend) | nur für das Backend: formatiert je Datensatz eine zusätzliche letzte Spalte der Datensatzliste; etwa einen direkt angezeigten RGB-Farbwert |
| Trigger-Templates | Templates, die bei Ereignissen der Datensätze aufgerufen werden und PHP-Code ausführen – beim Speichern, Löschen, Wiederherstellen und bei den Aktionen der Lösch-Policy (siehe Handbuch für Template-Programmierer). Sie können mehrere zuweisen; sie laufen nacheinander in der angezeigten Reihenfolge, die Sie mit den Pfeil-Schaltflächen ändern |
| Zugriff für Benutzergruppen | Erscheint nur beim Anlegen eines neuen Bereichs: welche Benutzergruppen den neuen Bereich nutzen dürfen; später im Reiter „Zugriff“ änderbar. |
PROFILE- und UGC-Bereiche haben zusätzliche Einstellungen für die Anmeldung auf der Website (siehe Kapitel 13).
Slug-Prefix
Ein Inhaltsbereich kann den Adressen seiner Datensätze ein Präfix voranstellen. Damit dürfen gleichnamige Slugs in verschiedenen Bereichen einer Instanz vorkommen:
| Bereich | Slug-Prefix | Slug | Adresse |
|---|---|---|---|
| Farben | farben |
blau |
/farben/blau |
| Farben | farben |
andere/rot |
/farben/andere/rot |
| Orte | – | bayern/schwabing |
/bayern/schwabing |
| Orte | – | rot |
/rot |
- Das Präfix ist ein einzelner Teil der Adresse – ohne Schrägstrich. Slugs der Datensätze dürfen dagegen Schrägstriche enthalten.
- Es wird je Sprache der Instanz eingegeben (alle Sprachen untereinander); eine leere Sprache übernimmt das Präfix der Hauptsprache.
- Ordner und Template-Bereiche haben kein Präfix. Beim Kopieren eines Bereichs wird es nicht übernommen.
- Die Adresse aus dem Präfix allein (
/de/termine) zeigt das Übersichts-Template des Bereichs, wenn eins zugewiesen ist.
Die Adresse als Ganzes muss eindeutig sein – innerhalb der Instanz und der Instanzen, die über „Lesbare Instanzen“ mit ihr zusammengeschaltet sind:
- Zwei Bereiche können nicht dasselbe Präfix führen.
- Ein Datensatz eines Bereichs ohne Präfix darf nicht mit einem Präfix beginnen:
der Slug
farben/gelbim Bereich Orte wird beim Speichern abgelehnt („'farben/' ist ein reservierter Slug-Prefix von Inhaltsbereich …“). - Ein Präfix setzen, ändern oder entfernen lehnt camindo CMS ab, wenn dadurch zwei Datensätze dieselbe Adresse hätten oder vorhandene Adressen mit dem neuen Präfix beginnen – die Meldung nennt den betroffenen Datensatz.
Wird eine Adresse aufgerufen, prüft camindo CMS zuerst, ob ihr erster Teil das Präfix eines Bereichs ist, und sucht den Rest dann nur dort; sonst den ganzen Pfad in den Bereichen ohne Präfix. Links erzeugen Templates mit CMS:URL – das Präfix kommt dabei automatisch hinzu.
Die Reiter eines Bereichs
Die Detailansicht eines Bereichs hat die Reiter:
- „Einstellungen“ – die Einstellungen oben, mit „Bearbeiten“, „Kopieren“ und „Löschen“;
- „Eingabefelder“ – die Felder des Bereichs (siehe Kapitel 5);
- „Zugriff“ – welche Benutzergruppen den Bereich lesen, schreiben und löschen dürfen (siehe Kapitel 7);
- „Datensätze“ bzw. „Templates“ – die Inhalte des Bereichs.
Bereich kopieren
„Kopieren“ legt einen neuen Bereich mit allen Einstellungen an – bei Inhaltsbereichen samt allen Eingabefeldern, Standard- und Sortierfeld und Template-Zuweisungen. Datensätze und Templates werden nicht kopiert, der Slug-Prefix ebenfalls nicht. Beschriftungen, die auf Snippets der Instanz verweisen, bleiben Verweise – bei einer Kopie in eine andere Instanz kommen die Snippets in deren Set. In der Eingabemaske vergeben Sie Label, Name, Instanz und Platz im Baum der Kopie. Nach dem Speichern zeigt camindo CMS die Detailansicht der Kopie.
Verweist ein Verknüpfungsfeld des Originals auf den Bereich selbst (etwa „Verwandte Artikel“), verweist es in der Kopie auf die Kopie. Verknüpfungen zu anderen Bereichen bleiben bestehen; beidseitige Verknüpfungen erhalten dort ein neues Gegenfeld.
Ganze Ordner mit Bereichen, Templates und Inhalten kopieren Sie per XML-Export und -Import.
Bereiche und Ordner löschen
Ein Inhaltsbereich wird samt seinen Datensätzen gelöscht, ein Template-Bereich samt seinen Templates; die Rückfrage nennt die Anzahl. Beim Löschen eines Ordners wählen Sie, ob die enthaltenen Bereiche mitgelöscht oder eine Ebene nach oben gerückt werden.
Gelöschte Bereiche kommen wie Datensätze in den Papierkorb und werden erst nach der Aufbewahrungsfrist endgültig entfernt (siehe Kapitel 12). Bis dahin kann ein Superuser sie wiederherstellen – mit allen Unterbereichen, Datensätzen und Eingabefeldern, die mit ihnen gelöscht wurden.
Mit einem Bereich gehen auch die Verknüpfungsfelder anderer Bereiche in den Papierkorb, die auf ihn verweisen – sie würden sonst ins Leere zeigen. Beim Wiederherstellen des Bereichs kommen sie mit zurück (siehe Eingabefeld löschen).
Die Datensätze eines gelöschten Bereichs gehen mit ihm in den Papierkorb und werden nach einigen Tagen endgültig gelöscht. Die Lösch-Policy des Bereichs wirkt dabei mit den Blöcken für den Auslöser „Bereich wurde gelöscht“ (siehe Kapitel 15), die Fristen gerechnet ab dem Löschen – mit den Standard-Policies wird der Verlauf im Audit-Log nach 1 Jahr gelöscht. Ist es ein Profil-Bereich, werden die Beiträge der User sofort nach ihren eigenen Policies gelöscht (Auslöser „UGC: Profil wurde gelöscht“) – das macht eine Wiederherstellung des Bereichs nicht rückgängig.
Instanzen
Betreiben Sie mehrere Instanzen, gehört jeder Teilbaum einer Instanz: Ein Bereich kann nur in einem Ordner derselben Instanz stehen. Wechselt ein Bereich die Instanz, ziehen seine Datensätze, Templates und Mediendateien mit.
5 Eingabefelder
Die Eingabefelder eines Inhaltsbereichs pflegen Sie im Modul „Struktur“. Wählen Sie einen Bereich aus und wechseln Sie in den Reiter „Eingabefelder“. Die Liste zeigt jedes Feld mit Name, Label, Typ und drei Schaltern für die Sichtbarkeit. Die Sichtbarkeit lässt sich direkt in der Liste umschalten:
| Schalter | Das Feld erscheint … |
|---|---|
| Eingabe | in der Eingabemaske |
| Suche | in der Suchmaske |
| Liste | als Spalte der Datensatzliste |
Die Reihenfolge der Felder in der Liste ist auch ihre Reihenfolge in der Maske. „Neu“ legt ein Feld an. Klick auf ein Feld öffnet seine Detailansicht mit „Bearbeiten“, „Kopieren“, „Löschen“ und „Typ ändern“.
Feldtypen
Beim Anlegen wählen Sie, was das Feld speichern soll:
| Gruppe | Typ | Speichert |
|---|---|---|
| Text | Kurzer Text | bis 255 Zeichen; optimal für Sortierung und Suche (Titel, Namen, Kennungen) |
| Langer Text | Fließtext bis 16 Millionen Zeichen | |
| Verschlüsselter Text | Text bis 16 Millionen Zeichen, verschlüsselt gespeichert; Suche nur nach exakter Übereinstimmung (siehe unten) | |
| Text mit Mehrfachauswahl | mehrere Werte aus einer festen Liste (Checkboxen) | |
| Volltext | sammelt den Text anderer Felder für die Volltextsuche (siehe unten) | |
| Passwort | nicht umkehrbar verschlüsselt (gehasht) | |
| Datum / Zeit | Datum + Uhrzeit, zeitzonenabhängig | Zeitpunkt mit Umrechnung zwischen Zeitzonen (Termine, Veröffentlichungen) |
| Datum + Uhrzeit | Datum und Uhrzeit ohne Umrechnung (Geburtstage, Stichtage) | |
| Uhrzeit | Uhrzeit ohne Umrechnung (Öffnungszeiten) | |
| Zahl | Ganzzahl | ganze Zahlen |
| Bit | zwei Zustände: 0 oder 1 (Schalter) | |
| Währungsbetrag | Betrag mit genau 2 Nachkommastellen, exakt ohne Rundungsverluste | |
| Fließkommazahl | hohe Genauigkeit, minimale Rundungsdifferenzen möglich | |
| Exakte Dezimalzahl | bis zu 10 Vor- und 10 Nachkommastellen, exakt | |
| Verknüpfung | Verknüpfung (bidirektional, n:1) | genau ein Datensatz eines anderen Bereichs, z. B. die Hauptrubrik |
| Verknüpfung (bidirektional, n:m) | mehrere Datensätze eines anderen Bereichs, z. B. Schlagwörter | |
| Verweis (unidirektional, n:1) | einseitiger Verweis auf genau einen Datensatz | |
| Verweis (unidirektional, n:m) | einseitiger Verweis auf mehrere Datensätze, z. B. „Verwandte Artikel“ | |
| Fest verknüpfte Inhalte (1:n) | exklusiv zugeordnete Inhalte, z. B. Text-Bild-Blöcke | |
| Eingebettete Inhalte (1:n) | wie oben, bearbeitet in der Maske des Datensatzes | |
| Datei | Datei-Upload | Upload-Feld für Dateien |
| Dateiversion (Thumbnail) | automatisch erzeugte Version einer hochgeladenen Datei – generiertes Vorschaubild, verkleinertes Video … (siehe Kapitel 8) | |
| Meta-Information | Veröffentlichungsdatum, Ablaufdatum, Gestaltungsvorlage, Status, Prüfung nötig, Eltern-Datensatz, Position | Metafelder, siehe unten |
Wählen Sie den Typ mit Bedacht – er bestimmt, wie Eingaben geprüft, sortiert und durchsucht werden.
Zahlen in einem Textfeld sortieren alphabetisch (10 vor 9),
ein Datum im Textfeld lässt sich nicht nach Zeiträumen filtern.
Die folgende Liste der Eingabefelder variiert je nach Feldtyp:
Name, Label und Hilfetexte
| Einstellung | Bedeutung |
|---|---|
| Name | interner Name, wird für die Templates benötigt, z. B. titel. Beginnt mit einem Kleinbuchstaben, danach Kleinbuchstaben, Ziffern und _ (siehe Namensregeln) |
| Darstellungstyp | siehe unten |
| Position nach... | Auswahl des vorangehenden Feldes (Reihenfolge) |
| Label | Beschriftung in Eingabe-, Suchmaske und Liste |
| Anmerkung | erscheint unter dem Label |
| Tooltip | erscheint beim Zeigen auf das Label |
| Prefix, Suffix | erscheinen links bzw. rechts vom Eingabefeld, z. B. „€“ oder „cm“ |
| Breite, Höhe | Größe des Eingabefelds |
| Sichtbarkeit | Einstellung, ob das Feld in der Eingabemaske, Suchmaske und Datensatzliste erscheint. |
| Hauptfeld | Das Feld vertritt den Datensatz in Listen und Verknüpfungen (eines je Bereich) |
| Mehrsprachig | siehe unten |
Schaltfläche „Snippets“ : In den Eingabefeldern „Label“, „Anmerkung“
und „Tooltip“ können Sie statt eines Textes den Namen eines Snippets angeben,
angeführt von #, etwa #label_file. Der Text erscheint dann in der jeweiligen Sprache des
Backend-Benutzers. Ein Klick auf die Schaltfläche erlaubt eine Suche über alle registrierten Snippets.
Für übliche Feld- und Bereichsnamen bringt camindo CMS die Übersetzungen in allen Backend-Sprachen schon mit – ein eigenes Snippet ist dafür nicht nötig. Beispiele:
#label_customers, #label_profiles, #label_comments, #label_products, #label_articles, #label_shopitems, #label_categories, #label_tags, #label_pages, #label_news, #label_events, #label_contacts, #label_text_image_blocks, #label_documents, #label_downloads, #label_files, #label_images, #label_media, #label_videos, #label_title, #label_subtitle, #label_teaser, #label_text, #label_description, #label_author, #label_date, #label_price, #label_document, #label_file, #label_image, #label_link, #label_icon, #label_url
Etwa #label_customers als Label des Bereichs „Kunden“: Das Gegenfeld einer
Verknüpfung übernimmt die Beschriftung des Bereichs und erscheint dann ebenfalls
übersetzt.
Feldinhalt
| Einstellung | Bedeutung |
|---|---|
| Standardwert | Wert, der bei neuen Datensätzen in der Eingabemaske voreingetragen wird (Vorgabewert). Bei Datumsfeldern sind auch Datumsfunktionen erlaubt, siehe unten |
| Aufbereitung | Der im Datensatz eingegebene Wert wird entsprechend der angehakten Regeln aufbereitet („Whitespace trimmen“ entfernt Leerzeichen am Anfang und Ende, „HTML-Tags entfernen“ lässt nur reinen Text übrig) |
Datumsfunktionen
Bei Datums- und Zeitfeldern darf der Standardwert eine Datumsfunktion sein. Sie wird beim Speichern des Datensatzes ausgewertet:
| Standardwert | ergibt |
|---|---|
now, today |
jetzt bzw. heute 0:00 Uhr |
now+2h, today+7d, today-1d |
mit Versatz in Sekunden (s), Minuten (m), Stunden (h) oder Tagen (d) |
UTC_TIMESTAMP(), UTC_DATE(), UTC_TIME() |
aktueller Zeitpunkt, Tag bzw. Uhrzeit in Weltzeit |
NOW(), CURRENT_TIMESTAMP(), CURDATE(), CURTIME() |
dasselbe in der Zeitzone der Datenbank |
Darstellungstyp
Der Darstellungstyp bestimmt, wie das Feld in der Maske erscheint:
| Darstellungstyp | für |
|---|---|
| Einzeilige / Mehrzeilige Texteingabe | Text, Zahl, Datum |
| E-Mail-, Telefon-, Passworteingabe | kurzer Text bzw. Passwort |
| Dropdown (Einfachauswahl), Radiobuttons | Verknüpfungen, Text, Zahl |
| Dropdown (Mehrfachauswahl), Checkboxen | Verknüpfungen, Texte (JSON-Array) |
| Switch (an/aus) | Bit (0 oder 1) |
| Lookup-Feld | Verknüpfungen – sobald der Zielbereich viele Datensätze hat |
| Eingebettet | Inhalte, die exklusiv zum Datensatz gehören |
| Upload-Feld | Dateien |
| Dateiversion | Vorschau-Bilder, verkleinerte Videos |
Bei Auswahllisten (Dropdown, Radiobuttons, Checkboxen) tragen Sie die Optionen in das Feld „Standardwert“ ein – eine Option je Zeile. Die erste Option ist der Vorgabewert. Soll kein Vorgabewert eingetragen werden, fügen Sie am Anfang einen Zeilenumbruch ein (leere Zeile).
Eingabeprüfung
| Einstellung | Wirkung |
|---|---|
| Pflichtfeld | Das Feld darf nicht leer bleiben |
| Nicht Null | Zahlenfelder dürfen nicht 0 sein |
| Minimum / Maximum | Bei Texten die Länge, bei Zahlen und Datumsangaben der Wert, bei Verknüpfungen und Mehrfachauswahl die Anzahl. Der Vergleichsoperator legt fest, ob die Grenze selbst erlaubt ist (>=) oder nicht (>) |
| RegEx | eigenes Prüfmuster als regulärer Ausdruck, z. B. [A-Z]{2}-[0-9]{4} für Artikelnummern wie „AB-1234“ |
| Wert einmalig im Inhaltsbereich | kein anderer Datensatz des Bereichs darf denselben Wert haben |
| Wert einmalig in der Datenbank | kein anderer Datensatz der Installation darf in diesem Feld denselben Wert haben |
| Inhalt verschlüsselt speichern | siehe unten |
Mehrsprachige Felder
Ein mehrsprachiges Feld hat je Sprache der Instanz einen eigenen Inhalt. Fehlt
eine Übersetzung, gilt der Inhalt der Hauptsprache (Fallback). Einsprachige Felder
haben in jeder Sprache denselben Wert.
Mehrsprachig sein können: Text (auch „Verschlüsselter Text“ und „Text mit
Mehrfachauswahl“), Zahl, Bit, Datum, Uhrzeit und Datei-Upload.
Thumbnail-Felder übernehmen die Einstellung ihrer Quelle: Bei einer mehrsprachigen
Quelle entsteht je Sprache ein eigenes Thumbnail; in Sprachen ohne eigene Datei gilt das
Thumbnail der Hauptsprache.
Ein Volltext hat keinen Schalter „Mehrsprachig“, entsteht aber immer je
Sprache – aus den Inhalten seiner Quellfelder in dieser Sprache (bei nicht
übersetzten Feldern aus dem Fallback der Hauptsprache).
Verknüpfung, Passwort und Metafeld sind immer einsprachig.
Verknüpfungen
| Einstellung | Bedeutung |
|---|---|
| Verknüpfter Inhaltsbereich | Zielbereich einer bidirektionalen Verknüpfung |
| Verknüpfte Inhaltsbereiche | Zielbereiche eines unidirektionalen Verweises oder fest verknüpfter Inhalte – auch mehrere |
| Gegenfeld | Bei beidseitigen Verknüpfungen legt camindo CMS im Zielbereich automatisch das Gegenfeld an: Wird ein Artikel mit einem Schlagwort verknüpft, kennt das Schlagwort den Artikel |
| Manuelle Sortierung | Die Redaktion bestimmt die Reihenfolge der verknüpften Datensätze (etwa die Bilder einer Galerie) |
| Ausführliche Liste | Im Lookup-Feld zeigt die Vorschau der verknüpften Datensätze statt nur des Hauptfeldes alle Felder, die auch in der Datensatzliste des Bereichs sichtbar sind, hier allerdings untereinander |
Zielbereiche müssen zur selben Instanz gehören oder zu einer Instanz, die diese lesen darf. Wählen Sie einen Zielbereich ab, in dem noch Verknüpfungen bestehen, fragt camindo CMS, ob diese Verknüpfungen gelöscht werden sollen.
Eine Verknüpfung „n:1“ ist nicht nur eine Beschränkung auf einen Datensatz: Templates können nach Feldern des verknüpften Datensatzes besonders schnell sortieren und filtern. Wählen Sie diesen Verknüpfungs-Typ dort, wo inhaltlich nur ein Ziel sinnvoll ist, z. B. eine Rubrik zum Artikel.
Fest verknüpfte und eingebettete Inhalte
Fest verknüpfte Inhalte bilden einen Seitenbaukasten: Eine Seite besteht aus Blöcken – Textblock, Bildblock, Zitat, Galerie –, jeder Blocktyp ist ein eigener Inhaltsbereich mit eigenen Feldern.
- Legen Sie für jeden Blocktyp einen Inhaltsbereich an und schalten Sie dort „Abhängiger Bereich“ ein. Nur abhängige Bereiche sind als Ziel wählbar.
- Geben Sie dem Seiten-Bereich ein Feld „Eingebettete Inhalte“ (oder „Fest verknüpfte Inhalte“ mit Suchfenster) und wählen Sie die Blockbereiche als Ziel.
Jeder Block gehört genau einer Seite. Er wird mit ihr gespeichert, kopiert, verschoben und gelöscht. Beim Typ „Eingebettet“ bearbeitet die Redaktion alle Blöcke direkt in der Eingabemaske der Seite: Blöcke können hinzugefügt, umsortiert und entfernt werden.
Dateien
Ein Upload-Feld nimmt eine Datei auf. Unter „Erlaubte Dateitypen“ schränken Sie
die zulässigen Formate ein – als MIME-Typ (image/jpeg, image/*) oder Endung
(.pdf), eine Angabe je Zeile. Ausführbare Dateien wie .php sind immer verboten,
und camindo CMS prüft, ob der Inhalt einer Datei zu ihrer Endung passt.
Unter „Authentifizierung“ kann ein Datei-Inhalt vor dem Zugriff unautorisierter Website-Besucher geschützt werden (siehe Kapitel 13).
Thumbnail-Felder erzeugen aus der Datei eines Upload-Felds automatisch weitere Versionen: verkleinerte Bilder, Vorschaubilder, web-taugliche Videos, Standbilder aus Videos. Sie wählen die Quelle (das Upload-Feld oder ein anderes Thumbnail) und einen oder mehrere Konverter. Die Konverter werden in der eingestellten Reihenfolge abgearbeitet; der erste Konverter, der zum Dateityp passt, erzeugt die Version. Details in Kapitel 8.
Volltext
Ein Volltextfeld sammelt den Inhalt mehrerer Textfelder in einem eigenen Suchindex
(neben fulltext, der automatisch in jedem Inhaltsbereich verfügbar ist).
Unter „Quellfelder“ wählen Sie die Felder aus; bei Upload-Feldern zählt der Dateiname (schraeg-vorn.jpg
wird zu „schraeg vorn schraegvorn jpg“: Binde- und Unterstrich-Wörter stehen getrennt
und zusammengeschrieben im Index). Verschlüsselte Felder und Thumbnails stehen nicht zur
Wahl. Unter den Feldern des Bereichs folgen – je mit dem Namen des Zielbereichs und des
Verknüpfungsfelds als Überschrift – die Felder der Zielbereiche seiner Felder vom Typ:
- „Fest verknüpfte Inhalte“: So findet die Suche ein Produkt etwa über die Titel seiner Bilder. Ändert sich ein verknüpfter Inhalt, wird der Volltext seines Datensatzes sofort mit aktualisiert – der Inhalt gehört ja zum Datensatz.
- „Verknüpfung“ (bidirektional): So findet die Suche ein Produkt etwa über die Bezeichnungen seiner Schlagwörter. Ändert sich aber ein verknüpfter Datensatz – etwa die Bezeichnung eines Schlagworts –, kommt das erst beim nächsten Speichern des Produkts in dessen Volltext. Lassen Sie deshalb für solche Bereiche die Aufgabe „Volltext neu aufbauen“ regelmäßig laufen, etwa nachts.
Felder hinter einem „Verweis“ stehen nicht zur Wahl: Ein Verweis ist eine lose,
einseitige Referenz auf fremde Inhalte, oft in mehreren Bereichen – deren Texte
beschreiben nicht den Datensatz selbst. Das Volltextfeld
wird bei jedem Speichern automatisch aktualisiert und hat keine eigene Eingabe; es
erscheint nur in der Suchmaske. Der Inhalt entsteht je Sprache der Website: In
der englischen Fassung findet die Suche die englischen Texte. HTML-Auszeichnungen
aus formatierten Texten gehören nicht dazu. Die Suche unterstützt die Syntax
+muss -darfnicht (siehe Anwender-Handbuch).
Der Standard-Volltext
Jeder Datensatzbereich hat von selbst einen Volltext über alle Felder vom
Typ „Kurzer Text“, „Langer Text“ und JSON sowie die Dateinamen der Upload-Felder –
ohne dass Sie dafür ein Eingabefeld anlegen. Dazu kommen dieselben Felder der
Zielbereiche seiner Felder vom Typ „Fest verknüpfte Inhalte“ (eine Ebene tief). Neue Felder kommen von selbst hinzu,
gelöschte fallen heraus; verschlüsselte Felder und Passwörter gehören nie dazu. In
der Feldliste des Bereichs erscheint er deshalb nicht, in jeder Suchmaske aber als
Suchfeld „Volltext“ – auch in der bereichsübergreifenden
Suche. Intern heißt er
fulltext.
Was im Volltext eines Datensatzes steht, zeigt dessen Detailansicht im Reiter „Metadaten“ unter „Volltext anzeigen“ – zusammen mit den selbst angelegten Volltextfeldern, je Sprache. Im Reiter „Inhalte“ erscheinen Volltextfelder nicht.
Volltext neu aufbauen
Beim Speichern eines Datensatzes wird sein Volltext automatisch aktualisiert. Nach manchen Änderungen an der Struktur passt aber der Volltext aller vorhandenen Datensätze nicht mehr zu den Quellfeldern:
- Sie legen ein Volltextfeld an oder ändern seine Quellfelder,
- ein Quellfeld wird gelöscht, bekommt einen anderen Typ oder wechselt zwischen ein- und mehrsprachig,
- die Zielbereiche eines Felds vom Typ „Fest verknüpfte Inhalte“ ändern sich oder das Feld wird gelöscht,
- eine Instanz bekommt eine Sprache mit anderen Sortierregeln, oder das Kürzel einer Sprache ändert sich (das betrifft alle Bereiche der Instanz).
camindo CMS baut den Volltext dann nicht sofort neu auf – bei großen Bereichen würde das den laufenden Betrieb aufhalten, und bei größeren Umbauten wäre es nach jedem Schritt vergeblich. Stattdessen erscheint in der Detailansicht und in der Feldliste des Bereichs der Hinweis „Der Volltext dieses Bereichs ist seit … nicht mehr aktuell“. Bis zur Aktualisierung findet die Suche dort teils noch alte Inhalte.
- „Jetzt aktualisieren“ im Hinweis startet den Neuaufbau als Hintergrundprozess. Solange er läuft, steht dort „Hintergrundprozess ‚Volltext aktualisieren‘ gestartet“; ein zweiter Neuaufbau desselben Bereichs startet nicht.
- Oder Sie überlassen es dem Zeitplaner: Die Aufgabe „Volltext neu aufbauen“ mit der Option „Nur veraltete Bereiche“ – bei der Installation eingerichtet, jede Nacht – erledigt alle markierten Bereiche. Ohne die Option baut sie die gewählten Bereiche (ohne Auswahl: alle) in jedem Fall neu auf. Einen Bereich, den gerade ein anderer Prozess neu aufbaut, überspringt sie.
Nach einem vollständigen Neuaufbau verschwindet der Hinweis.
Ausnahme: Wandeln Sie ein Quellfeld in „Verschlüsselter Text“ um, baut camindo CMS den Volltext sofort neu auf – sonst stünde der Klartext bis dahin im Suchindex.
Inhaltliche Änderungen an Datensätzen hinter einer „Verknüpfung“ markieren den Volltext nicht als veraltet. Holen Sie sie mit der Zeitplaner-Aufgabe „Volltext neu aufbauen“ ohne „Nur veraltete Bereiche“ nach.
Verschlüsselte Felder
Beim Typ „Verschlüsselter Text“ liegt der Inhalt verschlüsselt in der Datenbank –
geeignet für personenbezogene Daten wie Telefonnummern oder E-Mail-Adressen. Selbst
wer Zugriff auf die Datenbank oder eine Datenbanksicherung hat, kann ihn ohne die
Schlüsseldatei .camindo.key nicht lesen.
Der Preis: Verschlüsselte Felder lassen sich nur nach dem exakten Wert durchsuchen, nicht mit Platzhaltern, und nicht sinnvoll sortieren. Im CSV-Export erscheinen sie im Klartext.
Sie wählen den Typ beim Anlegen des Feldes oder wandeln ein bestehendes Textfeld nachträglich um (siehe Typ ändern).
Metafelder
Einige Angaben speichert camindo CMS für jeden Datensatz, unabhängig von seinem Bereich. Damit die Redaktion sie bearbeiten kann, fügen Sie sie der Maske als Metafeld hinzu:
| Metafeld | Bedeutung |
|---|---|
| Veröffentlichungsdatum | Der Datensatz erscheint zeitgesteuert auf der Website |
| Ablaufdatum | Der Datensatz verschwindet zum angegebenen Zeitpunkt aus den Listen der Website |
| Gestaltungsvorlage | Auswahl eines der wählbaren Templates |
| Status | Bearbeitungszustand; nur „Freigeschaltet“ erscheint auf der Website |
| Prüfung nötig | Markierung für Inhalte, die noch geprüft werden müssen |
| Eltern-Datensatz | macht den Bereich zu einem Baum (Seiten mit Unterseiten) |
| Position | Reihenfolge der Datensätze („Anordnen nach …“) |
Ohne Metafeld „Status“ sind neue Datensätze sofort freigeschaltet, ohne Veröffentlichungs- und Ablaufdatum unbegrenzt sichtbar.
Besondere Feldnamen
| Name | Wirkung |
|---|---|
slug |
Ein Feld „Kurzer Text“ mit diesem Namen liefert die Webadresse des Datensatzes (/betriebsfeier-2026 statt /1758). Bleibt es leer, füllt camindo CMS es beim Speichern aus dem Hauptfeld. Ein einmal gesetzter Slug ändert sich nicht mit dem Titel – bereits geteilte Links bleiben gültig. Er darf Schrägstriche enthalten (produkte/schuhe) und kann mehrsprachig sein. Eindeutig sein muss die Adresse samt Slug-Prefix des Bereichs – in Bereichen mit verschiedenen Präfixen darf derselbe Slug vorkommen |
Typ ändern
Typ und Mehrsprachigkeit eines bestehenden Feldes lassen sich nicht in der Bearbeitungsmaske ändern, sondern nur über „Typ ändern“ in der Detailansicht. camindo CMS wandelt dabei alle vorhandenen Inhalte um:
- zwischen Text- und Zahltypen, etwa „Kurzer Text“ ↔ „Ganzzahl“ oder „Währungsbetrag“,
- zwischen „n:m“ und „n:1“ bei Verknüpfungen und Verweisen,
- zwischen einsprachig und mehrsprachig.
Kann eine Umwandlung Inhalte verlieren (ein Text, der keine Zahl ist; beim Wechsel auf „n:1“ alle Verknüpfungen außer der ersten; beim Wechsel auf einsprachig alle Übersetzungen), warnt die Maske vorher. Wird der Feldname auch in anderen Bereichen verwendet – auch von einem Feld im Papierkorb –, muss das Feld vorher umbenannt werden; der Typ ist an den Namen gebunden.
Bei der Umwandlung in „Verschlüsselter Text“ fällt das Feld aus allen Volltextfeldern und dem Standard-Volltext; camindo CMS baut diese für alle Datensätze des Bereichs neu auf (auch für gelöschte im Papierkorb), damit kein Klartext im Suchindex zurückbleibt. Ist das Feld das Hauptfeld des Bereichs, steht in Listen und Verknüpfungen danach „ID …“ statt des Inhalts.
Sind Datensätze des Bereichs gerade zur Bearbeitung geöffnet, nennt die Bestätigung deren Anzahl und die Bearbeiter. Die Umwandlung beachtet die Bearbeitungssperre nicht. Der zwischengespeicherte Arbeitsstand der geöffneten Datensätze wird mit umgewandelt – auch neu hochgeladene, noch nicht gespeicherte Dateien. Beim Wechsel eines Datei-Felds auf einsprachig bleibt dabei nur die Datei der Hauptsprache. Die geöffnete Eingabemaske kennt aber noch den alten Feldtyp: Ungespeicherte Eingaben darin lassen sich danach unter Umständen nicht mehr speichern (etwa nach dem Wechsel auf einsprachig); dann hilft nur, die Bearbeitung abzubrechen und den Datensatz neu zu öffnen. Bitten Sie die Bearbeiter deshalb am besten, vorher zu speichern oder abzubrechen.
Eingabefeld löschen
„Löschen“ in der Detailansicht legt das Feld in den Papierkorb. Seine Inhalte bleiben bis zum endgültigen Löschen erhalten, das Feld selbst verschwindet aber sofort überall: aus Eingabe- und Suchmaske, aus der Datensatzliste, aus Export und Ausgabe. Templates finden über das Feld nichts mehr und sortieren nicht mehr danach – als hätte der Bereich das Feld nicht.
Mit dem Feld gehen in den Papierkorb:
- bei einer bidirektionalen Verknüpfung das Gegenfeld im Zielbereich,
- bei einem Upload-Feld seine Dateiversionen (Thumbnails).
Ist das Feld im Bereich als „Haupt-Feld“, „Standard-Sortierung“ oder für die Anmeldung (Name, Passwort) eingetragen, wird diese Einstellung geleert; beim Wiederherstellen kommt sie zurück, sofern inzwischen kein anderes Feld eingetragen wurde. Die Dateien eines Upload-Feldes bleiben liegen, sind aber nicht mehr direkt abrufbar. Volltexte, die das Feld als Quelle hatten, werden als veraltet markiert.
Solange das Feld im Papierkorb liegt, ist sein Name im Bereich belegt: Ein neues
Feld mit demselben Namen lässt sich erst anlegen, wenn das alte endgültig gelöscht oder
wiederhergestellt ist. Ein Feld parent_id behält die Baumstruktur des Bereichs bis
zum endgültigen Löschen.
Superuser stellen gelöschte Felder im Papierkorb wieder her – samt Inhalten, Gegenfeld und Dateiversionen. Nach der Aufbewahrungsfrist löscht die Zeitplaner-Aufgabe „Papierkorb leeren“ Feld und Inhalte endgültig. Wird ein ganzer Bereich gelöscht, gehen seine Eingabefelder mit ihm in den Papierkorb (siehe Kapitel 4).
Namensregeln
- Feldnamen beginnen mit einem Kleinbuchstaben
a-zund bestehen danach aus Kleinbuchstaben, Ziffern und dem Unterstrich_. Namen, die mit einer Ziffer oder einem Unterstrich beginnen, sind nicht erlaubt (Namen mit_am Anfang verwendet camindo CMS selbst, etwa_default). Mindestlänge für Namen: 2 Zeichen. - Der Name
fulltextist für den Standard-Volltext reserviert. - Ein Feldname ist systemweit an einen Typ gebunden: Wurde
titeleinmal als „Kurzer Text“ angelegt, kanntitelin keinem anderen Bereich eine Zahl sein. Das ist die Grundlage für die bereichsübergreifende Abfrage.
Reservierte Namens-Präfixe
Um Typkonflikte zu vermeiden, sind die nachfolgend gelisteten Namenspräfixe reserviert. Sie eignen sich besonders für Template-Sätze: Werden Inhaltsbereiche für fremde Datenbanken exportiert, stellen die Namenspräfixe sicher, dass die Namen in der fremden Datenbank nicht schon für andere Typen vergeben sind.
| Feldtyp | Präfix |
|---|---|
| bit | bit_ |
| chars | chr_ |
| currency | cur_ |
| datetime | dat_ |
| decimal | dec_ |
| encrypted | enc_ |
| file | fil_ |
| float | flt_ |
| fulltext | ftx_ |
| id | rid_ |
| ids | ids_ |
| integer | int_ |
| json | jsn_ |
| password | pwd_ |
| pointer, relation, link | rel_ |
| text | txt_ |
| time | tim_ |
| timestampl | tsl_ |
Extensions
Eine Extension erweitert ein Eingabefeld um zusätzliches Verhalten – einen Texteditor, einen Kalender, eine Symbolauswahl. Sie wählen sie im Feld unter „Erweiterung“; angeboten werden nur Extensions, die zum Feld- und Darstellungstyp passen. Die verfügbaren Extensions beschreibt Kapitel 11.
6 Templates verwalten
Wie Templates geschrieben werden, erklärt das Handbuch für Template-Programmierer. Dieses Kapitel beschreibt, wie Templates organisiert und den Inhalten zugeordnet werden.
Template-Bereiche
Templates liegen in Template-Bereichen (Bereichstyp TEMPLATE, angelegt im Modul „Struktur“). Wie Inhaltsbereiche gehören sie zu einer Instanz und lassen sich in Ordnern gruppieren. Bewährt hat sich ein Template-Bereich je Funktion oder Template-Satz – etwa „Layout“ für Seitenrahmen, Kopf und Fuß, „News“ für die Templates des Nachrichtenbereichs.
Im Modul „Templates“ öffnen Sie einen Template-Bereich und bearbeiten dort seine Templates.
| Einstellung | Bedeutung |
|---|---|
| Name (intern) | Name, unter dem Templates und Adressen das Template ansprechen. Muss nur innerhalb des Template-Bereichs eindeutig sein; gibt es ihn mehrfach, spricht man es als bereichsname.name an |
| Label | Beschriftung, die im Datensatz bei der Auswahl eines Templates erscheint (optional) |
| Standalone | Das Template darf ohne Datensatz aufgerufen werden, über die Adresse /0,name – etwa für eine Suchseite, eine Sitemap oder ein Kontaktformular |
| Verwendung | „Zeitgesteuert (Zeitplaner)“: Das Template läuft nur als Aufgabe des Zeitplaners und ist nie über eine Adresse aufrufbar (auch nicht als Standalone-Template). Einstellung im Reiter „Zugriff“ |
| Code | HTML mit CMS-Befehlen und PHP |
Die Detailansicht zeigt den Code farbig hervorgehoben. Fehler im Code – ein
unbekannter Befehl, ein falscher Parameter, eine fehlende Klammer – verhindern das
Speichern nicht, sondern werden mit Zeilennummer über dem Code angezeigt. Verweise auf
andere Templates sind anklickbar. Existiert das verwiesene Template noch nicht, bietet
camindo CMS an, es gleich anzulegen; ein Listentemplate (Parameter resulttemplate
von CMS:SELECT und CMS:SELECT_LANGVERSION) erhält dabei schon die Schleife
(CMS:RESULT_START) … (CMS:RESULT_END) als Code.
CMS-Befehl einfügen: Rechts über dem Code-Feld der Eingabemaske steht eine Auswahl
aller CMS-Befehle (alphabetisch, samt den Befehlen der Zusatzmodule). Wählen Sie einen aus,
öffnet sich eine Maske mit allen Parametern des Befehls: je Parameter ein Eingabefeld für den
Wert, davor bei Bedarf Felder für die Schlüssel (filter[preis]) und – bei filter –
eine Auswahl des Vergleichsoperators (=, ==, !=, <, >= …). Parameter mit
Schlüsseln dürfen mehrfach vorkommen; mit dem kleinen „+“ darunter fügen Sie eine weitere
Zeile hinzu. Das Fragezeichen neben dem Parameternamen zeigt seine Beschreibung,
Pflichtparameter sind mit * markiert. „Einfügen“ setzt den Befehl an der Cursorposition in
den Code ein – Parameter ohne Wert bleiben weg, ab drei Parametern steht jeder in einer
eigenen Zeile. Gespeichert wird erst mit dem Template.
Ein Template lässt sich in einen anderen Template-Bereich verschieben – über die
Schaltfläche „Verschieben“ der Template-Ansicht oder das Kontextmenü der Template-Liste.
Zur Auswahl stehen alle Template-Bereiche, in die Sie schreiben dürfen – bei mehreren
Instanzen nach Instanz gruppiert: der Instanzname als nicht wählbarer Eintrag, darunter
ihre Template-Bereiche. Die Zuweisungen bleiben erhalten, die Datei
zieht in das Verzeichnis des Zielbereichs um. Gibt es den Namen im Zielbereich schon,
wird nicht verschoben. Kommt der Name danach in mehreren Bereichen vor, müssen Verweise
anderer Templates den Bereich mit nennen (bereich.name).
Templates den Inhaltsbereichen zuweisen
Welches Template ein Datensatz im Frontend bekommt, entscheidet camindo CMS in dieser Reihenfolge:
- ein URL-Override-Template in der Adresse (
/betriebsfeier,druck) – nur wenn es für den Inhaltsbereich freigegeben ist, - das im Datensatz gewählte Template (Metafeld „Gestaltungsvorlage“) – nur aus den wählbaren Templates,
- das Standard-Template des Inhaltsbereichs.
Die Zuweisung pflegen Sie an zwei gleichwertigen Stellen: in den Einstellungen des Bereichs oder auf dem Reiter „Zugriff“ des Templates („Contentbereich hinzufügen“, dann je Bereich „Standard“, „Auswählbar“ und „URL-Override“). Die Auswahl „Contentbereich hinzufügen“ bietet nur die Inhaltsbereiche der Instanz des Templates und der Instanzen an, deren Inhalte diese Instanz lesen darf; jede Instanz erscheint dort wie ein Ordner, ihre Bereiche darunter eingerückt.
Ein Template, das über die Adresse angefordert wird, ohne dafür freigegeben zu sein, wird nicht ausgeliefert. So lassen sich keine internen Templates von außen aufrufen.
Templates im Dateisystem
Jedes Template liegt zusätzlich als Datei auf dem Server:
var/templates/{instance_id}/{bereichsname}/{templatename}.cms.php
Das ermöglicht die Arbeit mit einem gewohnten Code-Editor, einer Versionsverwaltung (Git) oder einem Deployment-Werkzeug. camindo CMS gleicht die Dateien minütlich mit dem Backend ab (und sofort über die Schaltfläche „Aktualisieren“ der Template-Listen):
| Im Dateisystem | Wirkung im Backend |
|---|---|
| neue Datei | neues Template wird erstellt |
| Datei geändert | der Template-Inhalt wird neu eingelesen |
| Datei umbenannt | das alte Template wird gelöscht, ein neues erstellt |
| Datei gelöscht | Template wird gelöscht – samt Zuweisungen |
| neues Verzeichnis | neuer Template-Bereich wird erstellt |
Umgekehrt schreibt das Backend jede Änderung in die Datei zurück.
Benennen Sie Templates besser im Backend um: Im Dateisystem ist
Umbenennen „Löschen und neu anlegen“, und die Zuweisungen gehen verloren.
Übersichts-Templates
Führt ein Inhaltsbereich ein Slug-Prefix (etwa termine), hat jeder Datensatz eine
Adresse wie /de/termine/betriebsfeier. Die Adresse aus dem Präfix allein – /de/termine
– zeigt das Übersichts-Template des Bereichs: typischerweise die Liste seiner
Datensätze. Es läuft ohne Datensatz und wird in den Einstellungen des Bereichs unter
„Template-Zuweisung“ gewählt. Weil das Präfix je Sprache übersetzt ist, hat auch die
Übersicht je Sprache ihre Adresse (/en/events). Ohne Übersichts-Template ergibt die
Adresse „Seite nicht gefunden“.
Statt eines Datensatzes stellt das Übersichts-Template die Angaben des Bereichs bereit –
die Id (area_id), den Namen, die Beschriftung, die Instanz und das Slug-Prefix in der
aufgerufenen Sprache. Damit fragt das Template die Datensätze seines Bereichs ab, ohne
den Bereich fest einzutragen (siehe
Handbuch für Template-Programmierer).
Haben Sie einem Bereich ein Übersichts-Template und ein Slug-Prefix zugewiesen, erscheint in den Einstellungen des Bereichs und über seiner Datensatzliste die Schaltfläche „Vorschau“. Sie zeigt die Übersicht so, wie sie im Frontend erscheint – bei mehreren Sprachen als Auswahl mit einem Eintrag je Sprache, jeweils unter dem Slug-Prefix dieser Sprache.
Listen-Templates für das Backend
Ein Inhaltsbereich kann ein Listen-Template erhalten. Es wird nicht im Frontend verwendet, sondern im Backend: Es gestaltet je Datensatz eine zusätzliche Spalte der Datensatzliste und die ausführliche Vorschau in Lookup-Feldern – etwa ein Farbfeld statt des eingegebenen RGB-Farbwerts oder einen ganzen Text-Bild-Block im finalen Layout.
Template-Sätze
Wie Sie Templates zusammen mit ihren Inhaltsbereichen als Template-Satz weitergeben und in anderen Installationen einsetzen, beschreibt Kapitel 9.
7 Benutzer und Rechte
Wer im Backend arbeitet, ist ein Benutzer – gleich in welcher Rolle: als Redakteur, Übersetzer, Administrator, Programmierer. Benutzer und ihre Benutzergruppen verwalten Sie im Modul „Benutzer“. Jeder Benutzer gehört genau einer Benutzergruppe; sie bestimmt, was er sehen und tun darf. Benutzer der Gruppe Superuser haben volle Rechte für alles.
Die Startseite des Moduls „Benutzer“ listet alle Benutzer (die Sie mit Ihren Gruppenrechten sehen dürfen). Superuser sind mit einem sechseckigen Symbol markiert. Klicken Sie auf die Schaltfläche „Neu“ oder wählen Sie einen Eintrag aus der Liste. Es erscheint die Eingabe-/Änderungsmaske für diesen Benutzer.
Eingabefelder
| Angabe | Bedeutung |
|---|---|
| Benutzername | Anmeldename: beginnt mit einem Kleinbuchstaben, danach Kleinbuchstaben, Ziffern und _. Neue Namen dürfen nicht mit admin_ beginnen – reserviert für anonymisierte Konten |
| Passwort | wird nur als Prüfwert (Hash) gespeichert und ist nicht lesbar; leer lassen = unverändert. Es muss die Passwort-Richtlinie erfüllen – die Anforderungen erscheinen beim Tippen. Beim Anlegen vergeben Sie ein Startpasswort. Das Passwort eines bestehenden anderen Benutzers ändert nur ein Superuser |
| Bisheriges Passwort, Ihr Passwort |
nur für Superuser beim Ändern eines bestehenden Kontos: Wer sein eigenes Passwort ändert, gibt das bisherige ein; wer das Passwort eines anderen Benutzers ändert, bestätigt das mit seinem eigenen Passwort – eine offen stehende Sitzung reicht also nicht, um ein Konto zu übernehmen. Beim Anlegen entfällt das Feld. Alle anderen ändern ihr Passwort in den persönlichen Einstellungen |
| Benutzergruppe | Benutzergruppe mit ihren Rechten |
| Status | „Freigeschaltet“ oder „Deaktiviert“ – ein deaktivierter Benutzer kann sich nicht anmelden |
| Haupt- (Nach-) Name, Angezeigter Name, Sortierwert |
Namen für Listen und Nachrichten |
| E-Mail, Mobilfunk-, Festnetznummer |
Kontaktdaten, verschlüsselt gespeichert. Die E-Mail-Adresse wird für den Anmelde-Code der Zwei-Faktor-Anmeldung benötigt |
Die persönlichen Einstellungen eines Benutzers (Sprache, Datumsformat, Zeitzone, Widgets, Passwort, Geräte …) pflegt jeder selbst; ein Superuser kann sie auch für andere ändern.
Benutzer löschen: Gelöschte Benutzer bleiben als „gelöscht“ erhalten, damit Datensätze und das Audit-Log weiterhin zeigen, wer sie angelegt und bearbeitet hat. Beim Löschen entfernt camindo CMS alles, womit sich das Konto noch anmelden könnte: seine Sitzungen (er wird sofort abgemeldet), die gespeicherten Geräte, Passkeys und Wiederherstellungscodes sowie die Liste der zuletzt bearbeiteten Datensätze und Templates. Die Einträge im Audit-Log bleiben bestehen. Das eigene Konto lässt sich nicht löschen. Name und Kontaktdaten eines gelöschten Benutzers entfernen Sie mit Anonymisieren (siehe Modul „Datenschutz“, Reiter „Gelöschte Benutzer“).
Passwort ändern müssen: Ein Passwort, das ein anderer Benutzer gesetzt hat, muss bei der ersten
Anmeldung geändert werden – etwa das Startpasswort beim Anlegen oder ein vom Superuser zurückgesetztes.
Die Konfigurationseinstellung admin.password_retention_days (0 = unbegrenzt)
erzwingt ebenfalls eine Passwortänderung nach der eingestellten Anzahl Tage. Ein neues muss
sich dann vom bisherigen unterscheiden. Die Detailansicht zeigt unter „Passwort“, wann
es zuletzt geändert wurde und ob eine Änderung ansteht.
Benutzergruppen
Nur Superuser sehen den Reiter „Benutzergruppen“. Die Liste zeigt alle bestehenden Benutzergruppen. Nach der Installation gibt es nur die eine Gruppe „Superuser“.
Benutzergruppe erstellen: Für die tägliche Arbeit sollte eine separate Gruppe mit eingeschränkten Rechten erstellt werden, etwa die Gruppe „Übersetzer“, „Redakteure“ oder „Praktikanten“. Klicken Sie dazu auf die Schaltfläche „Neu“.
Benutzergruppe löschen: Sind der Benutzergruppe noch Benutzer zugeordnet, wählen Sie beim Löschen eine Ersatzgruppe, der diese Benutzer zugewiesen werden. Gelöschte Benutzer der Gruppe verlieren dabei ihre Gruppenzuordnung – ohne Rückfrage; hat die Gruppe nur gelöschte Benutzer, erscheint keine Auswahl. Die Gruppe „Superuser“ steht dabei nicht zur Wahl.
Oberflächen
Unter „Oberflächen“ legen Sie fest, worüber sich die Benutzer der Benutzergruppe anmelden dürfen:
| Oberfläche | Wofür |
|---|---|
| Backend | die gewohnte Arbeitsoberfläche im Browser |
| Kommandozeile (CLI) | Programme auf dem Server, etwa php Core/cron/camindo.php api … (siehe Betrieb) – ohne Passwort, denn wer die Kommandozeile des Servers bedienen kann, hat ohnehin vollen Zugriff |
| PHP-API | Programme, die sich mit Name und Passwort anmelden |
Auf jeder Oberfläche gelten dieselben Rechte der Benutzergruppe; im Audit-Log erscheint der
Benutzer selbst, zusammen mit dem Weg (etwa cli). Eine neue Benutzergruppe hat nur das
Backend. Entziehen Sie einer Benutzergruppe eine Oberfläche, enden laufende Sitzungen dort beim
nächsten Zugriff. Für Programme empfiehlt sich ein eigener Benutzer in einer eigenen
Benutzergruppe, die nur die nötigen Oberflächen und Rechte hat.
Die Rechte einer Benutzergruppe haben vier Ebenen:
1. Module und Zusatzrechte
Welche Module die Benutzergruppe öffnen darf. Einige Module haben darunter eingerückt Zusatzrechte für einzelne Teile – ohne Zusatzrecht bleibt der Teil gesperrt:
| Modul | Zusatzrechte |
|---|---|
| Benutzer | „Benutzerdetails lesen: eigene Benutzergruppe“ · „Benutzerdetails lesen: andere Benutzergruppen“ · „Benutzer anlegen: eigene Benutzergruppe (mit Startpasswort)“ · „Benutzer ändern und sperren: eigene Benutzergruppe (ohne Passwort)“ |
| Datenschutz | „Lösch-Policies anlegen und ändern“ (nur für zugängliche Instanzen) · „Personenbezogene Daten exportieren“ (Profile aus lesbaren Bereichen, Benutzer aus sichtbaren Benutzergruppen) · „Vorlagen der Datenauskunft pflegen“ (zugängliche Instanzen) · „Gelöschte Benutzer anonymisieren“ (zugängliche Benutzergruppen) – siehe Kapitel 15 |
| Inhalte | „CSV-Import“, „Medien-Import (Zip-Datei)“, „CSV-Export“, „DOCX-Import (Übersetzung)“, „DOCX-Export (Übersetzung)“, „Stapelverarbeitung“ |
| Werkzeuge | je ein Recht für die Reiter „Server“, „Datenbank“, „Daten“, „Entwickler“ und „Papierkorb eines Users“ („Papierkorb eines Website-Users endgültig leeren“) |
Immer Superusern vorbehalten sind: die Verwaltung der Benutzergruppen, die Bereichsrechte, der XML-Export und -Import (Sicherung und Strukturübertragung) und das Modul „Logdateien“.
Ohne Eintrag in der Benutzergruppe stehen jedem Benutzer die internen Nachrichten, die persönlichen Einstellungen und der Papierkorb zur Verfügung. Wiederherstellen darf er dort nur, was er in dem Bereich auch löschen dürfte.
2. Instanzen
Welche Instanzen (Websites) die Benutzergruppe sieht. Weist man einer Benutzergruppe eine Instanz zu, erhält sie zunächst alle Bereiche dieser Instanz mit allen Rechten (außer „Owner anpassen“). Einschränken lässt sich das anschließend im Reiter „Bereichsrechte“.
3. Sprachen
Je Sprache zwei Häkchen: lesen und schreiben. Wer schreiben darf, darf auch lesen – ein Häkchen bei „schreiben“ setzt „lesen“ mit. Ein Klick auf die Spaltenüberschrift „lesen“ bzw. „schreiben“ hakt die ganze Spalte an – oder ab, wenn dort schon alle Häkchen gesetzt sind. Ohne Häkchen hat die Benutzergruppe keinen Zugriff auf die Sprache.
Die Einstellung gilt für alle Instanzen und für die Inhalte im Modul „Inhalte“: Nur lesbare Sprachen erscheinen in der Eingabemaske, nur schreibbare lassen sich dort ändern. So kann ein Übersetzer für Französisch alle Sprachen lesen, aber nur Französisch bearbeiten.
4. Status setzen
Je Status eine Checkbox: Angehakte Status dürfen Benutzer der Gruppe einem Datensatz
geben. Lesen dürfen sie alle Status – eingeschränkt wird nur das Setzen. So
bilden Sie einen flachen Workflow ab, etwa: Die Redaktion darf Beiträge anlegen und
auf „Gegenzulesen“ setzen, aber nicht freischalten – das übernimmt die Chefredaktion.
Weitergereicht wird über interne Nachrichten. Sie haben zwei Wege, Zugriffsrechte zu setzen:
(Hier) in der Benutzergruppe wählen Sie alle Status für eine Gruppe; im Modul „Status“
wählen Sie alle Benutzergruppen für einen Status.
Status in der Datensatz-Eingabemaske:
- Das Eingabefeld „Status“ zeigt nur Status, die vom Benutzer setzbar sind.
- Ein Datensatz, dessen aktueller Status vom Benutzer nicht setzbar ist, lässt sich von ihm nicht bearbeiten: Die Schaltfläche „Bearbeiten“ ist ausgegraut, im Kontextmenü der Liste fehlt der Eintrag. Lesen, Kopieren und – je nach Bereichsrecht – Löschen bleiben möglich.
5. Bereichsrechte
Nachdem eine Benutzergruppe erstellt wurde, zeigt ihre Infoseite den Reiter „Bereichsrechte“. Hier ist gelistet, was die Benutzer dieser Gruppe mit den Datensätzen unterschiedlicher Bereiche machen dürfen. Klicken Sie auf die Schaltfläche „Bearbeiten“, um Anpassungen durchzuführen.
| Recht | Bedeutung |
|---|---|
| Lesen | Der Bereich ist für die Benutzergruppe sichtbar – ohne dieses Recht existiert er für sie nicht |
| Eigene Benutzergruppe: Schreiben / Löschen | Datensätze bearbeiten bzw. löschen, deren Owner zur eigenen Benutzergruppe gehört |
| Andere Benutzergruppe: Schreiben / Löschen | dasselbe für Datensätze, deren Owner einer anderen Benutzergruppe angehört |
| Erweitert (Owner anpassen) | den Owner eines Datensatzes ändern (Auswahl am Ende der Eingabemaske) |
Template-Bereiche kennen nur Lesen und Schreiben. Ordner haben keine eigenen Rechte.
Die Bereichsrechte pflegen Sie an zwei gleichwertigen Stellen:
- (hier) im Modul „Benutzer“, Reiter „Bereichsrechte“: alle Bereiche für eine Benutzergruppe,
- im Modul „Struktur“, Reiter „Zugriff“: alle Benutzergruppen für einen Bereich.
Das Owner-Prinzip
Jeder Datensatz gehört einem Benutzer, seinem Owner – anfangs dem, der ihn angelegt hat. Über die Benutzergruppe des Owners unterscheiden die Bereichsrechte zwischen eigenen und fremden Inhalten. Beispiele:
- Zwei Redaktionen, ein Bereich: Die Benutzergruppen „Redaktion Nord“ und „Redaktion Süd“ dürfen alle Meldungen lesen, aber nur die der eigenen Benutzergruppe schreiben und löschen.
- Freigabe durch Chefredaktion: Die Benutzergruppe „Autoren“ darf eigene Artikel schreiben, aber nicht löschen; die „Chefredaktion“ darf alle Artikel schreiben und löschen.
- Übergabe: Verlässt ein Mitarbeiter die Redaktion, ändert ein Benutzer mit dem Recht „Owner anpassen“ den Owner seiner Datensätze.
Datensätze, die Frontend-User anlegen, erhalten den Owner, den das Template bzw. die Konfiguration vorgibt (siehe Kapitel 13).
Was die Rechte bewirken
Die Oberfläche zeigt nur, was für die Benutzergruppe freigegeben ist: Module, Bereiche, Schaltflächen, Menüeinträge, Sprachen. Unabhängig davon prüft camindo CMS jede Aktion auch beim Speichern und Löschen – ein Recht lässt sich also nicht durch eine manipulierte Anfrage umgehen. Hintergrundprozesse (Import, Export, Stapelverarbeitung) laufen mit den Rechten des Benutzers, der sie gestartet hat.
Verknüpfungsfelder, deren Zielbereiche die Benutzergruppe nicht lesen darf, erscheinen nicht in der Maske; ihre Verknüpfungen bleiben beim Speichern unangetastet. Ebenso mehrsprachige Inhalte, die die Benutzergruppe nur in ausgewählten Sprachen bearbeiten darf: die übrigen Inhalte bleiben beim Speichern erhalten.
Anmeldeschutz
- Zwei-Faktor-Anmeldung: Nach dem Passwort wird ein Code an die E-Mail-Adresse des Benutzers geschickt. Einschalten in der Konfiguration (siehe Kapitel 12).
- Authenticator-App (TOTP): Jeder Benutzer kann in seinen persönlichen
Einstellungen eine Authenticator-App einrichten; dann fragt die Anmeldung nach deren
Code statt nach dem E-Mail-Code, dazu gibt es zehn Wiederherstellungscodes (Anleitung
im Handbuch für Anwender).
Mitsecurity.admin_2fa = 'totp_required'ist sie für Superuser Pflicht – wer sie noch nicht hat, muss sie bei der nächsten Anmeldung im Anmeldedialog einrichten. Mit'email'ist sie abgeschaltet (siehe Kapitel 12). - Passkeys: Mit fester Backend-Domain kann jeder Benutzer Passkeys anlegen (Fingerabdruck, Gesicht, Geräte-PIN, Sicherheitsschlüssel) – die sicherste Form des zweiten Faktors (Handbuch für Anwender). Das Zurücksetzen unten entfernt auch sie.
- Zweiten Faktor zurücksetzen: Hat ein Benutzer sein Telefon bzw. seine Passkeys und seine Wiederherstellungscodes verloren, öffnet ein Superuser dessen Detailansicht, Reiter „Zwei-Faktor-Anmeldung“, und klickt auf „Zweiten Faktor zurücksetzen“ (entfernt App und Passkeys). Der Benutzer meldet sich danach wieder mit dem E-Mail-Code an (bzw. richtet die App bei Pflicht neu ein) und bekommt eine E-Mail darüber. Das Zurücksetzen steht mit dem Namen des Superusers im Audit-Log. Vergewissern Sie sich vorher – etwa per Telefon –, dass die Bitte wirklich vom Kontoinhaber kommt.
- Zurück zum E-Mail-Code: Wer die Authenticator-App nicht mehr nutzen möchte,
wechselt in seinen Einstellungen mit „Zum Code per E-Mail wechseln“ zurück (bestätigt
mit einem Code aus der App). Ist der E-Mail-Code nicht für alle eingeschaltet, kann
jeder Benutzer ihn für sich selbst einschalten.
(Ist mittels Konfiguration die App für alle Benutzer vorgeschrieben, kann nicht zum Code per E-Mail zurückgewechselt werden.) - Hinweis bei neuem Gerät: Meldet sich ein Benutzer von einem Browser an, den camindo CMS noch nicht kennt, geht eine E-Mail an seine Adresse – samt Gerät, IP-Adresse und Uhrzeit (siehe Kapitel 12).
- Geräte und Sitzungen: Jeder Benutzer sieht in seinen persönlichen Einstellungen seine Anmeldegeräte mit den laufenden Sitzungen, kann einzelne Geräte entfernen (ihre Sitzungen enden sofort) und alle anderen Sitzungen beenden. Ein Superuser kann in der Detailansicht eines anderen Benutzers, Reiter „Geräte und Sitzungen“, mit „Alle Geräte entfernen“ alle dessen Geräte und Sitzungen beenden – etwa nach einem verlorenen Laptop. Beides steht im Audit-Log. „Abmelden“ beendet nur die Sitzung im eigenen Browser.
- Aktivitäten: Was ein Benutzer geändert hat, sieht ein Superuser in dessen Detailansicht im Reiter „Aktivitäten“ – die zuletzt bearbeiteten Datensätze und alle seine Einträge im Audit-Log.
- Neues Passwort beendet andere Sitzungen: Wird ein Passwort geändert (vom Benutzer selbst oder vom Superuser), enden alle anderen Sitzungen des Kontos.
- Schutz vor Durchprobieren: Nach mehreren Fehlversuchen (Vorgabe: 3 in 10 Minuten) wird die Anmeldung für den Benutzernamen gesperrt. Sperren werden im Sicherheitsprotokoll festgehalten.
- Automatische Abmeldung nach 30 Minuten ohne Aktivität (einstellbar).
- Rechte und Sitzungen sind gegen Manipulation direkt in der Datenbank signiert: Wer nur Zugriff auf die Datenbank hat, kann sich damit keine Rechte verschaffen.
8 Medien: Uploads, Konverter und Thumbnails
camindo CMS nimmt Dateien über Upload-Felder entgegen und erzeugt daraus automatisch die Versionen, die die Website braucht: verkleinerte Bilder in mehreren Größen, Vorschaubilder, web-taugliche Videos, Standbilder aus Videos, komprimierte Audiodateien. Drei Begriffe sind dabei wichtig:
| Begriff | Bedeutung |
|---|---|
| Prozessor | ein Programmbaustein, der Dateien umwandeln kann – etwa „GD Bibliothek“ oder „FFmpeg (Video)“ |
| Konverter | ein eingestellter Prozessor: welche Dateien er wie umwandelt – etwa „Bild 800 px breit, JPEG, Qualität 80“ |
| Thumbnail-Feld | ein Feld, das mit einem oder mehreren Konvertern aus der Datei eines anderen Felds eine Version erzeugt |
Prozessoren
Mit dem Core werden ausgeliefert:
| Prozessor | Aufgabe | Voraussetzung |
|---|---|---|
| GD Bibliothek | Bilder skalieren, zuschneiden, umwandeln – Basisfunktionen ohne Zusatzsoftware | PHP-Erweiterung gd |
| ImageMagick | Bilder in sehr vielen Formaten (auch HEIC, TIFF, PSD), Expertenmodus mit eigenen Parametern, auch im Hintergrund | ImageMagick auf dem Server |
| FFmpeg (Video) | Videos umwandeln, skalieren, komprimieren | ffmpeg |
| FFmpeg (Audio) | Audiodateien umwandeln, Lautheit angleichen, Ausschnitte | ffmpeg |
| FFmpeg (Vorschaubild) | Standbild aus einem Video | ffmpeg |
Weitere Prozessoren lassen sich als Komponenten nachinstallieren. Ob ImageMagick und ffmpeg gefunden werden, zeigt das Modul „Werkzeuge“ auf dem Reiter „Server“.
Konverter einrichten
Konverter legen Sie im Modul „Medienkonverter“ an. Die Installation richtet bereits den Konverter „Interne Bildvorschau (GD)“ ein: Er wandelt alle Bildformate, die die GD Bibliothek liest, in JPEG-Bilder von höchstens 200 px Breite und 300 px Höhe um.
| Einstellung | Bedeutung |
|---|---|
| Prozessor | welcher Prozessor die Arbeit macht |
| Label | Name des Konverters |
| Eingeschlossene Medientypen | auf welche Dateien der Konverter anspringt: MIME-Typ (image/jpeg), Gruppe (image/*) oder Endung (.pdf), eine Angabe je Zeile |
| Ausgeschlossene Medientypen | Ausnahmen, etwa image/gif, damit animierte GIFs unverändert bleiben |
| Dateiendung | Format der erzeugten Datei, z. B. .jpg oder .mp4; leer = Format beibehalten |
| Konvertierungsoptionen | je nach Prozessor: Breite und Höhe, Einpassen oder Zuschneiden, Größe nur verkleinern bzw. vergrößern, Qualität, Hintergrundfarbe, Codec, Datenrate, Ausschnitt, Metadaten entfernen, Umwandlung im Hintergrund … |
Größe bei ImageMagick und der GD Bibliothek: Neben „Zielbreite“ und „Zielhöhe“ legen vier Einstellungen fest, wie das Bild auf diese Größe kommt:
| Einstellung | Auswahl | Wirkung |
|---|---|---|
| Anpassung an das Format | Als Ganzes in das Format einpassen | das ganze Bild passt hinein, eine Seite kann kürzer sein |
| Format ganz ausfüllen und beschneiden | füllt das Format, Überstehendes wird mittig abgeschnitten | |
| Format ganz ausfüllen, überstehen lassen | füllt das Format, eine Seite kann länger sein (nichts wird abgeschnitten) | |
| Genau auf das Format bringen, Seitenverhältnis ignorieren | Breite und Höhe exakt – das Bild wird dabei verzerrt | |
| Größe ändern | Immer / Nur verkleinern / Nur vergrößern | „Nur verkleinern“: Kleinere Bilder behalten ihre Größe – ein Thumbnail mit 440 px Breite wird aus einem 300 px breiten Bild nicht hochgerechnet. „Nur vergrößern“: Größere Bilder behalten ihre Größe |
| Einheit | Pixel / Prozent des Originals | mit Prozent sind Zielbreite und -höhe Prozentwerte, z. B. 50 für die halbe Größe (nur mit Einpassen oder Verzerren) |
| Höchstzahl Pixel | Zahl | skaliert proportional, bis Breite × Höhe diesem Wert entspricht, z. B. 1000000 für ein Megapixel; wirkt nach Zielbreite und -höhe und folgt ebenfalls „Größe ändern“ – mit „Nur verkleinern“ werden nur größere Bilder verkleinert, mit „Immer“ auch kleinere vergrößert |
Ausfüllen, Beschneiden und Verzerren brauchen beide Maße; fehlt eines, wird eingepasst. Beschneiden mit „Nur verkleinern“ schneidet kleinere Bilder nur mittig auf das Zielformat zu, soweit das Bild reicht – einen Rand in der Hintergrundfarbe gibt es nicht.
Abweichungen bei der GD Bibliothek: Statt „Anpassung an das Format“ gibt es dort die Einstellung „Beschneiden“ mit nur zwei Auswahlen: „Als Ganzes in neues Format einpassen“ und „Neues Format ganz ausfüllen“ (beschneidet mittig). „Größe ändern“, „Einheit“ und „Höchstzahl Pixel“ wirken wie bei ImageMagick; Prozent gilt nur ohne Beschneiden. Ein Prozentwert gilt für beide Seiten, zwei unterschiedliche Prozentwerte skalieren Breite und Höhe getrennt.
Weitere Einstellungen:
| Einstellung | Auswahl | Wirkung |
|---|---|---|
| Qualität | Prozent | Qualität bei komprimierten Formaten wie JPEG; 100 % = beste Qualität, aber größte Datei |
| Anzahl Farben | Zahl oder TrueColor |
Die Formate GIF und PNG erlauben eine reduzierte Farbpalette (höchstens 256 Farben). Die Anzahl kann hier angegeben werden, z. B. 2, 8 oder 128. TrueColor: Farbpalette nicht reduzieren |
| Transparenz | Alpha-Kanal erhalten | eingeschaltet: transparente Bereiche bleiben transparent; ausgeschaltet: sie werden mit der Hintergrundfarbe gefüllt |
| Hintergrundfarbe | Hexadezimalwert, z. B. #ffffff |
ersetzt die Transparenz, wenn der Alpha-Kanal nicht erhalten bleibt |
Die Detailansicht eines Konverters zeigt auf dem Reiter „Verwendet von …“, welche Thumbnail-Felder ihn nutzen. Wird ein verwendeter Konverter gelöscht, erzeugen diese Felder keine Versionen mehr – die Rückfrage warnt davor.
PDF und SVG mit ImageMagick: camindo CMS lässt ImageMagick nur mit einer eigenen Sicherheits-Policy arbeiten. SVG und PDF sind darin gesperrt, bis Sie sie in
.camindo.phpfreigeben:'security' => [ 'magick_allow' => ['svg'], // oder ['svg', 'pdf'] ],PDF liest ImageMagick über Ghostscript, das wiederholt Einfallstor für Angriffe über präparierte Dateien war – geben Sie es nur frei, wenn Sie es brauchen. Ob ein Format wirklich läuft, zeigt die Detailansicht des Konverters unter „Sicherheits-Policy“: Auch die Policy des Servers kann es sperren. PDF ist bei vielen Providern gesperrt, das können Sie in camindo CMS nicht ändern. Mehr dazu: Betrieb – ImageMagick absichern.
Thumbnail-Felder
Ein Thumbnail-Feld (Feldtyp „Dateiversion (Thumbnail)“) hat eine Quelle – ein Upload-Feld oder ein anderes Thumbnail-Feld – und eine sortierte Liste von Konvertern. Für jede neue Datei geht camindo CMS die Konverter der Reihe nach durch; der erste, dessen Medientypen passen, erzeugt die Version. So kann ein Feld „vorschau“ für Bilder einen Bildkonverter und für Videos einen Standbild-Konverter verwenden.
Thumbnail-Felder lassen sich verketten. Beispiel für ein Video:
video Upload-Feld
├── video_web FFmpeg (Video): MP4/H.264, 1920 px, im Hintergrund
└── video_standbild FFmpeg (Vorschaubild): Standbild bei 10 % der Laufzeit
└── video_teaser ImageMagick: 400 × 225 px zugeschnitten, JPEG
Die Versionen entstehen beim Speichern des Datensatzes, einmal – nicht bei jedem Zwischenspeichern. Bilder werden sofort umgewandelt; Videos und andere aufwändige Umwandlungen laufen als Hintergrundprozess (dafür muss der Cronjob laufen). Bis dahin zeigt das Backend ein Platzhalterbild.
Das Platzhalterbild bleibt auch nach Abschluss des Hintergrundprozesses in der Ansicht stehen – die Ansicht wird erst durch Klick auf die Schaltfläche „Aktualisieren“ erneuert.
Der Prozessor „GD Bibliothek“ arbeitet nicht im Hintergrund. Soll eine Version aus einer Datei entstehen, die selbst erst im Hintergrund erzeugt wird (etwa aus dem Standbild eines Videos), verwenden Sie ImageMagick.
Thumbnails neu erzeugen
Ändern Sie die Einstellungen eines Konverters oder fügen Sie einem Bereich ein neues Thumbnail-Feld hinzu, gilt das zunächst nur für neue Uploads. Für den Bestand erzeugt „Werkzeuge“ → „Daten“ → „Thumbnails neu erzeugen“ die Versionen aller Datensätze eines Bereichs neu – bei vielen Datensätzen im Hintergrund.
Upload-Felder
| Einstellung | Bedeutung |
|---|---|
| Erlaubte Dateitypen | MIME-Typen oder Endungen, eine Angabe je Zeile; leer = alle zulässigen |
| Mehrsprachig | je Sprache eine eigene Datei, etwa ein Prospekt je Sprache |
| Nur für angemeldete Frontend-User | Datei nur an angemeldete Frontend-User ausliefern (siehe Kapitel 13) |
Aus Sicherheitsgründen sind ausführbare Dateien (.php, .phtml, .cgi, .sh,
.htaccess u. a.) immer verboten, und camindo CMS prüft, ob der Inhalt einer Datei zu
ihrer Endung passt – ein als .jpg getarntes anderes Format wird abgewiesen.
Große Dateien: das Upload-Verzeichnis
Die Größe eines Uploads über den Browser begrenzt die PHP-Konfiguration des Servers
(upload_max_filesize, post_max_size). Größere Dateien – etwa Videos – übertragen
Sie per FTP oder SCP in das Verzeichnis var/upload/. In der Eingabemaske und beim
Import wählen Redakteure sie über „Datei auf dem Server auswählen“,
die Schaltfläche rechts an jedem Upload-Feld.
Ablage und Auslieferung
Dateien liegen unter public/media/ in der Struktur
{instanz}/{feld}/{datensatz}.{endung}. Die Adressen, die die Templates erzeugen,
tragen zusätzlich den ursprünglichen Dateinamen, etwa
/media/1/12/1977,strand-nord.jpg – gut für Suchmaschinen und für Besucher, die
eine Datei speichern.
- Domain-Sperre: Die Dateien einer Instanz werden nur über deren Domains (und die Domains der Instanzen, die sie lesen dürfen) ausgeliefert. Das verhindert, dass Dateien versehentlich über eine fremde Website verlinkt oder angezeigt werden. Eine Zugriffskontrolle ist es nicht (siehe Hinweis unten).
- Papierkorb: Wird ein Datensatz gelöscht, wandern seine Dateien mit in den Papierkorb und kommen bei einer Wiederherstellung zurück.
- Geschützte Felder: Dateien aus Feldern mit „Nur für angemeldete Frontend-User“ sind im Medienverzeichnis gesperrt und werden nur nach einer Prüfung ausgeliefert.
Wichtig: Die Domain-Sperre ist kein Zugriffsschutz. Welche Domain ein Request anspricht, entscheidet der Aufrufer: Er kann den Hostnamen frei setzen (Header
Host). Wer die Adresse einer Datei kennt, kann sie deshalb auch dann abrufen, wenn er sich als eine andere, berechtigte Domain derselben Installation ausgibt. Damit sind auch Dateien einer anderen Instanz auslesbar. Einen vollständigen Schutz erreichen Sie nur mit getrennten camindo-Installationen; vgl. Abschnitt Keine Mandantenfähigkeit.Vertrauliche Dateien schützt ausschließlich die Feldoption „Nur für angemeldete Frontend-User“. Das Verzeichnis des Feldes ist dann auf dem Server vollständig gesperrt (
Require all denied). Ausgeliefert wird nur überfile.php, und erst nachdem eine gültige Session eines Frontend-Users geprüft wurde (siehe Kapitel 13).
9 Strukturen exportieren und importieren
Mit dem XML-Export schreiben Sie ganze Strukturbäume in eine Datei: Ordner, Inhaltsbereiche mit allen Eingabefeldern und Einstellungen, Template-Bereiche mit ihren Templates und auf Wunsch alle Datensätze samt Dateien. Der XML-Import baut diese Struktur in derselben oder einer anderen camindo-Installation wieder auf.
Typische Anwendungen:
| Aufgabe | Vorgehen |
|---|---|
| Website-Struktur für eine neue Instanz vervielfältigen | Struktur und Templates exportieren, in eine neue Instanz importieren, Bereiche umbenennen |
| Entwicklung auf die Live-Website übertragen | Auf der Testumgebung entwickelte Bereiche, Felder und Templates exportieren und auf dem Live-System importieren – vorhandene Bereiche werden aktualisiert |
| Template-Sätze weitergeben | eine Funktion mit ihren Inhaltsbereichen und Templates als Paket bereitstellen (siehe unten) |
| Bereiche sichern | Struktur und Inhalte vor einem größeren Umbau sichern |
Export und Import ganzer Strukturen sind Superusern vorbehalten. Den Export und Import der Datensätze eines Bereichs beschreibt das Handbuch für Anwender.
Exportieren
Öffnen Sie das Modul „Inhalte“ und wählen Sie auf der Startseite im Menü „Export“. Die Maske zeigt den Baum aller Ordner und Bereiche aller Typen mit Checkboxen, gruppiert nach Instanzen: Jede Instanz erscheint wie ein Ordner mit ihrem Namen, darunter ihre Ordner und Bereiche. Ein Ordner oder eine Instanz wählt die enthaltenen Elemente mit an; einzelne lassen sich wieder abwählen.
| Option | Wirkung |
|---|---|
| Struktur exportieren | Ordner, Inhaltsbereiche und Eingabefelder mit allen Einstellungen (auch dem Slug-Prefix und der Lösch-Policy), Template-Zuweisungen (auch die Trigger-Templates in ihrer Reihenfolge), den Konvertern der Thumbnail-Felder und den Snippets der Instanz, auf die Beschriftungen verweisen (#custom.…) |
| Inhalte exportieren | die Datensätze der angehakten Inhaltsbereiche (alle Felder, alle Sprachen) und die Templates der angehakten Template-Bereiche – samt den Snippets der Instanz, die diese Templates verwenden (custom.…) |
| Upload-Dateien mit exportieren | die Dateien der Datensätze kommen mit in die Zip-Datei |
| Templates für Import in Fremddatenbank optimieren | markiert Verweise in den Templates, damit sie beim Import in eine andere Installation angepasst werden (siehe unten) |
| Als Hintergrundprozess ausführen | der Download-Link kommt als interne Nachricht |
Das Ergebnis ist eine Zip-Datei mit der XML-Datei und ggf. den Dateien. Der Download-Link gilt einmal; nicht abgeholte Dateien werden nach 24 Stunden gelöscht.
Die Datei enthält verschlüsselte Inhalte verschlüsselt und Passwörter nur als
Prüfwert. Beides hängt an der Schlüsseldatei .camindo.key: In einer Installation mit
anderem Schlüssel sind verschlüsselte Inhalte nicht lesbar, und importierte
Passwörter (etwa von Mitgliedern) passen nicht mehr – die Mitglieder müssen dann ein
neues Passwort anfordern.
Importieren
Im Modul „Inhalte“ wählen Sie auf der Startseite im Menü „Import“, laden die Zip- oder XML-Datei hoch (oder wählen sie aus dem Upload-Verzeichnis). Die Maske zeigt dann:
| Einstellung | Bedeutung |
|---|---|
| Instanz | Instanz für neu angelegte Bereiche. Aus derselben Installation kann auch die Instanz aus der Datei gelten |
| Zielebene für neue Ordner und Bereiche | Ordner, unter dem neu angelegte Bereiche landen. Bereiche, deren Ordner ebenfalls in der Datei ist, landen unter diesem. Angeboten werden nur die Ordner der gewählten Instanz (bei „aus der Importdatei“ alle) |
| Konverter der Thumbnail-Felder | je Konverter der Datei: einen vorhandenen verwenden, neu anlegen oder ignorieren (siehe unten) |
| je Bereich der Datei | Name (änderbar), Modus und Zuordnungskriterium – getrennt für Struktur, Datensätze und Templates |
Die Bereiche der Datei stehen eingerückt nach ihrer Hierarchie. Eine Auswahl in der Spaltenüberschrift setzt den Modus für eine ganze Spalte.
Verweisen Beschriftungen von Bereichen und Feldern auf Snippets der Instanz (Modul
„Snippets“, #custom.31.title), übernimmt der Import diese Snippets in das Set der
Zielinstanz und schreibt die Verweise darauf um (#custom.32.title). Vorhandene
Snippets der Zielinstanz bleiben unverändert; das Protokoll nennt die übernommenen und
die beibehaltenen Schlüssel.
Dasselbe gilt für die Snippets, die importierte Templates ausgeben – etwa
(CMS:SNIPPET custom.weiterlesen). Sie landen im Set der Instanz des Template-Bereichs,
die Templates selbst bleiben unverändert (die Kurzform custom.… meint immer das Set der
Instanz, in der die Seite läuft). Zusammengesetzte Schlüssel wie
"custom.status_{$cms['status']}" bringen alle Snippets mit diesem Anfang mit.
Das Slug-Prefix eines Bereichs wird über die Sprachkürzel den Sprachen der Zielinstanz zugeordnet. Ist es dort nicht zulässig – etwa weil ein anderer Bereich dasselbe Präfix führt –, entfällt es mit einem Hinweis im Protokoll.
Modus und Zuordnung
Für jeden Bereich wählen Sie getrennt für „Struktur“, „Datensätze“ und „Templates“ einen Modus – INSERT, UPDATE, UPDATE_OR_INSERT, REPLACE, REPLACE_OR_INSERT oder IGNORE (Bedeutung siehe Handbuch für Anwender) – und woran ein vorhandenes Element erkannt wird:
| Element | Zuordnung über |
|---|---|
| Bereich (Struktur) | Name oder Bereichsnummer |
| Datensätze | Slug oder Datensatznummer |
| Templates | Name oder Templatenummer |
Stammt die Datei aus derselben Installation, ist UPDATE_OR_INSERT vorgewählt: Vorhandenes wird aktualisiert, Fehlendes angelegt. Stammt sie aus einer anderen Installation, ist INSERT vorgewählt, und Nummern zählen nie als Kriterium – dort gehören sie zu ganz anderen Elementen. Zugeordnet wird dann nur über Namen und Slugs, neue Datensätze erhalten neue Nummern. Ein Bereich, den es im Ziel noch nicht gibt, kennt nur INSERT und IGNORE.
Bei REPLACE werden Eingabefelder, die die Datei nicht nennt, aus dem Bereich entfernt.
Was beim Import geschieht
- Bereiche werden in der Reihenfolge der Datei angelegt bzw. aktualisiert, Eltern vor Kindern.
- Die Konverter der Thumbnail-Felder werden zugeordnet: aus derselben Installation über ihre Nummer, sonst über ihre Einstellungen. Gibt es keinen passenden, wird er neu angelegt – sofern sein Prozessor installiert ist. Ein Thumbnail-Feld ohne Konverter wird übergangen.
- Eingabefelder, dann Templates (sie werden dabei neu übersetzt), dann die Einstellungen der Bereiche: Standard- und Sortierfeld, Standard-Template, Template-Zuweisungen, Trigger-Templates, Anmeldefelder. Die Lösch-Policy übernimmt der Import nur aus derselben Installation. Stammt die Datei aus einer anderen, erhält ein neu angelegter Bereich die Standard-Policy seines Typs („Datensatz löschen“, „Profil löschen“ bzw. „User-Generated-Content löschen“), und ein vorhandener behält seine.
- Die Datensätze in zwei Durchläufen: erst die Inhalte, dann die Verknüpfungen – mit den tatsächlichen Nummern der Zieldatenbank. Verknüpfungen zwischen importierten Datensätzen bleiben so erhalten, auch wenn sich alle Nummern ändern.
- Thumbnails und Volltexte werden neu erzeugt.
Wie beim Import eines einzelnen Bereichs zeigt eine Analyse vorher, was geschehen wird, und ein Protokoll danach, was geschehen ist – je Bereich, Feld, Template, Konverter und auf Wunsch je Datensatz.
Das Erstellungsdatum der Datensätze bleibt erhalten. Den Ersteller übernimmt der Import nur aus derselben Installation; sonst gilt der importierende Benutzer.
Eine Struktur vervielfältigen
Beispiel: Sie betreiben die Website eines Vereins und wollen dieselbe Struktur für einen zweiten Verein nutzen.
- Legen Sie die neue Instanz an (Modul „Instanzen“).
- Exportieren Sie den Ordner der ersten Website mit „Struktur exportieren“ und „Inhalte exportieren“ – so kommen die Templates mit. Datensätze, die nicht übernommen werden sollen, schließen Sie aus, indem Sie deren Bereiche beim Import für die Datensätze auf IGNORE stellen.
- Importieren Sie die Datei: Instanz = die neue Instanz, Modus INSERT.
Bereichsnamen müssen nur innerhalb einer Instanz und der Instanzen eindeutig sein,
die sie lesen darf bzw. von denen sie gelesen wird. Sind die beiden Websites
voneinander unabhängig, behalten die Bereiche ihre Namen, und die Templates
funktionieren unverändert. Andernfalls vergeben Sie in der Import-Maske neue
Namen, etwa
verein2_terminestatttermine. - Tragen Sie in der neuen Instanz Start-Datensatz und Start-Template ein.
Template-Sätze weitergeben
Ein Template-Satz besteht aus den Templates einer Funktion und den Inhaltsbereichen, die sie braucht (siehe Kapitel 2). Templates verweisen in ihren CMS-Befehlen auf andere Templates, auf Bereiche und manchmal auf einzelne Datensätze:
(CMS:INCLUDE header)
(CMS:SELECT news_liste filter[area]=meldungen src_id=1758 …)
In einer anderen Installation – oder nach dem Umbenennen beim Import – stimmen diese Namen und Nummern nicht mehr. Die Export-Option „Templates für Import in Fremddatenbank optimieren“ markiert solche Verweise in der Exportdatei. Der Import ersetzt sie durch die Namen und Nummern der importierten Elemente:
- Ein Bereich, der beim Import umbenannt wird, heißt auch in den Templates so.
- Ein Verweis auf einen Datensatz zeigt auf den importierten Datensatz; wurde er nicht mit importiert, auf den Datensatz mit derselben Adresse (Slug-Prefix und Slug) in der Instanz des Templates.
- Was sich nicht zuordnen lässt, behält den Wert aus der Datei; das Protokoll zählt diese Fälle.
So stellen Sie einen Template-Satz bereit:
- Legen Sie die Inhaltsbereiche und den Template-Bereich des Satzes in einem eigenen Ordner an. Halten Sie sich an die Namenskonventionen.
- Legen Sie bei Bedarf einige Beispiel-Datensätze an – sie zeigen nach dem Import sofort, wie der Satz funktioniert.
- Exportieren Sie den Ordner mit Struktur, Inhalten, Dateien und der Option „Templates für Import in Fremddatenbank optimieren“.
- In der Zielinstallation: importieren, Standard-Templates prüfen, die Gestaltung (HTML, CSS) an die Website anpassen.
Verweise, die ein Template erst zur Laufzeit berechnet (etwa aus PHP-Variablen), kann der Import nicht erkennen. Testen Sie einen importierten Template-Satz deshalb immer.
10 Weitere Module
Neben den Modulen für Inhalte, Struktur, Templates, Instanzen, Sprachen, Benutzer und Medien (Kapitel 3 bis 8) bringt camindo CMS weitere Module mit. Welche davon eine Benutzergruppe sieht, legen Sie in der Benutzergruppe fest – Papierkorb und Nachrichten hat jeder Benutzer.
Status
Im Modul „Status“ legen Sie die Bearbeitungszustände fest, die Datensätze haben können. Jeder Status hat ein Label, ein Icon, eine Farbe und eine Position in der Auswahlliste. Vorbereitet sind:
| Status | Bedeutung |
|---|---|
| Freigeschaltet | erscheint auf der Website |
| Deaktiviert | erscheint nicht auf der Website |
| Unbestätigt | für Registrierungen von Frontend-Usern, bis der Bestätigungslink angeklickt wurde |
Auf der Website erscheinen standardmäßig nur Datensätze mit Status „Freigeschaltet“. Standard für gesperrte Datensätze ist der Status „Deaktiviert“. Alle weiteren Status entsprechen diesem – sie dienen lediglich dazu, redaktionelle Abläufe abzubilden, z. B. „Entwurf“, „Gegenzulesen“, „Bereit zum Freischalten“, „Nachzubessern“ …
CMS:SELECT findet nur freigeschaltete Datensätze.
Ausschließlich für interne Ansichten ist es möglich, dem Befehl den Parameter filter[state]
mitzugeben, um Datensätze eines bestimmten oder beliebigen Status zu listen.
In der Eingabemaske eines Status legen Sie unter „Setzen dürfen“ fest, welche Benutzergruppen Datensätzen diesen Status geben dürfen (Mehrfachauswahl; Superuser dürfen immer alle Status setzen). Ein neuer Status ist zunächst für alle Benutzergruppen setzbar. Dieselbe Einstellung finden Sie im Formular jeder Benutzergruppe – siehe Benutzer und Rechte.
Beim Löschen eines Status wählen Sie einen Ersatz-Status; alle Datensätze mit dem bisherigen Status werden umgestellt. Die vorbereiteten Status „Freigeschaltet“ und „Deaktiviert“ können nicht gelöscht werden.
Snippets
camindo CMS kennt zwei Snippet-Systeme – zwei Wege, feste Texte getrennt von den Templates zu pflegen. Sie unterscheiden sich darin, wo die Texte stehen und in welchen Sprachen es sie gibt:
| Frontend-Snippets | Backend-Snippets | |
|---|---|---|
| Sprachen | die Sprachversionen der Instanz (z. B. de_DE, sv_SE) |
die Backend-Sprachen (z. B. de_DE, en_US) |
| Von wem gepflegt wird | Redakteure, wie jeder Inhalt – auch per Frontend-Editing | Entwickler (Sprachdateien) bzw. Benutzer (Modul „Snippets“) |
| Wo gespeichert wird | Datensätze eines Inhaltsbereichs mit mehrsprachigem Textfeld | Sprachdateien lang/{sprache}.ini und eigene Snippets im Modul „Snippets“ |
| Wie eingebunden wird | im Template (CMS:TEXT id=slug) oder (CMS:TEXT id=record_id) |
#präfix.schlüssel in den Feldern „Label“, „Anmerkung“ und „Tooltip“ |
Für Texte, die auf der Website erscheinen, sind die Frontend-Snippets der vorgesehene Weg: Sie folgen genau den Sprachen der Website.
Frontend-Snippets
Ein Frontend-Snippet ist ein gewöhnlicher Datensatz – etwa in einem
Inhaltsbereich „Textschnipsel“ mit einem Feld slug und einem mehrsprachigen
Textfeld text. Das Template holt den Text über den Slug oder die record_id:
<p class="hinweis">(CMS:TEXT id=versandhinweis)</p>
<p class="kontakt">(CMS:TEXT id=3109) (CMS:FED id=3109)</p>
Ohne field liest CMS:TEXT das Feld text des angegebenen Datensatzes, in der
Sprache der aufgerufenen Seite; ist ein Text nicht übersetzt, erscheint der Text der
Hauptsprache. Mit CMS:FED id=… erhält jeder Textbaustein sein eigenes Stift-Symbol
für das Frontend-Editing. Die Redaktion pflegt diese Texte wie alle Inhalte – mit
Status, Erscheinungsdatum und Rechten des Inhaltsbereichs. Ein Standard-Template
braucht der Bereich nicht.
Backend-Snippets
Backend-Snippets sind die Texte der Benutzeroberfläche. Sie stammen aus drei Quellen und werden über einen Präfix angesprochen:
| Quelle | Präfix | Beispiel |
|---|---|---|
| Eigene Snippets der Instanz (Modul „Snippets“, siehe unten) | custom.{instance_id} |
#custom.12.label_preis |
Core: Core/lang/{sprache}.ini |
keiner | #button_save |
Module: lang/ und backend/lang/ im Verzeichnis des Moduls |
Name des Moduls in Kleinbuchstaben | #area.field_area_slug_prefix |
In den Eingabefeldern „Label“, „Anmerkung“ und „Tooltip“ (Inhaltsbereiche und ihre Felder)
wird statt eines einsprachigen Textes der Verweis auf ein mehrsprachiges Snippet eingebunden – Form:
#präfix.schlüssel (siehe Kapitel 5). Das Backend setzt
beim Anzeigen den Text der Backend-Sprache des angemeldeten Benutzers ein
(intern über Cms::textOrSnippet()); die Extension Snippets
bietet dort eine Suche an.
Backend-Snippets sind auch im Frontend verfügbar: der Core verwendet sie
etwa für die Meldungen der CMS:USER_*-Befehle oder das Auslassungszeichen von
CMS:TEXT limit=…. Weil es Backend-Snippets nur in den Backend-Sprachen gibt, ist
jeder Sprachversion eine Backend-Sprache zugeordnet (Einstellung
„Backend-Sprache“ im Modul „Sprachen“):
de_DE und de_AT lesen beide die Snippets von de_DE. Eine Sprachversion, für die es
keine Backend-Übersetzung gibt, zeigt diese in en_US.
Templates können Backend-Snippets mittels $this->cms->snippet('custom.schlüssel') einbinden.
Zusatzsprachen nachinstallieren
Weitere Backend-Sprachen kommen als Übersetzungspakete in Form von .ini-Dateien.
Die Sprache steht am Anfang des Dateinamens: sv_SE.ini, sv_SE_core.ini, sv_SE_ext_password.ini.
Abgelegt werden diese in var/translation/translated/.
Wirksam wird ein Paket nach dem Neuaufbau des Snippet-Caches (Modul „Werkzeuge“, Reiter
„Entwickler“, oder auf der Kommandozeile mit php Core/cron/camindo.php refresh snippets).
Eigene Zusatzsprache entwickeln
Um das Backend von camindo CMS selbst in eine weitere Sprache zu übersetzen, kopieren Sie die Übersetzungs-Vorlagen
aus dem Verzeichnis var/translation/blueprint/.
en_US_core.ini wird zu {sprache}_core.ini, en_US_en_US.ini zu en_US_{sprache}.ini.
{sprache}_core.ini enthält alle Übersetzungen, en_US_{sprache}.ini registriert die neue
Sprache in der englischen Sprachversion und damit für alle anderen Sprachen.
Beispiel für eine en_US_no_NO.ini:
[backend]
backend_language_no_NO = "Norsk"
Beispiel für eine no_NO_core.ini:
[frontend]
core.yes = "Ja"
[backend]
core.button_save = "Lagre"
ext.datepicker.option_mode = "Modus"
Was ein Paket nicht übersetzt, erscheint auf Englisch.
Modul Snippets
Im Modul „Snippets“ pflegen Sie eigene Backend-Snippets – Beschriftungen wie „Weiterlesen“, „Suchen“ oder ein Hinweis im Seitenfuß – ohne Zugriff auf Server oder Templates, in allen Backend-Sprachen.
Jede Instanz hat ihr eigenes Snippet-Set. Das Modul listet die Instanzen, auf die Ihre Benutzergruppe Zugriff hat, mit dem Stand der Übersetzungen: welche Sprachen vollständig sind, welche teilweise übersetzt (mit Anzahl) und welche noch keine Texte haben. Ein Klick öffnet das Set als Tabelle: eine Zeile je Schlüssel, eine Spalte je angezeigter Sprache. Welche Sprachen als Spalten erscheinen, wählen Sie über „Sprachen“ oberhalb der Tabelle (Häkchen setzen, „Übernehmen“); ohne Auswahl sehen Sie nur Englisch. Die Auswahl gilt für alle Sets und bleibt erhalten, bis Sie sich abmelden.
Ein Klick auf eine Zeile öffnet die Maske mit allen Backend-Sprachen untereinander. Ein Rechtsklick öffnet das Kontextmenü: „Bearbeiten“ wie der Klick, „Kopieren“ öffnet eine neue Maske mit den Texten des Snippets – nur den Schlüssel geben Sie neu ein –, „Löschen“ zeigt das Snippet mit allen Texten und entfernt es nach Bestätigung in allen Sprachen. „Snippet hinzufügen“ legt ein neues an. Fehlende Übersetzungen erhalten den englischen Text. Schlüssel bestehen aus Kleinbuchstaben, Ziffern und Unterstrichen und lassen sich nach dem Anlegen nicht mehr ändern – Templates und Beschriftungsfelder verweisen über sie auf das Snippet.
| Verwendung | Schreibweise |
|---|---|
| in den Templates der eigenen Instanz | custom.{schlüssel} |
| in Templates anderer Instanzen | custom.{instance_id}.{schlüssel} |
| in Beschriftungsfeldern des Backends (Label, Anmerkung, Tooltip) | #custom.{instance_id}.{schlüssel} – die Extension „Snippets“ bietet dort eine Suche an |
Welche Snippet-Sprache im Frontend gilt, bestimmt die Einstellung „Backend-Sprache“ der jeweiligen Sprachversion.
Die Sets liegen unter var/custom/snippets/{instance_id}/lang/{sprache}.ini; wird die
Instanz gelöscht, wird auch ihr Set gelöscht. Sets im früheren PHP-Format
({sprache}.php, noch ältere de.php) wandelt der Neuaufbau des Snippet-Caches in
.ini-Dateien um – im Modul „Werkzeuge“ (Reiter „Entwickler“, „Snippets“), mit
php Core/cron/camindo.php refresh snippets und bei jedem upgrade. Gibt es zu einer
Sprache schon eine .ini-Datei, werden beide zusammengeführt; bei gleichem Schlüssel
gilt die .ini-Datei. Die alte Datei bleibt als {sprache}.php.bak liegen und kann
gelöscht werden, sobald die Snippets wieder stimmen.
Zeitplaner
Der Zeitplaner führt Aufgaben zeitgesteuert aus. Er setzt den minütlichen Cronjob voraus. Die Wartungsaufgaben – Backup, Papierkorb, temporäre Dateien, Fristen, Logs, Prüfungen – legt die Installation an (siehe Betrieb). Den Ausführungszeitpunkt können Sie anpassen.
| Aufgabe | Wirkung |
|---|---|
| URL-Aufruf | ruft eine Adresse auf (wahlweise mit Benutzername und Passwort) und speichert die Antwort unter var/custom/html/… oder verwirft sie – etwa um einen Export einer anderen Anwendung abzuholen oder einen Cache anzuwärmen. Dateinamen mit PHP-Endung sind nicht erlaubt |
| PHP-Aufruf | führt ein PHP-Script aus var/custom/php/ auf der Kommandozeile aus – für projekteigene Automatisierungen. Die Ausgabe wird wie beim URL-Aufruf unter var/custom/html/… gespeichert oder verworfen |
| Datenbank-Backup | schreibt eine vollständige Sicherung der Datenbank nach var/dbbackup/. backup-1.sql ist immer die neueste; ältere rücken nach (backup-2.sql …), über die eingestellte Anzahl hinaus werden sie gelöscht. Läuft höchstens einmal am Tag. Jede neue Sicherung wird geprüft: Ist sie kleiner als 10 KB oder fehlt die Schlusszeile -- Dump completed, wird sie verworfen und der Lauf gilt als fehlgeschlagen. Die Detailansicht der Aufgabe markiert unbrauchbare Dateien |
| Logs aufräumen | löscht Logdateien unter var/log/, die älter sind als die eingestellte Frist (Vorgabe 90 Tage). Sicherheitsprotokolle (security, csp) haben eine eigene, meist längere Frist (Vorgabe 365 Tage). Außerdem werden fehlgeschlagene Anmeldeversuche mit Name und IP-Adresse aus der Datenbank gelöscht (Vorgabe nach 30 Tagen). Empfohlen: täglich nachts. Das Audit-Log hat eigene Fristen |
| Frontend-Cache aufräumen | löscht abgelaufene Dateien des Ausgabe-Caches unter var/cache/include/, den Templates mit CMS:INCLUDE … caching=… anlegen, dazu Dateien zu gelöschten oder seither geänderten Templates. Dateien mit unbegrenzter Frist bleiben, bis ihr Template geändert wird. Keine Einstellungen. Empfohlen: stündlich, etwa Minute 15, alle anderen * |
| Volltext neu aufbauen | baut den Volltext der gewählten Bereiche (ohne Auswahl: aller Bereiche) aus den Quellfeldern neu auf – nach einer Änderung der Quellfelder eines Volltextfelds. Die Datensätze selbst bleiben unverändert, das Audit-Log erhält keine Einträge. Reicht die maximale Ausführungszeit nicht, bricht der Lauf ab und gilt als fehlgeschlagen; erhöhen Sie sie dann |
| Papierkorb leeren | löscht Datensätze, Eingabefelder und Inhaltsbereiche endgültig, die länger als admin.trash_retention_days (Vorgabe 7 Tage) im Papierkorb liegen. Keine Einstellungen |
| Temporäre Dateien löschen | räumt var/tmp/ auf (admin.tmp_retention_hours) und löscht abgelaufene Exportdateien (admin.export_retention_hours). Keine Einstellungen. Empfohlen: stündlich |
| Lösch-Policies anwenden | führt die fälligen Aufträge der Lösch-Policies aus. Keine Einstellungen |
| Aufbewahrungsfristen anwenden | kürzt IP-Adressen, löscht abgelaufene Einträge des Audit-Logs, alte interne Nachrichten und nie bestätigte Registrierungen – nach den Fristen der Konfiguration; dazu die Fristen installierter Zusatzmodule, etwa gelöschte Chats des KI-Assistenten. Keine Einstellungen |
| Audit-Log prüfen | prüft die Dateien des Audit-Logs auf Manipulation; Befunde erscheinen auf der Startseite. Keine Einstellungen |
| Nach Updates suchen | sucht neuere Versionen und bekannte Sicherheitslücken (siehe Updates). Keine Einstellungen |
| Nachrichten per E-Mail zusammenfassen | schickt Benutzern, die es in ihren persönlichen Einstellungen gewählt haben, eine Zusammenfassung ihrer neuen internen Nachrichten (siehe Nachrichten). Neu sind die Nachrichten seit dem vorigen Lauf – einmal täglich ausführen. Keine Einstellungen |
| Template | führt ein Frontend-Template mit der Verwendung „Zeitgesteuert“ aus, in einer Sprache seiner Website – etwa für E-Mails zum Ablauf einer Sperrfrist, Erinnerungen oder einen Feed. Das Template erfährt, welcher Zeitraum seit dem letzten erfolgreichen Lauf vergangen ist; schlägt ein Lauf fehl, holt der nächste diesen Zeitraum nach. Die Ausgabe wird wie beim URL-Aufruf gespeichert oder verworfen. Meldet das Template einen Fehler (etwa eine E-Mail ohne gültigen Empfänger), gilt der Lauf als fehlgeschlagen |
Die Zeitsteuerung folgt der Cron-Schreibweise mit sechs Angaben: Minute, Stunde,
Tag, Monat, Jahr, Wochentag (0 = Sonntag). Je Angabe: * für jeden Wert, eine Zahl,
einen Bereich 1-5, einen Schritt */10 oder eine Liste 1,15,30. Die Aufgabe läuft,
wenn alle sechs Angaben zutreffen. Beispiel für täglich um 3:30 Uhr: Minute 30,
Stunde 3, alle anderen *. Die Zeiten gelten in der Zeitzone des Systems.
Ausgaben und Scripte getrennt: Abgeholte oder erzeugte Inhalte landen nur unter
var/custom/html/, ausführbare Scripte liegen nur unter var/custom/php/. So kann
eine Antwort, die ein URL-Aufruf abholt, nie als PHP-Script ausgeführt werden.
Pfadangaben dürfen nicht aus dem jeweiligen Verzeichnis herausführen (kein .., keine
Verknüpfungen nach außen). Bestehende Scripte verschieben Sie beim Update nach
var/custom/php/.
Ausführen als: Jede Aufgabe läuft unter einem Benutzer und mit dessen
Rechten; im Audit-Log erscheint er mit der Herkunft „scheduler“. Neue
Aufgaben laufen unter dem Benutzer scheduler, den die Installation anlegt
(Benutzergruppe Superuser, ohne Anmeldung im Backend). Zur Auswahl stehen Benutzer, deren
Benutzergruppe die Oberfläche „Kommandozeile
(CLI)“ benutzen darf. Wird der Benutzer gelöscht oder gesperrt oder verliert seine
Benutzergruppe dieses Recht, schlägt die Aufgabe mit einem Hinweis fehl, bis Sie ihr einen
anderen zuweisen. Ein PHP-Script arbeitet über die API unter diesem Benutzer
(siehe Entwicklerdokumentation).
Weitere Einstellungen: aktiv/inaktiv, maximale Ausführungszeit und ob jeder Lauf ins Systemprotokoll geschrieben wird (Fehler immer). Die Liste zeigt nächsten und letzten Lauf mit Ergebnis; „Jetzt ausführen“ startet eine Aufgabe sofort als Hintergrundprozess.
Werkzeuge
Das Modul „Werkzeuge“ hat fünf Reiter; für jeden gibt es ein eigenes Zusatzrecht.
| Reiter | Werkzeuge |
|---|---|
| „Server“ | Versionen von camindo CMS, Betriebssystem, Webserver, Datenbank und PHP; Prüfung und Erneuerung der .htaccess-Datei; „Datensatz-Cache leeren“ – für alle Websites, eine Website oder einen Bereich; MySQL-Konfiguration; Verfügbarkeit von ImageMagick und ffmpeg; PHP-Info |
| „Datenbank“ | „Papierkorb leeren“ – endgültiges Löschen von Datensätzen, Eingabefeldern und Bereichen, die älter als n Tage im Papierkorb liegen (0 = alles); „Arbeitskopien verwerfen“ – liegen gebliebene Arbeitskopien älter als n Stunden entfernen und die Originale wieder freigeben |
| „Daten“ | „Thumbnails neu erzeugen“ für alle Datensätze eines Bereichs (siehe Kapitel 8); „Baum normalisieren“ – prüft und repariert die Reihenfolge in Bereichen mit Baumstruktur, falls sie etwa durch direkte Datenbankeingriffe durcheinandergeraten ist; die bestehende Reihenfolge bleibt erhalten |
| „Papierkorb eines Users“ | Profil und Beiträge eines Website-Users, die im Papierkorb liegen, sofort endgültig löschen – etwa auf Verlangen des Users (siehe Kapitel 15) |
| „Entwickler“ | Caches erneuern (Snippets, Backend-Vorlagen, Instanzen); Template-Dateien neu übersetzen und mit var/templates abgleichen (samt Parser-Meldungen – auf der Kommandozeile php Core/cron/camindo.php cache templates, bei upgrade automatisch); Zugriffsregeln des Medienverzeichnisses erneuern; Sitzungsdaten anzeigen |
Die Caches erneuert camindo CMS nach Änderungen selbst. Die Werkzeuge auf dem Reiter „Entwickler“ brauchen Sie nur nach Eingriffen am Dateisystem oder zur Fehlersuche.
Template-Meldungen (Widget)
Das Modul „Templates“ bringt ein Widget für die Startseite mit (persönliche
Einstellungen, „Widgets der Startseite“): Es listet jedes Template mit Parser-Meldungen – Fehler rot, Hinweise gelb – und
öffnet es per Klick. Das hilft vor allem, wenn Templates im Dateisystem
(var/templates) bearbeitet werden und niemand den Editor sieht. Dazu steht immer der
Hinweis, dass jedes Script im Template <script(CMS:NONCE)> braucht, damit es unter der
Script-Policy der Website läuft (Kapitel 3).
Sichtbar ist es für Benutzergruppen mit Zugriff auf das Modul „Templates“; gezeigt werden nur
Template-Bereiche, die die Benutzergruppe lesen darf.
Logdateien
Das Modul „Logdateien“ (nur Superuser) macht die Protokolle unter var/log/ im
Backend recherchierbar. Filtern lässt sich nach Protokoll, Tag, Art und Suchtext.
Die Trefferliste zeigt die neuesten Einträge zuerst, je Seite 100; „Ältere Einträge“
und „Neuere Einträge“ blättern weiter, die Filter bleiben dabei erhalten.
Die Einträge sind nach Arten eingeordnet, in der Reihenfolge ihrer Dringlichkeit:
| Art | Beispiele |
|---|---|
| Gesperrte Anmeldungen | zu viele Fehlversuche bei der Anmeldung |
| Sicherheit | Anzeichen für Manipulationen |
| Nicht versendete E-Mails | Fehler beim E-Mail-Versand |
| PHP-Fehler | Programmabbrüche |
| Datenbankfehler | fehlerhafte Datenbankabfragen |
| Hintergrundprozesse | Fehler bei Import, Export, Stapelverarbeitung, Thumbnails |
| PHP-Warnungen, Sonstiges | Hinweise |
Das Widget „Logdateien“ fasst die wichtigsten Meldungen der letzten Tage auf der Startseite zusammen.
Audit-Log
Das Audit-Log hält fest, wer wann was geändert hat – mit dem Stand vorher und nachher. Protokolliert werden:
- jedes Anlegen, Ändern, Löschen (Papierkorb), Wiederherstellen und endgültige Löschen von Datensätzen, Bereichen, Feldern, Templates, Benutzern, Benutzergruppen, Instanzen, Sprachen, Status, Konvertern, Zeitplaner-Aufgaben und Komponenten, gleich ob über die Eingabemaske, das Frontend (Beiträge von Website-Usern), einen Import, die Stapelverarbeitung oder die Zeitplaner-Aufgabe „Papierkorb leeren“
- fehlgeschlagene Anmeldungen am Backend; erfolgreiche An- und Abmeldungen nur mit
audit.log_logins = true(Vorgabe: nicht aufzeichnen) - jeder Datenexport personenbezogener Daten
- jede Änderung durch eine Lösch-Policy (Aktion „Datenschutz“)
Bei Änderungen werden alle Felder verglichen, auch Metafelder wie Status, Veröffentlichungsdatum oder Owner, bei mehrsprachigen Feldern jede Sprache einzeln. Gespeichert wird nur, was sich tatsächlich geändert hat; ein Speichern ohne Änderung erzeugt keinen Eintrag. Passwörter erscheinen nie im Klartext, nur als „geändert“. Verschlüsselte Felder bleiben im Protokoll verschlüsselt und werden erst bei der Anzeige entschlüsselt. Private Nachrichten zwischen Benutzern werden nicht protokolliert, ebenso wenig der Volltext: Er ist aus den Textfeldern abgeleitet, und die Zeitplaner-Aufgabe „Volltext neu aufbauen“ hinterlässt keine Einträge.
Reiter „Änderungen“: In der Detailansicht jedes Datensatzes zeigt der Reiter „Änderungen“ die letzten zehn Einträge seines Verlaufs, neueste Änderung zuerst; den vollständigen Verlauf zeigt das Modul „Audit-Log“. In Auswahlfenstern (Verknüpfungsfelder) gibt es den Reiter nicht. Je Feld stehen Vorher und Nachher nebeneinander. Texte werden absatzweise verglichen: Unveränderte Absätze sind grau, entfernte rot, neue grün; in geänderten Absätzen sind die einzelnen Wörter markiert. Den Reiter sieht jeder, der den Bereich lesen darf; die IP-Adresse nur Superuser.
Denselben Reiter „Änderungen“ haben die Detailansichten von Bereichen, Eingabefeldern, Templates, Status, Instanzen, Sprachen, Konvertern, Zeitplaner-Aufgaben, Komponenten und Benutzergruppen – jeweils für alle, die die Detailansicht öffnen dürfen. Bei Benutzern sehen ihn nur Superuser; er zeigt, was am Konto geändert wurde (auch Anmeldungen), der Reiter „Aktivitäten“ daneben, was der Benutzer selbst getan hat. Bei Templates wird der Quelltext verglichen; die eingefärbte Ansicht, die daraus entsteht, erscheint nicht im Protokoll.
Modul „Audit-Log“ (nur Superuser): Durchsucht das gesamte Protokoll nach Zeitraum,
Benutzer, Aktion, Objektart, Id, Bezeichnung, Name oder IP-Adresse und nach
geänderten Feldern (etwa status_id), seitenweise wie die übrigen Listen. Ein Klick auf einen Eintrag öffnet den
Vergleich; „Gesamter Verlauf“ zeigt alle Einträge zu diesem Objekt.
Recherche über die API und den KI-Assistenten: Dieselben Einträge lassen sich über die Programmierschnittstelle suchen und lesen – so kann auch der KI-Assistent Fragen beantworten wie „Wer hat gestern den Artikel X gelöscht?“ oder „Wie hat sich dieser Datensatz seit seiner Erstellung verändert?“, auch wenn der Datensatz im Papierkorb liegt oder endgültig gelöscht ist. Superuser sehen dabei das ganze Protokoll; alle anderen – wie im Reiter „Änderungen“ – nur die Einträge zu Datensätzen in Bereichen, die sie lesen dürfen, und keine IP-Adressen.
Reiter „Aktivitäten“: In der Detailansicht eines Benutzers (Modul „Benutzer“) zeigt der Reiter „Aktivitäten“ nur Superusern, was dieser Benutzer im Audit-Log hinterlassen hat: oben die zuletzt bearbeiteten Datensätze – je Datensatz die letzte Aktion mit Zeitpunkt und die Zahl seiner Einträge, ein Klick darauf öffnet den Verlauf –, darunter alle Aktionen seitenweise, einschließlich Anmeldungen und Änderungen an Bereichen oder Feldern. „Im Audit-Log öffnen“ führt ins Modul, vorgefiltert auf diesen Benutzer.
Aufbewahrung: Einstellungen in .camindo.php (siehe
Konfiguration):
| Schlüssel | Vorgabe | Bedeutung |
|---|---|---|
audit.retention_days_changes |
0 |
Einträge zu bestehenden Objekten, in Tagen. 0 = unbegrenzt: Jeder Datensatz bleibt bis zu seiner Entstehung nachvollziehbar |
audit.log_logins |
false |
Erfolgreiche An- und Abmeldungen am Backend aufzeichnen. Sie sagen nichts über Änderungen, wohl aber über Arbeitszeiten – deshalb aus |
audit.retention_days_logins |
90 |
An- und Abmeldungen sowie fehlgeschlagene Anmeldungen, in Tagen. 0 = wie audit.retention_days_changes |
audit.retention_days_deleted |
365 |
Verlauf endgültig gelöschter Objekte, gezählt ab dem endgültigen Löschen (nach dem Papierkorb). 0 = unbegrenzt. Gilt nicht für Datensätze: Deren Verlauf überschreibt oder löscht die Lösch-Policy des Bereichs |
audit.enabled |
true |
Audit-Log ein- oder ausschalten |
audit.page_bytes |
1048576 |
Größe in Bytes, ab der die Datei eines Objekts unter var/audit/ eine neue Seite beginnt |
Abgelaufene Einträge entfernt die Zeitplaner-Aufgabe „Aufbewahrungsfristen anwenden“ (Vorgabe: jede Nacht).
Datenschutz
Das Modul „Datenschutz“ hat diese Reiter:
| Reiter | Inhalt | Zusatzrecht |
|---|---|---|
| „Lösch-Policies“ | legen fest, was beim Löschen eines Datensatzes geschieht – in den Papierkorb legen, sofort oder zeitversetzt endgültig löschen, einzelne Felder überschreiben, den Verlauf im Audit-Log überschreiben oder löschen, eigene Regeln im Trigger-Template ausführen – auch für Unterdatensätze, die Beiträge eines gelöschten Profils und die Datensätze eines gelöschten Bereichs. Jeder Inhaltsbereich hat eine Policy | „Lösch-Policies anlegen und ändern“ – für die Instanzen, auf die die Benutzergruppe Zugriff hat |
| „Vorlagen“ | Vorlagen der Datenauskunft je Instanz, Art (Website-User oder Benutzer) und Sprache – siehe Kapitel 15 | „Vorlagen der Datenauskunft pflegen“ – für die Instanzen, auf die die Benutzergruppe Zugriff hat |
| „Datenexport“ | Datenexport personenbezogener Daten eines Website-Users oder eines Benutzers als Zip | „Personenbezogene Daten exportieren“ – für Profile der lesbaren Bereiche und Benutzer der sichtbaren Benutzergruppen |
| „Gelöschte Benutzer“ | Liste der gelöschten Benutzer mit Benutzergruppe und Löschdatum – nur aus den Benutzergruppen, deren Benutzer Sie im Modul „Benutzer“ sehen dürfen. Ein Klick führt auf die Infoseite des Benutzers im Modul „Benutzer“; ist er noch nicht anonymisiert, steht dort die Schaltfläche „Anonymisieren“. Siehe Kapitel 15 | Reiter: Zugriff auf das Modul „Benutzer“. Anonymisieren: „Gelöschte Benutzer anonymisieren“ – für Benutzer der sichtbaren Benutzergruppen |
Lesen dürfen die Policies alle Benutzer mit Zugriff auf das Modul. Die drei Standard-Policies und Policies für alle Instanzen ändert nur ein Superuser. Ausführlich: Kapitel 15.
Komponenten
Das Modul „Komponenten“ zeigt alle Module, Medien-Prozessoren und Extensions mit Herkunft (Core oder Zusatz), Version und Zustand:
| Zustand | Bedeutung |
|---|---|
| Core | Bestandteil des Core, immer aktiv |
| entdeckt – nicht installiert | die Dateien sind vorhanden, die Komponente ist aber noch nicht eingerichtet |
| installiert, inaktiv | eingerichtet, aber abgeschaltet |
| aktiv | in Backend und Frontend verfügbar |
| Update wartet | neuere Dateien liegen vor; „Aktualisieren“ zieht die Datenbank nach |
| verwaist – Dateien fehlen | die Dateien wurden entfernt, ohne die Komponente zu deinstallieren |
Die Aktionen „Installieren“, „Aktivieren“, „Deaktivieren“, „Aktualisieren“ und „Deinstallieren“ erklären in ihrer Maske, was sie tun. Beim Deinstallieren bleiben Tabellen und Daten erhalten, sofern Sie nicht ausdrücklich „Tabellen und Daten löschen“ wählen; auf Wunsch wird vorher die Datenbank gesichert. „Abgleich“ vergleicht die vorhandenen Dateien mit der Datenbank.
Die Dateien einer Komponente holt und entfernt immer Composer auf der
Kommandozeile (composer require … / composer remove …, siehe
Installation); das
Modul richtet sie in der Datenbank ein.
Papierkorb
Das Modul „Papierkorb“ hat jeder Benutzer, unabhängig von seiner Benutzergruppe; es erscheint als Schaltfläche auf der Startseite und als Widget, das die Anzahl der Einträge zeigt. Wie Redakteure damit arbeiten, beschreibt das Handbuch für Anwender.
Jeder Eintrag steht für einen Löschvorgang: Wird ein Datensatz mit seinen untergeordneten Datensätzen gelöscht, erscheint nur der oberste; fest verbundene Inhalte, die Datensätze und Eingabefelder eines gelöschten Bereichs, das Gegenfeld einer Verknüpfung und die Dateiversionen eines Upload-Feldes erscheinen gar nicht einzeln. „Wiederherstellen“ holt immer alles zurück, was im selben Vorgang gelöscht wurde – erkannt am identischen Löschzeitpunkt. Was vorher schon in einem eigenen Vorgang gelöscht worden war, bleibt im Papierkorb.
| Wer | sieht |
|---|---|
| jeder Benutzer | „Von mir gelöschte Datensätze“ – aus Bereichen, auf die er Zugriff hat, und nicht aus gelöschten Bereichen |
| Superuser | zusätzlich „Gelöschte Bereiche“ (mit Instanz, Umfang und wer gelöscht hat), „Gelöschte Eingabefelder“ (mit Bereich, Gegenfeld und Dateiversionen, die mitgelöscht wurden) und über „Alle Benutzer“ die gelöschten Datensätze aller Benutzer |
Wiederherstellen setzt das Löschrecht im Bereich voraus (siehe
Bereichsrechte); fehlt es, steht bei dem Eintrag
„keine Berechtigung“. Wie lange Einträge im Papierkorb bleiben, bestimmt die
Aufbewahrungsfrist. Große Vorgänge (mehr Datensätze als
admin.mass_delete_threshold) laufen wie beim Löschen als Hintergrundprozess.
Nachrichten
Die internen Nachrichten zwischen Benutzern erreichen Sie über das
Brief-Symbol in der Seitenleiste. Sie sind im
Handbuch für Anwender beschrieben.
Nachrichten werden privacy.message_days Tage (Vorgabe 60) nach dem Versand
automatisch gelöscht; alle Nachrichten eines Benutzers löscht ein Superuser in dessen
Einstellungen (siehe Kapitel 15).
Jeder Benutzer kann sich in seinen persönlichen Einstellungen eine tägliche Zusammenfassung per E-Mail schicken lassen: ungelesene Nachrichten je Absender und die neuen mit Datum, Absender und Betreff – ohne Nachrichtentexte, ohne Inhalte aus Datensätzen und ohne Link ins Backend. Verschickt wird sie von der Zeitplaner-Aufgabe „Nachrichten per E-Mail zusammenfassen“ (Vorgabe täglich 7:00), nur wenn seit dem vorigen Lauf neue Nachrichten eingegangen sind. Voraussetzung sind der E-Mail-Versand und eine E-Mail-Adresse im Konto des Benutzers. Bedenken Sie, dass Absender und Betreff damit das Haus verlassen.
Zusatzmodule
Zusatzmodule sind eigene Pakete, die Sie per Composer holen und als Komponente installieren (siehe Zusatzkomponenten installieren). Jedes bringt sein eigenes Handbuch mit: Nach der Installation erscheint es in der Übersicht der Handbücher unter „Handbücher der Zusatzkomponenten“ – mit Einrichtung, Einstellungen und allen Einzelheiten.
Zusatzmodul PDF
Das Zusatzmodul PDF (camindo/module-pdf) erzeugt PDF-Dokumente direkt aus
Templates – Rechnungen, Tickets, Datenblätter, Urkunden –, auf Wunsch auf einer
PDF-Vorlage wie einem Briefbogen, mit Texten, HTML, Bildern, Linien und Tabellen,
in RGB oder CMYK.
composer require camindo/module-pdf
php Core/cron/camindo.php component install Pdf --activate
Zusatzmodul KI-Assistent
Das Zusatzmodul KI-Assistent (camindo/module-ai) bringt ein Sprachmodell ins
Backend: Benutzer schreiben im Seitenpanel, was sie brauchen, und der Assistent sucht,
liest, legt an und ändert – mit den Rechten des Benutzers und erst nach Bestätigung.
Wie Redakteure damit arbeiten, beschreibt das
Handbuch für Anwender.
composer require camindo/module-ai
php Core/cron/camindo.php component install Ai --activate
Wer ihn nutzen darf, legen Sie über das Modul „KI-Assistent“ in der
Benutzergruppe fest.
Anbieter und Zugangsschlüssel stehen in der Konfiguration
(ai.*).
11 Extensions
Eine Extension erweitert ein Eingabefeld im Backend um zusätzliches Verhalten – einen Texteditor, einen Kalender, eine Symbolauswahl. Sie wird in der Felddefinition zugewiesen (Modul „Struktur“ → Bereich → Eingabefeld bearbeiten → Abschnitt „Erweiterung“). Die Einstellungen der Extension stehen darunter im Abschnitt „Einstellungen“. Ein Feld hat höchstens eine Extension, und angeboten werden nur die, die zum Feld- und Darstellungstyp passen.
Jede Core-Extension hat eine eigene Seite (Links in der Tabelle). Sie folgen als Unterseiten auf dieses Kapitel – „Weiter“ führt erst durch sie und dann zu Kapitel 12.
Core-Extensions
Sie sind mit dem Core installiert und immer aktiv.
| Extension | Feldtypen / Darstellung | Was sie tut |
|---|---|---|
| Calendar („Kalender“) | Datum/Uhrzeit, Uhrzeit / einzeilig | die Datums- und Zeitauswahl des Browsers neben dem Feld; bei neuen Datumsfeldern (auch vom KI-Assistenten angelegten) vorausgewählt – „nach Feldtyp“, Minutenschritt 1 |
| Datepicker | Datum/Uhrzeit / einzeilig | Kalender in der Sprache und im Datumsformat des Benutzers |
| IconPicker („Icon-Auswahl“) | alle / einzeilig | Auswahl eines Symbols mit Vorschau, blätterbaren Kategorien und Suche über Name und Schlagwörter; Standard für das Icon eines Bereichs |
| Markdown (visuell) („MarkdownVisual“) | Kurzer/Langer Text / mehrzeilig | Markdown-Editor, der in der formatierten Ansicht bearbeitet; Quelltext über die Schaltfläche <> |
| HTML (visuell) („HTMLVisual“) | Kurzer/Langer Text / mehrzeilig | HTML-Editor, der in der formatierten Ansicht bearbeitet; Quelltext über die Schaltfläche <>. Wie Markdown (visuell), speichert aber HTML |
| Password („Passwort-Richtlinie“) | Passwort / Passwort | Anforderungen als Sprechblase, Stärke als Balken; der Server prüft dieselben Regeln. Standard für die Passwörter der Benutzer |
| Snippets („Snippet-Auswahl“) | alle / einzeilig | Auswahl eines Textbausteins (Snippet) über ein Suchfenster; schreibt einen Verweis #präfix.schlüssel ins Feld, der in der jeweiligen Backend-Sprache erscheint. Wird auch im Backend für „Label“-Felder verwendet. |
Zusatz-Extensions
Zusatz-Extensions sind eigene Pakete. Sie werden per Composer geholt und dann als Komponente installiert (siehe Zusatzkomponenten installieren):
composer require camindo/extension-{name}
php Core/cron/camindo.php component install {Name} --activate
Jede Zusatzkomponente bringt ihr eigenes Handbuch mit. Nach der Installation finden Sie es in der Übersicht der Handbücher unter „Handbücher der Zusatzkomponenten“.
Eigene Stylesheets für Editoren
Editor-Extensions bieten in ihren Einstellungen ein Stylesheet zur Auswahl an, mit
dem Sie die Darstellung im Editor an die Website angleichen. Die Dateien legen Sie
selbst unter var/extensions/{name}/ ab (Name kleingeschrieben, also
var/extensions/markdownvisual/ bzw. var/extensions/htmlvisual/) – alle
.css-Dateien dort erscheinen in der Auswahl.
Damit ein Stylesheet mehrere Felder unterschiedlich gestalten kann, trägt jeder
Editor eine CSS-Klasse, die Sie je Feld festlegen können (Vorgabe:
c9-{name}-{feldname}, z. B. c9-htmlvisual-teaser). Beispiele stehen in der
Beschreibung der jeweiligen Extension.
Extension Calendar (Kalender)
Core-Extension für Datums- und Zeitfelder (Feldtypen „Datum + Uhrzeit“, „Datum + Uhrzeit, zeitzonenabhängig“ und „Uhrzeit“, Darstellung einzeilig). Neben das Textfeld tritt die Datums- bzw. Zeitauswahl des Browsers; Aussehen und Sprache bestimmt daher der Browser, nicht camindo CMS.
Immer verfügbar, keine Installation nötig. Ein neues Datums- oder Zeitfeld bekommt sie automatisch („nach Feldtyp“, Minutenschritt 1) – auch wenn der KI-Assistent das Feld anlegt. Wer keine Extension will, wählt beim Anlegen „keine“.
Einstellungen je Feld
| Einstellung | Vorgabe | Bedeutung |
|---|---|---|
| Auswahl | nach Feldtyp | „nach Feldtyp“: Uhrzeit-Felder bekommen eine Zeitauswahl, alle anderen Datum und Uhrzeit. Fest wählbar: „Datum und Uhrzeit“, „nur Datum“, „nur Uhrzeit“ |
| Minutenschritt | 1 | Raster der Zeitauswahl in Minuten (1–60), z. B. 15 für Viertelstunden |
Verhalten
- Eine Auswahl schreibt den Wert in der internationalen Schreibweise ins Textfeld:
2030-09-26 14:30, bei „nur Datum“2030-09-26, bei „nur Uhrzeit“14:30. Das Backend versteht diese Form in jedem Gebietsschema und zeigt den Wert nach dem Speichern im Format des Benutzers an. - Ein Wert in internationaler Schreibweise im Textfeld erscheint auch in der Auswahl.
Werte im Landesformat (
26.09.2030) übernimmt die Auswahl nicht – das Textfeld selbst nimmt sie aber an. - Das Textfeld bleibt immer frei beschreibbar.
Soll der Kalender in der Sprache und im Datumsformat des Benutzers erscheinen, ist Datepicker die Alternative.
Extension Datepicker
Core-Extension für Datumsfelder (Feldtypen „Datum + Uhrzeit“ und „Datum + Uhrzeit, zeitzonenabhängig“, Darstellung einzeilig – nicht für „Uhrzeit“). Neben das Textfeld treten ein Kalender in der Sprache und im Datumsformat des Benutzers und – je nach Einstellung – ein Zeitfeld. Grundlage ist die Bibliothek vanillajs-datepicker.
Immer verfügbar, keine Installation nötig. Anders als Calendar wird sie nicht automatisch vorausgewählt.
Einstellungen je Feld
| Einstellung | Vorgabe | Bedeutung |
|---|---|---|
| Auswahl | nach Feldtyp | „nach Feldtyp“ und „Datum und Uhrzeit“: Kalender und Zeitfeld; „nur Datum“: nur der Kalender |
| Schaltflächen „Heute“ und „Löschen“ | an | „Heute“ wählt das heutige Datum, „Löschen“ leert das Feld |
| Kalenderwochen anzeigen | aus | Spalte mit den Kalenderwochen links im Kalender |
Bedienung
- Ein Klick in das Kalenderfeld öffnet den Kalender; ein Klick auf einen Tag übernimmt ihn und schließt den Kalender.
- und blättern einen Monat zurück bzw. vor; ein Klick auf Monat und Jahr in der Kopfzeile wechselt zur Monats-, Jahres- und Jahrzehntübersicht.
- Das Zeitfeld nimmt Stunden und Minuten.
- Monatsnamen, Wochentage und Wochenbeginn folgen dem Gebietsschema des Benutzers (persönliche Einstellungen, „Datums- und Zahlenformat“); fehlt eine Übersetzung, erscheint der Kalender auf Englisch.
Was ins Feld geschrieben wird
Der Wert steht im Textfeld so, wie das Backend Datumswerte anzeigt – im mittleren
Datumsformat des Benutzers, z. B. 26.09.2030, 14:30 (de_DE) oder
Sep 26, 2030, 2:30 PM (en_US). Die Uhrzeit wird nur angehängt, wenn sie nicht 00:00
ist. Umgekehrt übernimmt der Kalender beim Öffnen einen Wert im Anzeigeformat oder in
internationaler Schreibweise (2030-09-26 14:30) aus dem Textfeld. Das Textfeld bleibt
frei beschreibbar; Änderungen dort erscheinen sofort in Kalender und Zeitfeld.
Extension IconPicker (Icon-Auswahl)
Core-Extension für einzeilige Felder aller Feldtypen, die den Namen eines
Material-Symbols speichern (z. B. menu_book). Standard für das Icon eines
Inhaltsbereichs (Modul „Struktur“ → Bereich → Icon). Immer verfügbar, keine
Installation nötig, keine Einstellungen.
Bedienung
Rechts neben dem Feld zeigt eine Vorschau das eingetragene Icon; bleibt sie leer, ist der Name unbekannt oder das Feld leer. Die Schaltfläche öffnet das Auswahlfenster:
- Ohne Suchbegriff zeigt das Fenster die Icons einer Kategorie (Aktionen, Hinweise, Audio & Video, Kommunikation, Inhalt, Geräte, Editor, Dateien, Hardware, Zuhause, Bilder, Karten, Navigation, Benachrichtigungen, Orte, Suche, Soziales, Schalter); blättern durch die Kategorien.
- Das Suchfeld durchsucht alle Icons nach Name und Schlagwörtern (englisch,
aus dem Suchindex von Google Fonts, z. B.
book,calendar,person). Mehrere Begriffe müssen alle vorkommen. Die Eingabetaste übernimmt den Suchbegriff ins Feld: einen exakten Icon-Namen, sonst den einzigen Treffer, sonst den Text selbst (Leerzeichen werden zu_). - Ein Klick auf ein Icon schreibt seinen Namen ins Feld und schließt das Fenster. „Kein Icon“ leert das Feld.
- , die Esc-Taste oder ein Klick außerhalb schließen das Fenster ohne Änderung.
Der Name lässt sich auch direkt eintippen; die Vorschau folgt beim Tippen. Die Namen und alle Icons stehen unter fonts.google.com/icons (Stil „Material Symbols Outlined“).
Extension Markdown (visuell)
Core-Extension – Markdown-Editor für mehrzeilige Textfelder (Feldtypen „Kurzer Text“ und „Langer Text“): Redakteure bearbeiten die formatierte Ansicht wie in einem Textprogramm, der Markdown-Quelltext erscheint erst über die Schaltfläche <> und lässt sich dort auch bearbeiten. Das Feld enthält weiterhin Markdown.
Immer verfügbar, keine Installation nötig.
Was der Editor kann
Fett, kursiv, unterstrichen, Code im Text, Absatzformat (Absatz, Überschrift 1–6), Aufzählung und nummerierte Liste mit Unterpunkten, Zitat, Codeblock, Link, horizontale Linie, Zeilenumbruch, Sonderzeichen (Währungen, ®, ™, Striche, geschützte und schmale Leerzeichen, weiches Trennzeichen …), Ausrichtung links, zentriert, rechts, Schreibrichtung für markierte Abschnitte und Tabellen mit Kopfzeile. Bilder unterstützt er nicht.
Beim Einfügen übernimmt der Editor nur, was er darstellen kann: Formatierter Text aus Word, Google Docs oder Webseiten wird in Markdown übersetzt, eingefügtes Markdown auf die unterstützten Formate reduziert. Bilder, Farben, Schriften und Durchstreichen entfallen, der Text bleibt.
Wie Redakteure damit arbeiten, beschreibt das Handbuch für Anwender (Datensätze bearbeiten → Eingabefelder → Text).
Einstellungen je Feld
| Einstellung | Bedeutung |
|---|---|
| Werkzeugleiste | alle Schaltflächen, einfach (Fett, Kursiv, Absatzformat, Listen, Link), eigene Auswahl |
| Eigene Schaltflächen | nur bei eigene Auswahl: Namen durch Komma oder Leerzeichen getrennt, \| als Trennstrich – bold italic underline code heading ul ol outdent indent quote codeblock link hr br special align_left align_center align_right dir table undo redo |
| Mindesthöhe / Maximale Höhe | in Pixeln; ohne Maximum wächst der Editor mit dem Inhalt |
| Stylesheet | eine .css-Datei aus var/extensions/markdownvisual/ |
| CSS-Klasse | Klasse am Editor-Container; leer = c9-markdownvisual-{feldname} |
Die Schaltfläche <> (Quelltext) ist immer da. Tastenkürzel (etwa Strg+B) und das Einfügen wirken unabhängig davon, welche Schaltflächen Sie auswählen.
Markdown im Feld
Der Editor schreibt übliches Markdown und vier Erweiterungen:
| Markdown | Bedeutung |
|---|---|
++Text++ |
unterstrichen |
::: center … ::: |
Ausrichtung der eingeschlossenen Absätze (left, center, right) |
<br> |
Zeilenumbruch in einer Tabellenzelle |
U+2067 … U+2069 bzw. U+2066 … U+2069 |
Abschnitt rechts nach links bzw. links nach rechts (Unicode-Isolate, unsichtbare Zeichen; auch als ⁧ … ⁩ geschrieben) |
Unsichtbare Sonderzeichen (geschütztes Leerzeichen, weiches Trennzeichen …) stehen als Zeichen im Text.
Schreibrichtung: Das Feld schreibt in der Richtung seiner Sprache (Arabisch,
Hebräisch, Persisch, Urdu … von rechts nach links), einsprachige Felder in der Richtung
des Backends. Die Schaltfläche dir zeigt die Richtung an der Einfügemarke und stellt
einen markierten Abschnitt auf die Gegenrichtung um – im Markdown umschlossen von den
Unicode-Zeichen RLI (U+2067, rechts nach links) bzw. LRI (U+2066, links nach
rechts) und PDI (U+2069, Ende). Browser werten diese Zeichen selbst aus; die Ausgabe
im Template braucht nichts Besonderes. Im Editor ist ein solcher Abschnitt gestrichelt
umrandet. Ein harter Zeilenumbruch sind zwei Leerzeichen am Zeilenende.
Im Template geben Sie das Feld mit (CMS:TEXT feldname markdown=true) aus – der
Parameter kennt die Erweiterungen (siehe Handbuch für Template-Programmierer, CMS:TEXT).
Andere Markdown-Umwandler zeigen ++ und ::: als Text.
Stylesheet
Der Editor steht direkt in der Backend-Seite. Schränken Sie Regeln deshalb immer mit
der CSS-Klasse des Feldes ein – sonst treffen sie das ganze Backend. Die
Bearbeitungsfläche ist .c9-mdv-content:
.c9-markdownvisual-text .c9-mdv-content h1 { color: #036; }
.c9-markdownvisual-text .c9-mdv-content { font-family: Georgia, serif; }Extension HTML (visuell)
Core-Extension – HTML-Editor für mehrzeilige Textfelder (Feldtypen „Kurzer Text“ und „Langer Text“). Sie ist eine Kopie von Markdown (visuell) und bedient sich genauso: Redakteure bearbeiten die formatierte Ansicht wie in einem Textprogramm, der HTML-Quelltext erscheint erst über die Schaltfläche <> und lässt sich dort auch bearbeiten. Das Feld enthält HTML statt Markdown.
Immer verfügbar, keine Installation nötig.
Was der Editor kann
Dasselbe wie Markdown (visuell): Fett, kursiv, unterstrichen, Code im Text, Absatzformat (Absatz, Überschrift 1–6), Aufzählung und nummerierte Liste mit Unterpunkten, Zitat, Codeblock, Link, horizontale Linie, Zeilenumbruch, Sonderzeichen, Ausrichtung links, zentriert, rechts, Schreibrichtung für markierte Abschnitte und Tabellen mit Kopfzeile. Bilder, Klassen und Stile lassen sich im Quelltext angeben (siehe unten).
Beim Einfügen übernimmt der Editor nur, was er darstellen kann: Formatierter Text aus Word, Google Docs oder Webseiten wird auf die unterstützten Formate gestutzt, eingefügter Klartext, der wie Markdown aussieht, übersetzt. Bilder, Farben, Schriften, Klassen und Durchstreichen entfallen, der Text bleibt.
Im Quelltext (<>) geht mehr: Dort geschriebenes oder geändertes HTML behält zusätzlich eigene Attribute und Bilder (siehe „Klassen, Stile und Bilder“ unten). Alles andere wird beim Zurückschalten in die formatierte Ansicht und beim Speichern ebenso gestutzt. Vorhandenes HTML im Feld bleibt unverändert, bis der Text im Editor geändert wird – dann gelten dieselben Regeln.
Wie Redakteure damit arbeiten, beschreibt das Handbuch für Anwender (Datensätze bearbeiten → Eingabefelder → Text).
Einstellungen je Feld
| Einstellung | Bedeutung |
|---|---|
| Werkzeugleiste | alle Schaltflächen, einfach (Fett, Kursiv, Absatzformat, Listen, Link), eigene Auswahl |
| Eigene Schaltflächen | nur bei eigene Auswahl: Namen durch Komma oder Leerzeichen getrennt, \| als Trennstrich – bold italic underline code heading ul ol outdent indent quote codeblock link hr br special align_left align_center align_right dir table undo redo |
| Mindesthöhe / Maximale Höhe | in Pixeln; ohne Maximum wächst der Editor mit dem Inhalt |
| Stylesheet | eine .css-Datei aus var/extensions/htmlvisual/ |
| CSS-Klasse | Klasse am Editor-Container; leer = c9-htmlvisual-{feldname} |
Die Schaltfläche <> (Quelltext) ist immer da. Tastenkürzel (etwa Strg+B) und das Einfügen wirken unabhängig davon, welche Schaltflächen Sie auswählen.
HTML im Feld
Der Editor schreibt nur diese Elemente – Klassen, Stile und Bilder nur, wenn sie im Quelltext angegeben wurden:
| HTML | Bedeutung |
|---|---|
<p>, <h1> … <h6> |
Absatz, Überschrift |
<strong>, <em>, <u>, <code> |
fett, kursiv, unterstrichen, Code im Text |
<a href="…"> |
Link (nur http(s):, mailto:, tel:, ftp: und relative Adressen) |
<br> |
Zeilenumbruch |
<ul>, <ol start="…">, <li> |
Listen, verschachtelt für Unterpunkte |
<blockquote> |
Zitat |
<pre><code class="language-…"> |
Codeblock |
<hr> |
horizontale Linie |
<table> mit <thead>/<tbody>, <th>, <td> |
Tabelle, erste Zeile Kopfzeile |
style="text-align: left\|center\|right;" |
Ausrichtung an Absatz, Überschrift, Liste, Zitat, Tabelle; an Zellen als Spaltenausrichtung |
<bdi dir="rtl"> / <bdi dir="ltr"> |
Abschnitt rechts nach links bzw. links nach rechts |
<span>, <img> |
nur aus dem Quelltext, siehe unten |
Klassen, Stile und Bilder
Im Quelltext angegeben, bleiben erhalten:
| Was | Wo |
|---|---|
class, style, id, title, data-…, aria-…, lang, role |
an <p>, <h1> … <h6>, <ul>, <ol>, <blockquote>, <pre>, <hr>, <table> und an <span>, <strong>, <em>, <u>, <code>, <a> (<b>, <i>, <ins> werden zu <strong>, <em>, <u>) |
target, rel, hreflang, download, type, referrerpolicy |
zusätzlich an <a> |
<img> mit src, alt, title, width, height, loading, srcset, sizes, class, style, id sowie data-…, aria-…, lang, role |
im Text, auch in Links und Tabellenzellen; src nur http(s):, relative Adressen und data:image/… |
<p class="lead">Einleitung mit <span class="marker">Hervorhebung</span>.</p>
<p><a class="button" href="/kontakt">Kontakt</a></p>
<p><a href="https://example.com" target="_blank" rel="noopener">Partner</a></p>
<p><a href="#" data-mail="…" data-mail-text>name (at) example (Punkt) com</a></p>
<p><img src="/media/1/12/bild.jpg" alt="Showroom" width="600" loading="lazy"></p>
In der formatierten Ansicht wirken Klassen und Stile sofort (zusammen mit dem
Stylesheet des Feldes); Bilder erscheinen an ihrer Stelle und lassen sich wie ein
Zeichen löschen oder verschieben. Attribute wie data-…, aria-…, target oder id
wirken im Backend nicht, sie erscheinen nur im gespeicherten HTML – etwa für Skripte
Ihrer Website. Ändern lassen sich Attribute nur im Quelltext.
Eine Ausrichtung über die Schaltflächen ergänzt style um text-align; ein
text-align im Quelltext wird zur Ausrichtung des Blocks.
Nicht erhalten bleiben: Attribute an Listenpunkten und Tabellenzellen, <div> (wird
zum Absatz, Klassen entfallen), andere Attribute (Ereignisse wie onclick)
und andere Elemente. Eingefügtes HTML aus der Zwischenablage verliert Klassen,
Stile und Bilder weiterhin – kopieren Sie dagegen innerhalb des Editors, bleiben sie
erhalten.
Unsichtbare Sonderzeichen stehen als Entities im HTML: ,   (schmales
geschütztes Leerzeichen),  ,  , ­, ‑ (geschützter
Bindestrich). Das HTML ist zeilenweise eingerückt, damit der Quelltext lesbar bleibt.
Schreibrichtung: wie bei Markdown (visuell) – das Feld schreibt in der Richtung
seiner Sprache, einsprachige Felder in der Richtung des Backends. Ein markierter
Abschnitt in der Gegenrichtung wird zu <bdi dir="…">; im Editor ist er gestrichelt
umrandet.
Im Template geben Sie das Feld ohne Umwandlung aus:
<div class="text">(CMS:TEXT feldname entitydecode=false lbrconvert=false)</div>
entitydecode=false lässt maskierten Text (<) maskiert, lbrconvert=false
verhindert zusätzliche <br> an den Zeilenumbrüchen des Quelltextes.
Stylesheet
Der Editor steht direkt in der Backend-Seite. Schränken Sie Regeln deshalb immer mit
der CSS-Klasse des Feldes ein – sonst treffen sie das ganze Backend. Die
Bearbeitungsfläche ist .c9-htv-content:
.c9-htmlvisual-text .c9-htv-content h1 { color: #036; }
.c9-htmlvisual-text .c9-htv-content { font-family: Georgia, serif; }Extension Password (Passwort-Richtlinie)
Core-Extension für Felder vom Typ „Passwort“. Unter dem Feld zeigt ein Balken die Stärke des eingegebenen Passworts (rot = schwach, orange = mittel, grün = stark); beim Tippen erscheint eine Sprechblase mit den Anforderungen, erfüllte werden abgehakt. Solange eine Anforderung fehlt, bleibt der Balken rot.
Immer verfügbar, keine Installation nötig. Die Passwörter der Benutzer nutzen sie automatisch.
Prüfung auf dem Server
Die Anzeige ist nur eine Hilfe. Entscheidend ist, dass camindo CMS beim Speichern dieselben Regeln prüft – und das tut es für ein Feld genau dann, wenn es diese Extension trägt. Ein zu schwaches Passwort wird mit einer Meldung abgewiesen, die die fehlenden Anforderungen nennt („mindestens 2 Sonderzeichen, …“).
Einstellungen je Feld
Jede Regel lässt sich am Feld abweichend einstellen. Leere Felder übernehmen die Vorgabe
der Installation (security.password_policy, siehe
Betrieb) – sie steht grau im Feld.
| Einstellung | Vorgabe | Bedeutung |
|---|---|---|
| Mindestlänge | 12 | Anzahl Zeichen |
| Sonderzeichen (mindestens) | 1 | alles, was kein Buchstabe und keine Ziffer ist – auch Leerzeichen, Bindestrich, Punkt |
| Großbuchstaben (mindestens) | 1 | auch Umlaute und Buchstaben anderer Schriften |
| Kleinbuchstaben (mindestens) | 1 | |
| Ziffern (mindestens) | 0 | |
| Großbuchstabe am Anfang zählt nicht | ja | „Sommer2026!“ erfüllt die Regel nicht allein durch das große S |
0 bedeutet: keine Anforderung.
Im Frontend
Die Registrierung und das Kundenkonto einer Website nutzen dasselbe Script. Der Template-Programmierer kopiert es in das Template und markiert das Feld – siehe CMS:USER_PASSWORD_RULES.
Extension Snippets (Snippet-Auswahl)
Core-Extension für einzeilige Felder aller Feldtypen. Sie setzt statt eines festen
Textes einen Verweis auf ein Snippet ins Feld – #präfix.schlüssel –, der überall
im Backend in der Sprache des jeweiligen Benutzers erscheint. Standard für die
Beschriftungsfelder („Label“) der Module, etwa die Bezeichnung eines Bereichs oder
Feldes. Immer verfügbar, keine Installation nötig, keine Einstellungen.
Bedienung
- Beginnt der Wert mit
#, zeigt rechts neben dem Feld eine Vorschau den aufgelösten Text in der eigenen Backend-Sprache – oder „Snippet nicht gefunden“. - Die Schaltfläche öffnet das Suchfenster. Steht schon ein Verweis im Feld, ist er als Suchbegriff vorbelegt.
- Gesucht wird in Id und Text aller Snippets, ohne Groß-/Kleinschreibung; mehrere Begriffe müssen alle vorkommen. Gezeigt werden höchstens 50 Treffer – bei mehr grenzen Sie die Suche ein.
- Ein Klick auf einen Treffer schreibt
#+ Id ins Feld. „Nur Text (kein Snippet)“ entfernt das#; der Rest bleibt als normaler Text stehen. - , die Esc-Taste oder ein Klick außerhalb schließen das Fenster.
Markierungen an den Treffern: nur Backend – das Snippet gibt es nur in den Backend-Texten; ICU – ein Text mit Platzhaltern (Mehrzahl, Zahlen), in der Vorschau mit leeren Werten.
Welche Snippets erscheinen
Alle Snippets in der Backend-Sprache des Benutzers: die des Core (Id ohne Präfix), der
Module, Extensions und Prozessoren sowie die eigenen Snippets einer Website aus dem
Modul „Snippets“ (custom.{instance_id}.…, siehe Kapitel 10) –
diese nur für Websites, auf die die Benutzergruppe Zugriff hat.
Für eigene Beschriftungen legen Sie zuerst das Snippet im Modul „Snippets“ an (fehlende Übersetzungen erhalten den englischen Text) und wählen es dann hier aus. Ein Verweis auf ein Snippet, das es nicht gibt, erscheint im Backend als Id.
12 Betrieb und Wartung
Cronjobs
camindo CMS braucht einen Cronjob des Webserver-Benutzers (Einrichtung siehe Installation, Schritt 5):
| Cronjob | Takt | Aufgaben |
|---|---|---|
Core/cron/cron.php |
jede Minute | Hintergrundumwandlung von Videos und Bildern, Abgleich der Template-Dateien und die fälligen Aufgaben des Zeitplaners – darunter alle Wartungsaufgaben |
Läuft cron.php nicht, liegen zeitgesteuerte Aufgaben still, Template-Dateien, die im Dateisystem
geändert wurden, kommen nicht im Backend an, Videos bleiben unumgewandelt. Superuser sehen das auf
der Startseite: Unter den Modulkacheln erscheint dann ein Hinweis
(siehe Betriebshinweise).
Scheduler
Der Zeitplaner (Scheduler) erledigt wiederkehrende und aufwendige Arbeiten im
Hintergrund, ohne die Redaktion aufzuhalten. Er hängt am minütlichen Cronjob
cron.php: Jede Minute sucht dieser die fälligen Aufgaben und startet jede als eigenen
Hintergrundprozess – eine lange Aufgabe hält die anderen nicht auf. Eingerichtet
werden die Aufgaben im Modul „Zeitplaner“. Welche Arten es gibt und wie die
Zeitsteuerung geschrieben wird, beschreibt Kapitel 10.
Wartungsaufgaben: Die Installation legt diese Aufgaben an (Benutzer
scheduler, mit Protokoll). Die Ausführung kann – wie bei jeder anderen Aufgabe – terminiert,
ausgeschaltet oder gelöscht werden. Fehlt eine der Wartungsaufgaben oder ist sie
ausgeschaltet, erscheint ein Betriebshinweis.
| Aufgabe | Vorgabe | Was sie tut |
|---|---|---|
| Datenbank-Backup | täglich 2:00 | Sicherung nach var/dbbackup/, 7 rotierende. Empfehlung: zusätzlich außerhalb des Servers ablegen (siehe Datensicherung) |
| Temporäre Dateien löschen | stündlich :10 | var/tmp/ und abgelaufene Exportdateien (auch Datenauskünfte) aufräumen |
| Papierkorb leeren | täglich 2:20 | Einträge endgültig löschen, die länger als admin.trash_retention_days im Papierkorb liegen |
| Lösch-Policies anwenden | täglich 2:30 | fällige Aufträge der Lösch-Policies |
| Aufbewahrungsfristen anwenden | täglich 2:45 | IP-Adressen kürzen, abgelaufene Einträge des Audit-Logs, alte interne Nachrichten und nie bestätigte Registrierungen löschen (Kapitel 15), dazu die Fristen installierter Zusatzmodule – etwa gelöschte Chats des KI-Assistenten |
| Logs aufräumen | täglich 3:00 | alte Logdateien und Anmeldeversuche löschen (siehe Protokolle) |
| Frontend-Cache aufräumen | täglich 3:10 | abgelaufene Dateien des Ausgabe-Caches. Nutzen Templates caching mit kurzen Fristen, sollte diese Aufgabe stündlich eingerichtet werden. |
| Volltext neu aufbauen | täglich 3:20, nur veraltete Bereiche | baut die Bereiche neu auf, deren Volltext nach einer Strukturänderung als nicht mehr aktuell markiert ist. Nutzen Volltextfelder Quellen hinter einer „Verknüpfung“, ist für diese Bereiche eine zusätzliche Aufgabe sinnvoll. Ohne diese Option reicht wöchentlich oder manuell (siehe Volltext neu aufbauen) |
| Audit-Log prüfen | täglich 3:40 | Dateien des Audit-Logs auf Manipulation prüfen. Befunde zeigt die Startseite |
| Nach Updates suchen | täglich 3:55 | neuere Versionen und bekannte Sicherheitslücken (siehe Updates) |
| Nachrichten per E-Mail zusammenfassen | täglich 7:00 | E-Mail an die Benutzer, die die Zusammenfassung ihrer neuen internen Nachrichten eingeschaltet haben (siehe Nachrichten) |
Fehlende Wartungsaufgaben – etwa nach versehentlichem Löschen – legt der Befehl
php Core/cron/camindo.php scheduler defaults wieder an, vorhandene bleiben unverändert.
scheduler list zeigt alle Aufgaben, scheduler run trash (oder eine Id) führt eine
sofort aus.
Terminieren oder sofort ausführen: Eine Aufgabe läuft zu den Zeitpunkten ihrer Zeitsteuerung, solange sie aktiv ist. „Jetzt ausführen“ in ihrer Detailansicht startet sie sofort als Hintergrundprozess – auch eine inaktive. So richten Sie eine Aufgabe, die nur gelegentlich gebraucht wird (etwa „Volltext neu aufbauen“), einmal ein, lassen sie inaktiv und starten sie bei Bedarf von Hand.
Vorübergehend aussetzen: „Deaktivieren“ im Kontextmenü der Liste oder in der Detailansicht setzt eine Aufgabe aus, ohne ihre Einstellungen anzutasten – die Liste zeigt sie als „vorübergehend ausgesetzt“, ein nächster Lauf steht dann nicht an. „Reaktivieren“ lässt sie wieder nach ihrer Zeitsteuerung laufen.
Berichte: Eine Aufgabe vom Typ „URL-Aufruf“ oder „PHP-Aufruf“ lässt sich als
wählbarer Bericht markieren; dazu gehört mindestens eine Benutzergruppe. Benutzer
dieser Gruppen finden den Bericht in ihren persönlichen Einstellungen unter „Bericht
abonnieren“. Nach jedem erfolgreichen Lauf erhalten die Abonnenten die Ausgabe als
interne Nachricht im HTML-Format (aktive Inhalte wie Scripts werden entfernt, bei
einem ganzen HTML-Dokument nur der Inhalt von <body>, Ausgaben über 2 MB nur als
Hinweis). Die Detailansicht der Aufgabe zeigt die Zahl der Abonnenten.
Ergebnis und Fehler: Liste und Detailansicht zeigen nächsten und letzten Lauf mit
Ergebnis und Meldung. Fehler landen immer im Protokoll var/log/{Datum}_scheduler.log,
erfolgreiche Läufe nur mit der Einstellung „System-Logfile schreiben“. Fehlgeschlagene Aufgaben
meldet die Startseite den Superusern (siehe Betriebshinweise).
Maximale Ausführungszeit: Jede Aufgabe hat eine Obergrenze in Minuten. Wird sie überschritten, bricht der Lauf ab und gilt als fehlgeschlagen. Eine Aufgabe, die länger als diese Grenze plus fünf Minuten als „läuft“ markiert ist, gilt als abgebrochen und startet beim nächsten Termin neu.
Rechte: Jede Aufgabe läuft unter einem Benutzer und mit dessen Rechten – neue
unter dem Benutzer scheduler, den die Installation anlegt. Näheres in
Kapitel 10.
Papierkorb
Gelöschte Datensätze, Eingabefelder und Bereiche werden zunächst nur als gelöscht
markiert; die Dateien gelöschter Datensätze wandern nach var/deleted/, die eines
gelöschten Eingabefeldes bleiben gesperrt an ihrem Platz. Ob ein Datensatz überhaupt in den Papierkorb
kommt, bestimmt die Lösch-Policy
seines Bereichs. Endgültig gelöscht wird nach der
Aufbewahrungsfrist (admin.trash_retention_days, Vorgabe 7 Tage) durch die
Zeitplaner-Aufgabe „Papierkorb leeren“ (jede Nacht) – oder sofort über „Werkzeuge“ → „Datenbank“ → „Papierkorb leeren“.
Gelöschte Benutzer bleiben immer erhalten.
Innerhalb der Frist wird wiederhergestellt – samt untergeordneten Datensätzen, fest verbundenen Inhalten und Dateien:
- Datensätze holt jeder Benutzer selbst aus seinem Papierkorb zurück.
- Bereiche stellt ein Superuser im Papierkorb wieder her. Mit dem Bereich kommen seine Unterbereiche und alle Datensätze und Eingabefelder zurück, die mit ihm gelöscht wurden.
- Eingabefelder stellt ein Superuser im Papierkorb wieder her – samt Inhalten (siehe Eingabefeld löschen).
Ohne Backend geht es auch auf der Kommandozeile:
php Core/cron/mass_delete.php --table=record --id=1758 --mode=restore --withchilds=1 --admin=1
--id ist die Nummer des Datensatzes, --admin die Nummer eines Benutzers mit
den nötigen Rechten (etwa eines Superusers), unter dessen Namen die Wiederherstellung
läuft. --withchilds=1 holt die untergeordneten Datensätze zurück, die mit demselben
Vorgang gelöscht wurden. Für einen gelöschten Bereich samt
Datensätzen verwenden Sie --table=area.
Arbeitskopien
Bricht ein Redakteur die Bearbeitung ab, ohne „Abbrechen“ zu klicken – etwa weil er
den Browser schließt –, bleibt eine Arbeitskopie zurück. Sie sperrt den Datensatz
nur, bis sie 90 Minuten unverändert war (admin.edit_lock_sec); danach kann ein anderer den Datensatz
wieder öffnen. Liegen gebliebene Arbeitskopien entfernt „Werkzeuge“ → „Datenbank“ →
„Arbeitskopien verwerfen“ (Vorgabe: älter als 24 Stunden).
Datensicherung
Zu einer vollständigen Sicherung gehören:
| Was | Wo |
|---|---|
| Datenbank | per Zeitplaner (Aufgabe „Datenbank-Backup“) nach var/dbbackup/ oder mit eigenen Werkzeugen |
| Konfiguration | .camindo.php |
| Schlüsseldatei | .camindo.key (oder der Inhalt der Umgebungsvariablen CAMINDO_KEY, siehe Zugangsdaten aus Umgebungsvariablen) – ohne sie sind verschlüsselte Inhalte und Passwörter unbrauchbar. An einem sicheren Ort getrennt von den Datenbanksicherungen aufbewahren |
| Mediendateien | public/media/ |
| Projektdaten | var/templates/ (Template-Quelltexte),var/custom/ (Snippets, Scripte und Ausgaben des Zeitplaners),var/extensions/ (Stylesheets),var/modules/ (z. B. PDF-Vorlagen und Schriften),var/area_blueprints/ (eigene Baupläne),var/deleted/ (Papierkorb),var/translation/translated sofern eine eigene Backend-Übersetzung angelegt wurde. |
| Composer-Stand | composer.json und composer.lock – damit sich genau dieselben Versionen wieder installieren lassen |
| Änderungsprotokolle | var/audit/ – die Inhalte des Audit-Logs; nach dem Einspielen einer Datenbanksicherung gleicht audit restore sie mit der Datenbank ab |
Vor jedem Update und vor Änderungen an Komponenten legt camindo CMS automatisch eine
Datenbanksicherung in var/dbbackup/ an. Manuell: php Core/cron/camindo.php backup;
alte Sicherungen räumt php Core/cron/camindo.php backup prune --keep=5 ab.
Einzelne Bereiche lassen sich zusätzlich per XML-Export sichern und gezielt wiederherstellen.
Updates
cd /var/www/mysite
php Core/cron/camindo.php maintenance on
composer update
php Core/cron/camindo.php upgrade
php Core/cron/camindo.php maintenance off
Composer tauscht die Dateien von Core und Zusatzkomponenten aus; upgrade sichert
die Datenbank, zieht sie auf den neuen Stand und baut alle Caches neu.
Wartungsmodus: Während maintenance on gilt, antwortet die Website mit einer
Wartungsseite (HTTP 503), Hintergrundprozesse pausieren, und das Backend ist nur für
Superuser erreichbar. Eine eigene Wartungsseite legen Sie als
var/custom/maintenance.html ab. Passen Dateien und Datenbank nach einem
composer update nicht zusammen, schaltet camindo CMS von selbst in den
Wartungsmodus, bis upgrade gelaufen ist.
Zurück auf den vorherigen Stand: Wartungsmodus an, Datenbanksicherung aus
var/dbbackup/ einspielen, die vorherige composer.lock wiederherstellen und
composer install ausführen, dann upgrade und Wartungsmodus aus.
Update-Prüfung
Jede Nacht prüft die Zeitplaner-Aufgabe „Nach Updates suchen“ mit Composer, ob es neuere Versionen von camindo CMS
und der installierten Pakete gibt (composer outdated, direkte Pakete und ihre
Abhängigkeiten) und ob für installierte Pakete Sicherheitslücken bekannt sind
(composer audit). Das Ergebnis zeigt das Hauptmenü unter „Info“ – nur für
Superuser, mit Tabelle der Pakete und der Schaltfläche „Jetzt prüfen“.
Gemeldet werden nur Versionen, die composer update innerhalb der Versionsgrenzen auch
installiert. Eine neue Hauptversion eines Pakets erscheint nicht – sie erfordert eine
Änderung der composer.json. Auf der Startseite erscheint ein Betriebshinweis nur bei einer
neuen Version von camindo CMS und bei bekannten Sicherheitslücken; neuere Versionen anderer
Pakete stehen nur unter „Info“.
Die Prüfung braucht Netzzugang zu Packagist bzw. zu den Paketquellen und das Programm
composer auf dem Server (paths.composer, leer = Prüfung aus). Webserver und Cronjob starten
Composer ohne Shell – ein Alias aus der .bashrc gilt dort nicht. Tragen Sie deshalb den
absoluten Pfad oder die ganze Befehlszeile ein, zum Beispiel für ein composer.phar mit
eigener PHP-Version:
'composer' => '/usr/bin/php8.4 -d memory_limit=-1 /home/www/bin/composer/composer.phar',
Wörter mit Leerzeichen setzen Sie in doppelte Anführungszeichen. JavaScript-Bibliotheken, die camindo CMS als Dateien mitbringt (jQuery, Bootstrap, Editoren), kommen mit dem Update von camindo CMS.
Die Kommandozeile
Alle Verwaltungsbefehle laufen über ein Programm:
php Core/cron/camindo.php <befehl> [argumente] [--optionen]
Befehle:
status
Zustand des Systems: Versionen, Komponenten, wartende Aktionen, Wartungsmodus
install
Erstinstallation; mit --step=… einzelne Schritte wiederholen
upgrade
Datenbank nach einem Update nachziehen
component list
component install NAME [--activate]
component activate NAME
component deactivate NAME
component update NAME
component uninstall NAME [--purge]
Zusatzkomponenten verwalten
maintenance on [--reason=…]
maintenance off
maintenance status
Wartungsmodus
backup
backup prune --keep=N
Datenbanksicherung
cache all
cache docs
Caches für Snippets und Backend-Vorlagen und den Suchindex der Handbücher neu bauen (docs: nur den Index); all leert auch den Ausgabe-Cache der Templates und schreibt den Zwischenspeicher der Websites und Gruppenrechte neu
cache include
Ausgabe-Cache der Templates (CMS:INCLUDE … caching=…) leeren – etwa damit eine Inhaltsänderung sofort sichtbar wird
cache records [--instance=ID] [--area=ID,…]
refresh records [--instance=ID] [--area=ID,…]
Datensatz-Cache leeren – alle Websites, eine Website (--instance) oder einzelne Bereiche (--area, mehrere durch Kommas getrennt). Nötig etwa nach Änderungen direkt in der Datenbank. Die Einträge entstehen beim nächsten Abruf neu, offene Arbeitskopien bleiben unberührt. Nicht Teil von cache all. Dasselbe im Backend unter „Werkzeuge“ → „Server“ → „Datensatz-Cache leeren“
refresh
Komponenten mit der Datenbank abgleichen
refresh snippets
refresh html
Snippet-Cache bzw. Cache der Backend-Vorlagen neu bauen; snippets wandelt vorher Snippet-Sets im früheren PHP-Format in .ini-Dateien um (siehe Kapitel 10)
admin password NAME
Passwort eines Benutzers setzen – etwa wenn der einzige Superuser seines vergessen hat
key status
key rotate [--invalidate-passwords]
key retire KID [--force]
Schlüssel .camindo.key wechseln, siehe Schlüssel wechseln
key rehash
Suchwerte verschlüsselter Felder neu berechnen – einmal für Daten, die vor der Suche ohne Groß-/Kleinschreibung gespeichert wurden
audit verify [TYP ID]
Audit-Log prüfen: Prüfsummenkette der Dateien unter var/audit/ und Abgleich mit der Datenbank
audit reseal TYP ID [--reason=…] [--dry-run]
eine gebrochene Prüfsummenkette nach Prüfung neu verketten, siehe Sicherheit und Compliance
audit anonymize-ip [--dry-run]
einmalig nach dem Update: IP-Adressen in den Dateien unter var/audit/ kürzen, die noch vollständig gespeichert sind, siehe Kapitel 15
audit restore [--dry-run]
nach dem Zurückspielen einer Datenbanksicherung: Einträge unter var/audit/, die neuer sind als die Datenbank, entfernen (Kopie unter var/audit-restore-…/)
audit delete TYP ID [--dry-run]
audit delete --area=ID [--force] [--dry-run]
den gesamten Verlauf eines Objekts löschen (z. B. audit delete record 4237, audit delete admin 34) – in der Datenbank und unter var/audit/, bei Datensätzen auch ihre Aufträge der Lösch-Policies. Mit --area=ID den Verlauf aller Datensätze eines Bereichs, auch bereits gelöschter; ohne --force nennt der Befehl nur die Anzahl. --dry-run zeigt, was gelöscht würde. Nur für Ausnahmefälle – regulär löschen die Aufbewahrungsfristen und die Lösch-Policies
audit strip-names
einmalig nach dem Update: Namen der Handelnden aus älteren Einträgen entfernen – sie stehen danach nur noch als Id (wiederholbar)
api login --admin=NAME [--lifetime=SEK]
api call METHODE '{…}'
api whoami
api methods
api describe METHODE
api logout
Die API auf der Kommandozeile: login legt eine Sitzung für den Benutzer an und gibt ihre Kennung aus, die folgenden Befehle brauchen sie als --session=… oder in der Umgebungsvariablen CAMINDO_API_SESSION. Die Benutzergruppe des Benutzers braucht die Oberfläche „Kommandozeile (CLI)“
cache instances
den Zwischenspeicher für Websites, Sprachen, Bereiche und Gruppenrechte neu schreiben (auch Teil von cache all)
htaccess
htaccess renew
.htaccess prüfen bzw. erneuern – wie die Schaltfläche „Erneuern“ unter „Werkzeuge“ → „Server“. Ohne Zusatz meldet der Befehl, ob die Datei zur Verzeichnisstruktur passt (Exit-Code 1, wenn nicht); renew schreibt den von camindo CMS verwalteten Abschnitt neu, Zeilen außerhalb bleiben erhalten. upgrade erneuert die Datei ohnehin
template commands --lang=de_DE
template commands --all --out=VERZEICHNIS
die CMS-Befehle (Kern und aktive Module) mit ihren Parametern und Beschreibungen als JSON ausgeben – für die Editor-Unterstützung, etwa die Erweiterung für Visual Studio Code. Ohne --all in einer Sprache auf die Standardausgabe, mit --all je Backend-Sprache eine Datei commands.{sprache}.json im Verzeichnis
Schlüssel wechseln
Die Datei .camindo.key verschlüsselt vertrauliche Felder (E-Mail-Adressen, Telefonnummern,
verschlüsselte Eingabefelder, Nachrichten, Secrets der Authenticator-App), würzt die
Passwort-Prüfwerte und signiert Konten, Benutzergruppen und Rechte: Zu jedem Konto und jedem
Recht speichert camindo CMS eine Prüfsumme, die nur mit dem Schlüssel berechnet werden
kann. Wer nur die Datenbank verändert, erzeugt damit eine ungültige Prüfsumme – das
Konto oder Recht gilt als manipuliert und wird ignoriert. Nach einem Schlüsselwechsel
müssen deshalb alle Prüfsummen neu berechnet werden („neu signieren“).
Einen neuen Schlüssel führen Sie ein mit
php Core/cron/camindo.php key rotate
Der Befehl sichert die Datenbank, schaltet den Wartungsmodus ein, verschlüsselt alles
mit dem neuen Schlüssel neu, signiert neu (auch die Prüfsummenkette des Audit-Logs,
nachdem die alte geprüft wurde) und meldet alle Benutzer ab. Er lässt sich
höchstens einmal in 24 Stunden ausführen – ein zweiter Aufruf so kurz danach wäre ein
Versehen; key status nennt den frühestmöglichen Zeitpunkt. Der alte
Schlüssel bleibt als abgelöster Schlüssel in .camindo.key.retired:
Passwörter lassen sich nicht umrechnen, weil camindo CMS sie nicht kennt – sie gelten
weiter und werden bei der nächsten Anmeldung automatisch auf den neuen Schlüssel
umgestellt. Ebenso gelten Wiederherstellungscodes und bekannte Geräte weiter.
Dateirechte des Schlüssels: Die neue .camindo.key und .camindo.key.retired
erhalten dieselben Rechte wie die bisherige .camindo.key – auch wenn Sie bewusst
andere als 0600 gesetzt haben, etwa weil der Webserver die Datei auf Ihrem System nur
über die Gruppe lesen kann. Gibt es keine .camindo.key, weil der Schlüssel aus der
Umgebungsvariablen CAMINDO_KEY kommt, gilt die Einstellung permissions.key_file in
.camindo.php (Vorgabe 0600). key status warnt, wenn die Rechte der Datei davon
abweichen. Rufen Sie den Wechsel als root auf, behalten beide Dateien außerdem den
Eigentümer der bisherigen .camindo.key – sonst könnte der Webserver sie danach nicht
mehr lesen.
key status zeigt den aktuellen Schlüssel, abgelöste Schlüssel mit der Frist
security.key_password_grace_days (Vorgabe 90 Tage) und wie viele Passwörter noch am
alten Schlüssel hängen. Ist die Frist um, entfernen Sie den alten Schlüssel mit
key retire KID --force: Wer sich bis dahin nicht angemeldet hat, braucht ein neues
Passwort (Benutzer: admin password NAME, Frontend-User: „Passwort vergessen“), und
Wiederherstellungscodes von vor dem Wechsel gelten nicht mehr.
Passwörter öffentlich aufgetaucht? Dann
php Core/cron/camindo.php key rotate --invalidate-passwords
Alle Passwörter werden sofort ungültig, alle Sitzungen, bekannten Geräte und
Wiederherstellungscodes gelöscht, und der alte Schlüssel wird gleich entfernt.
Anschließend setzen Sie die Passwörter der Benutzer mit
php Core/cron/camindo.php admin password NAME; Frontend-User setzen ihres über „Passwort
vergessen“. Liegt der Verdacht nahe, dass auch der Schlüssel selbst in fremde Hände
geraten ist, setzen Sie zusätzlich die Authenticator-Apps der Benutzer zurück.
Sichern Sie
.camindo.keynach jedem Wechsel erneut – getrennt von den Datenbanksicherungen.
Schlüssel in der Umgebungsvariablen CAMINDO_KEY? key rotate schreibt den neuen
Schlüssel trotzdem in die Datei .camindo.key – sie hat Vorrang vor der Variablen, das
System arbeitet also sofort mit dem neuen Schlüssel. Tragen Sie anschließend den Inhalt
von .camindo.key in die Variable ein; erst danach dürfen Sie die Datei wieder
entfernen. Bis dahin erscheint auf der Startseite ein Betriebshinweis.
Die Datei .camindo.key.retired mit den abgelösten Schlüsseln bleibt in jedem Fall
liegen.
Konfiguration
Die Konfiguration steht in .camindo.php im Projektverzeichnis. Der Installer
schreibt die wichtigsten Angaben; alles andere hat Vorgaben, die Sie dort überschreiben
können, siehe nachfolgende Tabelle. Die vollständige, kommentierte Liste steht in Core/src/Config.php.
Die Datei enthält Zugangsdaten: Rechte 0600, niemals in eine Versionsverwaltung!
| Schlüssel | Vorgabe | Bedeutung |
|---|---|---|
system.locale |
– | Gebietsschema der Installation, z. B. de_DE |
system.timezone |
– | Zeitzone des Systems und der Cronjobs |
system.development_version |
false |
Entwicklungsmodus – nie auf einem Live-System |
system.debugsql |
false |
alle SQL-Befehle mit Laufzeit protokollieren – nur zusammen mit system.development_version, reine Entwicklerfunktion |
system.link_length |
120 |
maximale Länge automatisch erzeugter Slugs |
system.html_allowed_tags |
[] |
optionale Whitelist erlaubter HTML-Tags in Inhalten, z. B. ['p','br','strong','a','h1','img']; andere Tags werden beim Speichern und Anzeigen entfernt. Script, iframe, object, embed, base, meta und Event-Handler entfernt camindo CMS immer |
admin.2_factor |
true |
Zwei-Faktor-Anmeldung per E-Mail-Code (Benutzer mit Authenticator-App bekommen immer deren Abfrage) |
admin.2_factor_expiration |
600 |
Gültigkeit des Anmelde-Codes in Sekunden |
admin.max_inactive_sec |
1800 |
automatische Abmeldung nach Untätigkeit (Sekunden) |
admin.edit_lock_sec |
5400 |
Verfallszeit von Bearbeitungssperren (Sekunden): so lange unverändert, sperrt eine Arbeitskopie den Datensatz nicht mehr. Länger als die automatische Abmeldung, damit sich eine offene Maske nach einer Pause und erneuter Anmeldung noch speichern lässt |
admin.bruteforce_max,admin.bruteforce_delay |
3 / 600 |
erlaubte Fehlversuche je Anmeldename und Sperrdauer in Sekunden (0 = Schutz aus). An einem Gerät, an dem sich der Benutzer schon angemeldet hat, zählen seine Versuche getrennt – ein gesperrter Name sperrt ihn dort nicht aus |
admin.bruteforce_ip |
true |
bei zu vielen Fehlversuchen die Besucher-Adresse im Log security vermerken |
admin.throttle.login_ip |
[20, 600] |
höchstens so viele Fehlanmeldungen je Besucher-Adresse im Zeitfenster (Sekunden), über alle Anmeldenamen – danach ist die Anmeldung von dieser Adresse aus gesperrt (0 = aus). Hinter einem Proxy security.trusted_proxies setzen |
admin.backend_domain |
'' |
feste Adresse des Backends, z. B. 'cms-k7x2.example.com' (siehe Feste Backend-Domain). Leer: Backend unter /backend/ jeder Domain |
admin.cookie_secure,admin.cookie_samesite |
true / 'Lax' |
Sitzungs-Cookie nur über HTTPS senden. false nur für einen lokalen Test ohne SSL (Schnellstart); SameSite-Attribut des Cookies |
admin.password_retention_days |
0 |
Gültigkeit eines Passworts in Tagen; danach muss der Benutzer bei der Anmeldung ein neues, anderes setzen (0 = unbegrenzt). Ein von einem anderen Benutzer gesetztes Passwort muss immer bei der ersten Anmeldung geändert werden |
admin.allowed_origins |
[] |
weitere Adressen, von denen aus Formulare an das Backend geschickt werden dürfen, z. B. ['https://cms.example.com'] – nur nötig, wenn ein Proxy den Hostnamen umschreibt (siehe Sicherheits-Header) |
admin.skiplist_default |
20 |
Datensätze je Seite in Listen; Vorgabe für die Einstellung „Datensätze je Seite“ eines Inhaltsbereichs |
admin.list_max_datasets |
200 |
maximale Einträge in Auswahllisten |
admin.max_include_depth |
20 |
maximale Verschachtelungstiefe von Templates (CMS:INCLUDE, CMS:SELECT) |
admin.trash_retention_days |
7 |
Aufbewahrungsfrist im Papierkorb |
admin.mass_delete_threshold |
200 |
ab dieser Anzahl laufen Massenlöschung und Stapelverarbeitung zwingend im Hintergrund (im Backend nicht abwählbar; über die API mit background: no übergehbar); 0 = Schwelle aus |
admin.import_background_threshold |
200 |
ab dieser Anzahl Datensätze läuft ein Import im Hintergrund |
admin.export_background_threshold |
1000 |
ab dieser Anzahl Datensätze läuft ein Export im Hintergrund |
admin.export_retention_hours |
24 |
Verweildauer nicht abgeholter Exportdateien |
admin.tmp_retention_hours |
24 |
Aufbewahrung temporärer Dateien in var/tmp |
admin.include_cache |
true |
Ausgabe-Cache der Templates (CMS:INCLUDE … caching=…); false schaltet ihn ab, alle Templates laufen wieder bei jedem Aufruf |
admin.include_cache_lock_wait |
30 |
so viele Sekunden wartet ein Seitenaufruf höchstens, während ein anderer dieselbe Cache-Datei erzeugt; danach erzeugt er die Ausgabe selbst |
api.max_inactive_sec,api.max_lifetime |
3600 / 86400 |
Sitzungen der Kommandozeile und der PHP-API: automatische Abmeldung nach Untätigkeit und höchste Laufzeit in Sekunden (auch Obergrenze einer beim Anmelden angegebenen Laufzeit) |
api.max_limit |
200 |
höchstens so viele Datensätze je Seite einer API-Liste |
api.base64_max_bytes |
20971520 |
Höchstgröße einer als Base64 übergebenen Datei in Bytes (0 = ohne Grenze) |
security.hsts_max_age |
0 |
HSTS: Browser lassen die Domain nur noch per HTTPS zu, für diese Anzahl Sekunden (0 = aus), siehe Sicherheits-Header |
security.hsts_include_subdomains |
false |
HSTS auch für alle Subdomains |
security.trusted_proxies |
[] |
Proxies bzw. Load-Balancer vor der Website (IP-Adressen oder Bereiche wie 10.0.0.0/8). Nur von ihnen übernimmt camindo CMS die Besucher-Adresse aus X-Forwarded-For – wichtig für Sperren und Drosselung je Besucher |
security.frontend_csp |
'off' |
Script-Policy der Websites ohne eigene Einstellung: 'off', 'report', 'enforce' – siehe Kapitel 3 |
security.form_challenge |
'' |
Klasse eines externen Captchas für geschützte Formulare (Entwickler) |
security.magick_allow |
[] |
Formate, die ImageMagick zusätzlich verarbeiten darf: 'svg', 'pdf' – siehe ImageMagick absichern |
security.password_policy |
12 Zeichen, 1 Sonderzeichen, 1 Groß- (nicht am Anfang), 1 Kleinbuchstabe | Passwort-Richtlinie, siehe Passwörter und Anmeldegeräte |
security.password_hash |
Argon2id, sonst bcrypt | Verfahren und Aufwand für gespeicherte Passwörter |
security.device_notify,security.device_days,security.device_cookie |
true / 180 / 'c9dev' |
Hinweis bei Anmeldung von einem neuen Gerät; wie lange ein unbenutztes Gerät bekannt bleibt (zugleich Laufzeit des Cookies); Name des Geräte-Cookies |
security.login_notifier |
'' |
eigene Klasse für die Hinweise (z. B. SMS statt E-Mail) |
security.admin_2fa |
'totp' |
Authenticator-App (TOTP) für Benutzer: 'totp' wählbar, 'totp_required' Pflicht für Superuser, 'email' abgeschaltet – siehe Zwei-Faktor-Anmeldung |
security.totp_issuer |
'' |
Name, unter dem das Konto in der App erscheint (leer: camindo); dazu Anmeldename@Domain |
security.webauthn |
true |
Passkeys und Sicherheitsschlüssel als zweiter Faktor im Backend – nur mit fester Backend-Domain (admin.backend_domain). false schaltet Anlegen und Anmeldung mit Passkey ab |
security.key_password_grace_days |
90 |
Frist nach einem Schlüsselwechsel, die key status für Passwörter am alten Schlüssel nennt |
security.backend_csp |
'enforce' |
Script-Schutz des Backends: 'enforce' lässt nur Scripts von camindo CMS zu. 'report' lässt alles laufen und protokolliert Verstöße (Modul „Logdateien“, Log csp), falls ein Zusatzmodul nicht mehr funktioniert. 'off' schaltet ihn ab |
audit.enabled |
true |
Audit-Log: wer hat wann was geändert, siehe Audit-Log |
audit.retention_days_changes |
0 |
Aufbewahrung der Einträge zu bestehenden Objekten in Tagen (0 = unbegrenzt) |
audit.log_logins |
false |
Erfolgreiche An- und Abmeldungen am Backend im Audit-Log aufzeichnen (fehlgeschlagene immer), siehe Kapitel 15 |
audit.retention_days_logins |
90 |
Aufbewahrung der An-/Abmeldungen und Fehlversuche in Tagen (0 = wie audit.retention_days_changes) |
audit.retention_days_deleted |
365 |
Aufbewahrung des Verlaufs endgültig gelöschter Objekte in Tagen, ab dem Löschen (0 = unbegrenzt) – nicht für Datensätze, deren Verlauf regelt die Lösch-Policy |
audit.page_bytes |
1048576 |
Inhalte des Audit-Logs liegen unter var/audit/, je Objekt eine Datei; ab dieser Größe in Bytes beginnt eine neue Seite |
privacy.ip_anonymize_days |
7 |
Nach so vielen Tagen werden IP-Adressen im Audit-Log, bei Anmeldeversuchen und in den Logdateien gekürzt (0 = beim nächsten Lauf der Aufgabe „Aufbewahrungsfristen anwenden“), siehe Kapitel 15 |
privacy.message_days |
60 |
Interne Nachrichten werden so viele Tage nach dem Versand gelöscht – für Absender und Empfänger (0 = nie) |
privacy.ip_v4_octets |
1 |
Wie viele Stellen am Ende einer IPv4-Adresse genullt werden: 1 (203.0.113.0) oder 2 (203.0.0.0). IPv6 verliert immer die letzten 80 Bit |
ai.* |
– | Zusatzmodul KI-Assistent: Anbieter, Zugangsschlüssel, Modell, siehe KI-Assistent |
email.* |
– | E-Mail-Versand, siehe unten |
user.* |
– | Frontend-Community, siehe Kapitel 13 |
paths.php,paths.mysqldump,paths.magick,paths.ffmpeg,paths.ffprobe,paths.composer |
– | Pfade zu externen Programmen; leer lassen, was es nicht gibt (composer: Update-Prüfung) |
paths.document_root,paths.media,paths.backend |
public/,'/media','/backend' |
Verzeichnis, auf das der Webserver zeigt; Adresspfade der Mediendateien und des Backends relativ dazu |
paths.key_file,paths.sqlpwd_file |
.camindo.key,.sqlpwd |
Schlüsseldatei und Zugangsdatei für mysqldump (absolute Pfade, Vorgabe im Projektverzeichnis) |
paths.var_dir,paths.tmp_dir,paths.upload_dir |
var/,var/tmp/,var/upload/ |
beschreibbares Hauptverzeichnis, temporäre Dateien und Verzeichnis für per FTP übertragene große Dateien (Auswahl über das Datei-Icon neben Upload-Feldern) |
permissions.dir,permissions.file |
0775 / 0664 |
Unix-Rechte für Verzeichnisse und Dateien, die camindo CMS anlegt |
permissions.key_file |
0600 |
Rechte von .camindo.key und .camindo.key.retired beim Schlüsselwechsel, wenn es noch keine .camindo.key gibt (Schlüssel aus CAMINDO_KEY) – sonst behält der Wechsel die Rechte der bisherigen Datei |
db.* |
– | Zugangsdaten der Datenbank |
Zugangsdaten aus Umgebungsvariablen
Passwörter und der Schlüssel müssen nicht in Dateien im Projektverzeichnis stehen. Lässt
Ihr Hoster oder Ihre Server-Umgebung Umgebungsvariablen setzen (Docker, PHP-FPM,
Webserver-Konfiguration, Secret-Verwaltung der Plattform), kann camindo CMS diese
Werte von dort übernehmen. Der Rest der Konfiguration – Datenbank-Host, Postfach,
Anbieter – bleibt in .camindo.php.
| Variable | ersetzt | Vorrang |
|---|---|---|
CAMINDO_DB_PASS |
db.pass |
Variable vor .camindo.php |
CAMINDO_SMTP_PASS |
email.smtp.pass |
Variable vor .camindo.php |
CAMINDO_AI_API_KEY |
ai.api_key (Zusatzmodul KI-Assistent) |
Variable vor .camindo.php |
CAMINDO_KEY |
die Schlüsseldatei .camindo.key (genau ihr Inhalt) |
Datei vor Variable – damit nach einem Schlüsselwechsel der neue Schlüssel gilt, bis Sie die Variable nachgezogen haben. Ist die Datei vorhanden, aber nicht lesbar, bricht camindo CMS ab, statt die Variable zu nehmen |
Eine leere Variable zählt als nicht gesetzt. Eine .env-Datei liest camindo CMS
nicht – die Variablen müssen von außen in die Umgebung von PHP gelangen, und zwar
sowohl für den Webserver als auch für die Cronjobs und die Kommandozeile.
Kommt das Datenbank-Passwort aus CAMINDO_DB_PASS, braucht die Datensicherung die
Datei .sqlpwd nicht: Sie schreibt für jeden Lauf eine eigene Optionsdatei und löscht
sie danach. Der Installer übernimmt CAMINDO_DB_PASS ebenfalls, lässt das Passwort dann
aus .camindo.php heraus und legt keine .sqlpwd an; ist CAMINDO_KEY gesetzt, legt er
keine .camindo.key an.
php Core/cron/camindo.php status zeigt, welche Werte aus der Umgebung kommen
(„from environment“). Nach dem Einlesen entfernt camindo CMS die Variablen aus der
Umgebung von PHP: Programme, die es aufruft (ImageMagick, ffmpeg, mysqldump), sehen sie
nicht, ebenso wenig die PHP-Info im Modul „Werkzeuge“ – außer unter „Apache Environment“, wenn
der Webserver sie mit SetEnv setzt. Bevorzugen Sie deshalb die Umgebung von PHP-FPM
oder des Containers.
E-Mail-Versand
camindo CMS versendet E-Mails unter anderem für den Anmelde-Code der Zwei-Faktor-Anmeldung.
| Schlüssel | Bedeutung |
|---|---|
email.noreply |
Absenderadresse der Systemmails – Voraussetzung für die Zwei-Faktor-Anmeldung |
email.reply |
Kontaktadresse, die in Systemmails genannt wird (siehe unten) |
email.smtp.host, user, pass, enc, port |
SMTP-Postfach für einen zuverlässigen Versand (enc: starttls oder smtps). Leer: PHP-Funktion mail() |
Mit einem SMTP-Postfach der Absenderdomain landen Systemmails deutlich seltener im Spam. Nicht versendete E-Mails erscheinen im Modul „Logdateien“.
Die Kontaktadresse (email.reply) wird nicht als Absender (From) eingesetzt – sonst
würden automatische Antworten (Autoresponder) Ihr Postfach füllen. Sie steht nur im
Text der E-Mail.
Feste Backend-Domain
Ohne weitere Einstellung erreichen Sie das Backend unter /backend/ jeder Domain Ihrer
Installation – und damit auch jeder, der Ihre Website kennt. Besser ist eine feste
Backend-Domain, am besten eine Subdomain, die niemand errät:
'admin' => [
'backend_domain' => 'website-bearbeiten.example.com',
],
Voraussetzungen: Die Subdomain zeigt per DNS auf denselben Server und im Webserver auf
dasselbe Verzeichnis public/ wie die Websites, und sie hat ein eigenes
HTTPS-Zertifikat (Let's Encrypt genügt).
Danach gilt:
- Unter allen anderen Domains antwortet
/backend/mit „nicht gefunden“ – ohne Hinweis auf die richtige Adresse. - Die Vorschau öffnet sich unter der Domain der Website. Der Link darin gilt nur, solange Sie im Backend angemeldet sind, und höchstens acht Stunden.
- Frontend-Editing überträgt das Speichern der persönlichen Einstellungen auf alle Websites.
- Die Adresse Ihres Backends taucht in keiner Seite der Website auf.
Eine feste Backend-Domain ist außerdem Voraussetzung für die Anmeldung mit Passkeys.
Sicherheits-Header
camindo CMS sendet mit jeder Seite Header, die der Browser als Schutz umsetzt:
- Kein fremder Rahmen: Das Backend lässt sich in keinem
<iframe>anzeigen, die Website nur innerhalb der eigenen Domain. Das verhindert, dass eine fremde Seite Klicks in Backend, Login oder Warenkorb unterschiebt (Clickjacking). - Nur eigene Scripts im Backend: Das Backend führt nur JavaScript von camindo CMS
selbst aus. Gelangt trotz aller Filter ein Script in Inhalte, läuft es nicht.
Funktioniert ein Zusatzmodul danach nicht mehr, stellen Sie vorübergehend
security.backend_cspauf'report'und geben dem Hersteller die Einträge des Logscspweiter. - Keine Umdeutung von Dateitypen (
nosniff) und sparsame Weitergabe der Adresse an externe Seiten (Referrer-Policy). - Herkunftsprüfung: Formulare und Aktionen, die im Backend etwas ändern, nimmt
camindo CMS nur an, wenn der Browser sie von der Adresse des Backends aus schickt
(Header
Originbzw.Referer) – zusätzlich zum Sicherheitstoken jeder Sitzung. Läuft das Backend hinter einem Proxy, der den Hostnamen umschreibt, tragen Sie die öffentliche Adresse inadmin.allowed_originsein.
Das müssen Sie nicht einrichten. Soll eine Seite von Partnern eingebettet werden, stellt der Template-Programmierer das im Template um (CMS:HEADER).
HSTS weist den Browser an, die Domain nur noch per HTTPS aufzurufen. Schalten Sie es
erst ein, wenn die Seite dauerhaft und vollständig über https:// läuft – der Browser
merkt sich die Regel für die eingestellte Zeit, auch wenn Sie sie wieder abschalten.
Am besten setzen Sie HSTS im Webserver oder beim Hoster; geht das nicht, in .camindo.php:
'security' => [
'hsts_max_age' => 300, // zum Test fünf Minuten, danach 31536000 (ein Jahr)
],
hsts_include_subdomains nur, wenn wirklich jede Subdomain HTTPS kann.
Passwörter und Anmeldegeräte
Gespeichert werden Passwörter mit Argon2id – einem absichtlich langsamen und speicherintensiven Verfahren, das das Durchprobieren gestohlener Daten teuer macht. Bietet das PHP des Servers Argon2id nicht an, nimmt camindo CMS bcrypt, das jedes PHP beherrscht. Vorgabe ist das OWASP-Minimum (19 MB Speicher, zwei Durchläufe, rund 30 Millisekunden je Anmeldung). Ältere Passwörter werden bei der nächsten Anmeldung automatisch umgestellt; niemand muss sein Passwort neu setzen.
'security' => [
'password_hash' => ['algo' => 'auto', 'memory_cost' => 19456, 'time_cost' => 2, 'cost' => 11],
],
algo: auto, argon2id oder bcrypt; memory_cost in KiB und time_cost für
Argon2id, cost für bcrypt.
Die Passwort-Richtlinie gilt für die Passwörter der Benutzer immer und für
Passwort-Felder im Frontend, wenn das Feld die Extension
Passwort-Richtlinie trägt. Jede Regel lässt sich mit 0
abschalten:
'security' => [
'password_policy' => [
'min_length' => 12, // Mindestlänge
'min_special' => 1, // Sonderzeichen: alles außer Buchstaben und Ziffern
'min_upper' => 1, // Großbuchstaben …
'upper_not_first' => true, // … ein Großbuchstabe am Anfang zählt nicht
'min_lower' => 1, // Kleinbuchstaben
'min_digit' => 0, // Ziffern
],
],
Länge schützt mehr als Sonderzeichen: ein langes Passwort aus mehreren Wörtern ist
stärker als ein kurzes mit Satzzeichen. Wer die Regeln lockert, sollte eher
min_special senken als min_length.
Anmeldegeräte: camindo CMS erkennt den Browser wieder, mit dem sich jemand anmeldet.
Meldet sich ein Konto von einem neuen Gerät an, bekommt der Inhaber einen Hinweis –
Benutzer per E-Mail an ihre hinterlegte Adresse (setzt den
E-Mail-Versand voraus), Frontend-User über die Templates der Website
(siehe Kapitel 13). Die erste Anmeldung
eines Kontos löst keinen Hinweis aus. Ein Gerät, das device_days Tage nicht benutzt
wurde, gilt danach wieder als neu; ebenso ein Browser, dessen Cookies gelöscht wurden.
Die Zwei-Faktor-Anmeldung bleibt auch auf bekannten Geräten bestehen.
Zwei-Faktor-Anmeldung
Nach dem Passwort verlangt camindo CMS einen zweiten Faktor – je Benutzer einen von dreien:
| Faktor | Wann | Stärke |
|---|---|---|
| Passkey (WebAuthn) | der Benutzer hat einen angelegt – setzt eine feste Backend-Domain voraus | am höchsten: an die Adresse des Backends gebunden, nicht abfangbar, keine Eingabe auf gefälschten Seiten möglich; dazu Wiederherstellungscodes |
| Authenticator-App (TOTP nach RFC 6238) | der Benutzer hat sie in seinen persönlichen Einstellungen eingerichtet und security.admin_2fa ist nicht 'email' |
hoch: der Code entsteht auf dem Telefon; dazu zehn einmal verwendbare Wiederherstellungscodes |
| Code per E-Mail | sonst, wenn admin.2_factor an ist |
so sicher wie das Postfach |
security.admin_2fa steuert die App:
'security' => [
'admin_2fa' => 'totp_required', // 'email' | 'totp' (Vorgabe) | 'totp_required'
],
Mit 'totp_required' müssen alle Superuser die App benutzen. Wer sie noch nicht
hat, richtet sie bei der nächsten Anmeldung direkt im Anmeldedialog ein; abschalten
kann ein Superuser sie dann nicht mehr. Für die übrigen Benutzergruppen bleibt die App freiwillig.
Mit 'email' ist die App nicht einrichtbar, und bereits eingerichtete ruhen – es
gilt wieder der E-Mail-Code.
Passkeys stehen jedem Benutzer offen, sobald admin.backend_domain
eingetragen ist, unabhängig von security.admin_2fa. Ein Passkey erfüllt auch die
Pflicht aus 'totp_required'. Hat ein Benutzer Passkeys und die App, nimmt der
Anmeldedialog beides. Abschalten lassen sich Passkeys mit
'security' => ['webauthn' => false] – Konten, die nur Passkeys hatten, melden sich
dann mit einem Wiederherstellungscode an. Die Bindung an die Domain bedeutet: Ändert
sich die Backend-Domain, müssen alle Passkeys neu angelegt werden.
Ein falscher Code zählt wie ein falsches Passwort (admin.bruteforce_max), und ein
richtiges Passwort setzt den Zähler nicht zurück – erst die vollständige Anmeldung.
So lässt sich der sechsstellige Code nicht durchprobieren. Jeder App-Code gilt nur
einmal.
Richtet ein Benutzer die App ein, schaltet sie ab oder meldet sich mit einem
Wiederherstellungscode an, bekommt er eine E-Mail (bzw. eine Nachricht über den
login_notifier), und der Vorgang steht im Audit-Log. Verlorene Telefone setzt ein
Superuser zurück (Kapitel 7).
Statt einer E-Mail kann eine SMS oder eine andere Nachricht gehen: Ein Entwickler
schreibt dafür eine kleine PHP-Klasse, die die Schnittstelle
Camindo\Core\LoginNotifierInterface erfüllt, und Sie tragen sie ein:
'security' => [
'login_notifier' => 'App\SmsNotifier',
],
Die Klasse bekommt die Ereignisse „Anmeldung von neuem Gerät“ (Backend und Frontend)
und „Passwort geändert“ (Frontend) mit Konto, Gerät, IP-Adresse und Uhrzeit. Kann sie
nicht senden, steht das im Log security.
ImageMagick absichern
Bilddateien sind ein beliebter Angriffsweg: Eine präparierte Datei nutzt eine Lücke in ImageMagick oder in einem Programm, das ImageMagick aufruft. camindo CMS schützt sich auf drei Ebenen, ohne dass Sie etwas einrichten müssen:
- Eigene Sicherheits-Policy: Vor jedem Aufruf gilt eine Policy, die camindo CMS in
var/config/magick/policy.xmlerzeugt. Sie sperrt Skript- und Sonderformate, fremde Hilfsprogramme (Ghostscript, curl, LibreOffice …) und PostScript und begrenzt Speicher, Laufzeit und Bildgröße. Sie ergänzt die Policy Ihres Servers, sie kann nichts freigeben, was der Server sperrt. Das funktioniert auch auf Shared Hosting. - Format aus dem Inhalt: ImageMagick liest jede Datei nur mit dem Format, das camindo CMS beim Hochladen erkannt hat. Passen Endung und Inhalt nicht zusammen, wird der Upload abgelehnt.
- Zeitlimits: Jede Umwandlung wird nach spätestens zwei Minuten abgebrochen.
SVG und PDF geben Sie mit security.magick_allow frei (siehe
Medien). Die Detailansicht eines Konverters zeigt
die installierte ImageMagick-Version, ob sie veraltet ist, und ob SVG und PDF
tatsächlich laufen.
Wenn Sie den Server selbst betreiben, können Sie ImageMagick weiter abschotten:
-
Halten Sie ImageMagick aktuell (ab Version 7.1.1). Ältere Versionen funktionieren, enthalten aber bekannte Lücken.
-
Installieren Sie Ghostscript nicht, wenn Sie keine PDFs umwandeln.
-
Lassen Sie ImageMagick unter einem eigenen Benutzer oder in einem eigenen Container laufen, der nur das Medienverzeichnis und
var/tmplesen und schreiben darf. Tragen Sie dann unterpaths.magickein kleines Script ein, das den Aufruf weiterreicht und Grenzen setzt. Es mussmagickheißen und in einem eigenen Verzeichnis liegen, daran erkennt camindo CMS ImageMagick 7:#!/bin/sh # /opt/camindo-magick/magick -> paths.magick ulimit -t 150 -v 1048576 # CPU-Sekunden, Speicher in KB exec sudo --preserve-env=MAGICK_CONFIGURE_PATH -u imagick /usr/bin/magick "$@"sudobraucht dafür einen Eintrag in den sudoers für den Webserver-Benutzer. Wichtig ist--preserve-env: ohne die VariableMAGICK_CONFIGURE_PATHfehlt die camindo-Policy. Der Benutzerimagickmussvar/config/magick/lesen können.Für ImageMagick 6 legen Sie zwei solche Scripte
convertundidentifyin das Verzeichnis und tragen den Pfad zuconvertein. -
Wenn Sie ausschließlich JPEG, PNG und GIF verarbeiten, genügt der GD-Prozessor. Er braucht kein ImageMagick.
Protokolle
Alle Protokolle liegen in var/log/, je Tag und Art eine Datei (etwa
2026-09-22_php_errors.log, …_scheduler.log, …_security.log). Superuser sehen sie
im Modul „Logdateien“.
php Core/cron/camindo.php status fasst den Zustand des Systems zusammen.
Die Logdateien wachsen, bis sie gelöscht werden. Die Zeitplaner-Aufgabe
„Logs aufräumen“ (von der Installation angelegt, siehe Scheduler) löscht
alte Logdateien und gespeicherte Anmeldeversuche mit IP-Adresse; die Fristen stellen
Sie in der Aufgabe ein. Unabhängig davon kürzt camindo CMS die IP-Adressen in den
Logdateien nach privacy.ip_anonymize_days Tagen (siehe
Kapitel 15).
Wer was im Backend geändert hat, steht nicht in den Logdateien, sondern im Audit-Log.
Betriebshinweise auf der Startseite
Superuser sehen auf der Startseite unter den Modulkacheln einen Block „Betriebshinweise“, sobald im Betrieb etwas nicht stimmt. Ist alles in Ordnung, erscheint er nicht.
| Hinweis | Bedeutung |
|---|---|
| Cronjob läuft nicht | cron.php hat sich seit über 15 Minuten nicht gemeldet. Zeitplaner (auch alle Wartungsaufgaben) und Thumbnails stehen still |
| Temporäre Dateien zu alt | In var/tmp/ liegen Einträge, die älter sind als admin.tmp_retention_hours (plus zwei Stunden). Die Aufgabe „Temporäre Dateien löschen“ greift nicht |
| Wartungsaufgaben fehlen | Für eine der Wartungsaufgaben (Papierkorb, temporäre Dateien, Lösch-Policies, Aufbewahrungsfristen, Audit-Log prüfen, Updates) gibt es keine eingeschaltete Aufgabe im Zeitplaner |
| Keine Datenbanksicherung | Es gibt keine eingeschaltete Aufgabe „Datenbank-Backup“ |
| Datenbanksicherung fehlgeschlagen / zu alt / unbrauchbar | Der letzte Lauf meldete einen Fehler, backup-1.sql ist älter als zwei Tage oder unbrauchbar: kleiner als 10 KB (dann steht darin meist nur eine Fehlermeldung) oder ohne die Schlusszeile -- Dump completed (Dump abgebrochen) |
| Aufgaben mit Fehler | Andere Zeitplaner-Aufgaben, deren letzter Lauf fehlschlug |
| Logs werden nicht aufgeräumt | Es gibt keine Aufgabe „Logs aufräumen“ |
| Frontend-Cache wird nicht aufgeräumt | Templates nutzen den Ausgabe-Cache, aber es gibt keine eingeschaltete Aufgabe „Frontend-Cache aufräumen“ |
| Wenig Speicherplatz | Unter 2 GB frei für var/ (unter 512 MB: Alarm) |
| Nicht beschreibbar | var/tmp, var/log oder das Medienverzeichnis |
| Zeitzonentabellen fehlen | Dem Datenbankserver fehlen die Zeitzonentabellen; camindo CMS rechnet mit dem aktuellen UTC-Versatz der eingestellten Zeitzone, nach einer Zeitumstellung liegen Zeitangaben eine Stunde daneben. Abhilfe siehe Kapitel 1 |
| E-Mail fehlt | Zwei-Faktor-Anmeldung ist an, aber keine Absendeadresse eingerichtet |
| Entwicklungsmodus | system.development_version ist eingeschaltet |
| Cookie ohne HTTPS | admin.cookie_secure ist false |
| Schlüssel in CAMINDO_KEY veraltet | Die Umgebungsvariable CAMINDO_KEY enthält nicht den aktuellen Schlüssel – meist nach einem Schlüsselwechsel. Verwendet wird .camindo.key; tragen Sie deren Inhalt in die Variable ein |
| security.txt fehlt | Es gibt keinen Meldeweg für Sicherheitslücken (siehe Kapitel 14) |
| Audit-Log beschädigt | Die tägliche Prüfung hat in var/audit/ eine gebrochene Prüfsummenkette, fehlende Einträge oder Einträge der Datenbank, die nicht zu den Dateien passen, gefunden; Details mit php Core/cron/camindo.php audit verify |
| Sicherheitslücken / neue Version / Updates | Ergebnis der täglichen Update-Prüfung: bekannte Lücken in installierten Paketen (Alarm), eine neue Version von camindo CMS (Warnung); „Öffnen“ führt zu „Info“ |
Ein Klick auf „Öffnen“ führt, wo möglich, direkt an die Stelle, an der sich der Hinweis beheben lässt.
Checkliste für den Live-Betrieb
- [ ] HTTPS eingerichtet,
admin.cookie_secureunduser.cookie_secureauftrue(Vorgabe – in.camindo.phpdarf keinfalsemehr stehen) - [ ]
system.development_versionistfalse - [ ] ImageMagick aktuell und in der Detailansicht der Konverter keine Warnung zu Version und Sicherheits-Policy
- [ ] HSTS eingeschaltet (Webserver oder
security.hsts_max_age), sobald HTTPS dauerhaft läuft - [ ] E-Mail-Versand eingerichtet, Zwei-Faktor-Anmeldung eingeschaltet, alle Benutzer mit E-Mail-Adresse (Anmelde-Code und Hinweis auf neue Geräte)
- [ ] Superuser mit Authenticator-App – auf Live-Systemen
security.admin_2fa = 'totp_required' - [ ] Passwort-Felder im Frontend mit der Extension „Passwort-Richtlinie“
- [ ] Shops und Mitgliederbereiche: zweiter Faktor im Profil-Bereich mindestens „Code bei neuem Gerät“ (Kapitel 13)
- [ ] Script-Policy der Website erst „Nur melden“, nach sauberem Protokoll „Durchsetzen“ (Kapitel 3)
- [ ] feste Backend-Domain eingetragen (
admin.backend_domain), eigene Subdomain mit HTTPS - [ ] hinter Proxy oder Load-Balancer:
security.trusted_proxiesgesetzt - [ ] der Cronjob
cron.phpläuft (php Core/cron/camindo.php status) - [ ] Wartungsaufgaben im Zeitplaner vorhanden und eingeschaltet (
php Core/cron/camindo.php scheduler list), Zeiten passend - [ ] Datenbanksicherungen zusätzlich außerhalb des Servers
- [ ] nutzen die Templates
caching: Aufgabe „Frontend-Cache aufräumen“ im Zeitplaner eingerichtet - [ ] Fristen des Audit-Logs (
audit.*) mit dem Datenschutzkonzept abgestimmt - [ ]
public/.well-known/security.txtangelegt - [ ] keine Betriebshinweise auf der Startseite
- [ ]
.camindo.keyan einem sicheren Ort gesichert (bzw. der Inhalt vonCAMINDO_KEY) - [ ] Schreibrechte des Webservers nur auf
var/undpublic/media/ - [ ] Instanzen mit „Kanonische Aufrufe“ für Suchmaschinen
Lizenz
camindo CMS ist freie Software unter der GNU AGPL Version 3 oder später. Den
Lizenztext finden Sie in Core/LICENSE, die Lizenzen der mitgelieferten Bibliotheken in
Core/THIRD-PARTY-NOTICES.md.
Für den Betrieb bedeutet das:
- Eine unveränderte Installation dürfen Sie ohne weitere Pflichten betreiben, auch für Kunden und gegen Entgelt.
- Ihre Templates und alle Inhalte gehören Ihnen und dürfen unter beliebiger
Lizenz stehen – eine Zusatzerlaubnis in
Core/LICENSING.mdnimmt sie ausdrücklich aus. - Haben Sie den Core oder eine AGPL-Komponente verändert und ist die Website öffentlich erreichbar, müssen Sie den Besuchern den Quellcode Ihrer geänderten Fassung anbieten, etwa mit einem Link auf ein öffentliches Repository.
13 Community-Funktionen
Mit den Community-Funktionen können sich Frontend-User registrieren, anmelden, ihr Profil pflegen und selbst Inhalte anlegen – Kommentare, Bewertungen, Anzeigen, Bilder. Geschützte Bereiche und Dateien stehen nur angemeldeten Frontend-Usern offen, ein Warenkorb merkt sich ausgewählte Artikel.
Registrierte Besucher heißen in camindo CMS Frontend-User – im Unterschied zu den Benutzern im Backend. Ein Frontend-User hat kein Benutzerkonto im Backend: Sein digitales Abbild im CMS ist ein Profil-Datensatz, ein gewöhnlicher Datensatz wie seine Beiträge auch. Dadurch gelten für sie alle Werkzeuge der Redaktion – Suche, Stapelverarbeitung, Export, Rechte.
Profil-Bereiche
Ein Bereich vom Typ PROFILE enthält einen Datensatz je Frontend-User. Der Bauplan „Mitglieder“ legt einen solchen Bereich mit den Feldern Name, E-Mail und Passwort an. Weitere Profilfelder – Avatar, Adresse, Interessen – fügen Sie wie gewohnt hinzu.
Unter „Anmeldung an der Website“ legen Sie fest:
| Einstellung | Bedeutung |
|---|---|
| Name | das Feld mit dem Anmeldenamen, Typ „Kurzer Text“ (auch verschlüsselt), z. B. die E-Mail-Adresse |
| Passwort | das Feld vom Typ „Passwort“, gegen das die Anmeldung prüft |
| Zweiter Faktor | ob die Anmeldung zusätzlich einen Code braucht – siehe unten |
Beide Felder sind erst wählbar, nachdem sie angelegt wurden.
Weisen Sie dem Passwort-Feld die Extension „Passwort-Richtlinie“ zu (Abschnitt „Erweiterung“ der Felddefinition). Erst dann weist camindo CMS zu schwache Passwörter bei Registrierung und Passwortwechsel zurück. Die Regeln sind die aus Kapitel 12, einzelne Werte können Sie am Feld abweichend einstellen. Der Template-Programmierer zeigt dieselben Regeln im Formular an (CMS:USER_PASSWORD_RULES).
Ohne die Extension lässt sich die Passwortstärke nur über Mindestlänge (Minimum) und Muster (RegEx) in den Einstellungen des Eingabefeldes steuern.
Beitrags-Bereiche
Ein Bereich vom Typ UGC („user-generated content“) nimmt Beiträge angemeldeter Frontend-User auf. Der Bauplan „Kommentare“ legt einen solchen Bereich mit Name und Kommentartext an. Unter „Authentifizierung“ wählen Sie die Profil-Container, deren Frontend-User hier Beiträge anlegen dürfen. Jeder Beitrag ist mit dem Profil seines Verfassers verbunden. Ändern und Löschen kann ein Frontend-User nur seine eigenen Beiträge.
Die Templates
Registrierung, Anmeldung, Passwort-Reset und das Speichern von Beiträgen übernehmen
Templates mit den Befehlen CMS:USER_* – siehe
Handbuch für Template-Programmierer.
Der Ablauf einer Registrierung:
- Der Besucher füllt das Registrierungsformular aus. camindo CMS legt sein Profil mit dem Status „Unbestätigt“ an und erzeugt einen Einmal-Code; das Template verschickt ihn als Bestätigungslink per E-Mail (Befehl CMS:EMAIL).
- Mit dem Klick auf den Link wird das Profil freigeschaltet; der Frontend-User kann sich anmelden.
- Vergisst er sein Passwort, fordert er auf dieselbe Weise einen Link zum Zurücksetzen an.
Die Links sind zeitlich begrenzt gültig (Vorgabe: 24 Stunden für die Bestätigung, eine Stunde für das Zurücksetzen des Passworts) und nur einmal verwendbar.
Anmeldegeräte und Passwörter
- Neues Passwort nur mit dem bisherigen. Im Kundenkonto ändert ein Frontend-User sein Passwort nur, wenn er das bisherige eingibt. Wer an eine offene Sitzung gelangt, kann das Konto so nicht übernehmen. Ausnahme ist der Link aus „Passwort vergessen“: er gilt als Nachweis, das bisherige Passwort entfällt.
- „Passwort vergessen“ funktioniert auf jedem Gerät – üblich und sinnvoll, denn man vergisst sein Passwort oft gerade am neuen Rechner oder Telefon. Die Sicherheit liegt im Link: er geht nur an die hinterlegte E-Mail-Adresse, gilt eine Stunde und nur einmal.
- Nach einem neuen Passwort werden alle anderen Anmeldungen des Users beendet. Soll der User über die Passwort-Änderung informiert werden (falls er es nicht selbst war), muss sich das Template, das nach dem Speichern des Profils angezeigt wird, um die Benachrichtigung kümmern, beispielsweise mittels CMS:EMAIL.
- Anmeldung von einem neuen Gerät: Die Website kann dem Frontend-User einen Hinweis schicken, wenn sich sein Konto von einem unbekannten Browser aus anmeldet. Die E-Mail verschickt das Template; alternativ ein eigener Benachrichtigungsweg, etwa per SMS (Kapitel 12).
Zweiter Faktor
Ein Kundenkonto soll nicht allein am Passwort hängen. Mit der Einstellung „Zweiter Faktor“ im Profil-Bereich braucht die Anmeldung zusätzlich einen sechsstelligen Code:
| Einstellung | Wirkung |
|---|---|
| Aus | wie bisher, nur das Passwort |
| Freiwillig | Frontend-User können im Kundenkonto selbst eine Authenticator-App oder den Code per E-Mail einschalten |
| Code bei neuem Gerät | wie „Freiwillig“. Zusätzlich schickt die Website einen Code per E-Mail, wenn sich jemand von einem unbekannten Gerät (Browser) anmeldet. Auf den gewohnten Geräten bleibt es beim Passwort. Empfohlen für Shops |
| Immer | jede Anmeldung braucht einen Code: per E-Mail oder – wenn eingerichtet – aus der App |
Der Frontend-User richtet eine Authenticator-App (Google Authenticator, Microsoft Authenticator, 1Password …) im Kundenkonto ein, indem er einen QR-Code scannt, den angezeigten Schlüssel abtippt oder auf dem Telefon einen Link öffnet. Er bekommt zehn Wiederherstellungscodes für den Fall, dass er sein Telefon verliert. Hat er auch diese nicht mehr, setzen Sie den zweiten Faktor im Backend zurück: Profil-Datensatz öffnen, Menü rechts „Zweiter Faktor“ → „Zweiten Faktor zurücksetzen“ (Schreibrecht auf den Bereich nötig; der Vorgang steht im Audit-Log). Prüfen Sie vorher, ob die Anfrage wirklich vom Inhaber kommt.
Ist eine App eingerichtet, verlangt auch der Link aus „Passwort vergessen“ den Code – sonst genügte der Zugriff auf das E-Mail-Postfach, um das Konto zu übernehmen.
Den Code per E-Mail verschickt – wie alle E-Mails der Community-Funktionen – das Template. Soll er per SMS gehen, ruft der Template-Programmierer dort statt der E-Mail einen SMS-Dienst auf.
Die Templates dafür (CMS:USER_LOGIN_CODE, CMS:USER_2FA) müssen vorhanden sein, bevor Sie die Einstellung einschalten – sonst scheitert jede Anmeldung, die einen Code bräuchte.
Schutz der Formulare
„Passwort vergessen“ und die Registrierung schicken E-Mails an Adressen, die jemand eingetippt hat. Damit niemand über Ihre Website fremde Postfächer flutet, begrenzt camindo CMS die Anfragen (Drosselung) – je eingegebener Adresse, je Besucher (IP-Adresse) und je Website. Dazu kommt ein Formularschutz gegen Robots mit einer Sperre je IP-Adresse gegen das massenhafte Durchprobieren von Passwörtern. Die Grenzen stehen in der Konfiguration (unten). Die Vorgaben passen für die meisten Websites.
Nie bestätigte Registrierungen werden nach sieben Tagen gelöscht – wer die Adresse eines anderen einträgt, blockiert sie so nur kurz.
Läuft die Website hinter einem Proxy oder Load-Balancer, tragen Sie ihn unter
security.trusted_proxiesein (Kapitel 12) – sonst sieht camindo CMS alle Besucher mit der Adresse des Proxys und sperrt bei der Drosselung alle zugleich.
Prüfen und Owner
Alles, was ein Frontend-User anlegt oder ändert, wird mit „Prüfung nötig“ markiert und erscheint im Widget „Ungeprüfte Inhalte von Frontend-Usern“ der Redaktion (siehe Handbuch für Anwender). Legen Sie das Metafeld „Prüfung nötig“ in den Profil- und Beitrags-Bereichen an, damit die Redaktion die Markierung nach der Prüfung entfernen kann.
Jeder Datensatz braucht einen Owner im Backend (siehe
Kapitel 7). Für Datensätze von Frontend-Usern
nennt ihn das Template (Parameter owner) oder die Konfiguration
(user.default_owner_id). Fehlt beides, kann der Befehl nicht speichern. Über die Benutzergruppe
dieses Owners steuern Sie, welche Redaktion für die Inhalte der Frontend-User zuständig ist.
Geschützte Dateien
Upload- und Thumbnail-Felder haben einen Abschnitt „Authentifizierung“. Mit „Nur für angemeldete Frontend-User“ und der Auswahl der berechtigten Profil-Container wird das Verzeichnis des Feldes auf dem Server gesperrt. Die Dateien werden dann nur an angemeldete Frontend-User aus diesen Profil-Bereichen ausgeliefert – etwa Mitgliederbilder, Unterlagen für Kursteilnehmer oder Downloads für Kunden. Alle anderen erhalten eine „nicht gefunden“-Antwort.
Datenexport und Löschen
Verlangt ein Website-User Auskunft über seine gespeicherten Daten (Art. 15 DSGVO)
oder eine Kopie zur Mitnahme (Art. 20 DSGVO), erstellen Sie einen
Datenexport personenbezogener Daten: am Profil-Datensatz im Menü rechts
oder im Modul „Datenschutz“ (siehe
Kapitel 15). Der Export ist
ein Teilauszug, den Sie vor der Weitergabe ergänzen.
Website-User können ihre Daten nicht selbst herunterladen.
Löschen (Art. 17 DSGVO): Was beim Löschen eines Profils und seiner Beiträge
geschieht, legt die Lösch-Policy des Bereichs fest – in den Papierkorb legen,
endgültig löschen, einzelne Felder überschreiben, auch zeitversetzt
(siehe Kapitel 15). Die Beiträge des
Users werden dabei immer nach der Policy ihres eigenen Bereichs gelöscht (Auslöser
„UGC: Profil wurde gelöscht“). Der
Löschdialog zeigt, was die Policy mit dem Datensatz macht. Muss der Papierkorb eines
Users sofort geleert werden: „Werkzeuge“ → „Papierkorb eines Users“
(Kapitel 15).
Müssen alle Daten inkl. Änderungshistorie (Audit-Log) entfernt werden:
camindo.php audit delete.
Was camindo CMS insgesamt über Website-User speichert, steht in Kapitel 15.
Konfiguration
Die Community-Einstellungen stehen in .camindo.php unter user (siehe
Kapitel 12):
| Schlüssel | Vorgabe | Bedeutung |
|---|---|---|
user.max_inactive_sec |
86400 |
automatische Abmeldung eines Users nach Untätigkeit (Sekunden) |
user.basket_days |
30 |
Aufbewahrung des Warenkorbs nicht angemeldeter Besucher (Tage) |
user.token_expiration |
86400 |
Gültigkeit des Bestätigungslinks nach der Registrierung (Sekunden) |
user.password_token_expiration |
3600 |
Gültigkeit des Links „Passwort vergessen“ und der Frist danach, in der das neue Passwort ohne das bisherige gesetzt werden kann (Sekunden) |
user.bruteforce_max / bruteforce_delay |
5 / 600 |
erlaubte Fehlversuche bei der Anmeldung und Sperrdauer (Sekunden) |
user.cookie_secure |
true |
Sitzungs-Cookie nur über HTTPS. false nur für einen lokalen Test ohne SSL |
user.default_owner_id |
0 |
Benutzer, dem Datensätze von Frontend-Usern gehören, wenn das Template keinen Owner nennt |
user.throttle |
siehe unten | Drosselung: je Regel [höchstens, Sekunden], höchstens 0 schaltet sie ab |
user.formguard_min_seconds / formguard_max_seconds |
3 / 3600 |
Formularschutz: frühestens bzw. spätestens so viele Sekunden nach dem Aufruf darf ein geschütztes Formular abgeschickt werden. Ein Template kann die Mindestzeit je Formular abweichend setzen |
user.unconfirmed_days |
7 |
nie bestätigte Registrierungen nach so vielen Tagen löschen (0 = nie) |
user.login_code_expiration |
600 |
Gültigkeit des Anmeldecodes (Sekunden) |
Vorgaben der Drosselung (user.throttle):
| Regel | Vorgabe | zählt |
|---|---|---|
pw_value |
3 je Stunde | „Passwort vergessen“ je eingegebener Adresse |
pw_ip |
10 je Stunde | „Passwort vergessen“ je Besucher (IP) |
register_ip |
5 je Stunde | Registrierungen je Besucher |
register_value |
3 je Tag | Registrierungen je E-Mail-Adresse |
mail_instance |
200 je Stunde | beides zusammen je Website |
login_ip |
30 je 10 Minuten | falsche Passwörter je Besucher, über alle Konten |
login_code |
3 je 10 Minuten | „Neuen Code senden“ je Konto |
email_ip |
5 je Stunde | Kontaktformulare mit Drosselung (CMS:EMAIL throttle=true) |
csp_report |
60 je 10 Minuten | Meldungen der Script-Policy je Besucher |
zip_ip |
30 je Stunde | neu erstellte ZIP-Downloads (CMS:ZIP) je Besucher |
Eine Regel ändern Sie einzeln, z. B. 'throttle' => ['pw_ip' => [20, 3600]].
14 Sicherheit, Datenschutz und Betrieb – für Entscheider
Dieses Kapitel richtet sich an alle, die über den Einsatz von camindo CMS entscheiden oder dafür verantwortlich sind: IT-Leitung, Datenschutzbeauftragte, Informationssicherheit und Projektverantwortliche. Es beschreibt, was das System leistet und welche organisatorischen Aufgaben beim Betreiber bleiben. Die technischen Einzelheiten stehen in den verlinkten Kapiteln.
- Sicherheit im Überblick
- Datensicherung und Wiederherstellung
- Updates und Sicherheitsupdates
- Sicherheitslücken melden
- Datenschutz (DSGVO)
- Nachvollziehbarkeit: das Audit-Log
- Betriebsüberwachung
- Aufgaben des Betreibers
Sicherheit im Überblick
| Bereich | Was camindo CMS mitbringt | Mehr dazu |
|---|---|---|
| Anmeldung am Backend | Passwort-Richtlinie (Vorgabe: mindestens 12 Zeichen), Speicherung mit Argon2id, Zwei-Faktor-Anmeldung per Authenticator-App (für Superuser erzwingbar) oder E-Mail-Code, Sperre nach wiederholten Fehlversuchen, Hinweis per E-Mail bei Anmeldung von einem neuen Gerät, automatische Abmeldung nach Untätigkeit | Kapitel 12 |
| Rechte | Benutzergruppen mit Rechten je Modul, Website (Instanz), Sprache und Inhaltsbereich; Datensätze mit Owner; Superuser-Module (Logdateien, Audit-Log) für niemanden sonst | Kapitel 7 |
| Manipulationsschutz | Rechte und Benutzerkonten sind signiert; verändert jemand sie direkt in der Datenbank, greifen sie nicht | Kapitel 12 |
| Anmeldung an der Website | Passwort-Richtlinie, Sperre nach Fehlversuchen je Konto und je Besucher, zweiter Faktor je Profil-Bereich (Authenticator-App oder Code per E-Mail, auch nur auf neuen Geräten), Drosselung und Formularschutz für „Passwort vergessen“ und Registrierung | Kapitel 13 |
| Angriffe über den Browser | Schutz gegen Cross-Site-Request-Forgery (Token) für Backend und Frontend-Formulare; Script-Richtlinie (Content Security Policy) im Backend, im Frontend je Website zuschaltbar; Bereinigung von HTML in Inhalten; Sicherheits-Header | Kapitel 3, Kapitel 12 |
| Verschlüsselung | Felder vom Typ „verschlüsselt“ liegen in der Datenbank verschlüsselt (AES-256-GCM), ebenso E-Mail-Adresse und Telefonnummern der Benutzer. Der Schlüssel liegt außerhalb der Datenbank (.camindo.key) |
Kapitel 5 |
| Dateien | Geschützte Dateien („Nur für angemeldete Frontend-User“) sind auf dem Server gesperrt und werden erst nach Prüfung der Sitzung ausgeliefert; Bildverarbeitung mit eingeschränkter ImageMagick-Richtlinie | Kapitel 8 |
| Nachvollziehbarkeit | Audit-Log aller Änderungen mit Vorher/Nachher | unten |
Grenzen, die Sie kennen sollten:
- Die Zwei-Faktor-Anmeldung per E-Mail-Code ist nur so sicher wie das
E-Mail-Postfach der Benutzer. Stärker ist die Authenticator-App; für Superuser
lässt sie sich vorschreiben (
security.admin_2fa = 'totp_required', Kapitel 12). - Die Domain-Sperre für Medien verhindert, dass Dateien über fremde Websites eingebunden werden. Ein Zugriffsschutz ist sie nicht. Vertrauliche Dateien schützt nur die Feldoption „Nur für angemeldete Frontend-User“. Mandanten, die gegenseitig nicht an ihre Dateien kommen dürfen, brauchen getrennte Installationen (Kapitel 8).
- Superuser haben uneingeschränkten Zugriff. Vergeben Sie diese Rolle sparsam und nur an namentlich bekannte Personen, und teilen Sie Zugänge nie.
Datensicherung und Wiederherstellung
Was gesichert werden muss
| Bestandteil | Ort | Häufigkeit (Empfehlung) |
|---|---|---|
| Datenbank | per Zeitplaner nach var/dbbackup/ |
täglich |
| Mediendateien | public/media/ |
täglich (inkrementell) |
| Projektdaten | var/templates/, var/custom/, var/extensions/, var/modules/, var/deleted/ |
täglich |
| Audit-Log (Inhalte) | var/audit/ – gehört zur Datenbanksicherung desselben Zeitpunkts |
täglich |
| Konfiguration | .camindo.php, composer.json, composer.lock |
bei jeder Änderung |
| Schlüsseldatei | .camindo.key |
einmalig, getrennt von allen anderen Sicherungen |
Nicht gesichert werden müssen var/cache/, var/php/, var/tmp/, var/export/
und vendor/ – sie entstehen neu.
Ohne die Schlüsseldatei sind verschlüsselte Inhalte und alle Signaturen nach einer Wiederherstellung unbrauchbar. Wer die Schlüsseldatei zusammen mit einer Datenbanksicherung erbeutet, kann die verschlüsselten Felder lesen. Deshalb getrennt aufbewahren, etwa im Passwort-Tresor der IT.
Wie gesichert wird
camindo CMS erzeugt die Datenbanksicherung selbst: eine Aufgabe
„Datenbank-Backup“ im Zeitplaner schreibt täglich einen
vollständigen Abzug nach var/dbbackup/ und hält die eingestellte Anzahl vor.
Zusätzlich sichert camindo CMS die Datenbank vor jedem Update automatisch.
Diese Sicherungen liegen auf demselben Server. Sie schützen vor Bedienfehlern und
missglückten Updates, nicht vor dem Verlust des Servers. Für den Betrieb gilt deshalb
die 3-2-1-Regel: drei Kopien, auf zwei verschiedenen Medien, eine davon außerhalb
des Rechenzentrums. Das übernimmt die Datensicherung Ihres Hosters oder Ihrer IT, die
var/dbbackup/ und die übrigen Verzeichnisse regelmäßig vom Server abholt.
Jede Sicherung wird nach dem Schreiben geprüft: Ist sie kleiner als 10 KB (dann enthält sie meist nur eine Fehlermeldung) oder fehlt die Schlusszeile, mit der jeder vollständige Dump endet, wird sie verworfen und der Lauf gilt als fehlgeschlagen. Fällt eine Sicherung aus, sehen Superuser das auf der Startseite (Betriebshinweise): keine Sicherungsaufgabe, fehlgeschlagener Lauf, Sicherung älter als zwei Tage oder unbrauchbar.
Wiederherstellung
Einzelne Inhalte holen Redakteure innerhalb der Aufbewahrungsfrist
(admin.trash_retention_days, Vorgabe 7 Tage) selbst aus dem
Papierkorb zurück – samt Dateien. Wie ein Datensatz
früher aussah, zeigt der Reiter „Änderungen“ (Audit-Log); daraus lassen sich einzelne
Werte von Hand zurückschreiben.
Ganze Installation (etwa nach einem Serverausfall):
- Server bereitstellen, Code per
composer installaus der gesichertencomposer.lockinstallieren. .camindo.phpund.camindo.keyzurückspielen.- Wartungsmodus einschalten:
php Core/cron/camindo.php maintenance on. - Datenbank anlegen und die Sicherung einspielen, etwa
mysql camindo < var/dbbackup/backup-1.sql. public/media/und die Projektverzeichnisse untervar/zurückspielen.php Core/cron/camindo.php upgrade– gleicht Komponenten ab und baut alle Caches neu.- Cronjobs einrichten (Kapitel 1), Wartungsmodus ausschalten, Startseite des Backends auf Betriebshinweise prüfen.
Einzelne Bereiche lassen sich zusätzlich per XML-Export sichern und gezielt zurückholen.
Wiederherstellung üben
Eine Sicherung, deren Wiederherstellung nie geprobt wurde, ist ein Versprechen. Legen Sie fest,
- wie viel Datenverlust höchstens hinnehmbar ist (Recovery Point Objective – bei täglicher Sicherung bis zu 24 Stunden) und
- wie lange die Website höchstens ausfallen darf (Recovery Time Objective),
und spielen Sie mindestens einmal im Jahr eine Sicherung auf einem Testsystem nach der Anleitung oben ein.
Updates und Sicherheitsupdates
Versionen
camindo CMS folgt der semantischen Versionierung MAJOR.MINOR.PATCH:
| Stufe | Bedeutung | Aufwand |
|---|---|---|
| PATCH (9.0.1) | nur Fehlerbehebungen, darunter Sicherheitskorrekturen; keine Änderung an der Datenbank | gefahrlos, zeitnah einspielen |
| MINOR (9.1.0) | neue Funktionen; Bestehendes läuft weiter; kann die Datenbank erweitern | einspielen nach kurzer Prüfung |
| MAJOR (10.0.0) | Änderungen, die Zusatzkomponenten oder Templates anpassen lassen können | planen, auf einem Testsystem prüfen |
Sicherheitskorrekturen erscheinen als Patch-Version für die aktuelle Hauptversion. Die Freigabehinweise jeder Version nennen, ob sie sicherheitsrelevante Korrekturen enthält.
Einspielen
php Core/cron/camindo.php maintenance on
composer update
php Core/cron/camindo.php upgrade
php Core/cron/camindo.php maintenance off
upgrade sichert die Datenbank vorher automatisch. Der Rückweg ist in
Kapitel 12 beschrieben.
Organisatorisch
- Legen Sie fest, wer Freigabehinweise verfolgt und wer Updates einspielt (Vertretung inklusive).
- Sicherheitskorrekturen innerhalb weniger Tage einspielen, übrige Updates im regulären Wartungsfenster.
- Server-Software (PHP, Datenbank, Webserver, ImageMagick, ffmpeg) gehört ebenso dazu. Sie wird über das Betriebssystem bzw. den Hoster aktualisiert, nicht über camindo CMS.
- Zusatzkomponenten und Composer-Pakete kommen mit
composer updatemit. Ob es neuere Versionen gibt und ob für installierte Pakete Sicherheitsmeldungen vorliegen, prüft camindo CMS täglich selbst (composer outdated/composer audit); das Ergebnis steht im Hauptmenü unter „Info“ und als Betriebshinweis auf der Startseite (Kapitel 12).
Sicherheitslücken melden
Lücken in camindo CMS
Den Ablauf – Meldeweg, Fristen, unterstützte Versionen – beschreibt die Datei
Core/SECURITY.md. Kurz: Sicherheitslücken in camindo CMS melden Sie bitte vertraulich an
camindo@camindo.de, nicht über öffentliche Kanäle wie Foren oder
Fehlerverfolgung. Beschreiben Sie, welche Version betroffen ist und wie sich die
Lücke nachvollziehen lässt.
Ein Meldeweg für Ihre Website: security.txt
Für die Websites, die Sie mit camindo CMS betreiben, sind Sie selbst Ansprechpartner.
Der Standard RFC 9116 sieht dafür eine
Datei /.well-known/security.txt vor. Legen Sie sie unter
public/.well-known/security.txt an, etwa so:
Contact: mailto:security@ihre-firma.de
Expires: 2027-09-30T23:00:00.000Z
Preferred-Languages: de, en
Policy: https://www.ihre-firma.de/sicherheit
Contact– eine Adresse, die regelmäßig gelesen wird (kein persönliches Postfach).Expires– höchstens ein Jahr in der Zukunft; rechtzeitig verlängern.Policy– optional: wie Sie mit Meldungen umgehen, ob Sie Meldende nennen.
Solange die Datei fehlt, erinnert die Startseite des Backends Superuser daran.
Datenschutz (DSGVO)
Welche personenbezogenen Daten camindo CMS speichert
Die vollständige Aufstellung – was, wo, wie lange – steht in Kapitel 15 – Datenschutz; hier der Überblick.
| Personen | Daten | Wo |
|---|---|---|
| Benutzer | Name, Anmeldename, E-Mail, Telefon (verschlüsselt), Passwort (als Hash), persönliche Einstellungen, Sitzungen, bekannte Geräte mit gekürzter IP-Adresse, Aktivitäten (und, falls eingeschaltet, Anmeldungen) im Audit-Log | Tabellen admin, admin_session, login_device, audit_log |
| Website-User (Community) | alle Felder des Profil-Bereichs, die Sie festlegen; ihre Beiträge; Sitzungen, Geräte mit gekürzter IP-Adresse, Warenkorb | Profil- und Beitragsbereiche, user_session, login_device, user_basket |
| Personen in Inhalten | was Redakteure in Inhaltsbereiche eintragen (etwa Ansprechpartner, Teams) | Inhaltsbereiche |
| Alle Besucher | IP-Adresse bei fehlgeschlagenen Anmeldungen; technische Protokolle | admin_login_attempt, user_login_attempt, var/log/ |
camindo CMS setzt im Frontend nur technisch notwendige Cookies (Sitzung, Frontend-Editing, Gerätewiedererkennung bei Anmeldung) und bindet keine Dienste Dritter ein. Was Ihre Templates zusätzlich laden (Schriften, Karten, Statistik), liegt in Ihrer Verantwortung.
Speicherfristen
| Daten | Frist | Einstellung |
|---|---|---|
| Gelöschte Inhalte im Papierkorb | 7 Tage, dann endgültig samt Dateien | admin.trash_retention_days |
| Gelöschte Datensätze, Profile und Beiträge | wie die Lösch-Policy des Bereichs es festlegt (Standard: Papierkorb, nach 7 Tagen endgültig; beim Profil nach 7 Tagen alle Felder im Audit-Log geleert; nach 1 Jahr Verlauf gelöscht) | Modul „Datenschutz“ (Kapitel 15) |
| Audit-Log zu bestehenden Inhalten | unbegrenzt (nachvollziehbar bis zur Entstehung) | audit.retention_days_changes |
| Audit-Log zu endgültig gelöschten Objekten (außer Datensätzen) | 365 Tage nach dem Löschen | audit.retention_days_deleted |
| Bekannte Geräte | 180 Tage nach letzter Nutzung | security.device_days |
| Interne Nachrichten zwischen Benutzern | 60 Tage nach dem Versand | privacy.message_days |
| Volle IP-Adressen (Audit-Log, Anmeldeversuche, Logdateien) | 7 Tage, danach gekürzt; Geräte und Audit-Dateien speichern sie von Anfang an gekürzt | privacy.ip_anonymize_days, privacy.ip_v4_octets (Kapitel 15) |
| Sitzungen von Website-Usern | 24 Stunden Untätigkeit | user.max_inactive_sec |
| Anonyme Warenkörbe | 30 Tage | user.basket_days |
| Logdateien, Sicherheitsprotokolle, fehlgeschlagene Anmeldungen | nach Einstellung der Aufgabe „Logs aufräumen“ (Vorgabe 90 / 365 / 30 Tage) | Zeitplaner |
| Datenbanksicherungen | nach eingestellter Anzahl | Zeitplaner, Aufgabe „Datenbank-Backup“ |
Stimmen Sie diese Fristen mit Ihrem Verzeichnis der Verarbeitungstätigkeiten ab. Denken Sie daran, dass gelöschte Daten in Datenbanksicherungen weiterleben, bis die Sicherung selbst ausläuft. Das ist zulässig, gehört aber in Ihr Löschkonzept.
Rechte der Betroffenen
| Recht | Umsetzung in camindo CMS |
|---|---|
| Auskunft (Art. 15) und Datenübertragbarkeit (Art. 20) | „Datenexport personenbezogener Daten“ im Modul „Datenschutz“ oder am Profil-Datensatz: ein Zip mit lesbarer Auskunft, maschinenlesbarem JSON und den Dateien, einschließlich Beiträgen, Geräten, Sitzungen, Änderungsprotokoll und Speicherfristen. Ein Teilauszug, den Sie um Daten außerhalb des CMS ergänzen (Kapitel 15) |
| Berichtigung (Art. 16) | Bearbeiten des Profils im Backend oder durch den Frontend-User selbst, wenn das Template es anbietet |
| Löschung (Art. 17) | Profil löschen – was dann mit Profil, Beiträgen, Dateien und Audit-Log geschieht, legt die Lösch-Policy fest; der Papierkorb eines Users lässt sich sofort leeren (Modul „Werkzeuge“). Den Löschweg für Frontend-User selbst bietet CMS:USER_DELETE |
| Einschränkung (Art. 18) | Status des Profils auf „Deaktiviert“ setzen: die Anmeldung ist gesperrt, die Daten bleiben |
Für Benutzer gilt dasselbe sinngemäß: Ihre Daten stehen in der Benutzerverwaltung; gelöschte Benutzer bleiben als Datensatz erhalten, damit die Angabe „geändert von“ in Inhalten und im Audit-Log gültig bleibt. Ihren Datenexport erstellt, wer das Recht dazu im Modul „Datenschutz“ hat (Kapitel 15).
Technische und organisatorische Maßnahmen
Für Ihre TOM-Dokumentation (Art. 32) können Sie auf die Übersicht Sicherheit im Überblick zurückgreifen. Beim Betreiber bleiben: Hosting mit Auftragsverarbeitungsvertrag, HTTPS, Zugangsregelung zum Server, Datensicherung außerhalb des Servers, Update-Prozess, Rollen- und Rechtekonzept.
Nachvollziehbarkeit: das Audit-Log
Das Audit-Log beantwortet die Frage „Wer hat wann was geändert?“ – für Inhalte ebenso wie für Struktur, Templates, Benutzer und Rechte:
- Jede Änderung mit Zeitpunkt, handelnder Person (Benutzer, Website-User oder System), Herkunft (Backend, Frontend, API, KI-Assistent, Import, Stapelverarbeitung, Zeitplaner) und IP-Adresse.
- Vorher und Nachher aller geänderten Felder, bei Texten absatzweise gegenübergestellt.
- Fehlgeschlagene Anmeldungen und Datenauskünfte; erfolgreiche An- und Abmeldungen
nur, wenn Sie es einschalten (
audit.log_logins).
Einträge lassen sich über die Oberfläche weder ändern noch löschen; sie verschwinden nur nach den eingestellten Fristen.
Ablage und Fälschungsschutz: Die Datenbank enthält nur, wer wann was an welchem
Objekt getan hat und welche Felder betroffen waren. Die Inhalte – Vorher und Nachher –
stehen im Dateisystem unter var/audit/, je Objekt eine Datei, an die nur angehängt
wird (bei mehr als 1 MB beginnt eine weitere Seite). Jede Zeile trägt eine Prüfsumme,
die die vorige einschließt (HMAC-Kette): Wird eine Zeile geändert, entfernt oder
eingeschoben, fällt es auf – fälschen kann die Kette nur, wer den Schlüssel
.camindo.key hat. Wer nur Zugriff auf die Datenbank hat, kann die Inhalte weder
lesen noch ändern; gelöschte, hinzugefügte oder veränderte Einträge der Datenbank
erkennt der Abgleich mit den Dateien – auch wenn dort nur Zeitpunkt, Aktion,
Handelnder oder Bezeichnung umgeschrieben wurden. Geprüft wird jede Nacht von der Zeitplaner-Aufgabe „Audit-Log prüfen“ (Betriebshinweis auf der Startseite bei Befunden), in der
Detailansicht jedes Eintrags und jederzeit mit php Core/cron/camindo.php audit verify.
Dessen Ergebnis ersetzt das der nächtlichen Prüfung; nach audit reseal oder der Prüfung
eines einzelnen Objekts wird der Hinweis auf der Startseite für dieses Objekt nachgeführt.
Datenbanksicherung zurückspielen: Die Dateien unter var/audit/ gehören nicht zum
Datenbank-Dump. Nach dem Zurückspielen enthalten sie Einträge, die es in der Datenbank
nicht mehr gibt, und die Datenbank vergibt deren Nummern neu. Führen Sie deshalb gleich
danach – bevor jemand wieder arbeitet – php Core/cron/camindo.php audit restore aus
(mit --dry-run nur zählen). Der Befehl entfernt alle Einträge, die neuer sind als der
Stand der Datenbank, vermerkt das in der Datei als Kontrollpunkt und legt die
betroffenen Dateien vorher unverändert unter var/audit-restore-{Zeitpunkt}/ ab.
Gebrochene Kette neu verketten: Meldet audit verify bei einem Objekt nur
„chain“ – die Einträge selbst sind echt, nur ihre Verkettung stimmt nicht, etwa weil
eine Datei ersetzt oder aus einer Sicherung zurückgeholt wurde –, prüfen Sie den
Vorgang und verketten danach neu:
php Core/cron/camindo.php audit reseal template 433 --reason="…" (mit --dry-run
nur anzeigen). Die Einträge bis zur Bruchstelle bleiben unverändert, der Rest wird hinter
einem vermerkten Kontrollpunkt neu verkettet; die alten Dateien liegen danach unter
var/audit-reseal-{Zeitpunkt}/. Ist ein Eintrag selbst verändert („hmac“), verweigert
der Befehl das – mit --force geht es trotzdem, der Inhalt dieses Eintrags gilt dann
aber als nicht belegt.
Das Audit-Log ist damit manipulationserkennend – „revisionssicher“ im Sinne der GoBD
wäre es erst mit einem zusätzlichen, nicht veränderbaren Speicher. Redakteure sehen die letzten Änderungen der
Datensätze, die sie lesen dürfen, im Reiter „Änderungen“; die gesamte Recherche ist
Superusern vorbehalten. Datenexporte erstellen nur Benutzer mit dem
Zusatzrecht „Personenbezogene Daten exportieren“ (Modul „Datenschutz“).
Das Audit-Log enthält selbst personenbezogene Daten (Nummern der Handelnden, IP-Adressen, frühere Inhalte). Nennen Sie es in Ihrem Verzeichnis der Verarbeitungstätigkeiten, mit dem Zweck „Nachvollziehbarkeit und Sicherheit“ und den gewählten Fristen.
Betriebsüberwachung
- Betriebshinweise auf der Startseite: Superuser sehen unter den Modulkacheln, wenn der Cronjob steht, temporäre Dateien nicht gelöscht werden, die Datenbanksicherung fehlt oder fehlschlug, der Speicherplatz knapp wird, Verzeichnisse nicht beschreibbar sind, die Konfiguration für den Live-Betrieb nicht passt oder die Update-Prüfung Sicherheitslücken bzw. neue Versionen meldet (Kapitel 12).
- Logdateien: Fehler, gesperrte Anmeldungen, nicht zugestellte E-Mails und Sicherheitsereignisse im Modul „Logdateien“, mit Widget für die Startseite.
- Kommandozeile:
php Core/cron/camindo.php statusfür die externe Überwachung.
Die Hinweise erscheinen nur, wenn jemand die Startseite öffnet. Für eine
Benachrichtigung ohne Anmeldung binden Sie den Server in Ihre bestehende
Überwachung ein (Erreichbarkeit der Website, Alter von var/dbbackup/backup-1.sql,
freier Speicher).
Aufgaben des Betreibers
- Verantwortliche benannt: Betrieb, Updates, Datenschutz, Sicherheitsmeldungen
- Hosting mit Auftragsverarbeitungsvertrag, HTTPS, aktuelle Server-Software
- Tägliche Datenbanksicherung im Zeitplaner, Abholung aller Sicherungen außerhalb
des Servers,
.camindo.keygetrennt verwahrt - Wiederherstellung einmal jährlich geprobt
- Update-Prozess festgelegt; Sicherheitskorrekturen innerhalb weniger Tage
-
public/.well-known/security.txtangelegt und jährlich verlängert - Aufgabe „Logs aufräumen“ eingerichtet, Fristen im Löschkonzept dokumentiert
- Fristen des Audit-Logs festgelegt und im Verzeichnis der Verarbeitungstätigkeiten genannt
- Ablauf für Auskunfts- und Löschersuchen festgelegt (wer, wie schnell, auf welchem Weg die Auskunft übermittelt wird)
- Rechtekonzept: Superuser nur wenige, namentlich; Gruppenrechte nach dem Prinzip der geringsten Rechte; Zugänge ausgeschiedener Mitarbeiter sofort sperren
- Checkliste Live-Betrieb abgearbeitet
15 Datenschutz
Dieses Kapitel beschreibt im Einzelnen, welche personenbezogenen Daten camindo CMS speichert, wo sie liegen und wie lange sie bleiben – getrennt nach Benutzern (Ihren Mitarbeitern im Backend), Website-Usern (Frontend-Community) und Besuchern ohne Konto. Es ist die Grundlage für Ihr Verzeichnis der Verarbeitungstätigkeiten und Ihre Datenschutzerklärung. Die Übersicht für Entscheider steht in Kapitel 14.
- Benutzer (Mitarbeiter)
- Website-User (Community)
- Besucher ohne Konto
- IP-Adressen
- Löschen nach Lösch-Policy
- Datenexport personenbezogener Daten
- Was außerhalb von camindo CMS liegt
- Checkliste
Alle Fristen sind Vorgaben; die Schlüssel stehen in .camindo.php (siehe
Kapitel 12). Gelöschte Daten leben in
Datenbanksicherungen weiter, bis die Sicherung selbst ausläuft – das gehört in
Ihr Löschkonzept.
Benutzer (Mitarbeiter)
| Daten | Wo | Wie lange | |
|---|---|---|---|
| Unverschlüsselte Benutzerdaten | Anmeldename, Namen (Vor-, Anzeige-, Sortiername), Benutzergruppe, Status (freigeschaltet/gesperrt/gelöscht) | Tabelle admin |
solange das Konto besteht; gelöschte Benutzer bleiben erhalten, damit „erstellt/geändert von“ in Inhalten und im Audit-Log gültig bleibt – bis sie anonymisiert werden |
| Verschlüsselte Benutzerdaten | E-Mail, Mobil, Telefon | admin, verschlüsselt |
wie oben |
| Passwort | Hash (nicht umkehrbar) Tag der letzten Änderung (ohne Uhrzeit) |
admin |
wie oben |
| 2FA-Daten | Authenticator-App, Passkeys (Bezeichnung, Zeitpunkt), Wiederherstellungscodes | admin (Schlüssel verschlüsselt), admin_passkey, admin_recovery_code (nur Hashes) |
bis zum Entfernen; Passkeys und Wiederherstellungscodes mit dem Löschen des Kontos; der Schlüssel der App beim Anonymisieren |
| Persönliche Einstellungen | Sprache, Zeitzone, Widgets, Berichte … | admin.settings |
solange das Konto besteht |
| Sitzungsdaten | Oberfläche, letzter Zugriff | admin_session |
bis zur Abmeldung bzw. admin.max_inactive_sec (30 Minuten) Untätigkeit; mit dem Löschen des Kontos sofort |
| Bekannte Geräte | Browser/Betriebssystem, gekürzte IP-Adresse, Zeitpunkt der ersten und letzten Anmeldung | login_device |
security.device_days (180 Tage) nach der letzten Nutzung; mit dem Löschen des Kontos sofort |
| Letzte Anmeldung | Tag (ohne Uhrzeit) | admin.login_date |
wird bei jeder Anmeldung überschrieben |
| Laufende Anmeldung | Zeitpunkt, zu dem die Zwei-Faktor-Anmeldung begann (Code-Versand) | admin.uid_date |
nur bis zum Abschluss der Anmeldung, danach geleert |
| Aktivitäten | was der Benutzer wann geändert hat, mit IP-Adresse | Audit-Log: audit_log (Metadaten), var/audit/ (Inhalte) |
audit.retention_days_changes (unbegrenzt); Einträge zu Datensätzen nach der Lösch-Policy ihres Bereichs; die IP-Adresse wird nach privacy.ip_anonymize_days (7 Tage) gekürzt |
| Fehlgeschlagene Anmeldungen (Audit-Log) | Nummer bzw. eingegebener Name, IP-Adresse, Zeitpunkt, Oberfläche (Backend, PHP-API, Kommandozeile) (bei erkanntem Konto unter dessen Nummer, sonst mit dem eingegebenen Namen) |
Audit-Log | audit.retention_days_logins (90 Tage) |
| „Erstellt von“, „Geändert von“, Owner |
Zeitpunkte | Tabelle record |
solange der Datensatz besteht |
| Historie | Zuletzt geöffnete Datensätze und Templates, Zeitpunkt | history |
nur die jeweils jüngsten Einträge, ältere fallen automatisch weg; mit dem Löschen des Kontos alle |
| Interne Nachrichten | Absender, Empfänger, Betreff, Text verschlüsselt, Zeitpunkt | message |
privacy.message_days (60 Tage) nach dem Versand – für beide Seiten, auch ungelesen; vorher, sobald Absender und Empfänger sie gelöscht haben |
| Erfolgreiche An- und Abmeldungen | Zeitpunkt, IP-Adresse, Oberfläche | Audit-Log – nur mit audit.log_logins = true |
Vorgabe: nicht aufgezeichnet; eingeschaltet audit.retention_days_logins (90 Tage) |
| Fehlgeschlagene Anmeldungen (Sperre) | Zeitpunkt, eingegebener Name, IP-Adresse | admin_login_attempt; beim Sperren eine Zeile im Log security |
in der Tabelle nur für die Sperrdauer admin.bruteforce_delay (10 Minuten), im Log nach der Aufgabe „Logs aufräumen“; IP-Adresse gekürzt nach privacy.ip_anonymize_days |
| Hinweis-E-Mails | Neues Gerät, Passwort geändert – mit voller IP-Adresse | Postfach des Benutzers | nicht in camindo CMS gespeichert |
Benutzernamen, die mit admin_ beginnen, sind für anonymisierte Konten reserviert und
lassen sich nicht neu vergeben. Den Datenexport eines Benutzers erstellt, wer im Modul
„Datenschutz“ das Recht dazu hat (siehe Datenexport).
Fehlgeschlagene Anmeldungen stehen immer im Audit-Log, nach mehreren Fehlversuchen
zusätzlich im Log security. Beides wird nach audit.retention_days_logins gelöscht;
im Datenexport steht bei jedem Eintrag der Tag seiner Löschung.
Anmeldezeiten: Reine Anmeldungen ohne Tätigkeit sagen nichts über Änderungen,
wohl aber über die Arbeitszeiten Ihrer Mitarbeiter. camindo CMS zeichnet erfolgreiche
An- und Abmeldungen deshalb nur auf, wenn Sie audit.log_logins einschalten;
die Standardeinstellung ist false.
Was Sie als Arbeitgeber beachten sollten: Das Audit-Log zeigt, wer wann was geändert hat. Das ist für Nachvollziehbarkeit und Sicherheit gedacht, kann aber zur Leistungs- und Verhaltenskontrolle genutzt werden. Regeln Sie Zweck und Zugriff (Recherche nur für Superuser) in einer Betriebsvereinbarung bzw. internen Richtlinie und informieren Sie Ihre Mitarbeiter.
Ausgeschiedener Mitarbeiter
Ein Benutzerkonto besteht nach dem Löschen weiter, taucht aber nicht mehr in der Benutzerliste auf. Anmeldung ist nicht mehr möglich. Zweck: Nachvollziehbarkeit – Datensätze, Templates und das Audit-Log verweisen auf ihn.
Ein Superuser kann die Nachrichten eines „gelöschten“ Benutzers löschen: Benutzer
öffnen → Reiter „Einstellungen“ → Interne Nachrichten → „Alle Nachrichten
löschen“. Empfangene Nachrichten werden endgültig gelöscht; gesendete verschwinden
aus seinem Postausgang, die Empfänger behalten ihre Fassung. Der Vorgang steht im
Log security. Geräte und Sitzungen entfernen Sie im Reiter „Geräte und Sitzungen“.
Gelöschte Benutzer anonymisieren
Sobald diese Nachvollziehbarkeit nicht mehr gebraucht wird (oder der ehemalige Mitarbeiter die Löschung verlangt), entfernen Sie die Person mit Anonymisieren: Modul „Datenschutz“ → Reiter „Gelöschte Benutzer“ → Benutzer anklicken → auf seiner Infoseite „Anonymisieren“. Die Schaltfläche sehen Superuser und Benutzergruppen mit dem Zusatzrecht „Gelöschte Benutzer anonymisieren“ (für Benutzer der Gruppen, die sie im Modul „Benutzer“ sehen).
| Daten | Anonymisierte Form |
|---|---|
| Benutzername | admin_{Id}, etwa admin_42 – überall, wo der Name erscheint, auch bei „erstellt/geändert von“ |
| Vor-, Anzeige- und Sortiername, E-Mail, Telefon, Mobil, persönliche Einstellungen | gelöscht |
| Passwort, Authenticator-App, Passkeys, Wiederherstellungscodes, Sitzungen, Geräte | gelöscht – das Konto kann sich nicht mehr anmelden |
| Audit-Log: Einträge, in denen er gehandelt hat | erscheinen mit admin_{Id} – das Audit-Log speichert Handelnde nur als Nummer und zeigt den heutigen Namen; die Änderungen selbst bleiben |
| Audit-Log seines Kontos | Bezeichnung admin_{Id}, die Werte der persönlichen Felder in Vorher/Nachher gelöscht |
| Fehlgeschlagene Anmeldungen unter seinem Namen | admin_{Id} statt des Namens |
Weil das Audit-Log Handelnde nur als Nummer speichert, dauert das Anonymisieren auch bei
Benutzern mit langer Vorgeschichte nur einen Augenblick. Bricht es dennoch ab, starten
Sie es einfach erneut – erst der Name admin_{Id} zeigt, dass es abgeschlossen ist.
Das lässt sich nicht rückgängig machen. Der Vorgang steht im Audit-Log des Kontos
(„Datenschutz“) und im Log security. Die Liste zeigt anonymisierte Benutzer mit dem
Hinweis „anonymisiert“.
Website-User (Community)
| Daten | Wo | Wie lange | |
|---|---|---|---|
| Persönliche Daten verschlüsselt | Alle Felder des Profils, die als verschlüsselte Felder eingerichtet wurden (i.d.R. alle mit persönlichen Daten, inkl. Benutzername, E-Mail-Adresse) | Profil-Bereich (Tabellen record, data_enc) |
bis zum Löschen des Profils, danach nach seiner Lösch-Policy – mit der Standard-Policy: admin.trash_retention_days (7 Tage) im Papierkorb, danach endgültig samt Dateien |
| Persönliche Daten unverschlüsselt | Alle Felder des Profils, die als unverschlüsselte Felder eingerichtet wurden, Zeitpunkte der Erstellung und letzten Änderung | Profil-Bereich (Tabellen record, data_*), media/ |
wie oben |
| Passwort | Hash | Profil-Bereich (Tabellen record, data_pwd) |
wie oben |
| Beiträge | Kommentare, Bewertungen … und hochgeladene Dateien, Zeitpunkte der Erstellung und letzten Änderung | Beitrags-Bereiche (Tabellen record, data_*), media/ |
nach der Lösch-Policy des Beitrags-Bereichs; mit den Standard-Policies wie das Profil, sobald es gelöscht wird |
| Datensätze, die auf das Profil verweisen | Verknüpfungen | jeweiliger Bereich | nach Ihren eigenen Regeln (etwa handels- und steuerrechtliche Fristen) |
| Bekannte Geräte | Gerät, gekürzte IP-Adresse, Zeitpunkt der ersten und letzten Anmeldung | login_device |
security.device_days (180 Tage) nach letzter Nutzung; mit dem Löschen des Profils sofort, gleich nach welcher Policy |
| Sitzungsdaten | Session-ID, letzter Zugriff | user_session |
user.max_inactive_sec (24 Stunden) Untätigkeit; mit dem Löschen des Profils sofort |
| 2FA-Daten | Art, Zeitpunkt der ersten Verwendung | user_second_factor |
bis zum Entfernen bzw. Löschen des Profils |
| Offene Bestätigungs- und Passwort-Links | Token, Zeitpunkt | user_token |
bis zur Nutzung bzw. zum Ablauf (user.token_expiration, user.password_token_expiration) |
| Nie bestätigte Registrierungen | Angaben aus dem Registrierungsprozess, Zeitpunkt | Profil-Bereich | user.unconfirmed_days (7 Tage) |
| Warenkorb | Datensatz-Ids (Produkte, Abos, …), Zeitpunkt der letzten Änderung | user_basket |
angemeldet: mit der Sitzung; anonym: user.basket_days (30 Tage) |
| Änderungsprotokoll | Audit-Log zum Profildatensatz und Beiträgen, mit IP-Adresse, Zeitpunkt | Audit-Log | nach der Lösch-Policy; mit den Standard-Policies beim Profil nach 7 Tagen alle Felder geleert, nach 1 Jahr gelöscht. Der User steht nur mit der Nummer seines Profils darin (anonym, sobald das Profil gelöscht ist). IP-Adresse gekürzt nach privacy.ip_anonymize_days |
| Fehlgeschlagene Anmeldungen | Anmeldename, Zeitpunkt, IP nur mit user.bruteforce_ip |
user_login_attempt |
für die Sperrdauer user.bruteforce_delay |
Anmeldenamen, die mit user_ beginnen, sind für anonymisierte Profile reserviert:
bei der Registrierung und im Backend abgelehnt – erlaubt ist nur user_{record_id}
des Profils selbst, wie es eine Lösch-Policy einsetzt.
Den Datenexport eines Website-Users erstellt, wer im Modul „Datenschutz“ das Recht dazu hat (siehe Datenexport und das Handbuch für Anwender).
Besucher ohne Konto
camindo CMS setzt im Frontend nur technisch notwendige Cookies (Sitzung, Frontend-Editing, Gerätewiedererkennung bei der Anmeldung) und bindet keine Dienste Dritter ein. Was Ihre Templates zusätzlich laden (Schriften, Karten, Statistik), liegt in Ihrer Verantwortung.
| Daten | Wo | Wie lange | |
|---|---|---|---|
| Drosselung (Formulare, Anmeldung, CSP-Berichte) |
IP-Adressen nur als Hash, nie im Klartext | Tabelle des RateLimiters | wenige Minuten bis Stunden (Zeitfenster der Drosselung) |
| Gesperrte Anmeldungen, abgewiesene Formulare |
Anmeldename, IP-Adresse, Zeitpunkt | Log security in var/log/ |
Aufgabe „Logs aufräumen“ (Vorgabe 365 Tage); IP-Adressen gekürzt nach privacy.ip_anonymize_days |
| Script-Verstöße (CSP-Berichte) | Script-URL, Zeitpunkt, (keine IP-Adresse) | Log csp |
wie oben |
| Formulareingaben | Teils persönliche Daten | je nach Template: als Datensatz oder E-Mail, je nach Bereich verschlüsselt / unverschlüsselt | nach den Lösch-Regeln des Bereichs, bzw. Postfachs |
IP-Adressen
IP-Adressen sind personenbezogene Daten. Das berechtigte Interesse an der vollständigen Adresse – Angriffe erkennen und abwehren – trägt nach verbreiteter Auffassung nur wenige Tage. camindo CMS hält es deshalb so:
| Wo | Was gespeichert wird | |
|---|---|---|
| Bekannte Geräte | login_device |
von Anfang an nur die gekürzte Adresse |
| Inhalte des Audit-Logs | var/audit/ |
von Anfang an nur die gekürzte Adresse – die Dateien sind fälschungsgeschützt und werden nur ergänzt, nachträglich kürzen ginge nicht |
| Metadaten des Audit-Logs | audit_log |
die volle Adresse, gekürzt nach privacy.ip_anonymize_days (7 Tage) |
| Fehlgeschlagene Anmeldungen | admin_login_attempt, user_login_attempt |
die volle Adresse für die Sperrdauer; gekürzt nach derselben Frist, falls sie länger stehen |
| Logdateien | var/log/ |
die volle Adresse; jede Logdatei, deren Tag älter ist als die Frist, wird gekürzt |
| Drosselung | RateLimiter-Tabelle | nur ein Hash, nie die Adresse |
Welche Adresse „die des Besuchers“ ist, bestimmt an allen Stellen dieselbe Regel:
REMOTE_ADDR, hinter einem eingetragenen Proxy (security.trusted_proxies) die
Adresse aus X-Forwarded-For. Ohne diesen Eintrag steht hinter einem Proxy überall die
Adresse des Proxys.
Wie gekürzt wird:
- IPv4: das letzte Oktett wird genullt (
203.0.113.45→203.0.113.0), mitprivacy.ip_v4_octets = 2die letzten beiden (203.0.0.0). - IPv6: die letzten 80 Bit werden genullt, es bleiben die ersten 48 Bit – das
Netz des Anbieters, nicht der einzelne Anschluss
(
2001:db8:abcd:12::1→2001:db8:abcd::).
Einstellung später ändern: Erhöhen Sie privacy.ip_v4_octets von 1 auf 2, kürzt
der nächste Lauf der Aufgabe „Aufbewahrungsfristen anwenden“ alle bereits gekürzten
Adressen weiter – in der Datenbank, den Logdateien und den Inhalten des Audit-Logs
(203.0.113.0 → 203.0.0.0, angezeigt als 203.0.xxx.xxx). Senken bringt nichts
zurück: Was einmal genullt ist, bleibt es; die Anzeige markiert weiterhin beide Stellen.
Angezeigt werden die gekürzten Stellen als xxx – in der Datenauskunft, in der
Recherche und im Reiter „Änderungen“ des Audit-Logs und in der Geräteliste
(203.0.113.xxx, 2001:db8:abcd:xxxx:xxxx:xxxx:xxxx:xxxx). So hält niemand die Null
für einen Teil der Adresse. Gespeichert bleibt die Adresse mit Nullen: nur so ist sie
weiterhin eine gültige IP-Adresse, die sich vergleichen und – nach einer Änderung von
privacy.ip_v4_octets – weiter kürzen lässt.
Das Kürzen erledigt die Zeitplaner-Aufgabe „Aufbewahrungsfristen anwenden“
(von der Installation eingerichtet, jede Nacht). Jeder Lauf nimmt nur die Einträge
seit dem vorigen Lauf und nutzt die Indizes der Zeitspalten. Logdateien werden
zeilenweise umgeschrieben; das hält es auch bei großen Datenbeständen schnell – unter
Linux wie unter Windows. Der erste Lauf nach dem Update geht einmal über den ganzen
Bestand, ebenso nach einer Änderung von privacy.ip_v4_octets.
Einmalig nach dem Update: Einträge in var/audit/, die vor diesem Update
geschrieben wurden, enthalten noch die volle Adresse. Kürzen Sie sie, am besten im
Wartungsmodus, mit
php Core/cron/camindo.php audit anonymize-ip --dry-run # nur zählen
php Core/cron/camindo.php audit anonymize-ip
Der Befehl schreibt die Dateien mit neu berechneter Prüfsummenkette und vermerkt das
als Kontrollpunkt „anonymize“. Dateien, deren Kette schon vorher gebrochen ist, lässt er
unverändert und nennt sie; prüfen Sie diese mit audit verify (siehe
Kapitel 14).
Bei einem konkreten Angriff: Werden die vollen Adressen zur weiteren Verfolgung
eines bereits erkannten Angriffs zwingend gebraucht, setzen Sie
privacy.ip_anonymize_days vorübergehend hoch. Das hält nur das Kürzen an – bereits
Gekürztes kommt nicht zurück. Sichern Sie die nötigen Einträge (etwa Export aus dem
Audit-Log, Kopie der Logdatei) an einem geschützten Ort, dokumentieren Sie Anlass und
Dauer und stellen Sie die Frist danach wieder zurück.
Die Frist von 7 Tagen ist eine Vorgabe, keine Rechtsberatung. Stimmen Sie sie mit Ihrem Datenschutzbeauftragten ab.
Löschen nach Lösch-Policy
Was „löschen“ bei einem Datensatz heißt, bestimmt die Lösch-Policy seines Inhaltsbereichs. Jeder Inhaltsbereich (Datensätze, Profile, Beiträge) hat genau eine; Sie wählen sie in den Einstellungen des Bereichs (siehe Kapitel 4) und verwalten sie im Modul „Datenschutz“ → „Lösch-Policies“.
Die Liste zeigt je Policy Instanz, Label und die Kategorien ihrer Blöcke. Ein Klick öffnet die Infoseite (mit den Bereichen, die die Policy benutzen, und dem Reiter „Änderungen“), ein Rechtsklick das Kontextmenü mit „Info“, „Bearbeiten“ und „Löschen“.
Aufbau einer Policy
Eine Policy hat ein Label (Text oder Snippet), gilt für eine Instanz (oder für alle) und besteht aus beliebig vielen Blöcken. Jeder Block sagt: bei welchem Auslöser, zu welchem Zeitpunkt, welche Aktion. Dazu wählen Sie eine Kategorie, die die Aktion einordnet – sie dient nur der Übersicht und hat keine Wirkung:
| Kategorie | Typisch für |
|---|---|
| In den Papierkorb legen | In den Papierkorb |
| Nicht mehr zwingend benötigte Daten entfernen | Einzelne Felder überschreiben (Datenminimierung) |
| Eintrag vollständig anonymisieren | Felder im Audit-Log überschreiben |
| Endgültig löschen | Endgültig löschen, samt Audit-Log; Audit-Log endgültig löschen |
| Auslöser | Wann |
|---|---|
| Datensatz wird gelöscht | gleich auf welchem Weg: Löschdialog der Eingabemaske, Stapelverarbeitung, API record.delete oder CMS:USER_DELETE im Frontend – auch für die Unterdatensätze, die mit ihm gelöscht werden |
| UGC: Profil wurde gelöscht | ein Profil wurde gelöscht – einzeln, per Stapelverarbeitung oder mit seinem ganzen Profil-Bereich. Das löst immer und sofort die Policies aller Datensätze dieses Users aus (Beiträge, Bewertungen …), jeweils die Policy ihres eigenen Bereichs. Hat sie keinen Block mit diesem Auslöser, bleiben die Datensätze stehen. Das lässt sich nicht rückgängig machen: Wird das Profil (oder sein Bereich) wiederhergestellt, holen Sie Beiträge im Papierkorb von Hand zurück |
| Bereich wurde gelöscht | der ganze Inhaltsbereich wurde gelöscht; seine Datensätze liegen dann schon mit ihm im Papierkorb. Darum nicht für „In den Papierkorb“ und „Einzelne Felder überschreiben“. Auch sofort fällige Blöcke laufen erst mit der Zeitplaner-Aufgabe „Lösch-Policies anwenden“; wird der Bereich wiederhergestellt, verfallen sie |
Zeitpunkt: sofort (0) oder nach einer Anzahl Tage bzw. Jahre, gerechnet ab dem Auslösen.
Die Aktionen sind in der Auswahl nach dem gruppiert, was sie betreffen:
| Gruppe | Aktion | Was geschieht |
|---|---|---|
| Datensatz | In den Papierkorb (wird nach … Tagen endgültig gelöscht) | der Datensatz kommt in den Papierkorb dessen, der löscht, und wird nach admin.trash_retention_days (Vorgabe 7 Tage) endgültig gelöscht – samt Mediendateien. Die Auswahl nennt die eingestellte Frist |
| Datensatz | Einzelne Felder überschreiben | Felder des Datensatzes bekommen neue Werte, z. B. status_id = "4", username = "user_{record_id}", kontonummer = "". Mehrsprachige Felder bekommen den Wert in allen Sprachen. Ein Upload-Feld nimmt nur "" an: Die Datei wird samt ihrer Thumbnails sofort vom Server entfernt (auch bei mehrsprachigen Uploads in allen Sprachen) |
| Datensatz | Trigger-Template auf den Datensatz anwenden | die Methode onPrivacyAction() im Trigger-Template des Bereichs bekommt den Datensatz – mehrsprachige Felder je Sprache – und kann ihn ändern; Änderungen werden gespeichert. Für alles, was „Einzelne Felder überschreiben“ nicht ausdrücken kann: verknüpfte Datensätze, mehrsprachige Texte je Sprache, eigene Regeln |
| Audit-Log | Felder im Audit-Log überschreiben | im Verlauf des Datensatzes (Datenbank und var/audit/) werden Vorher und Nachher der genannten Felder ersetzt, bei mehrsprachigen Feldern in allen Sprachen. Zusätzlich: _label (Bezeichnung des Eintrags) und * (alle übrigen Felder – gleich, an welcher Stelle die Zeile steht). Auch spätere Einträge – etwa der letzte Stand beim endgültigen Löschen – werden so geschrieben |
| Audit-Log | Trigger-Template auf das Audit-Log anwenden | onPrivacyAction() im Trigger-Template bekommt jeden Eintrag im Verlauf des Datensatzes und kann Bezeichnung und die Werte vorher/nachher ändern; Geändertes wird zurückgeschrieben |
| Audit-Log | Audit-Log endgültig löschen | der ganze Verlauf des Datensatzes |
| Alles | Endgültig löschen, samt Audit-Log | ohne Papierkorb: der Datensatz, seine Unterdatensätze, ihre Dateien und ihr ganzer Verlauf im Audit-Log sind weg |
Die Felder schreiben Sie je Zeile als feld = "wert". Platzhalter im Wert:
{record_id} (der Datensatz) und {user_id} (der User, dem der Datensatz gehört).
Ein Feld, das es im Bereich nicht gibt, wird übergangen; ein Thumbnail-Feld allein
lässt sich nicht leeren – es verschwindet mit seinem Upload-Feld.
Die beiden Trigger-Aktionen brauchen eine Kennung (Kleinbuchstaben, Ziffern,
_), die das Template als $action erhält – so unterscheidet es mehrere Blöcke. Hat
der Bereich mehrere Trigger-Templates, läuft onPrivacyAction() in jedem, das die
Methode enthält, nacheinander. Hat keines die Methode, scheitert der Auftrag und
steht im Log privacy.
Ob Blöcke einander widersprechen oder doppelt sind, prüft camindo CMS nicht – das ist
Sache dessen, der die Policy einrichtet.
Unabhängig von jeder Policy gilt: Beim Löschen eines Profils – auch mit seinem Bereich – werden seine bekannten Geräte und Sitzungen sofort gelöscht, und Mediendateien verschwinden immer mit dem endgültigen Löschen eines Datensatzes.
Unterdatensätze
Mit einem Datensatz werden auch seine Unterdatensätze gelöscht: die Kinder im Baum, wenn Sie „mit Unterdatensätzen“ löschen (sonst rücken sie eine Ebene nach oben und bleiben unberührt), und immer die fest verknüpften Inhalte (Felder vom Typ „link“), auch die der Kinder. Jeder Unterdatensatz bekommt die Blöcke der Policy seines Bereichs für „Datensatz wird gelöscht“ – mit einer Ausnahme: „In den Papierkorb“ und „Endgültig löschen, samt Audit-Log“ erledigt der Hauptdatensatz für alle mit. Ein Unterdatensatz, für den schon eine Löschung läuft, behält seine Aufträge.
Anonym durch das Profil
Das Audit-Log speichert, wer gehandelt hat, nur als Nummer – bei einem Website-User die Nummer seines Profil-Datensatzes, nie seinen Namen. Diese Verknüpfung bleibt immer bestehen; keine Aktion entfernt sie. Anonym werden die Einträge über das Profil: Ist es endgültig gelöscht oder sind seine personenbezogenen Felder mit „Einzelne Felder überschreiben“ geleert, führt die Nummer zu niemandem mehr – auch nicht in den Einträgen zu Beiträgen und anderen Datensätzen, an denen der User gearbeitet hat. Was in den Einträgen selbst personenbezogen ist (Werte vorher/nachher, Bezeichnung), überschreiben Sie mit „Felder im Audit-Log überschreiben“.
Die Standard-Policies
Bei der Installation entstehen drei Policies für alle Instanzen. Sie lassen sich ändern – als Policies für alle Instanzen nur von einem Superuser –, aber nicht löschen; ein neuer Bereich bekommt die seines Typs vorbelegt.
| Policy | Bereichstyp | Blöcke |
|---|---|---|
| Datensatz löschen | Datensätze | sofort in den Papierkorb (nach 7 Tagen endgültig), auch wenn das Profil des Users gelöscht wird; Audit-Log nach 1 Jahr endgültig löschen |
| Profil löschen | Profile | sofort in den Papierkorb (nach 7 Tagen endgültig); im Audit-Log nach 7 Tagen _label durch user_{record_id} ersetzen und alle übrigen Felder leeren; Audit-Log nach 1 Jahr endgültig löschen |
| User-Generated-Content löschen | Beiträge | sofort in den Papierkorb (nach 7 Tagen endgültig), auch wenn das Profil des Users gelöscht wird; Audit-Log nach 1 Jahr endgültig löschen |
Die Blöcke im Audit-Log gelten in allen drei Standard-Policies auch für den Auslöser „Bereich wurde gelöscht“.
Mit den Standard-Policies ist ein gelöschter Website-User nach 7 Tagen anonym: Das Profil ist endgültig gelöscht, sein eigener Verlauf geleert, und die Einträge zu seinen Beiträgen nennen nur noch eine Nummer, die zu keinem Profil mehr gehört.
Beispiel: Profil anonymisieren statt löschen
Soll ein Profil (etwa wegen Bestellungen) stehen bleiben, aber keine Person mehr erkennen lassen:
| Auslöser | Zeitpunkt | Aktion | Felder |
|---|---|---|---|
| Datensatz wird gelöscht | sofort | Einzelne Felder überschreiben | status_id = "4" |
| Datensatz wird gelöscht | 7 Tage | Einzelne Felder überschreiben | username = "user_{record_id}", name = "", kontonummer = "" |
| Datensatz wird gelöscht | 7 Tage | Felder im Audit-Log überschreiben | _label = "user_{record_id}", * = "" |
| Datensatz wird gelöscht | 1 Jahr | Endgültig löschen, samt Audit-Log |
Die Beiträge des Users werden dabei nach der Policy ihres Bereichs mit dem Auslöser „UGC: Profil wurde gelöscht“ gelöscht. Sollen sie bleiben, nehmen Sie diesen Auslöser aus deren Policy heraus.
Hinweis im Löschdialog
Wer im Backend einen Datensatz löscht, sieht vorher, was die Policy mit der Datenbank tut – sofort und nach Fristen, bei einem Profil auch mit seinen Beiträgen:
Der Profil-Datensatz bleibt bestehen, wird aber wie folgt angepasst: – Status: "Gelöscht"
Nach 7 Tagen: – Benutzername: "user_{record_id}" · – Kontonummer: ""
Nach 1 Jahr: – Endgültige Löschung
72 Beiträge des Users („Kommentare“) bleiben bestehen.
Die Stapelverarbeitung zeigt dasselbe je Bereich. Nach dem Löschen heißt die Meldung je nach Policy „gelöscht“, „angepasst“ oder „geplant“.
Wie es ausgeführt wird
Jeder Block wird beim Löschen ein Auftrag (Tabelle privacy_job) mit
Fälligkeit; die sofort fälligen laufen gleich, die übrigen mit der Zeitplaner-Aufgabe
„Lösch-Policies anwenden“ (Vorgabe: jede Nacht; für Fristen in Stunden öfter
terminieren). Ein Auftrag nimmt die Werte seines Blocks mit – eine spätere Änderung der
Policy wirkt nur auf künftige Löschungen. Scheitert ein Auftrag (etwa weil jemand den
Datensatz gerade bearbeitet), gibt es bis zu 20 Versuche; alles steht im Log
privacy. Aktionen einer Policy gelten als System: Pflichtfelder und Gruppenrechte
werden dabei nicht geprüft, und im Audit-Log steht die Änderung als „nach
Lösch-Policy angepasst“ ohne die bisherigen Werte.
Wird ein Datensatz aus dem Papierkorb wiederhergestellt, verfallen seine noch offenen Aufträge. Ein Datensatz, für den schon eine Löschung läuft, lässt sich nicht erneut löschen.
Beim Löschen eines ganzen Bereichs gehen seine Datensätze mit dem Bereich in
den Papierkorb, und camindo CMS plant für jeden die Blöcke der Bereichs-Policy mit dem
Auslöser „Bereich wurde gelöscht“ – mit den Standard-Policies: Audit-Log nach 1 Jahr
endgültig löschen. Hat die Policy keinen Block für diesen Auslöser, bleibt der Verlauf
stehen. Datensätze, für die es nie Aufträge gab (etwa vor Einführung der
Lösch-Policies gelöscht), bekommen beim endgültigen Löschen wenigstens die
Audit-Log-Blöcke dieses Auslösers, die Fristen gerechnet ab dem Löschen. Der Verlauf
endgültig gelöschter Datensätze im Audit-Log richtet sich nur nach den Policies, nicht
nach audit.retention_days_deleted (das gilt weiter für Bereiche, Felder, Templates
und andere Objekte).
Papierkorb eines Website-Users sofort leeren
Verlangt ein Website-User die sofortige Löschung, leert ein Benutzer mit dem Recht „Papierkorb eines Website-Users endgültig leeren“ (Modul „Werkzeuge“) dessen Papierkorb: „Werkzeuge“ → „Papierkorb eines Users“. Das Profil wählen Sie über die Suche in allen Profil-Bereichen, die Sie lesen dürfen, oder – wenn es selbst schon gelöscht ist – aus der Liste der Profile im Papierkorb. Profil und Beiträge, die im Papierkorb liegen, werden sofort endgültig gelöscht. Benutzer leeren ihren eigenen Papierkorb wie bisher selbst.
Audit-Log von Hand löschen
Das endgültige Löschen – auch über „Werkzeuge“ → „Datenbank“ → „Papierkorb leeren“ – lässt den Verlauf eines Datensatzes im Audit-Log stehen; ihn räumen die Audit-Log-Blöcke der Lösch-Policy nach ihrer Frist ab. Muss ein Verlauf früher verschwinden – etwa weil ein Website-User darauf besteht oder Testdaten im Spiel waren –, löschen Sie ihn auf der Kommandozeile:
php Core/cron/camindo.php audit delete record 4237 --dry-run # nur zählen
php Core/cron/camindo.php audit delete record 4237
php Core/cron/camindo.php audit delete --area=141 --force # alle Datensätze eines Bereichs
Gelöscht wird der ganze Verlauf: die Einträge der Datenbank, die Dateien unter
var/audit/ und die Aufträge der Lösch-Policy zu diesem Datensatz. Noch offene Aufträge
bleiben, solange es den Datensatz gibt – sonst würde er nie zu Ende gelöscht; sie räumen
später auch den Eintrag des endgültigen Löschens ab. --area erfasst jeden Datensatz,
der in dem Bereich liegt oder laut Audit-Log dort lag, auch gelöschte; ohne --force
nennt der Befehl nur die Anzahl. Statt record geht jeder andere Objekttyp des
Audit-Logs, etwa admin 34 für den Verlauf eines Benutzerkontos. Der Vorgang steht mit
Anzahl, aber ohne Inhalte im Log security. Einträge, in denen ein Website-User an
anderen Datensätzen gehandelt hat, erfasst audit delete nicht; sie nennen ihn nur mit
der Nummer seines Profils (siehe Anonym durch das Profil).
Datenexport personenbezogener Daten
Für ein Auskunftsersuchen (Art. 15 DSGVO) oder die Datenübertragbarkeit (Art. 20)
erstellt camindo CMS einen Datenexport: ein Zip mit report.html zum Lesen
und data.json maschinenlesbar, bei Website-Usern zusätzlich files/ mit ihren
hochgeladenen Dateien. Er ist ein Teilauszug – vor der Weitergabe an
die betroffene Person ergänzen Sie ihn um alles, was camindo CMS nicht kennt:
Rechtsgrundlagen, Server-Logfiles außerhalb des CMS, Daten in Buchhaltung, E-Mail und
anderen Systemen.
Den Export erstellt, wer im Modul „Datenschutz“ das Zusatzrecht „Personenbezogene Daten exportieren“ hat (Superuser immer), unter „Datenschutz“ → „Datenexport“:
| Person | Wer darf | Wie |
|---|---|---|
| Website-User | wer den Profil-Bereich lesen darf | Profil suchen (alle lesbaren Profil-Bereiche) oder aus den Profilen im Papierkorb wählen – oder am Profil-Datensatz im Menü ⋮ „Datenexport personenbezogener Daten“ |
| Benutzer | Benutzer der Gruppen, deren Benutzer die Gruppe im Modul „Benutzer“ sehen darf (eigene Gruppe mit „Benutzerdetails lesen: eigene Benutzergruppe“, andere mit „Benutzerdetails lesen: andere Benutzergruppen“) | Benutzer aus der Liste wählen |
Benutzer können ihren Export nicht selbst herunterladen.
Vor dem Erstellen prüft camindo CMS die Vorlagen:
- Gibt es für die Instanz des Profils keine Vorlage für Website-User – weder für seinen Profil-Bereich noch für alle Bereiche – (bei einem Benutzer: weder für seine Gruppe noch für alle Gruppen), erscheint ein Hinweis und keine Schaltfläche zum Erstellen – mit dem Recht dazu legen Sie über „Vorlage anlegen“ gleich eine an.
- Gibt es genau eine, wird sie verwendet.
- Gibt es Vorlagen in mehreren Sprachen, wählen Sie die Sprache der Auskunft. Bei Benutzern wählen Sie unter den Benutzer-Vorlagen aller Ihrer Instanzen.
Darunter steht ein Warnhinweis: Eine Datenauskunft darf nur eine dazu berechtigte Person erstellen – in der Regel der Datenschutzbeauftragte. Und: Jede Datenauskunft wird protokolliert; die betroffene Person erfährt in jeder späteren Auskunft, dass heute eine zu ihr erstellt wurde. Erst wenn Sie „Ich bin berechtigt, die Datenauskunft zu erstellen.“ ankreuzen, entsteht der Export mit „Datenauskunft erstellen“.
Der Export eines Website-Users enthält:
- alle Felder des Profils in allen Sprachen (verschlüsselte im Klartext, Passwörter nur als Hinweis),
- seine Beiträge, nach Bereich gegliedert, samt Dateien – Beiträge im Papierkorb sind als „gelöscht, noch im Papierkorb“ gekennzeichnet,
- endgültig gelöschte Beiträge, die das Audit-Log noch mit ihm verbindet, und was die Lösch-Policy damit noch vorhat (etwa „Audit-Log endgültig löschen: 2027-10-08“),
- Datensätze mit Bezug zum Profil (etwa Bestellungen),
- bekannte Geräte und Sitzungen – direkt darunter ihre Speicherdauer –, zweiter Faktor, offene Links, Warenkorb,
- fehlgeschlagene Anmeldeversuche unter seinem Anmeldenamen bzw. seinem Konto, je mit dem Tag der Löschung,
- Einträge in Protokolldateien, die eindeutig zu ihm gehören: Sperren nach zu
vielen Fehlversuchen (Log
security) und Zeilen des Mail-Logs mit seiner E-Mail-Adresse, etwa nicht zustellbare E-Mails, - das Änderungsprotokoll, die Speicherfristen und die Lösch-Policy seines Profil-Bereichs.
Namen anderer Personen stehen nicht in der Auskunft eines Website-Users: Wer
gehandelt hat, erscheint nur als „Sie selbst“, „Admin“, „User“
(ein anderer Website-User) oder „System“. Gekürzte IP-Adressen erscheinen mit
xxx statt der genullten Stellen (203.0.113.xxx), damit niemand die Null für einen
Teil der Adresse hält.
Der Export eines Benutzers enthält: Kontodaten (Kontaktdaten im Klartext, vom
Passwort nur der Tag der letzten Änderung), Geräte und Sitzungen mit ihrer
Speicherdauer, zweiter Faktor (ohne Schlüssel oder Codes), Anmeldungen (nur mit
audit.log_logins) und fehlgeschlagene Anmeldungen unter seinem Namen – je mit dem Tag
ihrer Löschung –, seine Aktivitäten im Audit-Log mit IP-Adresse (die neuesten 1000),
Änderungen an seinem Konto, interne Nachrichten an ihn (Datum, Absender, Betreff), die
Zahl der Datensätze mit seinem Namen und die Speicherfristen.
Jeder Export steht im Audit-Log. Das Zip liegt bis zum Herunterladen in
var/export/, wird dabei gelöscht und spätestens nach admin.export_retention_hours
(24 Stunden) entfernt.
Die Vorlagen der Datenauskunft
Wie report.html aussieht und welcher Text um die Daten herum steht, bestimmt eine
HTML-Vorlage, die Sie selbst gestalten – etwa mit Ihrem Logo und dem Abschnitt
„Speicherdauer“ Ihrer Datenschutzerklärung. Für Website-User und für
Benutzer gibt es getrennte Vorlagen, jeweils je Instanz und je Sprache –
und auf Wunsch je Profil-Bereich bzw. je Benutzergruppe, etwa:
| Art | Instanz | Gilt für | Sprache |
|---|---|---|---|
| Website-User | Shop | Kunden | Englisch |
| Website-User | Shop | Community | Englisch |
| Website-User | Shop | Alle Profil-Bereiche | Deutsch |
| Benutzer | Shop | Redaktion | Englisch |
| Benutzer | Shop | Alle Benutzergruppen | Englisch |
Beim Export gewinnt die spezifische Vorlage: Für ein Profil im Bereich „Kunden“ gelten die Vorlagen für „Kunden“; gibt es keine, die für alle Profil-Bereiche. Bei einem Benutzer gelten die Vorlagen für seine Benutzergruppe (aus allen Ihren Instanzen), sonst die für alle Gruppen. Sie pflegen die Vorlagen unter „Datenschutz“ → „Vorlagen“; anlegen, ändern und löschen darf, wer das Zusatzrecht „Vorlagen der Datenauskunft pflegen“ hat und die Instanz bearbeiten darf (Superuser immer).
Mit „Neu“ wählen Sie zuerst Art (Website-User oder Benutzer) und Instanz,
im Formular dann „Gilt für“ (Profil-Bereich bzw. Benutzergruppe oder alle) und
die Sprache. Eine zweite Vorlage für dieselbe Kombination lässt sich nicht
speichern. Die neue Vorlage ist mit
der Vorlage des Core für diese Art vorbelegt (Core/install/privacy/privacy_user_en_US.html
bzw. privacy_admin_en_US.html, englisch; sie listen am Anfang alle Platzhalter).
Ohne Vorlage für Website-User gibt es für die Website-User einer Instanz keinen
Datenexport; für einen Benutzer wählen Sie unter den Benutzer-Vorlagen aller Ihrer
Instanzen.
Die Auskunft entsteht in der Sprache der Vorlage: Snippets und die Beschriftungen der Tabellen erscheinen in dieser Sprache, unabhängig von Ihrer Backend-Sprache. Weil Arten, Profil-Bereiche und Benutzergruppen getrennte Vorlagen haben, braucht es keine Unterscheidung innerhalb einer Vorlage.
| Schreibweise | Wirkung |
|---|---|
{name} |
Platzhalter – Werte werden maskiert eingesetzt, Blöcke als fertige HTML-Tabellen |
<!-- if:name -->…<!-- endif:name --> |
Abschnitt nur, wenn die Bedingung gilt; verschachtelbar |
{#modul.schluessel} |
Sprach-Snippet in der Sprache der Vorlage, etwa {#record.gdpr_col_device} |
<!-- Kommentar --> |
Erläuterung für Sie – fällt im Export weg |
Bedingungen: audit, audit_changes_limited / audit_changes_unlimited,
audit_deleted_limited, logcleanup / no_logcleanup (Aufgabe „Logs aufräumen“
eingerichtet), dbbackup / no_dbbackup (Aufgabe „Datenbank-Backup“),
messages_limited, ip_v4_one / ip_v4_two.
Fristen (in beiden Arten): {trash_days}, {device_days}, {ip_days},
{ip_v4_octets}, {message_days}, {audit_changes_days}, {audit_deleted_days},
{session_hours} (Website-User), {session_minutes} (Benutzer), {basket_days},
{unconfirmed_days}, {export_hours}, {backups} (aufbewahrte Datenbanksicherungen),
{log_days}, {security_days}, {attempt_days} (aus der Aufgabe „Logs aufräumen“).
So stimmt der Text immer mit den Einstellungen überein – ändern Sie eine Frist, ändert
sich der Export mit.
Kopf: {subject}, {subject_id}, {domain} (Haupt-Domain der Instanz),
{instance} (Bezeichnung der Instanz), {created}, {lang}, {dir}.
Daten in der Vorlage für Website-User: {profile}, {contents} (nach Bereich gegliedert),
{purged} (endgültig gelöschte Beiträge, die das Audit-Log noch kennt),
{references}, {devices}, {sessions} (je mit der Speicherdauer darunter),
{second_factor}, {tokens}, {basket}, {login_attempts}, {log_lines},
{files}, {audit}, {retention} (die Fristen als fertige Liste), {delete_policy}
(die Lösch-Policy des Profil-Bereichs, je Block ein Satz).
Daten in der Vorlage für Benutzer: {account}, {devices}, {sessions},
{second_factor}, {logins}, {activity}, {activity_note}, {account_changes},
{messages}, {content_counts}, {retention}.
Lassen Sie einen Datenblock weg, fehlt er im Export – die Auskunft muss nach Art. 15
DSGVO aber vollständig sein. Prüfen Sie eine geänderte Vorlage deshalb mit einem
Export zu einem Testkonto. data.json enthält unabhängig von der Vorlage immer alle
Daten.
Was außerhalb von camindo CMS liegt
camindo CMS kann nur kürzen und löschen, was es selbst speichert. Auf Ihrer Liste stehen außerdem:
- Zugriffsprotokolle des Webservers (Apache, nginx, IIS) – sie enthalten die volle IP-Adresse jedes Aufrufs. Kürzen Sie sie im Webserver (etwa mit einem anonymisierenden Log-Format) oder löschen Sie sie nach wenigen Tagen per Logrotation.
- PHP- und Datenbank-Protokolle außerhalb von
var/log/. - Datenbanksicherungen und Server-Backups – sie enthalten den Stand zum Zeitpunkt der Sicherung, also auch noch ungekürzte Adressen der letzten Tage.
- E-Mails, die camindo CMS verschickt hat (Hinweise auf neue Geräte, Formulare).
- Proxies, Load-Balancer, CDN und Firewalls vor der Website.
Checkliste
- [ ] Fristen (
privacy.ip_anonymize_days,security.device_days,audit.*,admin.trash_retention_days, Aufgabe „Logs aufräumen“) mit dem Datenschutzbeauftragten abgestimmt und im Verzeichnis der Verarbeitungstätigkeiten eingetragen - [ ] Zeitplaner-Aufgabe „Logs aufräumen“ eingerichtet
- [ ] nach dem Update einmal
audit anonymize-ipausgeführt - [ ] Lösch-Policies geprüft: jeder Inhaltsbereich hat die passende; aufzubewahrende Daten (Bestellungen, Rechnungen) nicht im Papierkorb, sondern anonymisiert
- [ ] Vorlagen der Datenauskunft angelegt („Datenschutz“ → „Vorlagen“): für Website-User je Instanz mit Community (bei Bedarf je Profil-Bereich), für Benutzer mindestens eine (bei Bedarf je Benutzergruppe) – angepasst und mit einem Testkonto geprüft
- [ ] Rechte vergeben: „Personenbezogene Daten exportieren“, „Lösch-Policies anlegen und ändern“, „Vorlagen der Datenauskunft pflegen“ (Modul „Datenschutz“), „Papierkorb eines Website-Users endgültig leeren“ (Modul „Werkzeuge“)
- [ ] entschieden, ob erfolgreiche Anmeldungen aufgezeichnet werden (
audit.log_logins, Vorgabe nein) und wie lange Anmeldungen bleiben (audit.retention_days_logins) - [ ] Frist der internen Nachrichten (
privacy.message_days) festgelegt; bei ausgeschiedenen Mitarbeitern Nachrichten gelöscht - [ ] Zugriffsprotokolle des Webservers gekürzt oder kurzfristig gelöscht
- [ ] hinter einem Proxy:
security.trusted_proxiesgesetzt – sonst steht überall die Adresse des Proxys - [ ] Mitarbeiter über das Audit-Log informiert, Betriebsvereinbarung bzw. Richtlinie
- [ ] Datenschutzerklärung der Website nennt Cookies, Formulare, Community-Funktionen
- [ ] Ablauf für Auskunfts- und Löschersuchen festgelegt (wer, Frist ein Monat)
Stand: camindo CMS 9.1.3