fix deprecated jquery calls; move editapikey jq call to Ajax.php; fix edit of apikeys::allowed_from and allow cidr
Signed-off-by: Michael Kaufmann <d00p@froxlor.org>
This commit is contained in:
41
api_keys.php
41
api_keys.php
@@ -83,47 +83,6 @@ if ($action == 'delete') {
|
||||
'cid' => $cid
|
||||
));
|
||||
$success_message = $lng['apikeys']['apikey_added'];
|
||||
} elseif ($action == 'jqEditApiKey') {
|
||||
$keyid = isset($_POST['id']) ? (int) $_POST['id'] : 0;
|
||||
$allowed_from = isset($_POST['allowed_from']) ? $_POST['allowed_from'] : "";
|
||||
$valid_until = isset($_POST['valid_until']) ? (int) $_POST['valid_until'] : -1;
|
||||
|
||||
// validate allowed_from
|
||||
if (!empty($allowed_from)) {
|
||||
$ip_list = array_map('trim', explode(",", $allowed_from));
|
||||
$_check_list = $ip_list;
|
||||
foreach ($_check_list as $idx => $ip) {
|
||||
if (\Froxlor\Validate\Validate::validate_ip2($ip, true, 'invalidip', true, true) == false) {
|
||||
unset($ip_list[$idx]);
|
||||
}
|
||||
}
|
||||
$ip_list = array_map('inet_ntop', array_map('inet_pton', $ip_list));
|
||||
$allowed_from = implode(",", array_unique($ip_list));
|
||||
}
|
||||
|
||||
if ($valid_until <= 0 || !is_numeric($valid_until)) {
|
||||
$valid_until = -1;
|
||||
}
|
||||
|
||||
$upd_stmt = Database::prepare("
|
||||
UPDATE `" . TABLE_API_KEYS . "` SET
|
||||
`valid_until` = :vu, `allowed_from` = :af
|
||||
WHERE `id` = :keyid AND `adminid` = :aid AND `customerid` = :cid
|
||||
");
|
||||
if (AREA == 'admin') {
|
||||
$cid = 0;
|
||||
} elseif (AREA == 'customer') {
|
||||
$cid = $userinfo['customerid'];
|
||||
}
|
||||
Database::pexecute($upd_stmt, array(
|
||||
'keyid' => $keyid,
|
||||
'af' => $allowed_from,
|
||||
'vu' => $valid_until,
|
||||
'aid' => $userinfo['adminid'],
|
||||
'cid' => $cid
|
||||
));
|
||||
echo json_encode(true);
|
||||
exit();
|
||||
}
|
||||
|
||||
$log->logAction(\Froxlor\FroxlorLogger::USR_ACTION, LOG_NOTICE, "viewed api::api_keys");
|
||||
|
||||
@@ -444,7 +444,7 @@ class FroxlorInstall
|
||||
`vhostcontainer` = '1',
|
||||
`vhostcontainer_servername_statement` = '1'
|
||||
");
|
||||
$nvh = $this->_data['webserver'] == 'apache2' ? '1' : '0';
|
||||
$nvh = $this->_data['webserver'] == 'apache2' ? '1' : '0';
|
||||
$stmt->execute(array(
|
||||
'nvh' => $nvh,
|
||||
'serverip' => $this->_data['serverip'],
|
||||
@@ -1193,6 +1193,9 @@ class FroxlorInstall
|
||||
// check for json extension
|
||||
$this->_requirementCheckFor($content, $_die, 'json', false, 'phpjson');
|
||||
|
||||
// check for gmp extension
|
||||
$this->_requirementCheckFor($content, $_die, 'gmp', false, 'phpgmp');
|
||||
|
||||
// check for bcmath extension
|
||||
$this->_requirementCheckFor($content, $_die, 'bcmath', true, 'phpbcmath', 'bcmathdescription');
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ $lng['requirements']['phpcurl'] = 'PHP curl-extension...';
|
||||
$lng['requirements']['phpmbstring'] = 'PHP mbstring-extension...';
|
||||
$lng['requirements']['phpzip'] = 'PHP zip-extension...';
|
||||
$lng['requirements']['phpjson'] = 'PHP json-extension...';
|
||||
$lng['requirements']['phpgmp'] = 'PHP gmp-extension...';
|
||||
$lng['requirements']['bcmathdescription'] = 'Traffic-calculation related functions will not work correctly!';
|
||||
$lng['requirements']['zipdescription'] = 'The auto-update feature requires the zip extension.';
|
||||
$lng['requirements']['openbasedir'] = 'open_basedir...';
|
||||
|
||||
@@ -36,6 +36,7 @@ $lng['requirements']['phpcurl'] = 'PHP curl-Erweiterung...';
|
||||
$lng['requirements']['phpmbstring'] = 'PHP mbstring-Erweiterung...';
|
||||
$lng['requirements']['phpzip'] = 'PHP zip-Erweiterung...';
|
||||
$lng['requirements']['phpjson'] = 'PHP json-Erweiterung...';
|
||||
$lng['requirements']['phpgmp'] = 'PHP gmp-Erweiterung...';
|
||||
$lng['requirements']['bcmathdescription'] = 'Traffic-Berechnungs bezogene Funktionen stehen nicht vollständig zur Verfügung!';
|
||||
$lng['requirements']['zipdescription'] = 'Die Auto-Update Funktion benötigt die zip Erweiterung.';
|
||||
$lng['requirements']['openbasedir'] = 'open_basedir genutzt wird...';
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
namespace Froxlor\Ajax;
|
||||
|
||||
use Exception;
|
||||
use Froxlor\Database\Database;
|
||||
use Froxlor\Http\HttpClient;
|
||||
use Froxlor\Validate\Validate;
|
||||
use Froxlor\Settings;
|
||||
use Froxlor\UI\Listing;
|
||||
use Froxlor\UI\Panel\UI;
|
||||
@@ -52,7 +54,7 @@ class Ajax
|
||||
global $lng;
|
||||
|
||||
// query the whole table
|
||||
$result_stmt = \Froxlor\Database\Database::query("SELECT * FROM `" . TABLE_PANEL_LANGUAGE . "`");
|
||||
$result_stmt = Database::query("SELECT * FROM `" . TABLE_PANEL_LANGUAGE . "`");
|
||||
|
||||
$langs = array();
|
||||
// presort languages
|
||||
@@ -110,6 +112,8 @@ class Ajax
|
||||
return $this->searchGlobal();
|
||||
case 'tablelisting':
|
||||
return $this->updateTablelisting();
|
||||
case 'editapikey':
|
||||
return $this->editApiKey();
|
||||
default:
|
||||
return $this->errorResponse('Action not found!');
|
||||
}
|
||||
@@ -236,8 +240,7 @@ class Ajax
|
||||
|
||||
$result = array_merge($result_settings, $result_entities);
|
||||
|
||||
header("Content-type: application/json");
|
||||
echo json_encode($result);
|
||||
return $this->jsonResponse($result);
|
||||
}
|
||||
|
||||
private function updateTablelisting()
|
||||
@@ -249,6 +252,61 @@ class Ajax
|
||||
|
||||
Listing::storeColumnListingForUser([Request::get('listing') => $columns]);
|
||||
|
||||
return json_encode($columns);
|
||||
return $this->jsonResponse($columns);
|
||||
}
|
||||
|
||||
private function editApiKey()
|
||||
{
|
||||
$keyid = isset($_POST['id']) ? (int) $_POST['id'] : 0;
|
||||
$allowed_from = isset($_POST['allowed_from']) ? $_POST['allowed_from'] : "";
|
||||
$valid_until = isset($_POST['valid_until']) ? (int) $_POST['valid_until'] : -1;
|
||||
|
||||
// validate allowed_from
|
||||
if (!empty($allowed_from)) {
|
||||
$ip_list = array_map('trim', explode(",", $allowed_from));
|
||||
$_check_list = $ip_list;
|
||||
foreach ($_check_list as $idx => $ip) {
|
||||
if (Validate::validate_ip2($ip, true, 'invalidip', true, true, true) == false) {
|
||||
unset($ip_list[$idx]);
|
||||
continue;
|
||||
}
|
||||
// check for cidr
|
||||
if (strpos($ip, '/') !== false) {
|
||||
$ipparts = explode("/", $ip);
|
||||
// shorten IP
|
||||
$ip = inet_ntop(inet_pton($ipparts[0]));
|
||||
// re-add cidr
|
||||
$ip .= '/' . $ipparts[1];
|
||||
} else {
|
||||
// shorten IP
|
||||
$ip = inet_ntop(inet_pton($ip));
|
||||
}
|
||||
$ip_list[$idx] = $ip;
|
||||
}
|
||||
$allowed_from = implode(",", array_unique($ip_list));
|
||||
}
|
||||
|
||||
if ($valid_until <= 0 || !is_numeric($valid_until)) {
|
||||
$valid_until = -1;
|
||||
}
|
||||
|
||||
$upd_stmt = Database::prepare("
|
||||
UPDATE `" . TABLE_API_KEYS . "` SET
|
||||
`valid_until` = :vu, `allowed_from` = :af
|
||||
WHERE `id` = :keyid AND `adminid` = :aid AND `customerid` = :cid
|
||||
");
|
||||
if ((int) $this->userinfo['adminsession'] == 1) {
|
||||
$cid = 0;
|
||||
} else {
|
||||
$cid = $this->userinfo['customerid'];
|
||||
}
|
||||
Database::pexecute($upd_stmt, array(
|
||||
'keyid' => $keyid,
|
||||
'af' => $allowed_from,
|
||||
'vu' => $valid_until,
|
||||
'aid' => $this->userinfo['adminid'],
|
||||
'cid' => $cid
|
||||
));
|
||||
return $this->jsonResponse(['allowed_from' => $allowed_from, 'valid_until' => $valid_until]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace Froxlor\Api;
|
||||
|
||||
/**
|
||||
@@ -18,20 +19,21 @@ namespace Froxlor\Api;
|
||||
*/
|
||||
class Response
|
||||
{
|
||||
public static function jsonResponse($data = null, int $response_code = 200)
|
||||
{
|
||||
http_response_code($response_code);
|
||||
public static function jsonResponse($data = null, int $response_code = 200)
|
||||
{
|
||||
header("Content-Type: application/json");
|
||||
http_response_code($response_code);
|
||||
|
||||
return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
|
||||
}
|
||||
return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
|
||||
}
|
||||
|
||||
public static function jsonDataResponse($data = null, int $response_code = 200)
|
||||
{
|
||||
return self::jsonResponse(['data' => $data], $response_code);
|
||||
}
|
||||
public static function jsonDataResponse($data = null, int $response_code = 200)
|
||||
{
|
||||
return self::jsonResponse(['data' => $data], $response_code);
|
||||
}
|
||||
|
||||
public static function jsonErrorResponse($message = null, int $response_code = 400)
|
||||
{
|
||||
return self::jsonResponse(['message' => $message], $response_code);
|
||||
}
|
||||
public static function jsonErrorResponse($message = null, int $response_code = 400)
|
||||
{
|
||||
return self::jsonResponse(['message' => $message], $response_code);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,7 @@ class Text
|
||||
'editid' => $attributes['fields']['id']
|
||||
]);
|
||||
return [
|
||||
'entry' => $attributes['fields']['id'],
|
||||
'id' => 'akModal' . $attributes['fields']['id'],
|
||||
'title' => 'API-key ' . ($attributes['fields']['loginname'] ?? $attributes['fields']['adminname']),
|
||||
'body' => $body
|
||||
|
||||
@@ -40,15 +40,15 @@ return [
|
||||
'value' => $result['secret']
|
||||
],
|
||||
'allowed_from' => [
|
||||
'label' => UI::getLng('apikeys.allowed_from'),
|
||||
'label' => ['title' => UI::getLng('apikeys.allowed_from'), 'description' => UI::getLng('apikeys.allowed_from_help')],
|
||||
'type' => 'text',
|
||||
'value' => $result['allowed_from'],
|
||||
],
|
||||
'valid_until' => [
|
||||
'label' => UI::getLng('apikeys.valid_until'),
|
||||
'label' => ['title' => UI::getLng('apikeys.valid_until'), 'description' => UI::getLng('apikeys.valid_until_help')],
|
||||
/** @TODO datetime-picker */
|
||||
'type' => 'text',
|
||||
'value' => $result['valid_until'],
|
||||
'format_callback' => [Text::class, 'timestampUntil'],
|
||||
'value' => $result['valid_until'] < 0 ? "" : $result['valid_until']
|
||||
]
|
||||
]
|
||||
]
|
||||
|
||||
@@ -2041,7 +2041,7 @@ $lng['apikeys']['apikey_removed'] = 'The api key with the id #%s has been remove
|
||||
$lng['apikeys']['apikey_added'] = 'A new api key has been generated successfully';
|
||||
$lng['apikeys']['clicktoview'] = 'Click to view';
|
||||
$lng['apikeys']['allowed_from'] = 'Allowed from';
|
||||
$lng['apikeys']['allowed_from_help'] = 'Comma separated list of ip addresses. Default empty.<br>Specifying a subnet e.g. 192.168.1.1/24 is currently not supported.';
|
||||
$lng['apikeys']['allowed_from_help'] = 'Comma separated list of ip addresses / networks.<br>Default is empty (allow from all).';
|
||||
$lng['apikeys']['valid_until'] = 'Valid until';
|
||||
$lng['apikeys']['valid_until_help'] = 'Date until valid, format YYYY-MM-DD';
|
||||
$lng['serversettings']['enable_api']['title'] = 'Enable external API usage';
|
||||
@@ -2167,5 +2167,5 @@ $lng['panel']['settingsmodebasic'] = 'Basic';
|
||||
$lng['panel']['settingsmodeadvanced'] = 'Advanced';
|
||||
$lng['panel']['settingsmodetoggle'] = 'Click to toggle mode';
|
||||
$lng['panel']['modalclose'] = 'Close';
|
||||
$lng['panel']['managetablecolumnsmodal']['title'] = 'Manage Table columns';
|
||||
$lng['panel']['managetablecolumnsmodal']['description'] = 'Here you can individualise the table columns for yourself.';
|
||||
$lng['panel']['managetablecolumnsmodal']['title'] = 'Manage table columns';
|
||||
$lng['panel']['managetablecolumnsmodal']['description'] = 'Here you can customize the visible columns';
|
||||
|
||||
@@ -1683,7 +1683,7 @@ $lng['apikeys']['no_api_keys'] = 'Keine API Keys gefunden';
|
||||
$lng['apikeys']['key_add'] = 'API Key hinzufügen';
|
||||
$lng['apikeys']['apikey_removed'] = 'Der API Key mit der ID #%s wurde erfolgreich gelöscht.';
|
||||
$lng['apikeys']['allowed_from'] = 'Erlaube Zugriff von';
|
||||
$lng['apikeys']['allowed_from_help'] = 'Komma getrennte Liste von IPs. Standard ist leer.<br>Angabe von Subnetzen z.B. 192.168.1.1/24 wird derzeit nicht unterstützt.';
|
||||
$lng['apikeys']['allowed_from_help'] = 'Komma getrennte Liste von IPs oder Netzen.<br>Standard ist leer (von überall erlaubt).';
|
||||
$lng['apikeys']['valid_until'] = 'Gültig bis';
|
||||
$lng['apikeys']['valid_until_help'] = 'Datum Gültigkeitsende, Format JJJJ-MM-TT';
|
||||
$lng['serversettings']['enable_api']['title'] = 'Aktiviere externe API Nutzung';
|
||||
@@ -1806,4 +1806,4 @@ $lng['panel']['settingsmodeadvanced'] = 'Erweitert';
|
||||
$lng['panel']['settingsmodetoggle'] = 'Modus umschalten';
|
||||
$lng['panel']['modalclose'] = 'Schließen';
|
||||
$lng['panel']['managetablecolumnsmodal']['title'] = 'Tabellenspalten verwalten';
|
||||
$lng['panel']['managetablecolumnsmodal']['description'] = 'Hier kannst du die Tabellenspalten für dich selbst individualisieren.';
|
||||
$lng['panel']['managetablecolumnsmodal']['description'] = 'Hier können die angezeigten Tabellenspalten angepasst werden';
|
||||
|
||||
57
templates/Froxlor/src/js/components/apikeys.js
Normal file
57
templates/Froxlor/src/js/components/apikeys.js
Normal file
@@ -0,0 +1,57 @@
|
||||
$(function () {
|
||||
|
||||
var timer, delay = 500;
|
||||
$('div[data-action="apikeys"] #allowed_from').on('keyup change', function () {
|
||||
var _this = $(this);
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(function () {
|
||||
var akid = $('div[data-action="apikeys"]').data('entry');
|
||||
$.ajax({
|
||||
url: "lib/ajax.php?action=editapikey",
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
data: { id: akid, allowed_from: _this.val(), valid_until: $('div[data-action="apikeys"] #valid_until').val() },
|
||||
success: function (data) {
|
||||
if (data.message) {
|
||||
_this.removeClass('is-valid');
|
||||
_this.addClass('is-invalid');
|
||||
} else {
|
||||
_this.removeClass('is-invalid');
|
||||
_this.addClass('is-valid');
|
||||
_this.val(data.allowed_from);
|
||||
}
|
||||
},
|
||||
error: function (request, status, error) {
|
||||
console.log(request, status, error)
|
||||
}
|
||||
});
|
||||
}, delay);
|
||||
});
|
||||
|
||||
$('div[data-action="apikeys"] #valid_until').on('keyup change', function () {
|
||||
var _this = $(this);
|
||||
clearTimeout(timer);
|
||||
timer = setTimeout(function () {
|
||||
var akid = $('div[data-action="apikeys"]').data('entry');
|
||||
$.ajax({
|
||||
url: "lib/ajax.php?action=editapikey",
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
data: { id: akid, valid_until: _this.val(), allowed_from: $('div[data-action="apikeys"] #allowed_from').val() },
|
||||
success: function (data) {
|
||||
if (data.message) {
|
||||
_this.removeClass('is-valid');
|
||||
_this.addClass('is-invalid');
|
||||
} else {
|
||||
_this.removeClass('is-invalid');
|
||||
_this.addClass('is-valid');
|
||||
_this.val(data.valid_until);
|
||||
}
|
||||
},
|
||||
error: function (request, status, error) {
|
||||
console.log(request, status, error)
|
||||
}
|
||||
});
|
||||
}, delay);
|
||||
});
|
||||
});
|
||||
@@ -1,8 +1,8 @@
|
||||
$(document).ready(function () {
|
||||
$(function() {
|
||||
/*
|
||||
* config files - select all recommended
|
||||
*/
|
||||
$('#selectRecommendedConfig').click(function () {
|
||||
$('#selectRecommendedConfig').on('click', function () {
|
||||
$('input[data-recommended]').each(function () {
|
||||
if ($(this).data('recommended') == 1) {
|
||||
$(this).prop('checked', true);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
$(document).ready(function () {
|
||||
$(function() {
|
||||
|
||||
// Make inputs with enabled unlimited checked disabled
|
||||
$("input[name$='_ul']").each(function () {
|
||||
@@ -9,7 +9,7 @@ $(document).ready(function () {
|
||||
});
|
||||
});
|
||||
// change state when unlimited checkboxes are clicked
|
||||
$("input[name$='_ul']").change(function () {
|
||||
$("input[name$='_ul']").on('change', function () {
|
||||
var fieldname = $(this).attr("name").substring(0, $(this).attr("name").length - 3);
|
||||
$("input[name='" + fieldname + "']").prop({
|
||||
readonly: $(this).is(":checked"),
|
||||
@@ -21,7 +21,7 @@ $(document).ready(function () {
|
||||
});
|
||||
|
||||
// set values from hosting plan when adding/editing a customer according to the plan's values
|
||||
$('#use_plan').change(function () {
|
||||
$('#use_plan').on('change', function () {
|
||||
var pid = $(this).val();
|
||||
if (pid > 0) {
|
||||
$.ajax({
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
$(document).ready(function () {
|
||||
$(function() {
|
||||
|
||||
// disable unusable php-configuration by customer settings
|
||||
$('#customerid').change(function () {
|
||||
$('#customerid').on('change', function () {
|
||||
var cid = $(this).val();
|
||||
$.ajax({
|
||||
url: "admin_domains.php?page=domains&action=jqGetCustomerPHPConfigs",
|
||||
@@ -31,7 +31,7 @@ $(document).ready(function () {
|
||||
|
||||
// show warning if speciallogfile option is toggled
|
||||
if ($('input[name=speciallogverified]')) {
|
||||
$('input[name=speciallogfile]').click(function () {
|
||||
$('input[name=speciallogfile]').on('click', function () {
|
||||
$('#speciallogfilenote').remove();
|
||||
$('#speciallogfile').removeClass('is-invalid');
|
||||
$('#speciallogverified').val(0);
|
||||
@@ -64,7 +64,7 @@ $(document).ready(function () {
|
||||
$('#section_d').hide();
|
||||
}
|
||||
|
||||
$('#email_only').click(function () {
|
||||
$('#email_only').on('click', function () {
|
||||
if ($(this).is(':checked')) {
|
||||
// hide unnecessary sections
|
||||
$('#section_b').hide();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
$(document).ready(function () {
|
||||
$(function() {
|
||||
|
||||
// check for internal ip and output a notice if private-range ip is given
|
||||
$('#ip').change(function () {
|
||||
$('#ip').on('change', function () {
|
||||
var ipval = $(this).val();
|
||||
if (ipval.length > 0) {
|
||||
$('#ipnote').remove();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
$(document).ready(function () {
|
||||
$(function() {
|
||||
/*
|
||||
* newsfeed
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
$(document).ready(function () {
|
||||
$(function() {
|
||||
let search = $('#search')
|
||||
|
||||
search.submit(function (e) {
|
||||
search.on('submit', function (e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
$(document).ready(function () {
|
||||
$(function() {
|
||||
/*
|
||||
* updatecheck
|
||||
*/
|
||||
|
||||
@@ -6,7 +6,7 @@ import 'chart.js/dist/chart';
|
||||
// load jquery
|
||||
global.$ = require('jquery');
|
||||
|
||||
$(document).ready(function () {
|
||||
$(function() {
|
||||
window.$theme = 'Froxlor';
|
||||
});
|
||||
|
||||
@@ -19,3 +19,4 @@ require('./components/tablecolumns')
|
||||
require('./components/ipsandports')
|
||||
require('./components/domains')
|
||||
require('./components/configfiles')
|
||||
require('./components/apikeys')
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
{% endif %}
|
||||
</a>
|
||||
{% if data.modal is defined and data.modal is iterable %}
|
||||
<div class="modal fade" id="{{ data.modal.id }}" aria-hidden="true" aria-labelledby="{{ data.modal.id }}Label" tabindex="-1">
|
||||
<div class="modal fade" data-action="apikeys" data-entry="{{ data.modal.entry }}" id="{{ data.modal.id }}" aria-hidden="true" aria-labelledby="{{ data.modal.id }}Label" tabindex="-1">
|
||||
<div class="modal-dialog {{ data.modal.size|default('modal-xl') }} modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
|
||||
Reference in New Issue
Block a user