diff --git a/README.md b/README.md index 65fffe0..a787551 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,41 @@ -# OpenSim-Gridverwaltung +# MCP: OpenSim-Gridverwaltung +Das MCP ist ein PHP-Webinterface für Benutzer und Administratoren von OpenSimulator-Grids. Es ermöglicht Benutzern die Registrierung (auf Einladung) und Verwaltung des eigenen OpenSimulator-Accounts im Self-Service-Verfahren. Administratoren können Accounts und Regionen einfacher verwalten. + +## Installation + +Voraussetzung ist, dass die Datenbankstruktur eines OpenSimulator-Grids bereits existiert. Das MCP muss vor der Nutzung mit den Zugangsdaten derselben Datenbank konfiguriert werden. Eigene Tabellen des MCP besitzen zur Vermeidung von Konflikten den Präfix `mcp_`. + +Folgende PHP-Erweiterungen werden benötigt: +1. php-curl +2. php-mysql (PDO) +3. php-xml +4. php-xmlrpc + +Für bessere Performance kann optional `php-apcu` installiert werden. + +Die Installation läuft folgendermaßen ab: +1. Gewünschtes Release als ZIP/TAR-Archiv oder per `git clone` herunterladen +2. Verzeichnisse `app`, `data`, `lib`, `public` und `templates` in das Verzeichnis des Webservers entpacken +3. Öffentliche Stammverzeichnis des Webservers (Apache: `DocumentRoot`, nginx: `root`) auf Pfad zum Verzeichnis `public` ändern +4. Index des Webservers auf index.php ändern, falls erforderlich +5. Beispielkonfiguration `config.example.ini` anpassen, in `config.ini` umbenennen und in das Verzeichnis der in Schritt 2 entpackten Verzeichnisse verschieben + +## Aktualisierung + +Zur Aktualisierung müssen lediglich die Verzeichnisse `app`, `lib`, `public` und `templates`, sowie der Inhalt von `data` (außer `iars`) ersetzt werden. +Die Migration der Datenbankstruktur erfolgt automatisch. Möglicherweise erforderliche Änderungen an der Konfiguration sind den Release-Informationen zu entnehmen. + +## Entwickler + +Die Abhängigkeiten des Frontends werden über [npm](https://www.npmjs.com/) verwaltet. Alle erforderlichen Pakete können nach dem Download des Repository über `npm install` heruntergeladen werden. +In `package.json` ist zudem ein Buildprozess (Befehl: `npm build`) definiert, durch den die Sass-Stylesheets im Verzeichnis `scss` kompiliert und optimiert und zusammen mit Schriftarten und Skripts im öffentlichen Webverzeichnis abgelegt werden. + +Das Backend besitzt kein Dependency Management. Die einzige Abhängigkeit, [PHPMailer](https://github.com/PHPMailer/PHPMailer), wurde manuell in das Repository eingefügt. Der Autoloader sucht im Verzeichnis `lib` nach solchen externen Klassen. + +### Verarbeitung von Anfragen + +Das Skript `index.php` wird bei allen Anfragen aufgerufen. Die angeforderte Route wird als GET-Parameter `=` übermittelt. Gruppen (momentan `api` und `page`), zugehörige Seiten und die assoziierte `RequestHandler`-Subklasse sind in `Mcp.php` definiert. + +Ist zu einer Anfrage eine Route definiert, wird der zugehörige `RequestHandler` erzeugt. Ist eine `Middleware`-Klasse für diesen definiert, ist die weitere Verarbeitung von dem Rückgabewert von `Middleware::canAccess()` abhängig. +Schließlich wird je nach Methode der Anfrage `RequestHandler::get()` bzw. `RequestHandler::post()` aufgerufen. \ No newline at end of file diff --git a/app/Mcp.php b/app/Mcp.php index 3c8c4fe..ffcc48f 100644 --- a/app/Mcp.php +++ b/app/Mcp.php @@ -67,6 +67,9 @@ class Mcp implements ConnectionProvider } } + /** + * Connects to the MySQL database (if not done already) and returns the connection. + */ public function db(): PDO { if ($this->db == null) { @@ -78,17 +81,29 @@ class Mcp implements ConnectionProvider return $this->db; } + /** + * Returns the value associated with the specified key in this config, as either a string, an integer or an array. + * Keys are lower-cased for compatibility reasons. + * + * If there is no entry with this key, an empty array is returned. + */ public function config($key): string|array|int { $realKey = strtolower($key); return isset($this->config[$realKey]) ? $this->config[$realKey] : array(); } + /** + * Returns a hidden form field with the current CSRF token set. + */ public function csrfField(): string { return ''; } + /** + * Creates a TemplateBuilder instance for the specified template file, setting some basic variables. + */ public function template($name): TemplateBuilder { return (new TemplateBuilder($this->templateDir, $name))->vars([ @@ -98,6 +113,9 @@ class Mcp implements ConnectionProvider ])->unsafeVar('csrf', $this->csrfField()); } + /** + * Returns the path of the data/ directory, mostly used for dynamically created assets. + */ public function getDataDir(): string { return $this->dataDir; diff --git a/app/TemplateBuilder.php b/app/TemplateBuilder.php index 5feb870..f3372bc 100644 --- a/app/TemplateBuilder.php +++ b/app/TemplateBuilder.php @@ -19,12 +19,20 @@ class TemplateBuilder $this->name = $name; } + /** + * Sets another template to be the "parent" of this one. + * + * The template specified in this TemplateBuilder's constructor will be included into the parent. + */ public function parent(string $parent): TemplateBuilder { $this->parent = $parent; return $this; } + /** + * Sets multiple variables after escaping them. + */ public function vars(array $vars): TemplateBuilder { foreach ($vars as $key => $val) { @@ -33,18 +41,29 @@ class TemplateBuilder return $this; } + /** + * Sets the specified variable for this template, after escaping it. + */ public function var(string $key, string $val): TemplateBuilder { $this->vars[$key] = htmlspecialchars($val); return $this; } + /** + * Sets the specified variable for this template WITHOUT escaping it. + * + * User input included this way has to be manually sanitized before. + */ public function unsafeVar(string $key, string $val): TemplateBuilder { $this->vars[$key] = $val; return $this; } + /** + * Displays the template(s) with the current set of variables. + */ public function render(): void { $v = new TemplateVarArray($this->vars); diff --git a/app/cron/Frequency.php b/app/cron/Frequency.php index cdfe9e0..3ecf67f 100644 --- a/app/cron/Frequency.php +++ b/app/cron/Frequency.php @@ -5,10 +5,10 @@ namespace Mcp\Cron; enum Frequency { - case YEARLY; - case MONTHLY; - case WEEKLY; - case DAILY; - case HOURLY; - case EACH_MINUTE; + case YEARLY; // 01.01. of each year + case MONTHLY; // 1st of each month + case WEEKLY; // 1 week after last run + case DAILY; // Next day after last run, at 00:00 + case HOURLY; // One hour after last run + case EACH_MINUTE; // One minute after last run } diff --git a/app/middleware/Middleware.php b/app/middleware/Middleware.php index 7641702..3157192 100644 --- a/app/middleware/Middleware.php +++ b/app/middleware/Middleware.php @@ -3,8 +3,20 @@ declare(strict_types=1); namespace Mcp\Middleware; +/** + * Middleware implementations can be registered for a RequestHandler. + * + * If this is done, request processing continues only if Middleware::canAccess() returns true. + */ interface Middleware { + /** + * Returns true if the request should be processed, i.e. if the client has permissionn to perform this request. + */ public function canAccess(): bool; + + /** + * Called when canAcces() returns false, e.g. to redirect unauthorized users. + */ public function handleUnauthorized(): void; -} \ No newline at end of file +}