mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2026-07-29 08:03:36 +00:00
[Web] Move mailcow update check to server side
This commit is contained in:
@@ -0,0 +1,67 @@
|
|||||||
|
<?php
|
||||||
|
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
|
||||||
|
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
|
// Admins only
|
||||||
|
if (!isset($_SESSION['mailcow_cc_role']) || $_SESSION['mailcow_cc_role'] !== 'admin') {
|
||||||
|
http_response_code(403);
|
||||||
|
echo json_encode(array('status' => 'error', 'message' => 'access denied'));
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$owner = $GLOBALS['MAILCOW_GIT_OWNER'];
|
||||||
|
$repo = $GLOBALS['MAILCOW_GIT_REPO'];
|
||||||
|
$current = $GLOBALS['MAILCOW_GIT_VERSION'];
|
||||||
|
|
||||||
|
// Cache key is bound to the running version, so an update invalidates it naturally
|
||||||
|
$cache_key = 'MAILCOW_UPDATE_CHECK/' . $current;
|
||||||
|
|
||||||
|
// Serve cached result if present (one GitHub call per TTL, not one per page load)
|
||||||
|
$cached = $redis->get($cache_key);
|
||||||
|
if ($cached !== false) {
|
||||||
|
echo $cached;
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GitHub requires a User-Agent and rate-limits unauthenticated requests to 60/h per IP
|
||||||
|
function github_get($url) {
|
||||||
|
$ch = curl_init($url);
|
||||||
|
curl_setopt_array($ch, array(
|
||||||
|
CURLOPT_RETURNTRANSFER => true,
|
||||||
|
CURLOPT_USERAGENT => 'mailcow-update-check',
|
||||||
|
CURLOPT_TIMEOUT => 10,
|
||||||
|
CURLOPT_HTTPHEADER => array('Accept: application/vnd.github+json'),
|
||||||
|
));
|
||||||
|
$body = curl_exec($ch);
|
||||||
|
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||||
|
curl_close($ch);
|
||||||
|
if ($body === false || $code !== 200) return false;
|
||||||
|
$json = json_decode($body, true);
|
||||||
|
return is_array($json) ? $json : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$latest = github_get("https://api.github.com/repos/{$owner}/{$repo}/releases/latest");
|
||||||
|
$release = github_get("https://api.github.com/repos/{$owner}/{$repo}/releases/tags/{$current}");
|
||||||
|
|
||||||
|
// Any failure (rate limit, offline, unexpected payload) -> honest error, cached briefly
|
||||||
|
if ($latest === false || $release === false ||
|
||||||
|
empty($latest['tag_name']) || empty($latest['created_at']) || empty($release['created_at'])) {
|
||||||
|
$result = json_encode(array('status' => 'error', 'message' => 'could not reach GitHub API'));
|
||||||
|
$redis->setex($cache_key, 300, $result);
|
||||||
|
echo $result;
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$date_latest = strtotime($latest['created_at']);
|
||||||
|
$date_current = strtotime($release['created_at']);
|
||||||
|
|
||||||
|
if ($date_latest <= $date_current) {
|
||||||
|
$result = json_encode(array('status' => 'no_update'));
|
||||||
|
} else {
|
||||||
|
$result = json_encode(array('status' => 'update_available', 'latest_tag' => $latest['tag_name']));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache the positive result for an hour
|
||||||
|
$redis->setex($cache_key, 3600, $result);
|
||||||
|
echo $result;
|
||||||
@@ -30,7 +30,7 @@ $(document).ready(function() {
|
|||||||
// create host cpu and mem charts
|
// create host cpu and mem charts
|
||||||
createHostCpuAndMemChart();
|
createHostCpuAndMemChart();
|
||||||
// check for new version
|
// check for new version
|
||||||
if (mailcow_info.branch === "master"){
|
if (mailcow_info.branch === "master" && mailcow_cc_role === "admin"){
|
||||||
check_update(mailcow_info.version_tag, mailcow_info.project_url);
|
check_update(mailcow_info.version_tag, mailcow_info.project_url);
|
||||||
}
|
}
|
||||||
$("#mailcow_version").click(function(){
|
$("#mailcow_version").click(function(){
|
||||||
@@ -1669,41 +1669,26 @@ function createHostCpuAndMemChart(){
|
|||||||
function check_update(current_version, github_repo_url){
|
function check_update(current_version, github_repo_url){
|
||||||
if (!current_version || !github_repo_url) return false;
|
if (!current_version || !github_repo_url) return false;
|
||||||
|
|
||||||
var github_account = github_repo_url.split("/")[3];
|
|
||||||
var github_repo_name = github_repo_url.split("/")[4];
|
|
||||||
|
|
||||||
// get details about latest release
|
window.fetch("/inc/ajax/update_check.php", {method:'GET',cache:'no-cache'}).then(function(response) {
|
||||||
window.fetch("https://api.github.com/repos/"+github_account+"/"+github_repo_name+"/releases/latest", {method:'GET',cache:'no-cache'}).then(function(response) {
|
if (!response.ok) throw new Error("update check returned " + response.status);
|
||||||
return response.json();
|
return response.json();
|
||||||
}).then(function(latest_data) {
|
}).then(function(data) {
|
||||||
// get details about current release
|
if (data.status === "no_update") {
|
||||||
window.fetch("https://api.github.com/repos/"+github_account+"/"+github_repo_name+"/releases/tags/"+current_version, {method:'GET',cache:'no-cache'}).then(function(response) {
|
$("#mailcow_update").removeClass("text-warning text-danger").addClass("text-success");
|
||||||
return response.json();
|
$("#mailcow_update").html("<b>" + lang_debug.no_update_available + "</b>");
|
||||||
}).then(function(current_data) {
|
} else if (data.status === "update_available") {
|
||||||
// compare releases
|
$("#mailcow_update").removeClass("text-danger text-success").addClass("text-warning");
|
||||||
var date_current = new Date(current_data.created_at);
|
$("#mailcow_update").html(lang_debug.update_available + ` <a href="#" id="mailcow_update_changelog">`+data.latest_tag+`</a>`);
|
||||||
var date_latest = new Date(latest_data.created_at);
|
$("#mailcow_update_changelog").click(function(){
|
||||||
if (date_latest.getTime() <= date_current.getTime()){
|
if (mailcow_cc_role !== "admin" && mailcow_cc_role !== "domainadmin")
|
||||||
// no update available
|
return;
|
||||||
$("#mailcow_update").removeClass("text-warning text-danger").addClass("text-success");
|
|
||||||
$("#mailcow_update").html("<b>" + lang_debug.no_update_available + "</b>");
|
|
||||||
} else {
|
|
||||||
// update available
|
|
||||||
$("#mailcow_update").removeClass("text-danger text-success").addClass("text-warning");
|
|
||||||
$("#mailcow_update").html(lang_debug.update_available + ` <a href="#" id="mailcow_update_changelog">`+latest_data.tag_name+`</a>`);
|
|
||||||
$("#mailcow_update_changelog").click(function(){
|
|
||||||
if (mailcow_cc_role !== "admin" && mailcow_cc_role !== "domainadmin")
|
|
||||||
return;
|
|
||||||
|
|
||||||
showVersionModal("New Release " + latest_data.tag_name, latest_data.tag_name);
|
showVersionModal("New Release " + data.latest_tag, data.latest_tag);
|
||||||
})
|
})
|
||||||
}
|
} else {
|
||||||
}).catch(err => {
|
throw new Error(data.message || "update check failed");
|
||||||
// err
|
}
|
||||||
console.log(err);
|
|
||||||
$("#mailcow_update").removeClass("text-success text-warning").addClass("text-danger");
|
|
||||||
$("#mailcow_update").html("<b>"+ lang_debug.update_failed +"</b>");
|
|
||||||
});
|
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
// err
|
// err
|
||||||
console.log(err);
|
console.log(err);
|
||||||
|
|||||||
Reference in New Issue
Block a user