First code for #1050

This commit is contained in:
James Cole 2017-12-28 11:38:40 +01:00
parent 9ab3848755
commit b65e1e022e
No known key found for this signature in database
GPG Key ID: C16961E655E74B5E
14 changed files with 575 additions and 4 deletions

View File

@ -0,0 +1,71 @@
<?php
/**
* VersionCheckEventHandler.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Handlers\Events;
use FireflyIII\User;
use Illuminate\Auth\Events\Login;
use Log;
use Preferences;
/**
* Class VersionCheckEventHandler
*/
class VersionCheckEventHandler
{
/**
* @param Login $event
*/
public function checkForUpdates(Login $event)
{
// in Sandstorm, cannot check for updates:
$sandstorm = 1 === intval(getenv('SANDSTORM'));
if ($sandstorm === true) {
return;
}
/** @var User $user */
$user = $event->user;
$permission = Preferences::getForUser($user, 'permission_update_check', -1);
$lastCheckTime = Preferences::getForUser($user, 'last_update_check', time());
$now = time();
if ($now - $lastCheckTime->data < 604800) {
Log::debug('Checked for updates less than a week ago.');
return;
}
// last check time was more than a week ago.
Log::debug('Have not checked for a new version in a week!');
// have actual permission?
if ($permission->data === -1) {
// never asked before.
session()->flash('info', strval(trans('firefly.check_for_updates_permission', ['link' => route('admin.update-check')])));
return;
}
}
}

View File

@ -0,0 +1,135 @@
<?php
/**
* UpdateController.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Http\Controllers\Admin;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Http\Controllers\Controller;
use FireflyIII\Http\Middleware\IsDemoUser;
use FireflyIII\Http\Middleware\IsSandStormUser;
use FireflyIII\Services\Github\Object\Release;
use FireflyIII\Services\Github\Request\UpdateRequest;
use Illuminate\Http\Request;
use Log;
use Preferences;
use Response;
use Session;
/**
* Class HomeController.
*/
class UpdateController extends Controller
{
/**
* ConfigurationController constructor.
*/
public function __construct()
{
parent::__construct();
$this->middleware(
function ($request, $next) {
app('view')->share('title', strval(trans('firefly.administration')));
app('view')->share('mainTitleIcon', 'fa-hand-spock-o');
return $next($request);
}
);
$this->middleware(IsDemoUser::class)->except(['index']);
$this->middleware(IsSandStormUser::class)->except(['index']);
}
/**
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
* @throws \Illuminate\Container\EntryNotFoundException
*/
public function index()
{
$subTitle = trans('firefly.update_check_title');
$subTitleIcon = 'fa-star';
$permission = app('preferences')->get('permission_update_check', -1);
$selected = $permission->data;
$options = [
'-1' => trans('firefly.updates_ask_me_later'),
'0' => trans('firefly.updates_do_not_check'),
'1' => trans('firefly.updates_enable_check'),
];
return view('admin.update.index', compact('subTitle', 'subTitleIcon', 'selected', 'options'));
}
/**
* @param Request $request
*
* @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector
*/
public function post(Request $request)
{
$checkForUpdates = intval($request->get('check_for_updates'));
Preferences::set('permission_update_check', $checkForUpdates);
Session::flash('success', strval(trans('firefly.configuration_updated')));
Preferences::mark();
return redirect(route('admin.update-check'));
}
/**
* Does a manual update check.
*/
public function updateCheck()
{
$current = config('firefly.version');
$request = new UpdateRequest();
$check = -2;
try {
$request->call();
$releases = $request->getReleases();
// first entry should be the latest entry:
/** @var Release $first */
$first = reset($releases);
$string = '';
$check = version_compare($current, $first->getTitle());
Preferences::set('last_update_check', time());
} catch (FireflyException $e) {
Log::error(sprintf('Could not check for updates: %s', $e->getMessage()));
}
if ($check === -2) {
$string = strval(trans('firefly.update_check_error'));
}
if ($check === -1) {
// there is a new FF version!
$string = strval(trans('firefly.update_new_version_alert', ['your_version' => $current, 'new_version' => $first->getTitle()]));
}
if ($check === 0) {
// you are running the current version!
$string = strval(trans('firefly.update_current_version_alert', ['version' => $current]));
}
if ($check === 1) {
// you are running a newer version!
$string = strval(trans('firefly.update_newer_version_alert', ['your_version' => $current, 'new_version' => $first->getTitle()]));
}
return Response::json(['result' => $string]);
}
}

View File

@ -54,6 +54,7 @@ class EventServiceProvider extends ServiceProvider
// is a User related event.
Login::class => [
'FireflyIII\Handlers\Events\UserEventHandler@checkSingleUserIsAdmin',
'FireflyIII\Handlers\Events\VersionCheckEventHandler@checkForUpdates',
],
// is a User related event.

View File

@ -0,0 +1,30 @@
<?php
/**
* GithubObject.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Services\Github\Object;
/**
* Class SpectreObject
*/
class GithubObject
{
}

View File

@ -0,0 +1,89 @@
<?php
/**
* Release.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Services\Github\Object;
use Carbon\Carbon;
/**
* Class Release
*/
class Release extends GithubObject
{
/** @var string */
private $content;
/** @var string */
private $id;
/** @var string */
private $title;
/** @var Carbon */
private $updated;
/**
* Release constructor.
*
* @param array $data
*/
public function __construct(array $data)
{
$this->id = $data['id'];
$this->updated = new Carbon($data['updated']);
$this->title = $data['title'];
$this->content = $data['content'];
}
/**
* @return string
*/
public function getContent(): string
{
return $this->content;
}
/**
* @return string
*/
public function getId(): string
{
return $this->id;
}
/**
* @return string
*/
public function getTitle(): string
{
return $this->title;
}
/**
* @return Carbon
*/
public function getUpdated(): Carbon
{
return $this->updated;
}
}

View File

@ -0,0 +1,35 @@
<?php
/**
* GithubRequest.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Services\Github\Request;
/**
* Interface GithubRequest
*
* @package FireflyIII\Services\Github\Request
*/
interface GithubRequest
{
public function call();
}

View File

@ -0,0 +1,82 @@
<?php
/**
* UpdateRequest.php
* Copyright (c) 2017 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
declare(strict_types=1);
namespace FireflyIII\Services\Github\Request;
use Exception;
use FireflyIII\Exceptions\FireflyException;
use FireflyIII\Services\Github\Object\Release;
use Requests;
use SimpleXMLElement;
/**
* Class UpdateRequest
*/
class UpdateRequest implements GitHubRequest
{
/** @var array */
private $releases = [];
/**
*
* @throws FireflyException
*/
public function call()
{
$uri = 'https://github.com/firefly-iii/firefly-iii/releases.atom';
try {
$response = Requests::get($uri);
} catch (Exception $e) {
throw new FireflyException(sprintf('Response error from Github: %s', $e->getMessage()));
}
if ($response->status_code !== 200) {
throw new FireflyException(sprintf('Returned code %d, error: %s', $response->status_code, $response->body));
}
$releaseXml = new SimpleXMLElement($response->body, LIBXML_NOCDATA);
//fetch the products for each category
if (isset($releaseXml->entry)) {
foreach ($releaseXml->entry as $entry) {
$array = [
'id' => strval($entry->id),
'updated' => strval($entry->updated),
'title' => strval($entry->title),
'content' => strval($entry->content),
];
$this->releases[] = new Release($array);
}
}
}
/**
* @return array
*/
public function getReleases(): array
{
return $this->releases;
}
}

40
public/js/ff/admin/update/index.js vendored Normal file
View File

@ -0,0 +1,40 @@
/*
* index.js
* Copyright (c) 2017 thegrumpydictator@gmail.com
*
* This file is part of Firefly III.
*
* Firefly III is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Firefly III is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Firefly III. If not, see <http://www.gnu.org/licenses/>.
*/
$(function () {
"use strict";
// 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

@ -142,6 +142,22 @@ return [
'invalid_locale_settings' => 'Firefly III is unable to format monetary amounts because your server is missing the required packages. There are <a href="https://github.com/firefly-iii/help/wiki/Missing-locale-packages">instructions how to do this</a>.',
'quickswitch' => 'Quickswitch',
// check for updates:
'update_check_title' => 'Check for updates',
'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.',
'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_do_not_check' => 'Do not check for updates',
'updates_enable_check' => 'Enable the check for updates',
'admin_update_check_now_title' => 'Check for updates now',
'admin_update_check_now_explain' => 'If you press the button, Firefly III will see if your current version is the latest.',
'check_for_updates_button' => 'Check now!',
'update_new_version_alert' => 'A new version is available. You are running v:your_version, the latest version is v:new_version.',
'update_current_version_alert' => 'You are running v:version, which is the latest available release.',
'update_newer_version_alert' => 'You are running v:your_version, which is newer than the latest release, v:new_version.',
'update_check_error' => 'An error occurred while checking for updates. Please view the log files.',
// search
'search' => 'Search',
'search_query' => 'Query',

View File

@ -169,6 +169,7 @@ return [
'budget_keep_transactions' => 'The only transaction connected to this budget will not be deleted.|All :count transactions connected to this budget will spared deletion.',
'category_keep_transactions' => 'The only transaction connected to this category will not be deleted.|All :count transactions connected to this category will spared deletion.',
'tag_keep_transactions' => 'The only transaction connected to this tag will not be deleted.|All :count transactions connected to this tag will spared deletion.',
'check_for_updates' => 'Check for updates',
'email' => 'Email address',
'password' => 'Password',

View File

@ -14,6 +14,7 @@
<ul>
<li><a href="{{ route('admin.configuration.index') }}">{{ 'firefly_instance_configuration'|_ }}</a></li>
<li><a href="{{ route('admin.links.index') }}">{{ 'journal_link_configuration'|_ }}</a></li>
<li><a href="{{ route('admin.update-check') }}">{{ 'update_check_title'|_ }}</a></li>
</ul>
</div>
</div>
@ -55,7 +56,4 @@
</div>
</div>
</div>
{% endblock %}
{% endblock %}

View File

@ -0,0 +1,61 @@
{% extends "./layout/default" %}
{% block breadcrumbs %}
{{ Breadcrumbs.render }}
{% endblock %}
{% block content %}
<form action="{{ route('admin.update-check.post') }}" method="post" id="store" class="form-horizontal">
<div class="row">
<input type="hidden" name="_token" value="{{ csrf_token() }}"/>
{# do update check. #}
<div class="col-lg-6 col-md-8 col-sm-12 col-xs-12">
<div class="box box-default">
<div class="box-header with-border">
<h3 class="box-title">{{ 'admin_update_check_title'|_ }}</h3>
</div>
<div class="box-body">
<p class="text-info">
{{ 'admin_update_check_explain'|_ }}
</p>
{{ ExpandedForm.select('check_for_updates',options, selected) }}
</div>
</div>
</div>
{# check now button #}
<div class="col-lg-4 col-md-4 col-sm-12 col-xs-12">
<div class="box box-default">
<div class="box-header with-border">
<h3 class="box-title">{{ 'admin_update_check_now_title'|_ }}</h3>
</div>
<div class="box-body">
<p class="text-info">
{{ 'admin_update_check_now_explain'|_ }}
</p>
<p>
<a href="#" id="update" class="btn btn-info">{{ 'check_for_updates_button'|_ }}</a>
</p>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-lg-4 col-md-6 col-sm-12 col-xs-12">
<button type="submit" class="btn btn-success">
{{ ('store_configuration')|_ }}
</button>
</div>
</div>
</form>
{% endblock %}
{% block scripts %}
<script type="text/javascript">
var updateCheckUri = '{{ route('admin.update-check.manual') }}';
</script>
<script type="text/javascript" src="js/ff/admin/update/index.js?v={{ FF_VERSION }}"></script>
{% endblock %}

View File

@ -188,6 +188,13 @@ Breadcrumbs::register(
$breadcrumbs->push(trans('firefly.instance_configuration'), route('admin.configuration.index'));
}
);
Breadcrumbs::register(
'admin.update-check',
function (BreadCrumbsGenerator $breadcrumbs) {
$breadcrumbs->parent('admin.index');
$breadcrumbs->push(trans('firefly.update_check_title'), route('admin.update-check'));
}
);
Breadcrumbs::register(
'admin.links.index',

View File

@ -845,6 +845,11 @@ Route::group(
Route::get('', ['uses' => 'HomeController@index', 'as' => 'index']);
Route::post('test-message', ['uses' => 'HomeController@testMessage', 'as' => 'test-message']);
// check for updates?
Route::get('update-check', ['uses' => 'UpdateController@index', 'as' => 'update-check']);
Route::post('update-check/manual', ['uses' => 'UpdateController@updateCheck', 'as' => 'update-check.manual']);
Route::post('update-check', ['uses' => 'UpdateController@post', 'as' => 'update-check.post']);
// user manager
Route::get('users', ['uses' => 'UserController@index', 'as' => 'users']);
Route::get('users/edit/{user}', ['uses' => 'UserController@edit', 'as' => 'users.edit']);