forked from berhsi/matrix-register
initialer commit
This commit is contained in:
commit
47912a847c
32
README.md
Normal file
32
README.md
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
# matrix-register
|
||||||
|
|
||||||
|
Das Programm befindet sich noch in der Entwicklung! Es gibt keine Garantie
|
||||||
|
für eine korrekte Funktion.
|
||||||
|
|
||||||
|
matrix-register ist eine Webanwendung, welche die Möglichkeit der
|
||||||
|
Registrierung eines Accounts bei matrix.kraut.space anbietet. Der Nutzer
|
||||||
|
beantragt über ein Webformular die Registrierung, bekommt eine
|
||||||
|
Validierungsmail zugesand und nach Bestätigung der Mail den Account
|
||||||
|
aktiviert. Nach erfolgreicher Validierung wird ein temporäres Passwort
|
||||||
|
erzeugt und auf der Webseite angezeigt. Deshalb die Empfehlung https zu
|
||||||
|
benutzen. Auch wenn das Passwort als Hash gespeichert wird - bitte umgehend
|
||||||
|
per Client ändern.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Konfiguration
|
||||||
|
|
||||||
|
Datenbank, Loglevel und einige Parameter der Mail werden in etc/register.ini
|
||||||
|
konfiguriert. Mit einigen Anpassungen dürfte es auch auf andere Host
|
||||||
|
übertragbar sein. Einige Erläuterungen zu den Parametern befinden sich in
|
||||||
|
der Konfigurationsdatei.
|
||||||
|
|
||||||
|
## Abhängigkeiten
|
||||||
|
|
||||||
|
matrix-register benötigt zum Arbeiten folgende Programme:
|
||||||
|
|
||||||
|
* einen Webserver mit aktiviertem php-Support
|
||||||
|
* eine Datenbank (Postgres oder SQLite)
|
||||||
|
* matrix-synapse
|
55
etc/register.ini.example
Normal file
55
etc/register.ini.example
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
; file: register.ini.example
|
||||||
|
; desc: Konfigurationsdatei für das Programm matrix-register. Die Datei in
|
||||||
|
; register.ini umbennen und die Optionen anpassen. Das Programm sucht
|
||||||
|
; die Konfiguration im Verzeichnis ./etc
|
||||||
|
|
||||||
|
|
||||||
|
; Treiber für das php-Datenbankmodul PDO. Generell unterstütz das PDO Modul
|
||||||
|
; die folgenden Trieber:
|
||||||
|
; PDO_DBLIB (FreeTDS/Microsoft SQL Server/Sybase),
|
||||||
|
; PDO_FIREBIRD (Firebird/Interbase 6),
|
||||||
|
; PDO_IBM (IBM DB2),
|
||||||
|
; PDO_INFORMIX (IBM Informix Dynamic Server),
|
||||||
|
; PDO_MYSQL (MySQL 3.x/4.x/5.x),
|
||||||
|
; PDO_OCI (Oracle Call Interface),
|
||||||
|
; PDO_ODBC (ODBC v3 (IBM DB2, unixODBC, and win32 ODBC)),
|
||||||
|
; PDO_PGSQL (PostgreSQL),
|
||||||
|
; PDO_SQLITE (SQLite 3 and SQLite 2),
|
||||||
|
; PDO_4D (D).
|
||||||
|
; Die Verfügbarkeit hängt davon ab, ob das Modul den entsprechenden
|
||||||
|
; Treiber einkompiliert hat. Die verfügbaren Treiber lassen sich mit
|
||||||
|
; "print_r(PDO::getAvailableDrivers());" ausgeben. Je nach Datenbank
|
||||||
|
; sind unterschiedliche Optionen nötig. Der verwendete synapse-matrix Server
|
||||||
|
; unterstützt SQLite oder Postgres-Datenbanken.
|
||||||
|
driver=PDO_PGSQL
|
||||||
|
|
||||||
|
; Pfad zur Datenbank, wenn diese eine Datei ist (z.B. SQLite).
|
||||||
|
file=
|
||||||
|
|
||||||
|
; Parameter, um sich mit einem Datenbankserver zu verbinden
|
||||||
|
host=localhost
|
||||||
|
port=5432
|
||||||
|
database=requests
|
||||||
|
user=besitzer der datenbank requests
|
||||||
|
password=total geheimes passwort
|
||||||
|
|
||||||
|
; Loglevel festlegen. Derzeit sind error, warn, info und debug gültige
|
||||||
|
; Werte. Die Angabe ist nicht Case-Sesitive.
|
||||||
|
loglevel=debug
|
||||||
|
|
||||||
|
; Logdatei festlegen. Der Benutzer, unter dem der Dienst läuft braucht
|
||||||
|
; Schreibrechte für das Verzeichnis.
|
||||||
|
logfile=pfad/zur/logdatei
|
||||||
|
|
||||||
|
; Domainname des Matrixservers, bei der der Account registriert werden soll.
|
||||||
|
mxdomain="matrix.server.me"
|
||||||
|
|
||||||
|
; Parameter für den Validierungslink. Beide Parameter müssen eine valide
|
||||||
|
; URL ergeben. Der Token wird vom Programm generiert.
|
||||||
|
baseurl="https://meine.domain/"
|
||||||
|
validator="register/validation.php?token="
|
||||||
|
|
||||||
|
; Parameter für die Validierungsmail
|
||||||
|
mailfrom="From: Matrix Registrierung <meine.domain>"
|
||||||
|
mailsubject="Ihr Matrix Account bei meiner Domain"
|
||||||
|
mailclosure="Mfg"
|
154
index.php
Normal file
154
index.php
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
ini_set('display_errors', true);
|
||||||
|
|
||||||
|
require("static/web.php");
|
||||||
|
require("lib/request.php");
|
||||||
|
|
||||||
|
|
||||||
|
$outputLogin = "";
|
||||||
|
$outputEmail = "";
|
||||||
|
$class="";
|
||||||
|
$title = "";
|
||||||
|
$message = "";
|
||||||
|
$saved = false;
|
||||||
|
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||||
|
// echo '<pre>' . htmlspecialchars(var_export($_POST, true)) . '</pre>';
|
||||||
|
$inputLogin = $_POST['login'] ?? '';
|
||||||
|
$inputEmail = $_POST['email'] ?? '';
|
||||||
|
$inputCaptcha = $_POST['captcha'] ?? '';
|
||||||
|
if ($inputCaptcha && $inputLogin && $inputEmail) {
|
||||||
|
$request = new Request();
|
||||||
|
$saved = $request->checkRequest($message);
|
||||||
|
if ($saved) {
|
||||||
|
$class = "success";
|
||||||
|
$title = "Gespeichet";
|
||||||
|
} else {
|
||||||
|
$class = "error";
|
||||||
|
$title = "Sorry";
|
||||||
|
$outputLogin = $inputLogin;
|
||||||
|
$outputEmail = $inputEmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$class = "error";
|
||||||
|
$title = "Sorry";
|
||||||
|
$message = "Something goes wrong";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
|
||||||
|
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html lang="de">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>matrix.kraut.space - request</title>
|
||||||
|
<?php echo HTML_META ?>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="wrapper">
|
||||||
|
|
||||||
|
<?php echo HTML_HEADER ?>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
|
||||||
|
<section id="matrix">
|
||||||
|
<h2>Komm in die Matrix ...</h2>
|
||||||
|
Der Krautspace ist auch in der <a href="https://matrix.org">Matrix</a> zu
|
||||||
|
erreichen. Ihr findet uns dort unter <a
|
||||||
|
href="">#krautchan:matrix.kraut.space</a> oder <a
|
||||||
|
href="">#krautchan:matrix.org</a>. Da wir uns ein dezentrales Internet
|
||||||
|
wünschen, betreiben wir auch einen eigenen Matrix-Server. Wenn Ihr dort
|
||||||
|
einen Account möchtet, schreibt eine Mail an <a
|
||||||
|
href="mailto:matrix@kraut.space">matrix@kraut.space</a> oder benutzt
|
||||||
|
das untenstehende Formular.
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section id="register">
|
||||||
|
<h2>Als Benutzer für den Matrix Chat registrieren</h2>
|
||||||
|
|
||||||
|
<p>Über dieses Formular können Sie einen Account für die Benutzung des
|
||||||
|
Matrix-Chats auf dem Server matrix.kraut.space registrieren. Der
|
||||||
|
Benutzername sollte aus einem Wort ohne Umlaute, Leer- oder Sonderzeichen
|
||||||
|
bestehen. Stellen Sie sicher, daß Sie eine gültige E-Mail-Adresse angegeben
|
||||||
|
- an diese wird die Bestätigungsmail gesendet. Nach erfolgreicher
|
||||||
|
Aktivierung Ihres Accounts bekommen Sie Ihr vorläufiges Passwort. Sie
|
||||||
|
sollte dieses danach unverzüglich über Ihren Matrix-Client ändern.</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div class="<?php echo $class ?>">
|
||||||
|
<?php if ($title): ?>
|
||||||
|
<h3><?php echo $title ?></h3>
|
||||||
|
<?php endif ?>
|
||||||
|
|
||||||
|
<?php if ($message): ?>
|
||||||
|
<p><?php echo $message ?></p>
|
||||||
|
<?php endif ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<section id="formular">
|
||||||
|
<form id="matrix-register" method="post" accept-charset="utf-8" action="#">
|
||||||
|
<fieldset><legend>Registrieren</legend>
|
||||||
|
<div class="formrow">
|
||||||
|
<label class="formlabel" for="login">Benutzername
|
||||||
|
<input class="forminput"
|
||||||
|
id="login"
|
||||||
|
type="text"
|
||||||
|
name="login"
|
||||||
|
value="<?php echo htmlspecialchars($outputLogin)?>"
|
||||||
|
placeholder="your name"
|
||||||
|
pattern="^[a-z-\.=\_\/]+$"
|
||||||
|
size=50
|
||||||
|
maxlength="50"
|
||||||
|
required="required" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="formrow">
|
||||||
|
<label class="formlabel" for="email">E-Mail
|
||||||
|
<input class="forminput"
|
||||||
|
id="email"
|
||||||
|
type="email"
|
||||||
|
name="email"
|
||||||
|
value="<?php echo htmlspecialchars($outputEmail)?>"
|
||||||
|
placeholder="your email"
|
||||||
|
size=50
|
||||||
|
maxlength="50"
|
||||||
|
required="required" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="formrow" id="captchaframe">
|
||||||
|
<label class="captchalabel">
|
||||||
|
Der Krautspace residiert in der Krautgasse 26. Welche Hausnummer ist
|
||||||
|
das?
|
||||||
|
<input id="captchainput"
|
||||||
|
type="text"
|
||||||
|
name="captcha"
|
||||||
|
size=5
|
||||||
|
maxlength="3"
|
||||||
|
required="required" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<input type="submit" value="Registrieren" />
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<p>Bitte beachten Sie bei der Auswahl des Benutzernamens, daß die
|
||||||
|
Spezifikation für den 'localpart' der Matrix-ID neben Kleinbuchstaben und
|
||||||
|
Zahlen lediglich noch die Zeichen Minus, Punkt, Gleichheitszeichen,
|
||||||
|
Unterstrich und den Schrägstrich zuläßt.</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php echo HTML_FOOTER ?>
|
||||||
|
|
||||||
|
</div> <!-- ende div wrapper -->
|
||||||
|
</body>
|
||||||
|
</html>
|
92
lib/base.php
Normal file
92
lib/base.php
Normal file
|
@ -0,0 +1,92 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* file: lib/base.php
|
||||||
|
* date: 28.02.2021
|
||||||
|
* user: bernd@nr18.space
|
||||||
|
* desc:
|
||||||
|
*/
|
||||||
|
|
||||||
|
require("db.php");
|
||||||
|
require("config.php");
|
||||||
|
require("logger.php");
|
||||||
|
|
||||||
|
|
||||||
|
class BaseClass {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basisklasse ... stellt die Instanzen für die Konfiguration und die
|
||||||
|
* Datenbank zur verfügung. Bildet die Grundlage für request (Anfrage
|
||||||
|
* des Accounts) und Registrator (Registrierung des Accounts).
|
||||||
|
*/
|
||||||
|
|
||||||
|
private $config_path = "/etc/matrix-register/register.ini";
|
||||||
|
public $config; // Instanz der die Klasse Config
|
||||||
|
public $log; // Instanz der Klasse Logger
|
||||||
|
public $db; // Instanz der Klasse Database
|
||||||
|
public $token = ""; // Variable für Token oder temp. Password
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Beim Erstellen der Instanz wird das Einlesen der Config
|
||||||
|
* angestoßen. Sollte das Fehlschlagen, stellt die Klasse Config
|
||||||
|
* auch Defaultwerte zur Verfügung. Danach wird versucht ein
|
||||||
|
* Datenbankobjekt zu bekommen.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instanz der Klasse Logger erstellen. Nach den Erstellen der
|
||||||
|
* Instanz von Config wird noch das Loglevel angepaßt.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
$this->log = new Logger();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
throw new Exception("Can't create logger instance");
|
||||||
|
}
|
||||||
|
$this->log->d("Create a instance of BaseClass");
|
||||||
|
/**
|
||||||
|
* Instanz der Klasse Config erstellen und Konfigurationsdatei
|
||||||
|
* einlesen lassen.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
$this->config = new Config();
|
||||||
|
$this->config->loadConfig($this->config_path);
|
||||||
|
$this->log->d("Configuration file parsed");
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$this->log->e("Error: {$e->getMessage()}");
|
||||||
|
}
|
||||||
|
$this->log->setLogLevel($this->config->getLogLevel());
|
||||||
|
/**
|
||||||
|
* Instanz der Klasse Datenbank erstellen. Die Datenbank bekommt die
|
||||||
|
* Instanz der Klasse Config übergeben. Wenn nicht vorhanden wird
|
||||||
|
* die Tabelle requests angelegt.
|
||||||
|
*/
|
||||||
|
try {
|
||||||
|
$this->db = getDatabase($this->config, $this->log);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$this->log->e("Error: {$e->getMessage()}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generateToken(int $length): bool {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generiert einen Token aus zufälligen Bits der Länge 'length'.
|
||||||
|
* Speichert diesen Token in der als Refeenz übergebenen Variable.
|
||||||
|
*/
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->token = bin2hex(random_bytes($length));
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$this->log->e("Token creation failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
?>
|
100
lib/config.php
Normal file
100
lib/config.php
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
class Config {
|
||||||
|
|
||||||
|
private $config = [];
|
||||||
|
|
||||||
|
public function loadConfig(string $config_path) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Einlesen der Konfiguration.
|
||||||
|
* Anmerkung: Das @ unterdrückt die ausgabe von Warnungen. Ein
|
||||||
|
* Fehlen der Konfigurationsdatei erzeugt keine Exception!
|
||||||
|
*/
|
||||||
|
|
||||||
|
$this->config = @parse_ini_file($config_path);
|
||||||
|
if ($this->config === false)
|
||||||
|
{
|
||||||
|
throw new Exception("Failed to parse configuration file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDbDriver(): string {
|
||||||
|
$driver = $this->config['driver'] ?? "PDO_PGSQL";
|
||||||
|
return $driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDbFile(): string {
|
||||||
|
$file = $this->config['file'] ?? "./request.db";
|
||||||
|
return $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDbHost(): string {
|
||||||
|
$host = $this->config['host'] ?? "localhost";
|
||||||
|
return $host;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDbPort(): int {
|
||||||
|
$port = $this->config['port'] ?? 5432;
|
||||||
|
return $port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDbBase(): string {
|
||||||
|
$database = $this->config['database'] ?? "requests";
|
||||||
|
return $database;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDbUser(): string {
|
||||||
|
$user = $this->config['user'] ?? "matrixadmin";
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDbPass(): string {
|
||||||
|
$password = $this->config['password'] ?? "geheim";
|
||||||
|
return $password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLogLevel(): string {
|
||||||
|
$loglevel = strtoupper($this->config['loglevel']) ?? "INFO";
|
||||||
|
return $loglevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLogFile(): string {
|
||||||
|
$logfile = $this->config['logfile'] ?? "log/register.log";
|
||||||
|
return $logfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMxDomain(): string {
|
||||||
|
$driver = $this->config['mxdomain'] ?? "matrix.kraut.space";
|
||||||
|
return $driver;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getBaseURL(): string {
|
||||||
|
$baseurl = $this->config['baseurl'] ?? "";
|
||||||
|
return $baseurl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getValidator(): string {
|
||||||
|
$validator = $this->config['validator'] ?? "validator.php?token=";
|
||||||
|
return $validator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMailFrom(): string {
|
||||||
|
$mailfrom = $this->config['mailfrom'] ?? "";
|
||||||
|
return $mailfrom;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMailSubject(): string {
|
||||||
|
$mailsubject = $this->config['mailsubject'] ?? "Ihr Matrix Account";
|
||||||
|
return $mailsubject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMailClosure(): string {
|
||||||
|
$mailclosure = $this->config['mailclosure'] ?? "MfG";
|
||||||
|
return $mailclosure;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
340
lib/db.php
Normal file
340
lib/db.php
Normal file
|
@ -0,0 +1,340 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* file: db.php
|
||||||
|
* date: 25.01.2021
|
||||||
|
* author: bernd@nr18.space
|
||||||
|
* desc: Anbindung an die (Postgres) Datenbank.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
function testDriver(): bool
|
||||||
|
{
|
||||||
|
print_r(PDO::getAvailableDrivers());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDatabase(&$config): Database {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erstellt ein Datenbank Objekt und gibt dieses zurück. Im Fehlerfall
|
||||||
|
* wird eine Exception mit der Meldung der PDOException ausgelöst.
|
||||||
|
*/
|
||||||
|
|
||||||
|
try {
|
||||||
|
$pdo = Connection::get()->connect($config);
|
||||||
|
$db = new Database($pdo, $log);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
throw new Exception($e->getMessage());
|
||||||
|
}
|
||||||
|
return $db;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Connection {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stellt die Verbindung zur Datenbank her. Derzeit sind Postgres, MySQL
|
||||||
|
* und SQLite Datenbanken möglich.
|
||||||
|
*/
|
||||||
|
|
||||||
|
private static $conn;
|
||||||
|
|
||||||
|
public function connect(&$config)
|
||||||
|
{
|
||||||
|
|
||||||
|
$driver = $config->getDbDriver();
|
||||||
|
$file = $config->getDbFile();
|
||||||
|
$host = $config->getDbHost();
|
||||||
|
$port = $config->getDbPort();
|
||||||
|
$base = $config->getDbBase();
|
||||||
|
$user = $config->getDbUser();
|
||||||
|
$pass = $config->getDbPass();
|
||||||
|
|
||||||
|
try {
|
||||||
|
if ($driver === "PDO_PGSQL") {
|
||||||
|
$pdo = new PDO("pgsql:host=$host;port=$port;dbname=$base", $user, $pass);
|
||||||
|
}
|
||||||
|
else if ($driver === "PDO_SQLITE") {
|
||||||
|
$pdo = new PDO("sqlite:$file");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new Exception("Wrong driver for database: {$driver}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
throw new Exception($e->getMessage());
|
||||||
|
}
|
||||||
|
if (isset($pdo)) {
|
||||||
|
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||||
|
}
|
||||||
|
return $pdo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function get()
|
||||||
|
{
|
||||||
|
if (null === static::$conn)
|
||||||
|
{
|
||||||
|
static::$conn = new static();
|
||||||
|
}
|
||||||
|
return static::$conn;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function close()
|
||||||
|
{
|
||||||
|
static::$conn = null;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Database {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stellt das Datenbankobjekt und die Methoden zum Arbeiten mit der
|
||||||
|
* Datenbank zur verfügung.
|
||||||
|
*/
|
||||||
|
|
||||||
|
private $pdo;
|
||||||
|
private $log;
|
||||||
|
|
||||||
|
public function __construct($pdo, $log)
|
||||||
|
{
|
||||||
|
$this->pdo = $pdo;
|
||||||
|
$this->log = $log;
|
||||||
|
$this->log->d("Databaseobject created");
|
||||||
|
// hier vielleicht TableCreate hin
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function TableExists(): int
|
||||||
|
{
|
||||||
|
$stmt = "SELECT * FROM information_schema.tables WHERE
|
||||||
|
table_type = 'BASE TABLE' and
|
||||||
|
table_name = 'requests'";
|
||||||
|
$response = $this->pdo->query($stmt);
|
||||||
|
$count = $response->rowCount();
|
||||||
|
return $count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createTable()
|
||||||
|
{
|
||||||
|
$stmt = "CREATE TABLE IF NOT EXISTS requests (
|
||||||
|
id serial PRIMARY KEY,
|
||||||
|
nick varchar(80) NOT NULL UNIQUE,
|
||||||
|
email varchar(80) NOT NULL,
|
||||||
|
token char(32) NOT NULL UNIQUE,
|
||||||
|
time integer NOT NULL);";
|
||||||
|
$this->pdo->exec($stmt);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function UserExistsInUsers(string $nick): bool
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Sucht in der Tabelle users nach bereits angelegten Nutzern. Die
|
||||||
|
* Abfrage der Datenbank wird an die Funktion searchUser delegiert.
|
||||||
|
* Sollte diese eine Exception werfen, wird true (es gibt einen
|
||||||
|
* Benutzer) zurück gegeben. Ansonsten wird der Rückgabewert
|
||||||
|
* von der Funktion getNick ausgewertet, die aus der übergebenen
|
||||||
|
* Matrix-ID den localpart extrahiert.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$this->log->d("Search for localpart {$nick} in users");
|
||||||
|
$query = "SELECT name FROM users WHERE name LIKE :nick";
|
||||||
|
$pattern = "%$nick%";
|
||||||
|
try {
|
||||||
|
$response = $this->searchUser($query, $pattern);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$this->log->e("searchUser() returns true because PDOException");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
$count = count($response);
|
||||||
|
if ($count == 0)
|
||||||
|
{
|
||||||
|
$this->log->d("Nothing found");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach ($response as $array) {
|
||||||
|
$uid = $this->getNick($array['name']);
|
||||||
|
$this->log->d("Compare {$nick} with {$uid}");
|
||||||
|
if ($uid === $nick) {
|
||||||
|
$this->log->i("MID localpart already exists: {$nick}");
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
$this->log->d("False");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function UserExistsInRequests(string $nick): bool
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Sucht in der Tabelle requests nach breits beantragten
|
||||||
|
* Nutzernamen. Die Abfrage der Datenbank wird an die Funktion
|
||||||
|
* searchUser delegiert. Sollte diese eine Exception werfen, wird
|
||||||
|
* true (es gibt einen benutzer) zurück gegeben. Ansonsten wird die
|
||||||
|
* Anzahl der Treffer ausgewertet.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$this->log->d("Search for localpart {$nick} in requests");
|
||||||
|
$query = "SELECT nick FROM requests WHERE nick = :nick";
|
||||||
|
try {
|
||||||
|
$response = $this->searchUser($query, $nick);
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$this->log->e("searchUser() returns true because PDOException");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
$count = count($response);
|
||||||
|
if ($count > 0) {
|
||||||
|
$this->log->d("Search for {$nick}: {$count} hit(s)");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
$this->log->d("Nothing found");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function searchUser(string $query, string $nick): array
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Führt die Suchoperartion auf der Datenbank aus. Bekommt dafür den
|
||||||
|
* Querystring und den Nick übergeben. Sollte Abfrage der Datenbank
|
||||||
|
* fehlschlagen, wirft die Funktion die Exception an die aufrufende
|
||||||
|
* Funktion.
|
||||||
|
*/
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$stmt = $this->pdo->prepare($query,
|
||||||
|
array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
|
||||||
|
$stmt->execute(array(':nick' => $nick)); // gibt bool zurück
|
||||||
|
$response = $stmt->fetchAll();
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
catch (PDOException $e)
|
||||||
|
{
|
||||||
|
$errormsg = $e->getMessage();
|
||||||
|
$this->log->e("A PDO-Exception occurres");
|
||||||
|
$this->log->e("Error: {$errormsg}");
|
||||||
|
throw new PDOException($errormsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getNick(string $mid): string
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Extrahiert aus einer Matrix-ID den localpart.
|
||||||
|
* TODO: In eine bibliothek auslagern? (/lib/common)
|
||||||
|
*/
|
||||||
|
|
||||||
|
$this->log->d("Extract nick from {$mid}");
|
||||||
|
$uid = "";
|
||||||
|
$append = false;
|
||||||
|
$strarray = str_split($mid);
|
||||||
|
foreach ($strarray as $char)
|
||||||
|
{
|
||||||
|
if ($char == '@')
|
||||||
|
{
|
||||||
|
$append = true;
|
||||||
|
}
|
||||||
|
else if ($char == ':')
|
||||||
|
{
|
||||||
|
$this->log->d("Extracted: {$uid}");
|
||||||
|
return $uid;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ($append === true)
|
||||||
|
{
|
||||||
|
$uid = $uid.$char;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function saveRequest($token): bool
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Speichert den gewünschten Nick, die Emailadresse, das Token und
|
||||||
|
* einen Zeitstempel in der Tabelle Requests.
|
||||||
|
* TODO: Sollten/Müssen Nick und Email noch durch htmlspecialchars()
|
||||||
|
* oder reichen die prepared Statments?
|
||||||
|
*/
|
||||||
|
|
||||||
|
$nick = $_POST['login'];
|
||||||
|
$email = $_POST['email'];
|
||||||
|
date_default_timezone_set("Europe/Berlin");
|
||||||
|
$time = time();
|
||||||
|
$this->log->d("Save request for: {$nick} with {$token} at {$time}");
|
||||||
|
try {
|
||||||
|
$stmt = $this->pdo->prepare("INSERT INTO requests
|
||||||
|
(nick, email, token, time) VALUES
|
||||||
|
(:nick, :email, :token, :time)");
|
||||||
|
$response = $stmt->execute(array(':nick' => $nick,
|
||||||
|
':email' => $email,
|
||||||
|
':token' => $token,
|
||||||
|
':time' => $time));
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$errmsg = $e->getMessage();
|
||||||
|
$this->log->e("Saving request failed");
|
||||||
|
$this->log->e("Error: {$errmsg}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$this->log->i("Request saved successfull");
|
||||||
|
$this->log->d("Database returns: {$response}");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getToken(): array {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sucht in der Tabelle requests nach dem Token. Gibt im Erfolgsfall
|
||||||
|
* ein Array mit ID, Name und Token zurück. Andernfalls ein leeres
|
||||||
|
* Array. Im Falle eines Datenbankfehlers wird eine Exception
|
||||||
|
* geworfen.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$token = $_GET['token'];
|
||||||
|
$query = "SELECT id, nick, token FROM requests WHERE token = :token";
|
||||||
|
try {
|
||||||
|
$stmt = $this->pdo->prepare($query,
|
||||||
|
array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
|
||||||
|
$stmt->execute(array(':token' => $token)); // gibt bool zurück
|
||||||
|
$response = $stmt->fetchAll();
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$this->log->e("PDO Exception occures");
|
||||||
|
throw new Exception($e->getMessage());
|
||||||
|
}
|
||||||
|
$this->log->d("Database operation successfull");
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function removeToken(int $id): int {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Entfernt den Request aus der Tabelle requests. Wird aufgerufen,
|
||||||
|
* wenn die Registrierung des Nicks am Matrixserver erfolgreich war.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$query = "DELETE FROM requests WHERE id = :id";
|
||||||
|
try {
|
||||||
|
$stmt = $this->pdo->prepare($query,
|
||||||
|
array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
|
||||||
|
$stmt->execute(array(':id' => $id)); // gibt bool zurück
|
||||||
|
} catch (PDOException $e) {
|
||||||
|
$this->log->e("PDO Exception occures");
|
||||||
|
throw new Exception($e->getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$this->log->d("Database operation successfull");
|
||||||
|
return $stmt->rowCount();;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
73
lib/logger.php
Normal file
73
lib/logger.php
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* file: logger.php
|
||||||
|
* date: 01.03.2021
|
||||||
|
* author: bernd@nr18.space
|
||||||
|
* desc: Simpler Logger
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
class Logger {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Einfache Klasse zum Loggen von Nachrichten. Schreibt seine
|
||||||
|
* Nachrichten in eine Datei. Eleganter wäre ein Weiterreichen an den
|
||||||
|
* Logging-Daemon des Betriebssystems.
|
||||||
|
* TODO: Er ist wenig Fehlertolerant. Es wird nicht geprüft, ob der
|
||||||
|
* angefragte Key im Array existiert.
|
||||||
|
*/
|
||||||
|
|
||||||
|
private $levelnumbers = array(
|
||||||
|
"ERROR" => 10,
|
||||||
|
"WARN" => 20,
|
||||||
|
"INFO" => 30,
|
||||||
|
"DEBUG" => 40,
|
||||||
|
);
|
||||||
|
public $loglevel = "INFO";
|
||||||
|
private $logfile = "log/register.log";
|
||||||
|
private $app = "matrix-register";
|
||||||
|
|
||||||
|
public function e(string $msg) {
|
||||||
|
$this->logMsg("ERROR", $msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function w(string $msg) {
|
||||||
|
$this->logMsg("WARN", $msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function i(string $msg) {
|
||||||
|
$this->logMsg("INFO", $msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function d(string $msg) {
|
||||||
|
$this->logMsg("DEBUG", $msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setLogLevel(string $level) {
|
||||||
|
if (array_key_exists($level, $this->levelnumbers) === true) {
|
||||||
|
$this->loglevel = $level;
|
||||||
|
$this->writeLog("INFO", "Loglevel set to {$level}");
|
||||||
|
} else {
|
||||||
|
$this->writeLog("WARN", "{$level} is not a valid loglevel.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function logMsg(string $label, string $msg) {
|
||||||
|
$msglevel = $this->levelnumbers[$label];
|
||||||
|
$loglevel = $this->levelnumbers[$this->loglevel];
|
||||||
|
if ($loglevel >= $msglevel) {
|
||||||
|
$this->writeLog($label, $msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function writeLog(string $label, string $msg) {
|
||||||
|
$app = $this->app;
|
||||||
|
$file = $this->logfile;
|
||||||
|
error_log(date("[Y-m-d H:i:s]")." [".$label."] [".$app."] ".$msg."\n", 3, $file);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
?>
|
113
lib/register.php
Normal file
113
lib/register.php
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* file: lib/register.php
|
||||||
|
* date: 28.08.2021
|
||||||
|
* user: bernd@nr18.space
|
||||||
|
* desc: Klasse Registrator - validiert einen Token und registriert einen
|
||||||
|
* User am synapse-matrix Server. Achtung: z.Z. noch keine Registrierung!
|
||||||
|
*/
|
||||||
|
|
||||||
|
require("base.php");
|
||||||
|
|
||||||
|
|
||||||
|
class Registrator extends BaseClass {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Die Klasse zum Aktivieren des Matrix Accounts. Erbt aus dem
|
||||||
|
* Konstruktor von BaseClass ein Konfigurations- und ein Datenbakobjekt
|
||||||
|
* ($this->config, $this->db), die Funktion generateToken(), sowie die
|
||||||
|
* Variable $this->token.
|
||||||
|
*/
|
||||||
|
|
||||||
|
private $dataSet = [];
|
||||||
|
|
||||||
|
public function registerUser(&$message): bool {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hauptfunktion der Klasse Registrator - steuert die Validierung und
|
||||||
|
* das Registrieren der Anfrage.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!isset($this->db)) {
|
||||||
|
$this->log->e("There is no database");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->log->d("Validation started for token: {$_GET['token']}");
|
||||||
|
if ($this->checkToken() === true) {
|
||||||
|
if ($this->generateToken($token, 32) === true) {
|
||||||
|
if ($this->registerMXID() === true) {
|
||||||
|
$message = "Your temporary password is {$tmp_passwd}. Please
|
||||||
|
immediately change your password!";
|
||||||
|
if ($this->removeToken() === true) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function checkToken(): bool {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Läßt in der Tabelle requests schauen, ob es $_GET['token'] gibt.
|
||||||
|
* Speichert das zurückgegebene Array in der Variable $dataSet. Gibt
|
||||||
|
* die Datenbank eine Exception zurück oder ist das Array leer, gibt
|
||||||
|
* sie False, andernfals True zurück.
|
||||||
|
*/
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->dataSet = $this->db->getToken();
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$this->log->e("Error: {$e->getMessage()}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$count = count($this->dataSet);
|
||||||
|
if ($count === 0) {
|
||||||
|
$this->log->d("Token {$_GET['token']} not found in database");
|
||||||
|
} else if ($count > 1) {
|
||||||
|
$this->log->e("Error: More than one token found");
|
||||||
|
} else {
|
||||||
|
$this->log->d("Token found for nick: {$this->dataSet[1]}");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function registerMXID(string $tmp_passwd): bool {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registriert den Nutzer am Matrixserver. Dazu wird ein zufälliger
|
||||||
|
* String erzeugt und zusammen mit dem Nick ein CLI Tool aus dem Paket
|
||||||
|
* Paket von matrix-synapse aufgerufen.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// $cmd = "register_new_matrix_user -u {$this->dataSet[1]} -p {$tmp_pass}";
|
||||||
|
// $response = system($cmd);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function removeToken(): bool {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Läßt den Request aus der tabelle requests entfernen.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$id = $this->dataSet[0];
|
||||||
|
$nick = $this->dataSet[1];
|
||||||
|
$token = $this->dataSet[2];
|
||||||
|
try {
|
||||||
|
$response = $this->db->deleteToken($id);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
$this->log->e("Error: {$e->getMessage()}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
197
lib/request.php
Normal file
197
lib/request.php
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* file: lib/request.php
|
||||||
|
* date: 28.02.2021
|
||||||
|
* user: bernd@nr18.space
|
||||||
|
* desc:
|
||||||
|
*/
|
||||||
|
|
||||||
|
require("base.php");
|
||||||
|
require("static/mail.php");
|
||||||
|
|
||||||
|
|
||||||
|
class Request extends BaseClass {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Klasse zur Bearbeitung einer Anfrage nach einem Matrix Accuont. Erbt
|
||||||
|
* aus der Klasse BaseClass ein Konfigurations- und ein Datenbankobjekt
|
||||||
|
* ($this->config, $this->db), die Funktion generateToken() und sowie
|
||||||
|
* die Variable $this-token.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public function checkRequest(string &$message): bool {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hauptfunktion der Klasse Request - steuert alle Prüfungen, das
|
||||||
|
* Speichern des Requests und das Versenden der Email. Gibt True
|
||||||
|
* oder False zurück und setzt die Variable "message", welche auf
|
||||||
|
* der Webseite ausgegeben wird.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!isset($this->db)) {
|
||||||
|
$this->log->e("There is no database");
|
||||||
|
$message = "Something goes wrong";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->log->d("Request started for nick: {$_POST['login']}");
|
||||||
|
if (false === $this->checkCaptcha()) {
|
||||||
|
$message = "Captcha invalid";
|
||||||
|
return false;
|
||||||
|
} else if (false === $this->checkEmail()) {
|
||||||
|
$message = "Email invalid";
|
||||||
|
return false;
|
||||||
|
} else if (false === $this->checkMXID($this->config->getMxDomain())) {
|
||||||
|
$message = "User ID invalid";
|
||||||
|
return false;
|
||||||
|
} else if (false === $this->checkUser()) {
|
||||||
|
$message = "User Id is already taken";
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if ($this->generateToken($token, 16) === true) {
|
||||||
|
if ($this->saveRequest() === true) {
|
||||||
|
if ($this->sendVerificationMail() === true) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function saveRequest(): bool {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Veranlaßt die Speicherung der Anfrage in der Tabelle requests.
|
||||||
|
* TODO: Exceptions behandeln.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$response = $this->db->saveRequest($this->token);
|
||||||
|
if (!$response) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function sendVerificationMail(): bool {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verschickt die Mail mit dem Verifizierungslink.
|
||||||
|
* TODO: Reicht filter_input()? Was kann hier passieren?
|
||||||
|
*/
|
||||||
|
|
||||||
|
$mailTo = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL);
|
||||||
|
$mxdomain = $this->config->getMxDomain();
|
||||||
|
$baseurl = $this->config->getBaseURL();
|
||||||
|
$validator = $this->config->getValidator();
|
||||||
|
$mailFrom = $this->config->getMailFrom();
|
||||||
|
$mailSubject = $this->config->getMailSubject();
|
||||||
|
$mailClosure = $this->config->getMailClosure();
|
||||||
|
|
||||||
|
$link = $baseurl . $validator . $this->token . "\r\n\r\n";
|
||||||
|
$mailbody = MAILTEXT1 . $mxdomain . MAILTEXT2 . "\r\n\r\n" . $link . $mailClosure;
|
||||||
|
if (mail($mailTo, $mailSubject, $mailbody, $mailFrom))
|
||||||
|
{
|
||||||
|
$this->log->i("Validationmail successfull send");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
$this->log->e("Sending validation mail failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function checkCaptcha(): bool {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prüfen, ob das Captcha die korrekte Hausnummer abbildet.
|
||||||
|
* Filter_input gibt im Erfolgsfall einen Integer zurück.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$this->log->d("Checking captcha");
|
||||||
|
$captcha = filter_input(INPUT_POST, 'captcha', FILTER_VALIDATE_INT);
|
||||||
|
if ($captcha == 26) {
|
||||||
|
$this->log->d("Captcha valid");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
$this->log->e("Invalid captcha");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function checkEmail(): bool {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prüfen, ob die Emailadresse schematisch gültig ist. filter_input
|
||||||
|
* gibt im Erfolgsfall den Wert, im Fehlerfall false oder null, wenn
|
||||||
|
* die Variable nicht gestzt ist, zurück. Letzteres wird beim
|
||||||
|
* vorangehenden Test checkForms geprüft und kann daher nicht
|
||||||
|
* auftreten.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$this->log->d("Checking email schema");
|
||||||
|
if (filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL)) {
|
||||||
|
$this->log->d("Email schema is valid");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
$this->log->e("Email schema invalid");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function checkMXID(string $mxid): bool {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prüft, ob der gewünschte localpart nur Zeichen enthält, die von
|
||||||
|
* der Matrix-Spezifikation erlaubt sind. Die Spezifikation erlaubt
|
||||||
|
* nur Kleinbuchstaben, Ziffern, Minus, Punkt, Gleichheitszeichen,
|
||||||
|
* Unterstrich und Schrägstrich. Geprüft wird auch, ob die Länge des
|
||||||
|
* gewünschten localpart zusammen mit dem domainpart sowie dem @ und
|
||||||
|
* : die Länge von 255 Zeichen nicht überschreiten.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$this->log->d("Check MXID localpart");
|
||||||
|
$str_array = str_split($_POST['login']);
|
||||||
|
$max_length = 255 - (mb_strlen($mxid) + 2);
|
||||||
|
$specials = array('-', '.', '=', '_', '/');
|
||||||
|
$numbers = array('0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
|
||||||
|
$possibles = array_merge(range('a', 'z'), $numbers, $specials);
|
||||||
|
|
||||||
|
foreach ($str_array as $item) {
|
||||||
|
if (in_array($item, $possibles, true) === false) {
|
||||||
|
$this->log->e("MXID localpart: invalid character: {$item}");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mb_strlen($_POST['login']) > $max_length) {
|
||||||
|
$this->log->e("MXID localpart: too long");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$this->log->d("MXID localpart is valid");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function checkUser(): bool {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prüft, ob der gewünschte Nutzernamen nicht bereits vergeben ist.
|
||||||
|
* Dazu wird in den Datenbanktabellen users (bereits registrierte
|
||||||
|
* benutzer) und requests (bereits beantragte benutzer) nach einer
|
||||||
|
* eventuellen Übereinstimmung geschaut. Eine spezielle Behandlung
|
||||||
|
* des Suchstrings ist nach meiner Meinung hier nicht nötig, da der
|
||||||
|
* String vorher auf Matrix-konforme Zeichen getestet wurde und die
|
||||||
|
* Datenbankfuntionen prepared Statements verwendet.
|
||||||
|
*/
|
||||||
|
|
||||||
|
$this->log->d("Checking if username is available");
|
||||||
|
$nick = $_POST['login'];
|
||||||
|
if ($this->db->UserExistsInRequests($nick) === true) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($this->db->UserExistsInUsers($nick) === true) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
BIN
static/favicon.ico
Normal file
BIN
static/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 318 B |
BIN
static/logo.png
Normal file
BIN
static/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
20
static/mail.php
Normal file
20
static/mail.php
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* file: static/mail.php
|
||||||
|
* date: 28.02.2021
|
||||||
|
* user: bernd@nr18.space
|
||||||
|
* desc:
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
const MAILTEXT1 = <<<END
|
||||||
|
Wir freuen uns, daß Sie sich für einen Account bei
|
||||||
|
END;
|
||||||
|
|
||||||
|
const MAILTEXT2 = <<<END
|
||||||
|
entschieden haben. Rufen Sie zur Bestätigung den untenstehenden Link
|
||||||
|
im Browser auf.
|
||||||
|
END;
|
||||||
|
|
||||||
|
?>
|
89
static/register.css
Normal file
89
static/register.css
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
file: register.css
|
||||||
|
date: 04.01.2021
|
||||||
|
author: bernd@nr18.space
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
color: #333;
|
||||||
|
background-color: white;
|
||||||
|
font-family: DejaVu Sans;
|
||||||
|
font-size: 100%;
|
||||||
|
line-height: 1.4;
|
||||||
|
height: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
#wrapper {
|
||||||
|
min-height: 100%;
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 1.5em 3%;
|
||||||
|
}
|
||||||
|
|
||||||
|
main {
|
||||||
|
padding-top: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.success {
|
||||||
|
display: block;
|
||||||
|
padding: 1em;
|
||||||
|
border-radius: 0.5em;
|
||||||
|
background-color: #82c385;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
display: block;
|
||||||
|
padding: 1em;
|
||||||
|
border-radius: 0.5em;
|
||||||
|
background-color: #db6884;
|
||||||
|
}
|
||||||
|
|
||||||
|
section#formular {
|
||||||
|
margin: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldset {
|
||||||
|
max-width: 500px;
|
||||||
|
margin: auto;
|
||||||
|
padding: 2em;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formrow {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
margin-bottom: 1.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
label.formlabel {
|
||||||
|
display: block;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.forminput {
|
||||||
|
width: 60%;
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#captchaframe {
|
||||||
|
margin-top: 1em;
|
||||||
|
border: 1px solid #333;
|
||||||
|
border-radius: 2px;
|
||||||
|
padding: 1em;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
input#captchainput {
|
||||||
|
width: 30%;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=submit] {
|
||||||
|
width: max-content;
|
||||||
|
}
|
||||||
|
|
37
static/web.php
Normal file
37
static/web.php
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* file: static/web.php
|
||||||
|
* date: 06.01.2021
|
||||||
|
* author: bernd@nr18.space
|
||||||
|
* desc: Definition einiger Konstanten für die Webseiten
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// HTML
|
||||||
|
const HTML_META = <<<END
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="robots" content="noindex/nofollow" />
|
||||||
|
<link rel="stylesheet" href="./static/register.css" type="text/css" />
|
||||||
|
<link rel="shortcut icon" href="./static/favicon.ico" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
END;
|
||||||
|
const HTML_HEADER = <<<END
|
||||||
|
<header>
|
||||||
|
<h1>
|
||||||
|
<img src="./static/logo.png" alt="Logo Krautspace" width="281" height="58" />
|
||||||
|
<span id="subtitle">Hackspace Jena e.V.</span>
|
||||||
|
</h1>
|
||||||
|
</header>
|
||||||
|
END;
|
||||||
|
const HTML_FOOTER = <<<END
|
||||||
|
<footer>
|
||||||
|
<p>Krautspace Jena e.V. | 07743 Jena | Krautgasse 26</p>
|
||||||
|
<p>
|
||||||
|
<a href="">Impressum</a>
|
||||||
|
<a href="">Datenschutz</a>
|
||||||
|
</p>
|
||||||
|
</footer>
|
||||||
|
END;
|
||||||
|
|
||||||
|
?>
|
69
validation.php
Normal file
69
validation.php
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
ini_set('display_errors', true);
|
||||||
|
|
||||||
|
require("static/web.php");
|
||||||
|
require("lib/register.php");
|
||||||
|
|
||||||
|
|
||||||
|
$class = "";
|
||||||
|
$title = "";
|
||||||
|
$message = "";
|
||||||
|
$registered = false;
|
||||||
|
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] === 'GET') {
|
||||||
|
$token = $_GET['token'] ?? '';
|
||||||
|
if ($token) {
|
||||||
|
$registrator = new Registrator();
|
||||||
|
$registered = $registrator->registerUser($message);
|
||||||
|
if ($registered) {
|
||||||
|
$class = "success";
|
||||||
|
$title = "Congratulations";
|
||||||
|
} else {
|
||||||
|
$class = "error";
|
||||||
|
$title = "Sorry";
|
||||||
|
$message = "Failed to register your account.";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$class = "error";
|
||||||
|
$title = "Sorry";
|
||||||
|
$message = "Something goes wrong.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html lang="de">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>matrix.kraut.space - register</title>
|
||||||
|
<?php echo HTML_META ?>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="wrapper">
|
||||||
|
|
||||||
|
<?php echo HTML_HEADER ?>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
|
||||||
|
<div class="<?php echo $class ?>">
|
||||||
|
<?php if ($title): ?>
|
||||||
|
<h3><?php echo $title ?></h3>
|
||||||
|
<?php endif ?>
|
||||||
|
|
||||||
|
<?php if ($message): ?>
|
||||||
|
<p><?php echo $message ?></p>
|
||||||
|
<?php endif ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<?php echo HTML_FOOTER ?>
|
||||||
|
|
||||||
|
</div> <!-- ende div wrapper -->
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in a new issue