Forgot Password and Forgot Username for Customer, requested by fiberwan

This commit is contained in:
Ibnu Maksum 2024-09-20 17:07:18 +07:00
parent 686d2a188a
commit 9b1adb15da
No known key found for this signature in database
GPG Key ID: 7FC82848810579E5
6 changed files with 258 additions and 171 deletions

View File

@ -2,6 +2,12 @@
# CHANGELOG
## 2024.9.20
- Forgot Password
- Forgot Username
- Public header template
## 2024.9.13
- Add Selling Mikrotik VPN By @agstrxyz

View File

@ -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);

View File

@ -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' . '<br>';
}
if (Validator::Length($fullname, 36, 2) == false) {
$msg .= 'Full Name should be between 3 to 25 characters' . '<br>';
}
if (!Validator::Length($password, 35, 2)) {
$msg .= 'Password should be between 3 to 35 characters' . '<br>';
}
if (!Validator::Email($email)) {
$msg .= 'Email is not Valid<br>';
}
if ($password != $cpassword) {
$msg .= Lang::T('Passwords does not match') . '<br>';
}
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') . '<br>';
}
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") . ' : <b>' . $otp . '</b>'
);
$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');

View File

@ -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"
}

View File

@ -1,73 +1,99 @@
{include file="user-ui/header-public.tpl"}
<div class="row">
<div class="col-sm-6 col-sm-offset-1">
<div class="panel panel-info">
<div class="panel-heading">{Lang::T('Announcement')}</div>
<div class="panel-body">
{$Announcement = "{$PAGES_PATH}/Announcement.html"}
{if file_exists($Announcement)}
{include file=$Announcement}
{/if}
</div>
<div class="hidden-xs" style="height:100px"></div>
<form action="{$_url}forgot&step={$step+1}" method="post">
<div class="row">
<div class="col-sm-4 col-sm-offset-4">
{if $step == 1}
<div class="panel panel-primary">
<div class="panel-heading">{Lang::T('Verification Code')}</div>
<div class="panel-body">
<div class="form-group">
<div class="input-group">
{if $_c['country_code_phone']!= ''}
<span class="input-group-addon"><i class="glyphicon glyphicon-phone-alt"></i></span>
{else}
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
{/if}
<input type="text" readonly class="form-control" name="username" value="{$username}"
placeholder="{if $_c['country_code_phone']!= ''}{$_c['country_code_phone']} {Lang::T('Phone Number')}{else}{Lang::T('Username')}{/if}">
</div>
</div>
<div class="form-group">
<div class="input-group">
<span class="input-group-addon"><i class="glyphicon glyphicon-asterisk"></i></span>
<input type="text" required class="form-control" id="otp_code"
placeholder="{Lang::T('Verification Code')}" name="otp_code">
</div>
</div>
</div>
<div class="panel-footer">
<button type="submit" class="btn btn-block btn-primary">{Lang::T('Validate')}</button>
<a href="{$_url}forgot&step=-1" class="btn btn-block btn-link">{Lang::T('Cancel')}</a>
</div>
</div>
{elseif $step == 2}
<div class="panel panel-primary">
<div class="panel-heading">{Lang::T('Success')}</div>
<div class="panel-body">
<div class="form-group">
<label>{if $_c['country_code_phone']!= ''}{Lang::T('Phone Number')}{else}{Lang::T('Username')}{/if}</label>
<div class="input-group">
{if $_c['country_code_phone']!= ''}
<span class="input-group-addon"><i class="glyphicon glyphicon-phone-alt"></i></span>
{else}
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
{/if}
<input type="text" readonly class="form-control" name="username" value="{$username}"
placeholder="{if $_c['country_code_phone']!= ''}{$_c['country_code_phone']} {Lang::T('Phone Number')}{else}{Lang::T('Username')}{/if}">
</div>
</div>
<label>{Lang::T('Your Password has been change to')}</label>
<input type="text" readonly class="form-control" value="{$passsword}" onclick="this.select()">
<p class="help-block">
{Lang::T('Use the password to login, and change the password from password change page')}</p>
</div>
<div class="panel-footer">
<a href="{$_url}login" class="btn btn-block btn-primary">{Lang::T('Back')}</a>
</div>
</div>
{elseif $step == 6}
<div class="panel panel-primary">
<div class="panel-heading">{Lang::T('Forgot Username')}</div>
<div class="panel-body">
<label>{Lang::T('Please input your Email or Phone number')}</label>
<input type="text" name="find" class="form-control" required value="">
</div>
<div class="panel-footer">
<button type="submit" class="btn btn-block btn-primary">{Lang::T('Validate')}</button>
<a href="{$_url}forgot" class="btn btn-block btn-link">{Lang::T('Back')}</a>
</div>
</div>
{else}
<div class="panel panel-primary">
<div class="panel-heading">{Lang::T('Forgot Password')}</div>
<div class="panel-body">
<div class="form-group">
<label>{if $_c['country_code_phone']!= ''}{Lang::T('Phone Number')}{else}{Lang::T('Username')}{/if}</label>
<div class="input-group">
{if $_c['country_code_phone']!= ''}
<span class="input-group-addon"><i class="glyphicon glyphicon-phone-alt"></i></span>
{else}
<span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span>
{/if}
<input type="text" class="form-control" name="username" required
placeholder="{if $_c['country_code_phone']!= ''}{$_c['country_code_phone']} {Lang::T('Phone Number')}{else}{Lang::T('Username')}{/if}">
</div>
</div>
</div>
<div class="panel-footer">
<button type="submit" class="btn btn-block btn-primary">{Lang::T('Validate')}</button>
<a href="{$_url}forgot&step=6" class="btn btn-block btn-link">{Lang::T('Forgot Username')}</a>
<a href="{$_url}login" class="btn btn-block btn-link">{Lang::T('Back')}</a>
</div>
</div>
{/if}
</div>
</div>
<div class="col-sm-4">
<div class="panel panel-primary">
<div class="panel-heading">{Lang::T('Log in to Member Panel')}</div>
<div class="panel-body">
<form action="{$_url}login/post" method="post">
<div class="form-group">
<label>{if $_c['country_code_phone']!= ''}{Lang::T('Phone Number')}{else}{Lang::T('Username')}{/if}</label>
<div class="input-group">
{if $_c['country_code_phone']!= ''}
<span class="input-group-addon" id="basic-addon1"><i
class="glyphicon glyphicon-phone-alt"></i></span>
{else}
<span class="input-group-addon" id="basic-addon1"><i
class="glyphicon glyphicon-user"></i></span>
{/if}
<input type="text" class="form-control" name="username"
placeholder="{if $_c['country_code_phone']!= ''}{$_c['country_code_phone']} {Lang::T('Phone Number')}{else}{Lang::T('Username')}{/if}">
</div>
</div>
<div class="form-group">
<label>{Lang::T('Password')}</label>
<div class="input-group">
<span class="input-group-addon" id="basic-addon2"><i
class="glyphicon glyphicon-lock"></i></span>
<input type="password" class="form-control" name="password"
placeholder="{Lang::T('Password')}">
</div>
</div>
<div class="clearfix hidden">
<div class="ui-checkbox ui-checkbox-primary right">
<label>
<input type="checkbox">
<span>Remember me</span>
</label>
</div>
</div>
<div class="btn-group btn-group-justified mb15">
<div class="btn-group">
<a href="{$_url}register" class="btn btn-success">{Lang::T('Register')}</a>
</div>
<div class="btn-group">
<button type="submit" class="btn btn-primary">{Lang::T('Login')}</button>
</div>
</div>
<br>
<center>
<a href="{$_url}forgot" class="btn btn-link">{Lang::T('Forgot Password')}</a>
<br>
<a href="javascript:showPrivacy()">Privacy</a>
&bull;
<a href="javascript:showTaC()">T &amp; C</a>
</center>
</form>
</div>
</div>
</div>
</div>
</form>
{include file="user-ui/footer-public.tpl"}

View File

@ -1,3 +1,3 @@
{
"version": "2024.9.13"
"version": "2024.9.20"
}