[Web] add cors to json_api
This commit is contained in:
parent
73570cc8b5
commit
192f67cd41
@ -80,6 +80,11 @@ foreach ($RSPAMD_MAPS['regex'] as $rspamd_regex_desc => $rspamd_regex_map) {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// cors settings
|
||||||
|
$cors_settings = cors('get');
|
||||||
|
$cors_settings['allowed_origins'] = str_replace(", ", "\n", $cors_settings['allowed_origins']);
|
||||||
|
$cors_settings['allowed_methods'] = explode(", ", $cors_settings['allowed_methods']);
|
||||||
|
|
||||||
$template = 'admin.twig';
|
$template = 'admin.twig';
|
||||||
$template_data = [
|
$template_data = [
|
||||||
'tfa_data' => $tfa_data,
|
'tfa_data' => $tfa_data,
|
||||||
@ -106,6 +111,7 @@ $template_data = [
|
|||||||
'ip_check' => customize('get', 'ip_check'),
|
'ip_check' => customize('get', 'ip_check'),
|
||||||
'password_complexity' => password_complexity('get'),
|
'password_complexity' => password_complexity('get'),
|
||||||
'show_rspamd_global_filters' => @$_SESSION['show_rspamd_global_filters'],
|
'show_rspamd_global_filters' => @$_SESSION['show_rspamd_global_filters'],
|
||||||
|
'cors_settings' => $cors_settings,
|
||||||
'lang_admin' => json_encode($lang['admin']),
|
'lang_admin' => json_encode($lang['admin']),
|
||||||
'lang_datatables' => json_encode($lang['datatables'])
|
'lang_datatables' => json_encode($lang['datatables'])
|
||||||
];
|
];
|
||||||
|
@ -2131,6 +2131,110 @@ function rspamd_ui($action, $data = null) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function cors($action, $data = null) {
|
||||||
|
global $redis;
|
||||||
|
|
||||||
|
switch ($action) {
|
||||||
|
case "edit":
|
||||||
|
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $action, $data),
|
||||||
|
'msg' => 'access_denied'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$allowed_origins = isset($data['allowed_origins']) ? $data['allowed_origins'] : array($_SERVER['SERVER_NAME']);
|
||||||
|
$allowed_origins = !is_array($allowed_origins) ? array_map('trim', preg_split( "/( |,|;|\n)/", $allowed_origins)) : $allowed_origins;
|
||||||
|
|
||||||
|
$allowed_methods = isset($data['allowed_methods']) ? $data['allowed_methods'] : array('GET', 'POST', 'PUT', 'DELETE');
|
||||||
|
$allowed_methods = !is_array($allowed_methods) ? array_map('trim', preg_split( "/( |,|;|\n)/", $allowed_methods)) : $allowed_methods;
|
||||||
|
$available_methods = array('GET', 'POST', 'PUT', 'DELETE', 'OPTION');
|
||||||
|
foreach ($allowed_methods as $method) {
|
||||||
|
if (!in_array($method, $available_methods)) {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $action, $data),
|
||||||
|
'msg' => 'cors_invalid_method'
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$redis->hMSet('CORS_SETTINGS', array(
|
||||||
|
'allowed_origins' => implode(', ', $allowed_origins),
|
||||||
|
'allowed_methods' => implode(', ', $allowed_methods)
|
||||||
|
));
|
||||||
|
} catch (RedisException $e) {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $action, $data),
|
||||||
|
'msg' => array('redis_error', $e)
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'success',
|
||||||
|
'log' => array(__FUNCTION__, $action, $data),
|
||||||
|
'msg' => 'cors_headers_edited'
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case "get":
|
||||||
|
try {
|
||||||
|
$cors_settings = $redis->hMGet('CORS_SETTINGS', array('allowed_origins', 'allowed_methods'));
|
||||||
|
} catch (RedisException $e) {
|
||||||
|
$_SESSION['return'][] = array(
|
||||||
|
'type' => 'danger',
|
||||||
|
'log' => array(__FUNCTION__, $action, $data),
|
||||||
|
'msg' => array('redis_error', $e)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$cors_settings = !$cors_settings ? array('allowed_origins' => $_SERVER['SERVER_NAME'], 'allowed_methods' => 'GET, POST, PUT, DELETE') : $cors_settings;
|
||||||
|
$cors_settings['allowed_origins'] = empty($cors_settings['allowed_origins']) ? $_SERVER['SERVER_NAME'] : $cors_settings['allowed_origins'];
|
||||||
|
$cors_settings['allowed_methods'] = empty($cors_settings['allowed_methods']) ? 'GET, POST, PUT, DELETE, OPTION' : $cors_settings['allowed_methods'];
|
||||||
|
|
||||||
|
return $cors_settings;
|
||||||
|
break;
|
||||||
|
case "set_headers":
|
||||||
|
$cors_settings = cors('get');
|
||||||
|
// check if requested origin is in allowed origins
|
||||||
|
$allowed_origins = explode(', ', $cors_settings['allowed_origins']);
|
||||||
|
$cors_settings['allowed_origins'] = $allowed_origins[0];
|
||||||
|
if (in_array('*', $allowed_origins)){
|
||||||
|
$cors_settings['allowed_origins'] = '*';
|
||||||
|
} else if (in_array($_SERVER['HTTP_ORIGIN'], $allowed_origins)) {
|
||||||
|
$cors_settings['allowed_origins'] = $_SERVER['HTTP_ORIGIN'];
|
||||||
|
}
|
||||||
|
// always allow OPTIONS for preflight request
|
||||||
|
$cors_settings["allowed_methods"] = empty($cors_settings["allowed_methods"]) ? 'OPTIONS' : $cors_settings["allowed_methods"] . ', ' . 'OPTIONS';
|
||||||
|
|
||||||
|
header('Access-Control-Allow-Origin: ' . $cors_settings['allowed_origins']);
|
||||||
|
header('Access-Control-Allow-Methods: '. $cors_settings['allowed_methods']);
|
||||||
|
header('Access-Control-Allow-Headers: Accept, Content-Type, X-Api-Key, Origin');
|
||||||
|
|
||||||
|
// Access-Control settings requested, this is just a preflight request
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS' &&
|
||||||
|
isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD']) &&
|
||||||
|
isset($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS'])) {
|
||||||
|
|
||||||
|
$allowed_methods = explode(', ', $cors_settings["allowed_methods"]);
|
||||||
|
if (in_array($_SERVER['HTTP_ACCESS_CONTROL_REQUEST_METHOD'], $allowed_methods, true))
|
||||||
|
// method allowed send 200 OK
|
||||||
|
http_response_code(200);
|
||||||
|
else
|
||||||
|
// method not allowed send 405 METHOD NOT ALLOWED
|
||||||
|
http_response_code(405);
|
||||||
|
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function get_logs($application, $lines = false) {
|
function get_logs($application, $lines = false) {
|
||||||
if ($lines === false) {
|
if ($lines === false) {
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
/*
|
/*
|
||||||
see /api
|
see /api
|
||||||
*/
|
*/
|
||||||
|
|
||||||
header('Content-Type: application/json');
|
|
||||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
|
||||||
|
cors("set_headers");
|
||||||
|
header('Content-Type: application/json');
|
||||||
error_reporting(0);
|
error_reporting(0);
|
||||||
|
|
||||||
function api_log($_data) {
|
function api_log($_data) {
|
||||||
@ -1946,6 +1946,9 @@ if (isset($_GET['query'])) {
|
|||||||
process_edit_return(edit_user_account($attr));
|
process_edit_return(edit_user_account($attr));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "cors":
|
||||||
|
process_edit_return(cors('edit', $attr));
|
||||||
|
break;
|
||||||
// return no route found if no case is matched
|
// return no route found if no case is matched
|
||||||
default:
|
default:
|
||||||
http_response_code(404);
|
http_response_code(404);
|
||||||
|
@ -147,6 +147,7 @@
|
|||||||
"change_logo": "Logo ändern",
|
"change_logo": "Logo ändern",
|
||||||
"configuration": "Konfiguration",
|
"configuration": "Konfiguration",
|
||||||
"convert_html_to_text": "Konvertiere HTML zu reinem Text",
|
"convert_html_to_text": "Konvertiere HTML zu reinem Text",
|
||||||
|
"cors_settings": "CORS Einstellungen",
|
||||||
"credentials_transport_warning": "<b>Warnung</b>: Das Hinzufügen einer neuen Regel bewirkt die Aktualisierung der Authentifizierungsdaten aller vorhandenen Einträge mit identischem Next Hop.",
|
"credentials_transport_warning": "<b>Warnung</b>: Das Hinzufügen einer neuen Regel bewirkt die Aktualisierung der Authentifizierungsdaten aller vorhandenen Einträge mit identischem Next Hop.",
|
||||||
"customer_id": "Kunde",
|
"customer_id": "Kunde",
|
||||||
"customize": "UI-Anpassung",
|
"customize": "UI-Anpassung",
|
||||||
@ -996,6 +997,7 @@
|
|||||||
"bcc_deleted": "BCC-Map-Einträge gelöscht: %s",
|
"bcc_deleted": "BCC-Map-Einträge gelöscht: %s",
|
||||||
"bcc_edited": "BCC-Map-Eintrag %s wurde geändert",
|
"bcc_edited": "BCC-Map-Eintrag %s wurde geändert",
|
||||||
"bcc_saved": "BCC- Map-Eintrag wurde gespeichert",
|
"bcc_saved": "BCC- Map-Eintrag wurde gespeichert",
|
||||||
|
"cors_headers_edited": "CORS headers wurden erfolgreich gespeichert",
|
||||||
"db_init_complete": "Datenbankinitialisierung abgeschlossen",
|
"db_init_complete": "Datenbankinitialisierung abgeschlossen",
|
||||||
"delete_filter": "Filter-ID %s wurde gelöscht",
|
"delete_filter": "Filter-ID %s wurde gelöscht",
|
||||||
"delete_filters": "Filter gelöscht: %s",
|
"delete_filters": "Filter gelöscht: %s",
|
||||||
|
@ -133,6 +133,8 @@
|
|||||||
"admins": "Administrators",
|
"admins": "Administrators",
|
||||||
"admins_ldap": "LDAP Administrators",
|
"admins_ldap": "LDAP Administrators",
|
||||||
"advanced_settings": "Advanced settings",
|
"advanced_settings": "Advanced settings",
|
||||||
|
"allowed_methods": "Access-Control-Allow-Methods",
|
||||||
|
"allowed_origins": "Access-Control-Allow-Origin",
|
||||||
"api_allow_from": "Allow API access from these IPs/CIDR network notations",
|
"api_allow_from": "Allow API access from these IPs/CIDR network notations",
|
||||||
"api_info": "The API is a work in progress. The documentation can be found at <a href=\"/api\">/api</a>",
|
"api_info": "The API is a work in progress. The documentation can be found at <a href=\"/api\">/api</a>",
|
||||||
"api_key": "API key",
|
"api_key": "API key",
|
||||||
@ -149,6 +151,7 @@
|
|||||||
"change_logo": "Change logo",
|
"change_logo": "Change logo",
|
||||||
"configuration": "Configuration",
|
"configuration": "Configuration",
|
||||||
"convert_html_to_text": "Convert HTML to plain text",
|
"convert_html_to_text": "Convert HTML to plain text",
|
||||||
|
"cors_settings": "CORS Settings",
|
||||||
"credentials_transport_warning": "<b>Warning</b>: Adding a new transport map entry will update the credentials for all entries with a matching next hop column.",
|
"credentials_transport_warning": "<b>Warning</b>: Adding a new transport map entry will update the credentials for all entries with a matching next hop column.",
|
||||||
"customer_id": "Customer ID",
|
"customer_id": "Customer ID",
|
||||||
"customize": "Customize",
|
"customize": "Customize",
|
||||||
@ -358,6 +361,7 @@
|
|||||||
"bcc_exists": "A BCC map %s exists for type %s",
|
"bcc_exists": "A BCC map %s exists for type %s",
|
||||||
"bcc_must_be_email": "BCC destination %s is not a valid email address",
|
"bcc_must_be_email": "BCC destination %s is not a valid email address",
|
||||||
"comment_too_long": "Comment too long, max 160 chars allowed",
|
"comment_too_long": "Comment too long, max 160 chars allowed",
|
||||||
|
"cors_invalid_method": "Invalid Allow-Method specified",
|
||||||
"defquota_empty": "Default quota per mailbox must not be 0.",
|
"defquota_empty": "Default quota per mailbox must not be 0.",
|
||||||
"demo_mode_enabled": "Demo Mode is enabled",
|
"demo_mode_enabled": "Demo Mode is enabled",
|
||||||
"description_invalid": "Resource description for %s is invalid",
|
"description_invalid": "Resource description for %s is invalid",
|
||||||
@ -1003,6 +1007,7 @@
|
|||||||
"bcc_deleted": "BCC map entries deleted: %s",
|
"bcc_deleted": "BCC map entries deleted: %s",
|
||||||
"bcc_edited": "BCC map entry %s edited",
|
"bcc_edited": "BCC map entry %s edited",
|
||||||
"bcc_saved": "BCC map entry saved",
|
"bcc_saved": "BCC map entry saved",
|
||||||
|
"cors_headers_edited": "CORS headers successfully set.",
|
||||||
"db_init_complete": "Database initialization completed",
|
"db_init_complete": "Database initialization completed",
|
||||||
"delete_filter": "Deleted filters ID %s",
|
"delete_filter": "Deleted filters ID %s",
|
||||||
"delete_filters": "Deleted filters: %s",
|
"delete_filters": "Deleted filters: %s",
|
||||||
|
@ -97,6 +97,39 @@
|
|||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
<p class="text-muted">{{ lang.admin.api_info|raw }}</p>
|
<p class="text-muted">{{ lang.admin.api_info|raw }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-lg-12">
|
||||||
|
<div class="card mb-3">
|
||||||
|
<div class="card-header">
|
||||||
|
<h4 class="card-title"><i class="bi bi-file-earmark-arrow-down"></i> {{ lang.admin.cors_settings }}</h4>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form class="form-horizontal" autocapitalize="none" autocorrect="off" role="form" data-id="editcors" method="post">
|
||||||
|
<div class="row mb-4">
|
||||||
|
<label class="control-label col-sm-2 mb-4" for="allowed_origins">{{ lang.admin.allowed_origins }}</label>
|
||||||
|
<div class="col-sm-9 mb-4">
|
||||||
|
<textarea class="form-control textarea-code" rows="7" name="allowed_origins" id="allowed_origins">{{ cors_settings.allowed_origins }}</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-4">
|
||||||
|
<label class="control-label col-sm-2" for="allowed_methods">{{ lang.admin.allowed_methods }}</label>
|
||||||
|
<div class="col-sm-9">
|
||||||
|
<select name="allowed_methods" id="allowed_methods" multiple class="form-control">
|
||||||
|
<option value="POST"{% if "POST" in cors_settings.allowed_methods %} selected{% endif %}>POST</option>
|
||||||
|
<option value="GET"{% if "GET" in cors_settings.allowed_methods %} selected{% endif %}>GET</option>
|
||||||
|
<option value="DELETE"{% if "DELETE" in cors_settings.allowed_methods %} selected{% endif %}>DELETE</option>
|
||||||
|
<option value="PUT"{% if "PUT" in cors_settings.allowed_methods %} selected{% endif %}>PUT</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-4">
|
||||||
|
<div class="offset-sm-2 col-sm-9">
|
||||||
|
<button class="btn btn-sm visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline btn-success" data-item="cors" data-api-url="edit/cors" data-id="editcors" data-action="edit_selected" href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="card mb-3">
|
<div class="card mb-3">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
|
Loading…
Reference in New Issue
Block a user