Skip to content

Commit

Permalink
PUSH
Browse files Browse the repository at this point in the history
-> Added auth system :)
  • Loading branch information
NaysKutzu committed Nov 25, 2024
1 parent 52d14ab commit 36112ca
Show file tree
Hide file tree
Showing 24 changed files with 496 additions and 100 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"cSpell.words": [
"Swal",
"sweetalert"
]
}
15 changes: 10 additions & 5 deletions backend/app/Api/User/Auth/ForgotPassword.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
use MythicalClient\Config\ConfigInterface;
use MythicalSystems\CloudFlare\CloudFlare;

$router->add('/api/user/auth/forgot', function (): void {
$router->add('/api/user/auth/forgot', function (): void {
$appInstance = App::getInstance(true);
$config = $appInstance->getConfig();

$appInstance->allowOnlyPOST();
/**
/**
* Check if the required fields are set.
*
* @var string
Expand All @@ -20,7 +20,7 @@
$appInstance->BadRequest('Bad Request', ['error_code' => 'MISSING_EMAIL']);
}

/**
/**
* Process the turnstile response.
*
* IF the turnstile is enabled
Expand All @@ -37,10 +37,15 @@
$email = $_POST['email'];

if (User::exists(UserColumns::EMAIL, $email)) {
$appInstance->OK('Email exists', []);

if (User::forgotPassword($email)) {
$appInstance->OK('Successfully sent email', []);
} else {
$appInstance->BadRequest('Failed to send email', ['error_code' => 'FAILED_TO_SEND_EMAIL']);
}

} else {
$appInstance->BadRequest('Email does not exist', ['error_code' => 'EMAIL_DOES_NOT_EXIST']);
}


});
18 changes: 18 additions & 0 deletions backend/app/Api/User/Auth/Login.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@
*/

use MythicalClient\App;
use MythicalClient\Chat\columns\UserColumns;
use MythicalClient\Chat\User;
use MythicalClient\Mail\Mail;
use MythicalSystems\CloudFlare\Turnstile;
use MythicalClient\Config\ConfigInterface;
use MythicalSystems\CloudFlare\CloudFlare;
Expand Down Expand Up @@ -74,6 +76,22 @@
$login = User::login($login, $password);

if ($login) {
if (User::getInfo($_COOKIE['user_token'],UserColumns::VERIFIED, false) == "false") {
if (Mail::isEnabled() == true) {
setcookie('user_token', '', time() - 123600, '/');
$appInstance->BadRequest('Account not verified', ['error_code' => 'ACCOUNT_NOT_VERIFIED']);
}
}

if (User::getInfo($_COOKIE['user_token'],UserColumns::BANNED, false) != "NO") {
setcookie('user_token', '', time() - 123600, '/');
$appInstance->BadRequest('Account is banned', ['error_code' => 'ACCOUNT_BANNED']);
}

if (User::getInfo($_COOKIE['user_token'],UserColumns::DELETED, false) == "true") {
setcookie('user_token', '', time() - 123600, '/');
$appInstance->BadRequest('Account is deleted', ['error_code' => 'ACCOUNT_DELETED']);
}
$appInstance->OK('Successfully logged in', []);
} else {
$appInstance->BadRequest('Invalid login credentials', ['error_code' => 'INVALID_CREDENTIALS']);
Expand Down
93 changes: 93 additions & 0 deletions backend/app/Api/User/Auth/ResetPassword.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php
use MythicalClient\App;
use MythicalClient\Chat\columns\EmailVerificationColumns;
use MythicalClient\Chat\columns\UserColumns;
use MythicalClient\Chat\User;
use MythicalClient\Chat\Verification;
use MythicalSystems\CloudFlare\Turnstile;
use MythicalClient\Config\ConfigInterface;
use MythicalSystems\CloudFlare\CloudFlare;
use MythicalSystems\Utils\XChaCha20;

$router->get("/api/user/auth/reset", function (): void {
App::init();
$appInstance = App::getInstance(true);
$config = $appInstance->getConfig();

$appInstance->allowOnlyGET();

if (isset($_GET['code']) && $_GET['code'] != '') {
$code = $_GET['code'];

if (Verification::verify($code, EmailVerificationColumns::$type_password)) {
$appInstance->OK('Code is valid', ['reset_code' => $code]);
} else {
$appInstance->BadRequest('Bad Request', ['error_code' => 'INVALID_CODE']);
}
} else {
$appInstance->BadRequest('Bad Request', ['error_code' => 'MISSING_CODE']);
}
});

$router->post("/api/user/auth/reset", function (): void {
App::init();
$appInstance = App::getInstance(true);
$config = $appInstance->getConfig();

$appInstance->allowOnlyPOST();

if (!isset($_POST['email_code']) || $_POST['email_code'] == '') {
$appInstance->BadRequest('Bad Request', ['error_code' => 'MISSING_CODE']);
}

if (!isset($_POST['password']) || $_POST['password'] == '') {
$appInstance->BadRequest('Bad Request', ['error_code' => 'MISSING_PASSWORD']);
}

if (!isset($_POST['confirmPassword']) || $_POST['confirmPassword'] == '') {
$appInstance->BadRequest('Bad Request', ['error_code' => 'MISSING_PASSWORD_CONFIRM']);
}

if ($_POST['password'] != $_POST['confirmPassword']) {
$appInstance->BadRequest('Bad Request', ['error_code' => 'PASSWORDS_DO_NOT_MATCH']);
}

$code = $_POST['email_code'];
$password = $_POST['password'];

/**
* Process the turnstile response.
*
* IF the turnstile is enabled
*/
if ($appInstance->getConfig()->getSetting(ConfigInterface::TURNSTILE_ENABLED, 'false') == 'true') {
if (!isset($_POST['turnstileResponse']) || $_POST['turnstileResponse'] == '') {
$appInstance->BadRequest('Bad Request', ['error_code' => 'TURNSTILE_FAILED']);
}
$cfTurnstileResponse = $_POST['turnstileResponse'];
if (!Turnstile::validate($cfTurnstileResponse, CloudFlare::getRealUserIP(), $config->getSetting(ConfigInterface::TURNSTILE_KEY_PRIV, 'XXXX'))) {
$appInstance->BadRequest('Invalid TurnStile Key', ['error_code' => 'TURNSTILE_FAILED']);
}
}

if (Verification::verify($code, EmailVerificationColumns::$type_password)) {
$uuid = Verification::getUserUUID($code);
if ($uuid == null || $uuid == '') {
$appInstance->BadRequest('Bad Request', ['error_code' => 'INVALID_CODE']);
}
$userToken = User::getTokenFromUUID($uuid);
if ($userToken == null || $userToken == '') {
$appInstance->BadRequest('Bad Request', ['error_code' => 'INVALID_CODE']);
}

if (User::updateInfo($userToken, UserColumns::PASSWORD, $password, true) == true) {
Verification::delete($code);
$appInstance->OK('Password has been reset', []);
} else {
$appInstance->BadRequest('Failed to reset password', ['error_code' => 'FAILED_TO_RESET_PASSWORD']);
}

} else {
$appInstance->BadRequest('Bad Request', ['error_code' => 'INVALID_CODE']);
}
});
4 changes: 2 additions & 2 deletions backend/app/App.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ public function __construct(bool $softBoot)
self::InternalServerError($e->getMessage(), null);
}

if ($this->getConfig()->getSetting('app:url', null) == null) {
$this->getConfig()->setSetting('app:url', $_SERVER['HTTP_HOST']);
if ($this->getConfig()->getSetting('app_url', null) == null) {
$this->getConfig()->setSetting('app_url', $_SERVER['HTTP_HOST']);
}

new PluginCompiler();
Expand Down
41 changes: 36 additions & 5 deletions backend/app/Chat/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
use Gravatar\Gravatar;
use MythicalClient\App;
use MythicalClient\Mail\Mail;
use MythicalClient\Mail\templates\ResetPassword;
use MythicalClient\Mail\templates\Verify;
use MythicalClient\Mail\templates\NewLogin;
use MythicalClient\Chat\columns\UserColumns;
Expand Down Expand Up @@ -131,6 +132,40 @@ public static function register(string $username, string $password, string $emai
throw new \Exception('Failed to register user: ' . $e->getMessage());
}
}
/**
*
* Forgot password logic.
*
* @param string $email The email of the user
*
* @return bool If the email was sent
*/
public static function forgotPassword(string $email) : bool {
try {
$con = self::getPdoConnection();
$stmt = $con->prepare('SELECT token, uuid FROM ' . self::TABLE_NAME . ' WHERE email = :email');
$stmt->bindParam(':email', $email);
$stmt->execute();
$user = $stmt->fetch(\PDO::FETCH_ASSOC);

if ($user) {
if (Mail::isEnabled()) {
try {
$verify_token = base64_encode(random_bytes(16));
Verification::add($verify_token, $user['uuid'], EmailVerificationColumns::$type_password);
ResetPassword::sendMail($user['uuid'], $verify_token);
} catch (\Exception $e) {
App::getInstance(true)->getLogger()->error('Failed to send email: ' . $e->getMessage());
}
return true;
}
return false;
}
return false;
} catch (\Exception $e) {
return false;
}
}

/**
* Login the user.
Expand Down Expand Up @@ -159,16 +194,12 @@ public static function login(string $login, string $password): bool
App::getInstance(true)->getLogger()->error('Failed to send email: ' . $e->getMessage());
}
}

setcookie('user_token', $user['token'], time() + 3600, '/');
return true;
}

return false;

}

return false;

} catch (\Exception $e) {
return false;
}
Expand Down
11 changes: 4 additions & 7 deletions backend/app/Chat/Verification.php
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,12 @@ public static function verify(string $code, EmailVerificationColumns|string $typ
$query = $conn->prepare('SELECT * FROM ' . self::TABLE_NAME . ' WHERE code = :code AND type = :type');
$query->execute(['code' => $code, 'type' => $type]);
$result = $query->fetch();
if ($result === false) {
if (empty($result)) {
return false;
}

return true;

} catch (\Exception $e) {
App::getInstance(softBoot: true)->getLogger()->error('(' . APP_SOURCECODE_DIR . '/Chat/Verification.php) Failed to verify code table: ' . $e->getMessage());

return false;
}
}
Expand Down Expand Up @@ -112,16 +109,16 @@ public static function delete(string $code): void
/**
* Get the user's UUID from a code.
*
* @param string $uuid The code to get the user's UUID from
* @param string $code The code to get the user's UUID from
*
* @return string Get the user uuid
*/
public static function getUserUUID(string $uuid): string
public static function getUserUUID(string $code): string
{
try {
$conn = self::getPdoConnection();
$query = $conn->prepare('SELECT * FROM ' . self::TABLE_NAME . ' WHERE code = :code');
$query->execute(['code' => $uuid]);
$query->execute(['code' => $code]);
$result = $query->fetch();
if ($result === false) {
return '';
Expand Down
8 changes: 8 additions & 0 deletions backend/storage/.docker.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
DATABASE_HOST=mythicalclient_database
DATABASE_PORT=3306
DATABASE_USER=mythical
DATABASE_PASSWORD="Pizza2007!"
DATABASE_DATABASE=mythicalclient
DATABASE_ENCRYPTION=xchacha20
DATABASE_ENCRYPTION_KEY="Wk2nAV0QHORNEg8/ZQQBeqdW4p2G8lp747RpP6T9yxs="
REDIS_PASSWORD="eufefwefwefw"
6 changes: 3 additions & 3 deletions backend/storage/.env
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
DATABASE_HOST=mythicalclient_database
DATABASE_HOST=127.0.0.1
DATABASE_PORT=3306
DATABASE_USER=mythical
DATABASE_PASSWORD="Pizza2007!"
DATABASE_PASSWORD=
DATABASE_DATABASE=mythicalclient
DATABASE_ENCRYPTION=xchacha20
DATABASE_ENCRYPTION_KEY="Wk2nAV0QHORNEg8/ZQQBeqdW4p2G8lp747RpP6T9yxs="
DATABASE_ENCRYPTION_KEY=zKZ7//AocUD2wCuzjW5rdTbb8FvGBgKTZ8iCATslZ/8=
REDIS_PASSWORD="eufefwefwefw"
4 changes: 4 additions & 0 deletions frontend/env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ declare module '*.vue' {
const component: DefineComponent<{}, {}, any>;
export default component;
}

declare module '@vueuse/sound' {
export function useSound(url: string): { play: () => void };
}
13 changes: 7 additions & 6 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,16 @@
"format": "prettier --write src/"
},
"dependencies": {
"vue": "^3.5.12",
"vue-router": "^4.4.5",
"@tanstack/vue-table": "^8.20.5",
"@vueuse/sound": "^2.0.1",
"date-fns": "^4.1.0",
"lucide-vue": "^0.454.0",
"lucide-vue-next": "^0.454.0",
"vue": "^3.5.12",
"vue-i18n": "^10.0.4",
"vue-router": "^4.4.5",
"vue-sweetalert2": "^5.0.11",
"vue-turnstile": "^1.0.11",
"lucide-vue-next": "^0.454.0",
"date-fns": "^4.1.0",
"@tanstack/vue-table": "^8.20.5"
"vue-turnstile": "^1.0.11"
},
"devDependencies": {
"@tsconfig/node22": "^22.0.0",
Expand Down
Binary file added frontend/src/assets/sounds/error.mp3
Binary file not shown.
Binary file added frontend/src/assets/sounds/info.mp3
Binary file not shown.
Binary file added frontend/src/assets/sounds/success.mp3
Binary file not shown.
Loading

0 comments on commit 36112ca

Please sign in to comment.