diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8f9e0862..8b873a0b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,12 @@
# CHANGELOG
+## 2024.9.20
+
+- Forgot Password
+- Forgot Username
+- Public header template
+
## 2024.9.13
- Add Selling Mikrotik VPN By @agstrxyz
diff --git a/system/autoload/Message.php b/system/autoload/Message.php
index cdc04525..1f880f03 100644
--- a/system/autoload/Message.php
+++ b/system/autoload/Message.php
@@ -217,7 +217,7 @@ class Message
) {
if ($via == 'sms') {
Message::sendSMS($phone, $msg);
- } else if ($config['user_notification_payment'] == 'email') {
+ } else if ($via == 'email') {
self::sendEmail($cust['email'], '[' . $config['CompanyName'] . '] ' . Lang::T("Balance Notification"), $msg);
} else if ($via == 'wa') {
Message::sendWhatsapp($phone, $msg);
diff --git a/system/controllers/forgot.php b/system/controllers/forgot.php
index 4b711dfe..57b7c680 100644
--- a/system/controllers/forgot.php
+++ b/system/controllers/forgot.php
@@ -4,111 +4,165 @@
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
* by https://t.me/ibnux
**/
-$do = '';
-if (isset($routes['1'])) {
- $do = $routes['1'];
-}
-
+$step = _req('step', 0);
$otpPath = $CACHE_PATH . File::pathFixer('/forgot/');
-switch ($do) {
- case 'post':
- $otp_code = _post('otp_code');
- $username = alphanumeric(_post('username'), "+_.@-");
- $email = _post('email');
- $fullname = _post('fullname');
- $password = _post('password');
- $cpassword = _post('cpassword');
- $address = _post('address');
- if (!empty($config['sms_url']) && $_c['allow_phone_otp'] == 'yes') {
- $phonenumber = Lang::phoneFormat($username);
- $username = $phonenumber;
- } else if (strlen($username) < 21) {
- $phonenumber = $username;
- }
- $msg = '';
- if (Validator::Length($username, 35, 2) == false) {
- $msg .= 'Username should be between 3 to 55 characters' . '
';
- }
- if (Validator::Length($fullname, 36, 2) == false) {
- $msg .= 'Full Name should be between 3 to 25 characters' . '
';
- }
- if (!Validator::Length($password, 35, 2)) {
- $msg .= 'Password should be between 3 to 35 characters' . '
';
- }
- if (!Validator::Email($email)) {
- $msg .= 'Email is not Valid
';
- }
- if ($password != $cpassword) {
- $msg .= Lang::T('Passwords does not match') . '
';
- }
+if ($step == '-1') {
+ $_COOKIE['forgot_username'] = '';
+ setcookie('forgot_username', '', time() - 3600, '/');
+ $step = 0;
+}
- if (!empty($config['sms_url']) && $_c['allow_phone_otp'] == 'yes') {
+if (!empty($_COOKIE['forgot_username']) && in_array($step, [0, 1])) {
+ $step = 1;
+ $_POST['username'] = $_COOKIE['forgot_username'];
+}
+
+if ($step == 1) {
+ $username = _post('username');
+ if (!empty($username)) {
+ $ui->assign('username', $username);
+ if (!file_exists($otpPath)) {
+ mkdir($otpPath);
+ }
+ setcookie('forgot_username', $username, time() + 3600, '/');
+ $user = ORM::for_table('tbl_customers')->selects(['phonenumber', 'email'])->where('username', $username)->find_one();
+ if ($user) {
$otpPath .= sha1($username . $db_pass) . ".txt";
- run_hook('validate_otp'); #HOOK
- //expired 10 minutes
- if (file_exists($otpPath) && time() - filemtime($otpPath) > 1200) {
- unlink($otpPath);
- r2(U . 'register', 's', 'Verification code expired');
- } else if (file_exists($otpPath)) {
- $code = file_get_contents($otpPath);
- if ($code != $otp_code) {
- $ui->assign('username', $username);
- $ui->assign('fullname', $fullname);
- $ui->assign('address', $address);
- $ui->assign('email', $email);
- $ui->assign('phonenumber', $phonenumber);
- $ui->assign('notify', 'Wrong Verification code');
- $ui->assign('notify_t', 'd');
- $ui->display('user-ui/register-otp.tpl');
- exit();
- } else {
- unlink($otpPath);
+ if (file_exists($otpPath) && time() - filemtime($otpPath) < 600) {
+ $ui->assign('notify_t', 's');
+ $ui->assign('notify', Lang::T("If your Username is found, Verification Code has been Sent to Your Phone/Email/Whatsapp"));
+ } else {
+ $via = $config['user_notification_reminder'];
+ if ($via == 'email') {
+ $via = 'sms';
}
- } else {
- r2(U . 'register', 's', 'No Verification code');
- }
- }
- $d = ORM::for_table('tbl_customers')->where('username', $username)->find_one();
- if ($d) {
- $msg .= Lang::T('Account already axist') . '
';
- }
- if ($msg == '') {
- run_hook('register_user'); #HOOK
- $d = ORM::for_table('tbl_customers')->create();
- $d->username = alphanumeric($username, "+_.@-");
- $d->password = $password;
- $d->fullname = $fullname;
- $d->address = $address;
- $d->email = $email;
- $d->phonenumber = $phonenumber;
- if ($d->save()) {
- $user = $d->id();
- r2(U . 'login', 's', Lang::T('Register Success! You can login now'));
- } else {
- $ui->assign('username', $username);
- $ui->assign('fullname', $fullname);
- $ui->assign('address', $address);
- $ui->assign('email', $email);
- $ui->assign('phonenumber', $phonenumber);
- $ui->assign('notify', 'Failed to register');
- $ui->assign('notify_t', 'd');
- run_hook('view_otp_register'); #HOOK
- $ui->display('user-ui/register-rotp.tpl');
+ $otp = mt_rand(100000, 999999);
+ file_put_contents($otpPath, $otp);
+ if ($via == 'sms') {
+ Message::sendSMS($user['phonenumber'], $config['CompanyName'] . " C0de: $otp");
+ } else {
+ Message::sendWhatsapp($user['phonenumber'], $config['CompanyName'] . " C0de: $otp");
+ }
+ Message::sendEmail(
+ $user['email'],
+ $config['CompanyName'] . Lang::T("Your Verification Code") . ' : ' . $otp,
+ Lang::T("Your Verification Code") . ' : ' . $otp . ''
+ );
+ $ui->assign('notify_t', 's');
+ $ui->assign('notify', Lang::T("If your Username is found, Verification Code has been Sent to Your Phone/Email/Whatsapp"));
}
} else {
- $ui->assign('username', $username);
- $ui->assign('fullname', $fullname);
- $ui->assign('address', $address);
- $ui->assign('email', $email);
- $ui->assign('phonenumber', $phonenumber);
- $ui->assign('notify', $msg);
- $ui->assign('notify_t', 'd');
- $ui->display('user-ui/register.tpl');
+ // Username not found
+ $ui->assign('notify_t', 's');
+ $ui->assign('notify', Lang::T("If your Username is found, Verification Code has been Sent to Your Phone/Email/Whatsapp") . ".");
}
- break;
-
- default:
- $ui->display('user-ui/forgot.tpl');
- break;
+ } else {
+ $step = 0;
+ }
+} else if ($step == 2) {
+ $username = _post('username');
+ $otp_code = _post('otp_code');
+ if (!empty($username) && !empty($otp_code)) {
+ $otpPath .= sha1($username . $db_pass) . ".txt";
+ if (file_exists($otpPath) && time() - filemtime($otpPath) <= 600) {
+ $otp = file_get_contents($otpPath);
+ if ($otp == $otp_code) {
+ $pass = mt_rand(10000, 99999);
+ $user = ORM::for_table('tbl_customers')->where('username', $username)->find_one();
+ $user->password = $pass;
+ $user->save();
+ $ui->assign('username', $username);
+ $ui->assign('passsword', $pass);
+ $ui->assign('notify_t', 's');
+ $ui->assign('notify', Lang::T("Verification Code Valid"));
+ if (file_exists($otpPath)) {
+ unlink($otpPath);
+ }
+ setcookie('forgot_username', '', time() - 3600, '/');
+ } else {
+ r2(U . 'forgot&step=1', 'e', Lang::T('Invalid Username or Verification Code'));
+ }
+ } else {
+ if (file_exists($otpPath)) {
+ unlink($otpPath);
+ }
+ r2(U . 'forgot&step=1', 'e', Lang::T('Invalid Username or Verification Code'));
+ }
+ } else {
+ r2(U . 'forgot&step=1', 'e', Lang::T('Invalid Username or Verification Code'));
+ }
+} else if ($step == 7) {
+ $find = _post('find');
+ $step = 6;
+ if (!empty($find)) {
+ $via = $config['user_notification_reminder'];
+ if ($via == 'email') {
+ $via = 'sms';
+ }
+ if (!file_exists($otpPath)) {
+ mkdir($otpPath);
+ }
+ $otpPath .= sha1($find . $db_pass) . ".txt";
+ $users = ORM::for_table('tbl_customers')->selects(['username', 'phonenumber', 'email'])->where('phonenumber', $find)->find_array();
+ if ($users) {
+ // prevent flooding only can request every 10 minutes
+ if (!file_exists($otpPath) || (file_exists($otpPath) && time() - filemtime($otpPath) >= 600)) {
+ $usernames = implode(", ", array_column($users, 'username'));
+ if ($via == 'sms') {
+ Message::sendSMS($find, Lang::T("Your username for") . ' ' . $config['CompanyName'] . "\n" . $usernames);
+ } else {
+ Message::sendWhatsapp($find, Lang::T("Your username for") . ' ' . $config['CompanyName'] . "\n" . $usernames);
+ }
+ file_put_contents($otpPath, time());
+ }
+ $ui->assign('notify_t', 's');
+ $ui->assign('notify', Lang::T("Usernames have been sent to your phone/Whatsapp") . " $find");
+ $step = 0;
+ } else {
+ $users = ORM::for_table('tbl_customers')->selects(['username', 'phonenumber', 'email'])->where('email', $find)->find_array();
+ if ($users) {
+ // prevent flooding only can request every 10 minutes
+ if (!file_exists($otpPath) || (file_exists($otpPath) && time() - filemtime($otpPath) >= 600)) {
+ $usernames = implode(", ", array_column($users, 'username'));
+ $phones = [];
+ foreach ($users as $user) {
+ if (!in_array($user['phonenumber'], $phones)) {
+ if ($via == 'sms') {
+ Message::sendSMS($user['phonenumber'], Lang::T("Your username for") . ' ' . $config['CompanyName'] . "\n" . $usernames);
+ } else {
+ Message::sendWhatsapp($user['phonenumber'], Lang::T("Your username for") . ' ' . $config['CompanyName'] . "\n" . $usernames);
+ }
+ $phones[] = $user['phonenumber'];
+ }
+ }
+ Message::sendEmail(
+ $user['email'],
+ Lang::T("Your username for") . ' ' . $config['CompanyName'],
+ Lang::T("Your username for") . ' ' . $config['CompanyName'] . "\n" . $usernames
+ );
+ file_put_contents($otpPath, time());
+ }
+ $ui->assign('notify_t', 's');
+ $ui->assign('notify', Lang::T("Usernames have been sent to your phone/Whatsapp/Email"));
+ $step = 0;
+ } else {
+ $ui->assign('notify_t', 'e');
+ $ui->assign('notify', Lang::T("No data found"));
+ }
+ }
+ }
}
+
+// delete old files
+$pth = $CACHE_PATH . File::pathFixer('/forgot/');
+$fs = scandir($pth);
+foreach ($fs as $file) {
+ if(is_file($pth.$file) && time() - filemtime($pth.$file) > 3600) {
+ unlink($pth.$file);
+ }
+}
+
+$ui->assign('step', $step);
+$ui->assign('_title', Lang::T('Forgot Password'));
+$ui->display('user-ui/forgot.tpl');
diff --git a/system/lan/english.json b/system/lan/english.json
index b1e78a05..81315026 100644
--- a/system/lan/english.json
+++ b/system/lan/english.json
@@ -724,5 +724,6 @@
"Mail_Reply_To": "Mail Reply To",
"Customer_will_reply_email_to_this_address__empty_if_you_want_to_use_From_Address": "Customer will reply email to this address, empty if you want to use From Address",
"You_will_get_Payment_and_Error_notification": "You will get Payment and Error notification",
- "Languge_set_to_english": "Bahasa diatur ke bahasa Inggris"
+ "Languge_set_to_english": "Bahasa diatur ke bahasa Inggris",
+ "Forgot_Password": "Forgot Password"
}
\ No newline at end of file
diff --git a/ui/ui/user-ui/forgot.tpl b/ui/ui/user-ui/forgot.tpl
index 2289533c..b905a6e9 100644
--- a/ui/ui/user-ui/forgot.tpl
+++ b/ui/ui/user-ui/forgot.tpl
@@ -1,73 +1,99 @@
{include file="user-ui/header-public.tpl"}
-