2020-04-02 00:02:51 +02:00
|
|
|
<?php
|
|
|
|
|
2022-11-18 18:06:46 +01:00
|
|
|
namespace Core\Configuration;
|
2020-04-02 00:02:51 +02:00
|
|
|
|
2022-11-18 18:06:46 +01:00
|
|
|
use Core\Driver\SQL\SQL;
|
|
|
|
use Core\Driver\SQL\Strategy\SetNullStrategy;
|
|
|
|
use Core\Driver\SQL\Strategy\CascadeStrategy;
|
|
|
|
use Core\Objects\DatabaseEntity\DatabaseEntity;
|
2022-06-20 19:52:31 +02:00
|
|
|
use PHPUnit\Util\Exception;
|
2020-04-02 00:02:51 +02:00
|
|
|
|
2021-01-07 15:54:19 +01:00
|
|
|
class CreateDatabase extends DatabaseScript {
|
2020-04-02 00:02:51 +02:00
|
|
|
|
2021-04-02 21:58:06 +02:00
|
|
|
public static function createQueries(SQL $sql): array {
|
2020-04-02 00:02:51 +02:00
|
|
|
$queries = array();
|
|
|
|
|
2022-06-20 19:52:31 +02:00
|
|
|
self::loadEntities($queries, $sql);
|
2020-04-02 00:02:51 +02:00
|
|
|
|
2020-06-25 16:58:26 +02:00
|
|
|
$queries[] = $sql->insert("Language", array("code", "name"))
|
2021-04-02 21:58:06 +02:00
|
|
|
->addRow("en_US", 'American English')
|
|
|
|
->addRow("de_DE", 'Deutsch Standard');
|
2020-04-02 00:02:51 +02:00
|
|
|
|
|
|
|
$queries[] = $sql->createTable("UserToken")
|
|
|
|
->addInt("user_id")
|
|
|
|
->addString("token", 36)
|
2022-02-20 16:53:26 +01:00
|
|
|
->addEnum("token_type", array("password_reset", "email_confirm", "invite", "gpg_confirm"))
|
2020-04-02 00:02:51 +02:00
|
|
|
->addDateTime("valid_until")
|
2020-06-22 21:50:58 +02:00
|
|
|
->addBool("used", false)
|
2022-06-20 19:52:31 +02:00
|
|
|
->foreignKey("user_id", "User", "id", new CascadeStrategy());
|
2020-04-02 00:02:51 +02:00
|
|
|
|
2020-06-25 16:58:26 +02:00
|
|
|
$queries[] = $sql->insert("Group", array("name", "color"))
|
2020-06-25 16:54:58 +02:00
|
|
|
->addRow(USER_GROUP_MODERATOR_NAME, "#007bff")
|
|
|
|
->addRow(USER_GROUP_SUPPORT_NAME, "#28a745")
|
|
|
|
->addRow(USER_GROUP_ADMIN_NAME, "#dc3545");
|
2020-04-02 00:02:51 +02:00
|
|
|
|
|
|
|
$queries[] = $sql->createTable("UserGroup")
|
|
|
|
->addInt("user_id")
|
|
|
|
->addInt("group_id")
|
|
|
|
->unique("user_id", "group_id")
|
2022-06-20 19:52:31 +02:00
|
|
|
->foreignKey("user_id", "User", "id", new CascadeStrategy())
|
|
|
|
->foreignKey("group_id", "Group", "id", new CascadeStrategy());
|
2020-04-02 21:19:06 +02:00
|
|
|
|
|
|
|
$queries[] = $sql->createTable("UserNotification")
|
|
|
|
->addInt("user_id")
|
|
|
|
->addInt("notification_id")
|
2020-06-26 23:32:45 +02:00
|
|
|
->addBool("seen", false)
|
2022-06-20 19:52:31 +02:00
|
|
|
->foreignKey("user_id", "User", "id")
|
|
|
|
->foreignKey("notification_id", "Notification", "id")
|
2020-04-02 21:19:06 +02:00
|
|
|
->unique("user_id", "notification_id");
|
|
|
|
|
|
|
|
$queries[] = $sql->createTable("GroupNotification")
|
|
|
|
->addInt("group_id")
|
|
|
|
->addInt("notification_id")
|
2020-06-26 23:32:45 +02:00
|
|
|
->addBool("seen", false)
|
2022-06-20 19:52:31 +02:00
|
|
|
->foreignKey("group_id", "Group", "id")
|
|
|
|
->foreignKey("notification_id", "Notification", "id")
|
2020-04-02 21:19:06 +02:00
|
|
|
->unique("group_id", "notification_id");
|
|
|
|
|
2020-06-17 23:50:08 +02:00
|
|
|
$queries[] = $sql->createTable("Visitor")
|
2020-07-01 21:10:25 +02:00
|
|
|
->addInt("day")
|
2020-06-17 23:50:08 +02:00
|
|
|
->addInt("count", false, 1)
|
|
|
|
->addString("cookie", 26)
|
2020-07-01 21:10:25 +02:00
|
|
|
->unique("day", "cookie");
|
2020-06-17 23:50:08 +02:00
|
|
|
|
2020-06-19 13:13:13 +02:00
|
|
|
$queries[] = $sql->createTable("Route")
|
2022-06-20 19:52:31 +02:00
|
|
|
->addSerial("id")
|
2020-06-19 13:13:13 +02:00
|
|
|
->addString("request", 128)
|
|
|
|
->addEnum("action", array("redirect_temporary", "redirect_permanently", "static", "dynamic"))
|
|
|
|
->addString("target", 128)
|
|
|
|
->addString("extra", 64, true)
|
|
|
|
->addBool("active", true)
|
2022-05-31 16:14:49 +02:00
|
|
|
->addBool("exact", true)
|
2022-06-20 19:52:31 +02:00
|
|
|
->primaryKey("id")
|
2021-04-06 20:31:52 +02:00
|
|
|
->unique("request");
|
2020-06-19 13:13:13 +02:00
|
|
|
|
2022-05-31 16:14:49 +02:00
|
|
|
$queries[] = $sql->insert("Route", ["request", "action", "target", "extra", "exact"])
|
2022-11-18 18:06:46 +01:00
|
|
|
->addRow("/admin", "dynamic", "\\Core\\Documents\\Admin", NULL, false)
|
|
|
|
->addRow("/register", "dynamic", "\\Core\\Documents\\Account", json_encode(["account/register.twig"]), true)
|
|
|
|
->addRow("/confirmEmail", "dynamic", "\\Core\\Documents\\Account", json_encode(["account/confirm_email.twig"]), true)
|
|
|
|
->addRow("/acceptInvite", "dynamic", "\\Core\\Documents\\Account", json_encode(["account/accept_invite.twig"]), true)
|
|
|
|
->addRow("/resetPassword", "dynamic", "\\Core\\Documents\\Account", json_encode(["account/reset_password.twig"]), true)
|
|
|
|
->addRow("/login", "dynamic", "\\Core\\Documents\\Account", json_encode(["account/login.twig"]), true)
|
|
|
|
->addRow("/resendConfirmEmail", "dynamic", "\\Core\\Documents\\Account", json_encode(["account/resend_confirm_email.twig"]), true)
|
|
|
|
->addRow("/debug", "dynamic", "\\Core\\Documents\\Info", NULL, true)
|
2022-05-31 16:14:49 +02:00
|
|
|
->addRow("/", "static", "/static/welcome.html", NULL, true);
|
2020-06-19 13:13:13 +02:00
|
|
|
|
2020-06-25 16:54:58 +02:00
|
|
|
$queries[] = $sql->createTable("Settings")
|
|
|
|
->addString("name", 32)
|
|
|
|
->addString("value", 1024, true)
|
2020-06-26 23:32:45 +02:00
|
|
|
->addBool("private", false) // these values are not returned from '/api/settings/get', but can be changed
|
|
|
|
->addBool("readonly", false) // these values are neither returned, nor can be changed from outside
|
2020-06-25 16:54:58 +02:00
|
|
|
->primaryKey("name");
|
|
|
|
|
2020-06-26 19:31:31 +02:00
|
|
|
$settingsQuery = $sql->insert("Settings", array("name", "value", "private", "readonly"))
|
2020-06-25 16:54:58 +02:00
|
|
|
// ->addRow("mail_enabled", "0") # this key will be set during installation
|
2020-06-26 19:31:31 +02:00
|
|
|
->addRow("mail_host", "", false, false)
|
|
|
|
->addRow("mail_port", "", false, false)
|
|
|
|
->addRow("mail_username", "", false, false)
|
|
|
|
->addRow("mail_password", "", true, false)
|
|
|
|
->addRow("mail_from", "", false, false)
|
2022-02-20 16:53:26 +01:00
|
|
|
->addRow("mail_last_sync", "", false, false)
|
|
|
|
->addRow("mail_footer", "", false, false);
|
2020-06-25 16:54:58 +02:00
|
|
|
|
|
|
|
(Settings::loadDefaults())->addRows($settingsQuery);
|
|
|
|
$queries[] = $settingsQuery;
|
|
|
|
|
2020-06-26 23:32:45 +02:00
|
|
|
$queries[] = $sql->createTable("ContactRequest")
|
2022-06-20 19:52:31 +02:00
|
|
|
->addSerial("id")
|
2020-06-26 23:32:45 +02:00
|
|
|
->addString("from_name", 32)
|
|
|
|
->addString("from_email", 64)
|
|
|
|
->addString("message", 512)
|
2021-04-09 16:05:36 +02:00
|
|
|
->addString("messageId", 78, true) # null = don't sync with mails (usually if mail could not be sent)
|
2020-06-26 23:32:45 +02:00
|
|
|
->addDateTime("created_at", false, $sql->currentTimestamp())
|
2021-04-09 16:05:36 +02:00
|
|
|
->unique("messageId")
|
2022-06-20 19:52:31 +02:00
|
|
|
->primaryKey("id");
|
2020-06-26 23:32:45 +02:00
|
|
|
|
2021-04-09 16:05:36 +02:00
|
|
|
$queries[] = $sql->createTable("ContactMessage")
|
2022-06-20 19:52:31 +02:00
|
|
|
->addSerial("id")
|
2021-04-09 16:05:36 +02:00
|
|
|
->addInt("request_id")
|
|
|
|
->addInt("user_id", true) # null = customer has sent this message
|
|
|
|
->addString("message", 512)
|
|
|
|
->addString("messageId", 78)
|
|
|
|
->addDateTime("created_at", false, $sql->currentTimestamp())
|
2021-04-10 00:44:34 +02:00
|
|
|
->addBool("read", false)
|
2021-04-09 16:05:36 +02:00
|
|
|
->unique("messageId")
|
2022-06-20 19:52:31 +02:00
|
|
|
->primaryKey("id")
|
|
|
|
->foreignKey("request_id", "ContactRequest", "id", new CascadeStrategy())
|
|
|
|
->foreignKey("user_id", "User", "id", new SetNullStrategy());
|
2021-04-10 00:44:34 +02:00
|
|
|
|
2020-06-27 01:18:10 +02:00
|
|
|
$queries[] = $sql->createTable("ApiPermission")
|
|
|
|
->addString("method", 32)
|
|
|
|
->addJson("groups", true, '[]')
|
2020-06-27 22:47:12 +02:00
|
|
|
->addString("description", 128, false, "")
|
2020-06-27 01:18:10 +02:00
|
|
|
->primaryKey("method");
|
|
|
|
|
2022-02-20 16:53:26 +01:00
|
|
|
$queries[] = $sql->createTable("MailQueue")
|
2022-06-20 19:52:31 +02:00
|
|
|
->addSerial("id")
|
2022-02-20 16:53:26 +01:00
|
|
|
->addString("from", 64)
|
|
|
|
->addString("to", 64)
|
|
|
|
->addString("subject")
|
|
|
|
->addString("body")
|
|
|
|
->addString("replyTo", 64, true)
|
|
|
|
->addString("replyName", 32, true)
|
|
|
|
->addString("gpgFingerprint", 64, true)
|
2022-11-18 18:06:46 +01:00
|
|
|
->addEnum("status", ["waiting", "success", "error"], false, 'waiting')
|
2022-02-20 16:53:26 +01:00
|
|
|
->addInt("retryCount", false, 5)
|
|
|
|
->addDateTime("nextTry", false, $sql->now())
|
2022-11-18 18:06:46 +01:00
|
|
|
->addString("errorMessage", NULL, true)
|
2022-06-20 19:52:31 +02:00
|
|
|
->primaryKey("id");
|
2022-11-18 18:06:46 +01:00
|
|
|
|
|
|
|
$queries = array_merge($queries, \Core\Configuration\Patch\EntityLog_2021_04_08::createTableLog($sql, "MailQueue", 30));
|
2022-02-20 16:53:26 +01:00
|
|
|
|
2020-06-27 22:47:12 +02:00
|
|
|
$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")
|
|
|
|
->addRow("ApiKey/refresh", array(), "Allows users to refresh their API-Keys")
|
|
|
|
->addRow("ApiKey/revoke", array(), "Allows users to revoke their API-Keys")
|
|
|
|
->addRow("Groups/fetch", array(USER_GROUP_SUPPORT, USER_GROUP_ADMIN), "Allows users to list all available groups")
|
|
|
|
->addRow("Groups/create", array(USER_GROUP_ADMIN), "Allows users to create a new groups")
|
|
|
|
->addRow("Groups/delete", array(USER_GROUP_ADMIN), "Allows users to delete a group")
|
|
|
|
->addRow("Routes/fetch", array(USER_GROUP_ADMIN), "Allows users to list all configured routes")
|
|
|
|
->addRow("Routes/save", array(USER_GROUP_ADMIN), "Allows users to create, delete and modify routes")
|
|
|
|
->addRow("Mail/test", array(USER_GROUP_SUPPORT, USER_GROUP_ADMIN), "Allows users to send a test email to a given address")
|
2021-04-09 16:05:36 +02:00
|
|
|
->addRow("Mail/Sync", array(USER_GROUP_SUPPORT, USER_GROUP_ADMIN), "Allows users to synchronize mails with the database")
|
2020-06-27 22:47:12 +02:00
|
|
|
->addRow("Settings/get", array(USER_GROUP_ADMIN), "Allows users to fetch server settings")
|
|
|
|
->addRow("Settings/set", array(USER_GROUP_ADMIN), "Allows users create, delete or modify server settings")
|
|
|
|
->addRow("Stats", array(USER_GROUP_ADMIN, USER_GROUP_SUPPORT), "Allows users to fetch server stats")
|
|
|
|
->addRow("User/create", array(USER_GROUP_ADMIN), "Allows users to create a new user, email address does not need to be confirmed")
|
|
|
|
->addRow("User/fetch", array(USER_GROUP_ADMIN, USER_GROUP_SUPPORT), "Allows users to list all registered users")
|
|
|
|
->addRow("User/get", array(USER_GROUP_ADMIN, USER_GROUP_SUPPORT), "Allows users to get information about a single user")
|
|
|
|
->addRow("User/invite", array(USER_GROUP_ADMIN), "Allows users to create a new user and send them an invitation link")
|
|
|
|
->addRow("User/edit", array(USER_GROUP_ADMIN), "Allows users to edit details and group memberships of any user")
|
|
|
|
->addRow("User/delete", array(USER_GROUP_ADMIN), "Allows users to delete any other user")
|
2020-07-01 21:10:25 +02:00
|
|
|
->addRow("Permission/fetch", array(USER_GROUP_ADMIN), "Allows users to list all API permissions")
|
2021-04-10 00:44:34 +02:00
|
|
|
->addRow("Visitors/stats", array(USER_GROUP_ADMIN, USER_GROUP_SUPPORT), "Allows users to see visitor statistics")
|
|
|
|
->addRow("Contact/respond", array(USER_GROUP_ADMIN, USER_GROUP_SUPPORT), "Allows users to respond to contact requests")
|
|
|
|
->addRow("Contact/fetch", array(USER_GROUP_ADMIN, USER_GROUP_SUPPORT), "Allows users to fetch all contact requests")
|
|
|
|
->addRow("Contact/get", array(USER_GROUP_ADMIN, USER_GROUP_SUPPORT), "Allows users to see messages within a contact request");
|
2021-01-07 15:54:19 +01:00
|
|
|
|
|
|
|
self::loadPatches($queries, $sql);
|
2020-06-27 01:18:10 +02:00
|
|
|
|
2020-04-02 00:02:51 +02:00
|
|
|
return $queries;
|
|
|
|
}
|
2020-06-26 14:58:17 +02:00
|
|
|
|
2021-01-07 15:54:19 +01:00
|
|
|
private static function loadPatches(&$queries, $sql) {
|
2022-11-18 18:06:46 +01:00
|
|
|
$baseDirs = ["Core", "Site"];
|
|
|
|
foreach ($baseDirs as $baseDir) {
|
|
|
|
$patchDirectory = "./$baseDir/Configuration/Patch/";
|
|
|
|
if (file_exists($patchDirectory) && is_dir($patchDirectory)) {
|
|
|
|
$scan_arr = scandir($patchDirectory);
|
|
|
|
$files_arr = array_diff($scan_arr, array('.', '..'));
|
|
|
|
foreach ($files_arr as $file) {
|
|
|
|
$suffix = ".class.php";
|
|
|
|
if (endsWith($file, $suffix)) {
|
|
|
|
$className = substr($file, 0, strlen($file) - strlen($suffix));
|
|
|
|
$className = "\\$baseDir\\Configuration\\Patch\\$className";
|
|
|
|
$method = "$className::createQueries";
|
|
|
|
$patchQueries = call_user_func($method, $sql);
|
|
|
|
foreach ($patchQueries as $query) $queries[] = $query;
|
|
|
|
}
|
2021-01-07 15:54:19 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-06-17 22:58:42 +02:00
|
|
|
|
2022-08-20 22:17:17 +02:00
|
|
|
public static function loadEntities(&$queries, $sql) {
|
2022-11-18 18:06:46 +01:00
|
|
|
$handlers = [];
|
|
|
|
$baseDirs = ["Core", "Site"];
|
|
|
|
foreach ($baseDirs as $baseDir) {
|
|
|
|
$entityDirectory = "./$baseDir/Objects/DatabaseEntity/";
|
|
|
|
if (file_exists($entityDirectory) && is_dir($entityDirectory)) {
|
|
|
|
$scan_arr = scandir($entityDirectory);
|
|
|
|
$files_arr = array_diff($scan_arr, array('.', '..'));
|
|
|
|
foreach ($files_arr as $file) {
|
|
|
|
$suffix = ".class.php";
|
|
|
|
if (endsWith($file, $suffix)) {
|
|
|
|
$className = substr($file, 0, strlen($file) - strlen($suffix));
|
|
|
|
if (!in_array($className, ["DatabaseEntity", "DatabaseEntityQuery", "DatabaseEntityHandler"])) {
|
|
|
|
$className = "\\$baseDir\\Objects\\DatabaseEntity\\$className";
|
|
|
|
$reflectionClass = new \ReflectionClass($className);
|
|
|
|
if ($reflectionClass->isSubclassOf(DatabaseEntity::class)) {
|
|
|
|
$method = "$className::getHandler";
|
|
|
|
$handler = call_user_func($method, $sql);
|
|
|
|
$handlers[$handler->getTableName()] = $handler;
|
|
|
|
}
|
2022-06-20 19:52:31 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
$tableCount = count($handlers);
|
|
|
|
$createdTables = [];
|
|
|
|
while (!empty($handlers)) {
|
|
|
|
$prevCount = $tableCount;
|
|
|
|
$unmetDependenciesTotal = [];
|
|
|
|
|
|
|
|
foreach ($handlers as $tableName => $handler) {
|
|
|
|
$dependsOn = $handler->dependsOn();
|
|
|
|
$unmetDependencies = array_diff($dependsOn, $createdTables);
|
|
|
|
if (empty($unmetDependencies)) {
|
2022-06-17 22:58:42 +02:00
|
|
|
$queries[] = $handler->getTableQuery();
|
2022-06-20 19:52:31 +02:00
|
|
|
$createdTables[] = $tableName;
|
|
|
|
unset($handlers[$tableName]);
|
|
|
|
} else {
|
|
|
|
$unmetDependenciesTotal = array_merge($unmetDependenciesTotal, $unmetDependencies);
|
2022-06-17 22:58:42 +02:00
|
|
|
}
|
|
|
|
}
|
2022-06-20 19:52:31 +02:00
|
|
|
|
|
|
|
$tableCount = count($handlers);
|
|
|
|
if ($tableCount === $prevCount) {
|
|
|
|
throw new Exception("Circular or unmet table dependency detected. Unmet dependencies: "
|
|
|
|
. implode(", ", $unmetDependenciesTotal));
|
|
|
|
}
|
2022-06-17 22:58:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-04-02 00:02:51 +02:00
|
|
|
}
|