Core Update 1.4.0

This commit is contained in:
2022-02-20 16:53:26 +01:00
parent 918244125c
commit bd1f302433
86 changed files with 3301 additions and 41128 deletions

View File

@@ -14,7 +14,7 @@ class Configuration {
$this->settings = Settings::loadDefaults();
$class = \Configuration\Database::class;
$path = getClassPath($class, true);
$path = getClassPath($class, ".class");
if (file_exists($path) && is_readable($path)) {
include_once $path;
if (class_exists($class)) {
@@ -53,7 +53,7 @@ class Configuration {
} else if ($data instanceof ConnectionData) {
$superClass = get_class($data);
$host = addslashes($data->getHost());
$port = intval($data->getPort());
$port = $data->getPort();
$login = addslashes($data->getLogin());
$password = addslashes($data->getPassword());

View File

@@ -32,13 +32,20 @@ class CreateDatabase extends DatabaseScript {
->addString("email", 64, true)
->addString("name", 32)
->addString("password", 128)
->addString("fullName", 64, false, "")
->addString("profilePicture", 64, true)
->addDateTime("last_online", true, NULL)
->addBool("confirmed", false)
->addInt("language_id", true, 1)
->addInt("gpg_id", true)
->addInt("2fa_id", true)
->addDateTime("registered_at", false, $sql->currentTimestamp())
->primaryKey("uid")
->unique("email")
->unique("name")
->foreignKey("language_id", "Language", "uid", new SetNullStrategy());
->foreignKey("language_id", "Language", "uid", new SetNullStrategy())
->foreignKey("gpg_id", "GpgKey", "uid", new SetNullStrategy())
->foreignKey("2fa_id", "2FA", "uid", new SetNullStrategy());
$queries[] = $sql->createTable("Session")
->addSerial("uid")
@@ -57,7 +64,7 @@ class CreateDatabase extends DatabaseScript {
$queries[] = $sql->createTable("UserToken")
->addInt("user_id")
->addString("token", 36)
->addEnum("token_type", array("password_reset", "email_confirm", "invite"))
->addEnum("token_type", array("password_reset", "email_confirm", "invite", "gpg_confirm"))
->addDateTime("valid_until")
->addBool("used", false)
->foreignKey("user_id", "User", "uid", new CascadeStrategy());
@@ -131,11 +138,11 @@ class CreateDatabase extends DatabaseScript {
$queries[] = $sql->insert("Route", array("request", "action", "target", "extra"))
->addRow("^/admin(/.*)?$", "dynamic", "\\Documents\\Admin", NULL)
->addRow("^/register/?$", "dynamic", "\\Documents\\Account", "\\Views\\Account\\Register")
->addRow("^/confirmEmail/?$", "dynamic", "\\Documents\\Account", "\\Views\\Account\\ConfirmEmail")
->addRow("^/acceptInvite/?$", "dynamic", "\\Documents\\Account", "\\Views\\Account\\AcceptInvite")
->addRow("^/resetPassword/?$", "dynamic", "\\Documents\\Account", "\\Views\\Account\\ResetPassword")
->addRow("^/resendConfirmEmail/?$", "dynamic", "\\Documents\\Account", "\\Views\\Account\\ResendConfirmEmail")
->addRow("^/register/?$", "dynamic", "\\Documents\\Account", "account/register.twig")
->addRow("^/confirmEmail/?$", "dynamic", "\\Documents\\Account", "account/confirm_email.twig")
->addRow("^/acceptInvite/?$", "dynamic", "\\Documents\\Account", "account/accept_invite.twig")
->addRow("^/resetPassword/?$", "dynamic", "\\Documents\\Account", "account/reset_password.twig")
->addRow("^/resendConfirmEmail/?$", "dynamic", "\\Documents\\Account", "account/resend_confirm_email.twig")
->addRow("^/$", "static", "/static/welcome.html", NULL);
$queries[] = $sql->createTable("Settings")
@@ -152,10 +159,8 @@ class CreateDatabase extends DatabaseScript {
->addRow("mail_username", "", false, false)
->addRow("mail_password", "", true, false)
->addRow("mail_from", "", false, false)
->addRow("mail_last_sync", "", true, false)
->addRow("message_confirm_email", self::MessageConfirmEmail(), false, false)
->addRow("message_accept_invite", self::MessageAcceptInvite(), false, false)
->addRow("message_reset_password", self::MessageResetPassword(), false, false);
->addRow("mail_last_sync", "", false, false)
->addRow("mail_footer", "", false, false);
(Settings::loadDefaults())->addRows($settingsQuery);
$queries[] = $settingsQuery;
@@ -183,13 +188,54 @@ class CreateDatabase extends DatabaseScript {
->foreignKey("request_id", "ContactRequest", "uid", new CascadeStrategy())
->foreignKey("user_id", "User", "uid", new SetNullStrategy());
$queries[] = $sql->createTable("ApiPermission")
->addString("method", 32)
->addJson("groups", true, '[]')
->addString("description", 128, false, "")
->primaryKey("method");
$queries[] = $sql->createTable("MailQueue")
->addSerial("uid")
->addString("from", 64)
->addString("to", 64)
->addString("subject")
->addString("body")
->addString("replyTo", 64, true)
->addString("replyName", 32, true)
->addString("gpgFingerprint", 64, true)
->addEnum("status", ["waiting","success","error"], false, 'waiting')
->addInt("retryCount", false, 5)
->addDateTime("nextTry", false, $sql->now())
->addString("errorMessage", NULL, true)
->primaryKey("uid");
$queries = array_merge($queries, \Configuration\Patch\log::createTableLog($sql, "MailQueue", 30));
$queries[] = $sql->createTable("GpgKey")
->addSerial("uid")
->addString("fingerprint", 64)
->addDateTime("added", false, $sql->now())
->addDateTime("expires")
->addBool("confirmed")
->addString("algorithm", 32)
->primaryKey("uid");
$queries[] = $sql->createTable("2FA")
->addSerial("uid")
->addEnum("type", ["totp","fido"])
->addString("data", 512) // either totp secret, fido challenge or fido public key information
->addBool("confirmed", false)
->addDateTime("added", false, $sql->now())
->primaryKey("uid");
$queries[] = $sql->createTable("News")
->addSerial("uid")
->addInt("publishedBy")
->addDateTime("publishedAt", false, $sql->now())
->addString("title", 128)
->addString("text", 1024)
->foreignKey("publishedBy", "User", "uid", new CascadeStrategy())
->primaryKey("uid");
$queries[] = $sql->insert("ApiPermission", array("method", "groups", "description"))
->addRow("ApiKey/create", array(), "Allows users to create API-Keys for themselves")
->addRow("ApiKey/fetch", array(), "Allows users to list their API-Keys")
@@ -222,35 +268,6 @@ class CreateDatabase extends DatabaseScript {
return $queries;
}
private static function MessageConfirmEmail(): string {
return "Hello {{username}},<br>" .
"You recently created an account on {{site_name}}. Please click on the following link to " .
"confirm your email address and complete your registration. If you haven't registered an " .
"account, you can simply ignore this email. The link is valid for the next 48 hours:<br><br> " .
"<a href=\"{{link}}\">{{link}}</a><br><br> " .
"Best Regards<br> " .
"{{site_name}} Administration";
}
private static function MessageAcceptInvite(): string {
return "Hello {{username}},<br>" .
"You were invited to create an account on {{site_name}}. Please click on the following link to " .
"confirm your email address and complete your registration by choosing a new password. " .
"If you want to decline the invitation, you can simply ignore this email. The link is valid for the next 7 days:<br><br>" .
"<a href=\"{{link}}\">{{link}}</a><br><br>" .
"Best Regards<br>" .
"{{site_name}} Administration";
}
private static function MessageResetPassword(): string {
return "Hello {{username}},<br>" .
"you requested a password reset on {{site_name}}. Please click on the following link to " .
"choose a new password. If this request was not intended, you can simply ignore the email. The Link is valid for one hour:<br><br>" .
"<a href=\"{{link}}\">{{link}}</a><br><br>" .
"Best Regards<br>" .
"{{site_name}} Administration";
}
private static function loadPatches(&$queries, $sql) {
$patchDirectory = './core/Configuration/Patch/';
if (file_exists($patchDirectory) && is_dir($patchDirectory)) {

View File

@@ -1,75 +0,0 @@
<?php
namespace Configuration\Patch;
use Configuration\DatabaseScript;
use Driver\SQL\SQL;
use Driver\SQL\Column\Column;
use Driver\SQL\Strategy\CascadeStrategy;
use Driver\SQL\Strategy\UpdateStrategy;
class file_api extends DatabaseScript {
public static function createQueries(SQL $sql): array {
$queries = array();
$queries[] = $sql->insert("ApiPermission", array("method", "groups", "description"))
->onDuplicateKeyStrategy(new UpdateStrategy(array("method"), array("method" => new Column("method"))))
->addRow("File/GetRestrictions", array(), "Allows users to view global upload restrictions")
->addRow("File/Download", array(), "Allows users to download files when logged in, or using a given token")
->addRow("File/Upload", array(), "Allows users to upload files when logged in, or using a given token")
->addRow("File/ValidateToken", array(), "Allows users to validate a given token")
->addRow("File/RevokeToken", array(USER_GROUP_ADMIN), "Allows users to revoke a token")
->addRow("File/ListFiles", array(), "Allows users to list all files assigned to an account")
->addRow("File/ListTokens", array(USER_GROUP_ADMIN), "Allows users to list all tokens assigned to the virtual filesystem of an account")
->addRow("File/CreateDirectory", array(), "Allows users to create a virtual directory")
->addRow("File/Rename", array(), "Allows users to rename files in the virtual filesystem")
->addRow("File/Move", array(), "Allows users to move files in the virtual filesystem")
->addRow("File/Delete", array(), "Allows users to delete files in the virtual filesystem")
->addRow("File/CreateUploadToken", array(USER_GROUP_ADMIN), "Allows users to create a token to upload files to the virtual filesystem assigned to the users account")
->addRow("File/CreateDownloadToken", array(USER_GROUP_ADMIN), "Allows users to create a token to download files from the virtual filesystem assigned to the users account");
$queries[] = $sql->insert("Route", array("request", "action", "target", "extra"))
->onDuplicateKeyStrategy(new UpdateStrategy(array("request"), array("request" => new Column("request"))))
->addRow("^/files(/.*)?$", "dynamic", "\\Documents\\Files", NULL);
$queries[] = $sql->createTable("UserFile")
->onlyIfNotExists()
->addSerial("uid")
->addBool("directory")
->addString("name", 64, false)
->addString("path", 512, true)
->addInt("parent_id", true)
->addInt("user_id")
->primaryKey("uid")
->unique("user_id", "parent_id", "name")
->foreignKey("parent_id", "UserFile", "uid", new CascadeStrategy())
->foreignKey("user_id", "User", "uid", new CascadeStrategy());
$queries[] = $sql->createTable("UserFileToken")
->onlyIfNotExists()
->addSerial("uid")
->addString("token", 36, false)
->addDateTime("valid_until", true)
->addEnum("token_type", array("download", "upload"))
->addInt("user_id")
# upload only:
->addInt("maxFiles", true)
->addInt("maxSize", true)
->addInt("parent_id", true)
->addString("extensions", 64, true)
->primaryKey("uid")
->foreignKey("user_id", "User", "uid", new CascadeStrategy())
->foreignKey("parent_id", "UserFile", "uid", new CascadeStrategy());
$queries[] = $sql->createTable("UserFileTokenFile")
->addInt("file_id")
->addInt("token_id")
->unique("file_id", "token_id")
->foreignKey("file_id", "UserFile", "uid", new CascadeStrategy())
->foreignKey("token_id", "UserFileToken", "uid", new CascadeStrategy());
return $queries;
}
}

View File

@@ -5,6 +5,7 @@ namespace Configuration\Patch;
use Configuration\DatabaseScript;
use Driver\SQL\Column\IntColumn;
use Driver\SQL\Condition\Compare;
use Driver\SQL\Query\CreateProcedure;
use Driver\SQL\SQL;
use Driver\SQL\Type\CurrentColumn;
use Driver\SQL\Type\CurrentTable;
@@ -12,6 +13,32 @@ use Driver\SQL\Type\Trigger;
class log extends DatabaseScript {
public static function createTableLog(SQL $sql, string $table, int $lifetime = 90): array {
return [
$sql->createTrigger("${table}_trg_insert")
->after()->insert($table)
->exec(new CreateProcedure($sql, "InsertEntityLog"), [
"tableName" => new CurrentTable(),
"entityId" => new CurrentColumn("uid"),
"lifetime" => $lifetime,
]),
$sql->createTrigger("${table}_trg_update")
->after()->update($table)
->exec(new CreateProcedure($sql, "UpdateEntityLog"), [
"tableName" => new CurrentTable(),
"entityId" => new CurrentColumn("uid"),
]),
$sql->createTrigger("${table}_trg_delete")
->after()->delete($table)
->exec(new CreateProcedure($sql, "DeleteEntityLog"), [
"tableName" => new CurrentTable(),
"entityId" => new CurrentColumn("uid"),
])
];
}
public static function createQueries(SQL $sql): array {
$queries = array();
@@ -25,10 +52,11 @@ class log extends DatabaseScript {
$insertProcedure = $sql->createProcedure("InsertEntityLog")
->param(new CurrentTable())
->param(new IntColumn("uid"))
->param(new IntColumn("lifetime", false, 90))
->returns(new Trigger())
->exec(array(
$sql->insert("EntityLog", ["entityId", "tableName"])
->addRow(new CurrentColumn("uid"), new CurrentTable())
$sql->insert("EntityLog", ["entityId", "tableName", "lifetime"])
->addRow(new CurrentColumn("uid"), new CurrentTable(), new CurrentColumn("lifetime"))
));
$updateProcedure = $sql->createProcedure("UpdateEntityLog")
@@ -58,18 +86,7 @@ class log extends DatabaseScript {
$tables = ["ContactRequest"];
foreach ($tables as $table) {
$queries[] = $sql->createTrigger("${table}_trg_insert")
->after()->insert($table)
->exec($insertProcedure);
$queries[] = $sql->createTrigger("${table}_trg_update")
->after()->update($table)
->exec($updateProcedure);
$queries[] = $sql->createTrigger("${table}_trg_delete")
->after()->delete($table)
->exec($deleteProcedure);
$queries = array_merge($queries, self::createTableLog($sql, $table));
}
return $queries;

View File

@@ -23,6 +23,8 @@ class Settings {
private bool $mailEnabled;
private string $recaptchaPublicKey;
private string $recaptchaPrivateKey;
private string $mailSender;
private string $mailFooter;
public function getJwtSecret(): string {
return $this->jwtSecret;
@@ -47,6 +49,9 @@ class Settings {
$settings->recaptchaPrivateKey = "";
$settings->recaptchaEnabled = false;
$settings->mailEnabled = false;
$settings->mailSender = "webmaster@localhost";
$settings->mailFooter = "";
return $settings;
}
@@ -65,6 +70,8 @@ class Settings {
$this->recaptchaPublicKey = $result["recaptcha_public_key"] ?? $this->recaptchaPublicKey;
$this->recaptchaPrivateKey = $result["recaptcha_private_key"] ?? $this->recaptchaPrivateKey;
$this->mailEnabled = $result["mail_enabled"] ?? $this->mailEnabled;
$this->mailSender = $result["mail_from"] ?? $this->mailSender;
$this->mailFooter = $result["mail_footer"] ?? $this->mailFooter;
if (!isset($result["jwt_secret"])) {
$req = new \Api\Settings\Set($user);
@@ -115,4 +122,8 @@ class Settings {
public function isMailEnabled(): bool {
return $this->mailEnabled;
}
public function getMailSender(): string {
return $this->mailSender;
}
}