From 69ec83d02c4106825bf2e93463480c09638847a9 Mon Sep 17 00:00:00 2001 From: Partydragen Date: Sat, 6 Aug 2022 21:34:11 +0200 Subject: [PATCH 01/23] Fix upload image error (#2984) --- core/includes/image_upload.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/includes/image_upload.php b/core/includes/image_upload.php index 6796f67c66..eaa95b01f5 100644 --- a/core/includes/image_upload.php +++ b/core/includes/image_upload.php @@ -108,7 +108,7 @@ } http_response_code(500); - $error = $e->getMessage() ?: 'Unknown error, check logs for more details'; + $error = $image->getError() ?: 'Unknown error, check logs for more details'; ErrorHandler::logWarning('Image upload error: ' . $error); die($error); } From 05fc2216c503a30dc35b6f7f24e600bce0723339 Mon Sep 17 00:00:00 2001 From: Sam Date: Sat, 6 Aug 2022 20:34:26 +0100 Subject: [PATCH 02/23] Fix non-string config values not saving properly (#2983) --- core/classes/Core/Config.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/classes/Core/Config.php b/core/classes/Core/Config.php index 2814dc7683..f62b48a551 100644 --- a/core/classes/Core/Config.php +++ b/core/classes/Core/Config.php @@ -116,7 +116,7 @@ public static function set(string $key, $value): void { $loc = &$loc[$step]; } // Check if it is a string here so that `null` is not converted to `''` - $loc = $value === null ? $value : addslashes($value); + $loc = !is_string($value) ? $value : addslashes($value); } static::write((array) $config); @@ -140,7 +140,7 @@ public static function setMultiple(array $values): void { foreach ($path as $step) { $loc = &$loc[$step]; } - $loc = addslashes($value); + $loc = !is_string($value) ? $value : addslashes($value); } } From f2c60a9d3d2902945f88508d351fb51efff73e0c Mon Sep 17 00:00:00 2001 From: Tadhg Boyle Date: Sat, 6 Aug 2022 12:34:38 -0700 Subject: [PATCH 03/23] Remove mentions of "pre-release" from installer (#2985) --- README.md | 2 +- custom/languages/cs_CZ.json | 1 - custom/languages/da_DK.json | 3 +-- custom/languages/de_DE.json | 1 - custom/languages/el_GR.json | 1 - custom/languages/en_UK.json | 3 +-- custom/languages/en_US.json | 3 +-- custom/languages/es_419.json | 1 - custom/languages/es_ES.json | 1 - custom/languages/fr_FR.json | 2 +- custom/languages/it_IT.json | 1 - custom/languages/ja_JP.json | 1 - custom/languages/lt_LT.json | 1 - custom/languages/nl_NL.json | 3 +-- custom/languages/no_NO.json | 1 - custom/languages/pl_PL.json | 3 +-- custom/languages/pt_BR.json | 1 - custom/languages/ro_RO.json | 3 +-- custom/languages/ru_RU.json | 1 - custom/languages/sk_SK.json | 3 +-- custom/languages/sv_SE.json | 1 - custom/languages/th_TH.json | 3 +-- custom/languages/tr_TR.json | 1 - custom/languages/uk_UA.json | 1 - custom/languages/zh_CN.json | 1 - custom/languages/zh_TW.json | 1 - rewrite_test.php | 2 +- 27 files changed, 11 insertions(+), 35 deletions(-) diff --git a/README.md b/README.md index d1225fc7ac..35ce810c2c 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ The official project website, providing support and additional downloads such as Features -The following list is a brief summary of the features available in v2 pre-release 13: +The following list is a brief summary of the features available in v2: - 🙋 Forums - 📃 Custom pages: create your own HTML pages and even restrict access to them depending on group. - 👥 Social logins: allow your users to register/login with services such as Discord and Google. diff --git a/custom/languages/cs_CZ.json b/custom/languages/cs_CZ.json index 308d72ccc7..47ac5be2e0 100644 --- a/custom/languages/cs_CZ.json +++ b/custom/languages/cs_CZ.json @@ -795,7 +795,6 @@ "installer/outgoing_email": "Odchozí e-mail", "installer/password": "Heslo", "installer/passwords_must_match": "Vaše hesla se musí shodovat.", - "installer/pre-release": "předběžné vydání", "installer/proceed": "Pokračovat", "installer/reload": "Znovu načíst", "installer/reload_page": "Znovu načíst stránku", diff --git a/custom/languages/da_DK.json b/custom/languages/da_DK.json index e680103bd2..0ad06262f7 100644 --- a/custom/languages/da_DK.json +++ b/custom/languages/da_DK.json @@ -289,7 +289,7 @@ "installer/installer_information": "Installationsprogrammet vil guide dig gennem installationsprocessen.", "installer/installer_now_initialising_database": "Installationsprogrammet er nu ved at initialisere databasen. Dette kan tage et stykke tid...", "installer/installer_upgrading_database": "Vent venligst mens installationsprogrammet opgraderer din database...", - "installer/installer_welcome": "Velkommen til NamelessMC version 2.0 pre-release.", + "installer/installer_welcome": "Velkommen til NamelessMC version 2.0", "installer/language": "Sprog", "installer/nameless_path": "Installations Sti", "installer/nameless_path_info": "Dette er stien Nameless er installeret i, relativt til dit domæne. For eksempel, hvis Nameless er installeret i eksempel.com/forum, dette skal være forum. Efterlad blank, hvis Nameless ikke er i en undermappe.", @@ -300,7 +300,6 @@ "installer/outgoing_email": "Udgående E-Mail", "installer/password": "Adgangskode", "installer/passwords_must_match": "Dine adgangskoder stemmer ikke overens.", - "installer/pre-release": "pre-release", "installer/proceed": "Fortsæt", "installer/reload": "Genindlæs", "installer/reload_page": "Genindlæs side", diff --git a/custom/languages/de_DE.json b/custom/languages/de_DE.json index 0bd4f8e3e4..77cea2b95b 100644 --- a/custom/languages/de_DE.json +++ b/custom/languages/de_DE.json @@ -767,7 +767,6 @@ "installer/outgoing_email": "Absender Emailadresse", "installer/password": "Passwort", "installer/passwords_must_match": "Ihre Passwörter müssen übereinstimmen.", - "installer/pre-release": "Vorab Version (Pre-Release)", "installer/proceed": "Fortfahren", "installer/reload": "Neuladen", "installer/reload_page": "Seite neuladen", diff --git a/custom/languages/el_GR.json b/custom/languages/el_GR.json index f652d5fed9..92698cb38c 100644 --- a/custom/languages/el_GR.json +++ b/custom/languages/el_GR.json @@ -203,7 +203,6 @@ "installer/no": "Όχι", "installer/outgoing_email": "Εξερχόμενο Email", "installer/passwords_must_match": "Οι κωδικοί πρόσβασης πρέπει να ταιριάζουν.", - "installer/pre-release": "προδηµοσιεύσει", "installer/proceed": "συνεχίζω", "installer/requirements": "Απαιτήσεις:", "installer/requirements_error": "Πρέπει να έχετε όλες τις απαιτούμενες επεκτάσεις εγκατεστημένες, και να έχουν οριστεί σωστά δικαιώματα, προκειμένου να προχωρήσει με την εγκατάσταση.", diff --git a/custom/languages/en_UK.json b/custom/languages/en_UK.json index ef173525bb..de726824e0 100644 --- a/custom/languages/en_UK.json +++ b/custom/languages/en_UK.json @@ -891,7 +891,7 @@ "installer/installer_information": "The installer will guide you through the installation process.", "installer/installer_now_initialising_database": "The installer is now initialising the database. This may take a while...", "installer/installer_upgrading_database": "Please wait whilst the installer upgrades your database...", - "installer/installer_welcome": "Welcome to NamelessMC version 2.0 pre-release.", + "installer/installer_welcome": "Welcome to NamelessMC version 2.0", "installer/language": "Language", "installer/nameless_path": "Installation Path", "installer/nameless_path_info": "This is the path Nameless is installed in, relative to your domain. For example, if Nameless is installed at example.com\/forum, this needs to be \"forum\". Leave empty if Nameless is not in a subfolder.", @@ -903,7 +903,6 @@ "installer/outgoing_email": "Outgoing Email", "installer/password": "Password", "installer/passwords_must_match": "Your passwords must match.", - "installer/pre-release": "pre-release", "installer/proceed": "Proceed", "installer/reload": "Reload", "installer/reload_page": "Reload page", diff --git a/custom/languages/en_US.json b/custom/languages/en_US.json index 2f94d96b22..1c68f426a7 100644 --- a/custom/languages/en_US.json +++ b/custom/languages/en_US.json @@ -805,7 +805,7 @@ "installer/installer_information": "The installer will guide you through the installation process.", "installer/installer_now_initialising_database": "The installer is now initializing the database. This may take a while...", "installer/installer_upgrading_database": "Please wait whilst the installer upgrades your database...", - "installer/installer_welcome": "Welcome to NamelessMC version 2.0 pre-release.", + "installer/installer_welcome": "Welcome to NamelessMC version 2.0", "installer/language": "Language", "installer/nameless_path": "Installation Path", "installer/nameless_path_info": "This is the path Nameless is installed in, relative to your domain. For example, if Nameless is installed at example.com/forum, this needs to be forum. Leave empty if Nameless is not in a subfolder.", @@ -816,7 +816,6 @@ "installer/outgoing_email": "Outgoing Email", "installer/password": "Password", "installer/passwords_must_match": "Your passwords must match.", - "installer/pre-release": "pre-release", "installer/proceed": "Proceed", "installer/reload": "Reload", "installer/reload_page": "Reload page", diff --git a/custom/languages/es_419.json b/custom/languages/es_419.json index 5810d60fe7..9f66a13f3e 100644 --- a/custom/languages/es_419.json +++ b/custom/languages/es_419.json @@ -780,7 +780,6 @@ "installer/outgoing_email": "Correo saliente", "installer/password": "Contraseña", "installer/passwords_must_match": "La contraseña debe coincidir.", - "installer/pre-release": "pre-lanzamiento", "installer/proceed": "Siguiente", "installer/reload": "Recargar", "installer/reload_page": "Recargar pagina", diff --git a/custom/languages/es_ES.json b/custom/languages/es_ES.json index f07a06d535..0f5e4aee22 100644 --- a/custom/languages/es_ES.json +++ b/custom/languages/es_ES.json @@ -797,7 +797,6 @@ "installer/outgoing_email": "Dirección de correo electrónico de salida", "installer/password": "Contraseña", "installer/passwords_must_match": "Sus contraseñas deben coincidir.", - "installer/pre-release": "antes del lanzamiento", "installer/proceed": "Proceder", "installer/reload": "Recargar", "installer/reload_page": "Recargar la página", diff --git a/custom/languages/fr_FR.json b/custom/languages/fr_FR.json index 5ce8874b0d..eb8aed08e5 100644 --- a/custom/languages/fr_FR.json +++ b/custom/languages/fr_FR.json @@ -705,7 +705,7 @@ "installer/installer_information": "L’installateur vous guidera dans le processus d’installation.", "installer/installer_now_initialising_database": "L’installateur est en train d’initialiser la base de données. Celaa peut prendre du temps...", "installer/installer_upgrading_database": "Veuillez patienter pendant que l’installateur met à jour votre base de données...", - "installer/installer_welcome": "Bienvenue sur NamelessMC sous la version 2.0 pre-release.", + "installer/installer_welcome": "Bienvenue sur NamelessMC sous la version 2.0", "installer/nameless_path": "Chemin d'installation", "installer/nameless_path_info": "C'est le chemin d'installation où Nameless est installé, par rapport à votre domaine. Par exemple, si Nameless est installé à exemple.com/forum, cela doit être forum. Laisser vide si Nameless n’est pas dans un sous-dossier.", "installer/new_installation": "Nouvelle installation »", diff --git a/custom/languages/it_IT.json b/custom/languages/it_IT.json index 149ad8800e..84359620ca 100644 --- a/custom/languages/it_IT.json +++ b/custom/languages/it_IT.json @@ -726,7 +726,6 @@ "installer/outgoing_email": "Email in uscita", "installer/password": "Password", "installer/passwords_must_match": "Le password devono corrispondere.", - "installer/pre-release": "Pre-Rilascio", "installer/proceed": "Procedi", "installer/reload": "Ricarica", "installer/reload_page": "Ricarica la pagina", diff --git a/custom/languages/ja_JP.json b/custom/languages/ja_JP.json index ee53ad2c5e..531578ccc7 100644 --- a/custom/languages/ja_JP.json +++ b/custom/languages/ja_JP.json @@ -815,7 +815,6 @@ "installer/outgoing_email": "送信用メールアドレス", "installer/password": "パスワード", "installer/passwords_must_match": "パスワードが一致していません。", - "installer/pre-release": "プレリリース", "installer/proceed": "続行", "installer/reload": "再読み込み", "installer/reload_page": "ページを再読み込み", diff --git a/custom/languages/lt_LT.json b/custom/languages/lt_LT.json index f3d13919ec..afe58753f1 100644 --- a/custom/languages/lt_LT.json +++ b/custom/languages/lt_LT.json @@ -641,7 +641,6 @@ "installer/outgoing_email": "Išeinamasis el. paštas", "installer/password": "Slaptažodis", "installer/passwords_must_match": "Jūsų slaptažodžiai turi atitikti.", - "installer/pre-release": "Išankstinis išleidimas", "installer/proceed": "Tęsti", "installer/requirements": "Reikalavimai:", "installer/requirements_error": "Jei norite tęsti diegimą, turite turėti visus reikalingus plėtinius ir nustatyti teisingus leidimus.", diff --git a/custom/languages/nl_NL.json b/custom/languages/nl_NL.json index 0ae0690fe2..3331cc96ec 100644 --- a/custom/languages/nl_NL.json +++ b/custom/languages/nl_NL.json @@ -771,7 +771,7 @@ "installer/installer_information": "Het installatieprogramma leidt je door het installatieproces.", "installer/installer_now_initialising_database": "De installateur is de database aan het instellen. Dit kan een tijdje duren...", "installer/installer_upgrading_database": "Even geduld aub terwijl de installateur uw database upgrade...", - "installer/installer_welcome": "Welkom bij NamelessMC versie 2.0 pre-release.", + "installer/installer_welcome": "Welkom bij NamelessMC versie 2.0", "installer/language": "Taal", "installer/nameless_path": "Installatiepad", "installer/nameless_path_info": "Dit is het pad waarin Nameless is geïnstalleerd ten opzichte van uw domein. Als Nameless bijvoorbeeld is geïnstalleerd op example.com/forum, moet dit \"forum\" zijn. Laat leeg als Nameless zich niet in een submap bevindt.", @@ -782,7 +782,6 @@ "installer/outgoing_email": "Uitgaande Email", "installer/password": "Wachtwoord", "installer/passwords_must_match": "Uw wachtwoorden komen niet overeen.", - "installer/pre-release": "pre-release", "installer/proceed": "Doorgaan", "installer/reload": "Herlaad", "installer/reload_page": "Herlaad pagina", diff --git a/custom/languages/no_NO.json b/custom/languages/no_NO.json index 48604f28a5..fbdd65689d 100644 --- a/custom/languages/no_NO.json +++ b/custom/languages/no_NO.json @@ -746,7 +746,6 @@ "installer/outgoing_email": "Utgående e-post", "installer/password": "Passord", "installer/passwords_must_match": "Passordene dine er ikke like.", - "installer/pre-release": "beta-utgivelse", "installer/proceed": "Fortsett", "installer/reload": "Last inn på nytt", "installer/reload_page": "Last inn siden på nytt", diff --git a/custom/languages/pl_PL.json b/custom/languages/pl_PL.json index f9218f6a19..9b8b479ac6 100644 --- a/custom/languages/pl_PL.json +++ b/custom/languages/pl_PL.json @@ -763,7 +763,7 @@ "installer/installer_information": "Instalator przeprowadzi Cię przez proces instalacji.", "installer/installer_now_initialising_database": "Instalator tworzy bazę danych. Może to chwilę zająć...", "installer/installer_upgrading_database": "Poczekaj, aż instalator zaktualizuje twoją bazę danych...", - "installer/installer_welcome": "Witamy w wersji NamelessMc 2.0 pre-release.", + "installer/installer_welcome": "Witamy w wersji NamelessMc 2.0", "installer/language": "Język", "installer/nameless_path": "Ścieżka instalacji", "installer/nameless_path_info": "Wpisz tutaj ścieżkę do folderu w którym jest zainstalowany Nameless. Na przykład, jeśli Nameless jest zainstalowany w przyklad.pl/forum, musisz wpisać tu forum. Pozostaw to pole puste jeśli Nameless nie jest zainstalowany w subfolderze.", @@ -774,7 +774,6 @@ "installer/outgoing_email": "Email do wysyłania wiadomości do użytkowników", "installer/password": "Hasło", "installer/passwords_must_match": "Twoje hasła muszą być takie same.", - "installer/pre-release": "wersja-testowa", "installer/proceed": "Kontynuuj", "installer/reload": "Przeładuj", "installer/reload_page": "Przeładuj Stronę", diff --git a/custom/languages/pt_BR.json b/custom/languages/pt_BR.json index 47fa4e5587..ec9c92dc54 100644 --- a/custom/languages/pt_BR.json +++ b/custom/languages/pt_BR.json @@ -801,7 +801,6 @@ "installer/outgoing_email": "Email de envio", "installer/password": "Senha", "installer/passwords_must_match": "Suas senhas devem corresponder.", - "installer/pre-release": "pre-release", "installer/proceed": "Prosseguir", "installer/reload": "Recarregar", "installer/reload_page": "Recarregar a página", diff --git a/custom/languages/ro_RO.json b/custom/languages/ro_RO.json index 5dba295dea..7a74b9fff8 100644 --- a/custom/languages/ro_RO.json +++ b/custom/languages/ro_RO.json @@ -649,7 +649,7 @@ "installer/installer_information": "Programul de instalare vă va ghida în procesul de instalare.", "installer/installer_now_initialising_database": "Instalatorul inițiază acum baza de date. Acest lucru poate dura ceva timp...", "installer/installer_upgrading_database": "Vă rugăm să așteptați până instalatorul actualizează baza de date ...", - "installer/installer_welcome": "Bine ați venit la versiunea 2.0-pre-release a programului NamelessMC.", + "installer/installer_welcome": "Bine ați venit la versiunea 2.0 a programului NamelessMC.", "installer/language": "Language", "installer/nameless_path": "Calea de instalare", "installer/nameless_path_info": "Aceasta este calea în care este instalat scriptul, în raport cu domeniul dvs. De exemplu, dacă Nameless este instalat la example.com/forum, acesta trebuie să fie forum . Lăsați goal dacă Nameless nu se află într-un subfolder.", @@ -659,7 +659,6 @@ "installer/outgoing_email": "E-Mail de iesire", "installer/password": "Parola", "installer/passwords_must_match": "Parolele dvs. trebuie să se potrivească.", - "installer/pre-release": "pre-lansare", "installer/proceed": "Continuă", "installer/requirements": "Cerinţe:", "installer/requirements_error": "Trebuie să aveți instalate toate extensiile necesare și setați permisiunile corecte (permisiuni de scriere) pentru a continua instalarea.", diff --git a/custom/languages/ru_RU.json b/custom/languages/ru_RU.json index bc81214bdb..331486a6a0 100644 --- a/custom/languages/ru_RU.json +++ b/custom/languages/ru_RU.json @@ -814,7 +814,6 @@ "installer/outgoing_email": "Исходящий адрес электронной почты", "installer/password": "Пароль", "installer/passwords_must_match": "Ваши пароли должны совпадать.", - "installer/pre-release": "предрелиз", "installer/proceed": "Продолжить", "installer/reload": "Сброс", "installer/reload_page": "Перезагрузить страницу", diff --git a/custom/languages/sk_SK.json b/custom/languages/sk_SK.json index 4690dad7fa..20515cfc48 100644 --- a/custom/languages/sk_SK.json +++ b/custom/languages/sk_SK.json @@ -796,7 +796,7 @@ "installer/installer_information": "Inštalátor vás prevedie procesom inštalácie.", "installer/installer_now_initialising_database": "Inštalátor teraz inicializuje databázu. Môže to chvíľu trvať...", "installer/installer_upgrading_database": "Počkajte, kým inštalátor inovuje vašu databázu...", - "installer/installer_welcome": "Vitajte v NamelessMC verzie 2.0 pre-release.", + "installer/installer_welcome": "Vitajte v NamelessMC verzie 2.0", "installer/language": "Jazyk", "installer/nameless_path": "Cesta inštalácie", "installer/nameless_path_info": "Toto je cesta, na ktorej je Nameless nainštalovaný, vo vzťahu k vašej doméne. Ak je napríklad Nameless nainštalovaný na adrese example.com/forum, musí to byť forum. Ak nie je Nameless v podpriečinku, nechajte ho prázdne.", @@ -807,7 +807,6 @@ "installer/outgoing_email": "Odchádzajúci email", "installer/password": "Heslo", "installer/passwords_must_match": "Vaše heslá sa nezhodujú.", - "installer/pre-release": "pre-release", "installer/proceed": "Pokračovať", "installer/reload": "Znovu načítať", "installer/reload_page": "Znovu načítať stránku", diff --git a/custom/languages/sv_SE.json b/custom/languages/sv_SE.json index d7c3ae51ef..839c31ccb3 100644 --- a/custom/languages/sv_SE.json +++ b/custom/languages/sv_SE.json @@ -765,7 +765,6 @@ "installer/outgoing_email": "Utgående Email", "installer/password": "Lösenord", "installer/passwords_must_match": "Dina lösenord måste matcha.", - "installer/pre-release": "Förhands-utgivning", "installer/proceed": "Fortsätt", "installer/reload": "Ladda om", "installer/reload_page": "Ladda om sidan", diff --git a/custom/languages/th_TH.json b/custom/languages/th_TH.json index f37ce84004..ef71e7a1c5 100644 --- a/custom/languages/th_TH.json +++ b/custom/languages/th_TH.json @@ -760,7 +760,7 @@ "installer/installer_information": "โปรแกรมติดตั้งจะแนะนำคุณตลอดขั้นตอนการติดตั้ง", "installer/installer_now_initialising_database": "โปรแกรมติดตั้งกำลังเริ่มต้นฐานข้อมูล อาจใช้เวลาสักครู่...", "installer/installer_upgrading_database": "โปรดรอในขณะที่โปรแกรมติดตั้งอัปเกรดฐานข้อมูลของคุณ...", - "installer/installer_welcome": "ยินดีต้อนรับสู่ NamelessMC version 2.0 pre-release.", + "installer/installer_welcome": "ยินดีต้อนรับสู่ NamelessMC version 2.0", "installer/language": "ภาษา", "installer/nameless_path": "เส้นทางการติดตั้ง", "installer/nameless_path_info": "นี่คือเส้นทางที่มีการติดตั้ง Nameless ซึ่งสัมพันธ์กับโดเมนของคุณ ตัวอย่างเช่น หากติดตั้ง Nameless ไว้ที่ example.com/forum จะต้องเป็น forum. เว้นว่างไว้หาก Nameless ไม่ได้อยู่ในโฟลเดอร์ย่อย", @@ -771,7 +771,6 @@ "installer/outgoing_email": "อีเมลส่งออก", "installer/password": "รหัสผ่าน", "installer/passwords_must_match": "รหัสผ่านของคุณต้องตรงกัน", - "installer/pre-release": "pre-release", "installer/proceed": "ดำเนินการ", "installer/reload": "โหลดซ้ำ", "installer/reload_page": "โหลดหน้าใหม่", diff --git a/custom/languages/tr_TR.json b/custom/languages/tr_TR.json index 4b8fc98448..763ea3d303 100644 --- a/custom/languages/tr_TR.json +++ b/custom/languages/tr_TR.json @@ -667,7 +667,6 @@ "installer/outgoing_email": "Giden E-posta", "installer/password": "Şifre", "installer/passwords_must_match": "Şifreleriniz eşleşmeli", - "installer/pre-release": "Ön sürüm", "installer/proceed": "İlerle", "installer/requirements": "Gereksinimler:", "installer/requirements_error": "Yüklemeye devam etmek için gerekli tüm uzantıların kurulu olması ve doğru izinlerin ayarlanmış olması gerekir.", diff --git a/custom/languages/uk_UA.json b/custom/languages/uk_UA.json index 767e22b9c1..8128ee955b 100644 --- a/custom/languages/uk_UA.json +++ b/custom/languages/uk_UA.json @@ -775,7 +775,6 @@ "installer/outgoing_email": "Вихідна адреса електронної пошти", "installer/password": "Пароль", "installer/passwords_must_match": "Ваші паролі мають співпадати.", - "installer/pre-release": "Передреліз", "installer/proceed": "Продовжити", "installer/reload": "Скидання", "installer/reload_page": "Перезавантажити сторінку", diff --git a/custom/languages/zh_CN.json b/custom/languages/zh_CN.json index 644207fb34..c6088ad061 100644 --- a/custom/languages/zh_CN.json +++ b/custom/languages/zh_CN.json @@ -789,7 +789,6 @@ "installer/outgoing_email": "发件箱", "installer/password": "密码", "installer/passwords_must_match": "您的密码必须匹配", - "installer/pre-release": "预览版本", "installer/proceed": "继续", "installer/reload": "刷新", "installer/reload_page": "刷新页面", diff --git a/custom/languages/zh_TW.json b/custom/languages/zh_TW.json index 6f272f914a..663b84b8f1 100644 --- a/custom/languages/zh_TW.json +++ b/custom/languages/zh_TW.json @@ -386,7 +386,6 @@ "installer/outgoing_email": "外部電子郵件", "installer/password": "密碼", "installer/passwords_must_match": "密碼不相同。", - "installer/pre-release": "測試版", "installer/proceed": "繼續", "installer/requirements": "必要條件:", "installer/requirements_error": "您必須安裝所有必要條件,並設置正確才能繼續安裝。", diff --git a/rewrite_test.php b/rewrite_test.php index 524c8131de..fefbe8fd74 100644 --- a/rewrite_test.php +++ b/rewrite_test.php @@ -32,7 +32,7 @@



-

NamelessMC v2 pre-release

+

NamelessMC v2


From 46fd4b4b80cc98c1e9dabe77163da32fd4e59b84 Mon Sep 17 00:00:00 2001 From: Robin Date: Sat, 6 Aug 2022 23:09:47 +0200 Subject: [PATCH 04/23] Fix API error name --- modules/Core/classes/Misc/CoreApiErrors.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/Core/classes/Misc/CoreApiErrors.php b/modules/Core/classes/Misc/CoreApiErrors.php index 912c67bca9..1c078e2652 100644 --- a/modules/Core/classes/Misc/CoreApiErrors.php +++ b/modules/Core/classes/Misc/CoreApiErrors.php @@ -26,7 +26,7 @@ class CoreApiErrors { public const ERROR_INVALID_EMAIL_ADDRESS = 'core:invalid_email_address'; public const ERROR_INVALID_USERNAME = 'core:invalid_username'; public const ERROR_UNABLE_TO_CREATE_ACCOUNT = 'core:unable_to_create_account'; - public const ERROR_UNABLE_TO_SEND_REGISTRATION_EMAIL = 'core:unable_to_send_email'; + public const ERROR_UNABLE_TO_SEND_REGISTRATION_EMAIL = 'core:unable_to_send_registration_email'; public const ERROR_INVALID_INTEGRATION = 'core:invalid_integration'; public const ERROR_INVALID_CODE = 'core:invalid_code'; From 3726a17ab9f9aa27ca68aa668b7be32cb498aa1e Mon Sep 17 00:00:00 2001 From: Tadhg Boyle Date: Sun, 7 Aug 2022 10:33:26 -0700 Subject: [PATCH 05/23] Make update check more resilient to API being down (#2987) --- core/classes/Core/Util.php | 2 +- core/classes/DTO/UpdateCheck.php | 16 +++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/core/classes/Core/Util.php b/core/classes/Core/Util.php index ca94656288..eeeea929d9 100644 --- a/core/classes/Core/Util.php +++ b/core/classes/Core/Util.php @@ -237,7 +237,7 @@ public static function updateCheck() { return $update_check_response->getError(); } - $update_check = new UpdateCheck($update_check_response->json(true)); + $update_check = new UpdateCheck($update_check_response); if ($update_check->hasError()) { return $update_check->getErrorMessage(); } diff --git a/core/classes/DTO/UpdateCheck.php b/core/classes/DTO/UpdateCheck.php index 91f5ad6149..42a32a9a62 100644 --- a/core/classes/DTO/UpdateCheck.php +++ b/core/classes/DTO/UpdateCheck.php @@ -9,18 +9,24 @@ */ class UpdateCheck { - private array $_response; + private ?string $_raw_response; + private ?array $_response; - public function __construct(array $response) { - $this->_response = $response; + public function __construct(HttpClient $update_check_response) { + $this->_raw_response = $update_check_response->contents(); + $this->_response = json_decode($this->_raw_response, true); } public function hasError(): bool { - return !count($this->_response) || $this->_response['error']; + return $this->_response === null || !count($this->_response) || $this->_response['error']; } public function getErrorMessage(): string { - return $this->_response['message'] ?? 'Invalid response from server: ' . json_encode($this->_response); + if (isset($this->_response['message'])) { + return 'Error from server: ' . $this->_response['message']; + } + + return 'Invalid response from server: ' . $this->_raw_response; } public function updateAvailable(): bool { From cdd7d85686dffd2bad7de4f8da5d33e37434e57d Mon Sep 17 00:00:00 2001 From: Tadhg Boyle Date: Sun, 7 Aug 2022 10:33:44 -0700 Subject: [PATCH 06/23] Better module/template version check (#2994) --- core/classes/Core/Util.php | 15 +++++++++++++++ modules/Core/pages/panel/modules.php | 4 ++-- modules/Core/pages/panel/panel_templates.php | 11 ++++------- modules/Core/pages/panel/templates.php | 11 ++++------- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/core/classes/Core/Util.php b/core/classes/Core/Util.php index eeeea929d9..da1a0f6007 100644 --- a/core/classes/Core/Util.php +++ b/core/classes/Core/Util.php @@ -524,4 +524,19 @@ public static function findBeforeAfter(array $items, string $current): array { return [$before, $after]; } + /** + * Determine whether a module/template version is compatible with the current NamelessMC version. + * This ignores patch versions, and only checks major and minor versions. + * For example, 2.0.0 and 2.0.1 are compatible, but 2.0.0 and 2.1.0 are not. + * @param string $version Version of module/template to check + * @param string $nameless_version Current NamelessMC version + * @return bool Whether they are compatible or not + */ + public static function isCompatible(string $version, string $nameless_version): bool { + [$major, $minor, ] = explode('.', $version); + [$nameless_major, $nameless_minor, ] = explode('.', $nameless_version); + + return $major == $nameless_major && $minor == $nameless_minor; + } + } diff --git a/modules/Core/pages/panel/modules.php b/modules/Core/pages/panel/modules.php index 53faa15d6a..fd5330c0bb 100644 --- a/modules/Core/pages/panel/modules.php +++ b/modules/Core/pages/panel/modules.php @@ -54,10 +54,10 @@ 'nameless_version' => Output::getClean($module->getNamelessVersion()), 'author' => Output::getPurified($module->getAuthor()), 'author_x' => $language->get('admin', 'author_x', ['author' => Output::getPurified($module->getAuthor())]), - 'version_mismatch' => (($module->getNamelessVersion() != NAMELESS_VERSION) ? $language->get('admin', 'module_outdated', [ + 'version_mismatch' => !Util::isCompatible($module->getNamelessVersion(), NAMELESS_VERSION) ? $language->get('admin', 'module_outdated', [ 'intendedVersion' => Text::bold(Output::getClean($module->getNamelessVersion())), 'actualVersion' => Text::bold(NAMELESS_VERSION) - ]) : false), + ]) : false, 'disable_link' => (($module->getName() != 'Core' && $item->enabled) ? URL::build('/panel/core/modules/', 'action=disable&m=' . urlencode($item->id)) : null), 'enable_link' => (($module->getName() != 'Core' && !$item->enabled) ? URL::build('/panel/core/modules/', 'action=enable&m=' . urlencode($item->id)) : null), 'enabled' => $item->enabled diff --git a/modules/Core/pages/panel/panel_templates.php b/modules/Core/pages/panel/panel_templates.php index 2d5a51a90c..622da673fe 100644 --- a/modules/Core/pages/panel/panel_templates.php +++ b/modules/Core/pages/panel/panel_templates.php @@ -46,13 +46,10 @@ 'version' => Output::getClean($template->getVersion()), 'author' => $template->getAuthor(), 'author_x' => $language->get('admin', 'author_x', ['author' => $template->getAuthor()]), - 'version_mismatch' => (($template->getNamelessVersion() != NAMELESS_VERSION) - ? $language->get('admin', 'template_outdated', [ - 'intendedVersion' => Output::getClean($template->getNamelessVersion()), - 'actualVersion' => NAMELESS_VERSION, - ]) - : false - ), + 'version_mismatch' => !Util::isCompatible($template->getNamelessVersion(), NAMELESS_VERSION) ? $language->get('admin', 'template_outdated', [ + 'intendedVersion' => Output::getClean($template->getNamelessVersion()), + 'actualVersion' => NAMELESS_VERSION, + ]) : false, 'enabled' => $item->enabled, 'activate_link' => (($item->enabled) ? null : URL::build('/panel/core/panel_templates/', 'action=activate&template=' . urlencode($item->id))), 'delete_link' => (($item->id == 1 || $item->enabled) ? null : URL::build('/panel/core/panel_templates/', 'action=delete&template=' . urlencode($item->id))), diff --git a/modules/Core/pages/panel/templates.php b/modules/Core/pages/panel/templates.php index b5562cc8b4..36c0265c0e 100644 --- a/modules/Core/pages/panel/templates.php +++ b/modules/Core/pages/panel/templates.php @@ -56,13 +56,10 @@ 'version' => Output::getClean($template->getVersion()), 'author' => $template->getAuthor(), 'author_x' => $language->get('admin', 'author_x', ['author' => $template->getAuthor()]), - 'version_mismatch' => (($template->getNamelessVersion() != NAMELESS_VERSION) - ? $language->get('admin', 'template_outdated', [ - 'intendedVersion' => Text::bold(Output::getClean($template->getNamelessVersion())), - 'actualVersion' => Text::bold(NAMELESS_VERSION) - ]) - : false - ), + 'version_mismatch' => !Util::isCompatible($template->getNamelessVersion(), NAMELESS_VERSION) ? $language->get('admin', 'template_outdated', [ + 'intendedVersion' => Text::bold(Output::getClean($template->getNamelessVersion())), + 'actualVersion' => Text::bold(NAMELESS_VERSION) + ]) : false, 'enabled' => $item->enabled, 'default_warning' => (Output::getClean($item->name) == 'Default') ? $language->get('admin', 'template_not_supported') : null, 'activate_link' => (($item->enabled) ? null : URL::build('/panel/core/templates/', 'action=activate&template=' . urlencode($item->id))), From 98fe4b7fce5509e49e71f1357118db887b8b88e0 Mon Sep 17 00:00:00 2001 From: Sam Date: Sun, 7 Aug 2022 20:32:07 +0100 Subject: [PATCH 07/23] Add ability to rate limit via Validate class (#2998) --- core/classes/Core/Validate.php | 61 ++++++++++++++++++++++++++++++++-- custom/languages/en_UK.json | 1 + modules/Core/pages/login.php | 14 +++++--- 3 files changed, 70 insertions(+), 6 deletions(-) diff --git a/core/classes/Core/Validate.php b/core/classes/Core/Validate.php index b7e3f57fae..fdb5679bfb 100644 --- a/core/classes/Core/Validate.php +++ b/core/classes/Core/Validate.php @@ -81,6 +81,11 @@ class Validate { */ public const NOT_START_WITH = 'not_start_with'; + /** + * @var string Set a rate limit + */ + public const RATE_LIMIT = 'rate_limit'; + private DB $_db; private ?string $_message = null; @@ -112,6 +117,7 @@ private function __construct() { * @param array $items subset of inputs to be validated * * @return Validate New instance of Validate. + * @throws Exception If provided configuration for a rule is invalid - not if a provided value is invalid! */ public static function check(array $source, array $items = []): Validate { $validator = new Validate(); @@ -318,6 +324,51 @@ public static function check(array $source, array $items = []): Validate { break; } break; + + case self::RATE_LIMIT: + if (is_array($rule_value) && count($rule_value) === 2) { + // If array treat as [limit, seconds] + [$limit, $seconds] = $rule_value; + } else if (is_int($rule_value)) { + // If integer default seconds to 60 + [$limit, $seconds] = [$rule_value, 60]; + } + + if (!isset($limit) || !isset($seconds)) { + throw new Exception('Invalid rate limit configuration'); + } + + $key = "rate_limit_{$item}"; + $session = $_SESSION[$key]; + $time = date('U'); + $limit_end = $time + $seconds; + + if (isset($session) && is_array($session) && count($session) === 2) { + [$count, $expires] = $session; + $diff = $expires - $time; + + if (++$count >= $limit && $diff > 0) { + $validator->addError([ + 'field' => $item, + 'rule' => self::RATE_LIMIT, + 'fallback' => "$item has reached the rate limit which expires in $diff seconds.", + 'meta' => ['expires' => $diff], + ]); + break; + } + + if ($diff <= 0) { + // Reset + $_SESSION[$key] = [1, $limit_end]; + break; + } + + $_SESSION[$key] = [$count, $expires]; + } else { + $_SESSION[$key] = [1, $limit_end]; + } + + break; } } } @@ -379,7 +430,7 @@ public function errors(): array { // Loop all errors to convert and get their custom messages foreach ($this->_to_convert as $error) { - $message = $this->getMessage($error['field'], $error['rule'], $error['fallback']); + $message = $this->getMessage($error['field'], $error['rule'], $error['fallback'], $error['meta']); // If there is no generic `message()` set or the translated message is not equal to generic message // we can continue without worrying about duplications @@ -409,10 +460,11 @@ public function errors(): array { * @param string $field name of field to search for. * @param string $rule rule which check failed. should be from the constants defined above. * @param string $fallback fallback default message if custom message and generic message are not supplied. + * @param ?array $meta optional meta to provide to message. * * @return string Message for this field and rule. */ - private function getMessage(string $field, string $rule, string $fallback): string { + private function getMessage(string $field, string $rule, string $fallback, ?array $meta = []): string { // No custom messages defined for this field if (!isset($this->_messages[$field])) { @@ -436,6 +488,11 @@ private function getMessage(string $field, string $rule, string $fallback): stri return $this->_message ?? $fallback; } + // If the message is a callback function, provide it with meta + if (is_callable($this->_messages[$field][$rule])) { + return $this->_messages[$field][$rule]($meta); + } + // Rule-specific custom message was supplied return $this->_messages[$field][$rule]; } diff --git a/custom/languages/en_UK.json b/custom/languages/en_UK.json index de726824e0..29b69f1dbd 100644 --- a/custom/languages/en_UK.json +++ b/custom/languages/en_UK.json @@ -798,6 +798,7 @@ "general/previous": "Previous", "general/privacy_policy": "Privacy Policy", "general/profile": "Profile", + "general/rate_limit": "Please try again in {{expires}} seconds", "general/register": "Register", "general/remove": "Remove", "general/report": "Report", diff --git a/modules/Core/pages/login.php b/modules/Core/pages/login.php index 08e5af7ea0..bc452ae375 100644 --- a/modules/Core/pages/login.php +++ b/modules/Core/pages/login.php @@ -54,12 +54,15 @@ unset($_SESSION['remember'], $_SESSION['password'], $_SESSION['tfa']); } + $rate_limit = [5, 60]; // 5 attempts in 60 seconds - TODO allow this to be customised? + if ($login_method == 'email') { $to_validate = [ 'email' => [ Validate::REQUIRED => true, Validate::IS_BANNED => true, - Validate::IS_ACTIVE => true + Validate::IS_ACTIVE => true, + Validate::RATE_LIMIT => $rate_limit, ], 'password' => [ Validate::REQUIRED => true @@ -70,7 +73,8 @@ 'username' => [ Validate::REQUIRED => true, Validate::IS_BANNED => true, - Validate::IS_ACTIVE => true + Validate::IS_ACTIVE => true, + Validate::RATE_LIMIT => $rate_limit, ], 'password' => [ Validate::REQUIRED => true @@ -82,12 +86,14 @@ 'email' => [ Validate::REQUIRED => $language->get('user', 'must_input_email'), Validate::IS_BANNED => $language->get('user', 'account_banned'), - Validate::IS_ACTIVE => $language->get('user', 'inactive_account') + Validate::IS_ACTIVE => $language->get('user', 'inactive_account'), + Validate::RATE_LIMIT => fn($meta) => $language->get('general', 'rate_limit', $meta), ], 'username' => [ Validate::REQUIRED => ($login_method == 'username' ? $language->get('user', 'must_input_username') : $language->get('user', 'must_input_email_or_username')), Validate::IS_BANNED => $language->get('user', 'account_banned'), - Validate::IS_ACTIVE => $language->get('user', 'inactive_account') + Validate::IS_ACTIVE => $language->get('user', 'inactive_account'), + Validate::RATE_LIMIT => fn($meta) => $language->get('general', 'rate_limit', $meta), ], 'password' => $language->get('user', 'must_input_password') ]); From eee47b3164c2f171f43490ec55b84af7dbf31c8c Mon Sep 17 00:00:00 2001 From: Robin Date: Sun, 7 Aug 2022 21:32:28 +0200 Subject: [PATCH 08/23] Add croatian language (#2990) --- core/classes/Core/Language.php | 4 ++++ custom/languages/hr_HR.json | 1 + modules/Cookie Consent/language/hr_HR.json | 1 + .../Discord Integration/language/hr_HR.json | 1 + modules/Forum/language/hr_HR.json | 1 + scripts/create_lang.py | 19 +++++++++++++++++++ 6 files changed, 27 insertions(+) create mode 100644 custom/languages/hr_HR.json create mode 100644 modules/Cookie Consent/language/hr_HR.json create mode 100644 modules/Discord Integration/language/hr_HR.json create mode 100644 modules/Forum/language/hr_HR.json create mode 100644 scripts/create_lang.py diff --git a/core/classes/Core/Language.php b/core/classes/Core/Language.php index 0d458ae847..08367a3e7d 100644 --- a/core/classes/Core/Language.php +++ b/core/classes/Core/Language.php @@ -132,6 +132,10 @@ class Language { 'name' => 'Vietnamese', 'htmlCode' => 'vi', ], + 'hr_HR' => [ + 'name' => 'Croatian', + 'htmlCode' =>'hr', + ], ]; /** diff --git a/custom/languages/hr_HR.json b/custom/languages/hr_HR.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/custom/languages/hr_HR.json @@ -0,0 +1 @@ +{} diff --git a/modules/Cookie Consent/language/hr_HR.json b/modules/Cookie Consent/language/hr_HR.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/modules/Cookie Consent/language/hr_HR.json @@ -0,0 +1 @@ +{} diff --git a/modules/Discord Integration/language/hr_HR.json b/modules/Discord Integration/language/hr_HR.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/modules/Discord Integration/language/hr_HR.json @@ -0,0 +1 @@ +{} diff --git a/modules/Forum/language/hr_HR.json b/modules/Forum/language/hr_HR.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/modules/Forum/language/hr_HR.json @@ -0,0 +1 @@ +{} diff --git a/scripts/create_lang.py b/scripts/create_lang.py new file mode 100644 index 0000000000..9782f34225 --- /dev/null +++ b/scripts/create_lang.py @@ -0,0 +1,19 @@ +import sys +from pathlib import Path + +if __name__ == '__main__': + if len(sys.argv) != 2: + print(f"Usage: {sys.argv[0]} _") + sys.exit(1) + + name = sys.argv[1] + + modules = [e.name for e in Path('modules').iterdir() if e.name != 'Core'] + paths = [Path('modules', module, 'language', name + '.json') for module in modules] + paths.append(Path('custom', 'languages', name + '.json')) + + for path in paths: + with path.open('bw+') as f: + f.write(b'{}\n') + + print("Done. Don't forget to add the language to core/classes/Language/Language.php") From a73e4bc4f51c2b5e652e20656683abab06a0ffbb Mon Sep 17 00:00:00 2001 From: Tadhg Boyle Date: Sun, 7 Aug 2022 13:35:49 -0600 Subject: [PATCH 09/23] Display PHP version in die() when version is not acceptable --- index.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.php b/index.php index dec4c9d857..fa42bdb8b3 100644 --- a/index.php +++ b/index.php @@ -26,7 +26,7 @@ // Ensure PHP version >= 7.4 if (PHP_VERSION_ID < 70400) { - die('NamelessMC is not compatible with PHP versions older than 7.4'); + die('NamelessMC is not compatible with PHP versions older than 7.4, you are running PHP ' . PHP_VERSION); } // Start page load timer From 8dba3c36de0430581e0411280f2e143c31be1e41 Mon Sep 17 00:00:00 2001 From: Tadhg Boyle Date: Mon, 8 Aug 2022 07:45:46 -0700 Subject: [PATCH 10/23] Fix active language file value (#3004) --- core/classes/Core/Language.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/core/classes/Core/Language.php b/core/classes/Core/Language.php index 08367a3e7d..15f32702c7 100644 --- a/core/classes/Core/Language.php +++ b/core/classes/Core/Language.php @@ -188,7 +188,7 @@ public function __construct(string $module = 'core', string $active_language = n $path = str_replace('/', DIRECTORY_SEPARATOR, $module) . DIRECTORY_SEPARATOR . '__lng__.json'; } - $this->_activeLanguageFile = $path; + $this->_activeLanguageFile = str_replace('__lng__', $this->_activeLanguage, $path); // HTML language definition if (!defined('HTML_LANG')) { @@ -202,7 +202,7 @@ public function __construct(string $module = 'core', string $active_language = n $this->_i18n = new i18next( $this->_activeLanguage, - $this->_activeLanguageFile, + $path, 'en_UK' ); } @@ -254,13 +254,12 @@ public function getPluralForm(): ?Closure { * @param string $value New value to set for term. */ public function set(string $section, string $term, string $value): void { - $editing_file = implode(DIRECTORY_SEPARATOR, [ROOT_PATH, 'custom', 'languages', $this->_activeLanguage . '.json']); - $json = json_decode(file_get_contents($editing_file), true); + $json = json_decode(file_get_contents($this->_activeLanguageFile), true); $json[$section . '/' . $term] = $value; ksort($json); - file_put_contents($editing_file, json_encode($json, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE)); + file_put_contents($this->_activeLanguageFile, json_encode($json, JSON_PRETTY_PRINT|JSON_UNESCAPED_UNICODE)); } /** From 0922950682943bb2d93758e80ad47fa6afcbba18 Mon Sep 17 00:00:00 2001 From: Partydragen Date: Mon, 8 Aug 2022 17:12:20 +0200 Subject: [PATCH 11/23] Revert image upload changes --- core/includes/image_upload.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/core/includes/image_upload.php b/core/includes/image_upload.php index eaa95b01f5..fc6ef474a5 100644 --- a/core/includes/image_upload.php +++ b/core/includes/image_upload.php @@ -2,7 +2,7 @@ /* * Made by Samerton * https://github.com/NamelessMC/Nameless/ - * NamelessMC version 2.0.0-pr9 + * NamelessMC version 2.0.2 * * License: MIT * @@ -83,6 +83,14 @@ Redirect::to(URL::build('/profile/' . urlencode($user->data()->username))); } + if ( + !is_dir(join(DIRECTORY_SEPARATOR, [ROOT_PATH, 'uploads', 'profile_images', $user->data()->id])) + && !mkdir(join(DIRECTORY_SEPARATOR, [ROOT_PATH, 'uploads', 'profile_images', $user->data()->id])) + ) { + Session::flash('profile_banner_error', 'uploads/profile_images folder not writable! Back'); + Redirect::to(URL::build('/profile/' . urlencode($user->data()->username))); + } + $folder = implode(DIRECTORY_SEPARATOR, ['profile_images', $user->data()->id]); break; From 38eb2fd895a6eaab35fae4b958a4d0679f5eaac0 Mon Sep 17 00:00:00 2001 From: Partydragen Date: Mon, 8 Aug 2022 17:28:19 +0200 Subject: [PATCH 12/23] Fix several profile images issues --- modules/Core/pages/profile.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/modules/Core/pages/profile.php b/modules/Core/pages/profile.php index d510fb2cb1..de2603af5f 100644 --- a/modules/Core/pages/profile.php +++ b/modules/Core/pages/profile.php @@ -76,10 +76,8 @@ ] ); - // Requery to update banner - $user = new User(); - $profile_user = new User($profile, 'username'); - $query = $profile_user->data(); + // Refresh to update banner + Redirect::to($profile_user->getProfileURL()); } } } @@ -402,7 +400,7 @@ case 'reset_banner': if (Token::check($_POST['token'])) { if ($user->hasPermission('modcp.profile_banner_reset')) { - DB::getInstance()->update('users', $query->id, [ + $profile_user->update([ 'banner' => null ]); } @@ -514,7 +512,7 @@ $banners[] = [ 'src' => ((defined('CONFIG_PATH')) ? CONFIG_PATH . '/' : '/') . 'uploads/profile_images/' . Output::getClean($user->data()->id) . '/' . Output::getClean($image), 'name' => Output::getClean($user->data()->id) . '/' . Output::getClean($image), - 'active' => $user->data()->banner == $image + 'active' => $user->data()->banner == $user->data()->id . '/' . $image ]; } } From fbbc44b166d1ed413c62ea7df4239340798afea3 Mon Sep 17 00:00:00 2001 From: Partydragen Date: Mon, 8 Aug 2022 18:13:16 +0200 Subject: [PATCH 13/23] Fix upload image language --- core/includes/image_upload.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/includes/image_upload.php b/core/includes/image_upload.php index fc6ef474a5..58d72dd0e3 100644 --- a/core/includes/image_upload.php +++ b/core/includes/image_upload.php @@ -87,7 +87,7 @@ !is_dir(join(DIRECTORY_SEPARATOR, [ROOT_PATH, 'uploads', 'profile_images', $user->data()->id])) && !mkdir(join(DIRECTORY_SEPARATOR, [ROOT_PATH, 'uploads', 'profile_images', $user->data()->id])) ) { - Session::flash('profile_banner_error', 'uploads/profile_images folder not writable! Back'); + Session::flash('profile_banner_error', $language->get('admin', 'x_directory_not_writable', ['directory' => 'uploads/profile_images'])); Redirect::to(URL::build('/profile/' . urlencode($user->data()->username))); } @@ -111,7 +111,7 @@ try { if (!$image->upload()) { if (Input::get('type') === 'profile_banner') { - Session::flash('profile_banner_error', $image->getError()); + Session::flash('profile_banner_error', $image->getError() ?: $language->get('api', 'unknown_error')); Redirect::to(URL::build('/profile/' . urlencode($user->data()->username))); } From 5d56470de2df48ed637783c8b24b50dc1d829522 Mon Sep 17 00:00:00 2001 From: Tadhg Boyle Date: Thu, 11 Aug 2022 10:45:20 -0700 Subject: [PATCH 14/23] Better missing/extra migration exception page (#3005) --- core/classes/Database/PhinxAdapter.php | 42 +++++++++++++++++++++----- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/core/classes/Database/PhinxAdapter.php b/core/classes/Database/PhinxAdapter.php index c5a91492cb..208d514c64 100644 --- a/core/classes/Database/PhinxAdapter.php +++ b/core/classes/Database/PhinxAdapter.php @@ -9,22 +9,48 @@ class PhinxAdapter { * @throws RuntimeException If these numbers don't match. */ public static function ensureUpToDate(): void { - $migration_files = count(scandir(__DIR__ . '/../../migrations')) - 3; // -3 because of . and .. and phinx.php - $migration_database_entries = DB::getInstance()->query('SELECT COUNT(*) AS count FROM nl2_phinxlog')->first()->count; + $migration_files = array_map( + static function ($file_name) { + [$version, $migration_name] = explode('_', $file_name, 2); + $migration_name = str_replace(['.php', '_'], '', ucwords($migration_name, '_')); + return $version . '_' . $migration_name; + }, + array_filter(scandir(__DIR__ . '/../../migrations'), static function ($file_name) { + return !in_array($file_name, ['.', '..', 'phinx.php']); + }), + ); - if ($migration_files == $migration_database_entries) { - return; - } + $migration_database_entries = array_map(static function ($row) { + return $row->version . '_' . $row->migration_name; + }, DB::getInstance()->query('SELECT version, migration_name FROM nl2_phinxlog')->results()); + + $missing = array_diff($migration_files, $migration_database_entries); + $extra = array_diff($migration_database_entries, $migration_files); // Likely a pull from the repo dev branch or migrations // weren't run during an upgrade script. - if (($diff = $migration_files - $migration_database_entries) > 0) { - throw new RuntimeException("There are {$diff} database migrations pending."); + if (($missing_count = count($missing)) > 0) { + echo "There are $missing_count migrations files which have not been executed:" . '
'; + foreach ($missing as $missing_migration) { + echo " - $missing_migration" . '
'; + } } // Something went wonky, either they've deleted migration files, // or they've added stuff to the nl2_phinxlog table. - throw new RuntimeException("Inconsistent number of migration database entries ({$migration_database_entries}) and migration files ({$migration_files})."); + if (($extra_count = count($extra)) > 0) { + if ($missing_count > 0) { + echo '
'; + } + echo "There are $extra_count executed migrations which do not have migration files associated:" . '
'; + foreach ($extra as $extra_migration) { + echo " - $extra_migration" . '
'; + } + } + + if ($missing_count > 0 || $extra_count > 0) { + die(); + } } /** From 5b996f376734fb6858ab4d98f7c0927e0f25ddf4 Mon Sep 17 00:00:00 2001 From: Tadhg Boyle Date: Fri, 12 Aug 2022 07:02:34 -0700 Subject: [PATCH 15/23] Allow selecting an MC server to use for group sync options (#2991) --- custom/languages/en_UK.json | 4 ++- .../minecraft/minecraft_servers.tpl | 26 ++++++++++++++----- .../Group_Sync/MinecraftGroupSyncInjector.php | 9 ++++--- .../includes/endpoints/ServerInfoEndpoint.php | 10 ++++--- modules/Core/module.php | 2 ++ .../Core/pages/panel/minecraft_servers.php | 15 +++++++++++ 6 files changed, 53 insertions(+), 13 deletions(-) diff --git a/custom/languages/en_UK.json b/custom/languages/en_UK.json index 29b69f1dbd..ab8815ef78 100644 --- a/custom/languages/en_UK.json +++ b/custom/languages/en_UK.json @@ -252,7 +252,8 @@ "admin/group_sync": "Group Sync", "admin/group_sync_info": "You can configure the API to automatically update a user's website group when their integration group is changed. Simply enter the integration group name\/ID and the website group it will be synchronised with the below rules.", "admin/group_sync_logs": "Group Sync Changes", - "admin/group_sync_plugin_not_set_up": "In-game plugin is not set up", + "admin/group_sync_server": "Select a Minecraft server to use for group sync", + "admin/group_sync_plugin_not_set_up": "In-game plugin is not set up or no group sync server has been selected", "admin/group_sync_rule_created_successfully": "The group sync rule has been created successfully.", "admin/group_sync_rule_deleted_successfully": "The group sync rule has been deleted successfully.", "admin/group_sync_rules_updated_successfully": "Group sync rules have been updated successfully.", @@ -392,6 +393,7 @@ "admin/no_custom_pages": "No pages have been created yet.", "admin/no_default_server": "No default server", "admin/no_email_errors": "No email errors logged.", + "admin/no_group_sync_server": "No group sync server", "admin/no_hooks_yet": "There are no webhooks yet.", "admin/no_item_selected": "No items selected", "admin/no_notices": "No notices.", diff --git a/custom/panel_templates/Default/integrations/minecraft/minecraft_servers.tpl b/custom/panel_templates/Default/integrations/minecraft/minecraft_servers.tpl index d997e3e794..6f0192552b 100644 --- a/custom/panel_templates/Default/integrations/minecraft/minecraft_servers.tpl +++ b/custom/panel_templates/Default/integrations/minecraft/minecraft_servers.tpl @@ -77,13 +77,27 @@
+
+ +
+ +
@@ -208,4 +222,4 @@ - \ No newline at end of file + diff --git a/modules/Core/classes/Group_Sync/MinecraftGroupSyncInjector.php b/modules/Core/classes/Group_Sync/MinecraftGroupSyncInjector.php index 268ebdc67f..99e404f480 100644 --- a/modules/Core/classes/Group_Sync/MinecraftGroupSyncInjector.php +++ b/modules/Core/classes/Group_Sync/MinecraftGroupSyncInjector.php @@ -26,14 +26,17 @@ public function getColumnType(): string { } public function shouldEnable(): bool { - return count($this->getSelectionOptions()) > 0; + return Util::getSetting('group_sync_mc_server') != 0 && count($this->getSelectionOptions()) > 0; } public function getSelectionOptions(): array { - $row = DB::getInstance()->query('SELECT `groups` FROM `nl2_query_results` ORDER BY `id` DESC LIMIT 1')->first(); + $row = DB::getInstance()->query( + 'SELECT `groups` FROM `nl2_query_results` WHERE `server_id` = ? ORDER BY `id` DESC LIMIT 1', + [Util::getSetting('group_sync_mc_server')] + )->first(); if ($row === null) { - // Plugin is not set up + // Plugin is not set up and/or they did not select a server to source groups from/default server return []; } diff --git a/modules/Core/includes/endpoints/ServerInfoEndpoint.php b/modules/Core/includes/endpoints/ServerInfoEndpoint.php index a9596df188..6993070748 100644 --- a/modules/Core/includes/endpoints/ServerInfoEndpoint.php +++ b/modules/Core/includes/endpoints/ServerInfoEndpoint.php @@ -65,6 +65,7 @@ public function execute(Nameless2API $api): void { } $group_sync_log = []; + $should_group_sync = $serverId == Util::getSetting('group_sync_mc_server'); try { $integration = Integrations::getInstance()->getIntegration('Minecraft'); @@ -73,9 +74,12 @@ public function execute(Nameless2API $api): void { $integrationUser = new IntegrationUser($integration, $uuid, 'identifier'); if ($integrationUser->exists()) { $this->updateUsername($integrationUser, $player); - $log = $this->updateGroups($integrationUser, $player); - if (count($log)) { - $group_sync_log[] = $log; + + if ($should_group_sync) { + $log = $this->updateGroups($integrationUser, $player); + if (count($log)) { + $group_sync_log[] = $log; + } } if (isset($player['placeholders']) && count($player['placeholders'])) { diff --git a/modules/Core/module.php b/modules/Core/module.php index af907c72c5..6a1926c083 100644 --- a/modules/Core/module.php +++ b/modules/Core/module.php @@ -1602,6 +1602,7 @@ public static function addUserAction($title, $link): void { public function getDebugInfo(): array { $servers = []; + $group_sync_server_id = Util::getSetting('group_sync_mc_server'); foreach (DB::getInstance()->get('mc_servers', ['id', '<>', 0])->results() as $server) { $servers[(int)$server->id] = [ 'id' => (int)$server->id, @@ -1611,6 +1612,7 @@ public function getDebugInfo(): array { 'port' => $server->port, 'query_port' => $server->query_port, 'bedrock' => (bool)$server->bedrock, + 'group_sync_server' => $server->id == $group_sync_server_id, ]; } diff --git a/modules/Core/pages/panel/minecraft_servers.php b/modules/Core/pages/panel/minecraft_servers.php index 5c5718123e..e3e083055c 100644 --- a/modules/Core/pages/panel/minecraft_servers.php +++ b/modules/Core/pages/panel/minecraft_servers.php @@ -496,6 +496,12 @@ $new_default = 0; } + if (isset($_POST['group_sync_server']) && is_numeric($_POST['group_sync_server'])) { + $new_group_sync_server = $_POST['group_sync_server']; + } else { + $new_group_sync_server = 0; + } + if (isset($_POST['external_query']) && $_POST['external_query'] == 1) { $external = 1; } else { @@ -526,6 +532,9 @@ } } + // Group sync server + Util::setSetting('group_sync_mc_server', $new_group_sync_server); + // External query $external_query_id = DB::getInstance()->get('settings', ['name', 'external_query'])->results(); $external_query_id = $external_query_id[0]; @@ -600,6 +609,9 @@ $status_page = DB::getInstance()->get('settings', ['name', 'status_page'])->results(); $status_page = $status_page[0]->value; + $group_sync_server = DB::getInstance()->get('settings', ['name', 'group_sync_mc_server'])->results(); + $group_sync_server = $group_sync_server[0]->value; + // Query interval $cache->setCache('server_query_cache'); if ($cache->isCached('query_interval')) { @@ -632,6 +644,9 @@ 'DEFAULT_SERVER' => $language->get('admin', 'default_server'), 'DEFAULT_SERVER_VALUE' => $default, 'NO_DEFAULT_SERVER' => $language->get('admin', 'no_default_server'), + 'GROUP_SYNC_SERVER' => $language->get('admin', 'group_sync_server'), + 'GROUP_SYNC_SERVER_VALUE' => $group_sync_server, + 'NO_GROUP_SYNC_SERVER' => $language->get('admin', 'no_group_sync_server'), 'QUERY_INTERVAL' => $language->get('admin', 'query_interval'), 'QUERY_INTERVAL_VALUE' => $query_interval, 'EXTERNAL_QUERY' => $language->get('admin', 'external_query'), From 469bebc17855720e43f0c8209c88a57d2b55f6de Mon Sep 17 00:00:00 2001 From: Partydragen Date: Sat, 13 Aug 2022 06:29:09 +0200 Subject: [PATCH 16/23] Rework user sessions system (#3000) Co-authored-by: samerton --- core/classes/Core/User.php | 66 ++++++++++++------- core/init.php | 6 +- .../installation/includes/upgrade_perform.php | 37 ----------- ...2446_add_user_session_activity_columns.php | 22 +++++++ ...20807153708_delete_admin_session_table.php | 14 ++++ modules/Core/hooks/DeleteUserHook.php | 1 - modules/Core/pages/user/settings.php | 11 +++- 7 files changed, 89 insertions(+), 68 deletions(-) create mode 100644 core/migrations/20220807142446_add_user_session_activity_columns.php create mode 100644 core/migrations/20220807153708_delete_admin_session_table.php diff --git a/core/classes/Core/User.php b/core/classes/Core/User.php index ee4c890eba..8db27c050e 100644 --- a/core/classes/Core/User.php +++ b/core/classes/Core/User.php @@ -6,7 +6,7 @@ * @author Samerton * @author Partydragen * @author Aberdeener - * @version 2.0.0-pr13 + * @version 2.0.2 * @license MIT */ class User { @@ -73,14 +73,14 @@ public function __construct(string $user = null, string $field = 'id') { if ($user === null) { if (Session::exists($this->_sessionName)) { - $user = Session::get($this->_sessionName); - if ($this->find($user, $field)) { + $hash = Session::get($this->_sessionName); + if ($this->find($hash, 'hash')) { $this->_isLoggedIn = true; } } if (Session::exists($this->_admSessionName)) { - $user = Session::get($this->_admSessionName); - if ($user == $this->data()->id && $this->find($user, $field)) { + $hash = Session::get($this->_admSessionName); + if ($this->find($hash, 'hash')) { $this->_isAdmLoggedIn = true; } } @@ -107,7 +107,11 @@ public function find(string $value = null, string $field = 'id'): bool { return true; } - $data = $this->_db->get('users', [$field, $value]); + if ($field != 'hash') { + $data = $this->_db->get('users', [$field, $value]); + } else { + $data = $this->_db->query('SELECT nl2_users.* FROM nl2_users LEFT JOIN nl2_users_session ON nl2_users.id = user_id WHERE hash = ? AND nl2_users_session.active = 1', [$value]); + } if ($data->count()) { $this->_data = new UserData($data->first()); @@ -297,7 +301,7 @@ public function idToNickname(int $id): ?string { * @param string|null $username Their username (or email, depending on $method). * @param string|null $password Their password. * @param bool $remember Whether to keep them logged in or not. - * @param string $method What column to check for their details in. Can be either `username` or `email`. + * @param string $method What column to check for their details in. Can be either `username` or `email` or `oauth`. * * @return bool True/false on success or failure respectfully. */ @@ -307,29 +311,27 @@ public function login(?string $username = null, ?string $password = null, bool $ private function _commonLogin(?string $username, ?string $password, bool $remember, string $method, bool $is_admin): bool { $sessionName = $is_admin ? $this->_admSessionName : $this->_sessionName; - if (!$username && !$password && $this->exists()) { - Session::put($sessionName, $this->data()->id); + if (!$username && $method == 'hash' && $this->exists()) { + // Logged in using hash from cookie + Session::put($sessionName, $password); if (!$is_admin) { $this->_isLoggedIn = true; } } else if ($this->checkCredentials($username, $password, $method) === true) { // Valid credentials - Session::put($sessionName, $this->data()->id); + $hash = SecureRandom::alphanumeric(); + + $this->_db->insert('users_session', [ + 'user_id' => $this->data()->id, + 'hash' => $hash, + 'remember_me' => $remember, + 'active' => 1, + 'login_method' => $is_admin ? 'admin' : $method + ]); - if ($remember) { - $hash = SecureRandom::alphanumeric(); - $table = $is_admin ? 'users_admin_session' : 'users_session'; - $hashCheck = $this->_db->get($table, ['user_id', $this->data()->id]); - - if (!$hashCheck->count()) { - $this->_db->insert($table, [ - 'user_id' => $this->data()->id, - 'hash' => $hash - ]); - } else { - $hash = $hashCheck->first()->hash; - } + Session::put($sessionName, $hash); + if ($remember) { $expiry = $is_admin ? 3600 : Config::get('remember.cookie_expiry'); $cookieName = $is_admin ? ($this->_cookieName . '_adm') : $this->_cookieName; Cookie::put($cookieName, $hash, $expiry, HttpUtils::getProtocol() === 'https', true); @@ -532,12 +534,24 @@ public function hasPermission(string $permission): bool { return false; } + /** + * Log the user out from all other sessions. + */ + public function logoutAllOtherSessions(): void { + DB::getInstance()->query('UPDATE nl2_users_session SET `active` = 0 WHERE user_id = ? AND hash != ?', [ + $this->data()->id, + Session::get(Config::get('session.session_name')) + ]); + } + /** * Log the user out. * Deletes their cookies, sessions and database session entry. */ public function logout(): void { - $this->_db->delete('users_session', ['user_id', $this->data()->id]); + $this->_db->update('users_session', [['user_id', $this->data()->id], ['hash', Session::get($this->_sessionName)]], [ + 'active' => 0 + ]); Session::delete($this->_sessionName); Cookie::delete($this->_cookieName); @@ -547,7 +561,9 @@ public function logout(): void { * Process logout if user is admin */ public function admLogout(): void { - $this->_db->delete('users_admin_session', ['user_id', $this->data()->id]); + $this->_db->update('users_session', [['user_id', $this->data()->id], ['hash', Session::get($this->_admSessionName)]], [ + 'active' => 0 + ]); Session::delete($this->_admSessionName); Cookie::delete($this->_cookieName . '_adm'); diff --git a/core/init.php b/core/init.php index edc98df05d..5bcf48c672 100644 --- a/core/init.php +++ b/core/init.php @@ -2,7 +2,7 @@ /* * Made by Samerton * https://github.com/NamelessMC/Nameless/ - * NamelessMC version 2.0.0-pr9 + * NamelessMC version 2.0.2 * * License: MIT * @@ -132,11 +132,11 @@ // Do they need logging in (checked remember me)? if (Cookie::exists(Config::get('remember.cookie_name')) && !Session::exists(Config::get('session.session_name'))) { $hash = Cookie::get(Config::get('remember.cookie_name')); - $hashCheck = DB::getInstance()->get('users_session', ['hash', $hash]); + $hashCheck = DB::getInstance()->get('users_session', [['hash', $hash], ['active', true]]); if ($hashCheck->count()) { $user = new User($hashCheck->first()->user_id); - $user->login(); + $user->login(null, $hash, true, 'hash'); } } diff --git a/core/installation/includes/upgrade_perform.php b/core/installation/includes/upgrade_perform.php index 88624dd731..deface8ec5 100644 --- a/core/installation/includes/upgrade_perform.php +++ b/core/installation/includes/upgrade_perform.php @@ -521,43 +521,6 @@ $errors[] = 'Unable to convert users: ' . $e->getMessage(); } -// User admin session -> user profile wall replies -// User admin sessions -try { - $old = $conn->get('nl1_users_admin_session', ['id', '<>', 0]); - if ($old->count()) { - $old = $old->results(); - - foreach ($old as $item) { - DB::getInstance()->insert('users_admin_session', [ - 'id' => $item->id, - 'user_id' => $item->user_id, - 'hash' => $item->hash - ]); - } - } -} catch (Exception $e) { - $errors[] = 'Unable to convert user admin sessions: ' . $e->getMessage(); -} - -// User sessions -try { - $old = $conn->get('nl1_users_session', ['id', '<>', 0]); - if ($old->count()) { - $old = $old->results(); - - foreach ($old as $item) { - DB::getInstance()->insert('users_session', [ - 'id' => $item->id, - 'user_id' => $item->user_id, - 'hash' => $item->hash - ]); - } - } -} catch (Exception $e) { - $errors[] = 'Unable to convert user sessions: ' . $e->getMessage(); -} - // Username history try { $old = $conn->get('nl1_users_username_history', ['id', '<>', 0]); diff --git a/core/migrations/20220807142446_add_user_session_activity_columns.php b/core/migrations/20220807142446_add_user_session_activity_columns.php new file mode 100644 index 0000000000..5a2e0a08fd --- /dev/null +++ b/core/migrations/20220807142446_add_user_session_activity_columns.php @@ -0,0 +1,22 @@ +table('nl2_users_session'); + $table->addColumn('remember_me', 'boolean', ['default' => false]); + $table->addColumn('active', 'boolean', ['default' => false]); + $table->addColumn('device_name', 'string', ['length' => 256, 'null' => true, 'default' => null]); + $table->addColumn('last_seen', 'integer', ['length' => 11, 'null' => true, 'default' => null]); + $table->addColumn('login_method', 'string', ['length' => 32]); + $table->addIndex('hash', ['unique' => true]); + $table->update(); + + // Remove old data + $table->truncate(); + } +} diff --git a/core/migrations/20220807153708_delete_admin_session_table.php b/core/migrations/20220807153708_delete_admin_session_table.php new file mode 100644 index 0000000000..4a7524c3fa --- /dev/null +++ b/core/migrations/20220807153708_delete_admin_session_table.php @@ -0,0 +1,14 @@ +table('nl2_users_admin_session'); + $table->drop(); + $table->update(); + } +} diff --git a/modules/Core/hooks/DeleteUserHook.php b/modules/Core/hooks/DeleteUserHook.php index f8d76beeb4..dee829e171 100644 --- a/modules/Core/hooks/DeleteUserHook.php +++ b/modules/Core/hooks/DeleteUserHook.php @@ -54,7 +54,6 @@ public static function execute(array $params = []): void { $db->delete('reports_comments', ['commenter_id', $params['user_id']]); // User sessions - $db->delete('users_admin_session', ['user_id', $params['user_id']]); $db->delete('users_session', ['user_id', $params['user_id']]); // Profile fields diff --git a/modules/Core/pages/user/settings.php b/modules/Core/pages/user/settings.php index 3d0097e709..68d6c00b6d 100644 --- a/modules/Core/pages/user/settings.php +++ b/modules/Core/pages/user/settings.php @@ -2,7 +2,7 @@ /* * Made by Samerton * https://github.com/NamelessMC/Nameless/ - * NamelessMC version 2.0.0-pr13 + * NamelessMC version 2.0.2 * * License: MIT * @@ -80,6 +80,10 @@ 'tfa_enabled' => true, 'tfa_type' => 1 ]); + + // Logout all other sessions for this user + $user->logoutAllOtherSessions(); + Session::delete('force_tfa_alert'); Session::flash('tfa_success', $language->get('user', 'tfa_successful')); Redirect::to(URL::build('/user/settings')); @@ -364,6 +368,9 @@ 'pass_method' => 'default' ]); + // Logout all other sessions for this user + $user->logoutAllOtherSessions(); + $success = $language->get('user', 'password_changed_successfully'); } else { @@ -410,7 +417,7 @@ // Update email $user->update([ - 'email' => Output::getClean($_POST['email']) + 'email' => $_POST['email'] ]); Session::flash('settings_success', $language->get('user', 'email_changed_successfully')); From b70cedc3b76bba6ca12361b3304d2e9f259dfb89 Mon Sep 17 00:00:00 2001 From: Tadhg Boyle Date: Fri, 12 Aug 2022 22:40:21 -0600 Subject: [PATCH 17/23] Add OAuth to pages to not store as `last_page` --- core/templates/frontend_init.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/templates/frontend_init.php b/core/templates/frontend_init.php index 34ede5e3c0..8f3635ba86 100644 --- a/core/templates/frontend_init.php +++ b/core/templates/frontend_init.php @@ -12,7 +12,7 @@ const FRONT_END = true; // Set current page URL in session, provided it's not the login page -if (defined('PAGE') && PAGE != 'login' && PAGE != 'register' && PAGE != 404 && PAGE != 'maintenance' && (!isset($_GET['route']) || !str_contains($_GET['route'], '/queries'))) { +if (defined('PAGE') && PAGE != 'login' && PAGE != 'register' && PAGE != 404 && PAGE != 'maintenance' && PAGE != 'oauth' && (!isset($_GET['route']) || !str_contains($_GET['route'], '/queries'))) { if (FRIENDLY_URLS === true) { $split = explode('?', $_SERVER['REQUEST_URI']); From 52e95598fa2858ba4c6d9467b2793b49df1c9146 Mon Sep 17 00:00:00 2001 From: PadowYT2 Date: Sat, 13 Aug 2022 12:57:09 +0300 Subject: [PATCH 18/23] Remake tab initialization (#3009) * Remove tab initialization * Add it back, but different * And remove it here --- custom/templates/DefaultRevamp/js/core/core.js | 3 +-- custom/templates/DefaultRevamp/js/core/pages.js | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/custom/templates/DefaultRevamp/js/core/core.js b/custom/templates/DefaultRevamp/js/core/core.js index 2f1fae7ea5..1c35fe3008 100755 --- a/custom/templates/DefaultRevamp/js/core/core.js +++ b/custom/templates/DefaultRevamp/js/core/core.js @@ -49,8 +49,7 @@ $(function () { $(this).closest('.message').transition('fade'); }); - $('.menu .item').tab(); - + $('.tabular.menu .item').tab(); }); $(function () { diff --git a/custom/templates/DefaultRevamp/js/core/pages.js b/custom/templates/DefaultRevamp/js/core/pages.js index 70af61150f..fb75857a86 100755 --- a/custom/templates/DefaultRevamp/js/core/pages.js +++ b/custom/templates/DefaultRevamp/js/core/pages.js @@ -57,8 +57,6 @@ if (page !== '') { }); }); } else if (page === 'profile') { - $('.menu.tabular .item').tab(); - function showBannerSelect() { $('#imageModal').modal({ onVisible: function () { From be5c947ca64d97432ef914eb0d5e8631aa5fde91 Mon Sep 17 00:00:00 2001 From: Sam Date: Sat, 13 Aug 2022 11:06:49 +0100 Subject: [PATCH 19/23] Logout rework (#3008) * Logout rework * Uncomment * Output logout complete message via die() Co-authored-by: Tadhg Boyle * Add indentation back Co-authored-by: Tadhg Boyle --- core/templates/navbar.php | 1 + custom/languages/en_UK.json | 2 ++ .../templates/DefaultRevamp/js/core/core.js | 11 ++++++++ custom/templates/DefaultRevamp/navbar.tpl | 11 ++++++-- custom/templates/DefaultRevamp/template.php | 5 ++-- modules/Core/pages/logout.php | 27 +++++++++++++++---- 6 files changed, 48 insertions(+), 9 deletions(-) diff --git a/core/templates/navbar.php b/core/templates/navbar.php index 337b749846..694a2b9a8d 100644 --- a/core/templates/navbar.php +++ b/core/templates/navbar.php @@ -134,6 +134,7 @@ 'title' => $language->get('general', 'log_out'), 'link' => URL::build('/logout'), 'target' => '', + 'action' => 'logout', ], ], ]; diff --git a/custom/languages/en_UK.json b/custom/languages/en_UK.json index ab8815ef78..386698cda8 100644 --- a/custom/languages/en_UK.json +++ b/custom/languages/en_UK.json @@ -772,6 +772,8 @@ "general/links": "Links", "general/loading": "Loading...", "general/log_out": "Log Out", + "general/log_out_click": "Click here to log out", + "general/log_out_complete": "Logout successful. Click {{linkStart}}here{{linkEnd}} to continue.", "general/more": "More", "general/next": "Next", "general/no": "No", diff --git a/custom/templates/DefaultRevamp/js/core/core.js b/custom/templates/DefaultRevamp/js/core/core.js index 1c35fe3008..0920111add 100755 --- a/custom/templates/DefaultRevamp/js/core/core.js +++ b/custom/templates/DefaultRevamp/js/core/core.js @@ -25,6 +25,17 @@ function copy(element) { }); } +$(document).ready(function () { + $('[data-action="logout"]').click(function () { + const url = $(this).data('link'); + $.post(url, { + token: csrfToken + }).done(function () { + window.location.reload(); + }); + }); +}); + $(function () { $('.ui.sidebar').sidebar('attach events', '.toc.item'); diff --git a/custom/templates/DefaultRevamp/navbar.tpl b/custom/templates/DefaultRevamp/navbar.tpl index f2cdfbf6a1..3801a57139 100755 --- a/custom/templates/DefaultRevamp/navbar.tpl +++ b/custom/templates/DefaultRevamp/navbar.tpl @@ -66,8 +66,15 @@ {if isset($dropdown.separator)}
{else} - {$dropdown.icon} - {$dropdown.title} + {if isset($dropdown.action)} + + {$dropdown.icon} {$dropdown.title} + + {else} + + {$dropdown.icon} {$dropdown.title} + + {/if} {/if} {/foreach}
diff --git a/custom/templates/DefaultRevamp/template.php b/custom/templates/DefaultRevamp/template.php index 2853776de6..f474f70207 100755 --- a/custom/templates/DefaultRevamp/template.php +++ b/custom/templates/DefaultRevamp/template.php @@ -117,7 +117,8 @@ public function onPageLoad() { 'loggedIn' => $this->_user->isLoggedIn() ? '1' : '0', 'cookie' => defined('COOKIE_NOTICE') ? '1' : '0', 'loadingTime' => Util::getSetting('page_loading') === '1' ? PAGE_LOAD_TIME : '', - 'route' => $route + 'route' => $route, + 'csrfToken' => Token::get(), ]; if (strpos($route, '/forum/topic/') !== false || PAGE == 'profile') { @@ -136,7 +137,7 @@ public function onPageLoad() { $this->addJSScript($JSVars); $this->addJSFiles([ - $this->_template['path'] . 'js/core/core.js' => [], + $this->_template['path'] . 'js/core/core.js?v=202' => [], $this->_template['path'] . 'js/core/user.js' => [], $this->_template['path'] . 'js/core/pages.js' => [], $this->_template['path'] . 'js/scripts.js' => [], diff --git a/modules/Core/pages/logout.php b/modules/Core/pages/logout.php index 5f7b41bb06..85fe907777 100644 --- a/modules/Core/pages/logout.php +++ b/modules/Core/pages/logout.php @@ -2,7 +2,7 @@ /* * Made by Samerton * https://github.com/NamelessMC/Nameless/ - * NamelessMC version 2.0.0-dev + * NamelessMC version 2.0.2 * * License: MIT * @@ -10,10 +10,27 @@ */ if ($user->isLoggedIn()) { - Log::getInstance()->log(Log::Action('user/logout')); - $user->admLogout(); - $user->logout(); + if (Input::exists()) { + if (Token::check()) { + Log::getInstance()->log(Log::Action('user/logout')); + $user->admLogout(); + $user->logout(); - Session::flash('home', $language->get('user', 'successfully_logged_out')); + Session::flash('home', $language->get('user', 'successfully_logged_out')); + die($language->get('general', 'log_out_complete', ['linkStart' => '', 'linkEnd' => ''])); + } + + echo $language->get('general', 'invalid_token') . '
'; + } + + echo ' +
+ +
+ ' . $language->get('general', 'log_out_click') . ' + '; + + return; } + Redirect::to(URL::build('/')); From 49ba64fdd0d3ae784ed70051592cf1da0633879b Mon Sep 17 00:00:00 2001 From: Tadhg Boyle Date: Sat, 13 Aug 2022 03:08:32 -0700 Subject: [PATCH 20/23] Display each OAuth providers redirect URL & misc fixes to template (#3014) * Display each OAuth providers redirect URL & misc fixes to template * Use URL::build to build OAuth URL Co-authored-by: Sam --- custom/languages/en_UK.json | 3 +++ .../Default/core/registration.tpl | 18 ++++++++++++------ modules/Core/pages/panel/registration.php | 4 ++++ 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/custom/languages/en_UK.json b/custom/languages/en_UK.json index 386698cda8..f616d9ff3e 100644 --- a/custom/languages/en_UK.json +++ b/custom/languages/en_UK.json @@ -78,6 +78,8 @@ "admin/captcha_type": "Captcha Type", "admin/check_again": "Check again", "admin/clear_cache": "Clear Template Cache", + "admin/client_id": "Client ID", + "admin/client_secret": "Client Secret", "admin/closable": "Closable", "admin/config_not_writable": "Your core\/config.php file is not writable. Please check file permissions.", "admin/configuration": "Configuration", @@ -501,6 +503,7 @@ "admin/reaction_deleted_successfully": "Reaction deleted successfully.", "admin/reaction_edited_successfully": "Reaction edited successfully.", "admin/reason": "Ban Reason", + "admin/redirect_url": "Redirect URL", "admin/recent_users": "New Users", "admin/register_hook_info": "User registration", "admin/registered": "Registered", diff --git a/custom/panel_templates/Default/core/registration.tpl b/custom/panel_templates/Default/core/registration.tpl index 819ff8703b..0948508feb 100644 --- a/custom/panel_templates/Default/core/registration.tpl +++ b/custom/panel_templates/Default/core/registration.tpl @@ -164,17 +164,23 @@
- + + id="client-id-{$provider_name}" placeholder="Client ID" + value="{$provider_data['client_id']}">
- + + class="form-control" id="client-secret-{$provider_name}" + placeholder="Client Secret" value="{$provider_data['client_secret']}"> +
+ +
+ +
diff --git a/modules/Core/pages/panel/registration.php b/modules/Core/pages/panel/registration.php index e3e27fa983..99466afe29 100644 --- a/modules/Core/pages/panel/registration.php +++ b/modules/Core/pages/panel/registration.php @@ -190,6 +190,10 @@ 'docLinkStart' => '', 'docLinkEnd' => '' ]), + 'REDIRECT_URL' => $language->get('admin', 'redirect_url'), + 'CLIENT_ID' => $language->get('admin', 'client_id'), + 'CLIENT_SECRET' => $language->get('admin', 'client_secret'), + 'OAUTH_URL' => URL::getSelfURL() . ltrim(URL::build('/oauth/', 'provider={{provider}}'), '/'), 'PARENT_PAGE' => PARENT_PAGE, 'DASHBOARD' => $language->get('admin', 'dashboard'), 'CONFIGURATION' => $language->get('admin', 'configuration'), From aa73c4707985402c2acc9cd8df5b15f2170ff333 Mon Sep 17 00:00:00 2001 From: Partydragen Date: Sat, 13 Aug 2022 13:00:54 +0200 Subject: [PATCH 21/23] Fix exception when user id is null in email_error table (#3012) * Fix exception when user id is null in email_error table * Fix requested change --- modules/Core/pages/panel/emails_errors.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/Core/pages/panel/emails_errors.php b/modules/Core/pages/panel/emails_errors.php index b5bcc42be3..21b3cf4883 100644 --- a/modules/Core/pages/panel/emails_errors.php +++ b/modules/Core/pages/panel/emails_errors.php @@ -2,7 +2,7 @@ /* * Made by Samerton * https://github.com/NamelessMC/Nameless/ - * NamelessMC version 2.0.0-pr9 + * NamelessMC version 2.0.2 * * License: MIT * @@ -78,7 +78,7 @@ 'BACK_LINK' => URL::build('/panel/core/emails/errors'), 'VIEWING_ERROR' => $language->get('admin', 'viewing_email_error'), 'USERNAME' => $language->get('user', 'username'), - 'USERNAME_VALUE' => Output::getClean($user->idToName($error->user_id)), + 'USERNAME_VALUE' => $error->user_id ? Output::getClean($user->idToName($error->user_id)) : $language->get('general', 'deleted_user'), 'DATE' => $language->get('general', 'date'), 'DATE_VALUE' => date(DATE_FORMAT, $error->at), 'TYPE' => $language->get('admin', 'type'), @@ -186,7 +186,7 @@ $template_errors[] = [ 'type' => $type, 'date' => date(DATE_FORMAT, $error->at), - 'user' => $error->user_id ? Output::getClean($user->idToName($error->user_id)) : '', + 'user' => $error->user_id ? Output::getClean($user->idToName($error->user_id)) : $language->get('general', 'deleted_user'), 'view_link' => URL::build('/panel/core/emails/errors/', 'do=view&id=' . $error->id), 'id' => $error->id ]; From ace91ac5768a07636fb2a8b18063db17f6cde8e8 Mon Sep 17 00:00:00 2001 From: samerton Date: Sat, 13 Aug 2022 12:04:13 +0100 Subject: [PATCH 22/23] Convert two factor disabling to post request --- custom/languages/en_UK.json | 2 ++ .../templates/DefaultRevamp/user/settings.tpl | 9 ++++-- modules/Core/pages/user/settings.php | 31 ++++++++++++++----- 3 files changed, 32 insertions(+), 10 deletions(-) diff --git a/custom/languages/en_UK.json b/custom/languages/en_UK.json index f616d9ff3e..a959e65f83 100644 --- a/custom/languages/en_UK.json +++ b/custom/languages/en_UK.json @@ -1192,6 +1192,8 @@ "user/successfully_logged_out": "You have been logged out successfully.", "user/terms_and_conditions": "Terms and Conditions", "user/tfa_code": "If your device does not have a camera, or you are unable to scan the QR code, please input the following code:", + "user/tfa_disable_click": "Please click here to disable two factor authentication.", + "user/tfa_disabled": "Two factor authentication has been disabled.", "user/tfa_enter_code": "Please enter the code displaying within your authentication app:", "user/tfa_scan_code": "Please scan the following code within your authentication app:", "user/tfa_successful": "Two factor authentication set up successfully. You will need to authenticate every time you log in from now on.", diff --git a/custom/templates/DefaultRevamp/user/settings.tpl b/custom/templates/DefaultRevamp/user/settings.tpl index 49d94e0624..fd19be6e3c 100755 --- a/custom/templates/DefaultRevamp/user/settings.tpl +++ b/custom/templates/DefaultRevamp/user/settings.tpl @@ -168,11 +168,14 @@

{$TWO_FACTOR_AUTH}

{if isset($ENABLE)} - {$ENABLE} + {$ENABLE} {elseif isset($FORCED)} - + {else} - {$DISABLE} +
+ + +
{/if}
{if isset($CUSTOM_AVATARS)} diff --git a/modules/Core/pages/user/settings.php b/modules/Core/pages/user/settings.php index 68d6c00b6d..6dfc61795f 100644 --- a/modules/Core/pages/user/settings.php +++ b/modules/Core/pages/user/settings.php @@ -127,14 +127,31 @@ } else { if ($_GET['do'] == 'disable_tfa') { // Disable TFA - $user->update([ - 'tfa_enabled' => false, - 'tfa_type' => 0, - 'tfa_secret' => null, - 'tfa_complete' => false - ]); + // TODO - https://github.com/NamelessMC/Nameless/issues/3017 + if (Input::exists()) { + if (Token::check()) { + $user->update([ + 'tfa_enabled' => false, + 'tfa_type' => 0, + 'tfa_secret' => null, + 'tfa_complete' => false + ]); - Redirect::to(URL::build('/user/settings')); + Session::flash('settings_success', $language->get('user', 'tfa_disabled')); + Redirect::to(URL::build('/user/settings')); + } + + echo $language->get('general', 'invalid_token') . '
'; + } + + echo ' +
+ +
+ ' . $language->get('user', 'tfa_disable_click') . ' + '; + + return; } } From 8d4178bb93c68705837c9bd1b255851a80a8d24c Mon Sep 17 00:00:00 2001 From: samerton Date: Sat, 13 Aug 2022 12:27:22 +0100 Subject: [PATCH 23/23] Bump to 2.0.2 --- CHANGELOG.md | 32 ++++++++++++++++++- core/classes/Database/DatabaseInitialiser.php | 2 +- core/includes/updates/{200.php => 201.php} | 2 +- .../installation/includes/upgrade_perform.php | 4 +-- custom/panel_templates/Default/template.php | 4 +-- custom/templates/DefaultRevamp/template.php | 6 ++-- modules/Cookie Consent/module.php | 4 +-- modules/Core/module.php | 4 +-- modules/Discord Integration/module.php | 4 +-- modules/Forum/module.php | 4 +-- package.json | 2 +- 11 files changed, 49 insertions(+), 19 deletions(-) rename core/includes/updates/{200.php => 201.php} (77%) diff --git a/CHANGELOG.md b/CHANGELOG.md index ee06b10b42..44a589ff90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,36 @@ ## [Unreleased](https://github.com/NamelessMC/Nameless/compare/v2.0.0...v2) > [Milestone](https://github.com/NamelessMC/Nameless/milestone/18) +## [2.0.2](https://github.com/NamelessMC/Nameless/compare/v2.0.1...v2.0.2) - 2022-08-13 + +### Added +- Add ability to rate limit via Validate class +- Add base for Croatian translation +- Allow selecting an MC server to use for group sync options +- Display each OAuth provider's redirect URL + +### Changed +- Removed mentions of "pre-release" from installer +- Make update check more resilient to API being down +- Better module/template version check +- Display PHP version in die() when version is not acceptable +- Better missing/extra migration exception page +- Rework user sessions system +- Rework tab initialisation +- Rework logout +- Rework two factor authentication disabling + +### Fixed +- Fix image upload error message +- Fix non-string config values not saving properly +- Fix API error name +- Fix active language file value +- Fix several profile image issues +- Fix OAuth page being stored as last page location +- Fix exception when user ID is null in email errors table + +## [2.0.1](https://github.com/NamelessMC/Nameless/compare/v2.0.0...v2.0.1) - 2022-08-05 + ### Fixed - Fix exception when creating admin user during installation - Update upgrade check to use correct URL on Download button @@ -10,7 +40,7 @@ - Fix not checking if config file would be writable when installing -## [2.0.0](https://github.com/NamelessMC/Nameless/compare/v2.0.0-pr13...v2) - 2022-08-05 +## [2.0.0](https://github.com/NamelessMC/Nameless/compare/v2.0.0-pr13...v2.0.0) - 2022-08-05 > [Milestone](https://github.com/NamelessMC/Nameless/milestone/17) ### Added diff --git a/core/classes/Database/DatabaseInitialiser.php b/core/classes/Database/DatabaseInitialiser.php index 62c5cedfe5..f99e1e6046 100644 --- a/core/classes/Database/DatabaseInitialiser.php +++ b/core/classes/Database/DatabaseInitialiser.php @@ -171,7 +171,7 @@ private function initialiseSettings(): void { Util::setSetting('recaptcha_type', 'Recaptcha3'); Util::setSetting('recaptcha_login', '0'); Util::setSetting('email_verification', '1'); - Util::setSetting('nameless_version', '2.0.1'); + Util::setSetting('nameless_version', '2.0.2'); Util::setSetting('version_checked', date('U')); Util::setSetting('phpmailer', '0'); Util::setSetting('phpmailer_type', 'smtp'); diff --git a/core/includes/updates/200.php b/core/includes/updates/201.php similarity index 77% rename from core/includes/updates/200.php rename to core/includes/updates/201.php index 54a72f90ac..eb115a8a93 100644 --- a/core/includes/updates/200.php +++ b/core/includes/updates/201.php @@ -5,6 +5,6 @@ public function run(): void { $this->runMigrations(); - $this->setVersion('2.0.1'); + $this->setVersion('2.0.2'); } }; diff --git a/core/installation/includes/upgrade_perform.php b/core/installation/includes/upgrade_perform.php index deface8ec5..9a2c86dbec 100644 --- a/core/installation/includes/upgrade_perform.php +++ b/core/installation/includes/upgrade_perform.php @@ -739,13 +739,13 @@ if (count($version)) { DB::getInstance()->update('settings', $version[0]->id, [ 'name' => 'nameless_version', - 'value' => '2.0.1' + 'value' => '2.0.2' ]); DB::getInstance()->delete('settings', ['name', 'version']); } else { DB::getInstance()->insert('settings', [ 'name' => 'nameless_version', - 'value' => '2.0.1' + 'value' => '2.0.2' ]); } diff --git a/custom/panel_templates/Default/template.php b/custom/panel_templates/Default/template.php index 2953494265..4dd5d10576 100644 --- a/custom/panel_templates/Default/template.php +++ b/custom/panel_templates/Default/template.php @@ -24,8 +24,8 @@ public function __construct(Smarty $smarty, Language $language) { parent::__construct( 'Default', // Template name - '2.0.1', // Template version - '2.0.1', // Nameless version template is made for + '2.0.2', // Template version + '2.0.2', // Nameless version template is made for 'Coldfire' // Author, you can use HTML here ); diff --git a/custom/templates/DefaultRevamp/template.php b/custom/templates/DefaultRevamp/template.php index f474f70207..86c012efff 100755 --- a/custom/templates/DefaultRevamp/template.php +++ b/custom/templates/DefaultRevamp/template.php @@ -25,8 +25,8 @@ class DefaultRevamp_Template extends TemplateBase { public function __construct($cache, $smarty, $language, $user, $pages) { $template = [ 'name' => 'DefaultRevamp', - 'version' => '2.0.1', - 'nl_version' => '2.0.1', + 'version' => '2.0.2', + 'nl_version' => '2.0.2', 'author' => 'Xemah', ]; @@ -139,7 +139,7 @@ public function onPageLoad() { $this->addJSFiles([ $this->_template['path'] . 'js/core/core.js?v=202' => [], $this->_template['path'] . 'js/core/user.js' => [], - $this->_template['path'] . 'js/core/pages.js' => [], + $this->_template['path'] . 'js/core/pages.js?v=202' => [], $this->_template['path'] . 'js/scripts.js' => [], ]); diff --git a/modules/Cookie Consent/module.php b/modules/Cookie Consent/module.php index b21e644b78..196a55cd2a 100644 --- a/modules/Cookie Consent/module.php +++ b/modules/Cookie Consent/module.php @@ -20,8 +20,8 @@ public function __construct(Language $language, Language $cookie_language, Pages $name = 'Cookie Consent'; $author = 'Samerton'; - $module_version = '2.0.1'; - $nameless_version = '2.0.1'; + $module_version = '2.0.2'; + $nameless_version = '2.0.2'; parent::__construct($this, $name, $author, $module_version, $nameless_version); diff --git a/modules/Core/module.php b/modules/Core/module.php index 6a1926c083..e4d52b7f70 100644 --- a/modules/Core/module.php +++ b/modules/Core/module.php @@ -21,8 +21,8 @@ public function __construct(Language $language, Pages $pages, User $user, Naviga $name = 'Core'; $author = 'Samerton'; - $module_version = '2.0.1'; - $nameless_version = '2.0.1'; + $module_version = '2.0.2'; + $nameless_version = '2.0.2'; parent::__construct($this, $name, $author, $module_version, $nameless_version); diff --git a/modules/Discord Integration/module.php b/modules/Discord Integration/module.php index ea8a154b95..e4f8c65070 100644 --- a/modules/Discord Integration/module.php +++ b/modules/Discord Integration/module.php @@ -9,8 +9,8 @@ public function __construct(Language $language, Pages $pages, Endpoints $endpoin $name = 'Discord Integration'; $author = 'Aberdeener'; - $module_version = '2.0.1'; - $nameless_version = '2.0.1'; + $module_version = '2.0.2'; + $nameless_version = '2.0.2'; parent::__construct($this, $name, $author, $module_version, $nameless_version); diff --git a/modules/Forum/module.php b/modules/Forum/module.php index 065246864c..dc1d89482d 100644 --- a/modules/Forum/module.php +++ b/modules/Forum/module.php @@ -20,8 +20,8 @@ public function __construct(Language $language, Language $forum_language, Pages $name = 'Forum'; $author = 'Samerton'; - $module_version = '2.0.1'; - $nameless_version = '2.0.1'; + $module_version = '2.0.2'; + $nameless_version = '2.0.2'; parent::__construct($this, $name, $author, $module_version, $nameless_version); diff --git a/package.json b/package.json index d3e63c5fdd..6cbc6c0724 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nameless", - "version": "2.0.1", + "version": "2.0.2", "repository": "https://github.com/NamelessMC/Nameless", "license": "MIT", "private": true,