Merge branch 'Development' of https://github.com/gerandonk/phpnuxbill into Development
This commit is contained in:
commit
1a65c04666
@ -2,6 +2,13 @@
|
|||||||
|
|
||||||
# CHANGELOG
|
# CHANGELOG
|
||||||
|
|
||||||
|
## 2024.9.13
|
||||||
|
|
||||||
|
- Add Selling Mikrotik VPN By @agstrxyz
|
||||||
|
- Theme Redesign by @Focuslinkstech
|
||||||
|
- Fix That and this
|
||||||
|
|
||||||
|
|
||||||
## 2024.8.28
|
## 2024.8.28
|
||||||
|
|
||||||
- add Router Status Offline/Online by @Focuslinkstech
|
- add Router Status Offline/Online by @Focuslinkstech
|
||||||
|
@ -13,25 +13,27 @@ class Admin
|
|||||||
{
|
{
|
||||||
global $db_pass, $config;
|
global $db_pass, $config;
|
||||||
$enable_session_timeout = $config['enable_session_timeout'];
|
$enable_session_timeout = $config['enable_session_timeout'];
|
||||||
if ($enable_session_timeout) {
|
$session_timeout_duration = $config['session_timeout_duration'] ? intval($config['session_timeout_duration'] * 60) : intval(60 * 60); // Convert minutes to seconds
|
||||||
$timeout = 60;
|
|
||||||
if ($config['session_timeout_duration']) {
|
|
||||||
$timeout = intval($config['session_timeout_duration']);
|
|
||||||
}
|
|
||||||
$session_timeout_duration = $timeout * 60; // Convert minutes to seconds
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isset($_SESSION['aid']) && isset($_SESSION['aid_expiration']) && $_SESSION['aid_expiration'] > time()) {
|
// Check if the session is active and valid
|
||||||
|
if (isset($_SESSION['aid']) && isset($_SESSION['aid_expiration'])) {
|
||||||
|
if ($_SESSION['aid_expiration'] > time()) {
|
||||||
|
if ($enable_session_timeout) {
|
||||||
|
$_SESSION['aid_expiration'] = time() + $session_timeout_duration;
|
||||||
|
}
|
||||||
return $_SESSION['aid'];
|
return $_SESSION['aid'];
|
||||||
} elseif ($enable_session_timeout && isset($_SESSION['aid']) && isset($_SESSION['aid_expiration']) && $_SESSION['aid_expiration'] <= time()) {
|
}
|
||||||
|
// Session expired, log out the user
|
||||||
|
elseif ($enable_session_timeout && $_SESSION['aid_expiration'] <= time()) {
|
||||||
self::removeCookie();
|
self::removeCookie();
|
||||||
session_destroy();
|
session_destroy();
|
||||||
_alert(Lang::T('Session has expired. Please log in again.'), 'danger', "admin");
|
_alert(Lang::T('Session has expired. Please log in again.'), 'danger', "admin");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// Check if cookie is set and valid
|
}
|
||||||
|
|
||||||
|
// Check if the cookie is set and valid
|
||||||
elseif (isset($_COOKIE['aid'])) {
|
elseif (isset($_COOKIE['aid'])) {
|
||||||
// id.time.sha1
|
|
||||||
$tmp = explode('.', $_COOKIE['aid']);
|
$tmp = explode('.', $_COOKIE['aid']);
|
||||||
if (sha1($tmp[0] . '.' . $tmp[1] . '.' . $db_pass) == $tmp[2]) {
|
if (sha1($tmp[0] . '.' . $tmp[1] . '.' . $db_pass) == $tmp[2]) {
|
||||||
if (time() - $tmp[1] < 86400 * 7) {
|
if (time() - $tmp[1] < 86400 * 7) {
|
||||||
|
@ -154,6 +154,9 @@ class Message
|
|||||||
$mail->Body = $body;
|
$mail->Body = $body;
|
||||||
}
|
}
|
||||||
$mail->send();
|
$mail->send();
|
||||||
|
if (!$mail->send()) {
|
||||||
|
_log(Lang::T("Email not sent, Mailer Error: ") . $mail->ErrorInfo);
|
||||||
|
}
|
||||||
|
|
||||||
//<p style="font-family: Helvetica, sans-serif; font-size: 16px; font-weight: normal; margin: 0; margin-bottom: 16px;">
|
//<p style="font-family: Helvetica, sans-serif; font-size: 16px; font-weight: normal; margin: 0; margin-bottom: 16px;">
|
||||||
}
|
}
|
||||||
@ -201,10 +204,10 @@ class Message
|
|||||||
return "$via: $msg";
|
return "$via: $msg";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function sendBalanceNotification($cust, $balance, $balance_now, $message, $via)
|
public static function sendBalanceNotification($cust, $target, $balance, $balance_now, $message, $via)
|
||||||
{
|
{
|
||||||
global $config;
|
global $config;
|
||||||
$msg = str_replace('[[name]]', $cust['fullname'] . ' (' . $cust['username'] . ')', $message);
|
$msg = str_replace('[[name]]', $target['fullname'] . ' (' . $target['username'] . ')', $message);
|
||||||
$msg = str_replace('[[current_balance]]', Lang::moneyFormat($balance_now), $msg);
|
$msg = str_replace('[[current_balance]]', Lang::moneyFormat($balance_now), $msg);
|
||||||
$msg = str_replace('[[balance]]', Lang::moneyFormat($balance), $msg);
|
$msg = str_replace('[[balance]]', Lang::moneyFormat($balance), $msg);
|
||||||
$phone = $cust['phonenumber'];
|
$phone = $cust['phonenumber'];
|
||||||
@ -219,6 +222,7 @@ class Message
|
|||||||
} else if ($via == 'wa') {
|
} else if ($via == 'wa') {
|
||||||
Message::sendWhatsapp($phone, $msg);
|
Message::sendWhatsapp($phone, $msg);
|
||||||
}
|
}
|
||||||
|
self::addToInbox($cust['id'], Lang::T('Balance Notification'), $msg);
|
||||||
}
|
}
|
||||||
return "$via: $msg";
|
return "$via: $msg";
|
||||||
}
|
}
|
||||||
@ -258,4 +262,15 @@ class Message
|
|||||||
Message::sendWhatsapp($cust['phonenumber'], $textInvoice);
|
Message::sendWhatsapp($cust['phonenumber'], $textInvoice);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static function addToInbox($to_customer_id, $subject, $body, $from = 'System'){
|
||||||
|
$v = ORM::for_table('tbl_customers_inbox')->create();
|
||||||
|
$v->from = $from;
|
||||||
|
$v->customer_id = $to_customer_id;
|
||||||
|
$v->subject = $subject;
|
||||||
|
$v->date_created = date('Y-m-d H:i:s');
|
||||||
|
$v->body = nl2br($body);
|
||||||
|
$v->save();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -673,10 +673,10 @@ switch ($action) {
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
run_hook('list_customers'); #HOOK
|
run_hook('list_customers'); #HOOK
|
||||||
$search = _post('search');
|
$search = _req('search');
|
||||||
$order = _post('order', 'username');
|
$order = _req('order', 'username');
|
||||||
$filter = _post('filter', 'Active');
|
$filter = _req('filter', 'Active');
|
||||||
$orderby = _post('orderby', 'asc');
|
$orderby = _req('orderby', 'asc');
|
||||||
$order_pos = [
|
$order_pos = [
|
||||||
'username' => 0,
|
'username' => 0,
|
||||||
'created_at' => 8,
|
'created_at' => 8,
|
||||||
|
@ -214,6 +214,12 @@ if ($config['router_check']) {
|
|||||||
$ui->assign('routeroffs', $routeroffs);
|
$ui->assign('routeroffs', $routeroffs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$timestampFile = "$UPLOAD_PATH/cron_last_run.txt";
|
||||||
|
if (file_exists($timestampFile)) {
|
||||||
|
$lastRunTime = file_get_contents($timestampFile);
|
||||||
|
$ui->assign('run_date', date('Y-m-d h:i:s A', $lastRunTime));
|
||||||
|
}
|
||||||
|
|
||||||
// Assign the monthly sales data to Smarty
|
// Assign the monthly sales data to Smarty
|
||||||
$ui->assign('start_date', $start_date);
|
$ui->assign('start_date', $start_date);
|
||||||
$ui->assign('current_date', $current_date);
|
$ui->assign('current_date', $current_date);
|
||||||
|
@ -71,8 +71,9 @@ if (_post('send') == 'balance') {
|
|||||||
$d->pg_url_payment = 'balance';
|
$d->pg_url_payment = 'balance';
|
||||||
$d->status = 2;
|
$d->status = 2;
|
||||||
$d->save();
|
$d->save();
|
||||||
Message::sendBalanceNotification($user, $balance, ($user['balance'] - $balance), Lang::getNotifText('balance_send'), $config['user_notification_payment']);
|
//
|
||||||
Message::sendBalanceNotification($target, $balance, ($target['balance'] + $balance), Lang::getNotifText('balance_received'), $config['user_notification_payment']);
|
Message::sendBalanceNotification($user, $target, $balance, ($user['balance'] - $balance), Lang::getNotifText('balance_send'), $config['user_notification_payment']);
|
||||||
|
Message::sendBalanceNotification($target, $user, $balance, ($target['balance'] + $balance), Lang::getNotifText('balance_received'), $config['user_notification_payment']);
|
||||||
Message::sendTelegram("#u$user[username] send balance to #u$target[username] \n" . Lang::moneyFormat($balance));
|
Message::sendTelegram("#u$user[username] send balance to #u$target[username] \n" . Lang::moneyFormat($balance));
|
||||||
r2(U . 'home', 's', Lang::T('Sending balance success'));
|
r2(U . 'home', 's', Lang::T('Sending balance success'));
|
||||||
}
|
}
|
||||||
@ -317,6 +318,14 @@ if (!empty($_SESSION['nux-mac']) && !empty($_SESSION['nux-ip'] && !empty($_SESSI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$tcf = ORM::for_table('tbl_customers_fields')
|
||||||
|
->where('customer_id', $user['id'])
|
||||||
|
->find_many();
|
||||||
|
$vpn = ORM::for_table('tbl_port_pool')
|
||||||
|
->find_one();
|
||||||
|
$ui->assign('cf', $tcf);
|
||||||
|
$ui->assign('vpn', $vpn);
|
||||||
|
|
||||||
$ui->assign('unpaid', ORM::for_table('tbl_payment_gateway')
|
$ui->assign('unpaid', ORM::for_table('tbl_payment_gateway')
|
||||||
->where('username', $user['username'])
|
->where('username', $user['username'])
|
||||||
->where('status', 1)
|
->where('status', 1)
|
||||||
|
@ -113,12 +113,19 @@ switch ($action) {
|
|||||||
->where('type', 'Hotspot')
|
->where('type', 'Hotspot')
|
||||||
->where('prepaid', 'yes')
|
->where('prepaid', 'yes')
|
||||||
->find_many();
|
->find_many();
|
||||||
|
$plans_vpn = ORM::for_table('tbl_plans')
|
||||||
|
->where('plan_type', $account_type)
|
||||||
|
->where('enabled', '1')->where('is_radius', 0)
|
||||||
|
->where('type', 'VPN')
|
||||||
|
->where('prepaid', 'yes')
|
||||||
|
->find_many();
|
||||||
}
|
}
|
||||||
$ui->assign('routers', $routers);
|
$ui->assign('routers', $routers);
|
||||||
$ui->assign('radius_pppoe', $radius_pppoe);
|
$ui->assign('radius_pppoe', $radius_pppoe);
|
||||||
$ui->assign('radius_hotspot', $radius_hotspot);
|
$ui->assign('radius_hotspot', $radius_hotspot);
|
||||||
$ui->assign('plans_pppoe', $plans_pppoe);
|
$ui->assign('plans_pppoe', $plans_pppoe);
|
||||||
$ui->assign('plans_hotspot', $plans_hotspot);
|
$ui->assign('plans_hotspot', $plans_hotspot);
|
||||||
|
$ui->assign('plans_vpn', $plans_vpn);
|
||||||
run_hook('customer_view_order_plan'); #HOOK
|
run_hook('customer_view_order_plan'); #HOOK
|
||||||
$ui->display('user-ui/orderPlan.tpl');
|
$ui->display('user-ui/orderPlan.tpl');
|
||||||
break;
|
break;
|
||||||
|
@ -147,6 +147,132 @@ switch ($action) {
|
|||||||
} else {
|
} else {
|
||||||
r2(U . 'pool/edit/' . $id, 'e', $msg);
|
r2(U . 'pool/edit/' . $id, 'e', $msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'port':
|
||||||
|
$ui->assign('xfooter', '<script type="text/javascript" src="ui/lib/c/pool.js"></script>');
|
||||||
|
|
||||||
|
$name = _post('name');
|
||||||
|
if ($name != '') {
|
||||||
|
$query = ORM::for_table('tbl_port_pool')->where_like('pool_name', '%' . $name . '%')->order_by_desc('id');
|
||||||
|
$d = Paginator::findMany($query, ['name' => $name]);
|
||||||
|
} else {
|
||||||
|
$query = ORM::for_table('tbl_port_pool')->order_by_desc('id');
|
||||||
|
$d = Paginator::findMany($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
$ui->assign('d', $d);
|
||||||
|
run_hook('view_port'); #HOOK
|
||||||
|
$ui->display('port.tpl');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'add-port':
|
||||||
|
$r = ORM::for_table('tbl_routers')->find_many();
|
||||||
|
$ui->assign('r', $r);
|
||||||
|
run_hook('view_add_port'); #HOOK
|
||||||
|
$ui->display('port-add.tpl');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'edit-port':
|
||||||
|
$id = $routes['2'];
|
||||||
|
$d = ORM::for_table('tbl_port_pool')->find_one($id);
|
||||||
|
if ($d) {
|
||||||
|
$ui->assign('d', $d);
|
||||||
|
run_hook('view_edit_port'); #HOOK
|
||||||
|
$ui->display('port-edit.tpl');
|
||||||
|
} else {
|
||||||
|
r2(U . 'pool/port', 'e', Lang::T('Account Not Found'));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'delete-port':
|
||||||
|
$id = $routes['2'];
|
||||||
|
run_hook('delete_port'); #HOOK
|
||||||
|
$d = ORM::for_table('tbl_port_pool')->find_one($id);
|
||||||
|
if ($d) {
|
||||||
|
$d->delete();
|
||||||
|
|
||||||
|
r2(U . 'pool/port', 's', Lang::T('Data Deleted Successfully'));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'sync':
|
||||||
|
$pools = ORM::for_table('tbl_port_pool')->find_many();
|
||||||
|
$log = '';
|
||||||
|
foreach ($pools as $pool) {
|
||||||
|
if ($pool['routers'] != 'radius') {
|
||||||
|
(new MikrotikPppoe())->update_pool($pool, $pool);
|
||||||
|
$log .= 'DONE: ' . $pool['port_name'] . ': ' . $pool['range_port'] . '<br>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r2(U . 'pool/list', 's', $log);
|
||||||
|
break;
|
||||||
|
case 'add-port-post':
|
||||||
|
$name = _post('name');
|
||||||
|
$port_range = _post('port_range');
|
||||||
|
$public_ip = _post('public_ip');
|
||||||
|
$routers = _post('routers');
|
||||||
|
run_hook('add_pool'); #HOOK
|
||||||
|
$msg = '';
|
||||||
|
if (Validator::Length($name, 30, 2) == false) {
|
||||||
|
$msg .= 'Name should be between 3 to 30 characters' . '<br>';
|
||||||
|
}
|
||||||
|
if ($port_range == '' or $routers == '') {
|
||||||
|
$msg .= Lang::T('All field is required') . '<br>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$d = ORM::for_table('tbl_port_pool')->where('routers', $routers)->find_one();
|
||||||
|
if ($d) {
|
||||||
|
$msg .= Lang::T('Routers already have ports, each router can only have 1 port range!') . '<br>';
|
||||||
|
}
|
||||||
|
if ($msg == '') {
|
||||||
|
$b = ORM::for_table('tbl_port_pool')->create();
|
||||||
|
$b->public_ip = $public_ip;
|
||||||
|
$b->port_name = $name;
|
||||||
|
$b->range_port = $port_range;
|
||||||
|
$b->routers = $routers;
|
||||||
|
$b->save();
|
||||||
|
r2(U . 'pool/port', 's', Lang::T('Data Created Successfully'));
|
||||||
|
} else {
|
||||||
|
r2(U . 'pool/add-port', 'e', $msg);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case 'edit-port-post':
|
||||||
|
$name = _post('name');
|
||||||
|
$public_ip = _post('public_ip');
|
||||||
|
$range_port = _post('range_port');
|
||||||
|
$routers = _post('routers');
|
||||||
|
run_hook('edit_port'); #HOOK
|
||||||
|
$msg = '';
|
||||||
|
$msg = '';
|
||||||
|
if (Validator::Length($name, 30, 2) == false) {
|
||||||
|
$msg .= 'Name should be between 3 to 30 characters' . '<br>';
|
||||||
|
}
|
||||||
|
if ($range_port == '' or $routers == '') {
|
||||||
|
$msg .= Lang::T('All field is required') . '<br>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$id = _post('id');
|
||||||
|
$d = ORM::for_table('tbl_port_pool')->find_one($id);
|
||||||
|
$old = ORM::for_table('tbl_port_pool')->find_one($id);
|
||||||
|
if (!$d) {
|
||||||
|
$msg .= Lang::T('Data Not Found') . '<br>';
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($msg == '') {
|
||||||
|
$d->port_name = $name;
|
||||||
|
$d->public_ip = $public_ip;
|
||||||
|
$d->range_port = $range_port;
|
||||||
|
$d->routers = $routers;
|
||||||
|
$d->save();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
r2(U . 'pool/port', 's', Lang::T('Data Updated Successfully'));
|
||||||
|
} else {
|
||||||
|
r2(U . 'pool/edit-port/' . $id, 'e', $msg);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -901,6 +901,380 @@ switch ($action) {
|
|||||||
r2(U . 'services/balance-add', 'e', $msg);
|
r2(U . 'services/balance-add', 'e', $msg);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'vpn':
|
||||||
|
$ui->assign('_title', Lang::T('VPN Plans'));
|
||||||
|
$ui->assign('xfooter', '<script type="text/javascript" src="ui/lib/c/pppoe.js"></script>');
|
||||||
|
|
||||||
|
$name = _post('name');
|
||||||
|
$name = _req('name');
|
||||||
|
$type1 = _req('type1');
|
||||||
|
$type2 = _req('type2');
|
||||||
|
$type3 = _req('type3');
|
||||||
|
$bandwidth = _req('bandwidth');
|
||||||
|
$valid = _req('valid');
|
||||||
|
$device = _req('device');
|
||||||
|
$status = _req('status');
|
||||||
|
$router = _req('router');
|
||||||
|
$ui->assign('type1', $type1);
|
||||||
|
$ui->assign('type2', $type2);
|
||||||
|
$ui->assign('type3', $type3);
|
||||||
|
$ui->assign('bandwidth', $bandwidth);
|
||||||
|
$ui->assign('valid', $valid);
|
||||||
|
$ui->assign('device', $device);
|
||||||
|
$ui->assign('status', $status);
|
||||||
|
$ui->assign('router', $router);
|
||||||
|
|
||||||
|
$append_url = "&type1=" . urlencode($type1)
|
||||||
|
. "&type2=" . urlencode($type2)
|
||||||
|
. "&type3=" . urlencode($type3)
|
||||||
|
. "&bandwidth=" . urlencode($bandwidth)
|
||||||
|
. "&valid=" . urlencode($valid)
|
||||||
|
. "&device=" . urlencode($device)
|
||||||
|
. "&status=" . urlencode($status)
|
||||||
|
. "&router=" . urlencode($router);
|
||||||
|
|
||||||
|
$bws = ORM::for_table('tbl_plans')->distinct()->select("id_bw")->where('tbl_plans.type', 'VPN')->findArray();
|
||||||
|
$ids = array_column($bws, 'id_bw');
|
||||||
|
if(count($ids)){
|
||||||
|
$ui->assign('bws', ORM::for_table('tbl_bandwidth')->select("id")->select('name_bw')->where_id_in($ids)->findArray());
|
||||||
|
}else{
|
||||||
|
$ui->assign('bws', []);
|
||||||
|
}
|
||||||
|
$ui->assign('type2s', ORM::for_table('tbl_plans')->getEnum("plan_type"));
|
||||||
|
$ui->assign('type3s', ORM::for_table('tbl_plans')->getEnum("typebp"));
|
||||||
|
$ui->assign('valids', ORM::for_table('tbl_plans')->getEnum("validity_unit"));
|
||||||
|
$ui->assign('routers', array_column(ORM::for_table('tbl_plans')->distinct()->select("routers")->whereNotEqual('routers', '')->findArray(), 'routers'));
|
||||||
|
$devices = [];
|
||||||
|
$files = scandir($DEVICE_PATH);
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$ext = pathinfo($file, PATHINFO_EXTENSION);
|
||||||
|
if ($ext == 'php') {
|
||||||
|
$devices[] = pathinfo($file, PATHINFO_FILENAME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$ui->assign('devices', $devices);
|
||||||
|
$query = ORM::for_table('tbl_bandwidth')
|
||||||
|
->left_outer_join('tbl_plans', array('tbl_bandwidth.id', '=', 'tbl_plans.id_bw'))
|
||||||
|
->where('tbl_plans.type', 'VPN');
|
||||||
|
if (!empty($type1)) {
|
||||||
|
$query->where('tbl_plans.prepaid', $type1);
|
||||||
|
}
|
||||||
|
if (!empty($type2)) {
|
||||||
|
$query->where('tbl_plans.plan_type', $type2);
|
||||||
|
}
|
||||||
|
if (!empty($type3)) {
|
||||||
|
$query->where('tbl_plans.typebp', $type3);
|
||||||
|
}
|
||||||
|
if (!empty($bandwidth)) {
|
||||||
|
$query->where('tbl_plans.id_bw', $bandwidth);
|
||||||
|
}
|
||||||
|
if (!empty($valid)) {
|
||||||
|
$query->where('tbl_plans.validity_unit', $valid);
|
||||||
|
}
|
||||||
|
if (!empty($router)) {
|
||||||
|
if ($router == 'radius') {
|
||||||
|
$query->where('tbl_plans.is_radius', '1');
|
||||||
|
} else {
|
||||||
|
$query->where('tbl_plans.routers', $router);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!empty($device)) {
|
||||||
|
$query->where('tbl_plans.device', $device);
|
||||||
|
}
|
||||||
|
if (in_array($status, ['0', '1'])) {
|
||||||
|
$query->where('tbl_plans.enabled', $status);
|
||||||
|
}
|
||||||
|
if ($name != '') {
|
||||||
|
$query->where_like('tbl_plans.name_plan', '%' . $name . '%');
|
||||||
|
}
|
||||||
|
$d = Paginator::findMany($query, ['name' => $name], 20, $append_url);
|
||||||
|
|
||||||
|
$ui->assign('d', $d);
|
||||||
|
run_hook('view_list_vpn'); #HOOK
|
||||||
|
$ui->display('vpn.tpl');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'vpn-add':
|
||||||
|
$ui->assign('_title', Lang::T('VPN Plans'));
|
||||||
|
$d = ORM::for_table('tbl_bandwidth')->find_many();
|
||||||
|
$ui->assign('d', $d);
|
||||||
|
$r = ORM::for_table('tbl_routers')->find_many();
|
||||||
|
$ui->assign('r', $r);
|
||||||
|
$devices = [];
|
||||||
|
$files = scandir($DEVICE_PATH);
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$ext = pathinfo($file, PATHINFO_EXTENSION);
|
||||||
|
if ($ext == 'php') {
|
||||||
|
$devices[] = pathinfo($file, PATHINFO_FILENAME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$ui->assign('devices', $devices);
|
||||||
|
run_hook('view_add_vpn'); #HOOK
|
||||||
|
$ui->display('vpn-add.tpl');
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'vpn-edit':
|
||||||
|
$ui->assign('_title', Lang::T('VPN Plans'));
|
||||||
|
$id = $routes['2'];
|
||||||
|
$d = ORM::for_table('tbl_plans')->find_one($id);
|
||||||
|
if ($d) {
|
||||||
|
if (empty($d['device'])) {
|
||||||
|
if ($d['is_radius']) {
|
||||||
|
$d->device = 'Radius';
|
||||||
|
} else {
|
||||||
|
$d->device = 'MikrotikVpn';
|
||||||
|
}
|
||||||
|
$d->save();
|
||||||
|
}
|
||||||
|
$ui->assign('d', $d);
|
||||||
|
$p = ORM::for_table('tbl_pool')->where('routers', ($d['is_radius']) ? 'radius' : $d['routers'])->find_many();
|
||||||
|
$ui->assign('p', $p);
|
||||||
|
$b = ORM::for_table('tbl_bandwidth')->find_many();
|
||||||
|
$ui->assign('b', $b);
|
||||||
|
$r = [];
|
||||||
|
if ($d['is_radius']) {
|
||||||
|
$r = ORM::for_table('tbl_routers')->find_many();
|
||||||
|
}
|
||||||
|
$ui->assign('r', $r);
|
||||||
|
$devices = [];
|
||||||
|
$files = scandir($DEVICE_PATH);
|
||||||
|
foreach ($files as $file) {
|
||||||
|
$ext = pathinfo($file, PATHINFO_EXTENSION);
|
||||||
|
if ($ext == 'php') {
|
||||||
|
$devices[] = pathinfo($file, PATHINFO_FILENAME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$ui->assign('devices', $devices);
|
||||||
|
//select expired plan
|
||||||
|
if ($d['is_radius']) {
|
||||||
|
$exps = ORM::for_table('tbl_plans')->selects('id', 'name_plan')->where('type', 'VPN')->where("is_radius", 1)->findArray();
|
||||||
|
} else {
|
||||||
|
$exps = ORM::for_table('tbl_plans')->selects('id', 'name_plan')->where('type', 'VPN')->where("routers", $d['routers'])->findArray();
|
||||||
|
}
|
||||||
|
$ui->assign('exps', $exps);
|
||||||
|
run_hook('view_edit_vpn'); #HOOK
|
||||||
|
$ui->display('vpn-edit.tpl');
|
||||||
|
} else {
|
||||||
|
r2(U . 'services/vpn', 'e', Lang::T('Account Not Found'));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'vpn-delete':
|
||||||
|
$id = $routes['2'];
|
||||||
|
|
||||||
|
$d = ORM::for_table('tbl_plans')->find_one($id);
|
||||||
|
if ($d) {
|
||||||
|
run_hook('delete_vpn'); #HOOK
|
||||||
|
|
||||||
|
$dvc = Package::getDevice($d);
|
||||||
|
if ($_app_stage != 'demo') {
|
||||||
|
if (file_exists($dvc)) {
|
||||||
|
require_once $dvc;
|
||||||
|
(new $d['device'])->remove_plan($d);
|
||||||
|
} else {
|
||||||
|
new Exception(Lang::T("Devices Not Found"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$d->delete();
|
||||||
|
|
||||||
|
r2(U . 'services/vpn', 's', Lang::T('Data Deleted Successfully'));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'vpn-add-post':
|
||||||
|
$name = _post('name_plan');
|
||||||
|
$plan_type = _post('plan_type');
|
||||||
|
$radius = _post('radius');
|
||||||
|
$id_bw = _post('id_bw');
|
||||||
|
$price = _post('price');
|
||||||
|
$validity = _post('validity');
|
||||||
|
$validity_unit = _post('validity_unit');
|
||||||
|
$routers = _post('routers');
|
||||||
|
$device = _post('device');
|
||||||
|
$pool = _post('pool_name');
|
||||||
|
$enabled = _post('enabled');
|
||||||
|
$prepaid = _post('prepaid');
|
||||||
|
$expired_date = _post('expired_date');
|
||||||
|
|
||||||
|
|
||||||
|
$msg = '';
|
||||||
|
if (Validator::UnsignedNumber($validity) == false) {
|
||||||
|
$msg .= 'The validity must be a number' . '<br>';
|
||||||
|
}
|
||||||
|
if (Validator::UnsignedNumber($price) == false) {
|
||||||
|
$msg .= 'The price must be a number' . '<br>';
|
||||||
|
}
|
||||||
|
if ($name == '' or $id_bw == '' or $price == '' or $validity == '' or $pool == '') {
|
||||||
|
$msg .= Lang::T('All field is required') . '<br>';
|
||||||
|
}
|
||||||
|
if (empty($radius)) {
|
||||||
|
if ($routers == '') {
|
||||||
|
$msg .= Lang::T('All field is required') . '<br>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$d = ORM::for_table('tbl_plans')->where('name_plan', $name)->find_one();
|
||||||
|
if ($d) {
|
||||||
|
$msg .= Lang::T('Name Plan Already Exist') . '<br>';
|
||||||
|
}
|
||||||
|
run_hook('add_vpn'); #HOOK
|
||||||
|
if ($msg == '') {
|
||||||
|
$b = ORM::for_table('tbl_bandwidth')->where('id', $id_bw)->find_one();
|
||||||
|
if ($b['rate_down_unit'] == 'Kbps') {
|
||||||
|
$unitdown = 'K';
|
||||||
|
$raddown = '000';
|
||||||
|
} else {
|
||||||
|
$unitdown = 'M';
|
||||||
|
$raddown = '000000';
|
||||||
|
}
|
||||||
|
if ($b['rate_up_unit'] == 'Kbps') {
|
||||||
|
$unitup = 'K';
|
||||||
|
$radup = '000';
|
||||||
|
} else {
|
||||||
|
$unitup = 'M';
|
||||||
|
$radup = '000000';
|
||||||
|
}
|
||||||
|
$rate = $b['rate_up'] . $unitup . "/" . $b['rate_down'] . $unitdown;
|
||||||
|
$radiusRate = $b['rate_up'] . $radup . '/' . $b['rate_down'] . $raddown . '/' . $b['burst'];
|
||||||
|
$rate = trim($rate . " " . $b['burst']);
|
||||||
|
$d = ORM::for_table('tbl_plans')->create();
|
||||||
|
$d->type = 'VPN';
|
||||||
|
$d->name_plan = $name;
|
||||||
|
$d->id_bw = $id_bw;
|
||||||
|
$d->price = $price;
|
||||||
|
$d->plan_type = $plan_type;
|
||||||
|
$d->validity = $validity;
|
||||||
|
$d->validity_unit = $validity_unit;
|
||||||
|
$d->pool = $pool;
|
||||||
|
if (!empty($radius)) {
|
||||||
|
$d->is_radius = 1;
|
||||||
|
$d->routers = '';
|
||||||
|
} else {
|
||||||
|
$d->is_radius = 0;
|
||||||
|
$d->routers = $routers;
|
||||||
|
}
|
||||||
|
if ($prepaid == 'no') {
|
||||||
|
if ($expired_date > 28 && $expired_date < 1) {
|
||||||
|
$expired_date = 20;
|
||||||
|
}
|
||||||
|
$d->expired_date = $expired_date;
|
||||||
|
} else {
|
||||||
|
$d->expired_date = 0;
|
||||||
|
}
|
||||||
|
$d->enabled = $enabled;
|
||||||
|
$d->prepaid = $prepaid;
|
||||||
|
$d->device = $device;
|
||||||
|
$d->save();
|
||||||
|
|
||||||
|
$dvc = Package::getDevice($d);
|
||||||
|
if ($_app_stage != 'demo') {
|
||||||
|
if (file_exists($dvc)) {
|
||||||
|
require_once $dvc;
|
||||||
|
(new $d['device'])->add_plan($d);
|
||||||
|
} else {
|
||||||
|
new Exception(Lang::T("Devices Not Found"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r2(U . 'services/vpn', 's', Lang::T('Data Created Successfully'));
|
||||||
|
} else {
|
||||||
|
r2(U . 'services/vpn-add', 'e', $msg);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'edit-vpn-post':
|
||||||
|
$id = _post('id');
|
||||||
|
$plan_type = _post('plan_type');
|
||||||
|
$name = _post('name_plan');
|
||||||
|
$id_bw = _post('id_bw');
|
||||||
|
$price = _post('price');
|
||||||
|
$validity = _post('validity');
|
||||||
|
$validity_unit = _post('validity_unit');
|
||||||
|
$routers = _post('routers');
|
||||||
|
$device = _post('device');
|
||||||
|
$pool = _post('pool_name');
|
||||||
|
$plan_expired = _post('plan_expired');
|
||||||
|
$enabled = _post('enabled');
|
||||||
|
$prepaid = _post('prepaid');
|
||||||
|
$expired_date = _post('expired_date');
|
||||||
|
$on_login = _post('on_login');
|
||||||
|
$on_logout = _post('on_logout');
|
||||||
|
|
||||||
|
$msg = '';
|
||||||
|
if (Validator::UnsignedNumber($validity) == false) {
|
||||||
|
$msg .= 'The validity must be a number' . '<br>';
|
||||||
|
}
|
||||||
|
if (Validator::UnsignedNumber($price) == false) {
|
||||||
|
$msg .= 'The price must be a number' . '<br>';
|
||||||
|
}
|
||||||
|
if ($name == '' or $id_bw == '' or $price == '' or $validity == '' or $pool == '') {
|
||||||
|
$msg .= Lang::T('All field is required') . '<br>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$d = ORM::for_table('tbl_plans')->where('id', $id)->find_one();
|
||||||
|
$old = ORM::for_table('tbl_plans')->where('id', $id)->find_one();
|
||||||
|
if ($d) {
|
||||||
|
} else {
|
||||||
|
$msg .= Lang::T('Data Not Found') . '<br>';
|
||||||
|
}
|
||||||
|
run_hook('edit_vpn'); #HOOK
|
||||||
|
if ($msg == '') {
|
||||||
|
$b = ORM::for_table('tbl_bandwidth')->where('id', $id_bw)->find_one();
|
||||||
|
if ($b['rate_down_unit'] == 'Kbps') {
|
||||||
|
$unitdown = 'K';
|
||||||
|
$raddown = '000';
|
||||||
|
} else {
|
||||||
|
$unitdown = 'M';
|
||||||
|
$raddown = '000000';
|
||||||
|
}
|
||||||
|
if ($b['rate_up_unit'] == 'Kbps') {
|
||||||
|
$unitup = 'K';
|
||||||
|
$radup = '000';
|
||||||
|
} else {
|
||||||
|
$unitup = 'M';
|
||||||
|
$radup = '000000';
|
||||||
|
}
|
||||||
|
$rate = $b['rate_up'] . $unitup . "/" . $b['rate_down'] . $unitdown;
|
||||||
|
$radiusRate = $b['rate_up'] . $radup . '/' . $b['rate_down'] . $raddown . '/' . $b['burst'];
|
||||||
|
$rate = trim($rate . " " . $b['burst']);
|
||||||
|
|
||||||
|
$d->name_plan = $name;
|
||||||
|
$d->id_bw = $id_bw;
|
||||||
|
$d->price = $price;
|
||||||
|
$d->plan_type = $plan_type;
|
||||||
|
$d->validity = $validity;
|
||||||
|
$d->validity_unit = $validity_unit;
|
||||||
|
$d->routers = $routers;
|
||||||
|
$d->pool = $pool;
|
||||||
|
$d->plan_expired = $plan_expired;
|
||||||
|
$d->enabled = $enabled;
|
||||||
|
$d->prepaid = $prepaid;
|
||||||
|
$d->device = $device;
|
||||||
|
$d->on_login = $on_login;
|
||||||
|
$d->on_logout = $on_logout;
|
||||||
|
if ($prepaid == 'no') {
|
||||||
|
if ($expired_date > 28 && $expired_date < 1) {
|
||||||
|
$expired_date = 20;
|
||||||
|
}
|
||||||
|
$d->expired_date = $expired_date;
|
||||||
|
} else {
|
||||||
|
$d->expired_date = 0;
|
||||||
|
}
|
||||||
|
$d->save();
|
||||||
|
|
||||||
|
$dvc = Package::getDevice($d);
|
||||||
|
if ($_app_stage != 'demo') {
|
||||||
|
if (file_exists($dvc)) {
|
||||||
|
require_once $dvc;
|
||||||
|
(new $d['device'])->update_plan($old, $d);
|
||||||
|
} else {
|
||||||
|
new Exception(Lang::T("Devices Not Found"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
r2(U . 'services/vpn', 's', Lang::T('Data Updated Successfully'));
|
||||||
|
} else {
|
||||||
|
r2(U . 'services/vpn-edit/' . $id, 'e', $msg);
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
$ui->display('a404.tpl');
|
$ui->display('a404.tpl');
|
||||||
}
|
}
|
||||||
|
@ -295,6 +295,16 @@ switch ($action) {
|
|||||||
$d->value = _post('pppoe_plan');
|
$d->value = _post('pppoe_plan');
|
||||||
$d->save();
|
$d->save();
|
||||||
}
|
}
|
||||||
|
$d = ORM::for_table('tbl_appconfig')->where('setting', 'vpn_plan')->find_one();
|
||||||
|
if ($d) {
|
||||||
|
$d->value = _post('vpn_plan');
|
||||||
|
$d->save();
|
||||||
|
} else {
|
||||||
|
$d = ORM::for_table('tbl_appconfig')->create();
|
||||||
|
$d->setting = 'vpn_plan';
|
||||||
|
$d->value = _post('vpn_plan');
|
||||||
|
$d->save();
|
||||||
|
}
|
||||||
|
|
||||||
$currency_code = $_POST['currency_code'];
|
$currency_code = $_POST['currency_code'];
|
||||||
$d = ORM::for_table('tbl_appconfig')->where('setting', 'currency_code')->find_one();
|
$d = ORM::for_table('tbl_appconfig')->where('setting', 'currency_code')->find_one();
|
||||||
|
@ -1,6 +1,27 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
include "../init.php";
|
include "../init.php";
|
||||||
|
$lockFile = "$CACHE_PATH/router_monitor.lock";
|
||||||
|
|
||||||
|
if (!is_dir($CACHE_PATH)) {
|
||||||
|
echo "Directory '$CACHE_PATH' does not exist. Exiting...\n";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$lock = fopen($lockFile, 'c');
|
||||||
|
|
||||||
|
if ($lock === false) {
|
||||||
|
echo "Failed to open lock file. Exiting...\n";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!flock($lock, LOCK_EX | LOCK_NB)) {
|
||||||
|
echo "Script is already running. Exiting...\n";
|
||||||
|
fclose($lock);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$isCli = true;
|
$isCli = true;
|
||||||
if (php_sapi_name() !== 'cli') {
|
if (php_sapi_name() !== 'cli') {
|
||||||
$isCli = false;
|
$isCli = false;
|
||||||
@ -81,27 +102,7 @@ foreach ($d as $ds) {
|
|||||||
|
|
||||||
|
|
||||||
if ($config['router_check']) {
|
if ($config['router_check']) {
|
||||||
|
echo "Checking router status...\n";
|
||||||
$lockFile = $CACHE_PATH . '/router_monitor.lock';
|
|
||||||
|
|
||||||
if (!is_dir($CACHE_PATH)) {
|
|
||||||
echo "Directory '$CACHE_PATH' does not exist. Exiting...\n";
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$lock = fopen($lockFile, 'c');
|
|
||||||
|
|
||||||
if ($lock === false) {
|
|
||||||
echo "Failed to open lock file. Exiting...\n";
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!flock($lock, LOCK_EX | LOCK_NB)) {
|
|
||||||
echo "Script is already running. Exiting...\n";
|
|
||||||
fclose($lock);
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$routers = ORM::for_table('tbl_routers')->where('enabled', '1')->find_many();
|
$routers = ORM::for_table('tbl_routers')->where('enabled', '1')->find_many();
|
||||||
if (!$routers) {
|
if (!$routers) {
|
||||||
echo "No active routers found in the database.\n";
|
echo "No active routers found in the database.\n";
|
||||||
@ -186,14 +187,20 @@ if ($config['router_check']) {
|
|||||||
Message::SendEmail($adminEmail, $subject, $message);
|
Message::SendEmail($adminEmail, $subject, $message);
|
||||||
sendTelegram($message);
|
sendTelegram($message);
|
||||||
}
|
}
|
||||||
|
echo "Router monitoring finished\n";
|
||||||
if (defined('PHP_SAPI') && PHP_SAPI === 'cli') {
|
|
||||||
echo "Cronjob finished\n";
|
|
||||||
} else {
|
|
||||||
echo "</pre>";
|
|
||||||
}
|
|
||||||
|
|
||||||
flock($lock, LOCK_UN);
|
|
||||||
fclose($lock);
|
|
||||||
unlink($lockFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (defined('PHP_SAPI') && PHP_SAPI === 'cli') {
|
||||||
|
echo "Cronjob finished\n";
|
||||||
|
} else {
|
||||||
|
echo "</pre>";
|
||||||
|
}
|
||||||
|
|
||||||
|
flock($lock, LOCK_UN);
|
||||||
|
fclose($lock);
|
||||||
|
unlink($lockFile);
|
||||||
|
|
||||||
|
$timestampFile = "$UPLOAD_PATH/cron_last_run.txt";
|
||||||
|
file_put_contents($timestampFile, time());
|
||||||
|
|
||||||
|
@ -10,14 +10,14 @@
|
|||||||
|
|
||||||
use PEAR2\Net\RouterOS;
|
use PEAR2\Net\RouterOS;
|
||||||
|
|
||||||
class MikrotikPppoeCustom
|
class MikrotikPppoe
|
||||||
{
|
{
|
||||||
// show Description
|
// show Description
|
||||||
function description()
|
function description()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'title' => 'Mikrotik PPPOE',
|
'title' => 'Mikrotik PPPOE',
|
||||||
'description' => 'To handle connection between PHPNuxBill with Mikrotik PPPOE using Custom Username, IP and Password',
|
'description' => 'To handle connection between PHPNuxBill with Mikrotik PPPOE',
|
||||||
'author' => 'ibnux',
|
'author' => 'ibnux',
|
||||||
'url' => [
|
'url' => [
|
||||||
'Github' => 'https://github.com/hotspotbilling/phpnuxbill/',
|
'Github' => 'https://github.com/hotspotbilling/phpnuxbill/',
|
||||||
@ -51,6 +51,8 @@ class MikrotikPppoeCustom
|
|||||||
}
|
}
|
||||||
if (!empty($customer['pppoe_ip'])) {
|
if (!empty($customer['pppoe_ip'])) {
|
||||||
$setRequest->setArgument('remote-address', $customer['pppoe_ip']);
|
$setRequest->setArgument('remote-address', $customer['pppoe_ip']);
|
||||||
|
}else{
|
||||||
|
$setRequest->setArgument('remote-address', '0.0.0.0');
|
||||||
}
|
}
|
||||||
$setRequest->setArgument('profile', $plan['name_plan']);
|
$setRequest->setArgument('profile', $plan['name_plan']);
|
||||||
$setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'] . ' | ' . implode(', ', User::getBillNames($customer['id'])));
|
$setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'] . ' | ' . implode(', ', User::getBillNames($customer['id'])));
|
||||||
|
@ -1,27 +1,20 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
/**
|
|
||||||
* PHP Mikrotik Billing (https://github.com/hotspotbilling/phpnuxbill/)
|
|
||||||
* by https://t.me/ibnux
|
|
||||||
*
|
|
||||||
* This is Core, don't modification except you want to contribute
|
|
||||||
* better create new plugin
|
|
||||||
**/
|
|
||||||
|
|
||||||
use PEAR2\Net\RouterOS;
|
use PEAR2\Net\RouterOS;
|
||||||
|
|
||||||
class MikrotikPppoeCustom
|
class MikrotikVpn
|
||||||
{
|
{
|
||||||
// show Description
|
|
||||||
function description()
|
function description()
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'title' => 'Mikrotik PPPOE Custom',
|
'title' => 'Mikrotik Vpn',
|
||||||
'description' => 'To handle connection between PHPNuxBill with Mikrotik PPPOE using Custom Username, IP and Password',
|
'description' => 'To handle connection between PHPNuxBill with Mikrotik VPN',
|
||||||
'author' => 'ibnux',
|
'author' => 'agstr',
|
||||||
'url' => [
|
'url' => [
|
||||||
'Github' => 'https://github.com/hotspotbilling/phpnuxbill/',
|
'Github' => 'https://github.com/agstrxyz',
|
||||||
'Telegram' => 'https://t.me/phpnuxbill',
|
'Telegram' => 'https://t.me/agstrxyz',
|
||||||
|
'Youtube' => 'https://www.youtube.com/@agstrxyz',
|
||||||
'Donate' => 'https://paypal.me/ibnux'
|
'Donate' => 'https://paypal.me/ibnux'
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
@ -34,8 +27,7 @@ class MikrotikPppoeCustom
|
|||||||
$client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
$client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||||
$cid = self::getIdByCustomer($customer, $client);
|
$cid = self::getIdByCustomer($customer, $client);
|
||||||
if (empty($cid)) {
|
if (empty($cid)) {
|
||||||
//customer not exists, add it
|
$this->addVpnUser($client, $plan, $customer);
|
||||||
$this->addPpoeUser($client, $plan, $customer);
|
|
||||||
}else{
|
}else{
|
||||||
$setRequest = new RouterOS\Request('/ppp/secret/set');
|
$setRequest = new RouterOS\Request('/ppp/secret/set');
|
||||||
$setRequest->setArgument('numbers', $cid);
|
$setRequest->setArgument('numbers', $cid);
|
||||||
@ -50,18 +42,17 @@ class MikrotikPppoeCustom
|
|||||||
$setRequest->setArgument('name', $customer['username']);
|
$setRequest->setArgument('name', $customer['username']);
|
||||||
}
|
}
|
||||||
if (!empty($customer['pppoe_ip'])) {
|
if (!empty($customer['pppoe_ip'])) {
|
||||||
$setRequest->setArgument('local-address', $customer['pppoe_ip']);
|
$setRequest->setArgument('remote-address', $customer['pppoe_ip']);
|
||||||
}else{
|
}else{
|
||||||
$setRequest->setArgument('local-address', '0.0.0.0');
|
$setRequest->setArgument('remote-address', '0.0.0.0');
|
||||||
}
|
}
|
||||||
$setRequest->setArgument('profile', $plan['name_plan']);
|
$setRequest->setArgument('profile', $plan['name_plan']);
|
||||||
$setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'] . ' | ' . implode(', ', User::getBillNames($customer['id'])));
|
$setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'] . ' | ' . implode(', ', User::getBillNames($customer['id'])));
|
||||||
$client->sendSync($setRequest);
|
$client->sendSync($setRequest);
|
||||||
//disconnect then
|
|
||||||
if(isset($isChangePlan) && $isChangePlan){
|
if(isset($isChangePlan) && $isChangePlan){
|
||||||
$this->removePpoeActive($client, $customer['username']);
|
$this->removeVpnActive($client, $customer['username']);
|
||||||
if (!empty($customer['pppoe_username'])) {
|
if (!empty($customer['pppoe_username'])) {
|
||||||
$this->removePpoeActive($client, $customer['pppoe_username']);
|
$this->removeVpnActive($client, $customer['pppoe_username']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -75,29 +66,27 @@ class MikrotikPppoeCustom
|
|||||||
$p = ORM::for_table("tbl_plans")->find_one($plan['plan_expired']);
|
$p = ORM::for_table("tbl_plans")->find_one($plan['plan_expired']);
|
||||||
if($p){
|
if($p){
|
||||||
$this->add_customer($customer, $p);
|
$this->add_customer($customer, $p);
|
||||||
$this->removePpoeActive($client, $customer['username']);
|
$this->removeVpnActive($client, $customer['username']);
|
||||||
if (!empty($customer['pppoe_username'])) {
|
if (!empty($customer['pppoe_username'])) {
|
||||||
$this->removePpoeActive($client, $customer['pppoe_username']);
|
$this->removeVpnActive($client, $customer['pppoe_username']);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->removePpoeUser($client, $customer['username']);
|
$this->removeVpnUser($client, $customer['username'], $customer['id']);
|
||||||
if (!empty($customer['pppoe_username'])) {
|
if (!empty($customer['pppoe_username'])) {
|
||||||
$this->removePpoeUser($client, $customer['pppoe_username']);
|
$this->removeVpnUser($client, $customer['pppoe_username'], $customer['id']);
|
||||||
}
|
}
|
||||||
$this->removePpoeActive($client, $customer['username']);
|
$this->removeVpnActive($client, $customer['username']);
|
||||||
if (!empty($customer['pppoe_username'])) {
|
if (!empty($customer['pppoe_username'])) {
|
||||||
$this->removePpoeActive($client, $customer['pppoe_username']);
|
$this->removeVpnActive($client, $customer['pppoe_username']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// customer change username
|
|
||||||
public function change_username($plan, $from, $to)
|
public function change_username($plan, $from, $to)
|
||||||
{
|
{
|
||||||
$mikrotik = $this->info($plan['routers']);
|
$mikrotik = $this->info($plan['routers']);
|
||||||
$client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
$client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||||
//check if customer exists
|
|
||||||
$printRequest = new RouterOS\Request('/ppp/secret/print');
|
$printRequest = new RouterOS\Request('/ppp/secret/print');
|
||||||
$printRequest->setQuery(RouterOS\Query::where('name', $from));
|
$printRequest->setQuery(RouterOS\Query::where('name', $from));
|
||||||
$cid = $client->sendSync($printRequest)->getProperty('.id');
|
$cid = $client->sendSync($printRequest)->getProperty('.id');
|
||||||
@ -106,8 +95,7 @@ class MikrotikPppoeCustom
|
|||||||
$setRequest->setArgument('numbers', $cid);
|
$setRequest->setArgument('numbers', $cid);
|
||||||
$setRequest->setArgument('name', $to);
|
$setRequest->setArgument('name', $to);
|
||||||
$client->sendSync($setRequest);
|
$client->sendSync($setRequest);
|
||||||
//disconnect then
|
$this->removeVpnActive($client, $from);
|
||||||
$this->removePpoeActive($client, $from);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +104,6 @@ class MikrotikPppoeCustom
|
|||||||
$mikrotik = $this->info($plan['routers']);
|
$mikrotik = $this->info($plan['routers']);
|
||||||
$client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
$client = $this->getClient($mikrotik['ip_address'], $mikrotik['username'], $mikrotik['password']);
|
||||||
|
|
||||||
//Add Pool
|
|
||||||
|
|
||||||
$bw = ORM::for_table("tbl_bandwidth")->find_one($plan['id_bw']);
|
$bw = ORM::for_table("tbl_bandwidth")->find_one($plan['id_bw']);
|
||||||
if ($bw['rate_down_unit'] == 'Kbps') {
|
if ($bw['rate_down_unit'] == 'Kbps') {
|
||||||
@ -144,9 +131,7 @@ class MikrotikPppoeCustom
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to ID by username from Mikrotik
|
|
||||||
*/
|
|
||||||
function getIdByCustomer($customer, $client){
|
function getIdByCustomer($customer, $client){
|
||||||
$printRequest = new RouterOS\Request('/ppp/secret/print');
|
$printRequest = new RouterOS\Request('/ppp/secret/print');
|
||||||
$printRequest->setQuery(RouterOS\Query::where('name', $customer['username']));
|
$printRequest->setQuery(RouterOS\Query::where('name', $customer['username']));
|
||||||
@ -306,7 +291,7 @@ class MikrotikPppoeCustom
|
|||||||
return new RouterOS\Client($iport[0], $user, $pass, ($iport[1]) ? $iport[1] : null);
|
return new RouterOS\Client($iport[0], $user, $pass, ($iport[1]) ? $iport[1] : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
function removePpoeUser($client, $username)
|
function removeVpnUser($client, $username, $cstid)
|
||||||
{
|
{
|
||||||
global $_app_stage;
|
global $_app_stage;
|
||||||
if ($_app_stage == 'demo') {
|
if ($_app_stage == 'demo') {
|
||||||
@ -319,12 +304,13 @@ class MikrotikPppoeCustom
|
|||||||
$removeRequest = new RouterOS\Request('/ppp/secret/remove');
|
$removeRequest = new RouterOS\Request('/ppp/secret/remove');
|
||||||
$removeRequest->setArgument('numbers', $id);
|
$removeRequest->setArgument('numbers', $id);
|
||||||
$client->sendSync($removeRequest);
|
$client->sendSync($removeRequest);
|
||||||
|
$this->rmNat($client, $cstid);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addPpoeUser($client, $plan, $customer)
|
function addVpnUser($client, $plan, $customer)
|
||||||
{
|
{
|
||||||
$setRequest = new RouterOS\Request('/ppp/secret/add');
|
$setRequest = new RouterOS\Request('/ppp/secret/add');
|
||||||
$setRequest->setArgument('service', 'pppoe');
|
$setRequest->setArgument('service', 'any');
|
||||||
$setRequest->setArgument('profile', $plan['name_plan']);
|
$setRequest->setArgument('profile', $plan['name_plan']);
|
||||||
$setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'] . ' | ' . implode(', ', User::getBillNames($customer['id'])));
|
$setRequest->setArgument('comment', $customer['fullname'] . ' | ' . $customer['email'] . ' | ' . implode(', ', User::getBillNames($customer['id'])));
|
||||||
if (!empty($customer['pppoe_password'])) {
|
if (!empty($customer['pppoe_password'])) {
|
||||||
@ -338,12 +324,21 @@ class MikrotikPppoeCustom
|
|||||||
$setRequest->setArgument('name', $customer['username']);
|
$setRequest->setArgument('name', $customer['username']);
|
||||||
}
|
}
|
||||||
if (!empty($customer['pppoe_ip'])) {
|
if (!empty($customer['pppoe_ip'])) {
|
||||||
$setRequest->setArgument('local-address', $customer['pppoe_ip']);
|
$ips = $customer['pppoe_ip'];
|
||||||
|
$setRequest->setArgument('remote-address', $customer['pppoe_ip']);
|
||||||
|
} else {
|
||||||
|
$ips = $this->checkIpAddr($plan['pool'], $customer['id']);
|
||||||
|
$setRequest->setArgument('remote-address', $ips);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
$this->addNat($client, $plan, $customer, $ips);
|
||||||
$client->sendSync($setRequest);
|
$client->sendSync($setRequest);
|
||||||
|
$customer->service_type = 'VPN';
|
||||||
|
$customer->pppoe_ip = $ips;
|
||||||
|
$customer->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
function removePpoeActive($client, $username)
|
function removeVpnActive($client, $username)
|
||||||
{
|
{
|
||||||
global $_app_stage;
|
global $_app_stage;
|
||||||
if ($_app_stage == 'demo') {
|
if ($_app_stage == 'demo') {
|
||||||
@ -359,18 +354,6 @@ class MikrotikPppoeCustom
|
|||||||
$client->sendSync($removeRequest);
|
$client->sendSync($removeRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getIpHotspotUser($client, $username)
|
|
||||||
{
|
|
||||||
global $_app_stage;
|
|
||||||
if ($_app_stage == 'demo') {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
$printRequest = new RouterOS\Request(
|
|
||||||
'/ip hotspot active print',
|
|
||||||
RouterOS\Query::where('user', $username)
|
|
||||||
);
|
|
||||||
return $client->sendSync($printRequest)->getProperty('address');
|
|
||||||
}
|
|
||||||
|
|
||||||
function addIpToAddressList($client, $ip, $listName, $comment = '')
|
function addIpToAddressList($client, $ip, $listName, $comment = '')
|
||||||
{
|
{
|
||||||
@ -385,6 +368,7 @@ class MikrotikPppoeCustom
|
|||||||
->setArgument('comment', $comment)
|
->setArgument('comment', $comment)
|
||||||
->setArgument('list', $listName)
|
->setArgument('list', $listName)
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function removeIpFromAddressList($client, $ip)
|
function removeIpFromAddressList($client, $ip)
|
||||||
@ -404,4 +388,117 @@ class MikrotikPppoeCustom
|
|||||||
->setArgument('numbers', $id)
|
->setArgument('numbers', $id)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addNat($client, $plan, $cust, $ips)
|
||||||
|
{
|
||||||
|
global $_app_stage;
|
||||||
|
if ($_app_stage == 'demo') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
$this->checkPort($cust['id'], 'Winbox', $plan['routers']);
|
||||||
|
$this->checkPort($cust['id'], 'Api', $plan['routers']);
|
||||||
|
$this->checkPort($cust['id'], 'Web', $plan['routers']);
|
||||||
|
$tcf = ORM::for_table('tbl_customers_fields')
|
||||||
|
->where('customer_id', $cust['id'])
|
||||||
|
->find_many();
|
||||||
|
$ip = ORM::for_table('tbl_port_pool')
|
||||||
|
->where('routers', $plan['routers'])
|
||||||
|
->find_one();
|
||||||
|
foreach ($tcf as $cf) {
|
||||||
|
$dst = $cf['field_value'];
|
||||||
|
$cmnt = $cf['field_name'];
|
||||||
|
if ($cmnt == 'Winbox') {
|
||||||
|
$tp = '8291'; }
|
||||||
|
if ($cmnt == 'Web') {
|
||||||
|
$tp = '80'; }
|
||||||
|
if ($cmnt == 'Api') {
|
||||||
|
$tp = '8728'; }
|
||||||
|
if ($cmnt == 'Winbox' || $cmnt == 'Web' || $cmnt == 'Api') {
|
||||||
|
$addRequest = new RouterOS\Request('/ip/firewall/nat/add');
|
||||||
|
$client->sendSync(
|
||||||
|
$addRequest
|
||||||
|
->setArgument('chain', 'dstnat')
|
||||||
|
->setArgument('protocol', 'tcp')
|
||||||
|
->setArgument('dst-port', $dst)
|
||||||
|
->setArgument('action', 'dst-nat')
|
||||||
|
->setArgument('to-addresses', $ips)
|
||||||
|
->setArgument('to-ports', $tp)
|
||||||
|
->setArgument('dst-address', $ip['public_ip'])
|
||||||
|
->setArgument('comment', $cmnt.' || '.$cust['username'])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function rmNat($client, $cstid)
|
||||||
|
{
|
||||||
|
global $_app_stage;
|
||||||
|
if ($_app_stage == 'demo') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$cst = ORM::for_table('tbl_customers')->find_one($cstid);
|
||||||
|
$printRequest = new RouterOS\Request('/ip/firewall/nat/print');
|
||||||
|
$printRequest->setQuery(RouterOS\Query::where('to-addresses', $cst['pppoe_ip']));
|
||||||
|
$nats = $client->sendSync($printRequest);
|
||||||
|
foreach ($nats as $nat) {
|
||||||
|
$id = $client->sendSync($printRequest)->getProperty('.id');
|
||||||
|
$removeRequest = new RouterOS\Request('/ip/firewall/nat/remove');
|
||||||
|
$removeRequest->setArgument('numbers', $id);
|
||||||
|
$client->sendSync($removeRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function checkPort($id, $portn, $router)
|
||||||
|
{
|
||||||
|
$tcf = ORM::for_table('tbl_customers_fields')
|
||||||
|
->where('customer_id', $id)
|
||||||
|
->where('field_name', $portn)
|
||||||
|
->find_one();
|
||||||
|
$ports = ORM::for_table('tbl_port_pool')
|
||||||
|
->where('routers', $router)
|
||||||
|
->find_one();
|
||||||
|
$port = explode('-',$ports['range_port']);
|
||||||
|
if (empty($tcf) && !empty($ports)) {
|
||||||
|
repeat:
|
||||||
|
$portr = rand($port['0'], $port['1']);
|
||||||
|
if (ORM::for_table('tbl_customers_fields')->where('field_value', $portr)->find_one()) {
|
||||||
|
if($portr == $port['1'])
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
goto repeat;
|
||||||
|
}
|
||||||
|
$cf = ORM::for_table('tbl_customers_fields')->create();
|
||||||
|
$cf->customer_id = $id;
|
||||||
|
$cf->field_name = $portn;
|
||||||
|
$cf->field_value = $portr;
|
||||||
|
$cf->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkIpAddr($pname, $id) {
|
||||||
|
$c = ORM::for_table('tbl_customers')->find_one($id);
|
||||||
|
$ipp = ORM::for_table('tbl_pool')
|
||||||
|
->where('pool_name', $pname)
|
||||||
|
->find_one();
|
||||||
|
$ip_r = explode('-',$ipp['range_ip']);
|
||||||
|
$ip_1 = explode('.',$ip_r['0']);
|
||||||
|
$ip_2 = explode('.',$ip_r['1']);
|
||||||
|
repeat:
|
||||||
|
$ipt = rand($ip_1['3'], $ip_2['3']);
|
||||||
|
$ips = $ip_1['0'].'.'.$ip_1['1'].'.'.$ip_1['2'].'.'.$ipt;
|
||||||
|
if (empty($c['pppoe_ip'])) {
|
||||||
|
if (ORM::for_table('tbl_customers')->where('pppoe_ip' ,$ips)->find_one()) {
|
||||||
|
if ($ip_2['3'] == $ipt)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
goto repeat;
|
||||||
|
}
|
||||||
|
return $ips;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -155,5 +155,11 @@
|
|||||||
"2024.8.28" : [
|
"2024.8.28" : [
|
||||||
"ALTER TABLE `tbl_routers` ADD `status` ENUM('Online', 'Offline') DEFAULT 'Online' AFTER `coordinates`;",
|
"ALTER TABLE `tbl_routers` ADD `status` ENUM('Online', 'Offline') DEFAULT 'Online' AFTER `coordinates`;",
|
||||||
"ALTER TABLE `tbl_routers` ADD `last_seen` DATETIME AFTER `status`;"
|
"ALTER TABLE `tbl_routers` ADD `last_seen` DATETIME AFTER `status`;"
|
||||||
|
],
|
||||||
|
"2024.9.13" : [
|
||||||
|
"ALTER TABLE `tbl_plans` CHANGE `type` `type` ENUM('Hotspot','PPPOE','VPN','Balance') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;",
|
||||||
|
"ALTER TABLE `tbl_customers` CHANGE `service_type` `service_type` ENUM('Hotspot','PPPoE','VPN','Others') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT 'Others' COMMENT 'For selecting user type';",
|
||||||
|
"ALTER TABLE `tbl_transactions` CHANGE `type` `type` ENUM('Hotspot','PPPOE','VPN','Balance') CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL;",
|
||||||
|
"CREATE TABLE IF NOT EXISTS `tbl_port_pool` ( `id` int(10) NOT NULL AUTO_INCREMENT , `public_ip` varchar(40) NOT NULL, `port_name` varchar(40) NOT NULL, `range_port` varchar(40) NOT NULL, `routers` varchar(40) NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;"
|
||||||
]
|
]
|
||||||
}
|
}
|
@ -128,6 +128,14 @@
|
|||||||
</div>
|
</div>
|
||||||
<span class="help-block col-md-4">{Lang::T('Change title in user Plan order')}</span>
|
<span class="help-block col-md-4">{Lang::T('Change title in user Plan order')}</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label">{Lang::T('VPN Package')}</label>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input type="text" class="form-control" id="vpn_plan" name="vpn_plan"
|
||||||
|
value="{if $_c['vpn_plan']==''}VPN Plan{else}{$_c['vpn_plan']}{/if}">
|
||||||
|
</div>
|
||||||
|
<span class="help-block col-md-4">{Lang::T('Change title in user Plan order')}</span>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-lg-offset-2 col-lg-10">
|
<div class="col-lg-offset-2 col-lg-10">
|
||||||
<button class="btn btn-primary"
|
<button class="btn btn-primary"
|
||||||
|
@ -70,6 +70,7 @@
|
|||||||
<option value="Hotspot">Hotspot
|
<option value="Hotspot">Hotspot
|
||||||
</option>
|
</option>
|
||||||
<option value="PPPoE">PPPoE</option>
|
<option value="PPPoE">PPPoE</option>
|
||||||
|
<option value="VPN">VPN</option>
|
||||||
<option value="Others">{Lang::T('Others')}</option>
|
<option value="Others">{Lang::T('Others')}</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -75,6 +75,7 @@
|
|||||||
<option value="Hotspot" {if $d['service_type'] eq 'Hotspot' }selected{/if}>Hotspot
|
<option value="Hotspot" {if $d['service_type'] eq 'Hotspot' }selected{/if}>Hotspot
|
||||||
</option>
|
</option>
|
||||||
<option value="PPPoE" {if $d['service_type'] eq 'PPPoE' }selected{/if}>PPPoE</option>
|
<option value="PPPoE" {if $d['service_type'] eq 'PPPoE' }selected{/if}>PPPoE</option>
|
||||||
|
<option value="VPN" {if $d['service_type'] eq 'VPN' }selected{/if}>VPN</option>
|
||||||
<option value="Others" {if $d['service_type'] eq 'Others' }selected{/if}>Others</option>
|
<option value="Others" {if $d['service_type'] eq 'Others' }selected{/if}>Others</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
<div class="md-whiteframe-z1 mb20 text-center" style="padding: 15px">
|
<div class="md-whiteframe-z1 mb20 text-center" style="padding: 15px">
|
||||||
<div class="col-lg-4">
|
<div class="col-lg-4">
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<span class="input-group-addon">Order </span>
|
<span class="input-group-addon">Order </span>
|
||||||
<div class="row row-no-gutters">
|
<div class="row row-no-gutters">
|
||||||
<div class="col-xs-8">
|
<div class="col-xs-8">
|
||||||
<select class="form-control" id="order" name="order">
|
<select class="form-control" id="order" name="order">
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
<li>{Lang::dateFormat($start_date)}</li>
|
<li>{Lang::dateFormat($start_date)}</li>
|
||||||
<li>{Lang::dateFormat($current_date)}</li>
|
<li>{Lang::dateFormat($current_date)}</li>
|
||||||
{if $_c['enable_balance'] == 'yes' && in_array($_admin['user_type'],['SuperAdmin','Admin', 'Report'])}
|
{if $_c['enable_balance'] == 'yes' && in_array($_admin['user_type'],['SuperAdmin','Admin', 'Report'])}
|
||||||
<li>
|
<li onclick="window.location.href = '{$_url}customers&search=&order=balance&filter=Active&orderby=desc'" style="cursor: pointer;">
|
||||||
{Lang::T('Customer Balance')} <sup>{$_c['currency_code']}</sup>
|
{Lang::T('Customer Balance')} <sup>{$_c['currency_code']}</sup>
|
||||||
<b>{number_format($cb,0,$_c['dec_point'],$_c['thousands_sep'])}</b>
|
<b>{number_format($cb,0,$_c['dec_point'],$_c['thousands_sep'])}</b>
|
||||||
</li>
|
</li>
|
||||||
@ -194,6 +194,25 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
{if $run_date}
|
||||||
|
{assign var="current_time" value=$smarty.now}
|
||||||
|
{assign var="run_time" value=strtotime($run_date)}
|
||||||
|
{if $current_time - $run_time > 3600}
|
||||||
|
<div class="panel panel-cron-warning panel-hovered mb20 activities">
|
||||||
|
<div class="panel-heading"><i class="fa fa-clock-o"></i> {Lang::T('Cron has not run for over 1 hour. Please
|
||||||
|
check your setup.')}</div>
|
||||||
|
</div>
|
||||||
|
{else}
|
||||||
|
<div class="panel panel-cron-success panel-hovered mb20 activities">
|
||||||
|
<div class="panel-heading">{Lang::T('Cron Job last ran on')}: {$run_date}</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{else}
|
||||||
|
<div class="panel panel-cron-danger panel-hovered mb20 activities">
|
||||||
|
<div class="panel-heading"><i class="fa fa-warning"></i> {Lang::T('Cron appear not been setup, please check
|
||||||
|
your cron setup.')}</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
{if $_c['hide_pg'] != 'yes'}
|
{if $_c['hide_pg'] != 'yes'}
|
||||||
<div class="panel panel-success panel-hovered mb20 activities">
|
<div class="panel panel-success panel-hovered mb20 activities">
|
||||||
<div class="panel-heading">{Lang::T('Payment Gateway')}: {str_replace(',',', ',$_c['payment_gateway'])}
|
<div class="panel-heading">{Lang::T('Payment Gateway')}: {str_replace(',',', ',$_c['payment_gateway'])}
|
||||||
|
@ -104,12 +104,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
|
<div style="margin-left: 5px; margin-right: 5px;">
|
||||||
<table class="table table-bordered table-striped table-condensed">
|
<table class="table table-bordered table-striped table-condensed">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th></th>
|
<th></th>
|
||||||
<th colspan="5" class="text-center">{Lang::T('Internet Package')}</th>
|
<th colspan="5" class="text-center">{Lang::T('Internet Package')}</th>
|
||||||
<th colspan="2" class="text-center" style="background-color: rgb(246, 244, 244);">{Lang::T('Limit')}</th>
|
<th colspan="2" class="text-center" style="background-color: rgb(246, 244, 244);">
|
||||||
|
{Lang::T('Limit')}</th>
|
||||||
<th colspan="2"></th>
|
<th colspan="2"></th>
|
||||||
<th colspan="2" class="text-center" style="background-color: rgb(243, 241, 172);">
|
<th colspan="2" class="text-center" style="background-color: rgb(243, 241, 172);">
|
||||||
{Lang::T('Expired')}</th>
|
{Lang::T('Expired')}</th>
|
||||||
@ -163,14 +165,15 @@
|
|||||||
<a href="{$_url}services/edit/{$ds['id']}"
|
<a href="{$_url}services/edit/{$ds['id']}"
|
||||||
class="btn btn-info btn-xs">{Lang::T('Edit')}</a>
|
class="btn btn-info btn-xs">{Lang::T('Edit')}</a>
|
||||||
<a href="{$_url}services/delete/{$ds['id']}" id="{$ds['id']}"
|
<a href="{$_url}services/delete/{$ds['id']}" id="{$ds['id']}"
|
||||||
onclick="return confirm('{Lang::T('Delete')}?')" class="btn btn-danger btn-xs"><i
|
onclick="return confirm('{Lang::T('Delete')}?')"
|
||||||
class="glyphicon glyphicon-trash"></i></a>
|
class="btn btn-danger btn-xs"><i class="glyphicon glyphicon-trash"></i></a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{/foreach}
|
{/foreach}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="panel-footer">
|
<div class="panel-footer">
|
||||||
{include file="pagination.tpl"}
|
{include file="pagination.tpl"}
|
||||||
<div class="bs-callout bs-callout-info" id="callout-navbar-role">
|
<div class="bs-callout bs-callout-info" id="callout-navbar-role">
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
</div> *}
|
</div> *}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{Lang::T('Active Customers')}
|
{Lang::T('Active Customers')}
|
||||||
</div>
|
</div>
|
||||||
<form id="site-search" method="post" action="{$_url}plan/list/">
|
<form id="site-search" method="post" action="{$_url}plan/list/">
|
||||||
<div class="panel-body">
|
<div class="panel-body">
|
||||||
@ -70,6 +70,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
|
<div style="margin-left: 5px; margin-right: 5px;">
|
||||||
<table id="datatable" class="table table-bordered table-striped table-condensed">
|
<table id="datatable" class="table table-bordered table-striped table-condensed">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@ -85,7 +86,7 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{foreach $d as $ds}
|
{foreach $d as $ds}
|
||||||
<tr {if $ds['status']=='off'}class="danger" {/if}>
|
<tr {if $ds['status']=='off' }class="danger" {/if}>
|
||||||
<td>
|
<td>
|
||||||
{if $ds['customer_id'] == '0'}
|
{if $ds['customer_id'] == '0'}
|
||||||
<a href="{$_url}plan/voucher/&search={$ds['username']}">{$ds['username']}</a>
|
<a href="{$_url}plan/voucher/&search={$ds['username']}">{$ds['username']}</a>
|
||||||
@ -95,9 +96,13 @@
|
|||||||
</td>
|
</td>
|
||||||
{if $ds['type'] == 'Hotspot'}
|
{if $ds['type'] == 'Hotspot'}
|
||||||
<td><a href="{$_url}services/edit/{$ds['plan_id']}">{$ds['namebp']}</a></td>
|
<td><a href="{$_url}services/edit/{$ds['plan_id']}">{$ds['namebp']}</a></td>
|
||||||
{else}
|
{/if}
|
||||||
|
{if $ds['type'] == 'PPPOE'}
|
||||||
<td><a href="{$_url}services/pppoe-edit/{$ds['plan_id']}">{$ds['namebp']}</a></td>
|
<td><a href="{$_url}services/pppoe-edit/{$ds['plan_id']}">{$ds['namebp']}</a></td>
|
||||||
{/if}
|
{/if}
|
||||||
|
{if $ds['type'] == 'VPN'}
|
||||||
|
<td><a href="{$_url}services/vpn-edit/{$ds['plan_id']}">{$ds['namebp']}</a></td>
|
||||||
|
{/if}
|
||||||
<td>{$ds['type']}</td>
|
<td>{$ds['type']}</td>
|
||||||
<td>{Lang::dateAndTimeFormat($ds['recharged_on'],$ds['recharged_time'])}</td>
|
<td>{Lang::dateAndTimeFormat($ds['recharged_on'],$ds['recharged_time'])}</td>
|
||||||
<td>{Lang::dateAndTimeFormat($ds['expiration'],$ds['time'])}</td>
|
<td>{Lang::dateAndTimeFormat($ds['expiration'],$ds['time'])}</td>
|
||||||
@ -108,8 +113,8 @@
|
|||||||
style="color: black;">{Lang::T('Edit')}</a>
|
style="color: black;">{Lang::T('Edit')}</a>
|
||||||
{if in_array($_admin['user_type'],['SuperAdmin','Admin'])}
|
{if in_array($_admin['user_type'],['SuperAdmin','Admin'])}
|
||||||
<a href="{$_url}plan/delete/{$ds['id']}" id="{$ds['id']}"
|
<a href="{$_url}plan/delete/{$ds['id']}" id="{$ds['id']}"
|
||||||
onclick="return confirm('{Lang::T('Delete')}?')" class="btn btn-danger btn-xs"><i
|
onclick="return confirm('{Lang::T('Delete')}?')"
|
||||||
class="glyphicon glyphicon-trash"></i></a>
|
class="btn btn-danger btn-xs"><i class="glyphicon glyphicon-trash"></i></a>
|
||||||
{/if}
|
{/if}
|
||||||
{if $ds['status']=='off' && $_c['extend_expired']}
|
{if $ds['status']=='off' && $_c['extend_expired']}
|
||||||
<a href="javascript:extend('{$ds['id']}')"
|
<a href="javascript:extend('{$ds['id']}')"
|
||||||
@ -121,6 +126,7 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
{include file="pagination.tpl"}
|
{include file="pagination.tpl"}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -131,7 +137,7 @@
|
|||||||
var res = prompt("Extend for many days?", "3");
|
var res = prompt("Extend for many days?", "3");
|
||||||
if (res) {
|
if (res) {
|
||||||
if (confirm("Extend for " + res + " days?")) {
|
if (confirm("Extend for " + res + " days?")) {
|
||||||
window.location.href = "{$_url}plan/extend/"+idP+"/"+res+"&stoken={App::getToken()}";
|
window.location.href = "{$_url}plan/extend/" + idP + "/" + res + "&stoken={App::getToken()}";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
51
ui/ui/port-add.tpl
Normal file
51
ui/ui/port-add.tpl
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
{include file="sections/header.tpl"}
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12 col-md-12">
|
||||||
|
<div class="panel panel-primary panel-hovered panel-stacked mb30">
|
||||||
|
<div class="panel-heading">{Lang::T('Add Port Pool')}</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
|
||||||
|
<form class="form-horizontal" method="post" role="form" action="{$_url}pool/add-port-post" >
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label">{Lang::T('Port Name')}</label>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input type="text" class="form-control" id="name" name="name" placeholder="Vpn Tunnel">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label">{Lang::T('Public IP')}</label>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input type="text" class="form-control" id="public_ip" name="public_ip" placeholder="12.34.56.78">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label">{Lang::T('Range Port')}</label>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input type="text" class="form-control" id="port_range" name="port_range" placeholder=" 3000-8000">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label"><a href="{$_url}routers/add">{Lang::T('Routers')}</a></label>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<select id="routers" name="routers" class="form-control select2">
|
||||||
|
{foreach $r as $rs}
|
||||||
|
<option value="{$rs['name']}">{$rs['name']}</option>
|
||||||
|
{/foreach}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-lg-offset-2 col-lg-10">
|
||||||
|
<button class="btn btn-primary" type="submit">{Lang::T('Save Changes')}</button>
|
||||||
|
Or <a href="{$_url}pool/port">{Lang::T('Cancel')}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{include file="sections/footer.tpl"}
|
49
ui/ui/port-edit.tpl
Normal file
49
ui/ui/port-edit.tpl
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
{include file="sections/header.tpl"}
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12 col-md-12">
|
||||||
|
<div class="panel panel-primary panel-hovered panel-stacked mb30">
|
||||||
|
<div class="panel-heading">{Lang::T('Edit Port')}</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
|
||||||
|
<form class="form-horizontal" method="post" role="form" action="{$_url}pool/edit-port-post" >
|
||||||
|
<input type="hidden" name="id" value="{$d['id']}">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label">{Lang::T('Port Name')}</label>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input type="text" class="form-control" id="name" name="name" value="{$d['port_name']}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label">{Lang::T('Public IP')}</label>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input type="text" class="form-control" id="public_ip" name="public_ip" value="{$d['public_ip']}" placeholder="12.34.56.78">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label">{Lang::T('Range Port')}</label>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input type="text" class="form-control" id="range_port" name="range_port" value="{$d['range_port']}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label">{Lang::T('Routers')}</label>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input type="text" class="form-control" id="routers" name="routers" value="{$d['routers']}" readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-lg-offset-2 col-lg-10">
|
||||||
|
<button class="btn btn-success" type="submit">{Lang::T('Save Changes')}</button>
|
||||||
|
Or <a href="{$_url}pool/port">{Lang::T('Cancel')}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{include file="sections/footer.tpl"}
|
76
ui/ui/port.tpl
Normal file
76
ui/ui/port.tpl
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
{include file="sections/header.tpl"}
|
||||||
|
<!-- port -->
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<div class="panel panel-hovered mb20 panel-primary">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<div class="btn-group pull-right">
|
||||||
|
<a class="btn btn-primary btn-xs" title="save" href="{$_url}pool/sync"
|
||||||
|
onclick="return confirm('This will sync/send IP port to Mikrotik?')"><span
|
||||||
|
class="glyphicon glyphicon-refresh" aria-hidden="true"></span> sync</a>
|
||||||
|
</div>
|
||||||
|
{Lang::T('Port Pool')} - VPN Tunnels
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="md-whiteframe-z1 mb20 text-center" style="padding: 15px">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<form id="site-search" method="post" action="{$_url}pool/port/">
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-addon">
|
||||||
|
<span class="fa fa-search"></span>
|
||||||
|
</div>
|
||||||
|
<input type="text" name="name" class="form-control"
|
||||||
|
placeholder="{Lang::T('Search by Name')}...">
|
||||||
|
<div class="input-group-btn">
|
||||||
|
<button class="btn btn-success" type="submit">{Lang::T('Search')}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<a href="{$_url}pool/add-port" class="btn btn-primary btn-block"><i
|
||||||
|
class="ion ion-android-add"> </i> {Lang::T('New port')}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-bordered table-striped table-condensed">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>{Lang::T('Port Name')}</th>
|
||||||
|
<th>{Lang::T('Public IP')}</th>
|
||||||
|
<th>{Lang::T('Range Port')}</th>
|
||||||
|
<th>{Lang::T('Routers')}</th>
|
||||||
|
<th>{Lang::T('Manage')}</th>
|
||||||
|
<th>ID</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{foreach $d as $ds}
|
||||||
|
<tr>
|
||||||
|
<td>{$ds['port_name']}</td>
|
||||||
|
<td>{$ds['public_ip']}</td>
|
||||||
|
<td>{$ds['range_port']}</td>
|
||||||
|
<td>{$ds['routers']}</td>
|
||||||
|
<td align="center">
|
||||||
|
<a href="{$_url}pool/edit-port/{$ds['id']}" class="btn btn-info btn-xs">{Lang::T('Edit')}</a>
|
||||||
|
<a href="{$_url}pool/delete-port/{$ds['id']}" id="{$ds['id']}"
|
||||||
|
onclick="return confirm('{Lang::T('Delete')}?')"
|
||||||
|
class="btn btn-danger btn-xs"><i class="glyphicon glyphicon-trash"></i></a>
|
||||||
|
</td>
|
||||||
|
<td>{$ds['id']}</td>
|
||||||
|
</tr>
|
||||||
|
{/foreach}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{include file="pagination.tpl"}
|
||||||
|
<div class="bs-callout bs-callout-info" id="callout-navbar-role">
|
||||||
|
<h4>{Lang::T('Create expired Internet Plan')}</h4>
|
||||||
|
<p>{Lang::T('When customer expired, you can move it to Expired Internet Plan')}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{include file="sections/footer.tpl"}
|
@ -104,6 +104,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
|
<div style="margin-left: 5px; margin-right: 5px;">
|
||||||
<table class="table table-bordered table-striped table-condensed">
|
<table class="table table-bordered table-striped table-condensed">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@ -131,9 +132,10 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{foreach $d as $ds}
|
{foreach $d as $ds}
|
||||||
<tr {if $ds['enabled'] != 1}class="danger" title="disabled" {/if}>
|
<tr {if $ds['enabled'] !=1}class="danger" title="disabled" {/if}>
|
||||||
<td>{$ds['name_plan']}</td>
|
<td>{$ds['name_plan']}</td>
|
||||||
<td>{$ds['plan_type']} {if $ds['prepaid'] != 'yes'}<b>{Lang::T('Postpaid')}</b>{else}{Lang::T('Prepaid')}{/if}</td>
|
<td>{$ds['plan_type']} {if $ds['prepaid'] !=
|
||||||
|
'yes'}<b>{Lang::T('Postpaid')}</b>{else}{Lang::T('Prepaid')}{/if}</td>
|
||||||
<td>{$ds['name_bw']}</td>
|
<td>{$ds['name_bw']}</td>
|
||||||
<td>{Lang::moneyFormat($ds['price'])}</td>
|
<td>{Lang::moneyFormat($ds['price'])}</td>
|
||||||
<td>{$ds['validity']} {$ds['validity_unit']}</td>
|
<td>{$ds['validity']} {$ds['validity_unit']}</td>
|
||||||
@ -165,6 +167,7 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div class="panel-footer">
|
<div class="panel-footer">
|
||||||
{include file="pagination.tpl"}
|
{include file="pagination.tpl"}
|
||||||
<div class="bs-callout bs-callout-info" id="callout-navbar-role">
|
<div class="bs-callout bs-callout-info" id="callout-navbar-role">
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label><input type="radio" id="Hot" name="type" value="Hotspot"> {Lang::T('Hotspot Plans')}</label>
|
<label><input type="radio" id="Hot" name="type" value="Hotspot"> {Lang::T('Hotspot Plans')}</label>
|
||||||
<label><input type="radio" id="POE" name="type" value="PPPOE"> {Lang::T('PPPOE Plans')}</label>
|
<label><input type="radio" id="POE" name="type" value="PPPOE"> {Lang::T('PPPOE Plans')}</label>
|
||||||
|
<label><input type="radio" id="VPN" name="type" value="VPN"> {Lang::T('VPN Plans')}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
@ -96,7 +96,7 @@ $(function() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
}else{
|
} else if ($('#POE').is(':checked')) {
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "POST",
|
type: "POST",
|
||||||
dataType: "html",
|
dataType: "html",
|
||||||
@ -117,6 +117,27 @@ $(function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
$.ajax({
|
||||||
|
type: "POST",
|
||||||
|
dataType: "html",
|
||||||
|
url: "index.php?_route=autoload/server",
|
||||||
|
success: function(msg){
|
||||||
|
$("#server").html(msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$("#server").change(function(){
|
||||||
|
var server = $("#server").val();
|
||||||
|
$.ajax({
|
||||||
|
type: "POST",
|
||||||
|
dataType: "html",
|
||||||
|
url: "index.php?_route=autoload/plan",
|
||||||
|
data: "jenis=VPN&server="+server,
|
||||||
|
success: function(msg){
|
||||||
|
$("#plan").html(msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -148,12 +148,45 @@
|
|||||||
color: inherit;
|
color: inherit;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
|
border-bottom-right-radius: 21px;
|
||||||
|
border-bottom-left-radius: 21px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-primary>.panel-heading {
|
.panel-success>.panel-heading {
|
||||||
color: inherit;
|
border-bottom-right-radius: 21px;
|
||||||
background-color: transparent;
|
border-bottom-left-radius: 21px;
|
||||||
border-color: transparent;
|
}
|
||||||
|
|
||||||
|
.panel-cron-success>.panel-heading {
|
||||||
|
border-bottom-right-radius: 21px;
|
||||||
|
border-bottom-left-radius: 21px;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #169210;
|
||||||
|
border-color: #25e01c;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-cron-warning>.panel-heading {
|
||||||
|
border-bottom-right-radius: 21px;
|
||||||
|
border-bottom-left-radius: 21px;
|
||||||
|
color: #350808;
|
||||||
|
background-color: #efeb0a;
|
||||||
|
border-color: #efeb0a;
|
||||||
|
}
|
||||||
|
.panel-cron-danger>.panel-heading {
|
||||||
|
border-bottom-right-radius: 21px;
|
||||||
|
border-bottom-left-radius: 21px;
|
||||||
|
color: #fff;
|
||||||
|
background-color: #e61212;
|
||||||
|
border-color: #df1335;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-danger>.panel-heading {
|
||||||
|
color: #a94442;
|
||||||
|
background-color: #f2dede;
|
||||||
|
border-color: #ebccd1;
|
||||||
|
border-bottom-right-radius: 21px;
|
||||||
|
border-bottom-left-radius: 21px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.panel-heading {
|
.panel-heading {
|
||||||
@ -656,9 +689,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.toggle-container {
|
.toggle-container {
|
||||||
position: absolute;
|
|
||||||
top: 17px;
|
|
||||||
right: 15px;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -668,19 +698,6 @@
|
|||||||
transition: color 0.5s ease;
|
transition: color 0.5s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
|
||||||
.toggle-container {
|
|
||||||
top: 15px;
|
|
||||||
right: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toggle-container .toggle-icon {
|
|
||||||
font-size: 20px;
|
|
||||||
color: rgb(100 116 139);
|
|
||||||
transition: color 0.5s ease;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark-mode .toggle-container .toggle-icon {
|
.dark-mode .toggle-container .toggle-icon {
|
||||||
color: #ffdd57;
|
color: #ffdd57;
|
||||||
}
|
}
|
||||||
@ -1157,9 +1174,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<li>
|
<li>
|
||||||
<div class="toggle-container">
|
<a class="toggle-container" href="#">
|
||||||
<i class="toggle-icon" id="toggleIcon">🌞</i>
|
<i class="toggle-icon" id="toggleIcon">🌞</i>
|
||||||
</div>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown user user-menu">
|
<li class="dropdown user user-menu">
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||||
@ -1269,6 +1286,8 @@
|
|||||||
href="{$_url}services/hotspot">Hotspot</a></li>
|
href="{$_url}services/hotspot">Hotspot</a></li>
|
||||||
<li {if $_routes[1] eq 'pppoe' }class="active" {/if}><a
|
<li {if $_routes[1] eq 'pppoe' }class="active" {/if}><a
|
||||||
href="{$_url}services/pppoe">PPPOE</a></li>
|
href="{$_url}services/pppoe">PPPOE</a></li>
|
||||||
|
<li {if $_routes[1] eq 'vpn' }class="active" {/if}><a
|
||||||
|
href="{$_url}services/vpn">VPN</a></li>
|
||||||
<li {if $_routes[1] eq 'list' }class="active" {/if}><a
|
<li {if $_routes[1] eq 'list' }class="active" {/if}><a
|
||||||
href="{$_url}bandwidth/list">Bandwidth</a></li>
|
href="{$_url}bandwidth/list">Bandwidth</a></li>
|
||||||
{if $_c['enable_balance'] == 'yes'}
|
{if $_c['enable_balance'] == 'yes'}
|
||||||
@ -1327,6 +1346,8 @@
|
|||||||
href="{$_url}routers">Routers</a></li>
|
href="{$_url}routers">Routers</a></li>
|
||||||
<li {if $_routes[0] eq 'pool' and $_routes[1] eq 'list' }class="active" {/if}><a
|
<li {if $_routes[0] eq 'pool' and $_routes[1] eq 'list' }class="active" {/if}><a
|
||||||
href="{$_url}pool/list">IP Pool</a></li>
|
href="{$_url}pool/list">IP Pool</a></li>
|
||||||
|
<li {if $_routes[0] eq 'pool' and $_routes[1] eq 'port' }class="active" {/if}><a
|
||||||
|
href="{$_url}pool/port">Port Pool</a></li>
|
||||||
<li {if $_routes[0] eq 'routers' and $_routes[1] eq 'maps' }class="active" {/if}><a
|
<li {if $_routes[0] eq 'routers' and $_routes[1] eq 'maps' }class="active" {/if}><a
|
||||||
href="{$_url}routers/maps">{Lang::T('Routers Maps')}</a></li>
|
href="{$_url}routers/maps">{Lang::T('Routers Maps')}</a></li>
|
||||||
{$_MENU_NETWORK}
|
{$_MENU_NETWORK}
|
||||||
|
@ -88,6 +88,8 @@
|
|||||||
Hotspot
|
Hotspot
|
||||||
{elseif $_user.service_type == 'PPPoE'}
|
{elseif $_user.service_type == 'PPPoE'}
|
||||||
PPPoE
|
PPPoE
|
||||||
|
{elseif $_user.service_type == 'VPN'}
|
||||||
|
VPN
|
||||||
{elseif $_user.service_type == 'Others' || $_user.service_type == null}
|
{elseif $_user.service_type == 'Others' || $_user.service_type == null}
|
||||||
Others
|
Others
|
||||||
{/if}
|
{/if}
|
||||||
@ -165,8 +167,10 @@
|
|||||||
<div class="btn-group pull-right">
|
<div class="btn-group pull-right">
|
||||||
{if $_bill['type'] == 'Hotspot'}
|
{if $_bill['type'] == 'Hotspot'}
|
||||||
{if $_c['hotspot_plan']==''}Hotspot Plan{else}{$_c['hotspot_plan']}{/if}
|
{if $_c['hotspot_plan']==''}Hotspot Plan{else}{$_c['hotspot_plan']}{/if}
|
||||||
{else}
|
{else if $_bill['type'] == 'PPPOE'}
|
||||||
{if $_c['pppoe_plan']==''}PPPOE Plan{else}{$_c['pppoe_plan']}{/if}
|
{if $_c['pppoe_plan']==''}PPPOE Plan{else}{$_c['pppoe_plan']}{/if}
|
||||||
|
{else if $_bill['type'] == 'VPN'}
|
||||||
|
{if $_c['pppoe_plan']==''}VPN Plan{else}{$_c['vpn_plan']}{/if}
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -215,6 +219,25 @@
|
|||||||
{$_bill['plan_type']}
|
{$_bill['plan_type']}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
{if $_bill['type'] == 'VPN' && $_bill['routers'] == $vpn['routers']}
|
||||||
|
<tr>
|
||||||
|
<td class="small text-success text-uppercase text-normal">{Lang::T('Public IP')}</td>
|
||||||
|
<td class="small mb15">{$vpn['public_ip']} / {$vpn['port_name']}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="small text-success text-uppercase text-normal">{Lang::T('Private IP')}</td>
|
||||||
|
<td class="small mb15">{$_user['pppoe_ip']}</td>
|
||||||
|
</tr>
|
||||||
|
{foreach $cf as $tcf}
|
||||||
|
<tr>
|
||||||
|
{if $tcf['field_name'] == 'Winbox' or $tcf['field_name'] == 'Api' or $tcf['field_name'] == 'Web'}
|
||||||
|
<td class="small text-info text-uppercase text-normal">{$tcf['field_name']} - Port</td>
|
||||||
|
<td class="small mb15"><a href="http://{$vpn['public_ip']}:{$tcf['field_value']}" target="_blank">{$tcf['field_value']}</a></td>
|
||||||
|
</tr>
|
||||||
|
{/if}
|
||||||
|
{/foreach}
|
||||||
|
{/if}
|
||||||
|
|
||||||
{if $nux_ip neq ''}
|
{if $nux_ip neq ''}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="small text-primary text-uppercase text-normal">{Lang::T('Current IP')}</td>
|
<td class="small text-primary text-uppercase text-normal">{Lang::T('Current IP')}</td>
|
||||||
|
@ -333,9 +333,6 @@
|
|||||||
|
|
||||||
|
|
||||||
.toggle-container {
|
.toggle-container {
|
||||||
position: absolute;
|
|
||||||
top: 17px;
|
|
||||||
right: 15px;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,10 +343,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
.toggle-container {
|
|
||||||
top: 15px;
|
|
||||||
right: 200px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.toggle-container .toggle-icon {
|
.toggle-container .toggle-icon {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
@ -781,13 +774,13 @@
|
|||||||
<div class="navbar-custom-menu">
|
<div class="navbar-custom-menu">
|
||||||
<ul class="nav navbar-nav">
|
<ul class="nav navbar-nav">
|
||||||
<li>
|
<li>
|
||||||
<div class="toggle-container">
|
<a class="toggle-container" href="#">
|
||||||
<i class="toggle-icon" id="toggleIcon">🌞</i>
|
<i class="toggle-icon" id="toggleIcon">🌞</i>
|
||||||
</div>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="dropdown tasks-menu">
|
<li class="dropdown tasks-menu">
|
||||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="true">
|
<a href="#" class="dropdown-toggle" data-toggle="dropdown" aria-expanded="true">
|
||||||
<i class="fa fa-flag-o"></i> <span class="d-none d-sm-inline">{ucwords($user_language)}</span>
|
<i class="fa fa-flag-o"></i>
|
||||||
</a>
|
</a>
|
||||||
<ul class="dropdown-menu">
|
<ul class="dropdown-menu">
|
||||||
<li>
|
<li>
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
{if Text::is_html($mail['body'])}
|
{if Text::is_html($mail['body'])}
|
||||||
{$mail['body']}
|
{$mail['body']}
|
||||||
{else}
|
{else}
|
||||||
{nl2br($mail['body'])}
|
{nl2br(htmlspecialchars_decode($mail['body']))}
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -29,10 +29,11 @@
|
|||||||
{Lang::T("Next")}</a>
|
{Lang::T("Next")}</a>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
<a href="{$_url}mail" class="btn btn-primary"><i class="fa fa-arrow-left"></i> {Lang::T("Back")}</a>
|
||||||
<a href="{$_url}mail/delete/{$mail['id']}" class="btn btn-danger"
|
<a href="{$_url}mail/delete/{$mail['id']}" class="btn btn-danger"
|
||||||
onclick="return confirm('{Lang::T("Delete")}?')"><i class="fa fa-trash-o"></i>
|
onclick="return confirm('{Lang::T("Delete")}?')"><i class="fa fa-trash-o"></i>
|
||||||
{Lang::T("Delete")}</a>
|
{Lang::T("Delete")}</a>
|
||||||
<a href="https://api.whatsapp.com/send?text={if Text::is_html($mail['body'])}{urlencode(strip_tags($mail['body']))}{else}{urlencode($mail['body'])}{/if}" class="btn btn-primary"><i class="fa fa-share"></i> {Lang::T("Share")}</a>
|
<a href="https://api.whatsapp.com/send?text={if Text::is_html($mail['body'])}{urlencode(strip_tags($mail['body']))}{else}{urlencode($mail['body'])}{/if}" class="btn btn-success"><i class="fa fa-share"></i> {Lang::T("Share")}</a>
|
||||||
</div>
|
</div>
|
||||||
<!-- /.box-footer -->
|
<!-- /.box-footer -->
|
||||||
</div>
|
</div>
|
||||||
|
@ -226,6 +226,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
{foreach $routers as $router}
|
{foreach $routers as $router}
|
||||||
{if Validator::isRouterHasPlan($plans_hotspot, $router['name']) || Validator::isRouterHasPlan($plans_pppoe,
|
{if Validator::isRouterHasPlan($plans_hotspot, $router['name']) || Validator::isRouterHasPlan($plans_pppoe,
|
||||||
|
$router['name']) || Validator::isRouterHasPlan($plans_vpn,
|
||||||
$router['name'])}
|
$router['name'])}
|
||||||
<div class="box box-solid box-primary bg-gray">
|
<div class="box box-solid box-primary bg-gray">
|
||||||
<div class="box-header text-white text-bold">{$router['name']}</div>
|
<div class="box-header text-white text-bold">{$router['name']}</div>
|
||||||
@ -338,9 +339,62 @@
|
|||||||
{/if}
|
{/if}
|
||||||
{/foreach}
|
{/foreach}
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
||||||
|
{if $_user['service_type'] == 'VPN' && Validator::countRouterPlan($plans_vpn,$router['name'])>0}
|
||||||
|
<div class="box-header text-white">{if $_c['vpn_plan']==''}VPN Plan{else}{$_c['vpn_plan']}{/if}</div>
|
||||||
|
<div class="box-body row">
|
||||||
|
{foreach $plans_vpn as $plan}
|
||||||
|
{if $router['name'] eq $plan['routers']}
|
||||||
|
<div class="col col-md-4">
|
||||||
|
<div class="box box- box-primary">
|
||||||
|
<div class="box-header text-bold text-center">{$plan['name_plan']}</div>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<div style="margin-left: 5px; margin-right: 5px;">
|
||||||
|
<table class="table table-bordered table-striped">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>{Lang::T('Type')}</td>
|
||||||
|
<td>{$plan['type']}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{Lang::T('Price')}</td>
|
||||||
|
<td>{Lang::moneyFormat($plan['price'])}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{Lang::T('Validity')}</td>
|
||||||
|
<td>{$plan['validity']} {$plan['validity_unit']}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box-body">
|
||||||
|
<div class="btn-group btn-group-justified" role="group" aria-label="...">
|
||||||
|
<a href="{$_url}order/gateway/{$router['id']}/{$plan['id']}&stoken={App::getToken()}"
|
||||||
|
onclick="return confirm('{Lang::T('Buy this? your active package will be overwrite')}')"
|
||||||
|
class="btn btn-sm btn-block btn-warning text-black">{Lang::T('Buy')}</a>
|
||||||
|
{if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']}
|
||||||
|
<a href="{$_url}order/pay/{$router['id']}/{$plan['id']}&stoken={App::getToken()}"
|
||||||
|
onclick="return confirm('{Lang::T('Pay this with Balance? your active package will be overwrite')}')"
|
||||||
|
class="btn btn-sm btn-block btn-success">{Lang::T('Pay With Balance')}</a>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' &&
|
||||||
|
$_user['balance']>=$plan['price']}
|
||||||
|
<a href="{$_url}order/send/{$router['id']}/{$plan['id']}&stoken={App::getToken()}"
|
||||||
|
onclick="return confirm('{Lang::T('Buy this for friend account?')}')"
|
||||||
|
class="btn btn-sm btn-block btn-primary">{Lang::T('Buy for friend')}</a>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{/foreach}
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{if $_user['service_type'] == 'Others' || $_user['service_type'] == '' &&
|
{if $_user['service_type'] == 'Others' || $_user['service_type'] == '' &&
|
||||||
(Validator::countRouterPlan($plans_hotspot, $router['name'])>0 || Validator::countRouterPlan($plans_pppoe,
|
(Validator::countRouterPlan($plans_hotspot, $router['name'])>0 || Validator::countRouterPlan($plans_pppoe,
|
||||||
|
$router['name'])>0 || Validator::countRouterPlan($plans_vpn,
|
||||||
$router['name'])>0)}
|
$router['name'])>0)}
|
||||||
<div class="box-header text-white">{if $_c['hotspot_plan']==''}Hotspot Plan{else}{$_c['hotspot_plan']}{/if}
|
<div class="box-header text-white">{if $_c['hotspot_plan']==''}Hotspot Plan{else}{$_c['hotspot_plan']}{/if}
|
||||||
</div>
|
</div>
|
||||||
@ -443,6 +497,56 @@
|
|||||||
{/if}
|
{/if}
|
||||||
{/foreach}
|
{/foreach}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="box-header text-white">{if $_c['vpn_plan']==''}VPN Plan{else}{$_c['vpn_plan']}{/if}</div>
|
||||||
|
<div class="box-body row">
|
||||||
|
{foreach $plans_vpn as $plan}
|
||||||
|
{if $router['name'] eq $plan['routers']}
|
||||||
|
<div class="col col-md-4">
|
||||||
|
<div class="box box- box-primary">
|
||||||
|
<div class="box-header text-bold text-center">{$plan['name_plan']}</div>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<div style="margin-left: 5px; margin-right: 5px;">
|
||||||
|
<table class="table table-bordered table-striped">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>{Lang::T('Type')}</td>
|
||||||
|
<td>{$plan['type']}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{Lang::T('Price')}</td>
|
||||||
|
<td>{Lang::moneyFormat($plan['price'])}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>{Lang::T('Validity')}</td>
|
||||||
|
<td>{$plan['validity']} {$plan['validity_unit']}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="box-body">
|
||||||
|
<div class="btn-group btn-group-justified" role="group" aria-label="...">
|
||||||
|
<a href="{$_url}order/gateway/{$router['id']}/{$plan['id']}&stoken={App::getToken()}"
|
||||||
|
onclick="return confirm('{Lang::T('Buy this? your active package will be overwrite')}')"
|
||||||
|
class="btn btn-sm btn-block btn-warning text-black">{Lang::T('Buy')}</a>
|
||||||
|
{if $_c['enable_balance'] == 'yes' && $_user['balance']>=$plan['price']}
|
||||||
|
<a href="{$_url}order/pay/{$router['id']}/{$plan['id']}&stoken={App::getToken()}"
|
||||||
|
onclick="return confirm('{Lang::T('Pay this with Balance? your active package will be overwrite')}')"
|
||||||
|
class="btn btn-sm btn-block btn-success">{Lang::T('Pay With Balance')}</a>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{if $_c['enable_balance'] == 'yes' && $_c['allow_balance_transfer'] == 'yes' &&
|
||||||
|
$_user['balance']>=$plan['price']}
|
||||||
|
<a href="{$_url}order/send/{$router['id']}/{$plan['id']}&stoken={App::getToken()}"
|
||||||
|
onclick="return confirm('{Lang::T('Buy this for friend account?')}')"
|
||||||
|
class="btn btn-sm btn-block btn-primary">{Lang::T('Buy for friend')}</a>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{/foreach}
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -19,8 +19,9 @@
|
|||||||
{if in_array($_admin['user_type'],['SuperAdmin','Admin'])}
|
{if in_array($_admin['user_type'],['SuperAdmin','Admin'])}
|
||||||
<div class="btn-group pull-right">
|
<div class="btn-group pull-right">
|
||||||
<a class="btn btn-danger btn-xs" title="Remove used Voucher" href="{$_url}plan/remove-voucher"
|
<a class="btn btn-danger btn-xs" title="Remove used Voucher" href="{$_url}plan/remove-voucher"
|
||||||
onclick="return confirm('Delete all used voucher code more than 3 months?')"><span class="glyphicon glyphicon-trash"
|
onclick="return confirm('Delete all used voucher code more than 3 months?')"><span
|
||||||
aria-hidden="true"></span> {Lang::T('Delete')} > {Lang::T('3 Months')}</a>
|
class="glyphicon glyphicon-trash" aria-hidden="true"></span> {Lang::T('Delete')} > {Lang::T('3
|
||||||
|
Months')}</a>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
@ -76,8 +77,8 @@
|
|||||||
class="fa fa-search"></span></button>
|
class="fa fa-search"></span></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="btn-group" role="group">
|
<div class="btn-group" role="group">
|
||||||
<a class="btn btn-warning btn-block" title="Clear Search Query" href="{$_url}plan/voucher/"><span
|
<a class="btn btn-warning btn-block" title="Clear Search Query"
|
||||||
class="glyphicon glyphicon-remove-circle"></span></a>
|
href="{$_url}plan/voucher/"><span class="glyphicon glyphicon-remove-circle"></span></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -85,6 +86,7 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
|
<div style="margin-left: 5px; margin-right: 5px;">
|
||||||
<table id="datatable" class="table table-bordered table-striped table-condensed">
|
<table id="datatable" class="table table-bordered table-striped table-condensed">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@ -102,7 +104,7 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{foreach $d as $ds}
|
{foreach $d as $ds}
|
||||||
<tr {if $ds['status'] eq '1'}class="danger" {/if}>
|
<tr {if $ds['status'] eq '1' }class="danger" {/if}>
|
||||||
<td>{$ds['id']}</td>
|
<td>{$ds['id']}</td>
|
||||||
<td>{$ds['type']}</td>
|
<td>{$ds['type']}</td>
|
||||||
<td>{$ds['routers']}</td>
|
<td>{$ds['routers']}</td>
|
||||||
@ -119,7 +121,8 @@
|
|||||||
{/if}</td>
|
{/if}</td>
|
||||||
<td>{if $ds['used_date']}{Lang::dateTimeFormat($ds['used_date'])}{/if}</td>
|
<td>{if $ds['used_date']}{Lang::dateTimeFormat($ds['used_date'])}{/if}</td>
|
||||||
<td>{if $ds['generated_by']}
|
<td>{if $ds['generated_by']}
|
||||||
<a href="{$_url}settings/users-view/{$ds['generated_by']}">{$admins[$ds['generated_by']]}</a>
|
<a
|
||||||
|
href="{$_url}settings/users-view/{$ds['generated_by']}">{$admins[$ds['generated_by']]}</a>
|
||||||
{else} -
|
{else} -
|
||||||
{/if}
|
{/if}
|
||||||
</td>
|
</td>
|
||||||
@ -129,8 +132,8 @@
|
|||||||
class="btn btn-success btn-xs"> {Lang::T('View')} </a>
|
class="btn btn-success btn-xs"> {Lang::T('View')} </a>
|
||||||
{/if}
|
{/if}
|
||||||
{if in_array($_admin['user_type'],['SuperAdmin','Admin'])}
|
{if in_array($_admin['user_type'],['SuperAdmin','Admin'])}
|
||||||
<a href="{$_url}plan/voucher-delete/{$ds['id']}" id="{$ds['id']}" class="btn btn-danger btn-xs"
|
<a href="{$_url}plan/voucher-delete/{$ds['id']}" id="{$ds['id']}"
|
||||||
onclick="return confirm('{Lang::T('Delete')}?')"><i
|
class="btn btn-danger btn-xs" onclick="return confirm('{Lang::T('Delete')}?')"><i
|
||||||
class="glyphicon glyphicon-trash"></i></a>
|
class="glyphicon glyphicon-trash"></i></a>
|
||||||
{/if}
|
{/if}
|
||||||
</td>
|
</td>
|
||||||
@ -139,6 +142,7 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
{include file="pagination.tpl"}
|
{include file="pagination.tpl"}
|
||||||
</div>
|
</div>
|
||||||
{include file="sections/footer.tpl"}
|
{include file="sections/footer.tpl"}
|
188
ui/ui/vpn-add.tpl
Normal file
188
ui/ui/vpn-add.tpl
Normal file
@ -0,0 +1,188 @@
|
|||||||
|
{include file="sections/header.tpl"}
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12 col-md-12">
|
||||||
|
<div class="panel panel-primary panel-hovered panel-stacked mb30">
|
||||||
|
<div class="panel-heading">{Lang::T('Add Service Plan')}</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<form class="form-horizontal" method="post" role="form" action="{$_url}services/vpn-add-post">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label">{Lang::T('Status')}
|
||||||
|
<a tabindex="0" class="btn btn-link btn-xs" role="button" data-toggle="popover"
|
||||||
|
data-trigger="focus" data-container="body"
|
||||||
|
data-content="Customer cannot buy disabled Plan, but admin can recharge it, use it if you want only admin recharge it">?</a>
|
||||||
|
</label>
|
||||||
|
<div class="col-md-10">
|
||||||
|
<input type="radio" checked name="enabled" value="1"> {Lang::T('Enable')}
|
||||||
|
<input type="radio" name="enabled" value="0"> {Lang::T('Disable')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label">{Lang::T('Type')}
|
||||||
|
<a tabindex="0" class="btn btn-link btn-xs" role="button" data-toggle="popover"
|
||||||
|
data-trigger="focus" data-container="body"
|
||||||
|
data-content="Postpaid will have fix expired date">?</a>
|
||||||
|
</label>
|
||||||
|
<div class="col-md-10">
|
||||||
|
<input type="radio" name="prepaid" onclick="prePaid()" value="yes" checked> {Lang::T('Prepaid')}
|
||||||
|
<input type="radio" name="prepaid" onclick="postPaid()" value="no"> {Lang::T('Postpaid')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label">{Lang::T('Plan Type')}
|
||||||
|
<a tabindex="0" class="btn btn-link btn-xs" role="button" data-toggle="popover"
|
||||||
|
data-trigger="focus" data-container="body"
|
||||||
|
data-content="Personal Plan will only show to personal Customer, Business plan will only show to Business Customer">?</a>
|
||||||
|
</label>
|
||||||
|
<div class="col-md-10">
|
||||||
|
<input type="radio" name="plan_type" value="Personal" checked> {Lang::T('Personal')}
|
||||||
|
<input type="radio" name="plan_type" value="Business"> {Lang::T('Business')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label">{Lang::T('Device')}
|
||||||
|
<a tabindex="0" class="btn btn-link btn-xs" role="button" data-toggle="popover"
|
||||||
|
data-trigger="focus" data-container="body"
|
||||||
|
data-content="This Device are the logic how PHPNuxBill Communicate with Mikrotik or other Devices">?</a>
|
||||||
|
</label>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<select class="form-control" id="device" name="device">
|
||||||
|
{foreach $devices as $dev}
|
||||||
|
<option value="{$dev}" {if $dev == 'MikrotikVpn'}selected{/if}>{$dev}</option>
|
||||||
|
{/foreach}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label">{Lang::T('Plan Name')}</label>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input type="text" class="form-control" id="name_plan" maxlength="40" name="name_plan">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label"><a
|
||||||
|
href="{$_url}bandwidth/add">{Lang::T('Bandwidth Name')}</a></label>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<select id="id_bw" name="id_bw" class="form-control select2">
|
||||||
|
<option value="">{Lang::T('Select Bandwidth')}...</option>
|
||||||
|
{foreach $d as $ds}
|
||||||
|
<option value="{$ds['id']}">{$ds['name_bw']}</option>
|
||||||
|
{/foreach}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label">{Lang::T('Plan Price')}</label>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-addon">{$_c['currency_code']}</span>
|
||||||
|
<input type="number" class="form-control" name="price" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{if $_c['enable_tax'] == 'yes'}
|
||||||
|
{if $_c['tax_rate'] == 'custom'}
|
||||||
|
<p class="help-block col-md-4">{number_format($_c['custom_tax_rate'], 2)} % {Lang::T('Tax Rates
|
||||||
|
will be added')}</p>
|
||||||
|
{else}
|
||||||
|
<p class="help-block col-md-4">{number_format($_c['tax_rate'] * 100, 2)} % {Lang::T('Tax Rates
|
||||||
|
will be added')}</p>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label">{Lang::T('Plan Validity')}</label>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<input type="text" class="form-control" id="validity" name="validity">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-2">
|
||||||
|
<select class="form-control" id="validity_unit" name="validity_unit">
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<p class="help-block col-md-4">{Lang::T('1 Period = 1 Month, Expires the 20th of each month')}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="form-group hidden" id="expired_date">
|
||||||
|
<label class="col-md-2 control-label">{Lang::T('Expired Date')}
|
||||||
|
<a tabindex="0" class="btn btn-link btn-xs" role="button" data-toggle="popover"
|
||||||
|
data-trigger="focus" data-container="body"
|
||||||
|
data-content="Expired will be this date every month">?</a>
|
||||||
|
</label>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<input type="number" class="form-control" name="expired_date" maxlength="2" value="20" min="1" max="28" step="1" >
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label"><a
|
||||||
|
href="{$_url}routers/add">{Lang::T('Router Name')}</a></label>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<select id="routers" name="routers" required class="form-control select2">
|
||||||
|
<option value=''>{Lang::T('Select Routers')}</option>
|
||||||
|
{foreach $r as $rs}
|
||||||
|
<option value="{$rs['name']}">{$rs['name']}</option>
|
||||||
|
{/foreach}
|
||||||
|
</select>
|
||||||
|
<p class="help-block">{Lang::T('Cannot be change after saved')}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-2 control-label"><a href="{$_url}pool/add">{Lang::T('IP Pool')}</a></label>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<select id="pool_name" name="pool_name" required class="form-control select2">
|
||||||
|
<option value=''>{Lang::T('Select Pool')}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-md-offset-2 col-md-10">
|
||||||
|
<button class="btn btn-primary" type="submit">{Lang::T('Save Changes')}</button>
|
||||||
|
Or <a href="{$_url}services/pppoe">{Lang::T('Cancel')}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
var preOpt = `<option value="Mins">{Lang::T('Mins')}</option>
|
||||||
|
<option value="Hrs">{Lang::T('Hrs')}</option>
|
||||||
|
<option value="Days">{Lang::T('Days')}</option>
|
||||||
|
<option value="Months">{Lang::T('Months')}</option>`;
|
||||||
|
var postOpt = `<option value="Period">{Lang::T('Period')}</option>`;
|
||||||
|
function prePaid() {
|
||||||
|
$("#validity_unit").html(preOpt);
|
||||||
|
$('#expired_date').addClass('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
function postPaid() {
|
||||||
|
$("#validity_unit").html(postOpt);
|
||||||
|
$("#expired_date").removeClass('hidden');
|
||||||
|
}
|
||||||
|
document.addEventListener("DOMContentLoaded", function(event) {
|
||||||
|
prePaid()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
{if $_c['radius_enable']}
|
||||||
|
{literal}
|
||||||
|
<script>
|
||||||
|
function isRadius(cek) {
|
||||||
|
if (cek.checked) {
|
||||||
|
document.getElementById("routers").required = false;
|
||||||
|
document.getElementById("routers").disabled = true;
|
||||||
|
$.ajax({
|
||||||
|
url: "index.php?_route=autoload/pool",
|
||||||
|
data: "routers=radius",
|
||||||
|
cache: false,
|
||||||
|
success: function(msg) {
|
||||||
|
$("#pool_name").html(msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
document.getElementById("routers").required = true;
|
||||||
|
document.getElementById("routers").disabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{/literal}
|
||||||
|
{/if}
|
||||||
|
{include file="sections/footer.tpl"}
|
255
ui/ui/vpn-edit.tpl
Normal file
255
ui/ui/vpn-edit.tpl
Normal file
@ -0,0 +1,255 @@
|
|||||||
|
{include file="sections/header.tpl"}
|
||||||
|
|
||||||
|
<form class="form-horizontal" method="post" role="form" action="{$_url}services/edit-vpn-post">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="panel panel-primary panel-hovered panel-stacked mb30">
|
||||||
|
<div class="panel-heading">{Lang::T('Edit Service Plan')} || {$d['name_plan']}</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<input type="hidden" name="id" value="{$d['id']}">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-3 control-label">{Lang::T('Status')}
|
||||||
|
<a tabindex="0" class="btn btn-link btn-xs" role="button" data-toggle="popover"
|
||||||
|
data-trigger="focus" data-container="body"
|
||||||
|
data-content="Customer cannot buy disabled Plan, but admin can recharge it, use it if you want only admin recharge it">?</a>
|
||||||
|
</label>
|
||||||
|
<div class="col-md-9">
|
||||||
|
<input type="radio" name="enabled" value="1" {if $d['enabled'] == 1}checked{/if}> {Lang::T('Enable')}
|
||||||
|
<input type="radio" name="enabled" value="0" {if $d['enabled'] == 0}checked{/if}> {Lang::T('Disable')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-3 control-label">{Lang::T('Type')}
|
||||||
|
<a tabindex="0" class="btn btn-link btn-xs" role="button" data-toggle="popover"
|
||||||
|
data-trigger="focus" data-container="body"
|
||||||
|
data-content="Postpaid will have fix expired date">?</a>
|
||||||
|
</label>
|
||||||
|
<div class="col-md-9">
|
||||||
|
<input type="radio" name="prepaid" onclick="prePaid()" value="yes"
|
||||||
|
{if $d['prepaid'] == 'yes'}checked{/if}>
|
||||||
|
{Lang::T('Prepaid')}
|
||||||
|
<input type="radio" name="prepaid" onclick="postPaid()" value="no"
|
||||||
|
{if $d['prepaid'] == 'no'}checked{/if}> {Lang::T('Postpaid')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-3 control-label">{Lang::T('Plan Type')}
|
||||||
|
<a tabindex="0" class="btn btn-link btn-xs" role="button" data-toggle="popover"
|
||||||
|
data-trigger="focus" data-container="body"
|
||||||
|
data-content="Personal Plan will only show to personal Customer, Business plan will only show to Business Customer">?</a>
|
||||||
|
</label>
|
||||||
|
<div class="col-md-9">
|
||||||
|
<input type="radio" name="plan_type" value="Personal"
|
||||||
|
{if $d['plan_type'] == 'Personal'}checked{/if}>
|
||||||
|
{Lang::T('Personal')}
|
||||||
|
<input type="radio" name="plan_type" value="Business"
|
||||||
|
{if $d['plan_type'] == 'Business'}checked{/if}> {Lang::T('Business')}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{if $_c['radius_enable'] and $d['is_radius']}
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-3 control-label">Radius
|
||||||
|
<a tabindex="0" class="btn btn-link btn-xs" role="button" data-toggle="popover"
|
||||||
|
data-trigger="focus" data-container="body"
|
||||||
|
data-content="If you enable Radius, choose device to radius, except if you have custom device.">?</a>
|
||||||
|
</label>
|
||||||
|
<div class="col-md-9">
|
||||||
|
<label class="label label-primary">RADIUS</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-3 control-label">{Lang::T('Device')}
|
||||||
|
<a tabindex="0" class="btn btn-link btn-xs" role="button" data-toggle="popover"
|
||||||
|
data-trigger="focus" data-container="body"
|
||||||
|
data-content="This Device are the logic how PHPNuxBill Communicate with Mikrotik or other Devices">?</a>
|
||||||
|
</label>
|
||||||
|
<div class="col-md-9">
|
||||||
|
<select class="form-control" id="device" name="device">
|
||||||
|
{foreach $devices as $dev}
|
||||||
|
<option value="{$dev}" {if $dev == $d['device']}selected{/if}>{$dev}</option>
|
||||||
|
{/foreach}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-3 control-label">{Lang::T('Plan Name')}</label>
|
||||||
|
<div class="col-md-9">
|
||||||
|
<input type="text" class="form-control" id="name_plan" maxlength="40" name="name_plan"
|
||||||
|
value="{$d['name_plan']}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-3 control-label"><a
|
||||||
|
href="{$_url}bandwidth/add">{Lang::T('Bandwidth Name')}</a></label>
|
||||||
|
<div class="col-md-9">
|
||||||
|
<select id="id_bw" name="id_bw" class="form-control select2">
|
||||||
|
{foreach $b as $bs}
|
||||||
|
<option value="{$bs['id']}" {if $d['id_bw'] eq $bs['id']} selected {/if}>
|
||||||
|
{$bs['name_bw']}</option>
|
||||||
|
{/foreach}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-3 control-label">{Lang::T('Plan Price')}</label>
|
||||||
|
<div class="col-md-9">
|
||||||
|
<div class="input-group">
|
||||||
|
<span class="input-group-addon">{$_c['currency_code']}</span>
|
||||||
|
<input type="number" class="form-control" name="price" required value="{$d['price']}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{if $_c['enable_tax'] == 'yes'}
|
||||||
|
{if $_c['tax_rate'] == 'custom'}
|
||||||
|
<p class="help-block col-md-4">{number_format($_c['custom_tax_rate'], 2)} % {Lang::T('Tax Rates
|
||||||
|
will be added')}</p>
|
||||||
|
{else}
|
||||||
|
<p class="help-block col-md-4">{number_format($_c['tax_rate'] * 100, 2)} % {Lang::T('Tax Rates
|
||||||
|
will be added')}</p>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-3 control-label">{Lang::T('Plan Validity')}</label>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<input type="text" class="form-control" id="validity" name="validity"
|
||||||
|
value="{$d['validity']}">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<select class="form-control" id="validity_unit" name="validity_unit">
|
||||||
|
{if $d['prepaid'] == yes}
|
||||||
|
<option value="Mins" {if $d['validity_unit'] eq 'Mins'} selected {/if}>{Lang::T('Mins')}
|
||||||
|
</option>
|
||||||
|
<option value="Hrs" {if $d['validity_unit'] eq 'Hrs'} selected {/if}>{Lang::T('Hrs')}
|
||||||
|
</option>
|
||||||
|
<option value="Days" {if $d['validity_unit'] eq 'Days'} selected {/if}>{Lang::T('Days')}
|
||||||
|
</option>
|
||||||
|
<option value="Months" {if $d['validity_unit'] eq 'Months'} selected {/if}>
|
||||||
|
{Lang::T('Months')}</option>
|
||||||
|
{else}
|
||||||
|
<option value="Period" {if $d['validity_unit'] eq 'Period'} selected {/if}>
|
||||||
|
{Lang::T('Period')}</option>
|
||||||
|
{/if}
|
||||||
|
</select>
|
||||||
|
<p class="help-block">{Lang::T('1 Period = 1 Month, Expires the 20th of each month')}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="form-group {if $d['prepaid'] == yes}hidden{/if}" id="expired_date">
|
||||||
|
<label class="col-md-3 control-label">{Lang::T('Expired Date')}
|
||||||
|
<a tabindex="0" class="btn btn-link btn-xs" role="button" data-toggle="popover"
|
||||||
|
data-trigger="focus" data-container="body"
|
||||||
|
data-content="Expired will be this date every month">?</a>
|
||||||
|
</label>
|
||||||
|
<div class="col-md-9">
|
||||||
|
<input type="number" class="form-control" name="expired_date" maxlength="2"
|
||||||
|
value="{if $d['expired_date']}{$d['expired_date']}{else}20{/if}" min="1" max="28"
|
||||||
|
step="1">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-3 control-label"><a href="{$_url}pool/add">{Lang::T('IP Pool')}</a></label>
|
||||||
|
<div class="col-md-9">
|
||||||
|
<select id="pool_name" name="pool_name" required class="form-control select2">
|
||||||
|
{foreach $p as $ps}
|
||||||
|
<option value="{$ps['pool_name']}" {if $d['pool'] eq $ps['pool_name']} selected {/if}>
|
||||||
|
{$ps['pool_name']}</option>
|
||||||
|
{/foreach}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-3 control-label">{Lang::T('Router Name')}</label>
|
||||||
|
<div class="col-md-9">
|
||||||
|
<input type="text" class="form-control" id="routers" name="routers" value="{$d['routers']}"
|
||||||
|
readonly>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<legend>{Lang::T('Expired Action')} <sub>{Lang::T('Optional')}</sub></legend>
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="col-md-3 control-label">{Lang::T('Expired Internet Plan')}</label>
|
||||||
|
<div class="col-md-9">
|
||||||
|
<select id="plan_expired" name="plan_expired" class="form-control select2">
|
||||||
|
<option value='0'>Default - Remove Customer</option>
|
||||||
|
{foreach $exps as $exp}
|
||||||
|
<option value="{$exp['id']}" {if $d['plan_expired'] eq $exp['id']} selected {/if}>
|
||||||
|
{$exp['name_plan']}</option>
|
||||||
|
{/foreach}
|
||||||
|
</select>
|
||||||
|
<p class="help-block">
|
||||||
|
{Lang::T('When Expired, customer will be move to selected internet plan')}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{if !$d['is_radius']}
|
||||||
|
<div class="col-md-6">
|
||||||
|
<div class="panel panel-primary panel-hovered panel-stacked mb30">
|
||||||
|
<div class="panel-heading">{Lang::T('on-login / on-up')}</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<textarea class="form-control" id="code" name="on_login"
|
||||||
|
style="font-family: 'Courier New', Courier, monospace;" rows="15">{$d['on_login']}</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="panel panel-primary panel-hovered panel-stacked mb30">
|
||||||
|
<div class="panel-heading">{Lang::T('on-logout / on-down')}</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<textarea class="form-control" id="code2" name="on_logout"
|
||||||
|
style="font-family: 'Courier New', Courier, monospace;" rows="15">{$d['on_logout']}</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-lg-offset-2 col-lg-10">
|
||||||
|
<button class="btn btn-success" type="submit">{Lang::T('Save Changes')}</button>
|
||||||
|
Or <a href="{$_url}services/vpn">{Lang::T('Cancel')}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
<script>
|
||||||
|
var preOpt = `<option value="Mins">{Lang::T('Mins')}</option>
|
||||||
|
<option value="Hrs">{Lang::T('Hrs')}</option>
|
||||||
|
<option value="Days">{Lang::T('Days')}</option>
|
||||||
|
<option value="Months">{Lang::T('Months')}</option>`;
|
||||||
|
var postOpt = `<option value="Period">{Lang::T('Period')}</option>`;
|
||||||
|
function prePaid() {
|
||||||
|
$("#validity_unit").html(preOpt);
|
||||||
|
$('#expired_date').addClass('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
function postPaid() {
|
||||||
|
$("#validity_unit").html(postOpt);
|
||||||
|
$("#expired_date").removeClass('hidden');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script language="javascript" type="text/javascript"
|
||||||
|
src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/6.65.7/codemirror.min.js"></script>
|
||||||
|
<script language="javascript" type="text/javascript"
|
||||||
|
src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/6.65.7/mode/perl/perl.min.js"></script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" type="text/css"
|
||||||
|
href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/6.65.7/codemirror.min.css">
|
||||||
|
</link>
|
||||||
|
<link rel="stylesheet" type="text/css"
|
||||||
|
href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/6.65.7/theme/abbott.min.css">
|
||||||
|
</link>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
CodeMirror.fromTextArea(document.getElementById('code'), {
|
||||||
|
lineNumbers: true,
|
||||||
|
mode: 'text/x-perl',
|
||||||
|
});
|
||||||
|
CodeMirror.fromTextArea(document.getElementById('code2'), {
|
||||||
|
lineNumbers: true,
|
||||||
|
mode: 'text/x-perl',
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{include file="sections/footer.tpl"}
|
179
ui/ui/vpn.tpl
Normal file
179
ui/ui/vpn.tpl
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
{include file="sections/header.tpl"}
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<div class="panel panel-hovered mb20 panel-primary">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<div class="btn-group pull-right">
|
||||||
|
<a class="btn btn-primary btn-xs" title="save" href="{$_url}services/sync/vpn"
|
||||||
|
onclick="return confirm('This will sync/send vpn plan to Mikrotik?')"><span
|
||||||
|
class="glyphicon glyphicon-refresh" aria-hidden="true"></span> sync</a>
|
||||||
|
</div>{Lang::T('VPN Package')}
|
||||||
|
</div>
|
||||||
|
<form id="site-search" method="post" action="{$_url}services/vpn">
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="row row-no-gutters" style="padding: 5px">
|
||||||
|
<div class="col-lg-2">
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-btn">
|
||||||
|
<a class="btn btn-danger" title="Clear Search Query"
|
||||||
|
href="{$_url}services/vpn"><span
|
||||||
|
class="glyphicon glyphicon-remove-circle"></span></a>
|
||||||
|
</div>
|
||||||
|
<input type="text" name="name" class="form-control"
|
||||||
|
placeholder="{Lang::T('Search by Name')}...">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-1 col-xs-4">
|
||||||
|
<select class="form-control" id="type1" name="type1">
|
||||||
|
<option value="">{Lang::T('Prepaid')} & {Lang::T('Postpaid')}</option>
|
||||||
|
<option value="yes" {if $type1 eq 'yes' }selected{/if}>{Lang::T('Prepaid')}</option>
|
||||||
|
<option value="no" {if $type1 eq 'no' }selected{/if}>{Lang::T('Postpaid')}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-1 col-xs-4">
|
||||||
|
<select class="form-control" id="type2" name="type2">
|
||||||
|
<option value="">{Lang::T('Type')}</option>
|
||||||
|
{foreach $type2s as $t}
|
||||||
|
<option value="{$t}" {if $type2 eq $t }selected{/if}>{Lang::T($t)}
|
||||||
|
</option>
|
||||||
|
{/foreach}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-1 col-xs-4">
|
||||||
|
<select class="form-control" id="bandwidth" name="bandwidth">
|
||||||
|
<option value="">Bandwidth</option>
|
||||||
|
{foreach $bws as $b}
|
||||||
|
<option value="{$b['id']}" {if $bandwidth eq $b['id'] }selected{/if}>
|
||||||
|
{$b['name_bw']}
|
||||||
|
</option>
|
||||||
|
{/foreach}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-1 col-xs-4">
|
||||||
|
<select class="form-control" id="type3" name="type3">
|
||||||
|
<option value="">{Lang::T('Category')}</option>
|
||||||
|
{foreach $type3s as $t}
|
||||||
|
<option value="{$t}" {if $type3 eq $t }selected{/if}>{$t}
|
||||||
|
</option>
|
||||||
|
{/foreach}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-1 col-xs-4">
|
||||||
|
<select class="form-control" id="valid" name="valid">
|
||||||
|
<option value="">{Lang::T('Validity')}</option>
|
||||||
|
{foreach $valids as $v}
|
||||||
|
<option value="{$v}" {if $valid eq $v }selected{/if}>{$v}
|
||||||
|
</option>
|
||||||
|
{/foreach}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-1 col-xs-4">
|
||||||
|
<select class="form-control" id="router" name="router">
|
||||||
|
<option value="">{Lang::T('Location')}</option>
|
||||||
|
{foreach $routers as $r}
|
||||||
|
<option value="{$r}" {if $router eq $r }selected{/if}>{$r}</option>
|
||||||
|
{/foreach}
|
||||||
|
<option value="radius" {if $router eq 'radius' }selected{/if}>Radius</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-1 col-xs-4">
|
||||||
|
<select class="form-control" id="device" name="device">
|
||||||
|
<option value="">{Lang::T('Device')}</option>
|
||||||
|
{foreach $devices as $r}
|
||||||
|
<option value="{$r}" {if $device eq $r }selected{/if}>{$r}</option>
|
||||||
|
{/foreach}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-1 col-xs-4">
|
||||||
|
<select class="form-control" id="status" name="status">
|
||||||
|
<option value="-">{Lang::T('Status')}</option>
|
||||||
|
<option value="1" {if $status eq '1' }selected{/if}>{Lang::T('Enabled')}</option>
|
||||||
|
<option value="0" {if $status eq '0' }selected{/if}>{Lang::T('Disable')}</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-1 col-xs-8">
|
||||||
|
<button class="btn btn-success btn-block" type="submit"><span
|
||||||
|
class="fa fa-search"></span></button>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-1 col-xs-4">
|
||||||
|
<a href="{$_url}services/vpn-add" class="btn btn-primary btn-block"
|
||||||
|
title="{Lang::T('New Service Plan')}"><i class="ion ion-android-add"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-bordered table-striped table-condensed">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th colspan="4" class="text-center">{Lang::T('Internet Plan')}</th>
|
||||||
|
<th></th>
|
||||||
|
<th colspan="2" class="text-center" style="background-color: rgb(243, 241, 172);">
|
||||||
|
{Lang::T('Expired')}</th>
|
||||||
|
<th colspan="4"></th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>{Lang::T('Name')}</th>
|
||||||
|
<th>{Lang::T('Type')}</th>
|
||||||
|
<th><a href="{$_url}bandwidth/list">{Lang::T('Bandwidth')}</a></th>
|
||||||
|
<th>{Lang::T('Price')}</th>
|
||||||
|
<th>{Lang::T('Validity')}</th>
|
||||||
|
<th><a href="{$_url}pool/list">{Lang::T('IP Pool')}</a></th>
|
||||||
|
<th style="background-color: rgb(243, 241, 172);">{Lang::T('Internet Plan')}</th>
|
||||||
|
<th style="background-color: rgb(243, 241, 172);">{Lang::T('Date')}</th>
|
||||||
|
<th><a href="{$_url}routers/list">{Lang::T('Location')}</a></th>
|
||||||
|
<th>{Lang::T('Device')}</th>
|
||||||
|
<th>{Lang::T('Manage')}</th>
|
||||||
|
<th>ID</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{foreach $d as $ds}
|
||||||
|
<tr {if $ds['enabled'] != 1}class="danger" title="disabled" {/if}>
|
||||||
|
<td>{$ds['name_plan']}</td>
|
||||||
|
<td>{$ds['plan_type']} {if $ds['prepaid'] != 'yes'}<b>{Lang::T('Postpaid')}</b>{else}{Lang::T('Prepaid')}{/if}</td>
|
||||||
|
<td>{$ds['name_bw']}</td>
|
||||||
|
<td>{Lang::moneyFormat($ds['price'])}</td>
|
||||||
|
<td>{$ds['validity']} {$ds['validity_unit']}</td>
|
||||||
|
<td>{$ds['pool']}</td>
|
||||||
|
<td>{if $ds['plan_expired']}<a
|
||||||
|
href="{$_url}services/vpn-edit/{$ds['plan_expired']}">{Lang::T('Yes')}</a>{else}{Lang::T('No')}
|
||||||
|
{/if}</td>
|
||||||
|
<td>{if $ds['prepaid'] == no}{$ds['expired_date']}{/if}</td>
|
||||||
|
<td>
|
||||||
|
{if $ds['is_radius']}
|
||||||
|
<span class="label label-primary">RADIUS</span>
|
||||||
|
{else}
|
||||||
|
{if $ds['routers']!=''}
|
||||||
|
<a href="{$_url}routers/edit/0&name={$ds['routers']}">{$ds['routers']}</a>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
</td>
|
||||||
|
<td>{$ds['device']}</td>
|
||||||
|
<td>
|
||||||
|
<a href="{$_url}services/vpn-edit/{$ds['id']}"
|
||||||
|
class="btn btn-info btn-xs">{Lang::T('Edit')}</a>
|
||||||
|
<a href="{$_url}services/vpn-delete/{$ds['id']}"
|
||||||
|
onclick="return confirm('{Lang::T('Delete')}?')" id="{$ds['id']}"
|
||||||
|
class="btn btn-danger btn-xs"><i class="glyphicon glyphicon-trash"></i></a>
|
||||||
|
</td>
|
||||||
|
<td>{$ds['id']}</td>
|
||||||
|
</tr>
|
||||||
|
{/foreach}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="panel-footer">
|
||||||
|
{include file="pagination.tpl"}
|
||||||
|
<div class="bs-callout bs-callout-info" id="callout-navbar-role">
|
||||||
|
<h4>{Lang::T('Create expired Internet Plan')}</h4>
|
||||||
|
<p>{Lang::T('When customer expired, you can move it to Expired Internet Plan')}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{include file="sections/footer.tpl"}
|
@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"version": "2024.9.6"
|
"version": "2024.9.13"
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user