Simplify update check.

This commit is contained in:
James Cole
2020-02-02 10:39:37 +01:00
parent f99f166623
commit 7f3522339c
9 changed files with 173 additions and 167 deletions

View File

@@ -25,6 +25,7 @@ declare(strict_types=1);
namespace FireflyIII\Handlers\Events; namespace FireflyIII\Handlers\Events;
use Carbon\Carbon;
use FireflyIII\Events\RequestedVersionCheckStatus; use FireflyIII\Events\RequestedVersionCheckStatus;
use FireflyIII\Exceptions\FireflyException; use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Update\UpdateTrait; use FireflyIII\Helpers\Update\UpdateTrait;
@@ -55,7 +56,6 @@ class VersionCheckEventHandler
$value = (int)$permission->data; $value = (int)$permission->data;
if (1 !== $value) { if (1 !== $value) {
Log::info('Update check is not enabled.'); Log::info('Update check is not enabled.');
return; return;
} }
@@ -65,7 +65,6 @@ class VersionCheckEventHandler
$user = $event->user; $user = $event->user;
if (!$repository->hasRole($user, 'owner')) { if (!$repository->hasRole($user, 'owner')) {
Log::debug('User is not admin, done.'); Log::debug('User is not admin, done.');
return; return;
} }
@@ -76,26 +75,13 @@ class VersionCheckEventHandler
Log::debug(sprintf('Last check time is %d, current time is %d, difference is %d', $lastCheckTime->data, $now, $diff)); Log::debug(sprintf('Last check time is %d, current time is %d, difference is %d', $lastCheckTime->data, $now, $diff));
if ($diff < 604800) { if ($diff < 604800) {
Log::debug(sprintf('Checked for updates less than a week ago (on %s).', date('Y-m-d H:i:s', $lastCheckTime->data))); Log::debug(sprintf('Checked for updates less than a week ago (on %s).', date('Y-m-d H:i:s', $lastCheckTime->data)));
return; return;
} }
// last check time was more than a week ago. // last check time was more than a week ago.
Log::debug('Have not checked for a new version in a week!'); Log::debug('Have not checked for a new version in a week!');
try { $release = $this->getLatestRelease();
$latestRelease = $this->getLatestRelease();
} catch (FireflyException $e) {
Log::error($e);
session()->flash('error', (string)trans('firefly.update_check_error'));
// softfail. session()->flash($release['level'], $release['message']);
return;
}
$versionCheck = $this->versionCheck($latestRelease);
$resultString = $this->parseResult($versionCheck, $latestRelease);
if (0 !== $versionCheck && '' !== $resultString) {
// flash info
session()->flash('info', $resultString);
}
app('fireflyconfig')->set('last_update_check', time()); app('fireflyconfig')->set('last_update_check', time());
} }
} }

View File

@@ -23,8 +23,6 @@ declare(strict_types=1);
namespace FireflyIII\Helpers\Update; namespace FireflyIII\Helpers\Update;
use Carbon\Carbon;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Services\FireflyIIIOrg\Update\UpdateRequestInterface; use FireflyIII\Services\FireflyIIIOrg\Update\UpdateRequestInterface;
use Log; use Log;
@@ -35,10 +33,11 @@ use Log;
trait UpdateTrait trait UpdateTrait
{ {
/** /**
* Get object for the latest release from GitHub. * Returns an array with info on the next release, if any.
* 'message' => 'A new version is available.
* 'level' => 'info' / 'success' / 'error'
* *
* @return array * @return array
* @throws FireflyException
*/ */
public function getLatestRelease(): array public function getLatestRelease(): array
{ {
@@ -47,81 +46,6 @@ trait UpdateTrait
$checker = app(UpdateRequestInterface::class); $checker = app(UpdateRequestInterface::class);
$channel = app('fireflyconfig')->get('update_channel', 'stable')->data; $channel = app('fireflyconfig')->get('update_channel', 'stable')->data;
return $checker->getVersion($channel); return $checker->getUpdateInformation($channel);
}
/**
* Parses the version check result in a human readable sentence.
*
* @param int $versionCheck
* @param array $information
*
* @return string
*/
public function parseResult(int $versionCheck, array $information): string
{
Log::debug(sprintf('Now in parseResult(%d)', $versionCheck));
$current = (string)config('firefly.version');
$return = '';
$triggered = false;
if (-1 === $versionCheck) {
$triggered = true;
$monthAndDayFormat = (string)trans('config.month_and_day');
$carbon = Carbon::createFromFormat('Y-m-d', $information['date']);
$return = (string)trans(
'firefly.update_new_version_alert',
[
'your_version' => $current,
'new_version' => $information['version'],
'date' => $carbon->formatLocalized($monthAndDayFormat),
]
);
// append warning if beta or alpha.
$isBeta = $information['is_beta'] ?? false;
if (true === $isBeta) {
$return = sprintf('%s %s', $return, trans('firefly.update_version_beta'));
}
$isAlpha = $information['is_alpha'] ?? false;
if (true === $isAlpha) {
$return = sprintf('%s %s', $return, trans('firefly.update_version_alpha'));
}
}
if (0 === $versionCheck) {
$triggered = true;
Log::debug('User is running current version.');
// you are running the current version!
$return = (string)trans('firefly.update_current_version_alert', ['version' => $current]);
}
if (1 === $versionCheck) {
$triggered = true;
Log::debug('User is running NEWER version.');
// you are running a newer version!
$return = (string)trans('firefly.update_newer_version_alert', ['your_version' => $current, 'new_version' => $information['version']]);
}
if (false === $triggered) {
Log::debug('No option was triggered.');
$return = (string)trans('firefly.update_check_error');
}
return $return;
}
/**
* Compare version and store result.
*
* @param array $information
*
* @return int
*/
public function versionCheck(array $information): int
{
Log::debug('Now in versionCheck()');
$current = (string)config('firefly.version');
$check = version_compare($current, $information['version']);
Log::debug(sprintf('Comparing %s with %s, result is %s', $current, $information['version'], $check), $information);
return $check;
} }
} }

View File

@@ -23,14 +23,12 @@ declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Admin; namespace FireflyIII\Http\Controllers\Admin;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Helpers\Update\UpdateTrait; use FireflyIII\Helpers\Update\UpdateTrait;
use FireflyIII\Http\Controllers\Controller; use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Middleware\IsDemoUser; use FireflyIII\Http\Middleware\IsDemoUser;
use FireflyIII\Http\Middleware\IsSandStormUser; use FireflyIII\Http\Middleware\IsSandStormUser;
use Illuminate\Http\JsonResponse; use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Log;
/** /**
* Class HomeController. * Class HomeController.
@@ -110,46 +108,12 @@ class UpdateController extends Controller
/** /**
* Does a manual update check. * Does a manual update check.
*/ */
public function updateCheck(): JsonResponse public function updateCheck(): RedirectResponse
{ {
$success = true; $release = $this->getLatestRelease();
$latestRelease = '1.0';
$resultString = '';
$versionCheck = -2;
$channel = app('fireflyconfig')->get('update_channel', 'stable')->data;
try { session()->flash($release['level'], $release['message']);
$latestRelease = $this->getLatestRelease();
} catch (FireflyException $e) {
Log::error($e->getMessage());
$success = false;
}
// if error, tell the user. return redirect(route('admin.update-check'));
if (false === $success) {
$resultString = (string)trans('firefly.update_check_error');
session()->flash('error', $resultString);
}
// if not, compare and tell the user.
if (true === $success) {
$versionCheck = $this->versionCheck($latestRelease);
$resultString = $this->parseResult($versionCheck, $latestRelease);
}
Log::debug(sprintf('Result string is: "%s"', $resultString));
if (0 !== $versionCheck && '' !== $resultString) {
// flash info
session()->flash('info', $resultString);
}
app('fireflyconfig')->set('last_update_check', time());
return response()->json(
[
'result' => $resultString,
'channel' => $channel,
]
);
} }
} }

View File

@@ -21,8 +21,8 @@
namespace FireflyIII\Services\FireflyIIIOrg\Update; namespace FireflyIII\Services\FireflyIIIOrg\Update;
use Carbon\Carbon;
use Exception; use Exception;
use FireflyIII\Exceptions\FireflyException;
use GuzzleHttp\Client; use GuzzleHttp\Client;
use GuzzleHttp\Exception\GuzzleException; use GuzzleHttp\Exception\GuzzleException;
use JsonException; use JsonException;
@@ -38,14 +38,135 @@ class UpdateRequest implements UpdateRequestInterface
* @param string $channel * @param string $channel
* *
* @return array * @return array
* @throws FireflyException
*/ */
public function getVersion(string $channel): array public function getUpdateInformation(string $channel): array
{ {
Log::debug(sprintf('Now in getUpdateInformation(%s)', $channel));
$information = [
'level' => 'error',
'message' => (string)trans('firefly.unknown_error'),
];
// try get array from update server:
$updateInfo = $this->contactServer($channel);
if ('error' === $updateInfo['level']) {
Log::error('Update information contains an error.');
Log::error($updateInfo['message']);
$information['message'] = $updateInfo['message'];
return $information;
}
// if no error, parse the result and return
return $this->parseResult($updateInfo);
}
/**
* @param array $information
*
* @return array
*/
private function parseResult(array $information): array
{
Log::debug('Now in parseResult()', $information);
$return = [
'level' => 'error',
'message' => (string)trans('firefly.unknown_error'),
];
$current = config('firefly.version');
$latest = $information['version'];
$compare = version_compare($latest, $current);
Log::debug(sprintf('Current version is "%s", latest is "%s", result is: %d', $current, $latest, $compare));
// -1: you're running a newer version:
if (-1 === $compare) {
$return['level'] = 'info';
$return['message'] = (string)trans('firefly.update_newer_version_alert', ['your_version' => $current, 'new_version' => $latest]);
Log::debug('User is running a newer version', $return);
return $return;
}
// running the current version:
if (0 === $compare) {
$return['level'] = 'info';
$return['message'] = (string)trans('firefly.update_current_version_alert', ['version' => $current]);
Log::debug('User is the current version.', $return);
return $return;
}
// a newer version is available!
/** @var Carbon $released */
$released = $information['date'];
$today = Carbon::today()->startOfDay();
$diff = $today->diffInDays($released);
$expectedDiff = config('firefly.update_minimum_age') ?? 6;
// it's still very fresh, and user wants a stable release:
if ($diff <= $expectedDiff) {
$return['level'] = 'info';
$return['message'] = (string)trans(
'firefly.just_new_release',
['version' => $latest,
'date' => $released->formatLocalized((string)trans('config.month_and_day')),
'days' => $expectedDiff,
]
);
Log::debug('Release is very fresh.', $return);
return $return;
}
// its been around for a while:
$return['level'] = 'success';
$return['message'] = (string)trans(
'firefly.update_new_version_alert',
[
'your_version' => $current,
'new_version' => $latest,
'date' => $released->formatLocalized(
(string)trans('config.month_and_day')
)]
);
Log::debug('New release is old enough.');
// add warning in case of alpha or beta:
// append warning if beta or alpha.
$isBeta = $information['is_beta'] ?? false;
if (true === $isBeta) {
$return['message'] = sprintf('%s %s', $return['message'], trans('firefly.update_version_beta'));
Log::debug('New release is also a beta!');
}
$isAlpha = $information['is_alpha'] ?? false;
if (true === $isAlpha) {
$return['message'] = sprintf('%s %s', $return['message'], trans('firefly.update_version_alpha'));
Log::debug('New release is also a alpha!');
}
Log::debug('New release is here!', $return);
return $return;
}
/**
* @param string $channel
*
* @return array
*/
private function contactServer(string $channel): array
{
Log::debug(sprintf('Now in contactServer(%s)', $channel));
// always fall back to current version:
$return = [
'version' => config('firefly.version'),
'date' => Carbon::today()->startOfDay(),
'level' => 'error',
'message' => (string)trans('firefly.unknown_error'),
];
$uri = config('firefly.update_endpoint'); $uri = config('firefly.update_endpoint');
Log::debug(sprintf('Going to call %s', $uri)); Log::debug(sprintf('Going to call %s', $uri));
try { try {
$client = new Client(); $client = new Client;
$options = [ $options = [
'headers' => [ 'headers' => [
'User-Agent' => sprintf('FireflyIII/%s/%s', config('firefly.version'), $channel), 'User-Agent' => sprintf('FireflyIII/%s/%s', config('firefly.version'), $channel),
@@ -53,23 +174,46 @@ class UpdateRequest implements UpdateRequestInterface
]; ];
$res = $client->request('GET', $uri, $options); $res = $client->request('GET', $uri, $options);
} catch (GuzzleException|Exception $e) { } catch (GuzzleException|Exception $e) {
throw new FireflyException(sprintf('Response error from update check: %s', $e->getMessage())); Log::error('Ran into Guzzle error.');
Log::error($e->getMessage());
Log::error($e->getTraceAsString());
$return['message'] = sprintf('Guzzle: %s', $e->getMessage());
return $return;
} }
if (200 !== $res->getStatusCode()) { if (200 !== $res->getStatusCode()) {
throw new FireflyException(sprintf('Returned error code %d from update check.', $res->getStatusCode())); Log::error(sprintf('Response status from server is %d.', $res->getStatusCode()));
Log::error((string)$res->getBody());
$return['message'] = sprintf('Error: %d', $res->getStatusCode());
return $return;
} }
$body = (string)$res->getBody(); $body = (string)$res->getBody();
try { try {
$json = json_decode($body, true, 512, JSON_THROW_ON_ERROR); $json = json_decode($body, true, 512, JSON_THROW_ON_ERROR);
} catch (JsonException $e) {
throw new FireflyException('Invalid JSON in server response.'); } catch (JsonException|Exception $e) {
Log::error('Body is not valid JSON');
Log::error($body);
$return['message'] = 'Invalid JSON :(';
return $return;
} }
if (!isset($json['firefly_iii'][$channel])) { if (!isset($json['firefly_iii'][$channel])) {
throw new FireflyException(sprintf('Unknown update channel "%s"', $channel)); Log::error(sprintf('No valid update channel "%s"', $channel));
Log::error($body);
$return['message'] = sprintf('Unknown update channel "%s" :(', $channel);
} }
return $json['firefly_iii'][$channel]; // parse response a bit. No message yet.
$response = $json['firefly_iii'][$channel];
$return['version'] = $response['version'];
$return['level'] = 'success';
$return['date'] = Carbon::createFromFormat('Y-m-d', $response['date'])->startOfDay();
Log::info('Response from update server', $response);
return $return;
} }
} }

View File

@@ -32,8 +32,7 @@ interface UpdateRequestInterface
* @param string $channel * @param string $channel
* *
* @return array * @return array
* @throws FireflyException
*/ */
public function getVersion(string $channel): array; public function getUpdateInformation(string $channel): array;
} }

View File

@@ -160,6 +160,7 @@ return [
'login_provider' => envNonEmpty('LOGIN_PROVIDER', 'eloquent'), 'login_provider' => envNonEmpty('LOGIN_PROVIDER', 'eloquent'),
'cer_provider' => envNonEmpty('CER_PROVIDER', 'fixer'), 'cer_provider' => envNonEmpty('CER_PROVIDER', 'fixer'),
'update_endpoint' => 'https://version.firefly-iii.org/index.json', 'update_endpoint' => 'https://version.firefly-iii.org/index.json',
'update_minimum_age' => 6,
'default_location' => [ 'default_location' => [
'longitude' => env('MAP_DEFAULT_LONG', '5.916667'), 'longitude' => env('MAP_DEFAULT_LONG', '5.916667'),
'latitude' => env('MAP_DEFAULT_LAT', '51.983333'), 'latitude' => env('MAP_DEFAULT_LAT', '51.983333'),

View File

@@ -25,18 +25,4 @@ $(function () {
// Enable update button. // Enable update button.
$('#update').click(checkUpdate);
}); });
function checkUpdate() {
// do post update check:
$.post(updateCheckUri).done(function (data) {
alert(data.result);
}).fail(function () {
alert('Error while checking.');
});
return false;
}

View File

@@ -218,7 +218,7 @@ return [
// check for updates: // check for updates:
'update_check_title' => 'Check for updates', 'update_check_title' => 'Check for updates',
'admin_update_check_title' => 'Automatically check for update', 'admin_update_check_title' => 'Automatically check for update',
'admin_update_check_explain' => 'Firefly III can check for updates automatically. When you enable this setting, it will contact Github to see if a new version of Firefly III is available. When it is, you will get a notification. You can test this notification using the button on the right. Please indicate below if you want Firefly III to check for updates.', 'admin_update_check_explain' => 'Firefly III can check for updates automatically. When you enable this setting, it will contact the Firefly III update server to see if a new version of Firefly III is available. When it is, you will get a notification. You can test this notification using the button on the right. Please indicate below if you want Firefly III to check for updates.',
'check_for_updates_permission' => 'Firefly III can check for updates, but it needs your permission to do so. Please go to the <a href=":link">administration</a> to indicate if you would like this feature to be enabled.', 'check_for_updates_permission' => 'Firefly III can check for updates, but it needs your permission to do so. Please go to the <a href=":link">administration</a> to indicate if you would like this feature to be enabled.',
'updates_ask_me_later' => 'Ask me later', 'updates_ask_me_later' => 'Ask me later',
'updates_do_not_check' => 'Do not check for updates', 'updates_do_not_check' => 'Do not check for updates',
@@ -231,7 +231,9 @@ return [
'update_version_alpha' => 'This version is a ALPHA version. You may run into issues.', 'update_version_alpha' => 'This version is a ALPHA version. You may run into issues.',
'update_current_version_alert' => 'You are running :version, which is the latest available release.', 'update_current_version_alert' => 'You are running :version, which is the latest available release.',
'update_newer_version_alert' => 'You are running :your_version, which is newer than the latest release, :new_version.', 'update_newer_version_alert' => 'You are running :your_version, which is newer than the latest release, :new_version.',
'update_check_error' => 'An error occurred while checking for updates. Please view the log files.', 'update_check_error' => 'An error occurred while checking for updates: :error',
'unknown_error' => 'Unknown error. Sorry about that.',
'just_new_release' => 'A new version is available! Version :version was released :date. This release is very fresh. Wait a few days for the new release to stabilize.',
'admin_update_channel_title' => 'Update channel', 'admin_update_channel_title' => 'Update channel',
'admin_update_channel_explain' => 'Firefly III has three update "channels" which determine how ahead of the curve you are in terms of features, enhancements and bugs. Use the "beta" channel if you\'re adventurous and the "alpha" when you like to live life dangerously.', 'admin_update_channel_explain' => 'Firefly III has three update "channels" which determine how ahead of the curve you are in terms of features, enhancements and bugs. Use the "beta" channel if you\'re adventurous and the "alpha" when you like to live life dangerously.',
'update_channel_stable' => 'Stable. Everything should work as expected.', 'update_channel_stable' => 'Stable. Everything should work as expected.',

View File

@@ -50,7 +50,7 @@
{{ 'admin_update_check_now_explain'|_ }} {{ 'admin_update_check_now_explain'|_ }}
</p> </p>
<p> <p>
<a href="#" id="update" class="btn btn-info">{{ 'check_for_updates_button'|_ }}</a> <a href="{{ route('admin.update-check.manual') }}" class="btn btn-info">{{ 'check_for_updates_button'|_ }}</a>
</p> </p>
</div> </div>
</div> </div>