7 Commits

Author SHA1 Message Date
5eeaa11c0c fix in config.sample 2018-04-16 15:17:58 +02:00
f74a2f74e0 fix path to config.php in mail.l.php 2018-04-16 15:15:32 +02:00
53ccd1c2b3 hopefully complete operationMode=synapse 2018-04-16 15:06:44 +02:00
6d19d869c8 Merge branch 'master' into feature_multimodeOperation 2018-04-16 14:52:09 +02:00
6143a23dd8 autoformat to reduce merge conflicts 2018-04-16 14:29:40 +02:00
f808615f22 start implementing multiple modes for operation
- synapse: Only trigger register calls and do not store anything for longterm
- local: Provide an identity store and register to the own backend
2018-04-15 21:36:24 +02:00
ffce2fc28b run some autoformat 2018-04-04 20:43:24 +02:00
18 changed files with 196 additions and 307 deletions

View File

@@ -103,15 +103,7 @@ class MatrixConnection {
curl_setopt($handle, CURLOPT_HTTPHEADER, array("Content-Type: application/json"));
curl_setopt($handle, CURLOPT_POSTFIELDS, json_encode($data));
try {
return $this->exec_curl_request($handle);
} catch (Exception $e) {
if (strcmp("AUTHENTICATION_FAILED", $e->getMessage()) == 0) {
throw new Exception("WRONG_REGISTRATION_SHARED_SECRET");
} else {
throw $e;
}
}
}
function exec_curl_request($handle) {
@@ -134,7 +126,7 @@ class MatrixConnection {
$response = json_decode($response, true);
error_log("Request has failed with error {$response['error']}\n");
if ($http_code == 401) {
throw new Exception("AUTHENTICATION_FAILED");
throw new Exception('Invalid access token provided');
}
} else {
$response = json_decode($response, true);

View File

@@ -1,45 +1,28 @@
# matrix-register-bot
![state: alpha](https://img.shields.io/badge/state-alpha-yellowgreen.svg)
[![#matrix-register-bot:msg-net.de](https://img.shields.io/badge/matrix-%23matrix--register--bot%3Amsg--net.de-brightgreen.svg)](https://matrix.to/#/#matrix-register-bot:msg-net.de)
This bot provides a two-step-registration for matrix ([synapse](https://github.com/matrix-org/synapse)).
This bot provides a two-step-registration for matrix.
This is done in several steps:
- potential new user registers on a bot-provided site
- user has to verify its mail address
- potential new user registers on a bot-provided side
- bot sends a message to predefined room with a registration notification.
- users in that room now can approve or decline the registration.
- When approved
- the bot creates short time credentials
- the bot creates credentials
- sends them to the user
- stores them encrypted in own databas or uses that as initial password for registration
- stores them encrypted in own database
- provides that credentials to [matrix-synapse-rest-auth](https://github.com/kamax-io/matrix-synapse-rest-auth#integrate) which has to be configured to query login.php
To configure synapse so that the users can login that were created via this bot you can either
- set `operationMode=synapse` so the bot uses the register api to push the new users to synapse or
- integrate it via [matrix-synapse-rest-auth](https://github.com/kamax-io/matrix-synapse-rest-auth#integrate) by configuring your system to point at `internal/login.php`.
When using `operationMode=local` you can have the following benefits (some require [mxisd](https://github.com/kamax-io/mxisd/blob/master/docs/stores/rest.md))
- Automatically set the display name based on first and last name on first login
- Use the 3PID lookup for other users (only email)
- Search for users that you have not seen yet
## Requirements
- Working PHP environment with
- database connection provider \[one of sqlite, mysql, postgres\]
- curl extension to notify admins and register users (in `operationMode=synapse`)
- mail capability to interact with the users (Verification, Approval (+ initial password), Notifications)
- matrix-synapse-rest-auth when using `operationMode=local`
- some PHP capable webserver which makes the folder `public` accessible to the public and propably `internal` for server-internal access
2nd step: Implement the other apis to integrade [mxisd](https://github.com/kamax-io/mxisd/blob/master/docs/backends/rest.md)
This bot takes care for user accounts. So it stores the credentials itself and provides ways to access them via matrix-synapse-rest-auth or mxisd.
## How to install
- Copy `config.sample.php` to `config.php` and configure the bot as you can find there
- Configure your webserver to have the folder `public` accessible via web.
The folder `internal` contains files that only provide API access. They can be accessed by mxisd or matrix-synapse-rest-auth
- Configure your webserver to publish the folder `public`.
The folder `internal` contains files that can be accessed by mxisd or matrix-synapse-rest-auth or else via a reverse proxy
- To integrate with [matrix-synapse-rest-auth](https://github.com/kamax-io/matrix-synapse-rest-auth):
- `/_matrix-internal/identity/v1/check_credentials` should map to `internal/login.php`
- To integrate with [mxisd](https://github.com/kamax-io/mxisd): Have a look at [the docs of mxisd](https://github.com/kamax-io/mxisd/blob/master/docs/stores/rest.md) and apply as follows:
- To integrate with [mxisd](https://github.com/kamax-io/mxisd): Have a look at [the docs](https://github.com/kamax-io/mxisd/blob/master/docs/backends/rest.md) and apply as follows:
| Key | file which handles that | Description |
@@ -50,24 +33,15 @@ When using `operationMode=local` you can have the following benefits (some requi
| rest.endpoints.identity.bulk | internal/identity_bulk.php | Endpoint to query a list of 3PID |
## Further notes:
## Implement usage of additional features:
### Use the ChangePasswortInterceptor:
### Security: Passwords from registration form are stored in clear text
Currently the passwords which are typed in while capturing the register request are stored in clear text.
The bot needs to access them to trigger a register request with correct credentials.
It is currently strongly recommended to set `"getPasswordOnRegistration" => false` in your config!
This leads to autocreating passwords which will then be send to the users directly without storing it.
### Use the ChangePasswortInterceptor (if `operationMode=local`)
To allow users to change their pasword you need a reverse proxy which maps `/_matrix/client/r0/account/password` to `internal/intercept_change_password.php`.
You need a reverse proxy which maps `/_matrix/client/r0/account/password` to `internal/intercept_change_password.php`.
Here is an example for nginx:
```
location /_matrix/client/r0/account/password {
proxy_pass http://localhost/mxbot/internal/intercept_change_password.php;
proxy_set_header X-Forwarded-For $remote_addr;
}
```
### The bot postpones some actions
There is a cron.php which implements retries and database cleanups (e.g. to remove a username claim)
For this run cron.php regularly with your system of choice.

View File

@@ -14,18 +14,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require_once(__DIR__ . "/config.php");
require_once(__DIR__ . "/language.php");
require_once(__DIR__ . "/mail_templates.php");
require_once(__DIR__ . "/database.php");
require_once("config.php");
require_once("mail_templates.php");
require_once("database.php");
$sql = "SELECT id, first_name, last_name, username, password, email,"
. " state, note, verify_token, admin_token "
. "FROM registrations "
$sql = "SELECT id, first_name, last_name, username, email, state, note, verify_token, admin_token FROM registrations "
. "WHERE state = " . RegisterState::PendingEmailSend
. " OR state = " . RegisterState::PendingAdminSend
. " OR state = " . RegisterState::PendingRegistration
. " OR state = " . RegisterState::PendingSendRegistrationMail . ";";
. " OR state = " . RegisterState::PendingSendRegistrationMail
. " OR state = " . RegisterState::RegistrationDeclined
. " OR state = " . RegisterState::AllDone . ";";
foreach ($mx_db->query($sql) as $row) {
$first_name = $row["first_name"];
$last_name = $row["last_name"];
@@ -47,22 +46,16 @@ foreach ($mx_db->query($sql) as $row) {
}
break;
case RegisterState::PendingAdminSend:
require_once(__DIR__ . "/MatrixConnection.php");
require_once("MatrixConnection.php");
$adminUrl = $config["webroot"] . "/verify_admin.php?t=" . $row["admin_token"];
$mxConn = new MatrixConnection($config["homeserver"], $config["access_token"]);
$mxMsg = new MatrixMessage();
$mxMsg->set_body(strtr($language["MSG_USER_WANTS_REGISTER"], [
"@name" => (strlen($first_name . $last_name) > 0 ? $first_name . " " . $last_name : $username),
"@note" => $note,
"@adminUrl" => $adminUrl
]));
if (isset($language["MSG_USER_WANTS_REGISTER_FORMATTED"])) {
$mxMsg->set_formatted_body(strtr($language["MSG_USER_WANTS_REGISTER_FORMATTED"], [
"@name" => (strlen($first_name . $last_name) > 0 ? $first_name . " " . $last_name : $username),
"@note" => $note,
"@adminUrl" => $adminUrl
]));
}
$mxMsg->set_body($first_name . ' ' . $last_name . " möchte sich registrieren und hat folgende Notiz hinterlassen:\r\n"
. $row["note"] . "\r\n"
. "Zum Bearbeiten hier klicken:\r\n" . $adminUrl);
$mxMsg->set_formatted_body($first_name . ' ' . $last_name . " möchte sich registrieren und hat folgende Notiz hinterlassen:<br />"
. $row["note"] . "<br />"
. "Zum Bearbeiten <a href=\"" . $adminUrl . "\">hier</a> klicken");
$mxMsg->set_type("m.text");
$response = $mxConn->send($config["register_room"], $mxMsg);
@@ -76,29 +69,11 @@ foreach ($mx_db->query($sql) as $row) {
break;
case RegisterState::PendingRegistration:
// Registration got accepted but registration failed
switch ($config["operationMode"]) {
case "synapse":
// register with registration_shared_secret
// generate a password with 10 characters
$password = bin2hex(openssl_random_pseudo_bytes(5));
$res = $mxConn->register($row["username"], $password, $config["registration_shared_secret"]);
if (!$res) {
// something went wrong while registering
$password = NULL;
}
break;
case "local":
// register by adding a user to the local database
$password = $mx_db->addUser($row["first_name"], $row["last_name"], $row["username"], $row["password"], $row["email"]);
break;
default:
throw new Exception("Unknown operationMode");
}
$password = $mx_db->addUser($row["first_name"], $row["last_name"], $row["username"], $row["email"]);
if ($password != NULL) {
// send registration_success
$res = send_mail_registration_success(
$config["homeserver"], strlen($first_name . $last_name) > 0 ? $first_name . " " . $last_name : $username, $email, $username, $password, $config["howToURL"]
);
$res = send_mail_registration_success($config["homeserver"], $first_name . " " . $last_name, $email, $username, $password, $config["howToURL"]);
if ($res) {
$mx_db->setRegistrationStateById(RegisterState::AllDone, $row["id"]);
} else {
@@ -108,9 +83,7 @@ foreach ($mx_db->query($sql) as $row) {
send_mail_registration_allowed_but_failed($config["homeserver"], $first_name . " " . $last_name, $email);
$mxMsg = new MatrixMessage();
$mxMsg->set_type("m.text");
$mxMsg->set_body(strtr($language["REGISTRATION_FAILED_FOR"], [
"@name" => strlen($first_name . $last_name) > 0 ? $first_name . " " . $last_name : $username,
]));
$mxMsg->set_body("Fehler beim Registrieren von " . $first_name . " " . $last_name . ".");
$mxConn->send($config["register_room"], $mxMsg);
throw new Exception($language["REGISTRATION_FAILED"]);
}
@@ -118,29 +91,14 @@ foreach ($mx_db->query($sql) as $row) {
case RegisterState::PendingSendRegistrationMail:
print ("Error: Unhandled state: PendingSendRegistrationMail for " . $first_name . " " . $last_name . " (" . $username . ")\n");
break;
case RegisterState::RegistrationDeclined:
case RegisterState::AllDone:
// do reqular cleanup
break;
}
} catch (Exception $e) {
print("Error while handling cron for " . $first_name . " " . $last_name . " (" . $username . ")\n");
print($e->getMessage());
}
}
try {
//cleanup: all finished entries older than one month
$timestamp = date('Y-m-d H:m:s', strtotime("-1 month"));
$mx_db->query("DELETE FROM registrations "
. "WHERE request_date < '$timestamp'"
. " AND (state = " . RegisterState::RegistrationDeclined
. " OR state = " . RegisterState::AllDone . " );"
);
//cleanup: all entries which are pending email registration older than two days
$timestamp = date('Y-m-d H:m:s', strtotime("-2 days"));
$mx_db->query("DELETE FROM registrations "
. "WHERE request_date < '$timestamp'"
. " AND state = " . RegisterState::PendingEmailVerify . ";"
);
} catch (Exception $e) {
print("Error while database cleanup\n");
print($e->getMessage());
}
?>

View File

@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require_once(__DIR__ . "/config.php");
require_once("config.php");
if (!isset($config["databaseURI"])) {
throw new Exception("malformed configuration: databaseURI not defined");
}
@@ -78,7 +78,7 @@ class mxDatabase {
first_name TEXT,
last_name TEXT,
username TEXT,
password TEXT DEFAULT '',
password_hash TEXT DEFAULT '',
note TEXT,
email TEXT,
verify_token TEXT,
@@ -98,7 +98,7 @@ class mxDatabase {
)");
// make sure the bot is allowed to login
if (!$this->userRegistered("register_bot")) {
$password = $this->addUser("Register", "Bot", "register_bot", NULL, $config["register_email"]);
$password = $this->addUser("Register", "Bot", "register_bot", $config["register_email"]);
$config["register_password"] = $password;
$myfile = fopen(dirname(__FILE__) . "/config.json", "w");
fwrite($myfile, json_encode($config, JSON_PRETTY_PRINT));
@@ -184,7 +184,7 @@ class mxDatabase {
*
* @return ["verify_token"]
*/
function addRegistration($first_name, $last_name, $username, $password, $note, $email) {
function addRegistration($first_name, $last_name, $username, $note, $email) {
if ($this->userPendingRegistrations($username)) {
throw new Exception("USERNAME_PENDING_REGISTRATION");
}
@@ -196,9 +196,8 @@ class mxDatabase {
$admin_token = bin2hex(random_bytes(16));
$this->db->exec("INSERT INTO registrations
(first_name, last_name, username, password, note, email, verify_token, admin_token)
VALUES ('" . $first_name . "','" . $last_name . "','"
. $username . "','" . $password . "','" . $note . "','"
(first_name, last_name, username, note, email, verify_token, admin_token)
VALUES ('" . $first_name . "','" . $last_name . "','" . $username . "','" . $note . "','"
. $email . "','" . $verify_token . "','" . $admin_token . "')");
return [
@@ -218,7 +217,7 @@ class mxDatabase {
$res = $this->db->query($sql);
if ($res->fetchColumn() > 0) {
$sql = "SELECT first_name, last_name, username, password, note, email FROM registrations"
$sql = "SELECT first_name, last_name, username, note, email FROM registrations"
. " WHERE admin_token = '" . $admin_token . "'"
. " AND state = " . RegisterState::PendingAdminVerify
. " LIMIT 1;";
@@ -283,16 +282,14 @@ class mxDatabase {
* NULL when failed
*
*/
function addUser($first_name, $last_name, $username, $password, $email) {
function addUser($first_name, $last_name, $username, $email) {
// check if user already exists and abort in that case
if ($this->userRegistered($username)) {
return NULL;
}
if ($password == NULL) {
// generate a password with 10 characters
$password = bin2hex(openssl_random_pseudo_bytes(5));
}
$password_hash = password_hash($password, PASSWORD_BCRYPT, ["cost" => 12]);
$sql = "INSERT INTO logins (first_name, last_name, localpart, password_hash, email) VALUES "

View File

@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require_once(__DIR__ . "/../database.php");
require_once("../database.php");
$response = [
"limited" => false,
"result" => [],

View File

@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require_once(__DIR__ . "/../database.php");
require_once("../database.php");
$response = [
"lookup" => []
];

View File

@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require_once(__DIR__ . "/../database.php");
require_once("../database.php");
$response = new stdClass;
try {
$inputJSON = file_get_contents('php://input');

View File

@@ -44,14 +44,14 @@ try {
throw new Exception('"new_password" is not defined');
}
require_once(__DIR__ . "/../helpers.php");
require_once("../helpers.php");
$localpart = stripLocalpart($input["auth"]["user"]);
if (empty($localpart)) {
throw new Exception("localpart cannot be identified");
}
require_once(__DIR__ . "/../database.php");
require_once("../database.php");
if (!$mx_db->updatePassword(
$localpart, $input["auth"]["password"], $input["new_password"]
)) {

View File

@@ -20,7 +20,7 @@ $response = [
]
];
require_once(__DIR__ . "/../database.php");
require_once("../database.php");
abstract class LoginRequester {
@@ -56,7 +56,7 @@ try {
// prefer the localpart attribute of mxisd. But in case of matrix-synapse-rest-auth
// we have to parse it on our own
if (empty($localpart)) {
require_once(__DIR__ . "/../helpers.php");
require_once("../helpers.php");
$localpart = stripLocalpart($mxid);
}

View File

@@ -31,13 +31,10 @@ $language = array(
"UNKNOWN_SESSION" => "Sitzungstoken nicht vorhanden oder ungültig.",
"UNKNOWN_USERNAME" => "Nutzername fehlt",
"UNKNOWN_TOKEN" => "Token ist unbekannt",
"AUTHENTICATION_FAILED" => "Authentifizierung fehlgeschlagen",
"WRONG_REGISTRATION_SHARED_SECRET" => "registration_shared_secret fehlerhaft",
"USERNAME_INVALID" => "Nutzername muss aus 3 bis 20 Kleinbuchstaben bestehen",
"USERNAME_LENGTH_INVALID" => "Entweder mehr als 20 oder weniger als 3 Zeichen für den Nutzernamen verwendet",
"USERNAME_NOT_ALNUM" => "Nutzername ist nicht alphanumerisch",
"USERNAME_PENDING_REGISTRATION" => "Dieser Nutzername wurde bereits zur Registrierung vorgemerkt. Versuche es später noch einmal oder wähle einen anderen Nutzernamen",
"USERNAME_REGISTERED" => "Dieser Nutzername wurde bereits registriert. Bitte wähle einen anderen Nutzernamen",
"PASSWORD_NOT_PROVIDED" => "Ein oder beide Passwörter wurden nicht gesetzt",
"PASSWORD_NOT_MATCH" => "Passwörter stimmen nicht überein",
"NOTE_LENGTH_EXEEDED" => "Notiz ist länger als die erlaubten 50 Zeichen",
"PLACEHOLDER_NOTE_ABOUT_YOURSELF" => "Notiz zu dir (max. 50 Zeichen)",

View File

@@ -1,5 +1,4 @@
<?php
/**
* Copyright 2018 Matthias Kesler
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -31,13 +30,10 @@ $language = array(
"UNKNOWN_SESSION" => "Session token not found of invalid.",
"UNKNOWN_USERNAME" => "username unknown",
"UNKNOWN_TOKEN" => "Token is unknown",
"AUTHENTICATION_FAILED" => "Authentication failed",
"WRONG_REGISTRATION_SHARED_SECRET" => "wrong registration_shared_secret",
"USERNAME_INVALID" => "Username has to consist of 3 to 20 small letters",
"USERNAME_LENGTH_INVALID" => "Username cpnsists pf more than 20 or less than 3 characters",
"USERNAME_NOT_ALNUM" => "Username is not alphanumeric",
"USERNAME_PENDING_REGISTRATION" => "This username is locked for registration. Try again later or try again with a different username",
"USERNAME_REGISTERED" => "This username is already registered. Please try again with another username",
"PASSWORD_NOT_PROVIDED" => "One or both passwords are not provided",
"PASSWORD_NOT_MATCH" => "passwords do not match",
"NOTE_LENGTH_EXEEDED" => "Note consists of more than 50 characters",
"PLACEHOLDER_NOTE_ABOUT_YOURSELF" => "Note about yourself (max. 50 characters)",
@@ -57,8 +53,7 @@ $language = array(
"ADMIN_REGISTER_ACCEPTED_BODY" => "The registration request got accepted. The user got notified per email.",
"ADMIN_REGISTER_DECLINED_BODY" => "The registration request got declined. The user got notified per email.",
"JUMP_TO_HOMEPAGE" => "To homepage",
"TOPIC_PLEASE_REGISTER" => "Please register for @homeserver",
"TOPIC_PLEASE_REGISTER_NOTE" => "2-Step-Registration",
"TOPIC_PLEASE_REGISTER" => "Please register for @homeserver<small>2-Step-Registration</small>",
"NOTE_FOR_REGISTRATION" => "@homeserver is a closed chat network where every user has to be confirmed.<br />
You will get an email once sb. approved your registration. An initial password will be send to you afterwards.
Please leave a note about yourself (that will only be shown to the admins).<br />

View File

@@ -1,5 +1,4 @@
<?php
/**
* Copyright 2018 Matthias Kesler
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,7 +14,7 @@
* limitations under the License.
*/
function send_mail($receiver, $subject, $body) {
include(__DIR__ . "/../config.php");
include("../config.php");
$headers = "From: " . $config["register_email"] . "\r\n"
. "Content-Type: text/plain;charset=utf-8";
return mail($receiver, $subject, $body, $headers);
@@ -69,6 +68,7 @@ Wir melden uns, wenn die Registrierung erfolgreich war.
Das Administratoren-Team von " . $homeserver;
return send_mail($receiver, $subject, $body);
}
function send_mail_registration_success($homeserver, $user, $receiver, $username, $password, $howToURL) {
@@ -79,7 +79,7 @@ Deine Registrierungsanfrage wurde durch die Administratoren bestätigt.
Zum Anmelden kannst du folgende Zugangsdaten verwenden:
Nutzername: $username
Passwort: " . (empty($password) ? "wie selbst gesetzt": $password) . "
Passwort: $password
Hinweis: Das Passwort kannst du aktuell über die App selbst ändern. Auch wenn das Passwort nirgends
im Klartext gespeichert wird, kann jemand Zugriff auf diese Mail erlangen und so den Zugriff bekommen.
@@ -101,8 +101,8 @@ Bei Fragen findest du nach der Anmeldung ein paar Räume in denen du sie stellen
Das Administratoren-Team von " . $homeserver;
return send_mail($receiver, $subject, $body);
}
}
function send_mail_registration_decline($homeserver, $user, $receiver, $reason) {
$subject = "Registrierung auf $homeserver abgelehnt";
$body = "Guten Tag " . $user . ",
@@ -121,5 +121,4 @@ Wir hoffen, dass du dies akzeptieren kannst.
Das Administratoren-Team von " . $homeserver;
return send_mail($receiver, $subject, $body );
}
?>

View File

@@ -1,5 +1,4 @@
<?php
/**
* Copyright 2018 Matthias Kesler
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,7 +14,7 @@
* limitations under the License.
*/
function send_mail($receiver, $subject, $body) {
include(__DIR__ . "/../config.php");
include("../config.php");
$headers = "From: " . $config["register_email"] . "\r\n"
. "Content-Type: text/plain;charset=utf-8";
return mail($receiver, $subject, $body, $headers);
@@ -68,6 +67,7 @@ You will get another email with initial credentials once the registration got ha
The admin team of " . $homeserver;
return send_mail($receiver, $subject, $body);
}
function send_mail_registration_success($homeserver, $user, $receiver, $username, $password, $howToURL) {
@@ -78,7 +78,7 @@ Your registration request got verified by the admin team.
To log in you can use the following credentials::
Username: $username
Passwort: " . (empty($password) ? "as self-set": $password) . "
Password: $password
Important: Please change your password as soon as possible after your first login.
The password is not stored in clear text on the server but people could get access to this mail
@@ -95,8 +95,8 @@ You can ask further questions inside of the chat system.
The admin team of " . $homeserver;
return send_mail($receiver, $subject, $body);
}
}
function send_mail_registration_decline($homeserver, $user, $receiver, $reason) {
$subject = "Registration on $homeserver declined.";
$body = "Guten Tag " . $user . ",
@@ -115,5 +115,4 @@ We hope that you can understand this reason.
The admin team of " . $homeserver;
return send_mail($receiver, $subject, $body );
}
?>

View File

@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require_once(__DIR__ . "/config.php");
require_once("config.php");
$lang = $config["defaultLanguage"];
if (isset($_GET['lang'])) {
@@ -25,7 +25,7 @@ if (!file_exists($lang_file)) {
error_log("Translation for " . $lang . " not found. Fallback to 'de-de'");
$lang = "de-de";
}
$lang_file = __DIR__ . "/lang/lang." . $lang . ".php";
$lang_file = dirname(__FILE__) . "/lang/lang." . $lang . ".php";
require_once($lang_file);
unset($lang_file);
?>

View File

@@ -14,17 +14,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require_once(__DIR__ . "/config.php");
require_once("config.php");
$lang = $config["defaultLanguage"];
if (isset($_GET['lang'])) {
$lang = filter_var($_GET['lang'], FILTER_SANITIZE_STRING);
}
$lang_file = __DIR__ . "/lang/mail." . $lang . ".php";
$lang_file = dirname(__FILE__) . "/lang/mail." . $lang . ".php";
if (!file_exists($lang_file)) {
error_log("Mail templates for '" . $lang . "' not found. Fallback to 'de-de'");
$lang = "de-de";
}
$lang_file = __DIR__ . "/lang/mail." . $lang . ".php";
$lang_file = dirname(__FILE__) . "/lang/mail." . $lang . ".php";
require_once($lang_file);
unset($lang_file);
?>

View File

@@ -19,12 +19,12 @@ if (!isset($_SERVER['HTTPS'])) {
exit();
}
require_once(__DIR__ . "/../language.php");
require_once "../language.php";
if (!file_exists("../config.php")) {
print($language["NO_CONFIGURATION"]);
exit();
}
require_once(__DIR__ . "/../config.php");
require_once "../config.php";
// this values will not be used when using the register operation type
$storeFirstLastName = false;
@@ -49,18 +49,14 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
if (!isset($_POST["username"])) {
throw new Exception("UNKNOWN_USERNAME");
}
if (strlen($_POST["username"]) > 20 ||
strlen($_POST["username"]) < 3 ||
!ctype_lower($_POST["username"])) {
throw new Exception("USERNAME_INVALID");
if (strlen($_POST["username"] > 20 || strlen($_POST["username"]) < 3)) {
throw new Exception("USERNAME_LENGTH_INVALID");
}
if (ctype_alnum($_POST['username']) != true) {
throw new Exception("USERNAME_NOT_ALNUM");
}
if ($storePassword && (!isset($_POST["password"]) || !isset($_POST["password_confirm"]))) {
throw new Exception("PASSWORD_NOT_PROVIDED");
}
if ($storePassword && $_POST["password"] != $_POST["password_confirm"]) {
if (isset($config["getPasswordOnRegistration"]) && $config["getPasswordOnRegistration"] &&
$_POST["password"] != $_POST["password_confirm"]) {
throw new Exception("PASSWORD_NOT_MATCH");
}
if (isset($_POST["note"]) && strlen($_POST["note"]) > 50) {
@@ -84,15 +80,14 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
}
$username = filter_var($_POST["username"], FILTER_SANITIZE_STRING);
$password = "";
if ($storePassword && isset($_POST["password"])) {
$password = filter_var($_POST["password"], FILTER_SANITIZE_STRING);
}
$note = filter_var($_POST["note"], FILTER_SANITIZE_STRING);
$email = filter_var($_POST["email"], FILTER_VALIDATE_EMAIL);
require_once(__DIR__ . "/../database.php");
$res = $mx_db->addRegistration($first_name, $last_name, $username, $password, $note, $email);
require_once("../database.php");
$res = $mx_db->addRegistration($first_name, $last_name, $username, $note, $email);
if (!isset($res["verify_token"])) {
error_log("sth. went wrong. registration did not throw but admin_token not set");
@@ -101,7 +96,7 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
$verify_token = $res["verify_token"];
$verify_url = $config["webroot"] . "/verify.php?t=" . $verify_token;
require_once(__DIR__ . "/../mail_templates.php");
require_once "../mail_templates.php";
$success = send_mail_pending_verification(
$config["homeserver"], $storeFirstLastName ? $first_name . " " . $last_name : $username, $email, $verify_url);
@@ -151,10 +146,8 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
<div class="col-xs-12 col-sm-8 col-md-4 col-sm-offset-2 col-md-offset-4">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><?php
echo strtr($language["TOPIC_PLEASE_REGISTER"], ["@homeserver" => $config["homeserver"]])
. "<small>" . $language["TOPIC_PLEASE_REGISTER_NOTE"] . "</small>";
?></h3>
<h3 class="panel-title"><?php echo strtr($language["TOPIC_PLEASE_REGISTER"], [ "@homeserver" => $config["homeserver"] ])
. "<small>" . $language["TOPIC_PLEASE_REGISTER_NOTE"] . "</small>"; ?></h3>
</div>
<div class="panel-body">
<form name="regForm" role="form" action="index.php" method="post">
@@ -205,13 +198,11 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
<input type="submit" value="<?php echo $language["REGISTER"]; ?>" class="btn btn-info btn-block">
</form>
<?php
if (isset($language["NOTE_FOR_REGISTRATION"])) {
<?php if (isset($language["NOTE_FOR_REGISTRATION"])) {
echo "<p>" . $language["NOTE"] . ": <br />";
echo strtr($language["NOTE_FOR_REGISTRATION"], [ "@homeserver" => $config["homeserver"] ]);
echo "</p>";
}
?>
} ?>
</div>
</div>
</div>
@@ -220,7 +211,7 @@ if ($_SERVER["REQUEST_METHOD"] == "POST") {
<script type="text/javascript">
var user_name = document.getElementById("username");
user_name.oninvalid = function (event) {
event.target.setCustomValidity("<?php echo $language["USERNAME_INVALID"]; ?>");
event.target.setCustomValidity("<?php echo $language["USERNAME_LENGTH_INVALID"]; ?>");
}
user_name.onkeyup = function (event) {
event.target.setCustomValidity("");

View File

@@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require_once(__DIR__ . "/../language.php");
require_once "../language.php";
if (!file_exists("../config.php")) {
print($language["NO_CONFIGURATION"]);
exit();
}
require_once(__DIR__ . "/../config.php");
require_once(__DIR__ . "/../mail_templates.php");
require_once "../config.php";
require_once "../mail_templates.php";
// enforce admin via https
if (!isset($_SERVER['HTTPS'])) {
@@ -38,7 +38,7 @@ try {
}
$token = filter_var($_GET["t"], FILTER_SANITIZE_STRING);
require_once(__DIR__ . "/../database.php");
require_once("../database.php");
$user = $mx_db->getUserForVerify($token);
if ($user == NULL) {
@@ -51,7 +51,7 @@ try {
$email = $user["email"];
$admin_token = $user["admin_token"];
require_once(__DIR__ . "/../MatrixConnection.php");
require_once("../MatrixConnection.php");
$adminUrl = $config["webroot"] . "/verify_admin.php?t=" . $admin_token;
$mxConn = new MatrixConnection($config["homeserver"], $config["access_token"]);
$mxMsg = new MatrixMessage();

View File

@@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
require_once(__DIR__ . "/../language.php");
require_once "../language.php";
if (!file_exists("../config.php")) {
print($language["NO_CONFIGURATION"]);
exit();
}
require_once(__DIR__ . "/../config.php");
require_once(__DIR__ . "/../mail_templates.php");
require_once "../config.php";
require_once "../mail_templates.php";
// enforce admin via https
if (!isset($_SERVER['HTTPS'])) {
@@ -38,7 +38,7 @@ try {
}
$token = filter_var($_GET["t"], FILTER_SANITIZE_STRING);
require_once(__DIR__ . "/../database.php");
require_once("../database.php");
$action = NULL;
if (isset($_GET["allow"])) {
@@ -67,21 +67,15 @@ try {
$mx_db->setRegistrationStateAdmin(RegisterState::PendingRegistration, $token);
// register user
require_once(__DIR__ . "/../MatrixConnection.php");
require_once("../MatrixConnection.php");
$mxConn = new MatrixConnection($config["homeserver"], $config["access_token"]);
$password = NULL;
$use_db_password = (isset($config["getPasswordOnRegistration"]) && $config["getPasswordOnRegistration"]);
if ($use_db_password && isset($user["password"]) && strlen($user["password"]) > 0) {
$password = $user["password"];
} else {
$use_db_password = false;
// generate a password with 10 characters
$password = bin2hex(openssl_random_pseudo_bytes(5));
}
switch ($config["operationMode"]) {
case "synapse":
// register with registration_shared_secret
// generate a password with 10 characters
$password = bin2hex(openssl_random_pseudo_bytes(5));
$res = $mxConn->register($username, $password, $config["registration_shared_secret"]);
if (!$res) {
// something went wrong while registering
@@ -90,7 +84,7 @@ try {
break;
case "local":
// register by adding a user to the local database
$password = $mx_db->addUser($first_name, $last_name, $username, $password, $email);
$password = $mx_db->addUser($first_name, $last_name, $username, $email);
break;
default:
throw new Exception("Unknown operationMode");
@@ -98,13 +92,7 @@ try {
if ($password != NULL) {
// send registration_success
$res = send_mail_registration_success(
$config["homeserver"],
$first_name . " " . $last_name,
$email,
$username,
// only send password when auto-created
($use_db_password ? NULL : $password),
$config["howToURL"]
$config["homeserver"], $first_name . " " . $last_name, $email, $username, $password, $config["howToURL"]
);
if ($res) {
$mx_db->setRegistrationStateAdmin(RegisterState::AllDone, $token);
@@ -166,8 +154,7 @@ try {
</div>
<div class="panel-body">
<form name="appForm" role="form" action="verify_admin.php" method="GET">
<?php
if (isset($config["operationMode"]) && $config["operationMode"] === "local") {
<?php if (isset($config["operationMode"]) && $config["operationMode"] === "local") {
// this values will not be used when using the register operation type
?>
<div class="row">